Loading drivers/net/wireless/ath9k/ath9k.h +2 −2 Original line number Diff line number Diff line Loading @@ -587,8 +587,8 @@ struct ath9k_country_entry { u8 iso[3]; }; #define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) #define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) #define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) #define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) #define SM(_v, _f) (((_v) << _f##_S) & _f) #define MS(_v, _f) (((_v) & _f) >> _f##_S) Loading drivers/net/wireless/ath9k/core.h +33 −0 Original line number Diff line number Diff line Loading @@ -701,6 +701,7 @@ struct ath_softc { struct ath_hal *sc_ah; void __iomem *mem; spinlock_t sc_resetlock; spinlock_t sc_serial_rw; struct mutex mutex; u8 sc_curbssid[ETH_ALEN]; Loading Loading @@ -751,4 +752,36 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); /* * Read and write, they both share the same lock. We do this to serialize * reads and writes on Atheros 802.11n PCI devices only. This is required * as the FIFO on these devices can only accept sanely 2 requests. After * that the device goes bananas. Serializing the reads/writes prevents this * from happening. */ static inline void ath9k_iowrite32(struct ath_hal *ah, u32 reg_offset, u32 val) { if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { unsigned long flags; spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); iowrite32(val, ah->ah_sc->mem + reg_offset); spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); } else iowrite32(val, ah->ah_sc->mem + reg_offset); } static inline unsigned int ath9k_ioread32(struct ath_hal *ah, u32 reg_offset) { u32 val; if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { unsigned long flags; spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); val = ioread32(ah->ah_sc->mem + reg_offset); spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); } else val = ioread32(ah->ah_sc->mem + reg_offset); return val; } #endif /* CORE_H */ drivers/net/wireless/ath9k/hw.c +21 −1 Original line number Diff line number Diff line Loading @@ -437,6 +437,25 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) } ah->ah_config.intr_mitigation = 1; /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) * _and_ if on non-uniprocessor systems (Multiprocessor/HT). * This means we use it for all AR5416 devices, and the few * minor PCI AR9280 devices out there. * * Serialization is required because these devices do not handle * well the case of two concurrent reads/writes due to the latency * involved. During one read/write another read/write can be issued * on another CPU while the previous read/write may still be working * on our hardware, if we hit this case the hardware poops in a loop. * We prevent this by serializing reads and writes. * * This issue is not present on PCI-Express devices or pre-AR5416 * devices (legacy, 802.11abg). */ if (num_possible_cpus() > 1) ah->ah_config.serialize_regmode = SER_REG_MODE_AUTO; } static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, Loading Loading @@ -668,7 +687,8 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, } if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) { if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI || (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) { ah->ah_config.serialize_regmode = SER_REG_MODE_ON; } else { Loading drivers/net/wireless/ath9k/main.c +1 −0 Original line number Diff line number Diff line Loading @@ -1336,6 +1336,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) printk(KERN_ERR "Unable to create debugfs files\n"); spin_lock_init(&sc->sc_resetlock); spin_lock_init(&sc->sc_serial_rw); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, Loading drivers/net/wireless/zd1211rw/zd_mac.c +6 −2 Original line number Diff line number Diff line Loading @@ -575,13 +575,17 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) r = fill_ctrlset(mac, skb); if (r) return r; goto fail; info->rate_driver_data[0] = hw; r = zd_usb_tx(&mac->chip.usb, skb); if (r) return r; goto fail; return 0; fail: dev_kfree_skb(skb); return 0; } Loading Loading
drivers/net/wireless/ath9k/ath9k.h +2 −2 Original line number Diff line number Diff line Loading @@ -587,8 +587,8 @@ struct ath9k_country_entry { u8 iso[3]; }; #define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) #define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) #define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) #define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) #define SM(_v, _f) (((_v) << _f##_S) & _f) #define MS(_v, _f) (((_v) & _f) >> _f##_S) Loading
drivers/net/wireless/ath9k/core.h +33 −0 Original line number Diff line number Diff line Loading @@ -701,6 +701,7 @@ struct ath_softc { struct ath_hal *sc_ah; void __iomem *mem; spinlock_t sc_resetlock; spinlock_t sc_serial_rw; struct mutex mutex; u8 sc_curbssid[ETH_ALEN]; Loading Loading @@ -751,4 +752,36 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); /* * Read and write, they both share the same lock. We do this to serialize * reads and writes on Atheros 802.11n PCI devices only. This is required * as the FIFO on these devices can only accept sanely 2 requests. After * that the device goes bananas. Serializing the reads/writes prevents this * from happening. */ static inline void ath9k_iowrite32(struct ath_hal *ah, u32 reg_offset, u32 val) { if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { unsigned long flags; spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); iowrite32(val, ah->ah_sc->mem + reg_offset); spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); } else iowrite32(val, ah->ah_sc->mem + reg_offset); } static inline unsigned int ath9k_ioread32(struct ath_hal *ah, u32 reg_offset) { u32 val; if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { unsigned long flags; spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); val = ioread32(ah->ah_sc->mem + reg_offset); spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); } else val = ioread32(ah->ah_sc->mem + reg_offset); return val; } #endif /* CORE_H */
drivers/net/wireless/ath9k/hw.c +21 −1 Original line number Diff line number Diff line Loading @@ -437,6 +437,25 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) } ah->ah_config.intr_mitigation = 1; /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) * _and_ if on non-uniprocessor systems (Multiprocessor/HT). * This means we use it for all AR5416 devices, and the few * minor PCI AR9280 devices out there. * * Serialization is required because these devices do not handle * well the case of two concurrent reads/writes due to the latency * involved. During one read/write another read/write can be issued * on another CPU while the previous read/write may still be working * on our hardware, if we hit this case the hardware poops in a loop. * We prevent this by serializing reads and writes. * * This issue is not present on PCI-Express devices or pre-AR5416 * devices (legacy, 802.11abg). */ if (num_possible_cpus() > 1) ah->ah_config.serialize_regmode = SER_REG_MODE_AUTO; } static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, Loading Loading @@ -668,7 +687,8 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, } if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) { if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI || (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) { ah->ah_config.serialize_regmode = SER_REG_MODE_ON; } else { Loading
drivers/net/wireless/ath9k/main.c +1 −0 Original line number Diff line number Diff line Loading @@ -1336,6 +1336,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) printk(KERN_ERR "Unable to create debugfs files\n"); spin_lock_init(&sc->sc_resetlock); spin_lock_init(&sc->sc_serial_rw); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, Loading
drivers/net/wireless/zd1211rw/zd_mac.c +6 −2 Original line number Diff line number Diff line Loading @@ -575,13 +575,17 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) r = fill_ctrlset(mac, skb); if (r) return r; goto fail; info->rate_driver_data[0] = hw; r = zd_usb_tx(&mac->chip.usb, skb); if (r) return r; goto fail; return 0; fail: dev_kfree_skb(skb); return 0; } Loading