diff options
author | Robin Peng <robinpeng@google.com> | 2020-06-08 13:10:27 +0800 |
---|---|---|
committer | Robin Peng <robinpeng@google.com> | 2020-06-08 13:10:27 +0800 |
commit | 4743fca20a5011d480d8792cdf512e756ef431c0 (patch) | |
tree | 2e99b04408a194f52755ba755ca3c2eea5fd4529 /core | |
parent | 96195f87fc0f7df78d63386e6f3b8a9000774420 (diff) | |
parent | 0707871c9476b0e3bf4b231fc345e2654ca6721e (diff) | |
download | qcacld-4743fca20a5011d480d8792cdf512e756ef431c0.tar.gz |
Merge branch 'LA.UM.9.12.R2.10.00.00.685.014' into qcom-msm-4.19-7250-wlan-cld3.driver.lnx.2.0.5.r10
Change-Id: Ie2ab17b84ae91170a7cfa29d09464b492a673aad
Diffstat (limited to 'core')
-rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 13 | ||||
-rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.c | 6 | ||||
-rw-r--r-- | core/hdd/src/wlan_hdd_driver_ops.c | 78 | ||||
-rw-r--r-- | core/hdd/src/wlan_hdd_hostapd.c | 33 | ||||
-rw-r--r-- | core/hdd/src/wlan_hdd_main.c | 48 | ||||
-rw-r--r-- | core/hdd/src/wlan_hdd_stats.c | 410 | ||||
-rw-r--r-- | core/mac/inc/qwlan_version.h | 6 | ||||
-rw-r--r-- | core/mac/inc/sir_api.h | 1 | ||||
-rw-r--r-- | core/mac/src/pe/lim/lim_process_action_frame.c | 3 | ||||
-rw-r--r-- | core/pld/src/pld_pcie.c | 13 | ||||
-rw-r--r-- | core/sap/src/sap_ch_select.c | 16 | ||||
-rw-r--r-- | core/sap/src/sap_fsm.c | 7 | ||||
-rw-r--r-- | core/sap/src/sap_module.c | 16 | ||||
-rw-r--r-- | core/sme/src/csr/csr_api_roam.c | 114 | ||||
-rw-r--r-- | core/sme/src/csr/csr_api_scan.c | 3 | ||||
-rw-r--r-- | core/wma/src/wma_scan_roam.c | 17 |
16 files changed, 574 insertions, 210 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index cec3be1d59..ef5226d9bc 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1208,8 +1208,17 @@ struct hdd_adapter { /* estimated link speed */ uint32_t estimated_linkspeed; - /* QDF event for session close */ - qdf_event_t qdf_session_close_event; + /** + * vdev_destroy_event is moved from the qdf_event to linux event + * consciously, Lets take example when sap interface is waiting on the + * session_close event and then there is a SSR the wait event is + * completed the interface down is returned and the next command to the + * driver will hdd_hostapd_uinit-->vhdd_deinit_ap_mode--> + * hdd_hostapd_deinit_sap_session where in the sap_ctx would be freed. + * During the SSR if the same sap context is used it would result + * in null pointer de-reference. + */ + struct completion vdev_destroy_event; /* QDF event for session open */ qdf_event_t qdf_session_open_event; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 6c349b0e78..d8f793d5dd 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -20212,6 +20212,12 @@ wlan_hdd_get_cfg80211_disconnect_reason(struct hdd_adapter *adapter, if (reason >= eSIR_MAC_REASON_PROP_START) { adapter->last_disconnect_reason = wlan_hdd_sir_mac_to_qca_reason(reason); + /* + * Applications expect reason code as 0 for beacon miss failure + * due to backward compatibility. So send ieee80211_reason as 0. + */ + if (reason == eSIR_MAC_BEACON_MISSED) + ieee80211_reason = 0; } else { ieee80211_reason = (enum ieee80211_reasoncode)reason; adapter->last_disconnect_reason = diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 809bb32575..1f01bf20a1 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -55,6 +55,9 @@ #define SSR_MAX_FAIL_CNT 3 static uint8_t re_init_fail_cnt, probe_fail_cnt; +/* An atomic flag to check if SSR cleanup has been done or not */ +static qdf_atomic_t is_recovery_cleanup_done; + /* * In BMI Phase we are only sending small chunk (256 bytes) of the FW image at * a time, and wait for the completion interrupt to start the next transfer. @@ -762,13 +765,18 @@ static void hdd_psoc_shutdown_notify(struct hdd_context *hdd_ctx) hdd_send_hang_reason(); } -static void __hdd_soc_recovery_shutdown(void) +/** + * hdd_soc_recovery_cleanup() - Perform SSR related cleanup activities. + * + * This function will perform cleanup activities related to when driver + * undergoes SSR. Activities inclues stopping idle timer and invoking shutdown + * notifier. + * + * Return: None + */ +static void hdd_soc_recovery_cleanup(void) { struct hdd_context *hdd_ctx; - void *hif_ctx; - - /* recovery starts via firmware down indication; ensure we got one */ - QDF_BUG(cds_is_driver_recovering()); hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -791,6 +799,35 @@ static void __hdd_soc_recovery_shutdown(void) return; } + hdd_psoc_shutdown_notify(hdd_ctx); +} + +static void __hdd_soc_recovery_shutdown(void) +{ + struct hdd_context *hdd_ctx; + void *hif_ctx; + + /* recovery starts via firmware down indication; ensure we got one */ + QDF_BUG(cds_is_driver_recovering()); + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hdd_err("hdd_ctx is null"); + return; + } + + /* + * Perform SSR related cleanup if it has not already been done as a + * part of receiving the uevent. + */ + if (!qdf_atomic_read(&is_recovery_cleanup_done)) + hdd_soc_recovery_cleanup(); + else + qdf_atomic_set(&is_recovery_cleanup_done, 0); + + if (!hdd_wait_for_debugfs_threads_completion()) + hdd_err("Debufs threads are still pending, attempting SSR anyway"); + hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); if (!hif_ctx) { hdd_err("Failed to get HIF context, ignore SSR shutdown"); @@ -800,11 +837,6 @@ static void __hdd_soc_recovery_shutdown(void) /* mask the host controller interrupts */ hif_mask_interrupt_call(hif_ctx); - hdd_psoc_shutdown_notify(hdd_ctx); - - if (!hdd_wait_for_debugfs_threads_completion()) - hdd_err("Debufs threads are still pending, attempting SSR anyway"); - if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) { hif_disable_isr(hif_ctx); hdd_wlan_shutdown(); @@ -1434,7 +1466,7 @@ static int wlan_hdd_runtime_resume(struct device *dev) hdd_err("PMO Runtime resume failed: %d", status); } else { if (policy_mgr_get_connection_count(hdd_ctx->psoc)) - hdd_bus_bw_compute_timer_start(hdd_ctx); + hdd_bus_bw_compute_timer_try_start(hdd_ctx); } hdd_debug("Runtime resume done"); @@ -1728,21 +1760,23 @@ wlan_hdd_pld_uevent(struct device *dev, struct pld_uevent_data *event_data) case PLD_FW_DOWN: hdd_info("Received firmware down indication"); - /* NOTE! SSR cleanup logic goes in pld shutdown, not here */ - cds_set_target_ready(false); cds_set_recovery_in_progress(true); - /* SSR cleanup happens in pld shutdown, which is serialized by - * the platform driver. Other operations are also serialized by - * platform driver, such as probe, remove, and reinit. If the - * firmware goes down during one of these operations, the driver - * would normally have to wait for a timeout before shutdown - * could begin. Instead, forcefully complete events waiting on - * firmware with a "reset" status to avoid waiting to time out - * on a firmware we already know is down. + /* + * In case of some platforms, uevent will come to the driver in + * process context. In that case, it is safe to complete the + * SSR cleanup activities in the same context. In case of + * other platforms, it will be invoked in interrupt context. + * Performing the cleanup in interrupt context is not ideal, + * thus defer the cleanup to be done during + * hdd_soc_recovery_shutdown */ - qdf_complete_wait_events(); + if (qdf_in_interrupt()) + break; + + hdd_soc_recovery_cleanup(); + qdf_atomic_set(&is_recovery_cleanup_done, 1); break; default: diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index f11ced880d..2fa5719100 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -3562,13 +3562,7 @@ struct hdd_adapter *hdd_wlan_create_ap_dev(struct hdd_context *hdd_ctx, return NULL; } - qdf_status = qdf_event_create( - &adapter->qdf_session_close_event); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_err("failed to create session close QDF event!"); - free_netdev(adapter->dev); - return NULL; - } + init_completion(&adapter->vdev_destroy_event); SET_NETDEV_DEV(dev, hdd_ctx->parent_dev); spin_lock_init(&adapter->pause_map_lock); @@ -5770,21 +5764,21 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, * interval in not reset. */ if (ret) - return 0; + goto exit; if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); - return 0; + goto exit; } if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) { hdd_err("Driver module is closed; dropping request"); - return 0; + goto exit; } if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) { hdd_err("vdev is invalid. Hence return"); - return 0; + goto exit; } qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, @@ -5794,7 +5788,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, if (!(adapter->device_mode == QDF_SAP_MODE || adapter->device_mode == QDF_P2P_GO_MODE)) { hdd_err("stop ap is given on device modes other than SAP/GO. Hence return"); - return 0; + goto exit; } /* Clear SOFTAP_INIT_DONE flag to mark stop_ap deinit. So that we do @@ -5880,7 +5874,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, } else { hdd_debug("SAP already down"); mutex_unlock(&hdd_ctx->sap_lock); - return 0; + goto exit; } mutex_unlock(&hdd_ctx->sap_lock); @@ -5891,7 +5885,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, if (status != QDF_STATUS_SUCCESS) { hdd_err("Stopping the BSS"); - return -EINVAL; + goto exit; } qdf_copy_macaddr(&update_ie.bssid, &adapter->mac_addr); @@ -5917,9 +5911,15 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, ucfg_p2p_status_stop_bss(adapter->vdev); +exit: + if (adapter->session.ap.beacon) { + qdf_mem_free(adapter->session.ap.beacon); + adapter->session.ap.beacon = NULL; + } + hdd_exit(); - return ret; + return 0; } /** @@ -6520,7 +6520,8 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, sizeof(*sta_inactivity_timer)); if (!sta_inactivity_timer) { hdd_err("Failed to allocate Memory"); - return QDF_STATUS_E_FAILURE; + status = QDF_STATUS_E_FAILURE; + goto err_start_bss; } sta_inactivity_timer->session_id = adapter->vdev_id; sta_inactivity_timer->sta_inactivity_timeout = diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index dba90ab752..5adbcff853 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3803,7 +3803,7 @@ static int hdd_open(struct net_device *net_dev) int errno; struct osif_vdev_sync *vdev_sync; - errno = osif_vdev_sync_trans_start_wait(net_dev, &vdev_sync); + errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync); if (errno) return errno; @@ -4504,9 +4504,7 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr, if (QDF_IS_STATUS_ERROR(qdf_status)) goto free_net_dev; - qdf_status = qdf_event_create(&adapter->qdf_session_close_event); - if (QDF_IS_STATUS_ERROR(qdf_status)) - goto free_net_dev; + init_completion(&adapter->vdev_destroy_event); qdf_status = hdd_monitor_mode_qdf_create_event(adapter, session_type); if (QDF_IS_STATUS_ERROR(qdf_status)) { @@ -4658,7 +4656,7 @@ QDF_STATUS hdd_sme_close_session_callback(uint8_t vdev_id) * valid, before signaling completion */ if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic) - qdf_event_set(&adapter->qdf_session_close_event); + complete(&adapter->vdev_destroy_event); return QDF_STATUS_SUCCESS; } @@ -4716,6 +4714,7 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter) struct hdd_context *hdd_ctx; uint8_t vdev_id; struct wlan_objmgr_vdev *vdev; + long rc; vdev_id = adapter->vdev_id; hdd_nofl_debug("destroying vdev %d", vdev_id); @@ -4751,7 +4750,7 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter) hdd_objmgr_put_vdev(vdev); /* close sme session (destroy vdev in firmware via legacy API) */ - qdf_event_reset(&adapter->qdf_session_close_event); + INIT_COMPLETION(adapter->vdev_destroy_event); status = sme_close_session(hdd_ctx->mac_handle, adapter->vdev_id); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("failed to close sme session; status:%d", status); @@ -4759,11 +4758,9 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter) } /* block on a completion variable until sme session is closed */ - status = qdf_wait_for_event_completion( - &adapter->qdf_session_close_event, - SME_CMD_VDEV_CREATE_DELETE_TIMEOUT); - - if (QDF_IS_STATUS_ERROR(status)) { + rc = wait_for_completion_timeout(&adapter->vdev_destroy_event, + SME_CMD_VDEV_CREATE_DELETE_TIMEOUT); + if (rc) { clear_bit(SME_SESSION_OPENED, &adapter->event_flags); if (adapter->device_mode == QDF_NDI_MODE) @@ -4772,11 +4769,6 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter) if (status == QDF_STATUS_E_TIMEOUT) { hdd_err("timed out waiting for sme close session"); sme_cleanup_session(hdd_ctx->mac_handle, vdev_id); - } else if (adapter->qdf_session_close_event.force_set) { - hdd_info("SSR occurred during sme close session"); - } else { - hdd_err("failed to wait for sme close session; status:%u", - status); } } @@ -9046,7 +9038,11 @@ void hdd_bus_bandwidth_deinit(struct hdd_context *hdd_ctx) { hdd_enter(); + /* it is expecting the timer has been stopped or not started + * when coming deinit. + */ QDF_BUG(!qdf_periodic_work_stop_sync(&hdd_ctx->bus_bw_work)); + qdf_periodic_work_destroy(&hdd_ctx->bus_bw_work); hdd_pm_qos_remove_request(hdd_ctx); qdf_spinlock_destroy(&hdd_ctx->bus_bw_lock); @@ -15075,6 +15071,20 @@ static void hdd_driver_unload(void) pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR); + /* + * Wait for any trans to complete and then start the driver trans + * for the unload. This will ensure that the driver trans proceeds only + * after all trans have been completed. As a part of this trans, set + * the driver load/unload flag to further ensure that any upcoming + * trans are rejected via wlan_hdd_validate_context. + */ + status = osif_driver_sync_trans_start_wait(&driver_sync); + QDF_BUG(QDF_IS_STATUS_SUCCESS(status)); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Unable to unload wlan; status:%u", status); + return; + } + hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); if (hif_ctx) { /* @@ -15096,6 +15106,12 @@ static void hdd_driver_unload(void) hdd_bus_bw_compute_timer_stop(hdd_ctx); } + /* + * Stop the trans before calling unregister_driver as that involves a + * call to pld_remove which in itself is a psoc transaction + */ + osif_driver_sync_trans_stop(driver_sync); + /* trigger SoC remove */ wlan_hdd_unregister_driver(); diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 2c7d592579..a1e286c715 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -77,6 +77,8 @@ #define HDD_INFO_CONNECTED_TIME BIT(NL80211_STA_INFO_CONNECTED_TIME) #endif /* kernel version less than 4.0.0 && no_backport */ +#define HDD_LINK_STATS_MAX 5 + /* 11B, 11G Rate table include Basic rate and Extended rate * The IDX field is the rate index * The HI field is the rate when RSSI is strong or being ignored @@ -170,13 +172,38 @@ static int rssi_mcs_tbl[][12] = { #ifdef WLAN_FEATURE_LINK_LAYER_STATS /** + * struct hdd_ll_stats - buffered hdd link layer stats + * @ll_stats_node: pointer to next stats buffered in scheduler thread context + * @result_param_id: Received link layer stats ID + * @result: received stats from FW + * @more_data: if more stats are pending + * @no_of_radios: no of radios + * @no_of_peers: no of peers + */ +struct hdd_ll_stats { + qdf_list_node_t ll_stats_node; + u32 result_param_id; + void *result; + u32 more_data; + union { + u32 no_of_radios; + u32 no_of_peers; + } stats_nradio_npeer; +}; + +/** * struct hdd_ll_stats_priv - hdd link layer stats private + * @ll_stats: head to different link layer stats received in scheduler + * thread context * @request_id: userspace-assigned link layer stats request id * @request_bitmap: userspace-assigned link layer stats request bitmap + * @ll_stats_lock: Lock to serially access request_bitmap */ struct hdd_ll_stats_priv { + qdf_list_t ll_stats_q; uint32_t request_id; uint32_t request_bitmap; + qdf_spinlock_t ll_stats_lock; }; /* @@ -905,15 +932,22 @@ static int hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS, radiostat->num_channels)) { hdd_err("QCA_WLAN_VENDOR_ATTR put fail"); + goto failure; } if (radiostat->total_num_tx_power_levels) { - if (nla_put(vendor_event, + ret = + nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL, sizeof(u32) * radiostat->total_num_tx_power_levels, - radiostat->tx_time_per_power_level)) { + radiostat->tx_time_per_power_level); + qdf_mem_free(radiostat->tx_time_per_power_level); + radiostat->tx_time_per_power_level = NULL; + if (ret) { + qdf_mem_free(radiostat->channels); + radiostat->channels = NULL; hdd_err("nla_put fail"); goto failure; } @@ -922,6 +956,8 @@ static int hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, if (radiostat->num_channels) { ret = hdd_llstats_radio_fill_channels(adapter, radiostat, vendor_event); + qdf_mem_free(radiostat->channels); + radiostat->channels = NULL; if (ret) goto failure; } @@ -995,72 +1031,188 @@ hdd_link_layer_process_radio_stats(struct hdd_adapter *adapter, } -/** - * hdd_ll_process_radio_stats() - Wrapper function for cfg80211/debugfs - * @adapter: Pointer to device adapter - * @more_data: More data - * @data: Pointer to stats data - * @num_radios: Number of radios - * @resp_id: Response ID from FW - * - * Receiving Link Layer Radio statistics from FW. This function is a wrapper - * function which calls cfg80211/debugfs functions based on the response ID. - * - * Return: None - */ -static void hdd_ll_process_radio_stats(struct hdd_adapter *adapter, - uint32_t more_data, void *data, uint32_t num_radio, - uint32_t resp_id) +static void hdd_process_ll_stats(tSirLLStatsResults *results, + struct osif_request *request) { - if (DEBUGFS_LLSTATS_REQID == resp_id) - hdd_debugfs_process_radio_stats(adapter, more_data, - (struct wifi_radio_stats *)data, num_radio); - else - hdd_link_layer_process_radio_stats(adapter, more_data, - (struct wifi_radio_stats *)data, num_radio); -} + struct hdd_ll_stats_priv *priv = osif_request_priv(request); + struct hdd_ll_stats *stats = NULL; + size_t stat_size = 0; -/** - * hdd_ll_process_iface_stats() - Wrapper function for cfg80211/debugfs - * @adapter: Pointer to device adapter - * @data: Pointer to stats data - * @num_peers: Number of peers - * @resp_id: Response ID from FW - * - * Receiving Link Layer Radio statistics from FW. This function is a wrapper - * function which calls cfg80211/debugfs functions based on the response ID. - * - * Return: None - */ -static void hdd_ll_process_iface_stats(struct hdd_adapter *adapter, - void *data, uint32_t num_peers, - uint32_t resp_id) -{ - if (DEBUGFS_LLSTATS_REQID == resp_id) - hdd_debugfs_process_iface_stats(adapter, data, num_peers); - else - hdd_link_layer_process_iface_stats(adapter, data, num_peers); + if (!(priv->request_bitmap & results->paramId)) + return; + + if (results->paramId & WMI_LINK_STATS_RADIO) { + struct wifi_radio_stats *rs_results, *stat_result; + u64 channel_size = 0, pwr_lvl_size = 0; + int i; + stats = qdf_mem_malloc(sizeof(*stats)); + if (!stats) + goto exit; + + stat_size = sizeof(struct wifi_radio_stats) * + results->num_radio; + stats->result_param_id = WMI_LINK_STATS_RADIO; + stat_result = qdf_mem_malloc(stat_size); + if (!stat_result) { + qdf_mem_free(stats); + goto exit; + } + stats->result = stat_result; + rs_results = (struct wifi_radio_stats *)results->results; + qdf_mem_copy(stats->result, results->results, stat_size); + for (i = 0; i < results->num_radio; i++) { + channel_size = rs_results->num_channels * + sizeof(struct wifi_channel_stats); + pwr_lvl_size = sizeof(uint32_t) * + rs_results->total_num_tx_power_levels; + + if (rs_results->total_num_tx_power_levels && + rs_results->tx_time_per_power_level) { + stat_result->tx_time_per_power_level = + qdf_mem_malloc(pwr_lvl_size); + if (!stat_result->tx_time_per_power_level) { + while (i-- > 0) { + stat_result--; + qdf_mem_free(stat_result-> + tx_time_per_power_level); + qdf_mem_free(stat_result-> + channels); + } + qdf_mem_free(stat_result); + qdf_mem_free(stats); + goto exit; + } + qdf_mem_copy(stat_result->tx_time_per_power_level, + rs_results->tx_time_per_power_level, + pwr_lvl_size); + } + if (channel_size) { + stat_result->channels = + qdf_mem_malloc(channel_size); + if (!stat_result->channels) { + qdf_mem_free(stat_result-> + tx_time_per_power_level); + while (i-- > 0) { + stat_result--; + qdf_mem_free(stat_result-> + tx_time_per_power_level); + qdf_mem_free(stat_result-> + channels); + } + qdf_mem_free(stats->result); + qdf_mem_free(stats); + goto exit; + } + qdf_mem_copy(stat_result->channels, + rs_results->channels, + channel_size); + } + rs_results++; + stat_result++; + } + stats->stats_nradio_npeer.no_of_radios = results->num_radio; + stats->more_data = results->moreResultToFollow; + if (!results->moreResultToFollow) + priv->request_bitmap &= ~stats->result_param_id; + } else if (results->paramId & WMI_LINK_STATS_IFACE) { + stats = qdf_mem_malloc(sizeof(*stats)); + if (!stats) + goto exit; + + stats->result_param_id = WMI_LINK_STATS_IFACE; + stats->stats_nradio_npeer.no_of_peers = results->num_peers; + stats->result = qdf_mem_malloc(sizeof(struct + wifi_interface_stats)); + if (!stats->result) { + qdf_mem_free(stats); + goto exit; + } + qdf_mem_copy(stats->result, results->results, + sizeof(struct wifi_interface_stats)); + if (!results->num_peers) + priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + priv->request_bitmap &= ~stats->result_param_id; + } else if (results->paramId & WMI_LINK_STATS_ALL_PEER) { + struct wifi_peer_stat *peer_stat = (struct wifi_peer_stat *) + results->results; + struct wifi_peer_info *peer_info = NULL; + u64 num_rate = 0, peers, rates; + int i; + stats = qdf_mem_malloc(sizeof(*stats)); + if (!stats) + goto exit; + + peer_info = (struct wifi_peer_info *)peer_stat->peer_info; + for (i = 1; i <= peer_stat->num_peers; i++) { + num_rate += peer_info->num_rate; + peer_info = (struct wifi_peer_info *)((uint8_t *) + peer_info + sizeof(struct wifi_peer_info) + + (peer_info->num_rate * + sizeof(struct wifi_rate_stat))); + } + + peers = sizeof(struct wifi_peer_info) * peer_stat->num_peers; + rates = sizeof(struct wifi_rate_stat) * num_rate; + stat_size = sizeof(struct wifi_peer_stat) + peers + rates; + stats->result_param_id = WMI_LINK_STATS_ALL_PEER; + + stats->result = qdf_mem_malloc(stat_size); + if (!stats->result) { + qdf_mem_free(stats); + goto exit; + } + + qdf_mem_copy(stats->result, results->results, stat_size); + stats->more_data = results->moreResultToFollow; + if (!results->moreResultToFollow) + priv->request_bitmap &= ~stats->result_param_id; + } else { + hdd_err("INVALID LL_STATS_NOTIFY RESPONSE"); + } + /* send indication to caller thread */ + if (stats) + qdf_list_insert_back(&priv->ll_stats_q, &stats->ll_stats_node); + + if (!priv->request_bitmap) +exit: + osif_request_complete(request); } -/** - * hdd_ll_process_peer_stats() - Wrapper function for cfg80211/debugfs - * @adapter: Pointer to device adapter - * @more_data: More data - * @data: Pointer to stats data - * @resp_id: Response ID from FW - * - * Receiving Link Layer Radio statistics from FW. This function is a wrapper - * function which calls cfg80211/debugfs functions based on the response ID. - * - * Return: None - */ -static void hdd_ll_process_peer_stats(struct hdd_adapter *adapter, - uint32_t more_data, void *data, uint32_t resp_id) +static void hdd_debugfs_process_ll_stats(struct hdd_adapter *adapter, + tSirLLStatsResults *results, + struct osif_request *request) { - if (DEBUGFS_LLSTATS_REQID == resp_id) - hdd_debugfs_process_peer_stats(adapter, data); - else - hdd_link_layer_process_peer_stats(adapter, more_data, data); + struct hdd_ll_stats_priv *priv = osif_request_priv(request); + + if (results->paramId & WMI_LINK_STATS_RADIO) { + hdd_debugfs_process_radio_stats(adapter, + results->moreResultToFollow, + results->results, + results->num_radio); + if (!results->moreResultToFollow) + priv->request_bitmap &= ~(WMI_LINK_STATS_RADIO); + } else if (results->paramId & WMI_LINK_STATS_IFACE) { + hdd_debugfs_process_iface_stats(adapter, results->results, + results->num_peers); + + /* Firmware doesn't send peerstats event if no peers are + * connected. HDD should not wait for any peerstats in + * this case and return the status to middleware after + * receiving iface stats + */ + + if (!results->num_peers) + priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + } else if (results->paramId & WMI_LINK_STATS_ALL_PEER) { + hdd_debugfs_process_peer_stats(adapter, results->results); + if (!results->moreResultToFollow) + priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + } else { + hdd_err("INVALID LL_STATS_NOTIFY RESPONSE"); + } + + if (!priv->request_bitmap) + osif_request_complete(request); } void wlan_hdd_cfg80211_link_layer_stats_callback(hdd_handle_t hdd_handle, @@ -1104,8 +1256,7 @@ void wlan_hdd_cfg80211_link_layer_stats_callback(hdd_handle_t hdd_handle, priv = osif_request_priv(request); /* validate response received from target */ - if ((priv->request_id != results->rspId) || - !(priv->request_bitmap & results->paramId)) { + if (priv->request_id != results->rspId) { hdd_err("Request id %d response id %d request bitmap 0x%x response bitmap 0x%x", priv->request_id, results->rspId, priv->request_bitmap, results->paramId); @@ -1113,52 +1264,15 @@ void wlan_hdd_cfg80211_link_layer_stats_callback(hdd_handle_t hdd_handle, return; } - if (results->paramId & WMI_LINK_STATS_RADIO) { - hdd_ll_process_radio_stats(adapter, - results->moreResultToFollow, - results->results, - results->num_radio, - results->rspId); - - if (!results->moreResultToFollow) - priv->request_bitmap &= ~(WMI_LINK_STATS_RADIO); - - } else if (results->paramId & - WMI_LINK_STATS_IFACE) { - hdd_ll_process_iface_stats(adapter, - results->results, - results->num_peers, - results->rspId); - - /* Firmware doesn't send peerstats event if no peers are - * connected. HDD should not wait for any peerstats in - * this case and return the status to middleware after - * receiving iface stats - */ - if (!results->num_peers) - priv->request_bitmap &= - ~(WMI_LINK_STATS_ALL_PEER); - priv->request_bitmap &= ~(WMI_LINK_STATS_IFACE); - - } else if (results-> - paramId & WMI_LINK_STATS_ALL_PEER) { - hdd_ll_process_peer_stats(adapter, - results->moreResultToFollow, - results->results, - results->rspId); - - if (!results->moreResultToFollow) - priv->request_bitmap &= - ~(WMI_LINK_STATS_ALL_PEER); - - } else { - hdd_err("INVALID LL_STATS_NOTIFY RESPONSE"); + if (results->rspId == DEBUGFS_LLSTATS_REQID) { + hdd_debugfs_process_ll_stats(adapter, results, request); + } else { + qdf_spin_lock(&priv->ll_stats_lock); + if (priv->request_bitmap) + hdd_process_ll_stats(results, request); + qdf_spin_unlock(&priv->ll_stats_lock); } - /* complete response event if all requests are completed */ - if (!priv->request_bitmap) - osif_request_complete(request); - osif_request_put(request); break; } @@ -1339,12 +1453,56 @@ nla_policy [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK] = {.type = NLA_U32} }; -static int wlan_hdd_send_ll_stats_req(struct hdd_context *hdd_ctx, +static void wlan_hdd_handle_ll_stats(struct hdd_adapter *adapter, + struct hdd_ll_stats *stats, + int ret) +{ + switch (stats->result_param_id) { + case WMI_LINK_STATS_RADIO: + { + struct wifi_radio_stats *radio_stat = stats->result; + int i, num_radio = stats->stats_nradio_npeer.no_of_radios; + + if (ret == -ETIMEDOUT) { + for (i = 0; i < num_radio; i++) { + if (radio_stat->num_channels) + qdf_mem_free(radio_stat->channels); + if (radio_stat->total_num_tx_power_levels) + qdf_mem_free(radio_stat-> + tx_time_per_power_level); + radio_stat++; + } + return; + } + hdd_link_layer_process_radio_stats(adapter, stats->more_data, + radio_stat, num_radio); + } + break; + case WMI_LINK_STATS_IFACE: + hdd_link_layer_process_iface_stats(adapter, stats->result, + stats->stats_nradio_npeer. + no_of_peers); + break; + case WMI_LINK_STATS_ALL_PEER: + hdd_link_layer_process_peer_stats(adapter, + stats->more_data, + stats->result); + break; + default: + hdd_err("not requested event"); + } +} + +static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, tSirLLStatsGetReq *req) { - int ret; + int ret = 0; struct hdd_ll_stats_priv *priv; + struct hdd_ll_stats *stats = NULL; struct osif_request *request; + qdf_list_node_t *ll_node; + QDF_STATUS status; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); void *cookie; static const struct osif_request_params params = { .priv_size = sizeof(*priv), @@ -1365,6 +1523,8 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_context *hdd_ctx, priv->request_id = req->reqId; priv->request_bitmap = req->paramIdMask; + qdf_spinlock_create(&priv->ll_stats_lock); + qdf_list_create(&priv->ll_stats_q, HDD_LINK_STATS_MAX); if (QDF_STATUS_SUCCESS != sme_ll_stats_get_req(hdd_ctx->mac_handle, req, @@ -1373,18 +1533,33 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_context *hdd_ctx, ret = -EINVAL; goto exit; } - ret = osif_request_wait_for_response(request); if (ret) { hdd_err("Target response timed out request id %d request bitmap 0x%x", priv->request_id, priv->request_bitmap); + qdf_spin_lock(&priv->ll_stats_lock); + priv->request_bitmap = 0; + qdf_spin_unlock(&priv->ll_stats_lock); ret = -ETIMEDOUT; - goto exit; } - hdd_exit(); - + qdf_spin_lock(&priv->ll_stats_lock); + status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node); + qdf_spin_unlock(&priv->ll_stats_lock); + while (QDF_IS_STATUS_SUCCESS(status)) { + stats = qdf_container_of(ll_node, struct hdd_ll_stats, + ll_stats_node); + wlan_hdd_handle_ll_stats(adapter, stats, ret); + qdf_mem_free(stats->result); + qdf_mem_free(stats); + qdf_spin_lock(&priv->ll_stats_lock); + status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node); + qdf_spin_unlock(&priv->ll_stats_lock); + } + qdf_list_destroy(&priv->ll_stats_q); exit: + hdd_exit(); osif_request_put(request); + return ret; } @@ -1394,7 +1569,6 @@ int wlan_hdd_ll_stats_get(struct hdd_adapter *adapter, uint32_t req_id, int errno; tSirLLStatsGetReq get_req; struct hdd_station_ctx *hddstactx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); hdd_enter(); @@ -1418,7 +1592,7 @@ int wlan_hdd_ll_stats_get(struct hdd_adapter *adapter, uint32_t req_id, get_req.staId = adapter->vdev_id; rtnl_lock(); - errno = wlan_hdd_send_ll_stats_req(hdd_ctx, &get_req); + errno = wlan_hdd_send_ll_stats_req(adapter, &get_req); rtnl_unlock(); if (errno) hdd_err("Send LL stats req failed, id:%u, mask:%d, session:%d", @@ -1504,7 +1678,7 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) return -EINVAL; - ret = wlan_hdd_send_ll_stats_req(hdd_ctx, &LinkLayerStatsGetReq); + ret = wlan_hdd_send_ll_stats_req(adapter, &LinkLayerStatsGetReq); if (0 != ret) { hdd_err("Failed to send LL stats request (id:%u)", LinkLayerStatsGetReq.reqId); diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index fa47db010b..666b785f86 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 05 -#define QWLAN_VERSION_EXTRA "N" -#define QWLAN_VERSION_BUILD 20 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 21 -#define QWLAN_VERSIONSTR "5.2.05.20N" +#define QWLAN_VERSIONSTR "5.2.05.21" #endif /* QWLAN_VERSION_H */ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 2fd55f241f..596cc99dd7 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -724,6 +724,7 @@ struct bss_description { #endif uint32_t assoc_disallowed; uint32_t adaptive_11r_ap; + uint32_t mbo_oce_enabled_ap; #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) uint32_t is_single_pmk; #endif diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index ce5c87da39..d251afe338 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1650,8 +1650,7 @@ static void lim_process_addba_req(struct mac_context *mac_ctx, uint8_t *rx_pkt_i body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); - QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO, - body_ptr, frame_len); + QDF_TRACE_HEX_DUMP_DEBUG_RL(QDF_MODULE_ID_PE, body_ptr, frame_len); addba_req = qdf_mem_malloc(sizeof(*addba_req)); if (!addba_req) diff --git a/core/pld/src/pld_pcie.c b/core/pld/src/pld_pcie.c index c6b272c52c..ab91ddb083 100644 --- a/core/pld/src/pld_pcie.c +++ b/core/pld/src/pld_pcie.c @@ -490,11 +490,22 @@ static int pld_pcie_pm_resume_noirq(struct device *dev) #endif static struct pci_device_id pld_pcie_id_table[] = { - { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID }, +#ifdef CONFIG_AR6320_SUPPORT { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID }, +#elif defined(QCA_WIFI_QCA6290) + { 0x17cb, 0x1100, PCI_ANY_ID, PCI_ANY_ID }, +#elif defined(QCA_WIFI_QCA6390) + { 0x17cb, 0x1101, PCI_ANY_ID, PCI_ANY_ID }, +#elif defined(QCA_WIFI_QCA6490) + { 0x17cb, 0x1103, PCI_ANY_ID, PCI_ANY_ID }, +#elif defined(QCN7605_SUPPORT) + { 0x17cb, 0x1102, PCI_ANY_ID, PCI_ANY_ID }, +#else + { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID }, { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID }, { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID }, { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID }, +#endif { 0 } }; diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c index 4d6a3088fb..9502332b4c 100644 --- a/core/sap/src/sap_ch_select.c +++ b/core/sap/src/sap_ch_select.c @@ -1377,6 +1377,8 @@ static void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, pSpectInfoParams->numSpectChans; qdf_list_node_t *cur_lst = NULL, *next_lst = NULL; struct scan_cache_node *cur_node = NULL; + uint32_t normalized_weight; + uint8_t normalize_factor; bcn_struct = qdf_mem_malloc(sizeof(tSirProbeRespBeacon)); if (!bcn_struct) @@ -1555,6 +1557,20 @@ static void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, pSpectCh->bssCount = SOFTAP_MIN_COUNT; } + if (wlan_reg_is_dfs_ch(mac->pdev, + pSpectCh->chNum)) { + normalize_factor = + MLME_GET_DFS_CHAN_WEIGHT( + mac->mlme_cfg->acs.np_chan_weightage); + normalized_weight = + ((SAP_ACS_WEIGHT_MAX - pSpectCh->weight) * + (100 - normalize_factor)) / 100; + sap_debug("DFS ch %d old weight %d new weight %d", + pSpectCh->chNum, pSpectCh->weight, + pSpectCh->weight + normalized_weight); + pSpectCh->weight += normalized_weight; + + } if (pSpectCh->weight > SAP_ACS_WEIGHT_MAX) pSpectCh->weight = SAP_ACS_WEIGHT_MAX; pSpectCh->weight_copy = pSpectCh->weight; diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index bafbb09d3b..99e7403788 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -3383,6 +3383,13 @@ static QDF_STATUS sap_get_channel_list(struct sap_context *sap_ctx, WLAN_REG_CH_NUM(loop_count))) continue; + if (wlan_reg_is_dfs_ch(mac_ctx->pdev, + WLAN_REG_CH_NUM(loop_count)) && + !MLME_GET_DFS_CHAN_WEIGHT( + mac_ctx->mlme_cfg->acs.np_chan_weightage)) { + sap_debug("DFS ch with np weight 0, skipping"); + continue; + } #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE uint8_t ch; diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index d7eabeb67e..51e16a38d8 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -1211,10 +1211,22 @@ wlansap_update_csa_channel_params(struct sap_context *sap_context, if (sap_context->csr_roamProfile.phyMode == eCSR_DOT11_MODE_11ac || sap_context->csr_roamProfile.phyMode == - eCSR_DOT11_MODE_11ac_ONLY) + eCSR_DOT11_MODE_11ac_ONLY || + sap_context->csr_roamProfile.phyMode == + eCSR_DOT11_MODE_11ax || + sap_context->csr_roamProfile.phyMode == + eCSR_DOT11_MODE_11ax_ONLY) { bw = BW80; - else + } else if (sap_context->csr_roamProfile.phyMode == + eCSR_DOT11_MODE_11n || + sap_context->csr_roamProfile.phyMode == + eCSR_DOT11_MODE_11n_ONLY) { bw = BW40_HIGH_PRIMARY; + } else { + /* For legacy 11a mode return 20MHz */ + mac_ctx->sap.SapDfsInfo.new_chanWidth = CH_WIDTH_20MHZ; + return QDF_STATUS_SUCCESS; + } for (; bw >= BW20; bw--) { uint16_t op_class; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 49fb001274..e381671f54 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3538,20 +3538,10 @@ QDF_STATUS csr_roam_call_callback(struct mac_context *mac, uint32_t sessionId, csr_dump_connection_stats(mac, pSession, roam_info, u1, u2); if (pSession->callback) { - if (roam_info) { + if (roam_info) roam_info->sessionId = (uint8_t) sessionId; - /* - * the reasonCode will be passed to supplicant by - * cfg80211_disconnected. Based on the document, - * the reason code passed to supplicant needs to set - * to 0 if unknown. eSIR_BEACON_MISSED reason code is - * not recognizable so that we set to 0 instead. - */ - if (roam_info->reasonCode == eSIR_MAC_BEACON_MISSED) - roam_info->reasonCode = 0; - } status = pSession->callback(pSession->pContext, roam_info, - roamId, u1, u2); + roamId, u1, u2); } /* * EVENT_WLAN_STATUS_V2: eCSR_ROAM_ASSOCIATION_COMPLETION, @@ -5339,6 +5329,8 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx, enum policy_mgr_con_mode mode; uint8_t chan_id; QDF_STATUS qdf_status; + eCsrPhyMode self_phymode = mac_ctx->roam.configParam.phyMode; + tDot11fBeaconIEs *bcn_ies; vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id, @@ -5361,6 +5353,29 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx, * sessions exempted */ result = &scan_result->Result; + bcn_ies = result->pvIes; + /* + * If phymode is configured to DOT11 Only profile. + * Don't connect to profile which is less than them. + */ + if (bcn_ies && ((self_phymode == eCSR_DOT11_MODE_11n_ONLY && + !bcn_ies->HTCaps.present) || + (self_phymode == eCSR_DOT11_MODE_11ac_ONLY && + !bcn_ies->VHTCaps.present) || + (self_phymode == eCSR_DOT11_MODE_11ax_ONLY && + !bcn_ies->he_cap.present))) { + sme_info("self_phymode %d mismatch HT %d VHT %d HE %d", + self_phymode, bcn_ies->HTCaps.present, + bcn_ies->VHTCaps.present, + bcn_ies->he_cap.present); + *roam_state = eCsrStopRoamingDueToConcurrency; + status = true; + *roam_bss_entry = csr_ll_next(&bss_list->List, + *roam_bss_entry, + LL_ACCESS_LOCK); + continue; + } + /* * Ignore the BSS if any other vdev is already connected * to it. @@ -19257,22 +19272,38 @@ void csr_rso_command_fill_11w_params(struct mac_context *mac_ctx, #endif /** - * csr_get_peer_pmf_status() - Get the PMF capability of peer + * csr_update_btm_offload_config() - Update btm config param to fw * @mac_ctx: Global mac ctx + * @command: Roam offload command + * @req_buf: roam offload scan request * @session: roam session * - * Return: True if PMF is enabled, false otherwise. + * Return: None */ -static bool csr_get_peer_pmf_status(struct mac_context *mac_ctx, - struct csr_roam_session *session) +static void csr_update_btm_offload_config(struct mac_context *mac_ctx, + uint8_t command, + struct roam_offload_scan_req *req_buf, + struct csr_roam_session *session) { struct wlan_objmgr_peer *peer; bool is_pmf_enabled; + req_buf->btm_offload_config = + mac_ctx->mlme_cfg->btm.btm_offload_config; + + /* Return if INI is disabled */ + if (!req_buf->btm_offload_config) + return; + + /* For RSO Stop Disable BTM offload to firmware */ + if (command == ROAM_SCAN_OFFLOAD_STOP) { + req_buf->btm_offload_config = 0; + return; + } if (!session->pConnectBssDesc) { sme_err("Connected Bss Desc is NULL"); - return false; + return; } peer = wlan_objmgr_get_peer(mac_ctx->psoc, @@ -19282,7 +19313,7 @@ static bool csr_get_peer_pmf_status(struct mac_context *mac_ctx, if (!peer) { sme_debug("Peer of peer_mac %pM not found", session->pConnectBssDesc->bssId); - return false; + return; } is_pmf_enabled = mlme_get_peer_pmf_status(peer); @@ -19290,7 +19321,12 @@ static bool csr_get_peer_pmf_status(struct mac_context *mac_ctx, sme_debug("get is_pmf_enabled %d for %pM", is_pmf_enabled, session->pConnectBssDesc->bssId); - return is_pmf_enabled; + /* If peer does not support PMF in case of OCE/MBO + * Connection, Disable BTM offload to firmware. + */ + if (session->pConnectBssDesc->mbo_oce_enabled_ap && + !is_pmf_enabled) + req_buf->btm_offload_config = 0; } /** @@ -19564,15 +19600,7 @@ csr_create_roam_scan_offload_request(struct mac_context *mac_ctx, req_buf->lca_config_params.num_disallowed_aps = mac_ctx->mlme_cfg->lfr.lfr3_num_disallowed_aps; - /* For RSO Stop or if peer does not support PMF, Disable BTM offload - * to firmware. - */ - if (command == ROAM_SCAN_OFFLOAD_STOP || - !csr_get_peer_pmf_status(mac_ctx, session)) - req_buf->btm_offload_config = 0; - else - req_buf->btm_offload_config = - mac_ctx->mlme_cfg->btm.btm_offload_config; + csr_update_btm_offload_config(mac_ctx, command, req_buf, session); req_buf->btm_solicited_timeout = mac_ctx->mlme_cfg->btm.btm_solicited_timeout; @@ -22712,6 +22740,7 @@ static QDF_STATUS csr_process_roam_sync_callback(struct mac_context *mac_ctx, struct wlan_objmgr_vdev *vdev; struct mlme_roam_after_data_stall *vdev_roam_params; uint32_t chan_id; + struct wlan_crypto_pmksa *pmksa; vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, session_id, WLAN_LEGACY_SME_ID); @@ -22970,6 +22999,35 @@ static QDF_STATUS csr_process_roam_sync_callback(struct mac_context *mac_ctx, } else { sme_debug("PMKID Not found in cache for " QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(pmkid_cache->BSSID.bytes)); + if (roam_synch_data->pmk_len) { + pmksa = qdf_mem_malloc(sizeof(*pmksa)); + if (!pmksa) { + status = QDF_STATUS_E_NOMEM; + goto end; + } + + session->pmk_len = roam_synch_data->pmk_len; + qdf_mem_zero(session->psk_pmk, + sizeof(session->psk_pmk)); + qdf_mem_copy(session->psk_pmk, + roam_synch_data->pmk, + session->pmk_len); + + qdf_copy_macaddr(&pmksa->bssid, + &session-> + connectedProfile.bssid); + qdf_mem_copy(pmksa->pmkid, + roam_synch_data->pmkid, PMKID_LEN); + qdf_mem_copy(pmksa->pmk, roam_synch_data->pmk, + roam_synch_data->pmk_len); + pmksa->pmk_len = roam_synch_data->pmk_len; + + if (wlan_crypto_set_del_pmksa(vdev, pmksa, true) + != QDF_STATUS_SUCCESS) { + qdf_mem_zero(pmksa, sizeof(*pmksa)); + qdf_mem_free(pmksa); + } + } } qdf_mem_zero(pmkid_cache, sizeof(*pmkid_cache)); qdf_mem_free(pmkid_cache); diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 27605006b9..396be9e389 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2652,6 +2652,9 @@ static QDF_STATUS csr_fill_bss_from_scan_entry(struct mac_context *mac_ctx, scan_entry); bss_desc->adaptive_11r_ap = scan_entry->adaptive_11r_ap; + bss_desc->mbo_oce_enabled_ap = + util_scan_entry_mbo_oce(scan_entry) ? true : false; + csr_fill_single_pmk_ap_cap_from_scan_entry(bss_desc, scan_entry); qdf_mem_copy(&bss_desc->mbssid_info, &scan_entry->mbssid_info, diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index b35066bf49..8bc1db0c6a 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -2415,6 +2415,7 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, wmi_key_material_ext *key_ft; struct wma_txrx_node *iface = NULL; wmi_roam_fils_synch_tlv_param *fils_info; + wmi_roam_pmk_cache_synch_tlv_param *pmk_cache_info; int status = -EINVAL; uint8_t kck_len; uint8_t kek_len; @@ -2555,6 +2556,22 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, roam_synch_ind_ptr->update_erp_next_seq_num, roam_synch_ind_ptr->next_erp_seq_num); } + + pmk_cache_info = param_buf->roam_pmk_cache_synch_info; + if (pmk_cache_info && (pmk_cache_info->pmk_len)) { + if (pmk_cache_info->pmk_len > SIR_PMK_LEN) { + WMA_LOGE("%s: Invalid pmk_len %d", __func__, + pmk_cache_info->pmk_len); + wma_free_roam_synch_frame_ind(iface); + return status; + } + + roam_synch_ind_ptr->pmk_len = pmk_cache_info->pmk_len; + qdf_mem_copy(roam_synch_ind_ptr->pmk, + pmk_cache_info->pmk, pmk_cache_info->pmk_len); + qdf_mem_copy(roam_synch_ind_ptr->pmkid, + pmk_cache_info->pmkid, PMKID_LEN); + } wma_free_roam_synch_frame_ind(iface); return 0; } |