qcacmn: Access scan_req_q under lock
Currently, list empty checks for scan_req_q is done outside the lock. This is causing synchronization issue during scan and SSR/vdev delete in parallel. To avoid this, check for scan_req_q empty inside the lock. This change also updates the return type of wlan_schedule_scan_start_request to QDF_STATUS, which is expected by caller API. Change-Id: I8b6febdd98af7856fb047b1c9d852e4944a137b5 CRs-Fixed: 2763173
This commit is contained in:
@@ -658,9 +658,9 @@ wlan_copy_bssid_scan_request(struct scan_start_request *scan_req,
|
|||||||
* Schedule scan start request and enqueue scan request in the global scan
|
* Schedule scan start request and enqueue scan request in the global scan
|
||||||
* list. This list stores the active scan request information.
|
* list. This list stores the active scan request information.
|
||||||
*
|
*
|
||||||
* Return: 0 on success, error number otherwise
|
* Return: QDF_STATUS
|
||||||
*/
|
*/
|
||||||
static int
|
static QDF_STATUS
|
||||||
wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev,
|
wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev,
|
||||||
struct cfg80211_scan_request *req,
|
struct cfg80211_scan_request *req,
|
||||||
uint8_t source,
|
uint8_t source,
|
||||||
@@ -674,7 +674,7 @@ wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev,
|
|||||||
scan_req = qdf_mem_malloc(sizeof(*scan_req));
|
scan_req = qdf_mem_malloc(sizeof(*scan_req));
|
||||||
if (!scan_req) {
|
if (!scan_req) {
|
||||||
ucfg_scm_scan_free_scan_request_mem(scan_start_req);
|
ucfg_scm_scan_free_scan_request_mem(scan_start_req);
|
||||||
return -ENOMEM;
|
return QDF_STATUS_E_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get NL global context from objmgr*/
|
/* Get NL global context from objmgr*/
|
||||||
@@ -707,10 +707,9 @@ wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev,
|
|||||||
osif_rl_debug("Failed to enqueue Scan Req as max scan %d already queued",
|
osif_rl_debug("Failed to enqueue Scan Req as max scan %d already queued",
|
||||||
qdf_list_size(&osif_scan->scan_req_q));
|
qdf_list_size(&osif_scan->scan_req_q));
|
||||||
qdf_mem_free(scan_req);
|
qdf_mem_free(scan_req);
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -748,12 +747,13 @@ static QDF_STATUS wlan_scan_request_dequeue(
|
|||||||
}
|
}
|
||||||
scan_priv = osif_ctx->osif_scan;
|
scan_priv = osif_ctx->osif_scan;
|
||||||
|
|
||||||
|
qdf_mutex_acquire(&scan_priv->scan_req_q_lock);
|
||||||
if (qdf_list_empty(&scan_priv->scan_req_q)) {
|
if (qdf_list_empty(&scan_priv->scan_req_q)) {
|
||||||
osif_info("Scan List is empty");
|
osif_info("Scan List is empty");
|
||||||
|
qdf_mutex_release(&scan_priv->scan_req_q_lock);
|
||||||
return QDF_STATUS_E_FAILURE;
|
return QDF_STATUS_E_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
qdf_mutex_acquire(&scan_priv->scan_req_q_lock);
|
|
||||||
if (QDF_STATUS_SUCCESS !=
|
if (QDF_STATUS_SUCCESS !=
|
||||||
qdf_list_peek_front(&scan_priv->scan_req_q, &next_node)) {
|
qdf_list_peek_front(&scan_priv->scan_req_q, &next_node)) {
|
||||||
qdf_mutex_release(&scan_priv->scan_req_q_lock);
|
qdf_mutex_release(&scan_priv->scan_req_q_lock);
|
||||||
@@ -1085,9 +1085,11 @@ static void wlan_cfg80211_scan_done_callback(
|
|||||||
event->reason, unique_bss_count);
|
event->reason, unique_bss_count);
|
||||||
allow_suspend:
|
allow_suspend:
|
||||||
osif_priv = wlan_pdev_get_ospriv(pdev);
|
osif_priv = wlan_pdev_get_ospriv(pdev);
|
||||||
|
qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) {
|
if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) {
|
||||||
struct wlan_objmgr_psoc *psoc;
|
struct wlan_objmgr_psoc *psoc;
|
||||||
|
|
||||||
|
qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
qdf_runtime_pm_allow_suspend(
|
qdf_runtime_pm_allow_suspend(
|
||||||
&osif_priv->osif_scan->runtime_pm_lock);
|
&osif_priv->osif_scan->runtime_pm_lock);
|
||||||
|
|
||||||
@@ -1104,6 +1106,8 @@ allow_suspend:
|
|||||||
wlan_scan_acquire_wake_lock_timeout(psoc,
|
wlan_scan_acquire_wake_lock_timeout(psoc,
|
||||||
&osif_priv->osif_scan->scan_wake_lock,
|
&osif_priv->osif_scan->scan_wake_lock,
|
||||||
SCAN_WAKE_LOCK_CONNECT_DURATION);
|
SCAN_WAKE_LOCK_CONNECT_DURATION);
|
||||||
|
} else {
|
||||||
|
qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1381,12 +1385,15 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev,
|
|||||||
* is not empty, and the simultaneous scan is disabled, dont allow 2nd
|
* is not empty, and the simultaneous scan is disabled, dont allow 2nd
|
||||||
* scan.
|
* scan.
|
||||||
*/
|
*/
|
||||||
|
qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
if (!wlan_cfg80211_allow_simultaneous_scan(psoc) &&
|
if (!wlan_cfg80211_allow_simultaneous_scan(psoc) &&
|
||||||
!qdf_list_empty(&osif_priv->osif_scan->scan_req_q) &&
|
!qdf_list_empty(&osif_priv->osif_scan->scan_req_q) &&
|
||||||
opmode != QDF_SAP_MODE) {
|
opmode != QDF_SAP_MODE) {
|
||||||
|
qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
osif_err("Simultaneous scan disabled, reject scan");
|
osif_err("Simultaneous scan disabled, reject scan");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
|
|
||||||
req = qdf_mem_malloc(sizeof(*req));
|
req = qdf_mem_malloc(sizeof(*req));
|
||||||
if (!req)
|
if (!req)
|
||||||
@@ -1619,12 +1626,18 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev,
|
|||||||
qdf_status = wlan_schedule_scan_start_request(pdev, request,
|
qdf_status = wlan_schedule_scan_start_request(pdev, request,
|
||||||
params->source, req);
|
params->source, req);
|
||||||
if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
||||||
|
qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) {
|
if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) {
|
||||||
|
qdf_mutex_release(
|
||||||
|
&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
qdf_runtime_pm_allow_suspend(
|
qdf_runtime_pm_allow_suspend(
|
||||||
&osif_priv->osif_scan->runtime_pm_lock);
|
&osif_priv->osif_scan->runtime_pm_lock);
|
||||||
wlan_scan_release_wake_lock(
|
wlan_scan_release_wake_lock(
|
||||||
psoc,
|
psoc,
|
||||||
&osif_priv->osif_scan->scan_wake_lock);
|
&osif_priv->osif_scan->scan_wake_lock);
|
||||||
|
} else {
|
||||||
|
qdf_mutex_release(
|
||||||
|
&osif_priv->osif_scan->scan_req_q_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user