wil6210: protect wil_vring_fini_tx in parallel to tx completions
napi_synchronize is called before releasing the vring, with the assumption that setting txdata->enabled to 0 will prevent handling of this vring in the next scheduled napi. To guarantee this assumption, a memory barrier is added after disabling the txdata. In addition, as the ctx is zeroed in wil_tx_complete after this descriptor is handled (protected by wmb), ctx needs to be checked before releasing this descriptor in wil_vring_free. Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
ab6d7cc3ea
commit
34b8886e50
@ -184,6 +184,13 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
|
||||
&vring->va[vring->swtail].tx;
|
||||
|
||||
ctx = &vring->ctx[vring->swtail];
|
||||
if (!ctx) {
|
||||
wil_dbg_txrx(wil,
|
||||
"ctx(%d) was already completed\n",
|
||||
vring->swtail);
|
||||
vring->swtail = wil_vring_next_tail(vring);
|
||||
continue;
|
||||
}
|
||||
*d = *_d;
|
||||
wil_txdesc_unmap(dev, d, ctx);
|
||||
if (ctx->skb)
|
||||
@ -975,6 +982,13 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
|
||||
txdata->dot1x_open = false;
|
||||
txdata->enabled = 0; /* no Tx can be in progress or start anew */
|
||||
spin_unlock_bh(&txdata->lock);
|
||||
/* napi_synchronize waits for completion of the current NAPI but will
|
||||
* not prevent the next NAPI run.
|
||||
* Add a memory barrier to guarantee that txdata->enabled is zeroed
|
||||
* before napi_synchronize so that the next scheduled NAPI will not
|
||||
* handle this vring
|
||||
*/
|
||||
wmb();
|
||||
/* make sure NAPI won't touch this vring */
|
||||
if (test_bit(wil_status_napi_en, wil->status))
|
||||
napi_synchronize(&wil->napi_tx);
|
||||
|
Loading…
Reference in New Issue
Block a user