aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-03-17 17:29:22 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-17 17:29:22 -0400
commitf10023a4ef3f5cc05457b059c6880bc447adfa1f (patch)
treee5d229bb9719b0be27289a6736d2e22254da06f0 /drivers
parent4ada8107f465b97326751de66d3c11ed78bf8214 (diff)
parent640c65eae673d2caf6e7bf61c1eb4e9513b88fda (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath9k/ath9k.h4
-rw-r--r--drivers/net/wireless/ath9k/core.h33
-rw-r--r--drivers/net/wireless/ath9k/hw.c22
-rw-r--r--drivers/net/wireless/ath9k/main.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c8
5 files changed, 63 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index d27813502953..6650f609ece4 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -587,8 +587,8 @@ struct ath9k_country_entry {
587 u8 iso[3]; 587 u8 iso[3];
588}; 588};
589 589
590#define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) 590#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
591#define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) 591#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
592 592
593#define SM(_v, _f) (((_v) << _f##_S) & _f) 593#define SM(_v, _f) (((_v) << _f##_S) & _f)
594#define MS(_v, _f) (((_v) & _f) >> _f##_S) 594#define MS(_v, _f) (((_v) & _f) >> _f##_S)
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index 4ca2aed236e0..139566cbbf65 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -701,6 +701,7 @@ struct ath_softc {
701 struct ath_hal *sc_ah; 701 struct ath_hal *sc_ah;
702 void __iomem *mem; 702 void __iomem *mem;
703 spinlock_t sc_resetlock; 703 spinlock_t sc_resetlock;
704 spinlock_t sc_serial_rw;
704 struct mutex mutex; 705 struct mutex mutex;
705 706
706 u8 sc_curbssid[ETH_ALEN]; 707 u8 sc_curbssid[ETH_ALEN];
@@ -751,4 +752,36 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
751int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); 752int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
752int ath_cabq_update(struct ath_softc *); 753int ath_cabq_update(struct ath_softc *);
753 754
755/*
756 * Read and write, they both share the same lock. We do this to serialize
757 * reads and writes on Atheros 802.11n PCI devices only. This is required
758 * as the FIFO on these devices can only accept sanely 2 requests. After
759 * that the device goes bananas. Serializing the reads/writes prevents this
760 * from happening.
761 */
762
763static inline void ath9k_iowrite32(struct ath_hal *ah, u32 reg_offset, u32 val)
764{
765 if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) {
766 unsigned long flags;
767 spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
768 iowrite32(val, ah->ah_sc->mem + reg_offset);
769 spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
770 } else
771 iowrite32(val, ah->ah_sc->mem + reg_offset);
772}
773
774static inline unsigned int ath9k_ioread32(struct ath_hal *ah, u32 reg_offset)
775{
776 u32 val;
777 if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) {
778 unsigned long flags;
779 spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
780 val = ioread32(ah->ah_sc->mem + reg_offset);
781 spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
782 } else
783 val = ioread32(ah->ah_sc->mem + reg_offset);
784 return val;
785}
786
754#endif /* CORE_H */ 787#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index 34474edefc97..c38a00bbce64 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -437,6 +437,25 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah)
437 } 437 }
438 438
439 ah->ah_config.intr_mitigation = 1; 439 ah->ah_config.intr_mitigation = 1;
440
441 /*
442 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
443 * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
444 * This means we use it for all AR5416 devices, and the few
445 * minor PCI AR9280 devices out there.
446 *
447 * Serialization is required because these devices do not handle
448 * well the case of two concurrent reads/writes due to the latency
449 * involved. During one read/write another read/write can be issued
450 * on another CPU while the previous read/write may still be working
451 * on our hardware, if we hit this case the hardware poops in a loop.
452 * We prevent this by serializing reads and writes.
453 *
454 * This issue is not present on PCI-Express devices or pre-AR5416
455 * devices (legacy, 802.11abg).
456 */
457 if (num_possible_cpus() > 1)
458 ah->ah_config.serialize_regmode = SER_REG_MODE_AUTO;
440} 459}
441 460
442static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, 461static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
@@ -668,7 +687,8 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
668 } 687 }
669 688
670 if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) { 689 if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) {
671 if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { 690 if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI ||
691 (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) {
672 ah->ah_config.serialize_regmode = 692 ah->ah_config.serialize_regmode =
673 SER_REG_MODE_ON; 693 SER_REG_MODE_ON;
674 } else { 694 } else {
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 0e80990d8e84..3c04044a60bd 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -1336,6 +1336,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
1336 printk(KERN_ERR "Unable to create debugfs files\n"); 1336 printk(KERN_ERR "Unable to create debugfs files\n");
1337 1337
1338 spin_lock_init(&sc->sc_resetlock); 1338 spin_lock_init(&sc->sc_resetlock);
1339 spin_lock_init(&sc->sc_serial_rw);
1339 mutex_init(&sc->mutex); 1340 mutex_init(&sc->mutex);
1340 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); 1341 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
1341 tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, 1342 tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index a611ad857983..847057d682b1 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -575,13 +575,17 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
575 575
576 r = fill_ctrlset(mac, skb); 576 r = fill_ctrlset(mac, skb);
577 if (r) 577 if (r)
578 return r; 578 goto fail;
579 579
580 info->rate_driver_data[0] = hw; 580 info->rate_driver_data[0] = hw;
581 581
582 r = zd_usb_tx(&mac->chip.usb, skb); 582 r = zd_usb_tx(&mac->chip.usb, skb);
583 if (r) 583 if (r)
584 return r; 584 goto fail;
585 return 0;
586
587fail:
588 dev_kfree_skb(skb);
585 return 0; 589 return 0;
586} 590}
587 591