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:

committed by
Rahul Choudhary

parent
897bca02be
commit
a04c94da27
@@ -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) */
|
||||
|
@@ -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,
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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())
|
||||
|
Reference in New Issue
Block a user