diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_hw.c | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/gpio.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.c | 33 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_init.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 119 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/reg.h | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 21 |
13 files changed, 215 insertions, 68 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 82c3ab756cd0..064168909108 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -295,6 +295,26 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, /* Several PCIe massages to ensure proper behaviour */ if (ah->config.pcie_waen) REG_WRITE(ah, AR_WA, ah->config.pcie_waen); + else + REG_WRITE(ah, AR_WA, ah->WARegVal); + } + + /* + * Configire PCIE after Ini init. SERDES values now come from ini file + * This enables PCIe low power mode. + */ + if (ah->config.pcieSerDesWrite) { + unsigned int i; + struct ar5416IniArray *array; + + array = power_off ? &ah->iniPcieSerdes : + &ah->iniPcieSerdesLowPower; + + for (i = 0; i < array->ia_rows; i++) { + REG_WRITE(ah, + INI_RA(array, i, 0), + INI_RA(array, i, 1)); + } } } diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8d163ae4255e..72d5e52abb8f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -226,6 +226,7 @@ struct ath_buf_state { int bfs_retries; u8 bf_type; u8 bfs_paprd; + unsigned long bfs_paprd_timestamp; u32 bfs_keyix; enum ath9k_key_type bfs_keytype; }; @@ -425,6 +426,8 @@ int ath_beaconq_config(struct ath_softc *sc); #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ +#define ATH_PAPRD_TIMEOUT 100 /* msecs */ + void ath_paprd_calibrate(struct work_struct *work); void ath_ani_calibrate(unsigned long data); @@ -516,6 +519,7 @@ void ath_deinit_leds(struct ath_softc *sc); #define SC_OP_TSF_RESET BIT(11) #define SC_OP_BT_PRIORITY_DETECTED BIT(12) #define SC_OP_BT_SCAN BIT(13) +#define SC_OP_ANI_RUN BIT(14) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) @@ -559,7 +563,6 @@ struct ath_softc { struct mutex mutex; struct work_struct paprd_work; struct completion paprd_complete; - int paprd_txok; u32 intrstatus; u32 sc_flags; /* SC_OP_* */ @@ -628,6 +631,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) extern struct ieee80211_ops ath9k_ops; extern int modparam_nohwcrypt; +extern int led_blink; irqreturn_t ath_isr(int irq, void *dev); int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 0ee75e79fe35..3a8ee999da5d 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -76,7 +76,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev, case LED_FULL: if (led->led_type == ATH_LED_ASSOC) { sc->sc_flags |= SC_OP_LED_ASSOCIATED; - ieee80211_queue_delayed_work(sc->hw, + if (led_blink) + ieee80211_queue_delayed_work(sc->hw, &sc->ath_led_blink_work, 0); } else if (led->led_type == ATH_LED_RADIO) { ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); @@ -143,7 +144,8 @@ void ath_init_leds(struct ath_softc *sc) /* LED off, active low */ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); - INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); + if (led_blink) + INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); trigger = ieee80211_get_radio_led_name(sc->hw); snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), @@ -180,7 +182,8 @@ void ath_init_leds(struct ath_softc *sc) return; fail: - cancel_delayed_work_sync(&sc->ath_led_blink_work); + if (led_blink) + cancel_delayed_work_sync(&sc->ath_led_blink_work); ath_deinit_leds(sc); } diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 5f3ea7091ae0..ad9134bddd1e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -16,10 +16,27 @@ #include "htc.h" +/* identify firmware images */ +#define FIRMWARE_AR7010 "ar7010.fw" +#define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw" +#define FIRMWARE_AR9271 "ar9271.fw" + +MODULE_FIRMWARE(FIRMWARE_AR7010); +MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); +MODULE_FIRMWARE(FIRMWARE_AR9271); + static struct usb_device_id ath9k_hif_usb_ids[] = { - { USB_DEVICE(0x0cf3, 0x9271) }, - { USB_DEVICE(0x0cf3, 0x1006) }, - { USB_DEVICE(0x0cf3, 0x7010) }, + { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ + { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */ + { USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */ + { USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */ + { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */ + { USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */ + { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */ + { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */ + { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */ + { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ + { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */ { }, }; @@ -879,17 +896,15 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, /* Find out which firmware to load */ switch(hif_dev->device_id) { - case 0x9271: - case 0x1006: - hif_dev->fw_name = "ar9271.fw"; - break; case 0x7010: + case 0x9018: if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) - hif_dev->fw_name = "ar7010_1_1.fw"; + hif_dev->fw_name = FIRMWARE_AR7010_1_1; else - hif_dev->fw_name = "ar7010.fw"; + hif_dev->fw_name = FIRMWARE_AR7010; break; default: + hif_dev->fw_name = FIRMWARE_AR9271; break; } diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 58f52a1dc7ea..3756400e6bf9 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -287,6 +287,7 @@ struct ath9k_debug { #define ATH_LED_PIN_DEF 1 #define ATH_LED_PIN_9287 8 #define ATH_LED_PIN_9271 15 +#define ATH_LED_PIN_7010 12 #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index a63ae88abf3e..148b43317fdb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -244,17 +244,12 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) */ switch(devid) { - case 0x9271: - case 0x1006: - priv->htc->credits = 33; - break; case 0x7010: + case 0x9018: priv->htc->credits = 45; break; default: - dev_err(priv->dev, "ath9k_htc: Unsupported device id: 0x%x\n", - devid); - goto err; + priv->htc->credits = 33; } ret = htc_init(priv->htc); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 05445d8a9818..e38ca66db849 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -931,6 +931,8 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv) priv->ah->led_pin = ATH_LED_PIN_9287; else if (AR_SREV_9271(priv->ah)) priv->ah->led_pin = ATH_LED_PIN_9271; + else if (AR_DEVID_7010(priv->ah)) + priv->ah->led_pin = ATH_LED_PIN_7010; else priv->ah->led_pin = ATH_LED_PIN_DEF; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 62597f4ca319..3ed5c9ec7bc1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -388,6 +388,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.ht_enable = 0; ah->config.rx_intr_mitigation = true; + ah->config.pcieSerDesWrite = true; /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) @@ -571,24 +572,13 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_mode_regs(ah); /* - * Configire PCIE after Ini init. SERDES values now come from ini file - * This enables PCIe low power mode. + * Read back AR_WA into a permanent copy and set bits 14 and 17. + * We need to do this to avoid RMW of this register. We cannot + * read the reg when chip is asleep. */ - if (AR_SREV_9300_20_OR_LATER(ah)) { - u32 regval; - unsigned int i; - - /* Set Bits 16 and 17 in the AR_WA register. */ - regval = REG_READ(ah, AR_WA); - regval |= 0x00030000; - REG_WRITE(ah, AR_WA, regval); - - for (i = 0; i < ah->iniPcieSerdesLowPower.ia_rows; i++) { - REG_WRITE(ah, - INI_RA(&ah->iniPcieSerdesLowPower, i, 0), - INI_RA(&ah->iniPcieSerdesLowPower, i, 1)); - } - } + ah->WARegVal = REG_READ(ah, AR_WA); + ah->WARegVal |= (AR_WA_D3_L1_DISABLE | + AR_WA_ASPM_TIMER_BASED_DISABLE); if (ah->is_pciexpress) ath9k_hw_configpcipowersave(ah, 0, 0); @@ -1009,6 +999,11 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) ENABLE_REGWRITE_BUFFER(ah); + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_WA, ah->WARegVal); + udelay(10); + } + REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); @@ -1063,6 +1058,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) { ENABLE_REGWRITE_BUFFER(ah); + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_WA, ah->WARegVal); + udelay(10); + } + REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); @@ -1070,6 +1070,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) REG_WRITE(ah, AR_RC, AR_RC_AHB); REG_WRITE(ah, AR_RTC_RESET, 0); + udelay(2); REGWRITE_BUFFER_FLUSH(ah); DISABLE_REGWRITE_BUFFER(ah); @@ -1099,6 +1100,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) { + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_WA, ah->WARegVal); + udelay(10); + } + REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); @@ -1262,7 +1268,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; /* For chips on which RTC reset is done, save TSF before it gets cleared */ - if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) + if (AR_SREV_9100(ah) || + (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))) tsf = ath9k_hw_gettsf64(ah); saveLedState = REG_READ(ah, AR_CFG_LED) & @@ -1294,7 +1301,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, } /* Restore TSF */ - if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) + if (tsf) ath9k_hw_settsf64(ah, tsf); if (AR_SREV_9280_10_OR_LATER(ah)) @@ -1307,6 +1314,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (r) return r; + /* + * Some AR91xx SoC devices frequently fail to accept TSF writes + * right after the chip reset. When that happens, write a new + * value after the initvals have been applied, with an offset + * based on measured time difference + */ + if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) { + tsf += 1500; + ath9k_hw_settsf64(ah, tsf); + } + /* Setup MFP options for CCMP */ if (AR_SREV_9280_20_OR_LATER(ah)) { /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt @@ -1492,7 +1510,7 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) } EXPORT_SYMBOL(ath9k_hw_keyreset); -bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) +static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) { u32 macHi, macLo; u32 unicast_flag = AR_KEYTABLE_VALID; @@ -1530,7 +1548,6 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) return true; } -EXPORT_SYMBOL(ath9k_hw_keysetmac); bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, const struct ath9k_keyval *k, @@ -1731,17 +1748,6 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, } EXPORT_SYMBOL(ath9k_hw_set_keycache_entry); -bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) -{ - if (entry < ah->caps.keycache_size) { - u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry)); - if (val & AR_KEYTABLE_VALID) - return true; - } - return false; -} -EXPORT_SYMBOL(ath9k_hw_keyisvalid); - /******************************/ /* Power Management (Chipset) */ /******************************/ @@ -1768,6 +1774,11 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) REG_CLR_BIT(ah, (AR_RTC_RESET), AR_RTC_RESET_EN); } + + /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ + if (AR_SREV_9300_20_OR_LATER(ah)) + REG_WRITE(ah, AR_WA, + ah->WARegVal & ~AR_WA_D3_L1_DISABLE); } /* @@ -1794,6 +1805,10 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) AR_RTC_FORCE_WAKE_EN); } } + + /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */ + if (AR_SREV_9300_20_OR_LATER(ah)) + REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); } static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) @@ -1801,6 +1816,12 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) u32 val; int i; + /* Set Bits 14 and 17 of AR_WA before powering on the chip. */ + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_WA, ah->WARegVal); + udelay(10); + } + if (setChip) { if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { @@ -2155,6 +2176,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9271(ah)) pCap->num_gpio_pins = AR9271_NUM_GPIO; + else if (AR_DEVID_7010(ah)) + pCap->num_gpio_pins = AR7010_NUM_GPIO; else if (AR_SREV_9285_10_OR_LATER(ah)) pCap->num_gpio_pins = AR9285_NUM_GPIO; else if (AR_SREV_9280_10_OR_LATER(ah)) @@ -2295,8 +2318,15 @@ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) BUG_ON(gpio >= ah->caps.num_gpio_pins); - gpio_shift = gpio << 1; + if (AR_DEVID_7010(ah)) { + gpio_shift = gpio; + REG_RMW(ah, AR7010_GPIO_OE, + (AR7010_GPIO_OE_AS_INPUT << gpio_shift), + (AR7010_GPIO_OE_MASK << gpio_shift)); + return; + } + gpio_shift = gpio << 1; REG_RMW(ah, AR_GPIO_OE_OUT, (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), @@ -2312,7 +2342,11 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) if (gpio >= ah->caps.num_gpio_pins) return 0xffffffff; - if (AR_SREV_9300_20_OR_LATER(ah)) + if (AR_DEVID_7010(ah)) { + u32 val; + val = REG_READ(ah, AR7010_GPIO_IN); + return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0; + } else if (AR_SREV_9300_20_OR_LATER(ah)) return MS_REG_READ(AR9300, gpio) != 0; else if (AR_SREV_9271(ah)) return MS_REG_READ(AR9271, gpio) != 0; @@ -2332,10 +2366,16 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, { u32 gpio_shift; - ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); + if (AR_DEVID_7010(ah)) { + gpio_shift = gpio; + REG_RMW(ah, AR7010_GPIO_OE, + (AR7010_GPIO_OE_AS_OUTPUT << gpio_shift), + (AR7010_GPIO_OE_MASK << gpio_shift)); + return; + } + ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); gpio_shift = 2 * gpio; - REG_RMW(ah, AR_GPIO_OE_OUT, (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), @@ -2345,6 +2385,13 @@ EXPORT_SYMBOL(ath9k_hw_cfg_output); void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) { + if (AR_DEVID_7010(ah)) { + val = val ? 0 : 1; + REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio), + AR_GPIO_BIT(gpio)); + return; + } + if (AR_SREV_9271(ah)) val = ~val; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 5ecbfcf7470a..bb99e2e1f943 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -235,6 +235,7 @@ struct ath9k_ops_config { int ack_6mb; u32 cwm_ignore_extcca; u8 pcie_powersave_enable; + bool pcieSerDesWrite; u8 pcie_clock_req; u32 pcie_waen; u8 analog_shiftreg; @@ -819,6 +820,12 @@ struct ath_hw { u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; + /* + * Store the permanent value of Reg 0x4004in WARegVal + * so we dont have to R/M/W. We should not be reading + * this register when in sleep states. + */ + u32 WARegVal; }; static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) @@ -852,11 +859,9 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); /* Key Cache Management */ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); -bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac); bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, const struct ath9k_keyval *k, const u8 *mac); -bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry); /* GPIO / RFKILL / Antennae */ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 514a4014c198..8700e3dc53cf 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -33,6 +33,10 @@ int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); +int led_blink = 1; +module_param_named(blink, led_blink, int, 0444); +MODULE_PARM_DESC(blink, "Enable LED blink on activity"); + /* We use the hw_value as an index into our private channel structure */ #define CHAN2G(_freq, _idx) { \ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c8de50fa6378..efbf53534ade 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -268,7 +268,6 @@ void ath_paprd_calibrate(struct work_struct *work) int time_left; int i; - ath9k_ps_wakeup(sc); skb = alloc_skb(len, GFP_KERNEL); if (!skb) return; @@ -289,6 +288,7 @@ void ath_paprd_calibrate(struct work_struct *work) qnum = sc->tx.hwq_map[WME_AC_BE]; txctl.txq = &sc->tx.txq[qnum]; + ath9k_ps_wakeup(sc); ar9003_paprd_init_table(ah); for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { if (!(ah->caps.tx_chainmask & BIT(chain))) @@ -310,13 +310,13 @@ void ath_paprd_calibrate(struct work_struct *work) break; time_left = wait_for_completion_timeout(&sc->paprd_complete, - 100); + msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); if (!time_left) { ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, "Timeout waiting for paprd training on " "TX chain %d\n", chain); - break; + goto fail_paprd; } if (!ar9003_paprd_is_done(ah)) @@ -334,6 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work) ath_paprd_activate(sc); } +fail_paprd: ath9k_ps_restore(sc); } @@ -451,6 +452,10 @@ static void ath_start_ani(struct ath_common *common) { struct ath_hw *ah = common->ah; unsigned long timestamp = jiffies_to_msecs(jiffies); + struct ath_softc *sc = (struct ath_softc *) common->priv; + + if (!(sc->sc_flags & SC_OP_ANI_RUN)) + return; common->ani.longcal_timer = timestamp; common->ani.shortcal_timer = timestamp; @@ -766,11 +771,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, /* Reset rssi stats */ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } else { ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); common->curaid = 0; /* Stop ANI */ + sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); } } @@ -1241,7 +1248,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) aphy->state = ATH_WIPHY_INACTIVE; - cancel_delayed_work_sync(&sc->ath_led_blink_work); + if (led_blink) + cancel_delayed_work_sync(&sc->ath_led_blink_work); + cancel_delayed_work_sync(&sc->tx_complete_work); cancel_work_sync(&sc->paprd_work); @@ -1374,8 +1383,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MONITOR) + vif->type == NL80211_IFTYPE_MONITOR) { + sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); + } out: mutex_unlock(&sc->mutex); @@ -1396,6 +1407,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); /* Stop ANI */ + sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); /* Reclaim beacon resources */ diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 3e3ccef438db..633e3d949ec0 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -704,6 +704,11 @@ #define AR_WA_BIT7 (1 << 7) #define AR_WA_BIT23 (1 << 23) #define AR_WA_D3_L1_DISABLE (1 << 14) +#define AR_WA_D3_TO_L1_DISABLE_REAL (1 << 16) +#define AR_WA_ASPM_TIMER_BASED_DISABLE (1 << 17) +#define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */ +#define AR_WA_ANALOG_SHIFT (1 << 20) +#define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */ #define AR9285_WA_DEFAULT 0x004a050b #define AR9280_WA_DEFAULT 0x0040073b #define AR_WA_DEFAULT 0x0000073f @@ -877,6 +882,7 @@ #define AR_SREV_9271_11(_ah) \ (AR_SREV_9271(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) + #define AR_SREV_9300(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) #define AR_SREV_9300_20(_ah) \ @@ -891,6 +897,10 @@ (AR_SREV_9285_12_OR_LATER(_ah) && \ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) +#define AR_DEVID_7010(_ah) \ + (((_ah)->hw_version.devid == 0x7010) || \ + ((_ah)->hw_version.devid == 0x9018)) + #define AR_RADIO_SREV_MAJOR 0xf0 #define AR_RAD5133_SREV_MAJOR 0xc0 #define AR_RAD2133_SREV_MAJOR 0xd0 @@ -988,6 +998,7 @@ enum { #define AR9287_NUM_GPIO 11 #define AR9271_NUM_GPIO 16 #define AR9300_NUM_GPIO 17 +#define AR7010_NUM_GPIO 16 #define AR_GPIO_IN_OUT 0x4048 #define AR_GPIO_IN_VAL 0x0FFFC000 @@ -1002,6 +1013,8 @@ enum { #define AR9271_GPIO_IN_VAL_S 16 #define AR9300_GPIO_IN_VAL 0x0001FFFF #define AR9300_GPIO_IN_VAL_S 0 +#define AR7010_GPIO_IN_VAL 0x0000FFFF +#define AR7010_GPIO_IN_VAL_S 0 #define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c) #define AR_GPIO_OE_OUT_DRV 0x3 @@ -1010,6 +1023,21 @@ enum { #define AR_GPIO_OE_OUT_DRV_HI 0x2 #define AR_GPIO_OE_OUT_DRV_ALL 0x3 +#define AR7010_GPIO_OE 0x52000 +#define AR7010_GPIO_OE_MASK 0x1 +#define AR7010_GPIO_OE_AS_OUTPUT 0x0 +#define AR7010_GPIO_OE_AS_INPUT 0x1 +#define AR7010_GPIO_IN 0x52004 +#define AR7010_GPIO_OUT 0x52008 +#define AR7010_GPIO_SET 0x5200C +#define AR7010_GPIO_CLEAR 0x52010 +#define AR7010_GPIO_INT 0x52014 +#define AR7010_GPIO_INT_TYPE 0x52018 +#define AR7010_GPIO_INT_POLARITY 0x5201C +#define AR7010_GPIO_PENDING 0x52020 +#define AR7010_GPIO_INT_MASK 0x52024 +#define AR7010_GPIO_FUNCTION 0x52028 + #define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050) #define AR_GPIO_INTR_POL_VAL 0x0001FFFF #define AR_GPIO_INTR_POL_VAL_S 0 diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 20221b8c04fd..c3681a1dc941 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -328,6 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; + struct ieee80211_tx_rate rates[4]; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -335,6 +336,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tx_info = IEEE80211_SKB_CB(skb); hw = bf->aphy->hw; + memcpy(rates, tx_info->control.rates, sizeof(rates)); + rcu_read_lock(); /* XXX: use ieee80211_find_sta! */ @@ -375,6 +378,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, txfail = txpending = 0; bf_next = bf->bf_next; + skb = bf->bf_mpdu; + tx_info = IEEE80211_SKB_CB(skb); + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { /* transmit completion, subframe is * acked by block ack */ @@ -428,6 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { + memcpy(tx_info->control.rates, rates, sizeof(rates)); ath_tx_rc_status(bf, ts, nbad, txok, true); rc_update = false; } else { @@ -1644,6 +1651,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, } bf->bf_state.bfs_paprd = txctl->paprd; + if (txctl->paprd) + bf->bf_state.bfs_paprd_timestamp = jiffies; bf->bf_flags = setup_tx_flags(skb, use_ldpc); bf->bf_keytype = get_hw_crypto_keytype(skb); @@ -1944,8 +1953,12 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); if (bf->bf_state.bfs_paprd) { - sc->paprd_txok = txok; - complete(&sc->paprd_complete); + if (time_after(jiffies, + bf->bf_state.bfs_paprd_timestamp + + msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) + dev_kfree_skb_any(skb); + else + complete(&sc->paprd_complete); } else { ath_tx_complete(sc, skb, bf->aphy, tx_flags); ath_debug_stat_tx(sc, txq, bf, ts); @@ -2027,7 +2040,7 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, tx_info->status.rates[i].idx = -1; } - tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; + tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; } static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) @@ -2138,7 +2151,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * This frame is sent out as a single frame. * Use hardware retry status for this frame. */ - bf->bf_retries = ts.ts_longretry; if (ts.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; ath_tx_rc_status(bf, &ts, 0, txok, true); @@ -2268,7 +2280,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) } if (!bf_isampdu(bf)) { - bf->bf_retries = txs.ts_longretry; if (txs.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; ath_tx_rc_status(bf, &txs, 0, txok, true); |