Commit 875e9439 authored by Maya Erez's avatar Maya Erez Committed by Kalle Valo

wil6210: prevent access to vring_tx_data lock during its init

wil_tx_vring locks the vring_tx_data lock before accessing the TX
vring to check if it is enabled and valid for use.
In case of quick disconnect / connect events for the same station,
spin_lock(&txdata->lock) can be called during the lock initialization
in the vring init function.
To prevent such a race, the TX vrings spin lock should be initialized
once during wil6210 driver initialization.
Signed-off-by: default avatarMaya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 1286558e
...@@ -438,6 +438,9 @@ int wil_priv_init(struct wil6210_priv *wil) ...@@ -438,6 +438,9 @@ int wil_priv_init(struct wil6210_priv *wil)
for (i = 0; i < WIL6210_MAX_CID; i++) for (i = 0; i < WIL6210_MAX_CID; i++)
spin_lock_init(&wil->sta[i].tid_rx_lock); spin_lock_init(&wil->sta[i].tid_rx_lock);
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++)
spin_lock_init(&wil->vring_tx_data[i].lock);
mutex_init(&wil->mutex); mutex_init(&wil->mutex);
mutex_init(&wil->wmi_mutex); mutex_init(&wil->wmi_mutex);
mutex_init(&wil->back_rx_mutex); mutex_init(&wil->back_rx_mutex);
......
...@@ -717,6 +717,21 @@ void wil_rx_fini(struct wil6210_priv *wil) ...@@ -717,6 +717,21 @@ void wil_rx_fini(struct wil6210_priv *wil)
wil_vring_free(wil, vring, 0); wil_vring_free(wil, vring, 0);
} }
static inline void wil_tx_data_init(struct vring_tx_data *txdata)
{
spin_lock_bh(&txdata->lock);
txdata->dot1x_open = 0;
txdata->enabled = 0;
txdata->idle = 0;
txdata->last_idle = 0;
txdata->begin = 0;
txdata->agg_wsize = 0;
txdata->agg_timeout = 0;
txdata->agg_amsdu = 0;
txdata->addba_in_progress = false;
spin_unlock_bh(&txdata->lock);
}
int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
int cid, int tid) int cid, int tid)
{ {
...@@ -758,8 +773,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, ...@@ -758,8 +773,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
goto out; goto out;
} }
memset(txdata, 0, sizeof(*txdata)); wil_tx_data_init(txdata);
spin_lock_init(&txdata->lock);
vring->size = size; vring->size = size;
rc = wil_vring_alloc(wil, vring); rc = wil_vring_alloc(wil, vring);
if (rc) if (rc)
...@@ -791,8 +805,10 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, ...@@ -791,8 +805,10 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
return 0; return 0;
out_free: out_free:
spin_lock_bh(&txdata->lock);
txdata->dot1x_open = false; txdata->dot1x_open = false;
txdata->enabled = 0; txdata->enabled = 0;
spin_unlock_bh(&txdata->lock);
wil_vring_free(wil, vring, 1); wil_vring_free(wil, vring, 1);
wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; wil->vring2cid_tid[id][0] = WIL6210_MAX_CID;
wil->vring2cid_tid[id][1] = 0; wil->vring2cid_tid[id][1] = 0;
...@@ -834,8 +850,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) ...@@ -834,8 +850,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
goto out; goto out;
} }
memset(txdata, 0, sizeof(*txdata)); wil_tx_data_init(txdata);
spin_lock_init(&txdata->lock);
vring->size = size; vring->size = size;
rc = wil_vring_alloc(wil, vring); rc = wil_vring_alloc(wil, vring);
if (rc) if (rc)
...@@ -865,8 +880,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) ...@@ -865,8 +880,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
return 0; return 0;
out_free: out_free:
spin_lock_bh(&txdata->lock);
txdata->enabled = 0; txdata->enabled = 0;
txdata->dot1x_open = false; txdata->dot1x_open = false;
spin_unlock_bh(&txdata->lock);
wil_vring_free(wil, vring, 1); wil_vring_free(wil, vring, 1);
out: out:
...@@ -894,7 +911,6 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) ...@@ -894,7 +911,6 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
napi_synchronize(&wil->napi_tx); napi_synchronize(&wil->napi_tx);
wil_vring_free(wil, vring, 1); wil_vring_free(wil, vring, 1);
memset(txdata, 0, sizeof(*txdata));
} }
static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment