aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2008-08-18 15:45:27 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-26 20:06:31 -0400
commit004829730cb1b03abe7555e1c1faadec62cbcf6f (patch)
tree414985c79061809ddfdd72ba138a5402b3cbe978 /drivers
parentd0c2912fe8df81a8b723fb6ec4d4cdf523cbaff7 (diff)
Ath5k: lock beacons
Beacons setup and config was racy with beacon send. Ensure that ISR and reset functions see consistent state of bbuf. Use also dev_kfree_skb_any in ath5k_txbuf_free since we call it from atomic now. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Cc: Nick Kossifidis <mickflemm@gmail.com> Cc: Luis R. Rodriguez <mcgrof@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath5k/base.c15
-rw-r--r--drivers/net/wireless/ath5k/base.h1
2 files changed, 13 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index b20a45aa8680..7bc012fca059 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -251,7 +251,7 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
251 return; 251 return;
252 pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, 252 pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len,
253 PCI_DMA_TODEVICE); 253 PCI_DMA_TODEVICE);
254 dev_kfree_skb(bf->skb); 254 dev_kfree_skb_any(bf->skb);
255 bf->skb = NULL; 255 bf->skb = NULL;
256} 256}
257 257
@@ -466,6 +466,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
466 mutex_init(&sc->lock); 466 mutex_init(&sc->lock);
467 spin_lock_init(&sc->rxbuflock); 467 spin_lock_init(&sc->rxbuflock);
468 spin_lock_init(&sc->txbuflock); 468 spin_lock_init(&sc->txbuflock);
469 spin_lock_init(&sc->block);
469 470
470 /* Set private data */ 471 /* Set private data */
471 pci_set_drvdata(pdev, hw); 472 pci_set_drvdata(pdev, hw);
@@ -2179,8 +2180,11 @@ ath5k_beacon_config(struct ath5k_softc *sc)
2179 2180
2180 sc->imask |= AR5K_INT_SWBA; 2181 sc->imask |= AR5K_INT_SWBA;
2181 2182
2182 if (ath5k_hw_hasveol(ah)) 2183 if (ath5k_hw_hasveol(ah)) {
2184 spin_lock(&sc->block);
2183 ath5k_beacon_send(sc); 2185 ath5k_beacon_send(sc);
2186 spin_unlock(&sc->block);
2187 }
2184 } 2188 }
2185 /* TODO else AP */ 2189 /* TODO else AP */
2186 2190
@@ -2403,7 +2407,9 @@ ath5k_intr(int irq, void *dev_id)
2403 TSF_TO_TU(tsf), 2407 TSF_TO_TU(tsf),
2404 (unsigned long long) tsf); 2408 (unsigned long long) tsf);
2405 } else { 2409 } else {
2410 spin_lock(&sc->block);
2406 ath5k_beacon_send(sc); 2411 ath5k_beacon_send(sc);
2412 spin_unlock(&sc->block);
2407 } 2413 }
2408 } 2414 }
2409 if (status & AR5K_INT_RXEOL) { 2415 if (status & AR5K_INT_RXEOL) {
@@ -3050,6 +3056,7 @@ static int
3050ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) 3056ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
3051{ 3057{
3052 struct ath5k_softc *sc = hw->priv; 3058 struct ath5k_softc *sc = hw->priv;
3059 unsigned long flags;
3053 int ret; 3060 int ret;
3054 3061
3055 ath5k_debug_dump_skb(sc, skb, "BC ", 1); 3062 ath5k_debug_dump_skb(sc, skb, "BC ", 1);
@@ -3059,12 +3066,14 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
3059 goto end; 3066 goto end;
3060 } 3067 }
3061 3068
3069 spin_lock_irqsave(&sc->block, flags);
3062 ath5k_txbuf_free(sc, sc->bbuf); 3070 ath5k_txbuf_free(sc, sc->bbuf);
3063 sc->bbuf->skb = skb; 3071 sc->bbuf->skb = skb;
3064 ret = ath5k_beacon_setup(sc, sc->bbuf); 3072 ret = ath5k_beacon_setup(sc, sc->bbuf);
3065 if (ret) 3073 if (ret)
3066 sc->bbuf->skb = NULL; 3074 sc->bbuf->skb = NULL;
3067 else { 3075 spin_unlock_irqrestore(&sc->block, flags);
3076 if (!ret) {
3068 ath5k_beacon_config(sc); 3077 ath5k_beacon_config(sc);
3069 mmiowb(); 3078 mmiowb();
3070 } 3079 }
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h
index d7e03e6b8271..7ec2f377d5c7 100644
--- a/drivers/net/wireless/ath5k/base.h
+++ b/drivers/net/wireless/ath5k/base.h
@@ -172,6 +172,7 @@ struct ath5k_softc {
172 struct tasklet_struct txtq; /* tx intr tasklet */ 172 struct tasklet_struct txtq; /* tx intr tasklet */
173 struct ath5k_led tx_led; /* tx led */ 173 struct ath5k_led tx_led; /* tx led */
174 174
175 spinlock_t block; /* protects beacon */
175 struct ath5k_buf *bbuf; /* beacon buffer */ 176 struct ath5k_buf *bbuf; /* beacon buffer */
176 unsigned int bhalq, /* SW q for outgoing beacons */ 177 unsigned int bhalq, /* SW q for outgoing beacons */
177 bmisscount, /* missed beacon transmits */ 178 bmisscount, /* missed beacon transmits */