Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wifi: wfx: scan_lock is global to the device

Currently, one scan_lock is associated to each vif. However, concurrent
scan on vifs is explicitly prohibited by the device. Currently,
scan_lock is associated with a vif but it is always locked with
conf_mutex (there is a case where conf_mutex is not associated to
scan_lock but scan_lock is tested on all interfaces). So concurrent scan
on vifs cannot happen.

So, this patch relocate scan_lock to the device and simplify the code.

Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20231004172843.195332-7-jerome.pouiller@silabs.com

authored by

Jérôme Pouiller and committed by
Kalle Valo
04106ec5 f091bcb6

+8 -12
+2
drivers/net/wireless/silabs/wfx/main.c
··· 246 246 247 247 mutex_destroy(&wdev->tx_power_loop_info_lock); 248 248 mutex_destroy(&wdev->rx_stats_lock); 249 + mutex_destroy(&wdev->scan_lock); 249 250 mutex_destroy(&wdev->conf_mutex); 250 251 ieee80211_free_hw(wdev->hw); 251 252 } ··· 315 314 gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup"); 316 315 317 316 mutex_init(&wdev->conf_mutex); 317 + mutex_init(&wdev->scan_lock); 318 318 mutex_init(&wdev->rx_stats_lock); 319 319 mutex_init(&wdev->tx_power_loop_info_lock); 320 320 init_completion(&wdev->firmware_ready);
+2 -2
drivers/net/wireless/silabs/wfx/scan.c
··· 95 95 int chan_cur, ret, err; 96 96 97 97 mutex_lock(&wvif->wdev->conf_mutex); 98 - mutex_lock(&wvif->scan_lock); 98 + mutex_lock(&wvif->wdev->scan_lock); 99 99 if (wvif->join_in_progress) { 100 100 dev_info(wvif->wdev->dev, "abort in-progress REQ_JOIN"); 101 101 wfx_reset(wvif); ··· 116 116 ret = -ETIMEDOUT; 117 117 } 118 118 } while (ret >= 0 && chan_cur < hw_req->req.n_channels); 119 - mutex_unlock(&wvif->scan_lock); 119 + mutex_unlock(&wvif->wdev->scan_lock); 120 120 mutex_unlock(&wvif->wdev->conf_mutex); 121 121 wfx_ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0); 122 122 }
+3 -8
drivers/net/wireless/silabs/wfx/sta.c
··· 97 97 FIF_PROBE_REQ | FIF_PSPOLL; 98 98 99 99 /* Filters are ignored during the scan. No frames are filtered. */ 100 - if (mutex_is_locked(&wvif->scan_lock)) 100 + if (mutex_is_locked(&wdev->scan_lock)) 101 101 return; 102 102 103 103 mutex_lock(&wdev->conf_mutex); ··· 621 621 622 622 void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd) 623 623 { 624 - struct wfx_vif *wvif_it; 625 - 626 624 if (notify_cmd != STA_NOTIFY_AWAKE) 627 625 return; 628 626 629 627 /* Device won't be able to honor CAB if a scan is in progress on any interface. Prefer to 630 628 * skip this DTIM and wait for the next one. 631 629 */ 632 - wvif_it = NULL; 633 - while ((wvif_it = wvif_iterate(wvif->wdev, wvif_it)) != NULL) 634 - if (mutex_is_locked(&wvif_it->scan_lock)) 635 - return; 630 + if (mutex_is_locked(&wvif->wdev->scan_lock)) 631 + return; 636 632 637 633 if (!wfx_tx_queues_has_cab(wvif) || wvif->after_dtim_tx_allowed) 638 634 dev_warn(wvif->wdev->dev, "incorrect sequence (%d CAB in queue)", ··· 726 730 complete(&wvif->set_pm_mode_complete); 727 731 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); 728 732 729 - mutex_init(&wvif->scan_lock); 730 733 init_completion(&wvif->scan_complete); 731 734 INIT_WORK(&wvif->scan_work, wfx_hw_scan_work); 732 735
+1 -2
drivers/net/wireless/silabs/wfx/wfx.h
··· 43 43 struct delayed_work cooling_timeout_work; 44 44 bool poll_irq; 45 45 bool chip_frozen; 46 + struct mutex scan_lock; 46 47 struct mutex conf_mutex; 47 48 48 49 struct wfx_hif_cmd hif_cmd; ··· 81 80 82 81 unsigned long uapsd_mask; 83 82 84 - /* avoid some operations in parallel with scan */ 85 - struct mutex scan_lock; 86 83 struct work_struct scan_work; 87 84 struct completion scan_complete; 88 85 int scan_nb_chan_done;