diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c index bfd4f2af82..73c7de5c46 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c @@ -990,6 +990,9 @@ static uint32_t policy_mgr_dump_current_concurrency_one_connection( case PM_NAN_DISC_MODE: count = strlcat(cc_mode, "NAN DISC", length); break; + case PM_NDI_MODE: + count = strlcat(cc_mode, "NDI", length); + break; default: policy_mgr_err("unexpected mode %d", mode); break; @@ -1047,6 +1050,12 @@ static uint32_t policy_mgr_dump_current_concurrency_two_connection( count += strlcat(cc_mode, "+IBSS", length); break; + case PM_NDI_MODE: + count = policy_mgr_dump_current_concurrency_one_connection( + cc_mode, length); + count += strlcat(cc_mode, "+NDI", + length); + break; default: policy_mgr_err("unexpected mode %d", mode); break; @@ -1104,6 +1113,18 @@ static uint32_t policy_mgr_dump_current_concurrency_three_connection( count += strlcat(cc_mode, "+IBSS", length); break; + case PM_NAN_DISC_MODE: + count = policy_mgr_dump_current_concurrency_two_connection( + cc_mode, length); + count += strlcat(cc_mode, "+NAN Disc", + length); + break; + case PM_NDI_MODE: + count = policy_mgr_dump_current_concurrency_two_connection( + cc_mode, length); + count += strlcat(cc_mode, "+NDI", + length); + break; default: policy_mgr_err("unexpected mode %d", mode); break; @@ -1486,6 +1507,8 @@ enum policy_mgr_con_mode policy_mgr_get_mode(uint8_t type, mode = PM_IBSS_MODE; } else if (type == WMI_VDEV_TYPE_NAN) { mode = PM_NAN_DISC_MODE; + } else if (type == WMI_VDEV_TYPE_NDI) { + mode = PM_NDI_MODE; } else { policy_mgr_err("Unknown type %d", type); } @@ -2432,6 +2455,21 @@ bool policy_mgr_allow_new_home_channel(struct wlan_objmgr_psoc *psoc, policy_mgr_err("don't allow 3rd home channel on same MAC"); status = false; } + } else if ((pm_conc_connection_list[0].mode == + PM_NAN_DISC_MODE && + pm_conc_connection_list[1].mode == + PM_NDI_MODE) || + (pm_conc_connection_list[0].mode == + PM_NDI_MODE && + pm_conc_connection_list[1].mode == + PM_NAN_DISC_MODE)) { + /* + * NAN + NDI are managed in Firmware by dividing + * up slots. Connection on NDI is re-negotiable + * and therefore a 3rd connection with the + * same MAC is possible. + */ + status = true; } else if (((WLAN_REG_IS_24GHZ_CH(channel)) && (WLAN_REG_IS_24GHZ_CH (pm_conc_connection_list[0].chan)) && diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c index ab49036905..a707590c9b 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c @@ -1767,6 +1767,9 @@ bool policy_mgr_map_concurrency_mode(enum QDF_OPMODE *old_mode, case QDF_NAN_DISC_MODE: *new_mode = PM_NAN_DISC_MODE; break; + case QDF_NDI_MODE: + *new_mode = PM_NDI_MODE; + break; default: *new_mode = PM_MAX_NUM_OF_MODE; status = false; @@ -2486,6 +2489,9 @@ enum policy_mgr_con_mode policy_mgr_convert_device_mode_to_qdf_type( case QDF_NAN_DISC_MODE: mode = PM_NAN_DISC_MODE; break; + case QDF_NDI_MODE: + mode = PM_NDI_MODE; + break; default: policy_mgr_debug("Unsupported mode (%d)", device_mode); @@ -2518,6 +2524,9 @@ enum QDF_OPMODE policy_mgr_get_qdf_mode_from_pm( case PM_NAN_DISC_MODE: mode = QDF_NAN_DISC_MODE; break; + case PM_NDI_MODE: + mode = QDF_NDI_MODE; + break; default: policy_mgr_debug("Unsupported policy mgr mode (%d)", device_mode); diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c index 899e092262..ef20048f2c 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c @@ -1324,6 +1324,68 @@ static enum policy_mgr_two_connection_mode return index; } +static enum policy_mgr_two_connection_mode + policy_mgr_get_third_connection_pcl_table_index_nan_ndi(void) +{ + enum policy_mgr_two_connection_mode index = PM_MAX_TWO_CONNECTION_MODE; + /* SCC */ + if (pm_conc_connection_list[0].chan == + pm_conc_connection_list[1].chan) { + /* NAN Discovery can only be on 2.4GHz */ + if (POLICY_MGR_ONE_ONE == pm_conc_connection_list[0].chain_mask) + index = PM_NAN_DISC_NDI_SCC_24_1x1; + else + index = PM_NAN_DISC_NDI_SCC_24_2x2; + /* MCC */ + } else if (pm_conc_connection_list[0].mac == + pm_conc_connection_list[1].mac) { + /* NAN Discovery can only be on 2.4GHz */ + if (POLICY_MGR_ONE_ONE == pm_conc_connection_list[0].chain_mask) + index = PM_NAN_DISC_NDI_MCC_24_1x1; + else + index = PM_NAN_DISC_NDI_MCC_24_2x2; + /* DBS */ + } else if (pm_conc_connection_list[0].mac != + pm_conc_connection_list[1].mac) { + if (POLICY_MGR_ONE_ONE == pm_conc_connection_list[0].chain_mask) + index = PM_NAN_DISC_NDI_DBS_1x1; + else + index = PM_NAN_DISC_NDI_DBS_2x2; + } + return index; +} + +static enum policy_mgr_two_connection_mode + policy_mgr_get_third_connection_pcl_table_index_sta_nan(void) +{ + enum policy_mgr_two_connection_mode index = PM_MAX_TWO_CONNECTION_MODE; + /* SCC */ + if (pm_conc_connection_list[0].chan == + pm_conc_connection_list[1].chan) { + /* NAN Discovery can only be on 2.4GHz */ + if (POLICY_MGR_ONE_ONE == pm_conc_connection_list[0].chain_mask) + index = PM_STA_NAN_DISC_SCC_24_1x1; + else + index = PM_STA_NAN_DISC_SCC_24_2x2; + /* MCC */ + } else if (pm_conc_connection_list[0].mac == + pm_conc_connection_list[1].mac) { + /* NAN Discovery can only be on 2.4GHz */ + if (POLICY_MGR_ONE_ONE == pm_conc_connection_list[0].chain_mask) + index = PM_STA_NAN_DISC_MCC_24_1x1; + else + index = PM_STA_NAN_DISC_MCC_24_2x2; + /* DBS */ + } else if (pm_conc_connection_list[0].mac != + pm_conc_connection_list[1].mac) { + if (POLICY_MGR_ONE_ONE == pm_conc_connection_list[0].chain_mask) + index = PM_STA_NAN_DISC_DBS_1x1; + else + index = PM_STA_NAN_DISC_DBS_2x2; + } + return index; +} + enum policy_mgr_two_connection_mode policy_mgr_get_third_connection_pcl_table_index( struct wlan_objmgr_psoc *psoc) @@ -1384,6 +1446,18 @@ enum policy_mgr_two_connection_mode (PM_STA_MODE == pm_conc_connection_list[1].mode))) index = policy_mgr_get_third_connection_pcl_table_index_sta_sta(); + else if (((PM_NAN_DISC_MODE == pm_conc_connection_list[0].mode) && + (PM_STA_MODE == pm_conc_connection_list[1].mode)) || + ((PM_STA_MODE == pm_conc_connection_list[0].mode) && + (PM_NAN_DISC_MODE == pm_conc_connection_list[1].mode))) + index = + policy_mgr_get_third_connection_pcl_table_index_sta_nan(); + else if (((PM_NAN_DISC_MODE == pm_conc_connection_list[0].mode) && + (PM_NDI_MODE == pm_conc_connection_list[1].mode)) || + ((PM_NDI_MODE == pm_conc_connection_list[0].mode) && + (PM_NAN_DISC_MODE == pm_conc_connection_list[1].mode))) + index = + policy_mgr_get_third_connection_pcl_table_index_nan_ndi(); policy_mgr_debug("mode0:%d mode1:%d chan0:%d chan1:%d chain:%d index:%d", pm_conc_connection_list[0].mode, diff --git a/components/nan/core/src/nan_main.c b/components/nan/core/src/nan_main.c index b28c7f4c68..e32e18b2b4 100644 --- a/components/nan/core/src/nan_main.c +++ b/components/nan/core/src/nan_main.c @@ -431,16 +431,18 @@ ndi_remove_and_update_primary_connection(struct wlan_objmgr_psoc *psoc, } if (!peer && psoc_nan_obj->nan_caps.ndi_dbs_supported) { - /* TODO: Remove connection from policy manager tables */ + policy_mgr_decr_session_set_pcl(psoc, QDF_NDI_MODE, + wlan_vdev_get_id(vdev)); return QDF_STATUS_SUCCESS; } if (peer_nan_obj && psoc_nan_obj->nan_caps.ndi_dbs_supported) { psoc_nan_obj->cb_obj.update_ndi_conn(wlan_vdev_get_id(vdev), &peer_nan_obj->home_chan_info); - /* TODO: Update policy mgr with connection info */ + policy_mgr_update_connection_info(psoc, wlan_vdev_get_id(vdev)); qdf_mem_copy(vdev_nan_obj->primary_peer_mac.bytes, wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE); + policy_mgr_check_n_start_opportunistic_timer(psoc); } wlan_objmgr_peer_release_ref(peer, WLAN_NAN_ID); @@ -506,10 +508,11 @@ ndi_update_ndp_session(struct wlan_objmgr_vdev *vdev, static QDF_STATUS nan_handle_confirm( struct nan_datapath_confirm_event *confirm) { - uint8_t vdev_id; + uint8_t vdev_id, channel; struct wlan_objmgr_psoc *psoc; struct nan_psoc_priv_obj *psoc_nan_obj; struct nan_vdev_priv_obj *vdev_nan_obj; + QDF_STATUS status; vdev_id = wlan_vdev_get_id(confirm->vdev); psoc = wlan_vdev_get_psoc(confirm->vdev); @@ -564,11 +567,33 @@ static QDF_STATUS nan_handle_confirm( psoc_nan_obj->cb_obj.update_ndi_conn(vdev_id, &confirm->ch[0]); if (psoc_nan_obj->nan_caps.ndi_dbs_supported) { - /* - * TODO: Update connection in Policy Manager if NDI - * concurrencies are supported and this is the first - * active NDP for the NDI. - */ + channel = wlan_freq_to_chan(confirm->ch[0].freq); + status = policy_mgr_reset_connection_update(psoc); + if (!QDF_IS_STATUS_SUCCESS(status)) { + nan_err("Policy mgr reset connection failed-%d", + status); + return status; + } + + status = policy_mgr_current_connections_update(psoc, + vdev_id, channel, + POLICY_MGR_UPDATE_REASON_NDP_UPDATE); + if (QDF_STATUS_E_FAILURE == status) { + nan_err("connections update failed!!"); + return status; + } + + if (QDF_STATUS_SUCCESS == status) { + status = policy_mgr_wait_for_connection_update( + psoc); + if (!QDF_IS_STATUS_SUCCESS(status)) { + nan_err("qdf wait for event failed!!"); + return status; + } + } + + policy_mgr_incr_active_session(psoc, QDF_NDI_MODE, + vdev_id); } } diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 3c9095e5b0..3d57a0cdbe 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -17939,10 +17939,21 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, if (0 != status) return status; - /* Disable NAN Discovery if enabled */ - if (adapter->device_mode == QDF_P2P_CLIENT_MODE) + /* + * Disable NAN Discovery if incoming connection is P2P or if a STA + * connection already exists and if this is a case of STA+STA. + */ + if (adapter->device_mode == QDF_P2P_CLIENT_MODE || + policy_mgr_mode_specific_connection_count(hdd_ctx->psoc, + PM_STA_MODE, NULL)) ucfg_nan_disable_concurrency(hdd_ctx->psoc); + /* + * STA+NDI concurrency gets preference over NDI+NDI. Disable + * first NDI in case an NDI+NDI concurrency exists. + */ + ucfg_nan_check_and_disable_unsupported_ndi(hdd_ctx->psoc); + if (req->bssid) bssid = req->bssid; else if (bssid_hint) diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c index d7f75f0a80..2f9950ae72 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.c +++ b/core/hdd/src/wlan_hdd_nan_datapath.c @@ -503,6 +503,7 @@ int hdd_ndi_open(char *iface_name) struct hdd_adapter *adapter; struct qdf_mac_addr random_ndi_mac; struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + uint8_t ndi_adapter_count = 0; uint8_t *ndi_mac_addr; hdd_enter(); @@ -511,6 +512,16 @@ int hdd_ndi_open(char *iface_name) return -EINVAL; } + hdd_for_each_adapter(hdd_ctx, adapter) { + if (WLAN_HDD_IS_NDI(adapter)) + ndi_adapter_count++; + } + if (ndi_adapter_count >= MAX_NDI_ADAPTERS) { + hdd_err("Can't allow more than %d NDI adapters", + MAX_NDI_ADAPTERS); + return -EINVAL; + } + if (cfg_nan_get_ndi_mac_randomize(hdd_ctx->psoc)) { if (hdd_get_random_nan_mac_addr(hdd_ctx, &random_ndi_mac)) { hdd_err("get random mac address failed"); diff --git a/core/hdd/src/wlan_hdd_nan_datapath.h b/core/hdd/src/wlan_hdd_nan_datapath.h index a79871f1c9..bd13ec326c 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.h +++ b/core/hdd/src/wlan_hdd_nan_datapath.h @@ -37,6 +37,9 @@ struct wireless_dev; #define NDP_BROADCAST_STAID (0) #ifdef WLAN_FEATURE_NAN + +#define MAX_NDI_ADAPTERS 2 + #define WLAN_HDD_IS_NDI(adapter) ((adapter)->device_mode == QDF_NDI_MODE) #define WLAN_HDD_IS_NDI_CONNECTED(adapter) ( \ diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 0af8c04820..682eab686f 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -726,6 +726,7 @@ struct vdev_type_nss { uint8_t tdls; uint8_t ocb; uint8_t nan; + uint8_t ndi; }; /** diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 8a70c164b2..fa236eb62a 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -12812,6 +12812,10 @@ void sme_update_vdev_type_nss(mac_handle_t mac_handle, uint8_t max_supp_nss, nss_chains_ini_cfg-> rx_nss[band], NAN_NSS_CHAIN_SHIFT)); + vdev_nss->ndi = QDF_MIN(max_supp_nss, GET_VDEV_NSS_CHAIN( + nss_chains_ini_cfg-> + rx_nss[band], + NAN_NSS_CHAIN_SHIFT)); sme_debug("band %d NSS:sta %d sap %d cli %d go %d dev %d ibss %d tdls %d ocb %d nan %d", band, vdev_nss->sta, vdev_nss->sap, vdev_nss->p2p_cli, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 20abcb91dc..101763fdd6 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -16386,6 +16386,10 @@ void csr_get_vdev_type_nss(struct mac_context *mac_ctx, *nss_2g = mac_ctx->vdev_type_nss_2g.nan; *nss_5g = mac_ctx->vdev_type_nss_5g.nan; break; + case QDF_NDI_MODE: + *nss_2g = mac_ctx->vdev_type_nss_2g.ndi; + *nss_5g = mac_ctx->vdev_type_nss_5g.ndi; + break; default: *nss_2g = 1; *nss_5g = 1;