qcacld-3.0: Handle concurrency scenarios in connected monitor mode

If the monitor_mode_concurrency ini is set to 1 and SAP/P2P/NAN is trying
to come up when STA + connected monitor is running, then because of
this ini setting, SAP/P2P/NAN bring up is terminated.

Fix this issue by allowing the SAP/P2P/NAN to come up by terminating the
monitor interface if connected monitor is running.

Change-Id: Ic37d97522c1a1e72a8a1614d6eab2c411ab46f3e
CRs-Fixed: 3610132
This commit is contained in:
Srinivas Girigowda
2023-09-15 16:06:17 -07:00
committed by Rahul Choudhary
parent 897bca02be
commit a04c94da27
4 changed files with 149 additions and 17 deletions

View File

@@ -1803,6 +1803,18 @@ static inline bool hdd_get_wlan_driver_status(void)
}
#endif
/**
* struct hdd_lpc_info - Local packet capture information
* @lpc_wk: local packet capture work
* @lpc_wk_scheduled: flag to indicate if lpc work is scheduled or not
* @mon_adapter: monitor adapter
*/
struct hdd_lpc_info {
qdf_work_t lpc_wk;
bool lpc_wk_scheduled;
struct hdd_adapter *mon_adapter;
};
/**
* enum wlan_state_ctrl_str_id - state control param string id
* @WLAN_OFF_STR: Turn OFF WiFi
@@ -2015,6 +2027,7 @@ enum wlan_state_ctrl_str_id {
* @is_mlo_per_link_stats_supported: Per link mlo stats is supported or not
* @num_mlo_peers: Total number of MLO peers
* @more_peer_data: more mlo peer data in peer stats
* @lpc_info: Local packet capture info
*/
struct hdd_context {
struct wlan_objmgr_psoc *psoc;
@@ -2296,6 +2309,9 @@ struct hdd_context {
uint8_t num_mlo_peers;
uint32_t more_peer_data;
#endif
#ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
struct hdd_lpc_info lpc_info;
#endif
};
/**
@@ -5450,4 +5466,42 @@ static inline void hdd_set_sar_init_index(struct hdd_context *hdd_ctx)
{}
#endif
#ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
/**
* wlan_hdd_lpc_handle_concurrency() - Handle local packet capture
* concurrency scenario
* @hdd_ctx: hdd_ctx
* @is_virtual_iface: is virtual interface
*
* This function takes care of handling concurrency scenario
* If STA+Mon present and SAP is coming up, terminate Mon and let SAP come up
* If STA+Mon present and P2P is coming up, terminate Mon and let P2P come up
* If STA+Mon present and NAN is coming up, terminate Mon and let NAN come up
*
* Return: none
*/
void wlan_hdd_lpc_handle_concurrency(struct hdd_context *hdd_ctx,
bool is_virtual_iface);
/**
* hdd_lpc_is_work_scheduled() - function to return if lpc wq scheduled
* @hdd_ctx: hdd_ctx
*
* Return: true if scheduled; false otherwise
*/
bool hdd_lpc_is_work_scheduled(struct hdd_context *hdd_ctx);
#else
static inline void
wlan_hdd_lpc_handle_concurrency(struct hdd_context *hdd_ctx,
bool is_virtual_iface)
{}
static inline bool
hdd_lpc_is_work_scheduled(struct hdd_context *hdd_ctx)
{
return false;
}
#endif
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */

View File

@@ -22285,7 +22285,10 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
if (wlan_hdd_is_mon_concurrency())
return -EINVAL;
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
wlan_hdd_lpc_handle_concurrency(hdd_ctx, false);
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) &&
!hdd_lpc_is_work_scheduled(hdd_ctx))
return -EINVAL;
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,

View File

@@ -541,16 +541,17 @@ void hdd_start_complete(int ret)
/**
* wlan_hdd_lpc_del_monitor_interface() - Delete monitor interface
* @hdd_ctx: hdd_ctx
* @is_virtual_iface: Is virtual interface
*
* This function takes care of deleting monitor interface
*
* Return: none
*/
static void
wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx)
wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx,
bool is_virtual_iface)
{
struct hdd_adapter *adapter;
struct osif_vdev_sync *vdev_sync;
void *soc;
bool running;
@@ -575,21 +576,90 @@ wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx)
}
hdd_debug("lpc: Delete monitor interface");
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);
qdf_zero_macaddr(&adapter->mac_addr);
hdd_stop_adapter(hdd_ctx, adapter);
hdd_deinit_adapter(hdd_ctx, adapter, true);
hdd_close_adapter(hdd_ctx, adapter, true);
adapter->is_virtual_iface = is_virtual_iface;
hdd_ctx->lpc_info.mon_adapter = adapter;
if (vdev_sync)
osif_vdev_sync_destroy(vdev_sync);
hdd_ctx->lpc_info.lpc_wk_scheduled = true;
qdf_sched_work(0, &hdd_ctx->lpc_info.lpc_wk);
}
void wlan_hdd_lpc_handle_concurrency(struct hdd_context *hdd_ctx,
bool is_virtual_iface)
{
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
wlan_hdd_lpc_del_monitor_interface(hdd_ctx, is_virtual_iface);
}
bool hdd_lpc_is_work_scheduled(struct hdd_context *hdd_ctx)
{
return hdd_ctx->lpc_info.lpc_wk_scheduled;
}
static void hdd_lpc_work_handler(void *arg)
{
struct hdd_context *hdd_ctx = (struct hdd_context *)arg;
struct hdd_adapter *adapter;
struct osif_vdev_sync *vdev_sync;
int errno;
if (!hdd_ctx)
return;
adapter = hdd_ctx->lpc_info.mon_adapter;
if (!adapter) {
hdd_err("There is no monitor adapter");
return;
}
errno = osif_vdev_sync_trans_start_wait(adapter->dev, &vdev_sync);
if (errno)
return;
osif_vdev_sync_unregister(adapter->dev);
osif_vdev_sync_wait_for_ops(vdev_sync);
hdd_close_adapter(hdd_ctx, adapter, true);
hdd_ctx->lpc_info.lpc_wk_scheduled = false;
osif_vdev_sync_trans_stop(vdev_sync);
osif_vdev_sync_destroy(vdev_sync);
}
static inline
void hdd_lp_create_work(struct hdd_context *hdd_ctx)
{
hdd_ctx->lpc_info.lpc_wk_scheduled = false;
qdf_create_work(0, &hdd_ctx->lpc_info.lpc_wk, hdd_lpc_work_handler,
hdd_ctx);
}
static inline
void hdd_lpc_delete_work(struct hdd_context *hdd_ctx)
{
qdf_flush_work(&hdd_ctx->lpc_info.lpc_wk);
hdd_ctx->lpc_info.lpc_wk_scheduled = false;
qdf_destroy_work(NULL, &hdd_ctx->lpc_info.lpc_wk);
}
#else
static inline
void wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx)
void hdd_lp_create_work(struct hdd_context *hdd_ctx)
{
}
static inline
void hdd_lpc_delete_work(struct hdd_context *hdd_ctx)
{
}
static inline
void wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx,
bool is_virtual_iface)
{
}
#endif
@@ -8789,7 +8859,6 @@ static void __hdd_close_adapter(struct hdd_context *hdd_ctx,
struct qdf_mac_addr adapter_mac;
struct wlan_hdd_link_info *link_info;
qdf_copy_macaddr(&adapter_mac, &adapter->mac_addr);
if (adapter->device_mode == QDF_STA_MODE) {
hdd_adapter_for_each_link_info(adapter, link_info)
@@ -10943,6 +11012,8 @@ static inline void hdd_pm_notifier_deinit(struct hdd_context *hdd_ctx)
*/
static int hdd_context_deinit(struct hdd_context *hdd_ctx)
{
hdd_lpc_delete_work(hdd_ctx);
qdf_wake_lock_destroy(&hdd_ctx->monitor_mode_wakelock);
wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
@@ -13611,6 +13682,7 @@ static int hdd_context_init(struct hdd_context *hdd_ctx)
qdf_wake_lock_create(&hdd_ctx->monitor_mode_wakelock,
"monitor_mode_wakelock");
hdd_lp_create_work(hdd_ctx);
return 0;
@@ -14560,7 +14632,7 @@ int hdd_start_station_adapter(struct hdd_adapter *adapter)
if ((adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
(adapter->device_mode == QDF_NAN_DISC_MODE))
wlan_hdd_lpc_del_monitor_interface(adapter->hdd_ctx);
wlan_hdd_lpc_del_monitor_interface(adapter->hdd_ctx, false);
status = hdd_adapter_fill_link_address(adapter);
if (QDF_IS_STATUS_ERROR(status)) {
@@ -14636,8 +14708,6 @@ int hdd_start_ap_adapter(struct hdd_adapter *adapter, bool rtnl_held)
return qdf_status_to_os_return(QDF_STATUS_SUCCESS);
}
wlan_hdd_lpc_del_monitor_interface(hdd_ctx);
status = hdd_adapter_fill_link_address(adapter);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_debug("Link address derive failed");
@@ -18329,7 +18399,7 @@ static void __hdd_inform_wifi_off(void)
ucfg_dlm_wifi_off(hdd_ctx->pdev);
if (rtnl_trylock()) {
wlan_hdd_lpc_del_monitor_interface(hdd_ctx);
wlan_hdd_lpc_del_monitor_interface(hdd_ctx, false);
rtnl_unlock();
}
}

View File

@@ -111,7 +111,9 @@ static int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
return -EINVAL;
}
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
wlan_hdd_lpc_handle_concurrency(hdd_ctx, false);
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) &&
!hdd_lpc_is_work_scheduled(hdd_ctx))
return -EINVAL;
if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
@@ -679,7 +681,10 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
if (ret)
return ERR_PTR(ret);
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
wlan_hdd_lpc_handle_concurrency(hdd_ctx, true);
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) &&
!hdd_lpc_is_work_scheduled(hdd_ctx))
return ERR_PTR(-EINVAL);
if (wlan_hdd_is_mon_concurrency())