Commit 5933a06d authored by Vladimir Kondratiev's avatar Vladimir Kondratiev Committed by Kalle Valo

wil6210: fix race between xmit and Tx vring de-allocation

Use spinlock, this should not impact Tx as lock is always free
except for de-allocation.
Signed-off-by: default avatarVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent e59d16c0
...@@ -671,6 +671,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, ...@@ -671,6 +671,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
} }
memset(txdata, 0, sizeof(*txdata)); memset(txdata, 0, sizeof(*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)
...@@ -718,8 +719,10 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) ...@@ -718,8 +719,10 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
wil_dbg_misc(wil, "%s() id=%d\n", __func__, id); wil_dbg_misc(wil, "%s() id=%d\n", __func__, id);
spin_lock_bh(&txdata->lock);
txdata->enabled = 0; /* no Tx can be in progress or start anew */
spin_unlock_bh(&txdata->lock);
/* make sure NAPI won't touch this vring */ /* make sure NAPI won't touch this vring */
wil->vring_tx_data[id].enabled = 0;
if (test_bit(wil_status_napi_en, wil->status)) if (test_bit(wil_status_napi_en, wil->status))
napi_synchronize(&wil->napi_tx); napi_synchronize(&wil->napi_tx);
...@@ -935,8 +938,8 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil, ...@@ -935,8 +938,8 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil,
return 0; return 0;
} }
static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct device *dev = wil_to_dev(wil); struct device *dev = wil_to_dev(wil);
struct vring_tx_desc dd, *d = &dd; struct vring_tx_desc dd, *d = &dd;
...@@ -952,6 +955,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, ...@@ -952,6 +955,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
wil_dbg_txrx(wil, "%s()\n", __func__); wil_dbg_txrx(wil, "%s()\n", __func__);
if (unlikely(!txdata->enabled))
return -EINVAL;
if (avail < 1 + nr_frags) { if (avail < 1 + nr_frags) {
wil_err_ratelimited(wil, wil_err_ratelimited(wil,
"Tx ring full. No space for %d fragments\n", "Tx ring full. No space for %d fragments\n",
...@@ -1050,6 +1056,19 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, ...@@ -1050,6 +1056,19 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
return -EINVAL; return -EINVAL;
} }
static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
struct sk_buff *skb)
{
int vring_index = vring - wil->vring_tx;
struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
int rc;
spin_lock(&txdata->lock);
rc = __wil_tx_vring(wil, vring, skb);
spin_unlock(&txdata->lock);
return rc;
}
netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ {
struct wil6210_priv *wil = ndev_to_wil(ndev); struct wil6210_priv *wil = ndev_to_wil(ndev);
......
...@@ -385,6 +385,7 @@ struct vring_tx_data { ...@@ -385,6 +385,7 @@ struct vring_tx_data {
u16 agg_timeout; u16 agg_timeout;
u8 agg_amsdu; u8 agg_amsdu;
bool addba_in_progress; /* if set, agg_xxx is for request in progress */ bool addba_in_progress; /* if set, agg_xxx is for request in progress */
spinlock_t lock;
}; };
enum { /* for wil6210_priv.status */ enum { /* for wil6210_priv.status */
......
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