aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>2015-02-01 03:55:13 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-02-03 08:36:34 -0500
commit5933a06dc96cad21b7c125995791c93a86be7915 (patch)
treecee8a4f99f6329f43595c9d03df5120d9b40daf8 /drivers/net/wireless
parente59d16c08b3aa147f5c3c664d5dfda77fa93a827 (diff)
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: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c25
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h1
2 files changed, 23 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index e37cab1c5a53..85ecea2e6a67 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -671,6 +671,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
671 } 671 }
672 672
673 memset(txdata, 0, sizeof(*txdata)); 673 memset(txdata, 0, sizeof(*txdata));
674 spin_lock_init(&txdata->lock);
674 vring->size = size; 675 vring->size = size;
675 rc = wil_vring_alloc(wil, vring); 676 rc = wil_vring_alloc(wil, vring);
676 if (rc) 677 if (rc)
@@ -718,8 +719,10 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
718 719
719 wil_dbg_misc(wil, "%s() id=%d\n", __func__, id); 720 wil_dbg_misc(wil, "%s() id=%d\n", __func__, id);
720 721
722 spin_lock_bh(&txdata->lock);
723 txdata->enabled = 0; /* no Tx can be in progress or start anew */
724 spin_unlock_bh(&txdata->lock);
721 /* make sure NAPI won't touch this vring */ 725 /* make sure NAPI won't touch this vring */
722 wil->vring_tx_data[id].enabled = 0;
723 if (test_bit(wil_status_napi_en, wil->status)) 726 if (test_bit(wil_status_napi_en, wil->status))
724 napi_synchronize(&wil->napi_tx); 727 napi_synchronize(&wil->napi_tx);
725 728
@@ -935,8 +938,8 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil,
935 return 0; 938 return 0;
936} 939}
937 940
938static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, 941static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
939 struct sk_buff *skb) 942 struct sk_buff *skb)
940{ 943{
941 struct device *dev = wil_to_dev(wil); 944 struct device *dev = wil_to_dev(wil);
942 struct vring_tx_desc dd, *d = &dd; 945 struct vring_tx_desc dd, *d = &dd;
@@ -952,6 +955,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
952 955
953 wil_dbg_txrx(wil, "%s()\n", __func__); 956 wil_dbg_txrx(wil, "%s()\n", __func__);
954 957
958 if (unlikely(!txdata->enabled))
959 return -EINVAL;
960
955 if (avail < 1 + nr_frags) { 961 if (avail < 1 + nr_frags) {
956 wil_err_ratelimited(wil, 962 wil_err_ratelimited(wil,
957 "Tx ring full. No space for %d fragments\n", 963 "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 return -EINVAL; 1056 return -EINVAL;
1051} 1057}
1052 1058
1059static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
1060 struct sk_buff *skb)
1061{
1062 int vring_index = vring - wil->vring_tx;
1063 struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
1064 int rc;
1065
1066 spin_lock(&txdata->lock);
1067 rc = __wil_tx_vring(wil, vring, skb);
1068 spin_unlock(&txdata->lock);
1069 return rc;
1070}
1071
1053netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) 1072netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
1054{ 1073{
1055 struct wil6210_priv *wil = ndev_to_wil(ndev); 1074 struct wil6210_priv *wil = ndev_to_wil(ndev);
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 90dc24fb60f8..94611568fc9a 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -385,6 +385,7 @@ struct vring_tx_data {
385 u16 agg_timeout; 385 u16 agg_timeout;
386 u8 agg_amsdu; 386 u8 agg_amsdu;
387 bool addba_in_progress; /* if set, agg_xxx is for request in progress */ 387 bool addba_in_progress; /* if set, agg_xxx is for request in progress */
388 spinlock_t lock;
388}; 389};
389 390
390enum { /* for wil6210_priv.status */ 391enum { /* for wil6210_priv.status */