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:
Bapiraju Alla
2020-08-26 19:23:05 +05:30
committed by snandini
parent 09a17690e8
commit cc025bf48c

View File

@@ -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);
} }
} }