From fd9f26cb8ecf120edf9cdcffd2078cbb37cb3e7a Mon Sep 17 00:00:00 2001 From: Amruta Kulkarni Date: Thu, 12 Nov 2020 15:39:04 -0800 Subject: [PATCH] qcacld-3.0: Add support for STA + monitor mode In mission mode, add support for virtual add/del monitor mode interface. In addition to STA vdev, create and maintain a new vdev for monitor interface. Change-Id: I91ea8e56976cce92f9b1ae308d4bd0fb30815366 CRs-Fixed: 2818499 --- .../pkt_capture/src/target_if_pkt_capture.c | 2 +- core/dp/txrx/ol_tx_send.c | 4 +- core/hdd/inc/wlan_hdd_main.h | 110 ++++---- core/hdd/src/wlan_hdd_assoc.c | 13 +- core/hdd/src/wlan_hdd_cfg80211.c | 11 +- core/hdd/src/wlan_hdd_hostapd.c | 7 + core/hdd/src/wlan_hdd_main.c | 266 +++++++++--------- core/hdd/src/wlan_hdd_p2p.c | 46 ++- core/hdd/src/wlan_hdd_power.c | 12 +- core/hdd/src/wlan_hdd_rx_monitor.c | 35 +-- core/hdd/src/wlan_hdd_rx_monitor.h | 43 ++- core/mac/src/pe/lim/lim_api.c | 2 +- core/wma/src/wma_main.c | 3 +- 13 files changed, 314 insertions(+), 240 deletions(-) diff --git a/components/target_if/pkt_capture/src/target_if_pkt_capture.c b/components/target_if/pkt_capture/src/target_if_pkt_capture.c index 78b44545e029..7621667e304d 100644 --- a/components/target_if/pkt_capture/src/target_if_pkt_capture.c +++ b/components/target_if/pkt_capture/src/target_if_pkt_capture.c @@ -175,7 +175,7 @@ target_if_register_mgmt_data_offload_event(struct wlan_objmgr_psoc *psoc) } wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); - if (ucfg_pkt_capture_get_mode(psoc) && + if ((ucfg_pkt_capture_get_mode(psoc) != PACKET_CAPTURE_MODE_DISABLE) && wmi_service_enabled(wmi_handle, wmi_service_packet_capture_support)) { uint8_t status; diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c index aa1bf5591350..8bfca9dd83b2 100644 --- a/core/dp/txrx/ol_tx_send.c +++ b/core/dp/txrx/ol_tx_send.c @@ -1005,8 +1005,8 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev, msg_word_header, &msg_word_payload, num_msdus); } - if ((ucfg_pkt_capture_get_mode((void *)soc->psoc) & - PKT_CAPTURE_MODE_DATA_ONLY)) + if ((ucfg_pkt_capture_get_mode((void *)soc->psoc) == + PACKET_CAPTURE_MODE_DATA_ONLY)) pkt_capture_txcomp_hdr_list = ucfg_pkt_capture_tx_get_txcomplete_data_hdr( msg_word, diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 33c3406ac8a9..39b2bbc50f9e 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1061,6 +1061,8 @@ struct hdd_chan_change_params { * @dfs: dfs context to prevent/allow runtime pm * @connect: connect context to prevent/allow runtime pm * @user: user context to prevent/allow runtime pm + * @is_user_wakelock_acquired: boolean to check if user wakelock status + * @monitor_mode: monitor mode context to prevent/allow runtime pm * * Runtime PM control for underlying activities */ @@ -1069,6 +1071,7 @@ struct hdd_runtime_pm_context { qdf_runtime_lock_t connect; qdf_runtime_lock_t user; bool is_user_wakelock_acquired; + qdf_runtime_lock_t monitor_mode; }; /* @@ -1754,6 +1757,7 @@ struct hdd_adapter_ops_history { * @qos_cpu_mask: voted cpu core mask * @adapter_ops_wq: High priority workqueue for handling adapter operations * @multi_client_thermal_mitigation: Multi client thermal mitigation by fw + * @disconnect_for_sta_mon_conc: disconnect if sta monitor intf concurrency */ struct hdd_context { struct wlan_objmgr_psoc *psoc; @@ -2095,6 +2099,7 @@ struct hdd_context { #ifdef FEATURE_WPSS_THERMAL_MITIGATION bool multi_client_thermal_mitigation; #endif + bool disconnect_for_sta_mon_conc; }; /** @@ -2604,6 +2609,11 @@ void hdd_deinit_adapter(struct hdd_context *hdd_ctx, QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter); +/** + * hdd_set_station_ops() - update net_device ops + * @dev: Handle to struct net_device to be updated. + * Return: None + */ void hdd_set_station_ops(struct net_device *dev); /** @@ -4540,7 +4550,57 @@ QDF_STATUS hdd_common_roam_callback(struct wlan_objmgr_psoc *psoc, eCsrRoamResult roam_result); #ifdef WLAN_FEATURE_PKT_CAPTURE +/** + * wlan_hdd_is_mon_concurrency() - check if MONITOR and STA concurrency + * is UP when packet capture mode is enabled. + * + * Return: True - if STA and monitor concurrency is there, else False + * + */ +bool wlan_hdd_is_mon_concurrency(void); +/** + * wlan_hdd_del_monitor() - delete monitor interface + * @hdd_ctx: pointer to hdd context + * @adapter: adapter to be deleted + * @rtnl_held: rtnl lock held + * + * This function is invoked to delete monitor interface. + * + * Return: None + */ +void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter, bool rtnl_held); + +/** + * wlan_hdd_del_p2p_interface() - delete p2p interface + * @hdd_ctx: pointer to hdd context + * + * This function is invoked to delete p2p interface. + * + * Return: None + */ +void +wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx); + +#else +static inline +void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter, bool rtnl_held) +{ +} + +static inline +bool wlan_hdd_is_mon_concurrency(void) +{ + return false; +} + +static inline +void wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx) +{ +} +#endif /* WLAN_FEATURE_PKT_CAPTURE */ /** * wlan_hdd_is_session_type_monitor() - check if session type is MONITOR * @session_type: session type @@ -4550,15 +4610,6 @@ QDF_STATUS hdd_common_roam_callback(struct wlan_objmgr_psoc *psoc, */ bool wlan_hdd_is_session_type_monitor(uint8_t session_type); -/** - * wlan_hdd_check_mon_concurrency() - check if MONITOR and STA concurrency - * is UP when packet capture mode is enabled. - * - * Return: True - if STA and monitor concurrency is there, else False - * - */ -bool wlan_hdd_check_mon_concurrency(void); - /** * wlan_hdd_add_monitor_check() - check for monitor intf and add if needed * @hdd_ctx: pointer to hdd context @@ -4575,47 +4626,6 @@ int wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx, const char *name, bool rtnl_held, unsigned char name_assign_type); -/** - * wlan_hdd_del_monitor() - delete monitor interface - * @hdd_ctx: pointer to hdd context - * @adapter: adapter to be deleted - * @rtnl_held: rtnl lock held - * - * This function is invoked to delete monitor interface. - * - * Return: None - */ -void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, - struct hdd_adapter *adapter, bool rtnl_held); -#else -static inline -bool wlan_hdd_is_session_type_monitor(uint8_t session_type) -{ - return false; -} - -static inline -bool wlan_hdd_check_mon_concurrency(void) -{ - return false; -} - -static inline -int wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx, - struct hdd_adapter **adapter, - const char *name, bool rtnl_held, - unsigned char name_assign_type) -{ - return 0; -} - -static inline -void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, - struct hdd_adapter *adapter, bool rtnl_held) -{ -} -#endif /* WLAN_FEATURE_PKT_CAPTURE */ - #ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT /** * hdd_crash_inject() - Inject a crash diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index a26a535de0fb..982d28dfc45b 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1830,7 +1830,7 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, struct net_device *dev = adapter->dev; struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - bool sendDisconInd = true; + bool send_discon_ind = true; mac_handle_t mac_handle; struct wlan_ies disconnect_ies = {0}; bool from_ap = false; @@ -1878,8 +1878,13 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, sta_ctx->conn_info.conn_state) || (eConnectionState_Connecting == sta_ctx->conn_info.conn_state)) { - hdd_debug("HDD has initiated a disconnect, no need to send disconnect indication to kernel"); - sendDisconInd = false; + if (hdd_ctx->disconnect_for_sta_mon_conc) { + hdd_debug("Disconnect triggered by HDD to add monitor intf notify kernel"); + hdd_ctx->disconnect_for_sta_mon_conc = false; + } else { + hdd_debug("HDD has initiated a disconnect, don't send disconnect indication to kernel"); + send_discon_ind = false; + } } else { INIT_COMPLETION(adapter->disconnect_comp_var); hdd_conn_set_connection_state(adapter, @@ -1917,7 +1922,7 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, * Only send indication to kernel if not initiated * by kernel */ - if (sendDisconInd) { + if (send_discon_ind) { int reason = WLAN_REASON_UNSPECIFIED; if (roam_info && roam_info->disconnect_ies) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 58501ed66700..a64170c29731 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -17051,7 +17051,10 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, if (errno) return errno; - if (wlan_hdd_check_mon_concurrency()) + if (wlan_hdd_is_mon_concurrency()) + return -EINVAL; + + if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc)) return -EINVAL; qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, @@ -18431,7 +18434,8 @@ void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq, wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev, oper_freq, sec_ch_freq, ch_params); - if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) + if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE || + policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc)) hdd_mon_select_cbmode(adapter, oper_freq, ch_params); } @@ -20650,6 +20654,9 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, if (0 != status) return status; + if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc)) + return -EINVAL; + if (req->bssid) bssid = req->bssid; else if (bssid_hint) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index b760ec3622d6..3ebc179b6942 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -5130,6 +5130,13 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, hdd_enter(); + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) + return ret; + + if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc)) + return -EINVAL; + hdd_notify_teardown_tdls_links(hdd_ctx->psoc); ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index d2d3f3a67855..1e052b8280fe 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1428,6 +1428,7 @@ static void hdd_runtime_suspend_context_init(struct hdd_context *hdd_ctx) qdf_runtime_lock_init(&ctx->dfs); qdf_runtime_lock_init(&ctx->connect); qdf_runtime_lock_init(&ctx->user); + qdf_runtime_lock_init(&ctx->monitor_mode); ctx->is_user_wakelock_acquired = false; @@ -1447,6 +1448,7 @@ static void hdd_runtime_suspend_context_deinit(struct hdd_context *hdd_ctx) if (ctx->is_user_wakelock_acquired) qdf_runtime_pm_allow_suspend(&ctx->user); + qdf_runtime_lock_deinit(&ctx->monitor_mode); qdf_runtime_lock_deinit(&ctx->user); qdf_runtime_lock_deinit(&ctx->connect); qdf_runtime_lock_deinit(&ctx->dfs); @@ -2742,7 +2744,8 @@ static int __hdd_mon_open(struct net_device *dev) hdd_mon_mode_ether_setup(dev); - if (con_mode == QDF_GLOBAL_MONITOR_MODE) { + if (con_mode == QDF_GLOBAL_MONITOR_MODE || + ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) { ret = hdd_trigger_psoc_idle_restart(hdd_ctx); if (ret) { hdd_err("Failed to start WLAN modules return"); @@ -2750,7 +2753,8 @@ static int __hdd_mon_open(struct net_device *dev) } hdd_err("hdd_wlan_start_modules() successful !"); - if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) { + if ((!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) || + (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))) { ret = hdd_start_adapter(adapter); if (ret) { hdd_err("Failed to start adapter :%d", @@ -2763,6 +2767,15 @@ static int __hdd_mon_open(struct net_device *dev) set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); } + if (con_mode != QDF_GLOBAL_MONITOR_MODE && + ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) { + hdd_info("Acquire wakelock for STA + monitor mode"); + qdf_wake_lock_acquire(&hdd_ctx->monitor_mode_wakelock, + WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE); + qdf_runtime_pm_prevent_suspend( + &hdd_ctx->runtime_context.monitor_mode); + } + ret = hdd_set_mon_rx_cb(dev); if (!ret) @@ -4358,12 +4371,15 @@ static int __hdd_stop(struct net_device *dev) if (adapter->device_mode == QDF_STA_MODE) { hdd_lpass_notify_stop(hdd_ctx); - if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) hdd_close_monitor_interface(hdd_ctx); } if (wlan_hdd_is_session_type_monitor(adapter->device_mode) && - adapter->vdev) { + adapter->vdev && + ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { ucfg_pkt_capture_deregister_callbacks(adapter->vdev); hdd_objmgr_put_vdev(adapter->vdev); adapter->vdev = NULL; @@ -5044,16 +5060,21 @@ static const struct net_device_ops wlan_mon_drv_ops = { .ndo_get_stats = hdd_get_stats, }; -#ifdef WLAN_FEATURE_TSF_PTP /** - * hdd_set_station_ops() - update net_device ops for monitor mode + * hdd_set_mon_ops() - update net_device ops for monitor mode * @dev: Handle to struct net_device to be updated. * Return: None */ +static void hdd_set_mon_ops(struct net_device *dev) +{ + dev->netdev_ops = &wlan_mon_drv_ops; +} + +#ifdef WLAN_FEATURE_TSF_PTP void hdd_set_station_ops(struct net_device *dev) { if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) { - dev->netdev_ops = &wlan_mon_drv_ops; + hdd_set_mon_ops(dev); } else { dev->netdev_ops = &wlan_drv_ops; dev->ethtool_ops = &wlan_ethtool_ops; @@ -5063,7 +5084,7 @@ void hdd_set_station_ops(struct net_device *dev) void hdd_set_station_ops(struct net_device *dev) { if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) - dev->netdev_ops = &wlan_mon_drv_ops; + hdd_set_mon_ops(dev); else dev->netdev_ops = &wlan_drv_ops; } @@ -5082,6 +5103,9 @@ void hdd_set_station_ops(struct net_device *dev) dev->netdev_ops = &wlan_drv_ops; } #endif +static void hdd_set_mon_ops(struct net_device *dev) +{ +} #endif #ifdef WLAN_FEATURE_PKT_CAPTURE @@ -5177,10 +5201,15 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr, qdf_mem_copy(adapter->mac_addr.bytes, mac_addr, sizeof(tSirMacAddr)); dev->watchdog_timeo = HDD_TX_TIMEOUT; - if (wlan_hdd_is_session_type_monitor(session_type)) - hdd_set_pktcapture_ops(adapter->dev); - else + if (wlan_hdd_is_session_type_monitor(session_type)) { + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) + hdd_set_pktcapture_ops(adapter->dev); + if (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) + hdd_set_mon_ops(adapter->dev); + } else { hdd_set_station_ops(adapter->dev); + } hdd_dev_setup_destructor(dev); dev->ieee80211_ptr = &adapter->wdev; @@ -6970,7 +6999,8 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, hdd_destroy_adapter_sysfs_files(adapter); if (adapter->device_mode == QDF_STA_MODE && - ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) + ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) hdd_del_monitor_interface(hdd_ctx); if (adapter->vdev_id != WLAN_UMAC_VDEV_ID_MAX) @@ -7101,14 +7131,28 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, case QDF_MONITOR_MODE: if (wlan_hdd_is_session_type_monitor(QDF_MONITOR_MODE) && - adapter->vdev) { + adapter->vdev && + ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { ucfg_pkt_capture_deregister_callbacks(adapter->vdev); hdd_objmgr_put_vdev(adapter->vdev); adapter->vdev = NULL; } + if (wlan_hdd_is_session_type_monitor(QDF_MONITOR_MODE) && + ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) { + hdd_info("Release wakelock for STA + monitor mode!"); + qdf_runtime_pm_allow_suspend( + &hdd_ctx->runtime_context.monitor_mode); + qdf_wake_lock_release(&hdd_ctx->monitor_mode_wakelock, + WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE); + } wlan_hdd_scan_abort(adapter); hdd_deregister_hl_netdev_fc_timer(adapter); hdd_deregister_tx_flow_control(adapter); + status = hdd_disable_monitor_mode(); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err_rl("datapath reset failed for montior mode"); + hdd_set_idle_ps_config(hdd_ctx, true); status = hdd_monitor_mode_vdev_status(adapter); if (QDF_IS_STATUS_ERROR(status)) hdd_err_rl("stop failed montior mode"); @@ -8066,7 +8110,8 @@ int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, qdf_freq_t freq, enum phy_ch_width ch_width; int ret; - if (hdd_get_conparam() != QDF_GLOBAL_MONITOR_MODE) { + if ((hdd_get_conparam() != QDF_GLOBAL_MONITOR_MODE) && + (!policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))) { hdd_err("Not supported, device is not in monitor mode"); return -EINVAL; } @@ -8322,7 +8367,8 @@ QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx) case QDF_MONITOR_MODE: if (wlan_hdd_is_session_type_monitor( QDF_MONITOR_MODE) && - ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) { + ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { vdev = hdd_objmgr_get_vdev(adapter); if (vdev) { ucfg_pkt_capture_register_callbacks( @@ -18202,40 +18248,7 @@ void hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle, uint8_t vdev_id) } #ifdef WLAN_FEATURE_PKT_CAPTURE - -/** - * wlan_hdd_is_session_type_monitor() - check if session type is MONITOR - * @session_type: session type - * - * Return: True - if session type for adapter is monitor, else False - * - */ -bool wlan_hdd_is_session_type_monitor(uint8_t session_type) -{ - struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); - - if (!hdd_ctx) { - cds_err("HDD context is NULL"); - return false; - } - - if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) && - cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE && - session_type == QDF_MONITOR_MODE) - return true; - else - return false; -} - -/** - * wlan_hdd_check_mon_concurrency() - check if MONITOR and STA concurrency - * is UP when packet capture mode is enabled. - * @void - * - * Return: True - if STA and monitor concurrency is there, else False - * - */ -bool wlan_hdd_check_mon_concurrency(void) +bool wlan_hdd_is_mon_concurrency(void) { struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); @@ -18244,7 +18257,8 @@ bool wlan_hdd_check_mon_concurrency(void) return -EINVAL; } - if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) { + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { if (policy_mgr_get_concurrency_mode(hdd_ctx->psoc) == (QDF_STA_MASK | QDF_MONITOR_MASK)) { hdd_err("STA + MON mode is UP"); @@ -18254,16 +18268,6 @@ bool wlan_hdd_check_mon_concurrency(void) return false; } -/** - * wlan_hdd_del_monitor() - delete monitor interface - * @hdd_ctx: pointer to hdd context - * @adapter: adapter to be deleted - * @rtnl_held: rtnl lock held - * - * This function is invoked to delete monitor interface. - * - * Return: None - */ void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter, bool rtnl_held) { @@ -18280,17 +18284,46 @@ void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, hdd_open_p2p_interface(hdd_ctx); } -/** - * wlan_hdd_add_monitor_check() - check for monitor intf and add if needed - * @hdd_ctx: pointer to hdd context - * @adapter: output pointer to hold created monitor adapter - * @name: name of the interface - * @rtnl_held: True if RTNL lock is held - * @name_assign_type: the name of assign type of the netdev - * - * Return: 0 - on success - * err code - on failure - */ +void +wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx) +{ + struct hdd_adapter *adapter = NULL, *next_adapter = NULL; + struct osif_vdev_sync *vdev_sync; + + hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) { + if (adapter->device_mode == QDF_P2P_CLIENT_MODE || + adapter->device_mode == QDF_P2P_DEVICE_MODE || + adapter->device_mode == QDF_P2P_GO_MODE) { + vdev_sync = osif_vdev_sync_unregister(adapter->dev); + if (vdev_sync) + osif_vdev_sync_wait_for_ops(vdev_sync); + + hdd_clean_up_interface(hdd_ctx, adapter); + + if (vdev_sync) + osif_vdev_sync_destroy(vdev_sync); + } + } +} + +#endif /* WLAN_FEATURE_PKT_CAPTURE */ + +bool wlan_hdd_is_session_type_monitor(uint8_t session_type) +{ + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return false; + } + + if (cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE && + session_type == QDF_MONITOR_MODE) + return true; + else + return false; +} + int wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx, struct hdd_adapter **adapter, @@ -18299,86 +18332,50 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx, { struct hdd_adapter *sta_adapter; struct hdd_adapter *mon_adapter; - uint32_t mode; + int errno; uint8_t num_open_session = 0; + QDF_STATUS status; /* if no interface is up do not add monitor mode */ if (!hdd_is_any_interface_open(hdd_ctx)) return -EINVAL; - /* - * If add interface request is for monitor mode, then it can run in - * parallel with only one station interface. - * If there is no existing station interface return error - */ - if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions( - hdd_ctx->psoc, - QDF_MONITOR_MODE, - &num_open_session)) - return -EINVAL; - - if (num_open_session) { - hdd_err("monitor mode already exists, only one is possible"); - return -EBUSY; - } - - /* Ensure there is only one station interface */ - if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions( - hdd_ctx->psoc, - QDF_STA_MODE, - &num_open_session)) - return -EINVAL; - - if (num_open_session != 1) { - hdd_err("cannot add monitor mode, due to %u sta interfaces", - num_open_session); - return -EINVAL; - } - sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE); if (!sta_adapter) { hdd_err("No station adapter"); return -EINVAL; } - if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions( - hdd_ctx->psoc, - QDF_SAP_MODE, - &num_open_session)) + status = policy_mgr_check_mon_concurrency(hdd_ctx->psoc); + + if (QDF_IS_STATUS_ERROR(status)) return -EINVAL; - if (num_open_session) { - hdd_err("cannot add monitor mode, due to SAP concurrency"); + if (hdd_is_connection_in_progress(NULL, NULL)) { + hdd_err("cannot add monitor mode, Connection in progress"); return -EINVAL; } - /* delete p2p interface */ - for (mode = QDF_P2P_CLIENT_MODE; mode <= QDF_P2P_DEVICE_MODE; mode++) { - struct hdd_adapter *adapter; + num_open_session = policy_mgr_mode_specific_connection_count( + hdd_ctx->psoc, + PM_STA_MODE, + NULL); - if (mode == QDF_FTM_MODE || - mode == QDF_MONITOR_MODE) - continue; - - adapter = hdd_get_adapter(hdd_ctx, mode); - if (adapter) { - struct osif_vdev_sync *vdev_sync; - - vdev_sync = osif_vdev_sync_unregister(adapter->dev); - if (vdev_sync) - osif_vdev_sync_wait_for_ops(vdev_sync); - - wlan_hdd_release_intf_addr(hdd_ctx, - adapter->mac_addr.bytes); - hdd_stop_adapter(hdd_ctx, adapter); - hdd_deinit_adapter(hdd_ctx, adapter, true); - hdd_close_adapter(hdd_ctx, adapter, rtnl_held); - - if (vdev_sync) - osif_vdev_sync_destroy(vdev_sync); + if (num_open_session == 1) { + hdd_ctx->disconnect_for_sta_mon_conc = true; + /* Try disconnecting if already in connected state */ + errno = wlan_hdd_try_disconnect(sta_adapter, + REASON_UNSPEC_FAILURE); + if (errno > 0) { + hdd_err("Failed to disconnect the existing connection"); + return -EALREADY; } } + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) + wlan_hdd_del_p2p_interface(hdd_ctx); + mon_adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, name, wlan_hdd_get_intf_addr( hdd_ctx, @@ -18386,15 +18383,18 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx, name_assign_type, rtnl_held); if (!mon_adapter) { hdd_err("hdd_open_adapter failed"); - hdd_open_p2p_interface(hdd_ctx); + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) + hdd_open_p2p_interface(hdd_ctx); return -EINVAL; } + if (mon_adapter) + hdd_set_idle_ps_config(hdd_ctx, false); + *adapter = mon_adapter; return 0; } -#endif /* WLAN_FEATURE_PKT_CAPTURE */ - #ifdef FEATURE_MONITOR_MODE_SUPPORT diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index 34d52c3b6e9a..1689b10b507a 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -173,6 +173,9 @@ static int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, return -EINVAL; } + if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc)) + return -EINVAL; + if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) return -EINVAL; @@ -711,7 +714,10 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, if (ret) return ERR_PTR(ret); - if (wlan_hdd_check_mon_concurrency()) + if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc)) + return ERR_PTR(-EINVAL); + + if (wlan_hdd_is_mon_concurrency()) return ERR_PTR(-EINVAL); qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, @@ -727,6 +733,7 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, case QDF_P2P_GO_MODE: case QDF_P2P_CLIENT_MODE: case QDF_STA_MODE: + case QDF_MONITOR_MODE: break; default: mode = QDF_STA_MODE; @@ -750,16 +757,23 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, } adapter = NULL; - if ((ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) && - (type == NL80211_IFTYPE_MONITOR)) { - ret = wlan_hdd_add_monitor_check(hdd_ctx, &adapter, name, - true, name_assign_type); - if (ret) - return ERR_PTR(-EINVAL); + if (type == NL80211_IFTYPE_MONITOR) { + if (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) || + ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { + ret = wlan_hdd_add_monitor_check(hdd_ctx, + &adapter, name, true, + name_assign_type); + if (ret) + return ERR_PTR(-EINVAL); - if (adapter) { - hdd_exit(); - return adapter->dev->ieee80211_ptr; + if (adapter) { + hdd_exit(); + return adapter->dev->ieee80211_ptr; + } + } else { + hdd_err("Adding monitor interface not supported"); + return ERR_PTR(-EINVAL); } } @@ -883,8 +897,8 @@ struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, } #endif -static void hdd_clean_up_sap_interface(struct hdd_context *hdd_ctx, - struct hdd_adapter *adapter) +static void hdd_clean_up_interface(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter) { wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes); @@ -931,13 +945,15 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) if (adapter->device_mode == QDF_SAP_MODE && wlan_sap_is_pre_cac_active(hdd_ctx->mac_handle)) { - hdd_clean_up_sap_interface(hdd_ctx, adapter); + hdd_clean_up_interface(hdd_ctx, adapter); hdd_clean_up_pre_cac_interface(hdd_ctx); } else if (wlan_hdd_is_session_type_monitor( - adapter->device_mode)) { + adapter->device_mode) && + ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { wlan_hdd_del_monitor(hdd_ctx, adapter, TRUE); } else { - hdd_clean_up_sap_interface(hdd_ctx, adapter); + hdd_clean_up_interface(hdd_ctx, adapter); } if (!hdd_is_any_interface_open(hdd_ctx)) diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 952235cd13df..69282ae53839 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1487,7 +1487,8 @@ QDF_STATUS hdd_wlan_shutdown(void) dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC)); - if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) { + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE); if (adapter) { vdev = hdd_objmgr_get_vdev(adapter); @@ -1903,7 +1904,8 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) if (hdd_ctx->enable_dp_rx_threads) dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC)); - if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) { + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE); if (adapter) { vdev = hdd_objmgr_get_vdev(adapter); @@ -2147,7 +2149,8 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, goto resume_ol_rx; } - if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) { + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE); if (adapter) { vdev = hdd_objmgr_get_vdev(adapter); @@ -2182,7 +2185,8 @@ resume_dp_thread: dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC)); /* Resume packet capture MON thread */ - if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) { + if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) != + PACKET_CAPTURE_MODE_DISABLE) { adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE); if (adapter) { vdev = hdd_objmgr_get_vdev(adapter); diff --git a/core/hdd/src/wlan_hdd_rx_monitor.c b/core/hdd/src/wlan_hdd_rx_monitor.c index 082134e59cda..bc68f49d94fe 100644 --- a/core/hdd/src/wlan_hdd_rx_monitor.c +++ b/core/hdd/src/wlan_hdd_rx_monitor.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 The Linux Foundation. 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 @@ -25,15 +25,8 @@ #include #include "wlan_hdd_rx_monitor.h" #include "ol_txrx.h" +#include "cdp_txrx_mon.h" -/** - * hdd_rx_monitor_callback(): Callback function for receive monitor mode - * @vdev: Handle to vdev object - * @mpdu: pointer to mpdu to be delivered to os - * @rx_status: receive status - * - * Returns: None - */ void hdd_rx_monitor_callback(ol_osif_vdev_handle context, qdf_nbuf_t rxbuf, void *rx_status) @@ -95,29 +88,12 @@ void hdd_rx_monitor_callback(ol_osif_vdev_handle context, } } -/** - * hdd_monitor_set_rx_monitor_cb(): Set rx monitor mode callback function - * @txrx: pointer to txrx ops - * @rx_monitor_cb: pointer to callback function - * - * Returns: None - */ void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx, ol_txrx_rx_mon_fp rx_monitor_cb) { txrx->rx.mon = rx_monitor_cb; } -/** - * hdd_enable_monitor_mode() - Enable monitor mode - * @dev: Pointer to the net_device structure - * - * This function invokes cdp interface API to enable - * monitor mode configuration on the hardware. In this - * case sends HTT messages to FW to setup hardware rings - * - * Return: 0 for success; non-zero for failure - */ int hdd_enable_monitor_mode(struct net_device *dev) { void *soc = cds_get_context(QDF_MODULE_ID_SOC); @@ -131,3 +107,10 @@ int hdd_enable_monitor_mode(struct net_device *dev) return cdp_set_monitor_mode(soc, vdev_id, false); } + +int hdd_disable_monitor_mode(void) +{ + void *soc = cds_get_context(QDF_MODULE_ID_SOC); + + return cdp_reset_monitor_mode(soc, OL_TXRX_PDEV_ID, false); +} diff --git a/core/hdd/src/wlan_hdd_rx_monitor.h b/core/hdd/src/wlan_hdd_rx_monitor.h index 49a8cb07b8c2..bfe2b5b4219f 100644 --- a/core/hdd/src/wlan_hdd_rx_monitor.h +++ b/core/hdd/src/wlan_hdd_rx_monitor.h @@ -23,14 +23,49 @@ struct ol_txrx_ops; #if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \ defined(QCA_WIFI_QCA6490) || defined(QCA_WIFI_QCA6750) +/** + * hdd_rx_monitor_callback(): Callback function for receive monitor mode + * @vdev: Handle to vdev object + * @mpdu: pointer to mpdu to be delivered to os + * @rx_status: receive status + * + * Returns: None + */ void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx, ol_txrx_rx_mon_fp rx_monitor_cb); +/** + * hdd_monitor_set_rx_monitor_cb(): Set rx monitor mode callback function + * @txrx: pointer to txrx ops + * @rx_monitor_cb: pointer to callback function + * + * Returns: None + */ void hdd_rx_monitor_callback(ol_osif_vdev_handle vdev, qdf_nbuf_t mpdu, void *rx_status); - +/** + * hdd_enable_monitor_mode() - Enable monitor mode + * @dev: Pointer to the net_device structure + * + * This function invokes cdp interface API to enable + * monitor mode configuration on the hardware. In this + * case sends HTT messages to FW to setup hardware rings + * + * Return: 0 for success; non-zero for failure + */ int hdd_enable_monitor_mode(struct net_device *dev); + +/** + * hdd_disable_monitor_mode() - Disable monitor mode + * + * This function invokes cdp interface API to disable + * monitor mode configuration on the hardware. In this + * case sends HTT messages to FW to reset hardware rings + * + * Return: 0 for success; non-zero for failure + */ +int hdd_disable_monitor_mode(void); #else static inline void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx, ol_txrx_rx_mon_fp rx_monitor_cb){ } @@ -41,6 +76,12 @@ static inline int hdd_enable_monitor_mode(struct net_device *dev) { return 0; } + +static inline int hdd_disable_monitor_mode(void) +{ + return 0; +} + #endif /* CONFIG_LITHIUM */ #endif /* __WLAN_HDD_RX_MONITOR_H */ diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 8962062875cd..c7780922fdee 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1210,7 +1210,7 @@ static QDF_STATUS pe_handle_mgmt_frame(struct wlan_objmgr_psoc *psoc, int ret; /* skip offload packets */ - if (ucfg_pkt_capture_get_mode(psoc) && + if ((ucfg_pkt_capture_get_mode(psoc) != PACKET_CAPTURE_MODE_DISABLE) && mgmt_rx_params->status & WMI_RX_OFFLOAD_MON_MODE) { qdf_nbuf_free(buf); return QDF_STATUS_SUCCESS; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index aca521181c53..c9cc5e3b6c19 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -6842,7 +6842,8 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event, wma_update_num_peers_tids(wma_handle, wlan_res_cfg); } - if (ucfg_pkt_capture_get_mode(wma_handle->psoc) && + if ((ucfg_pkt_capture_get_mode(wma_handle->psoc) != + PACKET_CAPTURE_MODE_DISABLE) && wmi_service_enabled(wmi_handle, wmi_service_packet_capture_support)) wlan_res_cfg->pktcapture_support = true;