diff --git a/components/nan/core/src/nan_main_i.h b/components/nan/core/src/nan_main_i.h index 03665af064..0af2f0035e 100644 --- a/components/nan/core/src/nan_main_i.h +++ b/components/nan/core/src/nan_main_i.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -150,6 +151,8 @@ struct nan_psoc_priv_obj { * @disable_context: Disable all NDP's operation context * @ndp_init_done: Flag to indicate NDP initialization complete after first peer * connection. + * @peer_mc_addr_list: Peer multicast address list + * @num_peer_mc_addr: Number of entries in peer multicast list */ struct nan_vdev_priv_obj { qdf_spinlock_t lock; @@ -162,6 +165,8 @@ struct nan_vdev_priv_obj { struct qdf_mac_addr primary_peer_mac; void *disable_context; bool ndp_init_done; + struct qdf_mac_addr *peer_mc_addr_list; + uint8_t num_peer_mc_addr; }; /** diff --git a/components/nan/dispatcher/inc/nan_ucfg_api.h b/components/nan/dispatcher/inc/nan_ucfg_api.h index b7e872dcec..c1949f4f4c 100644 --- a/components/nan/dispatcher/inc/nan_ucfg_api.h +++ b/components/nan/dispatcher/inc/nan_ucfg_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -92,6 +93,39 @@ QDF_STATUS ucfg_nan_set_active_peers(struct wlan_objmgr_vdev *vdev, */ uint32_t ucfg_nan_get_active_peers(struct wlan_objmgr_vdev *vdev); +/** + * ucfg_nan_set_peer_mc_list: API to derive peer multicast address and add it + * to the list + * @vdev: pointer to vdev object + * @peer_mac_addr: Peer MAC address + * + * Return: None + */ +void ucfg_nan_set_peer_mc_list(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr peer_mac_addr); + +/** + * ucfg_nan_get_peer_mc_list: API to get peer multicast address list + * @vdev: pointer to vdev object + * @peer_mc_addr_list: Out pointer to the peer multicast address list + * + * Return: None + */ +void ucfg_nan_get_peer_mc_list(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr **peer_mc_addr_list); + +/** + * ucfg_nan_clear_peer_mc_list: Clear peer multicast address list + * @psoc: pointer to psoc object + * @vdev: pointer to vdev object + * @peer_mac_addr: Pointer to peer MAC address + * + * Return: None + */ +void ucfg_nan_clear_peer_mc_list(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *peer_mac_addr); + /** * ucfg_nan_set_ndp_create_transaction_id: set ndp create transaction id * @vdev: pointer to vdev object @@ -624,5 +658,11 @@ static inline bool ucfg_get_disable_6g_nan(struct wlan_objmgr_psoc *psoc) { return true; } + +static inline void +ucfg_nan_get_peer_mc_list(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr **peer_mc_addr_list) +{ +} #endif /* WLAN_FEATURE_NAN */ #endif /* _NAN_UCFG_API_H_ */ diff --git a/components/nan/dispatcher/src/nan_ucfg_api.c b/components/nan/dispatcher/src/nan_ucfg_api.c index ffc48aa7cf..9b98e9af8d 100644 --- a/components/nan/dispatcher/src/nan_ucfg_api.c +++ b/components/nan/dispatcher/src/nan_ucfg_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -33,6 +34,7 @@ #include "cfg_ucfg_api.h" #include "cfg_nan.h" #include "wlan_mlme_api.h" +#include "cfg_nan_api.h" struct wlan_objmgr_psoc; struct wlan_objmgr_vdev; @@ -183,6 +185,108 @@ inline QDF_STATUS ucfg_nan_set_active_peers(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } +inline void ucfg_nan_set_peer_mc_list(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr peer_mac_addr) +{ + struct nan_vdev_priv_obj *priv_obj = nan_get_vdev_priv_obj(vdev); + uint32_t max_ndp_sessions = 0; + struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev); + int i, list_idx = 0; + + if (!priv_obj) { + nan_err("priv_obj is null"); + return; + } + + if (!psoc) { + nan_err("psoc is null"); + return; + } + + qdf_spin_lock_bh(&priv_obj->lock); + if (!priv_obj->peer_mc_addr_list) { + cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions); + + priv_obj->peer_mc_addr_list = + qdf_mem_malloc(max_ndp_sessions * + sizeof(struct qdf_mac_addr)); + if (!priv_obj->peer_mc_addr_list) { + nan_err("Failed to allocate multicast address list"); + goto end; + } + priv_obj->num_peer_mc_addr = 0; + } else { + for (i = 0; i < max_ndp_sessions; i++) { + if (qdf_is_macaddr_zero( + &priv_obj->peer_mc_addr_list[i])) { + list_idx = i; + break; + } + } + if (list_idx == max_ndp_sessions) { + nan_err("Peer multicast address list is full"); + goto end; + } + } + /* Derive peer multicast addr */ + peer_mac_addr.bytes[0] = 0x33; + peer_mac_addr.bytes[1] = 0x33; + peer_mac_addr.bytes[2] = 0xff; + priv_obj->peer_mc_addr_list[list_idx] = peer_mac_addr; + priv_obj->num_peer_mc_addr++; + +end: + qdf_spin_unlock_bh(&priv_obj->lock); +} + +inline void ucfg_nan_get_peer_mc_list( + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr **peer_mc_addr_list) +{ + struct nan_vdev_priv_obj *priv_obj = nan_get_vdev_priv_obj(vdev); + + if (!priv_obj) { + nan_err("priv_obj is null"); + return; + } + + *peer_mc_addr_list = priv_obj->peer_mc_addr_list; +} + +inline void ucfg_nan_clear_peer_mc_list(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *peer_mac_addr) +{ + struct nan_vdev_priv_obj *priv_obj = nan_get_vdev_priv_obj(vdev); + int i; + uint32_t max_ndp_sessions = 0; + + if (!priv_obj) { + nan_err("priv_obj is null"); + return; + } + + qdf_spin_lock_bh(&priv_obj->lock); + if (priv_obj->peer_mc_addr_list) { + cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions); + for (i = 0; i < max_ndp_sessions; i++) { + if (qdf_is_macaddr_equal( + &priv_obj->peer_mc_addr_list[i], + peer_mac_addr)) { + qdf_zero_macaddr( + &priv_obj->peer_mc_addr_list[i]); + priv_obj->num_peer_mc_addr--; + break; + } + } + if (priv_obj->num_peer_mc_addr == 0) { + qdf_mem_free(priv_obj->peer_mc_addr_list); + priv_obj->peer_mc_addr_list = NULL; + } + } + qdf_spin_unlock_bh(&priv_obj->lock); +} + inline uint32_t ucfg_nan_get_active_peers(struct wlan_objmgr_vdev *vdev) { uint32_t val; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index d409ecb3e3..adc8c555cb 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5442,6 +5442,54 @@ void wlan_hdd_release_intf_addr(struct hdd_context *hdd_ctx, QDF_MAC_ADDR_REF(releaseAddr)); } +/** + * hdd_set_derived_multicast_list(): Add derived peer multicast address list in + * multicast list request to the FW + * @psoc: Pointer to psoc + * @adapter: Pointer to hdd adapter + * @mc_list_request: Multicast list request to the FW + * @mc_count: number of multicast addresses received from the kernel + * + * Return: None + */ +static void +hdd_set_derived_multicast_list(struct wlan_objmgr_psoc *psoc, + struct hdd_adapter *adapter, + struct pmo_mc_addr_list_params *mc_list_request, + int *mc_count) +{ + int i = 0, j = 0, list_count = *mc_count; + struct qdf_mac_addr *peer_mc_addr_list = NULL; + uint8_t driver_mc_cnt = 0; + uint32_t max_ndp_sessions = 0; + + cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions); + + ucfg_nan_get_peer_mc_list(adapter->vdev, &peer_mc_addr_list); + + for (j = 0; j < max_ndp_sessions; j++) { + for (i = 0; i < list_count; i++) { + if (qdf_is_macaddr_zero(&peer_mc_addr_list[j]) || + qdf_is_macaddr_equal(&mc_list_request->mc_addr[i], + &peer_mc_addr_list[j])) + break; + } + if (i == list_count) { + qdf_mem_copy( + &(mc_list_request->mc_addr[list_count + + driver_mc_cnt].bytes), + peer_mc_addr_list[j].bytes, ETH_ALEN); + hdd_debug("mlist[%d] = " QDF_MAC_ADDR_FMT, + list_count + driver_mc_cnt, + QDF_MAC_ADDR_REF( + mc_list_request->mc_addr[list_count + + driver_mc_cnt].bytes)); + driver_mc_cnt++; + } + } + *mc_count += driver_mc_cnt; +} + /** * __hdd_set_multicast_list() - set the multicast address list * @dev: Pointer to the WLAN device. @@ -5517,6 +5565,11 @@ static void __hdd_set_multicast_list(struct net_device *dev) QDF_MAC_ADDR_REF(mc_list_request->mc_addr[i].bytes)); i++; } + + if (adapter->device_mode == QDF_NDI_MODE) + hdd_set_derived_multicast_list(psoc, adapter, + mc_list_request, + &mc_count); } adapter->mc_addr_list.mc_cnt = mc_count; diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c index 1554780993..0c49ac2adf 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.c +++ b/core/hdd/src/wlan_hdd_nan_datapath.c @@ -1127,6 +1127,8 @@ void hdd_ndp_peer_departed_handler(uint8_t vdev_id, uint16_t sta_id, if (last_peer) { hdd_debug("No more ndp peers."); + ucfg_nan_clear_peer_mc_list(hdd_ctx->psoc, adapter->vdev, + peer_mac_addr); hdd_cleanup_ndi(hdd_ctx, adapter); qdf_event_set(&adapter->peer_cleanup_done); /* diff --git a/core/mac/src/pe/nan/nan_datapath.c b/core/mac/src/pe/nan/nan_datapath.c index 0c4868f3fe..7795b60371 100644 --- a/core/mac/src/pe/nan/nan_datapath.c +++ b/core/mac/src/pe/nan/nan_datapath.c @@ -80,6 +80,8 @@ static QDF_STATUS lim_add_ndi_peer(struct mac_context *mac_ctx, pe_info("Need to create NDI Peer :" QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac_addr.bytes)); + ucfg_nan_set_peer_mc_list(session->vdev, peer_mac_addr); + peer_idx = lim_assign_peer_idx(mac_ctx, session); if (!peer_idx) { pe_err("Invalid peer_idx: %d", peer_idx);