Эх сурвалжийг харах

qcacld-3.0: Update NDP peer MC list

Currently, driver gets peer multicast address list from kernel for
all interfaces and it send this list to firmware. For NDI, on NDP
confirmation indication, driver appends the multicast list with
new NDP peer added and then send it to firmware. But this is done
for first NDP peer only, kernel does not provide multicast list
again as kernel already configures the multicast addresses, unless
there is some reset happens in kernel.
This can cause issue as firmware is expecting the updated multicast
filter on each NDP confirmation (new peer is added) to enable the
NS frame exchange. As new peer is not added in the filter, firmware
will reject the NS frame.

So, to fix this, update the multicast list on NDP peer addition and
deletion.

Change-Id: I6371199ae5c3a8f4088987f1e6f10c39cbed1685
CRs-Fixed: 3518887
Rahul Gusain 1 жил өмнө
parent
commit
ea6a35e9f6

+ 2 - 0
components/nan/core/inc/nan_public_structs.h

@@ -798,6 +798,7 @@ struct nan_datapath_host_event {
  * @delete_peers_by_addr: LIM callback for deleting peer by MAC address
  * @update_ndi_conn: WMA callback to update NDI's connection info
  * @nan_concurrency_update: Callback to handle nan concurrency
+ * @set_mc_list: HDD callback to set multicast peer list
  * @nan_sr_concurrency_update: Callback to handle nan SR(Spatial Reuse)
  * concurrency
  */
@@ -826,6 +827,7 @@ struct nan_callbacks {
 				      struct nan_datapath_channel_info
 								    *chan_info);
 	void (*nan_concurrency_update)(void);
+	void (*set_mc_list)(struct wlan_objmgr_vdev *vdev);
 #ifdef WLAN_FEATURE_SR
 	void (*nan_sr_concurrency_update)(struct nan_event_params *nan_evt);
 #endif

+ 39 - 2
components/nan/dispatcher/src/nan_ucfg_api.c

@@ -175,6 +175,37 @@ inline QDF_STATUS ucfg_nan_set_active_peers(struct wlan_objmgr_vdev *vdev,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * ucfg_nan_update_mc_list() - update the multicast list
+ * @vdev: Pointer to VDEV Object
+ *
+ * This function will update the multicast list for NDP peer
+ */
+static void ucfg_nan_update_mc_list(struct wlan_objmgr_vdev *vdev)
+{
+	struct nan_callbacks cb_obj;
+	QDF_STATUS status;
+	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
+
+	if (!psoc) {
+		nan_err("psoc is null");
+		return;
+	}
+
+	status = ucfg_nan_get_callbacks(psoc, &cb_obj);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		nan_err("Couldn't get callback object");
+		return;
+	}
+
+	if (!cb_obj.set_mc_list) {
+		nan_err("set_mc_list callback not registered");
+		return;
+	}
+
+	cb_obj.set_mc_list(vdev);
+}
+
 inline void ucfg_nan_set_peer_mc_list(struct wlan_objmgr_vdev *vdev,
 				      struct qdf_mac_addr peer_mac_addr)
 {
@@ -204,7 +235,7 @@ inline void ucfg_nan_set_peer_mc_list(struct wlan_objmgr_vdev *vdev,
 	}
 	if (list_idx == max_ndp_sessions) {
 		nan_err("Peer multicast address list is full");
-		goto end;
+		qdf_spin_unlock_bh(&priv_obj->lock);
 	}
 	/* Derive peer multicast addr */
 	peer_mac_addr.bytes[0] = 0x33;
@@ -212,8 +243,9 @@ inline void ucfg_nan_set_peer_mc_list(struct wlan_objmgr_vdev *vdev,
 	peer_mac_addr.bytes[2] = 0xff;
 	priv_obj->peer_mc_addr_list[list_idx] = peer_mac_addr;
 
-end:
 	qdf_spin_unlock_bh(&priv_obj->lock);
+
+	ucfg_nan_update_mc_list(vdev);
 }
 
 inline void ucfg_nan_get_peer_mc_list(
@@ -258,7 +290,10 @@ inline void ucfg_nan_clear_peer_mc_list(struct wlan_objmgr_psoc *psoc,
 			break;
 		}
 	}
+
 	qdf_spin_unlock_bh(&priv_obj->lock);
+
+	ucfg_nan_update_mc_list(vdev);
 }
 
 inline uint32_t ucfg_nan_get_active_peers(struct wlan_objmgr_vdev *vdev)
@@ -628,6 +663,8 @@ int ucfg_nan_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
 				ucfg_nan_request_process_cb;
 	psoc_obj->cb_obj.nan_concurrency_update =
 				cb_obj->nan_concurrency_update;
+	psoc_obj->cb_obj.set_mc_list = cb_obj->set_mc_list;
+
 	nan_register_sr_concurrency_callback(psoc_obj, cb_obj);
 	return 0;
 }

+ 8 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -4982,4 +4982,12 @@ static inline void wlan_hdd_link_speed_update(struct wlan_objmgr_psoc *psoc,
 {}
 #endif
 
+/**
+ * hdd_update_multicast_list() - update the multicast list
+ * @vdev: pointer to VDEV object
+ *
+ * Return: none
+ */
+void hdd_update_multicast_list(struct wlan_objmgr_vdev *vdev);
+
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 38 - 2
core/hdd/src/wlan_hdd_main.c

@@ -3950,6 +3950,8 @@ static void hdd_nan_register_callbacks(struct hdd_context *hdd_ctx)
 	cb_obj.peer_departed_ind = hdd_ndp_peer_departed_handler;
 
 	cb_obj.nan_concurrency_update = hdd_nan_concurrency_update;
+	cb_obj.set_mc_list = hdd_update_multicast_list;
+
 	hdd_register_sr_concurrency_cb(&cb_obj);
 
 	os_if_nan_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj);
@@ -4773,7 +4775,7 @@ int hdd_wlan_start_modules(struct hdd_context *hdd_ctx, bool reinit)
 			goto deregister_cb;
 
 		/*
-		 * NAN compoenet requires certain operations like, open adapter,
+		 * NAN component requires certain operations like, open adapter,
 		 * close adapter, etc. to be initiated by HDD, for those
 		 * register HDD callbacks with UMAC's NAN component.
 		 */
@@ -5922,7 +5924,7 @@ hdd_set_derived_multicast_list(struct wlan_objmgr_psoc *psoc,
 
 /**
  * __hdd_set_multicast_list() - set the multicast address list
- * @dev:	Pointer to the WLAN device.
+ * @dev: Pointer to the WLAN device.
  *
  * This function sets the multicast address list.
  *
@@ -6037,6 +6039,40 @@ static void hdd_set_multicast_list(struct net_device *net_dev)
 	osif_vdev_sync_op_stop(vdev_sync);
 }
 
+void hdd_update_multicast_list(struct wlan_objmgr_vdev *vdev)
+{
+	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	struct wlan_hdd_link_info *link_info;
+	struct hdd_adapter *adapter;
+	uint8_t vdev_id = wlan_vdev_get_id(vdev);
+	struct net_device *net_dev;
+
+	if (!hdd_ctx) {
+		hdd_err("hdd_ctx is null");
+		return;
+	}
+
+	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
+	if (!link_info) {
+		hdd_err("adapter is null for vdev_id %d", vdev_id);
+		return;
+	}
+
+	adapter = link_info->adapter;
+	if (!adapter) {
+		hdd_err("adapter is null for vdev_id %d", vdev_id);
+		return;
+	}
+
+	net_dev = adapter->dev;
+	if (!net_dev) {
+		hdd_err("netdev is null");
+		return;
+	}
+
+	__hdd_set_multicast_list(net_dev);
+}
+
 #ifdef WLAN_FEATURE_TSF_PTP
 static const struct ethtool_ops wlan_ethtool_ops = {
 	.get_ts_info = wlan_get_ts_info,

+ 3 - 3
core/hdd/src/wlan_hdd_nan_datapath.c

@@ -1235,11 +1235,11 @@ void hdd_ndp_peer_departed_handler(uint8_t vdev_id, uint16_t sta_id,
 
 	hdd_delete_peer(sta_ctx, peer_mac_addr);
 
+	ucfg_nan_clear_peer_mc_list(hdd_ctx->psoc, link_info->vdev,
+				    peer_mac_addr);
+
 	if (last_peer) {
 		hdd_debug("No more ndp peers.");
-		ucfg_nan_clear_peer_mc_list(hdd_ctx->psoc,
-					    link_info->vdev,
-					    peer_mac_addr);
 		hdd_cleanup_ndi(hdd_ctx, adapter);
 		qdf_event_set(&adapter->peer_cleanup_done);
 		/*