Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -671,6 +671,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
	}

	memset(txdata, 0, sizeof(*txdata));
	spin_lock_init(&txdata->lock);
	vring->size = size;
	rc = wil_vring_alloc(wil, vring);
	if (rc)
@@ -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);

	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 */
	wil->vring_tx_data[id].enabled = 0;
	if (test_bit(wil_status_napi_en, wil->status))
		napi_synchronize(&wil->napi_tx);

@@ -935,7 +938,7 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil,
	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 device *dev = wil_to_dev(wil);
@@ -952,6 +955,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,

	wil_dbg_txrx(wil, "%s()\n", __func__);

	if (unlikely(!txdata->enabled))
		return -EINVAL;

	if (avail < 1 + nr_frags) {
		wil_err_ratelimited(wil,
				    "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,
	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)
{
	struct wil6210_priv *wil = ndev_to_wil(ndev);
+1 −0
Original line number Diff line number Diff line
@@ -385,6 +385,7 @@ struct vring_tx_data {
	u16 agg_timeout;
	u8 agg_amsdu;
	bool addba_in_progress; /* if set, agg_xxx is for request in progress */
	spinlock_t lock;
};

enum { /* for wil6210_priv.status */