diff options
33 files changed, 835 insertions, 307 deletions
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e0138ac8bf50..e974e5829e1a 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
| @@ -64,6 +64,8 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
| 64 | { USB_DEVICE(0x0cf3, 0x9170) }, | 64 | { USB_DEVICE(0x0cf3, 0x9170) }, |
| 65 | /* Atheros TG121N */ | 65 | /* Atheros TG121N */ |
| 66 | { USB_DEVICE(0x0cf3, 0x1001) }, | 66 | { USB_DEVICE(0x0cf3, 0x1001) }, |
| 67 | /* TP-Link TL-WN821N v2 */ | ||
| 68 | { USB_DEVICE(0x0cf3, 0x1002) }, | ||
| 67 | /* Cace Airpcap NX */ | 69 | /* Cace Airpcap NX */ |
| 68 | { USB_DEVICE(0xcace, 0x0300) }, | 70 | { USB_DEVICE(0xcace, 0x0300) }, |
| 69 | /* D-Link DWA 160A */ | 71 | /* D-Link DWA 160A */ |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 3234995e8881..0ad6d0b76e9e 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
| @@ -609,14 +609,24 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 609 | AR_PHY_CH1_EXT_CCA, | 609 | AR_PHY_CH1_EXT_CCA, |
| 610 | AR_PHY_CH2_EXT_CCA | 610 | AR_PHY_CH2_EXT_CCA |
| 611 | }; | 611 | }; |
| 612 | u8 chainmask; | 612 | u8 chainmask, rx_chain_status; |
| 613 | 613 | ||
| 614 | rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); | ||
| 614 | if (AR_SREV_9285(ah)) | 615 | if (AR_SREV_9285(ah)) |
| 615 | chainmask = 0x9; | 616 | chainmask = 0x9; |
| 616 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) | 617 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { |
| 617 | chainmask = 0x1B; | 618 | if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) |
| 618 | else | 619 | chainmask = 0x1B; |
| 619 | chainmask = 0x3F; | 620 | else |
| 621 | chainmask = 0x09; | ||
| 622 | } else { | ||
| 623 | if (rx_chain_status & 0x4) | ||
| 624 | chainmask = 0x3F; | ||
| 625 | else if (rx_chain_status & 0x2) | ||
| 626 | chainmask = 0x1B; | ||
| 627 | else | ||
| 628 | chainmask = 0x09; | ||
| 629 | } | ||
| 620 | 630 | ||
| 621 | h = ah->nfCalHist; | 631 | h = ah->nfCalHist; |
| 622 | 632 | ||
| @@ -697,6 +707,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) | |||
| 697 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; | 707 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; |
| 698 | else if (AR_SREV_9285(ah)) | 708 | else if (AR_SREV_9285(ah)) |
| 699 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; | 709 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; |
| 710 | else if (AR_SREV_9287(ah)) | ||
| 711 | noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; | ||
| 700 | else | 712 | else |
| 701 | noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; | 713 | noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; |
| 702 | 714 | ||
| @@ -924,6 +936,7 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) | |||
| 924 | regVal |= (1 << (19 + i)); | 936 | regVal |= (1 << (19 + i)); |
| 925 | REG_WRITE(ah, 0x7834, regVal); | 937 | REG_WRITE(ah, 0x7834, regVal); |
| 926 | udelay(1); | 938 | udelay(1); |
| 939 | regVal = REG_READ(ah, 0x7834); | ||
| 927 | regVal &= (~(0x1 << (19 + i))); | 940 | regVal &= (~(0x1 << (19 + i))); |
| 928 | reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); | 941 | reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); |
| 929 | regVal |= (reg_field << (19 + i)); | 942 | regVal |= (reg_field << (19 + i)); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 019bcbba40ed..9028ab193e42 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
| @@ -28,6 +28,7 @@ extern const struct ath9k_percal_data adc_init_dc_cal; | |||
| 28 | #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 | 28 | #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 |
| 29 | #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 | 29 | #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 |
| 30 | #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 | 30 | #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 |
| 31 | #define AR_PHY_CCA_MAX_AR9287_GOOD_VALUE -118 | ||
| 31 | #define AR_PHY_CCA_MAX_HIGH_VALUE -62 | 32 | #define AR_PHY_CCA_MAX_HIGH_VALUE -62 |
| 32 | #define AR_PHY_CCA_MIN_BAD_VALUE -140 | 33 | #define AR_PHY_CCA_MIN_BAD_VALUE -140 |
| 33 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 | 34 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index ae7fb5dcb266..4071fc91da0a 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
| @@ -509,6 +509,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
| 509 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, | 509 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, |
| 510 | eep->baseEepHeader.dacLpMode); | 510 | eep->baseEepHeader.dacLpMode); |
| 511 | 511 | ||
| 512 | udelay(100); | ||
| 513 | |||
| 512 | REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, | 514 | REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, |
| 513 | pModal->miscBits >> 2); | 515 | pModal->miscBits >> 2); |
| 514 | 516 | ||
| @@ -902,7 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
| 902 | u16 powerLimit) | 904 | u16 powerLimit) |
| 903 | { | 905 | { |
| 904 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | 906 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ |
| 905 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ | 907 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ |
| 906 | 908 | ||
| 907 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 909 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
| 908 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 910 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b6c6cca07812..ca7694caf364 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -842,7 +842,7 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah) | |||
| 842 | 842 | ||
| 843 | static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | 843 | static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) |
| 844 | { | 844 | { |
| 845 | if (AR_SREV_9287_11(ah)) | 845 | if (AR_SREV_9287_11_OR_LATER(ah)) |
| 846 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 846 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 847 | ar9287Modes_rx_gain_9287_1_1, | 847 | ar9287Modes_rx_gain_9287_1_1, |
| 848 | ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); | 848 | ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); |
| @@ -853,7 +853,7 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | |||
| 853 | else if (AR_SREV_9280_20(ah)) | 853 | else if (AR_SREV_9280_20(ah)) |
| 854 | ath9k_hw_init_rxgain_ini(ah); | 854 | ath9k_hw_init_rxgain_ini(ah); |
| 855 | 855 | ||
| 856 | if (AR_SREV_9287_11(ah)) { | 856 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
| 857 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 857 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 858 | ar9287Modes_tx_gain_9287_1_1, | 858 | ar9287Modes_tx_gain_9287_1_1, |
| 859 | ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); | 859 | ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); |
| @@ -965,7 +965,7 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
| 965 | ath9k_hw_init_mode_regs(ah); | 965 | ath9k_hw_init_mode_regs(ah); |
| 966 | 966 | ||
| 967 | if (ah->is_pciexpress) | 967 | if (ah->is_pciexpress) |
| 968 | ath9k_hw_configpcipowersave(ah, 0); | 968 | ath9k_hw_configpcipowersave(ah, 0, 0); |
| 969 | else | 969 | else |
| 970 | ath9k_hw_disablepcie(ah); | 970 | ath9k_hw_disablepcie(ah); |
| 971 | 971 | ||
| @@ -1273,6 +1273,15 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, | |||
| 1273 | */ | 1273 | */ |
| 1274 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 1274 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
| 1275 | 1275 | ||
| 1276 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
| 1277 | val = REG_READ(ah, AR_PCU_MISC_MODE2) & | ||
| 1278 | (~AR_PCU_MISC_MODE2_HWWAR1); | ||
| 1279 | |||
| 1280 | if (AR_SREV_9287_10_OR_LATER(ah)) | ||
| 1281 | val = val & (~AR_PCU_MISC_MODE2_HWWAR2); | ||
| 1282 | |||
| 1283 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); | ||
| 1284 | } | ||
| 1276 | 1285 | ||
| 1277 | if (!AR_SREV_5416_20_OR_LATER(ah) || | 1286 | if (!AR_SREV_5416_20_OR_LATER(ah) || |
| 1278 | AR_SREV_9280_10_OR_LATER(ah)) | 1287 | AR_SREV_9280_10_OR_LATER(ah)) |
| @@ -1784,7 +1793,7 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 1784 | static bool ath9k_hw_chip_reset(struct ath_hw *ah, | 1793 | static bool ath9k_hw_chip_reset(struct ath_hw *ah, |
| 1785 | struct ath9k_channel *chan) | 1794 | struct ath9k_channel *chan) |
| 1786 | { | 1795 | { |
| 1787 | if (OLC_FOR_AR9280_20_LATER) { | 1796 | if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) { |
| 1788 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) | 1797 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) |
| 1789 | return false; | 1798 | return false; |
| 1790 | } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) | 1799 | } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) |
| @@ -2338,6 +2347,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2338 | struct ath9k_channel *curchan = ah->curchan; | 2347 | struct ath9k_channel *curchan = ah->curchan; |
| 2339 | u32 saveDefAntenna; | 2348 | u32 saveDefAntenna; |
| 2340 | u32 macStaId1; | 2349 | u32 macStaId1; |
| 2350 | u64 tsf = 0; | ||
| 2341 | int i, rx_chainmask, r; | 2351 | int i, rx_chainmask, r; |
| 2342 | 2352 | ||
| 2343 | ah->extprotspacing = sc->ht_extprotspacing; | 2353 | ah->extprotspacing = sc->ht_extprotspacing; |
| @@ -2347,7 +2357,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2347 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 2357 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
| 2348 | return -EIO; | 2358 | return -EIO; |
| 2349 | 2359 | ||
| 2350 | if (curchan) | 2360 | if (curchan && !ah->chip_fullsleep) |
| 2351 | ath9k_hw_getnf(ah, curchan); | 2361 | ath9k_hw_getnf(ah, curchan); |
| 2352 | 2362 | ||
| 2353 | if (bChannelChange && | 2363 | if (bChannelChange && |
| @@ -2356,8 +2366,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2356 | (chan->channel != ah->curchan->channel) && | 2366 | (chan->channel != ah->curchan->channel) && |
| 2357 | ((chan->channelFlags & CHANNEL_ALL) == | 2367 | ((chan->channelFlags & CHANNEL_ALL) == |
| 2358 | (ah->curchan->channelFlags & CHANNEL_ALL)) && | 2368 | (ah->curchan->channelFlags & CHANNEL_ALL)) && |
| 2359 | (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && | 2369 | !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) || |
| 2360 | !IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) { | 2370 | IS_CHAN_A_5MHZ_SPACED(ah->curchan))) { |
| 2361 | 2371 | ||
| 2362 | if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { | 2372 | if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { |
| 2363 | ath9k_hw_loadnf(ah, ah->curchan); | 2373 | ath9k_hw_loadnf(ah, ah->curchan); |
| @@ -2372,6 +2382,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2372 | 2382 | ||
| 2373 | macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; | 2383 | macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; |
| 2374 | 2384 | ||
| 2385 | /* For chips on which RTC reset is done, save TSF before it gets cleared */ | ||
| 2386 | if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | ||
| 2387 | tsf = ath9k_hw_gettsf64(ah); | ||
| 2388 | |||
| 2375 | saveLedState = REG_READ(ah, AR_CFG_LED) & | 2389 | saveLedState = REG_READ(ah, AR_CFG_LED) & |
| 2376 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | | 2390 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | |
| 2377 | AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); | 2391 | AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); |
| @@ -2398,6 +2412,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2398 | udelay(50); | 2412 | udelay(50); |
| 2399 | } | 2413 | } |
| 2400 | 2414 | ||
| 2415 | /* Restore TSF */ | ||
| 2416 | if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | ||
| 2417 | ath9k_hw_settsf64(ah, tsf); | ||
| 2418 | |||
| 2401 | if (AR_SREV_9280_10_OR_LATER(ah)) | 2419 | if (AR_SREV_9280_10_OR_LATER(ah)) |
| 2402 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | 2420 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); |
| 2403 | 2421 | ||
| @@ -3005,9 +3023,10 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
| 3005 | * Programming the SerDes must go through the same 288 bit serial shift | 3023 | * Programming the SerDes must go through the same 288 bit serial shift |
| 3006 | * register as the other analog registers. Hence the 9 writes. | 3024 | * register as the other analog registers. Hence the 9 writes. |
| 3007 | */ | 3025 | */ |
| 3008 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) | 3026 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) |
| 3009 | { | 3027 | { |
| 3010 | u8 i; | 3028 | u8 i; |
| 3029 | u32 val; | ||
| 3011 | 3030 | ||
| 3012 | if (ah->is_pciexpress != true) | 3031 | if (ah->is_pciexpress != true) |
| 3013 | return; | 3032 | return; |
| @@ -3017,84 +3036,113 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) | |||
| 3017 | return; | 3036 | return; |
| 3018 | 3037 | ||
| 3019 | /* Nothing to do on restore for 11N */ | 3038 | /* Nothing to do on restore for 11N */ |
| 3020 | if (restore) | 3039 | if (!restore) { |
| 3021 | return; | 3040 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
| 3041 | /* | ||
| 3042 | * AR9280 2.0 or later chips use SerDes values from the | ||
| 3043 | * initvals.h initialized depending on chipset during | ||
| 3044 | * ath9k_hw_init() | ||
| 3045 | */ | ||
| 3046 | for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { | ||
| 3047 | REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), | ||
| 3048 | INI_RA(&ah->iniPcieSerdes, i, 1)); | ||
| 3049 | } | ||
| 3050 | } else if (AR_SREV_9280(ah) && | ||
| 3051 | (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { | ||
| 3052 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); | ||
| 3053 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
| 3054 | |||
| 3055 | /* RX shut off when elecidle is asserted */ | ||
| 3056 | REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); | ||
| 3057 | REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); | ||
| 3058 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); | ||
| 3059 | |||
| 3060 | /* Shut off CLKREQ active in L1 */ | ||
| 3061 | if (ah->config.pcie_clock_req) | ||
| 3062 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); | ||
| 3063 | else | ||
| 3064 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); | ||
| 3022 | 3065 | ||
| 3023 | if (AR_SREV_9280_20_OR_LATER(ah)) { | 3066 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); |
| 3024 | /* | 3067 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); |
| 3025 | * AR9280 2.0 or later chips use SerDes values from the | 3068 | REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); |
| 3026 | * initvals.h initialized depending on chipset during | ||
| 3027 | * ath9k_hw_init() | ||
| 3028 | */ | ||
| 3029 | for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { | ||
| 3030 | REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), | ||
| 3031 | INI_RA(&ah->iniPcieSerdes, i, 1)); | ||
| 3032 | } | ||
| 3033 | } else if (AR_SREV_9280(ah) && | ||
| 3034 | (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { | ||
| 3035 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); | ||
| 3036 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
| 3037 | 3069 | ||
| 3038 | /* RX shut off when elecidle is asserted */ | 3070 | /* Load the new settings */ |
| 3039 | REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); | 3071 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
| 3040 | REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); | ||
| 3041 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); | ||
| 3042 | 3072 | ||
| 3043 | /* Shut off CLKREQ active in L1 */ | 3073 | } else { |
| 3044 | if (ah->config.pcie_clock_req) | 3074 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); |
| 3045 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); | 3075 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); |
| 3046 | else | ||
| 3047 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); | ||
| 3048 | |||
| 3049 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | ||
| 3050 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
| 3051 | REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); | ||
| 3052 | 3076 | ||
| 3053 | /* Load the new settings */ | 3077 | /* RX shut off when elecidle is asserted */ |
| 3054 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 3078 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); |
| 3079 | REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); | ||
| 3080 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); | ||
| 3055 | 3081 | ||
| 3056 | } else { | 3082 | /* |
| 3057 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); | 3083 | * Ignore ah->ah_config.pcie_clock_req setting for |
| 3058 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | 3084 | * pre-AR9280 11n |
| 3085 | */ | ||
| 3086 | REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); | ||
| 3059 | 3087 | ||
| 3060 | /* RX shut off when elecidle is asserted */ | 3088 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); |
| 3061 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); | 3089 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); |
| 3062 | REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); | 3090 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); |
| 3063 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); | ||
| 3064 | 3091 | ||
| 3065 | /* | 3092 | /* Load the new settings */ |
| 3066 | * Ignore ah->ah_config.pcie_clock_req setting for | 3093 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
| 3067 | * pre-AR9280 11n | 3094 | } |
| 3068 | */ | ||
| 3069 | REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); | ||
| 3070 | 3095 | ||
| 3071 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | 3096 | udelay(1000); |
| 3072 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
| 3073 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); | ||
| 3074 | 3097 | ||
| 3075 | /* Load the new settings */ | 3098 | /* set bit 19 to allow forcing of pcie core into L1 state */ |
| 3076 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 3099 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); |
| 3077 | } | ||
| 3078 | 3100 | ||
| 3079 | udelay(1000); | 3101 | /* Several PCIe massages to ensure proper behaviour */ |
| 3102 | if (ah->config.pcie_waen) { | ||
| 3103 | val = ah->config.pcie_waen; | ||
| 3104 | if (!power_off) | ||
| 3105 | val &= (~AR_WA_D3_L1_DISABLE); | ||
| 3106 | } else { | ||
| 3107 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || | ||
| 3108 | AR_SREV_9287(ah)) { | ||
| 3109 | val = AR9285_WA_DEFAULT; | ||
| 3110 | if (!power_off) | ||
| 3111 | val &= (~AR_WA_D3_L1_DISABLE); | ||
| 3112 | } else if (AR_SREV_9280(ah)) { | ||
| 3113 | /* | ||
| 3114 | * On AR9280 chips bit 22 of 0x4004 needs to be | ||
| 3115 | * set otherwise card may disappear. | ||
| 3116 | */ | ||
| 3117 | val = AR9280_WA_DEFAULT; | ||
| 3118 | if (!power_off) | ||
| 3119 | val &= (~AR_WA_D3_L1_DISABLE); | ||
| 3120 | } else | ||
| 3121 | val = AR_WA_DEFAULT; | ||
| 3122 | } | ||
| 3080 | 3123 | ||
| 3081 | /* set bit 19 to allow forcing of pcie core into L1 state */ | 3124 | REG_WRITE(ah, AR_WA, val); |
| 3082 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | 3125 | } |
| 3083 | 3126 | ||
| 3084 | /* Several PCIe massages to ensure proper behaviour */ | 3127 | if (power_off) { |
| 3085 | if (ah->config.pcie_waen) { | ||
| 3086 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); | ||
| 3087 | } else { | ||
| 3088 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) | ||
| 3089 | REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); | ||
| 3090 | /* | 3128 | /* |
| 3091 | * On AR9280 chips bit 22 of 0x4004 needs to be set to | 3129 | * Set PCIe workaround bits |
| 3092 | * otherwise card may disappear. | 3130 | * bit 14 in WA register (disable L1) should only |
| 3131 | * be set when device enters D3 and be cleared | ||
| 3132 | * when device comes back to D0. | ||
| 3093 | */ | 3133 | */ |
| 3094 | else if (AR_SREV_9280(ah)) | 3134 | if (ah->config.pcie_waen) { |
| 3095 | REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT); | 3135 | if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) |
| 3096 | else | 3136 | REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); |
| 3097 | REG_WRITE(ah, AR_WA, AR_WA_DEFAULT); | 3137 | } else { |
| 3138 | if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || | ||
| 3139 | AR_SREV_9287(ah)) && | ||
| 3140 | (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || | ||
| 3141 | (AR_SREV_9280(ah) && | ||
| 3142 | (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { | ||
| 3143 | REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); | ||
| 3144 | } | ||
| 3145 | } | ||
| 3098 | } | 3146 | } |
| 3099 | } | 3147 | } |
| 3100 | 3148 | ||
| @@ -3652,15 +3700,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
| 3652 | } | 3700 | } |
| 3653 | #endif | 3701 | #endif |
| 3654 | 3702 | ||
| 3655 | if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || | 3703 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; |
| 3656 | (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) || | ||
| 3657 | (ah->hw_version.macVersion == AR_SREV_VERSION_9160) || | ||
| 3658 | (ah->hw_version.macVersion == AR_SREV_VERSION_9100) || | ||
| 3659 | (ah->hw_version.macVersion == AR_SREV_VERSION_9280) || | ||
| 3660 | (ah->hw_version.macVersion == AR_SREV_VERSION_9285)) | ||
| 3661 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; | ||
| 3662 | else | ||
| 3663 | pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; | ||
| 3664 | 3704 | ||
| 3665 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) | 3705 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) |
| 3666 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; | 3706 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9106a0b537dd..b89234571829 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
| @@ -106,7 +106,7 @@ | |||
| 106 | #define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ | 106 | #define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ |
| 107 | #define AH_TIME_QUANTUM 10 | 107 | #define AH_TIME_QUANTUM 10 |
| 108 | #define AR_KEYTABLE_SIZE 128 | 108 | #define AR_KEYTABLE_SIZE 128 |
| 109 | #define POWER_UP_TIME 200000 | 109 | #define POWER_UP_TIME 10000 |
| 110 | #define SPUR_RSSI_THRESH 40 | 110 | #define SPUR_RSSI_THRESH 40 |
| 111 | 111 | ||
| 112 | #define CAB_TIMEOUT_VAL 10 | 112 | #define CAB_TIMEOUT_VAL 10 |
| @@ -650,7 +650,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
| 650 | const struct ath9k_beacon_state *bs); | 650 | const struct ath9k_beacon_state *bs); |
| 651 | bool ath9k_hw_setpower(struct ath_hw *ah, | 651 | bool ath9k_hw_setpower(struct ath_hw *ah, |
| 652 | enum ath9k_power_mode mode); | 652 | enum ath9k_power_mode mode); |
| 653 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore); | 653 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off); |
| 654 | 654 | ||
| 655 | /* Interrupt Handling */ | 655 | /* Interrupt Handling */ |
| 656 | bool ath9k_hw_intrpend(struct ath_hw *ah); | 656 | bool ath9k_hw_intrpend(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3dc7b5a13e64..52bed89063d4 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -1131,7 +1131,7 @@ void ath_radio_enable(struct ath_softc *sc) | |||
| 1131 | int r; | 1131 | int r; |
| 1132 | 1132 | ||
| 1133 | ath9k_ps_wakeup(sc); | 1133 | ath9k_ps_wakeup(sc); |
| 1134 | ath9k_hw_configpcipowersave(ah, 0); | 1134 | ath9k_hw_configpcipowersave(ah, 0, 0); |
| 1135 | 1135 | ||
| 1136 | if (!ah->curchan) | 1136 | if (!ah->curchan) |
| 1137 | ah->curchan = ath_get_curchannel(sc, sc->hw); | 1137 | ah->curchan = ath_get_curchannel(sc, sc->hw); |
| @@ -1202,7 +1202,7 @@ void ath_radio_disable(struct ath_softc *sc) | |||
| 1202 | spin_unlock_bh(&sc->sc_resetlock); | 1202 | spin_unlock_bh(&sc->sc_resetlock); |
| 1203 | 1203 | ||
| 1204 | ath9k_hw_phy_disable(ah); | 1204 | ath9k_hw_phy_disable(ah); |
| 1205 | ath9k_hw_configpcipowersave(ah, 1); | 1205 | ath9k_hw_configpcipowersave(ah, 1, 1); |
| 1206 | ath9k_ps_restore(sc); | 1206 | ath9k_ps_restore(sc); |
| 1207 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | 1207 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); |
| 1208 | } | 1208 | } |
| @@ -1226,11 +1226,6 @@ static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) | |||
| 1226 | bool blocked = !!ath_is_rfkill_set(sc); | 1226 | bool blocked = !!ath_is_rfkill_set(sc); |
| 1227 | 1227 | ||
| 1228 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | 1228 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); |
| 1229 | |||
| 1230 | if (blocked) | ||
| 1231 | ath_radio_disable(sc); | ||
| 1232 | else | ||
| 1233 | ath_radio_enable(sc); | ||
| 1234 | } | 1229 | } |
| 1235 | 1230 | ||
| 1236 | static void ath_start_rfkill_poll(struct ath_softc *sc) | 1231 | static void ath_start_rfkill_poll(struct ath_softc *sc) |
| @@ -1260,6 +1255,7 @@ void ath_detach(struct ath_softc *sc) | |||
| 1260 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); | 1255 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); |
| 1261 | 1256 | ||
| 1262 | ath_deinit_leds(sc); | 1257 | ath_deinit_leds(sc); |
| 1258 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | ||
| 1263 | 1259 | ||
| 1264 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 1260 | for (i = 0; i < sc->num_sec_wiphy; i++) { |
| 1265 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 1261 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
| @@ -1942,7 +1938,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
| 1942 | init_channel = ath_get_curchannel(sc, hw); | 1938 | init_channel = ath_get_curchannel(sc, hw); |
| 1943 | 1939 | ||
| 1944 | /* Reset SERDES registers */ | 1940 | /* Reset SERDES registers */ |
| 1945 | ath9k_hw_configpcipowersave(sc->sc_ah, 0); | 1941 | ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0); |
| 1946 | 1942 | ||
| 1947 | /* | 1943 | /* |
| 1948 | * The basic interface to setting the hardware in a good | 1944 | * The basic interface to setting the hardware in a good |
| @@ -2166,11 +2162,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 2166 | } else | 2162 | } else |
| 2167 | sc->rx.rxlink = NULL; | 2163 | sc->rx.rxlink = NULL; |
| 2168 | 2164 | ||
| 2169 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | ||
| 2170 | |||
| 2171 | /* disable HAL and put h/w to sleep */ | 2165 | /* disable HAL and put h/w to sleep */ |
| 2172 | ath9k_hw_disable(sc->sc_ah); | 2166 | ath9k_hw_disable(sc->sc_ah); |
| 2173 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); | 2167 | ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1); |
| 2174 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | 2168 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); |
| 2175 | 2169 | ||
| 2176 | sc->sc_flags |= SC_OP_INVALID; | 2170 | sc->sc_flags |= SC_OP_INVALID; |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index e5c29eb86e80..d83b77f821e9 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
| @@ -676,8 +676,9 @@ | |||
| 676 | #define AR_RC_HOSTIF 0x00000100 | 676 | #define AR_RC_HOSTIF 0x00000100 |
| 677 | 677 | ||
| 678 | #define AR_WA 0x4004 | 678 | #define AR_WA 0x4004 |
| 679 | #define AR_WA_D3_L1_DISABLE (1 << 14) | ||
| 679 | #define AR9285_WA_DEFAULT 0x004a05cb | 680 | #define AR9285_WA_DEFAULT 0x004a05cb |
| 680 | #define AR9280_WA_DEFAULT 0x0040073f | 681 | #define AR9280_WA_DEFAULT 0x0040073b |
| 681 | #define AR_WA_DEFAULT 0x0000073f | 682 | #define AR_WA_DEFAULT 0x0000073f |
| 682 | 683 | ||
| 683 | 684 | ||
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 83e38134accb..54ea61c15d8b 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
| @@ -61,11 +61,28 @@ config B43_PCMCIA | |||
| 61 | 61 | ||
| 62 | If unsure, say N. | 62 | If unsure, say N. |
| 63 | 63 | ||
| 64 | config B43_SDIO | ||
| 65 | bool "Broadcom 43xx SDIO device support (EXPERIMENTAL)" | ||
| 66 | depends on B43 && SSB_SDIOHOST_POSSIBLE && EXPERIMENTAL | ||
| 67 | select SSB_SDIOHOST | ||
| 68 | ---help--- | ||
| 69 | Broadcom 43xx device support for Soft-MAC SDIO devices. | ||
| 70 | |||
| 71 | With this config option you can drive Soft-MAC b43 cards with a | ||
| 72 | Secure Digital I/O interface. | ||
| 73 | This includes the WLAN daughter card found on the Nintendo Wii | ||
| 74 | video game console. | ||
| 75 | Note that this does not support Broadcom 43xx Full-MAC devices. | ||
| 76 | |||
| 77 | It's safe to select Y here, even if you don't have a B43 SDIO device. | ||
| 78 | |||
| 79 | If unsure, say N. | ||
| 80 | |||
| 64 | # Data transfers to the device via PIO | 81 | # Data transfers to the device via PIO |
| 65 | # This is only needed on PCMCIA devices. All others can do DMA properly. | 82 | # This is only needed on PCMCIA and SDIO devices. All others can do DMA properly. |
| 66 | config B43_PIO | 83 | config B43_PIO |
| 67 | bool | 84 | bool |
| 68 | depends on B43 && (B43_PCMCIA || B43_FORCE_PIO) | 85 | depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO) |
| 69 | select SSB_BLOCKIO | 86 | select SSB_BLOCKIO |
| 70 | default y | 87 | default y |
| 71 | 88 | ||
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index da379f4b0c3a..84772a2542dc 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
| @@ -16,6 +16,7 @@ b43-$(CONFIG_B43_PIO) += pio.o | |||
| 16 | b43-y += rfkill.o | 16 | b43-y += rfkill.o |
| 17 | b43-$(CONFIG_B43_LEDS) += leds.o | 17 | b43-$(CONFIG_B43_LEDS) += leds.o |
| 18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o | 18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o |
| 19 | b43-$(CONFIG_B43_SDIO) += sdio.o | ||
| 19 | b43-$(CONFIG_B43_DEBUG) += debugfs.o | 20 | b43-$(CONFIG_B43_DEBUG) += debugfs.o |
| 20 | 21 | ||
| 21 | obj-$(CONFIG_B43) += b43.o | 22 | obj-$(CONFIG_B43) += b43.o |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 09cfe68537b6..fa1549a03c71 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
| @@ -629,13 +629,6 @@ struct b43_wl { | |||
| 629 | * from the mac80211 subsystem. */ | 629 | * from the mac80211 subsystem. */ |
| 630 | u16 mac80211_initially_registered_queues; | 630 | u16 mac80211_initially_registered_queues; |
| 631 | 631 | ||
| 632 | /* R/W lock for data transmission. | ||
| 633 | * Transmissions on 2+ queues can run concurrently, but somebody else | ||
| 634 | * might sync with TX by write_lock_irqsave()'ing. */ | ||
| 635 | rwlock_t tx_lock; | ||
| 636 | /* Lock for LEDs access. */ | ||
| 637 | spinlock_t leds_lock; | ||
| 638 | |||
| 639 | /* We can only have one operating interface (802.11 core) | 632 | /* We can only have one operating interface (802.11 core) |
| 640 | * at a time. General information about this interface follows. | 633 | * at a time. General information about this interface follows. |
| 641 | */ | 634 | */ |
| @@ -686,6 +679,9 @@ struct b43_wl { | |||
| 686 | struct work_struct tx_work; | 679 | struct work_struct tx_work; |
| 687 | /* Queue of packets to be transmitted. */ | 680 | /* Queue of packets to be transmitted. */ |
| 688 | struct sk_buff_head tx_queue; | 681 | struct sk_buff_head tx_queue; |
| 682 | |||
| 683 | /* The device LEDs. */ | ||
| 684 | struct b43_leds leds; | ||
| 689 | }; | 685 | }; |
| 690 | 686 | ||
| 691 | /* The type of the firmware file. */ | 687 | /* The type of the firmware file. */ |
| @@ -768,13 +764,10 @@ struct b43_wldev { | |||
| 768 | /* The device initialization status. | 764 | /* The device initialization status. |
| 769 | * Use b43_status() to query. */ | 765 | * Use b43_status() to query. */ |
| 770 | atomic_t __init_status; | 766 | atomic_t __init_status; |
| 771 | /* Saved init status for handling suspend. */ | ||
| 772 | int suspend_init_status; | ||
| 773 | 767 | ||
| 774 | bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ | 768 | bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ |
| 775 | bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ | 769 | bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ |
| 776 | bool radio_hw_enable; /* saved state of radio hardware enabled state */ | 770 | bool radio_hw_enable; /* saved state of radio hardware enabled state */ |
| 777 | bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */ | ||
| 778 | bool qos_enabled; /* TRUE, if QoS is used. */ | 771 | bool qos_enabled; /* TRUE, if QoS is used. */ |
| 779 | bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ | 772 | bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ |
| 780 | 773 | ||
| @@ -794,12 +787,6 @@ struct b43_wldev { | |||
| 794 | /* Various statistics about the physical device. */ | 787 | /* Various statistics about the physical device. */ |
| 795 | struct b43_stats stats; | 788 | struct b43_stats stats; |
| 796 | 789 | ||
| 797 | /* The device LEDs. */ | ||
| 798 | struct b43_led led_tx; | ||
| 799 | struct b43_led led_rx; | ||
| 800 | struct b43_led led_assoc; | ||
| 801 | struct b43_led led_radio; | ||
| 802 | |||
| 803 | /* Reason code of the last interrupt. */ | 790 | /* Reason code of the last interrupt. */ |
| 804 | u32 irq_reason; | 791 | u32 irq_reason; |
| 805 | u32 dma_reason[6]; | 792 | u32 dma_reason[6]; |
| @@ -830,6 +817,10 @@ struct b43_wldev { | |||
| 830 | /* Debugging stuff follows. */ | 817 | /* Debugging stuff follows. */ |
| 831 | #ifdef CONFIG_B43_DEBUG | 818 | #ifdef CONFIG_B43_DEBUG |
| 832 | struct b43_dfsentry *dfsentry; | 819 | struct b43_dfsentry *dfsentry; |
| 820 | unsigned int irq_count; | ||
| 821 | unsigned int irq_bit_count[32]; | ||
| 822 | unsigned int tx_count; | ||
| 823 | unsigned int rx_count; | ||
| 833 | #endif | 824 | #endif |
| 834 | }; | 825 | }; |
| 835 | 826 | ||
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 8f64943e3f60..80b19a44a407 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c | |||
| @@ -689,6 +689,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) | |||
| 689 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); | 689 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); |
| 690 | add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); | 690 | add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); |
| 691 | add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); | 691 | add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); |
| 692 | add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0); | ||
| 692 | 693 | ||
| 693 | #undef add_dyn_dbg | 694 | #undef add_dyn_dbg |
| 694 | } | 695 | } |
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index e47b4b488b04..822aad8842f4 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h | |||
| @@ -13,6 +13,7 @@ enum b43_dyndbg { /* Dynamic debugging features */ | |||
| 13 | B43_DBG_LO, | 13 | B43_DBG_LO, |
| 14 | B43_DBG_FIRMWARE, | 14 | B43_DBG_FIRMWARE, |
| 15 | B43_DBG_KEYS, | 15 | B43_DBG_KEYS, |
| 16 | B43_DBG_VERBOSESTATS, | ||
| 16 | __B43_NR_DYNDBG, | 17 | __B43_NR_DYNDBG, |
| 17 | }; | 18 | }; |
| 18 | 19 | ||
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index a467ee260a19..8701034569fa 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
| @@ -1428,9 +1428,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
| 1428 | ring->nr_failed_tx_packets++; | 1428 | ring->nr_failed_tx_packets++; |
| 1429 | ring->nr_total_packet_tries += status->frame_count; | 1429 | ring->nr_total_packet_tries += status->frame_count; |
| 1430 | #endif /* DEBUG */ | 1430 | #endif /* DEBUG */ |
| 1431 | ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); | 1431 | ieee80211_tx_status(dev->wl->hw, meta->skb); |
| 1432 | 1432 | ||
| 1433 | /* skb is freed by ieee80211_tx_status_irqsafe() */ | 1433 | /* skb is freed by ieee80211_tx_status() */ |
| 1434 | meta->skb = NULL; | 1434 | meta->skb = NULL; |
| 1435 | } else { | 1435 | } else { |
| 1436 | /* No need to call free_descriptor_buffer here, as | 1436 | /* No need to call free_descriptor_buffer here, as |
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index c8b317094c31..fbe3d4f62ce2 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c | |||
| @@ -34,57 +34,88 @@ | |||
| 34 | static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, | 34 | static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, |
| 35 | bool activelow) | 35 | bool activelow) |
| 36 | { | 36 | { |
| 37 | struct b43_wl *wl = dev->wl; | ||
| 38 | unsigned long flags; | ||
| 39 | u16 ctl; | 37 | u16 ctl; |
| 40 | 38 | ||
| 41 | spin_lock_irqsave(&wl->leds_lock, flags); | ||
| 42 | ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); | 39 | ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); |
| 43 | if (activelow) | 40 | if (activelow) |
| 44 | ctl &= ~(1 << led_index); | 41 | ctl &= ~(1 << led_index); |
| 45 | else | 42 | else |
| 46 | ctl |= (1 << led_index); | 43 | ctl |= (1 << led_index); |
| 47 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); | 44 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); |
| 48 | spin_unlock_irqrestore(&wl->leds_lock, flags); | ||
| 49 | } | 45 | } |
| 50 | 46 | ||
| 51 | static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index, | 47 | static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index, |
| 52 | bool activelow) | 48 | bool activelow) |
| 53 | { | 49 | { |
| 54 | struct b43_wl *wl = dev->wl; | ||
| 55 | unsigned long flags; | ||
| 56 | u16 ctl; | 50 | u16 ctl; |
| 57 | 51 | ||
| 58 | spin_lock_irqsave(&wl->leds_lock, flags); | ||
| 59 | ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); | 52 | ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); |
| 60 | if (activelow) | 53 | if (activelow) |
| 61 | ctl |= (1 << led_index); | 54 | ctl |= (1 << led_index); |
| 62 | else | 55 | else |
| 63 | ctl &= ~(1 << led_index); | 56 | ctl &= ~(1 << led_index); |
| 64 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); | 57 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); |
| 65 | spin_unlock_irqrestore(&wl->leds_lock, flags); | ||
| 66 | } | 58 | } |
| 67 | 59 | ||
| 68 | /* Callback from the LED subsystem. */ | 60 | static void b43_led_update(struct b43_wldev *dev, |
| 69 | static void b43_led_brightness_set(struct led_classdev *led_dev, | 61 | struct b43_led *led) |
| 70 | enum led_brightness brightness) | ||
| 71 | { | 62 | { |
| 72 | struct b43_led *led = container_of(led_dev, struct b43_led, led_dev); | ||
| 73 | struct b43_wldev *dev = led->dev; | ||
| 74 | bool radio_enabled; | 63 | bool radio_enabled; |
| 64 | bool turn_on; | ||
| 75 | 65 | ||
| 76 | if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) | 66 | if (!led->wl) |
| 77 | return; | 67 | return; |
| 78 | 68 | ||
| 79 | /* Checking the radio-enabled status here is slightly racy, | ||
| 80 | * but we want to avoid the locking overhead and we don't care | ||
| 81 | * whether the LED has the wrong state for a second. */ | ||
| 82 | radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); | 69 | radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); |
| 83 | 70 | ||
| 84 | if (brightness == LED_OFF || !radio_enabled) | 71 | /* The led->state read is racy, but we don't care. In case we raced |
| 85 | b43_led_turn_off(dev, led->index, led->activelow); | 72 | * with the brightness_set handler, we will be called again soon |
| 73 | * to fixup our state. */ | ||
| 74 | if (radio_enabled) | ||
| 75 | turn_on = atomic_read(&led->state) != LED_OFF; | ||
| 86 | else | 76 | else |
| 77 | turn_on = 0; | ||
| 78 | if (turn_on == led->hw_state) | ||
| 79 | return; | ||
| 80 | led->hw_state = turn_on; | ||
| 81 | |||
| 82 | if (turn_on) | ||
| 87 | b43_led_turn_on(dev, led->index, led->activelow); | 83 | b43_led_turn_on(dev, led->index, led->activelow); |
| 84 | else | ||
| 85 | b43_led_turn_off(dev, led->index, led->activelow); | ||
| 86 | } | ||
| 87 | |||
| 88 | static void b43_leds_work(struct work_struct *work) | ||
| 89 | { | ||
| 90 | struct b43_leds *leds = container_of(work, struct b43_leds, work); | ||
| 91 | struct b43_wl *wl = container_of(leds, struct b43_wl, leds); | ||
| 92 | struct b43_wldev *dev; | ||
| 93 | |||
| 94 | mutex_lock(&wl->mutex); | ||
| 95 | dev = wl->current_dev; | ||
| 96 | if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED)) | ||
| 97 | goto out_unlock; | ||
| 98 | |||
| 99 | b43_led_update(dev, &wl->leds.led_tx); | ||
| 100 | b43_led_update(dev, &wl->leds.led_rx); | ||
| 101 | b43_led_update(dev, &wl->leds.led_radio); | ||
| 102 | b43_led_update(dev, &wl->leds.led_assoc); | ||
| 103 | |||
| 104 | out_unlock: | ||
| 105 | mutex_unlock(&wl->mutex); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* Callback from the LED subsystem. */ | ||
| 109 | static void b43_led_brightness_set(struct led_classdev *led_dev, | ||
| 110 | enum led_brightness brightness) | ||
| 111 | { | ||
| 112 | struct b43_led *led = container_of(led_dev, struct b43_led, led_dev); | ||
| 113 | struct b43_wl *wl = led->wl; | ||
| 114 | |||
| 115 | if (likely(!wl->leds.stop)) { | ||
| 116 | atomic_set(&led->state, brightness); | ||
| 117 | ieee80211_queue_work(wl->hw, &wl->leds.work); | ||
| 118 | } | ||
| 88 | } | 119 | } |
| 89 | 120 | ||
| 90 | static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, | 121 | static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, |
| @@ -93,15 +124,15 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, | |||
| 93 | { | 124 | { |
| 94 | int err; | 125 | int err; |
| 95 | 126 | ||
| 96 | b43_led_turn_off(dev, led_index, activelow); | 127 | if (led->wl) |
| 97 | if (led->dev) | ||
| 98 | return -EEXIST; | 128 | return -EEXIST; |
| 99 | if (!default_trigger) | 129 | if (!default_trigger) |
| 100 | return -EINVAL; | 130 | return -EINVAL; |
| 101 | led->dev = dev; | 131 | led->wl = dev->wl; |
| 102 | led->index = led_index; | 132 | led->index = led_index; |
| 103 | led->activelow = activelow; | 133 | led->activelow = activelow; |
| 104 | strncpy(led->name, name, sizeof(led->name)); | 134 | strncpy(led->name, name, sizeof(led->name)); |
| 135 | atomic_set(&led->state, 0); | ||
| 105 | 136 | ||
| 106 | led->led_dev.name = led->name; | 137 | led->led_dev.name = led->name; |
| 107 | led->led_dev.default_trigger = default_trigger; | 138 | led->led_dev.default_trigger = default_trigger; |
| @@ -110,19 +141,19 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, | |||
| 110 | err = led_classdev_register(dev->dev->dev, &led->led_dev); | 141 | err = led_classdev_register(dev->dev->dev, &led->led_dev); |
| 111 | if (err) { | 142 | if (err) { |
| 112 | b43warn(dev->wl, "LEDs: Failed to register %s\n", name); | 143 | b43warn(dev->wl, "LEDs: Failed to register %s\n", name); |
| 113 | led->dev = NULL; | 144 | led->wl = NULL; |
| 114 | return err; | 145 | return err; |
| 115 | } | 146 | } |
| 147 | |||
| 116 | return 0; | 148 | return 0; |
| 117 | } | 149 | } |
| 118 | 150 | ||
| 119 | static void b43_unregister_led(struct b43_led *led) | 151 | static void b43_unregister_led(struct b43_led *led) |
| 120 | { | 152 | { |
| 121 | if (!led->dev) | 153 | if (!led->wl) |
| 122 | return; | 154 | return; |
| 123 | led_classdev_unregister(&led->led_dev); | 155 | led_classdev_unregister(&led->led_dev); |
| 124 | b43_led_turn_off(led->dev, led->index, led->activelow); | 156 | led->wl = NULL; |
| 125 | led->dev = NULL; | ||
| 126 | } | 157 | } |
| 127 | 158 | ||
| 128 | static void b43_map_led(struct b43_wldev *dev, | 159 | static void b43_map_led(struct b43_wldev *dev, |
| @@ -137,24 +168,20 @@ static void b43_map_led(struct b43_wldev *dev, | |||
| 137 | * generic LED triggers. */ | 168 | * generic LED triggers. */ |
| 138 | switch (behaviour) { | 169 | switch (behaviour) { |
| 139 | case B43_LED_INACTIVE: | 170 | case B43_LED_INACTIVE: |
| 140 | break; | ||
| 141 | case B43_LED_OFF: | 171 | case B43_LED_OFF: |
| 142 | b43_led_turn_off(dev, led_index, activelow); | ||
| 143 | break; | ||
| 144 | case B43_LED_ON: | 172 | case B43_LED_ON: |
| 145 | b43_led_turn_on(dev, led_index, activelow); | ||
| 146 | break; | 173 | break; |
| 147 | case B43_LED_ACTIVITY: | 174 | case B43_LED_ACTIVITY: |
| 148 | case B43_LED_TRANSFER: | 175 | case B43_LED_TRANSFER: |
| 149 | case B43_LED_APTRANSFER: | 176 | case B43_LED_APTRANSFER: |
| 150 | snprintf(name, sizeof(name), | 177 | snprintf(name, sizeof(name), |
| 151 | "b43-%s::tx", wiphy_name(hw->wiphy)); | 178 | "b43-%s::tx", wiphy_name(hw->wiphy)); |
| 152 | b43_register_led(dev, &dev->led_tx, name, | 179 | b43_register_led(dev, &dev->wl->leds.led_tx, name, |
| 153 | ieee80211_get_tx_led_name(hw), | 180 | ieee80211_get_tx_led_name(hw), |
| 154 | led_index, activelow); | 181 | led_index, activelow); |
| 155 | snprintf(name, sizeof(name), | 182 | snprintf(name, sizeof(name), |
| 156 | "b43-%s::rx", wiphy_name(hw->wiphy)); | 183 | "b43-%s::rx", wiphy_name(hw->wiphy)); |
| 157 | b43_register_led(dev, &dev->led_rx, name, | 184 | b43_register_led(dev, &dev->wl->leds.led_rx, name, |
| 158 | ieee80211_get_rx_led_name(hw), | 185 | ieee80211_get_rx_led_name(hw), |
| 159 | led_index, activelow); | 186 | led_index, activelow); |
| 160 | break; | 187 | break; |
| @@ -164,18 +191,15 @@ static void b43_map_led(struct b43_wldev *dev, | |||
| 164 | case B43_LED_MODE_BG: | 191 | case B43_LED_MODE_BG: |
| 165 | snprintf(name, sizeof(name), | 192 | snprintf(name, sizeof(name), |
| 166 | "b43-%s::radio", wiphy_name(hw->wiphy)); | 193 | "b43-%s::radio", wiphy_name(hw->wiphy)); |
| 167 | b43_register_led(dev, &dev->led_radio, name, | 194 | b43_register_led(dev, &dev->wl->leds.led_radio, name, |
| 168 | ieee80211_get_radio_led_name(hw), | 195 | ieee80211_get_radio_led_name(hw), |
| 169 | led_index, activelow); | 196 | led_index, activelow); |
| 170 | /* Sync the RF-kill LED state with radio and switch states. */ | ||
| 171 | if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) | ||
| 172 | b43_led_turn_on(dev, led_index, activelow); | ||
| 173 | break; | 197 | break; |
| 174 | case B43_LED_WEIRD: | 198 | case B43_LED_WEIRD: |
| 175 | case B43_LED_ASSOC: | 199 | case B43_LED_ASSOC: |
| 176 | snprintf(name, sizeof(name), | 200 | snprintf(name, sizeof(name), |
| 177 | "b43-%s::assoc", wiphy_name(hw->wiphy)); | 201 | "b43-%s::assoc", wiphy_name(hw->wiphy)); |
| 178 | b43_register_led(dev, &dev->led_assoc, name, | 202 | b43_register_led(dev, &dev->wl->leds.led_assoc, name, |
| 179 | ieee80211_get_assoc_led_name(hw), | 203 | ieee80211_get_assoc_led_name(hw), |
| 180 | led_index, activelow); | 204 | led_index, activelow); |
| 181 | break; | 205 | break; |
| @@ -186,58 +210,150 @@ static void b43_map_led(struct b43_wldev *dev, | |||
| 186 | } | 210 | } |
| 187 | } | 211 | } |
| 188 | 212 | ||
| 189 | void b43_leds_init(struct b43_wldev *dev) | 213 | static void b43_led_get_sprominfo(struct b43_wldev *dev, |
| 214 | unsigned int led_index, | ||
| 215 | enum b43_led_behaviour *behaviour, | ||
| 216 | bool *activelow) | ||
| 190 | { | 217 | { |
| 191 | struct ssb_bus *bus = dev->dev->bus; | 218 | struct ssb_bus *bus = dev->dev->bus; |
| 192 | u8 sprom[4]; | 219 | u8 sprom[4]; |
| 193 | int i; | ||
| 194 | enum b43_led_behaviour behaviour; | ||
| 195 | bool activelow; | ||
| 196 | 220 | ||
| 197 | sprom[0] = bus->sprom.gpio0; | 221 | sprom[0] = bus->sprom.gpio0; |
| 198 | sprom[1] = bus->sprom.gpio1; | 222 | sprom[1] = bus->sprom.gpio1; |
| 199 | sprom[2] = bus->sprom.gpio2; | 223 | sprom[2] = bus->sprom.gpio2; |
| 200 | sprom[3] = bus->sprom.gpio3; | 224 | sprom[3] = bus->sprom.gpio3; |
| 201 | 225 | ||
| 202 | for (i = 0; i < 4; i++) { | 226 | if (sprom[led_index] == 0xFF) { |
| 203 | if (sprom[i] == 0xFF) { | 227 | /* There is no LED information in the SPROM |
| 204 | /* There is no LED information in the SPROM | 228 | * for this LED. Hardcode it here. */ |
| 205 | * for this LED. Hardcode it here. */ | 229 | *activelow = 0; |
| 206 | activelow = 0; | 230 | switch (led_index) { |
| 207 | switch (i) { | 231 | case 0: |
| 208 | case 0: | 232 | *behaviour = B43_LED_ACTIVITY; |
| 209 | behaviour = B43_LED_ACTIVITY; | 233 | *activelow = 1; |
| 210 | activelow = 1; | 234 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) |
| 211 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) | 235 | *behaviour = B43_LED_RADIO_ALL; |
| 212 | behaviour = B43_LED_RADIO_ALL; | 236 | break; |
| 213 | break; | 237 | case 1: |
| 214 | case 1: | 238 | *behaviour = B43_LED_RADIO_B; |
| 215 | behaviour = B43_LED_RADIO_B; | 239 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) |
| 216 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) | 240 | *behaviour = B43_LED_ASSOC; |
| 217 | behaviour = B43_LED_ASSOC; | 241 | break; |
| 218 | break; | 242 | case 2: |
| 219 | case 2: | 243 | *behaviour = B43_LED_RADIO_A; |
| 220 | behaviour = B43_LED_RADIO_A; | 244 | break; |
| 221 | break; | 245 | case 3: |
| 222 | case 3: | 246 | *behaviour = B43_LED_OFF; |
| 223 | behaviour = B43_LED_OFF; | 247 | break; |
| 224 | break; | 248 | default: |
| 225 | default: | 249 | B43_WARN_ON(1); |
| 226 | B43_WARN_ON(1); | 250 | return; |
| 227 | return; | 251 | } |
| 228 | } | 252 | } else { |
| 253 | *behaviour = sprom[led_index] & B43_LED_BEHAVIOUR; | ||
| 254 | *activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW); | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | void b43_leds_init(struct b43_wldev *dev) | ||
| 259 | { | ||
| 260 | struct b43_led *led; | ||
| 261 | unsigned int i; | ||
| 262 | enum b43_led_behaviour behaviour; | ||
| 263 | bool activelow; | ||
| 264 | |||
| 265 | /* Sync the RF-kill LED state (if we have one) with radio and switch states. */ | ||
| 266 | led = &dev->wl->leds.led_radio; | ||
| 267 | if (led->wl) { | ||
| 268 | if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) { | ||
| 269 | b43_led_turn_on(dev, led->index, led->activelow); | ||
| 270 | led->hw_state = 1; | ||
| 271 | atomic_set(&led->state, 1); | ||
| 229 | } else { | 272 | } else { |
| 230 | behaviour = sprom[i] & B43_LED_BEHAVIOUR; | 273 | b43_led_turn_off(dev, led->index, led->activelow); |
| 231 | activelow = !!(sprom[i] & B43_LED_ACTIVELOW); | 274 | led->hw_state = 0; |
| 275 | atomic_set(&led->state, 0); | ||
| 232 | } | 276 | } |
| 233 | b43_map_led(dev, i, behaviour, activelow); | ||
| 234 | } | 277 | } |
| 278 | |||
| 279 | /* Initialize TX/RX/ASSOC leds */ | ||
| 280 | led = &dev->wl->leds.led_tx; | ||
| 281 | if (led->wl) { | ||
| 282 | b43_led_turn_off(dev, led->index, led->activelow); | ||
| 283 | led->hw_state = 0; | ||
| 284 | atomic_set(&led->state, 0); | ||
| 285 | } | ||
| 286 | led = &dev->wl->leds.led_rx; | ||
| 287 | if (led->wl) { | ||
| 288 | b43_led_turn_off(dev, led->index, led->activelow); | ||
| 289 | led->hw_state = 0; | ||
| 290 | atomic_set(&led->state, 0); | ||
| 291 | } | ||
| 292 | led = &dev->wl->leds.led_assoc; | ||
| 293 | if (led->wl) { | ||
| 294 | b43_led_turn_off(dev, led->index, led->activelow); | ||
| 295 | led->hw_state = 0; | ||
| 296 | atomic_set(&led->state, 0); | ||
| 297 | } | ||
| 298 | |||
| 299 | /* Initialize other LED states. */ | ||
| 300 | for (i = 0; i < B43_MAX_NR_LEDS; i++) { | ||
| 301 | b43_led_get_sprominfo(dev, i, &behaviour, &activelow); | ||
| 302 | switch (behaviour) { | ||
| 303 | case B43_LED_OFF: | ||
| 304 | b43_led_turn_off(dev, i, activelow); | ||
| 305 | break; | ||
| 306 | case B43_LED_ON: | ||
| 307 | b43_led_turn_on(dev, i, activelow); | ||
| 308 | break; | ||
| 309 | default: | ||
| 310 | /* Leave others as-is. */ | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | dev->wl->leds.stop = 0; | ||
| 235 | } | 316 | } |
| 236 | 317 | ||
| 237 | void b43_leds_exit(struct b43_wldev *dev) | 318 | void b43_leds_exit(struct b43_wldev *dev) |
| 238 | { | 319 | { |
| 239 | b43_unregister_led(&dev->led_tx); | 320 | struct b43_leds *leds = &dev->wl->leds; |
| 240 | b43_unregister_led(&dev->led_rx); | 321 | |
| 241 | b43_unregister_led(&dev->led_assoc); | 322 | b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow); |
| 242 | b43_unregister_led(&dev->led_radio); | 323 | b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow); |
| 324 | b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow); | ||
| 325 | b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow); | ||
| 326 | } | ||
| 327 | |||
| 328 | void b43_leds_stop(struct b43_wldev *dev) | ||
| 329 | { | ||
| 330 | struct b43_leds *leds = &dev->wl->leds; | ||
| 331 | |||
| 332 | leds->stop = 1; | ||
| 333 | cancel_work_sync(&leds->work); | ||
| 334 | } | ||
| 335 | |||
| 336 | void b43_leds_register(struct b43_wldev *dev) | ||
| 337 | { | ||
| 338 | unsigned int i; | ||
| 339 | enum b43_led_behaviour behaviour; | ||
| 340 | bool activelow; | ||
| 341 | |||
| 342 | INIT_WORK(&dev->wl->leds.work, b43_leds_work); | ||
| 343 | |||
| 344 | /* Register the LEDs to the LED subsystem. */ | ||
| 345 | for (i = 0; i < B43_MAX_NR_LEDS; i++) { | ||
| 346 | b43_led_get_sprominfo(dev, i, &behaviour, &activelow); | ||
| 347 | b43_map_led(dev, i, behaviour, activelow); | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | void b43_leds_unregister(struct b43_wldev *dev) | ||
| 352 | { | ||
| 353 | struct b43_leds *leds = &dev->wl->leds; | ||
| 354 | |||
| 355 | b43_unregister_led(&leds->led_tx); | ||
| 356 | b43_unregister_led(&leds->led_rx); | ||
| 357 | b43_unregister_led(&leds->led_assoc); | ||
| 358 | b43_unregister_led(&leds->led_radio); | ||
| 243 | } | 359 | } |
diff --git a/drivers/net/wireless/b43/leds.h b/drivers/net/wireless/b43/leds.h index b8b1dd521243..9592e4c5a5f5 100644 --- a/drivers/net/wireless/b43/leds.h +++ b/drivers/net/wireless/b43/leds.h | |||
| @@ -7,12 +7,13 @@ struct b43_wldev; | |||
| 7 | 7 | ||
| 8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
| 9 | #include <linux/leds.h> | 9 | #include <linux/leds.h> |
| 10 | #include <linux/workqueue.h> | ||
| 10 | 11 | ||
| 11 | 12 | ||
| 12 | #define B43_LED_MAX_NAME_LEN 31 | 13 | #define B43_LED_MAX_NAME_LEN 31 |
| 13 | 14 | ||
| 14 | struct b43_led { | 15 | struct b43_led { |
| 15 | struct b43_wldev *dev; | 16 | struct b43_wl *wl; |
| 16 | /* The LED class device */ | 17 | /* The LED class device */ |
| 17 | struct led_classdev led_dev; | 18 | struct led_classdev led_dev; |
| 18 | /* The index number of the LED. */ | 19 | /* The index number of the LED. */ |
| @@ -22,8 +23,24 @@ struct b43_led { | |||
| 22 | bool activelow; | 23 | bool activelow; |
| 23 | /* The unique name string for this LED device. */ | 24 | /* The unique name string for this LED device. */ |
| 24 | char name[B43_LED_MAX_NAME_LEN + 1]; | 25 | char name[B43_LED_MAX_NAME_LEN + 1]; |
| 26 | /* The current status of the LED. This is updated locklessly. */ | ||
| 27 | atomic_t state; | ||
| 28 | /* The active state in hardware. */ | ||
| 29 | bool hw_state; | ||
| 25 | }; | 30 | }; |
| 26 | 31 | ||
| 32 | struct b43_leds { | ||
| 33 | struct b43_led led_tx; | ||
| 34 | struct b43_led led_rx; | ||
| 35 | struct b43_led led_radio; | ||
| 36 | struct b43_led led_assoc; | ||
| 37 | |||
| 38 | bool stop; | ||
| 39 | struct work_struct work; | ||
| 40 | }; | ||
| 41 | |||
| 42 | #define B43_MAX_NR_LEDS 4 | ||
| 43 | |||
| 27 | #define B43_LED_BEHAVIOUR 0x7F | 44 | #define B43_LED_BEHAVIOUR 0x7F |
| 28 | #define B43_LED_ACTIVELOW 0x80 | 45 | #define B43_LED_ACTIVELOW 0x80 |
| 29 | /* LED behaviour values */ | 46 | /* LED behaviour values */ |
| @@ -42,23 +59,35 @@ enum b43_led_behaviour { | |||
| 42 | B43_LED_INACTIVE, | 59 | B43_LED_INACTIVE, |
| 43 | }; | 60 | }; |
| 44 | 61 | ||
| 62 | void b43_leds_register(struct b43_wldev *dev); | ||
| 63 | void b43_leds_unregister(struct b43_wldev *dev); | ||
| 45 | void b43_leds_init(struct b43_wldev *dev); | 64 | void b43_leds_init(struct b43_wldev *dev); |
| 46 | void b43_leds_exit(struct b43_wldev *dev); | 65 | void b43_leds_exit(struct b43_wldev *dev); |
| 66 | void b43_leds_stop(struct b43_wldev *dev); | ||
| 47 | 67 | ||
| 48 | 68 | ||
| 49 | #else /* CONFIG_B43_LEDS */ | 69 | #else /* CONFIG_B43_LEDS */ |
| 50 | /* LED support disabled */ | 70 | /* LED support disabled */ |
| 51 | 71 | ||
| 52 | struct b43_led { | 72 | struct b43_leds { |
| 53 | /* empty */ | 73 | /* empty */ |
| 54 | }; | 74 | }; |
| 55 | 75 | ||
| 76 | static inline void b43_leds_register(struct b43_wldev *dev) | ||
| 77 | { | ||
| 78 | } | ||
| 79 | static inline void b43_leds_unregister(struct b43_wldev *dev) | ||
| 80 | { | ||
| 81 | } | ||
| 56 | static inline void b43_leds_init(struct b43_wldev *dev) | 82 | static inline void b43_leds_init(struct b43_wldev *dev) |
| 57 | { | 83 | { |
| 58 | } | 84 | } |
| 59 | static inline void b43_leds_exit(struct b43_wldev *dev) | 85 | static inline void b43_leds_exit(struct b43_wldev *dev) |
| 60 | { | 86 | { |
| 61 | } | 87 | } |
| 88 | static inline void b43_leds_stop(struct b43_wldev *dev) | ||
| 89 | { | ||
| 90 | } | ||
| 62 | #endif /* CONFIG_B43_LEDS */ | 91 | #endif /* CONFIG_B43_LEDS */ |
| 63 | 92 | ||
| 64 | #endif /* B43_LEDS_H_ */ | 93 | #endif /* B43_LEDS_H_ */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e789792a36bc..9b907a36bb8c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -8,6 +8,9 @@ | |||
| 8 | Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> | 8 | Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> |
| 9 | Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> | 9 | Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> |
| 10 | 10 | ||
| 11 | SDIO support | ||
| 12 | Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es> | ||
| 13 | |||
| 11 | Some parts of the code in this file are derived from the ipw2200 | 14 | Some parts of the code in this file are derived from the ipw2200 |
| 12 | driver Copyright(c) 2003 - 2004 Intel Corporation. | 15 | driver Copyright(c) 2003 - 2004 Intel Corporation. |
| 13 | 16 | ||
| @@ -53,6 +56,8 @@ | |||
| 53 | #include "xmit.h" | 56 | #include "xmit.h" |
| 54 | #include "lo.h" | 57 | #include "lo.h" |
| 55 | #include "pcmcia.h" | 58 | #include "pcmcia.h" |
| 59 | #include "sdio.h" | ||
| 60 | #include <linux/mmc/sdio_func.h> | ||
| 56 | 61 | ||
| 57 | MODULE_DESCRIPTION("Broadcom B43 wireless driver"); | 62 | MODULE_DESCRIPTION("Broadcom B43 wireless driver"); |
| 58 | MODULE_AUTHOR("Martin Langer"); | 63 | MODULE_AUTHOR("Martin Langer"); |
| @@ -1587,7 +1592,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) | |||
| 1587 | mutex_lock(&wl->mutex); | 1592 | mutex_lock(&wl->mutex); |
| 1588 | dev = wl->current_dev; | 1593 | dev = wl->current_dev; |
| 1589 | if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { | 1594 | if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { |
| 1590 | if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { | 1595 | if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { |
| 1591 | /* wl->mutex is enough. */ | 1596 | /* wl->mutex is enough. */ |
| 1592 | b43_do_beacon_update_trigger_work(dev); | 1597 | b43_do_beacon_update_trigger_work(dev); |
| 1593 | mmiowb(); | 1598 | mmiowb(); |
| @@ -1825,6 +1830,16 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
| 1825 | 1830 | ||
| 1826 | /* Re-enable interrupts on the device by restoring the current interrupt mask. */ | 1831 | /* Re-enable interrupts on the device by restoring the current interrupt mask. */ |
| 1827 | b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); | 1832 | b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); |
| 1833 | |||
| 1834 | #if B43_DEBUG | ||
| 1835 | if (b43_debug(dev, B43_DBG_VERBOSESTATS)) { | ||
| 1836 | dev->irq_count++; | ||
| 1837 | for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) { | ||
| 1838 | if (reason & (1 << i)) | ||
| 1839 | dev->irq_bit_count[i]++; | ||
| 1840 | } | ||
| 1841 | } | ||
| 1842 | #endif | ||
| 1828 | } | 1843 | } |
| 1829 | 1844 | ||
| 1830 | /* Interrupt thread handler. Handles device interrupts in thread context. */ | 1845 | /* Interrupt thread handler. Handles device interrupts in thread context. */ |
| @@ -1905,6 +1920,21 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) | |||
| 1905 | return ret; | 1920 | return ret; |
| 1906 | } | 1921 | } |
| 1907 | 1922 | ||
| 1923 | /* SDIO interrupt handler. This runs in process context. */ | ||
| 1924 | static void b43_sdio_interrupt_handler(struct b43_wldev *dev) | ||
| 1925 | { | ||
| 1926 | struct b43_wl *wl = dev->wl; | ||
| 1927 | irqreturn_t ret; | ||
| 1928 | |||
| 1929 | mutex_lock(&wl->mutex); | ||
| 1930 | |||
| 1931 | ret = b43_do_interrupt(dev); | ||
| 1932 | if (ret == IRQ_WAKE_THREAD) | ||
| 1933 | b43_do_interrupt_thread(dev); | ||
| 1934 | |||
| 1935 | mutex_unlock(&wl->mutex); | ||
| 1936 | } | ||
| 1937 | |||
| 1908 | void b43_do_release_fw(struct b43_firmware_file *fw) | 1938 | void b43_do_release_fw(struct b43_firmware_file *fw) |
| 1909 | { | 1939 | { |
| 1910 | release_firmware(fw->data); | 1940 | release_firmware(fw->data); |
| @@ -2645,6 +2675,20 @@ static void b43_adjust_opmode(struct b43_wldev *dev) | |||
| 2645 | cfp_pretbtt = 50; | 2675 | cfp_pretbtt = 50; |
| 2646 | } | 2676 | } |
| 2647 | b43_write16(dev, 0x612, cfp_pretbtt); | 2677 | b43_write16(dev, 0x612, cfp_pretbtt); |
| 2678 | |||
| 2679 | /* FIXME: We don't currently implement the PMQ mechanism, | ||
| 2680 | * so always disable it. If we want to implement PMQ, | ||
| 2681 | * we need to enable it here (clear DISCPMQ) in AP mode. | ||
| 2682 | */ | ||
| 2683 | if (0 /* ctl & B43_MACCTL_AP */) { | ||
| 2684 | b43_write32(dev, B43_MMIO_MACCTL, | ||
| 2685 | b43_read32(dev, B43_MMIO_MACCTL) | ||
| 2686 | & ~B43_MACCTL_DISCPMQ); | ||
| 2687 | } else { | ||
| 2688 | b43_write32(dev, B43_MMIO_MACCTL, | ||
| 2689 | b43_read32(dev, B43_MMIO_MACCTL) | ||
| 2690 | | B43_MACCTL_DISCPMQ); | ||
| 2691 | } | ||
| 2648 | } | 2692 | } |
| 2649 | 2693 | ||
| 2650 | static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm) | 2694 | static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm) |
| @@ -2873,6 +2917,27 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) | |||
| 2873 | 2917 | ||
| 2874 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | 2918 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); |
| 2875 | wmb(); | 2919 | wmb(); |
| 2920 | |||
| 2921 | #if B43_DEBUG | ||
| 2922 | if (b43_debug(dev, B43_DBG_VERBOSESTATS)) { | ||
| 2923 | unsigned int i; | ||
| 2924 | |||
| 2925 | b43dbg(dev->wl, "Stats: %7u IRQs/sec, %7u TX/sec, %7u RX/sec\n", | ||
| 2926 | dev->irq_count / 15, | ||
| 2927 | dev->tx_count / 15, | ||
| 2928 | dev->rx_count / 15); | ||
| 2929 | dev->irq_count = 0; | ||
| 2930 | dev->tx_count = 0; | ||
| 2931 | dev->rx_count = 0; | ||
| 2932 | for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) { | ||
| 2933 | if (dev->irq_bit_count[i]) { | ||
| 2934 | b43dbg(dev->wl, "Stats: %7u IRQ-%02u/sec (0x%08X)\n", | ||
| 2935 | dev->irq_bit_count[i] / 15, i, (1 << i)); | ||
| 2936 | dev->irq_bit_count[i] = 0; | ||
| 2937 | } | ||
| 2938 | } | ||
| 2939 | } | ||
| 2940 | #endif | ||
| 2876 | } | 2941 | } |
| 2877 | 2942 | ||
| 2878 | static void do_periodic_work(struct b43_wldev *dev) | 2943 | static void do_periodic_work(struct b43_wldev *dev) |
| @@ -3002,14 +3067,18 @@ static void b43_security_init(struct b43_wldev *dev) | |||
| 3002 | static int b43_rng_read(struct hwrng *rng, u32 *data) | 3067 | static int b43_rng_read(struct hwrng *rng, u32 *data) |
| 3003 | { | 3068 | { |
| 3004 | struct b43_wl *wl = (struct b43_wl *)rng->priv; | 3069 | struct b43_wl *wl = (struct b43_wl *)rng->priv; |
| 3070 | struct b43_wldev *dev; | ||
| 3071 | int count = -ENODEV; | ||
| 3005 | 3072 | ||
| 3006 | /* FIXME: We need to take wl->mutex here to make sure the device | 3073 | mutex_lock(&wl->mutex); |
| 3007 | * is not going away from under our ass. However it could deadlock | 3074 | dev = wl->current_dev; |
| 3008 | * with hwrng internal locking. */ | 3075 | if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) { |
| 3009 | 3076 | *data = b43_read16(dev, B43_MMIO_RNG); | |
| 3010 | *data = b43_read16(wl->current_dev, B43_MMIO_RNG); | 3077 | count = sizeof(u16); |
| 3078 | } | ||
| 3079 | mutex_unlock(&wl->mutex); | ||
| 3011 | 3080 | ||
| 3012 | return (sizeof(u16)); | 3081 | return count; |
| 3013 | } | 3082 | } |
| 3014 | #endif /* CONFIG_B43_HWRNG */ | 3083 | #endif /* CONFIG_B43_HWRNG */ |
| 3015 | 3084 | ||
| @@ -3068,6 +3137,9 @@ static void b43_tx_work(struct work_struct *work) | |||
| 3068 | dev_kfree_skb(skb); /* Drop it */ | 3137 | dev_kfree_skb(skb); /* Drop it */ |
| 3069 | } | 3138 | } |
| 3070 | 3139 | ||
| 3140 | #if B43_DEBUG | ||
| 3141 | dev->tx_count++; | ||
| 3142 | #endif | ||
| 3071 | mutex_unlock(&wl->mutex); | 3143 | mutex_unlock(&wl->mutex); |
| 3072 | } | 3144 | } |
| 3073 | 3145 | ||
| @@ -3820,7 +3892,7 @@ redo: | |||
| 3820 | 3892 | ||
| 3821 | /* Disable interrupts on the device. */ | 3893 | /* Disable interrupts on the device. */ |
| 3822 | b43_set_status(dev, B43_STAT_INITIALIZED); | 3894 | b43_set_status(dev, B43_STAT_INITIALIZED); |
| 3823 | if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { | 3895 | if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { |
| 3824 | /* wl->mutex is locked. That is enough. */ | 3896 | /* wl->mutex is locked. That is enough. */ |
| 3825 | b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); | 3897 | b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); |
| 3826 | b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ | 3898 | b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ |
| @@ -3830,10 +3902,15 @@ redo: | |||
| 3830 | b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ | 3902 | b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ |
| 3831 | spin_unlock_irq(&wl->hardirq_lock); | 3903 | spin_unlock_irq(&wl->hardirq_lock); |
| 3832 | } | 3904 | } |
| 3833 | /* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */ | 3905 | /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */ |
| 3834 | orig_dev = dev; | 3906 | orig_dev = dev; |
| 3835 | mutex_unlock(&wl->mutex); | 3907 | mutex_unlock(&wl->mutex); |
| 3836 | synchronize_irq(dev->dev->irq); | 3908 | if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { |
| 3909 | b43_sdio_free_irq(dev); | ||
| 3910 | } else { | ||
| 3911 | synchronize_irq(dev->dev->irq); | ||
| 3912 | free_irq(dev->dev->irq, dev); | ||
| 3913 | } | ||
| 3837 | mutex_lock(&wl->mutex); | 3914 | mutex_lock(&wl->mutex); |
| 3838 | dev = wl->current_dev; | 3915 | dev = wl->current_dev; |
| 3839 | if (!dev) | 3916 | if (!dev) |
| @@ -3850,7 +3927,7 @@ redo: | |||
| 3850 | dev_kfree_skb(skb_dequeue(&wl->tx_queue)); | 3927 | dev_kfree_skb(skb_dequeue(&wl->tx_queue)); |
| 3851 | 3928 | ||
| 3852 | b43_mac_suspend(dev); | 3929 | b43_mac_suspend(dev); |
| 3853 | free_irq(dev->dev->irq, dev); | 3930 | b43_leds_exit(dev); |
| 3854 | b43dbg(wl, "Wireless interface stopped\n"); | 3931 | b43dbg(wl, "Wireless interface stopped\n"); |
| 3855 | 3932 | ||
| 3856 | return dev; | 3933 | return dev; |
| @@ -3864,12 +3941,20 @@ static int b43_wireless_core_start(struct b43_wldev *dev) | |||
| 3864 | B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); | 3941 | B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); |
| 3865 | 3942 | ||
| 3866 | drain_txstatus_queue(dev); | 3943 | drain_txstatus_queue(dev); |
| 3867 | err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, | 3944 | if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { |
| 3868 | b43_interrupt_thread_handler, | 3945 | err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler); |
| 3869 | IRQF_SHARED, KBUILD_MODNAME, dev); | 3946 | if (err) { |
| 3870 | if (err) { | 3947 | b43err(dev->wl, "Cannot request SDIO IRQ\n"); |
| 3871 | b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); | 3948 | goto out; |
| 3872 | goto out; | 3949 | } |
| 3950 | } else { | ||
| 3951 | err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, | ||
| 3952 | b43_interrupt_thread_handler, | ||
| 3953 | IRQF_SHARED, KBUILD_MODNAME, dev); | ||
| 3954 | if (err) { | ||
| 3955 | b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); | ||
| 3956 | goto out; | ||
| 3957 | } | ||
| 3873 | } | 3958 | } |
| 3874 | 3959 | ||
| 3875 | /* We are ready to run. */ | 3960 | /* We are ready to run. */ |
| @@ -3882,8 +3967,10 @@ static int b43_wireless_core_start(struct b43_wldev *dev) | |||
| 3882 | /* Start maintainance work */ | 3967 | /* Start maintainance work */ |
| 3883 | b43_periodic_tasks_setup(dev); | 3968 | b43_periodic_tasks_setup(dev); |
| 3884 | 3969 | ||
| 3970 | b43_leds_init(dev); | ||
| 3971 | |||
| 3885 | b43dbg(dev->wl, "Wireless interface started\n"); | 3972 | b43dbg(dev->wl, "Wireless interface started\n"); |
| 3886 | out: | 3973 | out: |
| 3887 | return err; | 3974 | return err; |
| 3888 | } | 3975 | } |
| 3889 | 3976 | ||
| @@ -4160,10 +4247,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
| 4160 | macctl |= B43_MACCTL_PSM_JMP0; | 4247 | macctl |= B43_MACCTL_PSM_JMP0; |
| 4161 | b43_write32(dev, B43_MMIO_MACCTL, macctl); | 4248 | b43_write32(dev, B43_MMIO_MACCTL, macctl); |
| 4162 | 4249 | ||
| 4163 | if (!dev->suspend_in_progress) { | ||
| 4164 | b43_leds_exit(dev); | ||
| 4165 | b43_rng_exit(dev->wl); | ||
| 4166 | } | ||
| 4167 | b43_dma_free(dev); | 4250 | b43_dma_free(dev); |
| 4168 | b43_pio_free(dev); | 4251 | b43_pio_free(dev); |
| 4169 | b43_chip_exit(dev); | 4252 | b43_chip_exit(dev); |
| @@ -4180,7 +4263,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
| 4180 | /* Initialize a wireless core */ | 4263 | /* Initialize a wireless core */ |
| 4181 | static int b43_wireless_core_init(struct b43_wldev *dev) | 4264 | static int b43_wireless_core_init(struct b43_wldev *dev) |
| 4182 | { | 4265 | { |
| 4183 | struct b43_wl *wl = dev->wl; | ||
| 4184 | struct ssb_bus *bus = dev->dev->bus; | 4266 | struct ssb_bus *bus = dev->dev->bus; |
| 4185 | struct ssb_sprom *sprom = &bus->sprom; | 4267 | struct ssb_sprom *sprom = &bus->sprom; |
| 4186 | struct b43_phy *phy = &dev->phy; | 4268 | struct b43_phy *phy = &dev->phy; |
| @@ -4264,7 +4346,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
| 4264 | /* Maximum Contention Window */ | 4346 | /* Maximum Contention Window */ |
| 4265 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); | 4347 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); |
| 4266 | 4348 | ||
| 4267 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) { | 4349 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || |
| 4350 | (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || | ||
| 4351 | B43_FORCE_PIO) { | ||
| 4268 | dev->__using_pio_transfers = 1; | 4352 | dev->__using_pio_transfers = 1; |
| 4269 | err = b43_pio_init(dev); | 4353 | err = b43_pio_init(dev); |
| 4270 | } else { | 4354 | } else { |
| @@ -4280,15 +4364,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
| 4280 | ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); | 4364 | ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); |
| 4281 | b43_upload_card_macaddress(dev); | 4365 | b43_upload_card_macaddress(dev); |
| 4282 | b43_security_init(dev); | 4366 | b43_security_init(dev); |
| 4283 | if (!dev->suspend_in_progress) | 4367 | |
| 4284 | b43_rng_init(wl); | 4368 | ieee80211_wake_queues(dev->wl->hw); |
| 4285 | 4369 | ||
| 4286 | ieee80211_wake_queues(dev->wl->hw); | 4370 | ieee80211_wake_queues(dev->wl->hw); |
| 4287 | 4371 | ||
| 4288 | b43_set_status(dev, B43_STAT_INITIALIZED); | 4372 | b43_set_status(dev, B43_STAT_INITIALIZED); |
| 4289 | 4373 | ||
| 4290 | if (!dev->suspend_in_progress) | ||
| 4291 | b43_leds_init(dev); | ||
| 4292 | out: | 4374 | out: |
| 4293 | return err; | 4375 | return err; |
| 4294 | 4376 | ||
| @@ -4837,7 +4919,6 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
| 4837 | 4919 | ||
| 4838 | /* Initialize struct b43_wl */ | 4920 | /* Initialize struct b43_wl */ |
| 4839 | wl->hw = hw; | 4921 | wl->hw = hw; |
| 4840 | spin_lock_init(&wl->leds_lock); | ||
| 4841 | mutex_init(&wl->mutex); | 4922 | mutex_init(&wl->mutex); |
| 4842 | spin_lock_init(&wl->hardirq_lock); | 4923 | spin_lock_init(&wl->hardirq_lock); |
| 4843 | INIT_LIST_HEAD(&wl->devlist); | 4924 | INIT_LIST_HEAD(&wl->devlist); |
| @@ -4878,6 +4959,8 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) | |||
| 4878 | err = ieee80211_register_hw(wl->hw); | 4959 | err = ieee80211_register_hw(wl->hw); |
| 4879 | if (err) | 4960 | if (err) |
| 4880 | goto err_one_core_detach; | 4961 | goto err_one_core_detach; |
| 4962 | b43_leds_register(wl->current_dev); | ||
| 4963 | b43_rng_init(wl); | ||
| 4881 | } | 4964 | } |
| 4882 | 4965 | ||
| 4883 | out: | 4966 | out: |
| @@ -4906,12 +4989,15 @@ static void b43_remove(struct ssb_device *dev) | |||
| 4906 | * might have modified it. Restoring is important, so the networking | 4989 | * might have modified it. Restoring is important, so the networking |
| 4907 | * stack can properly free resources. */ | 4990 | * stack can properly free resources. */ |
| 4908 | wl->hw->queues = wl->mac80211_initially_registered_queues; | 4991 | wl->hw->queues = wl->mac80211_initially_registered_queues; |
| 4992 | b43_leds_stop(wldev); | ||
| 4909 | ieee80211_unregister_hw(wl->hw); | 4993 | ieee80211_unregister_hw(wl->hw); |
| 4910 | } | 4994 | } |
| 4911 | 4995 | ||
| 4912 | b43_one_core_detach(dev); | 4996 | b43_one_core_detach(dev); |
| 4913 | 4997 | ||
| 4914 | if (list_empty(&wl->devlist)) { | 4998 | if (list_empty(&wl->devlist)) { |
| 4999 | b43_rng_exit(wl); | ||
| 5000 | b43_leds_unregister(wldev); | ||
| 4915 | /* Last core on the chip unregistered. | 5001 | /* Last core on the chip unregistered. |
| 4916 | * We can destroy common struct b43_wl. | 5002 | * We can destroy common struct b43_wl. |
| 4917 | */ | 5003 | */ |
| @@ -4929,80 +5015,17 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason) | |||
| 4929 | ieee80211_queue_work(dev->wl->hw, &dev->restart_work); | 5015 | ieee80211_queue_work(dev->wl->hw, &dev->restart_work); |
| 4930 | } | 5016 | } |
| 4931 | 5017 | ||
| 4932 | #ifdef CONFIG_PM | ||
| 4933 | |||
| 4934 | static int b43_suspend(struct ssb_device *dev, pm_message_t state) | ||
| 4935 | { | ||
| 4936 | struct b43_wldev *wldev = ssb_get_drvdata(dev); | ||
| 4937 | struct b43_wl *wl = wldev->wl; | ||
| 4938 | |||
| 4939 | b43dbg(wl, "Suspending...\n"); | ||
| 4940 | |||
| 4941 | mutex_lock(&wl->mutex); | ||
| 4942 | wldev->suspend_in_progress = true; | ||
| 4943 | wldev->suspend_init_status = b43_status(wldev); | ||
| 4944 | if (wldev->suspend_init_status >= B43_STAT_STARTED) | ||
| 4945 | wldev = b43_wireless_core_stop(wldev); | ||
| 4946 | if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED) | ||
| 4947 | b43_wireless_core_exit(wldev); | ||
| 4948 | mutex_unlock(&wl->mutex); | ||
| 4949 | |||
| 4950 | b43dbg(wl, "Device suspended.\n"); | ||
| 4951 | |||
| 4952 | return 0; | ||
| 4953 | } | ||
| 4954 | |||
| 4955 | static int b43_resume(struct ssb_device *dev) | ||
| 4956 | { | ||
| 4957 | struct b43_wldev *wldev = ssb_get_drvdata(dev); | ||
| 4958 | struct b43_wl *wl = wldev->wl; | ||
| 4959 | int err = 0; | ||
| 4960 | |||
| 4961 | b43dbg(wl, "Resuming...\n"); | ||
| 4962 | |||
| 4963 | mutex_lock(&wl->mutex); | ||
| 4964 | if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) { | ||
| 4965 | err = b43_wireless_core_init(wldev); | ||
| 4966 | if (err) { | ||
| 4967 | b43err(wl, "Resume failed at core init\n"); | ||
| 4968 | goto out; | ||
| 4969 | } | ||
| 4970 | } | ||
| 4971 | if (wldev->suspend_init_status >= B43_STAT_STARTED) { | ||
| 4972 | err = b43_wireless_core_start(wldev); | ||
| 4973 | if (err) { | ||
| 4974 | b43_leds_exit(wldev); | ||
| 4975 | b43_rng_exit(wldev->wl); | ||
| 4976 | b43_wireless_core_exit(wldev); | ||
| 4977 | b43err(wl, "Resume failed at core start\n"); | ||
| 4978 | goto out; | ||
| 4979 | } | ||
| 4980 | } | ||
| 4981 | b43dbg(wl, "Device resumed.\n"); | ||
| 4982 | out: | ||
| 4983 | wldev->suspend_in_progress = false; | ||
| 4984 | mutex_unlock(&wl->mutex); | ||
| 4985 | return err; | ||
| 4986 | } | ||
| 4987 | |||
| 4988 | #else /* CONFIG_PM */ | ||
| 4989 | # define b43_suspend NULL | ||
| 4990 | # define b43_resume NULL | ||
| 4991 | #endif /* CONFIG_PM */ | ||
| 4992 | |||
| 4993 | static struct ssb_driver b43_ssb_driver = { | 5018 | static struct ssb_driver b43_ssb_driver = { |
| 4994 | .name = KBUILD_MODNAME, | 5019 | .name = KBUILD_MODNAME, |
| 4995 | .id_table = b43_ssb_tbl, | 5020 | .id_table = b43_ssb_tbl, |
| 4996 | .probe = b43_probe, | 5021 | .probe = b43_probe, |
| 4997 | .remove = b43_remove, | 5022 | .remove = b43_remove, |
| 4998 | .suspend = b43_suspend, | ||
| 4999 | .resume = b43_resume, | ||
| 5000 | }; | 5023 | }; |
| 5001 | 5024 | ||
| 5002 | static void b43_print_driverinfo(void) | 5025 | static void b43_print_driverinfo(void) |
| 5003 | { | 5026 | { |
| 5004 | const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", | 5027 | const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", |
| 5005 | *feat_leds = ""; | 5028 | *feat_leds = "", *feat_sdio = ""; |
| 5006 | 5029 | ||
| 5007 | #ifdef CONFIG_B43_PCI_AUTOSELECT | 5030 | #ifdef CONFIG_B43_PCI_AUTOSELECT |
| 5008 | feat_pci = "P"; | 5031 | feat_pci = "P"; |
| @@ -5016,11 +5039,14 @@ static void b43_print_driverinfo(void) | |||
| 5016 | #ifdef CONFIG_B43_LEDS | 5039 | #ifdef CONFIG_B43_LEDS |
| 5017 | feat_leds = "L"; | 5040 | feat_leds = "L"; |
| 5018 | #endif | 5041 | #endif |
| 5042 | #ifdef CONFIG_B43_SDIO | ||
| 5043 | feat_sdio = "S"; | ||
| 5044 | #endif | ||
| 5019 | printk(KERN_INFO "Broadcom 43xx driver loaded " | 5045 | printk(KERN_INFO "Broadcom 43xx driver loaded " |
| 5020 | "[ Features: %s%s%s%s, Firmware-ID: " | 5046 | "[ Features: %s%s%s%s%s, Firmware-ID: " |
| 5021 | B43_SUPPORTED_FIRMWARE_ID " ]\n", | 5047 | B43_SUPPORTED_FIRMWARE_ID " ]\n", |
| 5022 | feat_pci, feat_pcmcia, feat_nphy, | 5048 | feat_pci, feat_pcmcia, feat_nphy, |
| 5023 | feat_leds); | 5049 | feat_leds, feat_sdio); |
| 5024 | } | 5050 | } |
| 5025 | 5051 | ||
| 5026 | static int __init b43_init(void) | 5052 | static int __init b43_init(void) |
| @@ -5031,13 +5057,18 @@ static int __init b43_init(void) | |||
| 5031 | err = b43_pcmcia_init(); | 5057 | err = b43_pcmcia_init(); |
| 5032 | if (err) | 5058 | if (err) |
| 5033 | goto err_dfs_exit; | 5059 | goto err_dfs_exit; |
| 5034 | err = ssb_driver_register(&b43_ssb_driver); | 5060 | err = b43_sdio_init(); |
| 5035 | if (err) | 5061 | if (err) |
| 5036 | goto err_pcmcia_exit; | 5062 | goto err_pcmcia_exit; |
| 5063 | err = ssb_driver_register(&b43_ssb_driver); | ||
| 5064 | if (err) | ||
| 5065 | goto err_sdio_exit; | ||
| 5037 | b43_print_driverinfo(); | 5066 | b43_print_driverinfo(); |
| 5038 | 5067 | ||
| 5039 | return err; | 5068 | return err; |
| 5040 | 5069 | ||
| 5070 | err_sdio_exit: | ||
| 5071 | b43_sdio_exit(); | ||
| 5041 | err_pcmcia_exit: | 5072 | err_pcmcia_exit: |
| 5042 | b43_pcmcia_exit(); | 5073 | b43_pcmcia_exit(); |
| 5043 | err_dfs_exit: | 5074 | err_dfs_exit: |
| @@ -5048,6 +5079,7 @@ err_dfs_exit: | |||
| 5048 | static void __exit b43_exit(void) | 5079 | static void __exit b43_exit(void) |
| 5049 | { | 5080 | { |
| 5050 | ssb_driver_unregister(&b43_ssb_driver); | 5081 | ssb_driver_unregister(&b43_ssb_driver); |
| 5082 | b43_sdio_exit(); | ||
| 5051 | b43_pcmcia_exit(); | 5083 | b43_pcmcia_exit(); |
| 5052 | b43_debugfs_exit(); | 5084 | b43_debugfs_exit(); |
| 5053 | } | 5085 | } |
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 3e02d969f683..1e318d815a5b 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
| @@ -2228,6 +2228,16 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev, | |||
| 2228 | return B43_TXPWR_RES_DONE; | 2228 | return B43_TXPWR_RES_DONE; |
| 2229 | } | 2229 | } |
| 2230 | 2230 | ||
| 2231 | void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on) | ||
| 2232 | { | ||
| 2233 | if (on) { | ||
| 2234 | b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8); | ||
| 2235 | } else { | ||
| 2236 | b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007); | ||
| 2237 | b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007); | ||
| 2238 | } | ||
| 2239 | } | ||
| 2240 | |||
| 2231 | const struct b43_phy_operations b43_phyops_lp = { | 2241 | const struct b43_phy_operations b43_phyops_lp = { |
| 2232 | .allocate = b43_lpphy_op_allocate, | 2242 | .allocate = b43_lpphy_op_allocate, |
| 2233 | .free = b43_lpphy_op_free, | 2243 | .free = b43_lpphy_op_free, |
| @@ -2239,7 +2249,7 @@ const struct b43_phy_operations b43_phyops_lp = { | |||
| 2239 | .radio_read = b43_lpphy_op_radio_read, | 2249 | .radio_read = b43_lpphy_op_radio_read, |
| 2240 | .radio_write = b43_lpphy_op_radio_write, | 2250 | .radio_write = b43_lpphy_op_radio_write, |
| 2241 | .software_rfkill = b43_lpphy_op_software_rfkill, | 2251 | .software_rfkill = b43_lpphy_op_software_rfkill, |
| 2242 | .switch_analog = b43_phyop_switch_analog_generic, | 2252 | .switch_analog = b43_lpphy_op_switch_analog, |
| 2243 | .switch_channel = b43_lpphy_op_switch_channel, | 2253 | .switch_channel = b43_lpphy_op_switch_channel, |
| 2244 | .get_default_chan = b43_lpphy_op_get_default_chan, | 2254 | .get_default_chan = b43_lpphy_op_get_default_chan, |
| 2245 | .set_rx_antenna = b43_lpphy_op_set_rx_antenna, | 2255 | .set_rx_antenna = b43_lpphy_op_set_rx_antenna, |
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 3498b68385e7..e96091b31499 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c | |||
| @@ -574,7 +574,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, | |||
| 574 | q->buffer_used -= total_len; | 574 | q->buffer_used -= total_len; |
| 575 | q->free_packet_slots += 1; | 575 | q->free_packet_slots += 1; |
| 576 | 576 | ||
| 577 | ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb); | 577 | ieee80211_tx_status(dev->wl->hw, pack->skb); |
| 578 | pack->skb = NULL; | 578 | pack->skb = NULL; |
| 579 | list_add(&pack->list, &q->packets_list); | 579 | list_add(&pack->list, &q->packets_list); |
| 580 | 580 | ||
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 31e55999893f..7a3218c5ba7d 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | /* Returns TRUE, if the radio is enabled in hardware. */ | 28 | /* Returns TRUE, if the radio is enabled in hardware. */ |
| 29 | bool b43_is_hw_radio_enabled(struct b43_wldev *dev) | 29 | bool b43_is_hw_radio_enabled(struct b43_wldev *dev) |
| 30 | { | 30 | { |
| 31 | if (dev->phy.rev >= 3) { | 31 | if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) { |
| 32 | if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) | 32 | if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) |
| 33 | & B43_MMIO_RADIO_HWENABLED_HI_MASK)) | 33 | & B43_MMIO_RADIO_HWENABLED_HI_MASK)) |
| 34 | return 1; | 34 | return 1; |
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c new file mode 100644 index 000000000000..0d3ac64147a5 --- /dev/null +++ b/drivers/net/wireless/b43/sdio.c | |||
| @@ -0,0 +1,202 @@ | |||
| 1 | /* | ||
| 2 | * Broadcom B43 wireless driver | ||
| 3 | * | ||
| 4 | * SDIO over Sonics Silicon Backplane bus glue for b43. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2009 Albert Herranz | ||
| 7 | * Copyright (C) 2009 Michael Buesch <mb@bu3sch.de> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or (at | ||
| 12 | * your option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/mmc/card.h> | ||
| 17 | #include <linux/mmc/sdio_func.h> | ||
| 18 | #include <linux/mmc/sdio_ids.h> | ||
| 19 | #include <linux/ssb/ssb.h> | ||
| 20 | |||
| 21 | #include "sdio.h" | ||
| 22 | #include "b43.h" | ||
| 23 | |||
| 24 | |||
| 25 | #define HNBU_CHIPID 0x01 /* vendor & device id */ | ||
| 26 | |||
| 27 | #define B43_SDIO_BLOCK_SIZE 64 /* rx fifo max size in bytes */ | ||
| 28 | |||
| 29 | |||
| 30 | static const struct b43_sdio_quirk { | ||
| 31 | u16 vendor; | ||
| 32 | u16 device; | ||
| 33 | unsigned int quirks; | ||
| 34 | } b43_sdio_quirks[] = { | ||
| 35 | { 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, }, | ||
| 36 | { }, | ||
| 37 | }; | ||
| 38 | |||
| 39 | |||
| 40 | static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device) | ||
| 41 | { | ||
| 42 | const struct b43_sdio_quirk *q; | ||
| 43 | |||
| 44 | for (q = b43_sdio_quirks; q->quirks; q++) { | ||
| 45 | if (vendor == q->vendor && device == q->device) | ||
| 46 | return q->quirks; | ||
| 47 | } | ||
| 48 | |||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static void b43_sdio_interrupt_dispatcher(struct sdio_func *func) | ||
| 53 | { | ||
| 54 | struct b43_sdio *sdio = sdio_get_drvdata(func); | ||
| 55 | struct b43_wldev *dev = sdio->irq_handler_opaque; | ||
| 56 | |||
| 57 | if (unlikely(b43_status(dev) < B43_STAT_STARTED)) | ||
| 58 | return; | ||
| 59 | |||
| 60 | sdio_release_host(func); | ||
| 61 | sdio->irq_handler(dev); | ||
| 62 | sdio_claim_host(func); | ||
| 63 | } | ||
| 64 | |||
| 65 | int b43_sdio_request_irq(struct b43_wldev *dev, | ||
| 66 | void (*handler)(struct b43_wldev *dev)) | ||
| 67 | { | ||
| 68 | struct ssb_bus *bus = dev->dev->bus; | ||
| 69 | struct sdio_func *func = bus->host_sdio; | ||
| 70 | struct b43_sdio *sdio = sdio_get_drvdata(func); | ||
| 71 | int err; | ||
| 72 | |||
| 73 | sdio->irq_handler_opaque = dev; | ||
| 74 | sdio->irq_handler = handler; | ||
| 75 | sdio_claim_host(func); | ||
| 76 | err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher); | ||
| 77 | sdio_release_host(func); | ||
| 78 | |||
| 79 | return err; | ||
| 80 | } | ||
| 81 | |||
| 82 | void b43_sdio_free_irq(struct b43_wldev *dev) | ||
| 83 | { | ||
| 84 | struct ssb_bus *bus = dev->dev->bus; | ||
| 85 | struct sdio_func *func = bus->host_sdio; | ||
| 86 | struct b43_sdio *sdio = sdio_get_drvdata(func); | ||
| 87 | |||
| 88 | sdio_claim_host(func); | ||
| 89 | sdio_release_irq(func); | ||
| 90 | sdio_release_host(func); | ||
| 91 | sdio->irq_handler_opaque = NULL; | ||
| 92 | sdio->irq_handler = NULL; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int b43_sdio_probe(struct sdio_func *func, | ||
| 96 | const struct sdio_device_id *id) | ||
| 97 | { | ||
| 98 | struct b43_sdio *sdio; | ||
| 99 | struct sdio_func_tuple *tuple; | ||
| 100 | u16 vendor = 0, device = 0; | ||
| 101 | int error; | ||
| 102 | |||
| 103 | /* Look for the card chip identifier. */ | ||
| 104 | tuple = func->tuples; | ||
| 105 | while (tuple) { | ||
| 106 | switch (tuple->code) { | ||
| 107 | case 0x80: | ||
| 108 | switch (tuple->data[0]) { | ||
| 109 | case HNBU_CHIPID: | ||
| 110 | if (tuple->size != 5) | ||
| 111 | break; | ||
| 112 | vendor = tuple->data[1] | (tuple->data[2]<<8); | ||
| 113 | device = tuple->data[3] | (tuple->data[4]<<8); | ||
| 114 | dev_info(&func->dev, "Chip ID %04x:%04x\n", | ||
| 115 | vendor, device); | ||
| 116 | break; | ||
| 117 | default: | ||
| 118 | break; | ||
| 119 | } | ||
| 120 | break; | ||
| 121 | default: | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | tuple = tuple->next; | ||
| 125 | } | ||
| 126 | if (!vendor || !device) { | ||
| 127 | error = -ENODEV; | ||
| 128 | goto out; | ||
| 129 | } | ||
| 130 | |||
| 131 | sdio_claim_host(func); | ||
| 132 | error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE); | ||
| 133 | if (error) { | ||
| 134 | dev_err(&func->dev, "failed to set block size to %u bytes," | ||
| 135 | " error %d\n", B43_SDIO_BLOCK_SIZE, error); | ||
| 136 | goto err_release_host; | ||
| 137 | } | ||
| 138 | error = sdio_enable_func(func); | ||
| 139 | if (error) { | ||
| 140 | dev_err(&func->dev, "failed to enable func, error %d\n", error); | ||
| 141 | goto err_release_host; | ||
| 142 | } | ||
| 143 | sdio_release_host(func); | ||
| 144 | |||
| 145 | sdio = kzalloc(sizeof(*sdio), GFP_KERNEL); | ||
| 146 | if (!sdio) { | ||
| 147 | error = -ENOMEM; | ||
| 148 | dev_err(&func->dev, "failed to allocate ssb bus\n"); | ||
| 149 | goto err_disable_func; | ||
| 150 | } | ||
| 151 | error = ssb_bus_sdiobus_register(&sdio->ssb, func, | ||
| 152 | b43_sdio_get_quirks(vendor, device)); | ||
| 153 | if (error) { | ||
| 154 | dev_err(&func->dev, "failed to register ssb sdio bus," | ||
| 155 | " error %d\n", error); | ||
| 156 | goto err_free_ssb; | ||
| 157 | } | ||
| 158 | sdio_set_drvdata(func, sdio); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | |||
| 162 | err_free_ssb: | ||
| 163 | kfree(sdio); | ||
| 164 | err_disable_func: | ||
| 165 | sdio_disable_func(func); | ||
| 166 | err_release_host: | ||
| 167 | sdio_release_host(func); | ||
| 168 | out: | ||
| 169 | return error; | ||
| 170 | } | ||
| 171 | |||
| 172 | static void b43_sdio_remove(struct sdio_func *func) | ||
| 173 | { | ||
| 174 | struct b43_sdio *sdio = sdio_get_drvdata(func); | ||
| 175 | |||
| 176 | ssb_bus_unregister(&sdio->ssb); | ||
| 177 | sdio_disable_func(func); | ||
| 178 | kfree(sdio); | ||
| 179 | sdio_set_drvdata(func, NULL); | ||
| 180 | } | ||
| 181 | |||
| 182 | static const struct sdio_device_id b43_sdio_ids[] = { | ||
| 183 | { SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */ | ||
| 184 | { }, | ||
| 185 | }; | ||
| 186 | |||
| 187 | static struct sdio_driver b43_sdio_driver = { | ||
| 188 | .name = "b43-sdio", | ||
| 189 | .id_table = b43_sdio_ids, | ||
| 190 | .probe = b43_sdio_probe, | ||
| 191 | .remove = b43_sdio_remove, | ||
| 192 | }; | ||
| 193 | |||
| 194 | int b43_sdio_init(void) | ||
| 195 | { | ||
| 196 | return sdio_register_driver(&b43_sdio_driver); | ||
| 197 | } | ||
| 198 | |||
| 199 | void b43_sdio_exit(void) | ||
| 200 | { | ||
| 201 | sdio_unregister_driver(&b43_sdio_driver); | ||
| 202 | } | ||
diff --git a/drivers/net/wireless/b43/sdio.h b/drivers/net/wireless/b43/sdio.h new file mode 100644 index 000000000000..fb633094403a --- /dev/null +++ b/drivers/net/wireless/b43/sdio.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | #ifndef B43_SDIO_H_ | ||
| 2 | #define B43_SDIO_H_ | ||
| 3 | |||
| 4 | #include <linux/ssb/ssb.h> | ||
| 5 | |||
| 6 | struct b43_wldev; | ||
| 7 | |||
| 8 | |||
| 9 | #ifdef CONFIG_B43_SDIO | ||
| 10 | |||
| 11 | struct b43_sdio { | ||
| 12 | struct ssb_bus ssb; | ||
| 13 | void *irq_handler_opaque; | ||
| 14 | void (*irq_handler)(struct b43_wldev *dev); | ||
| 15 | }; | ||
| 16 | |||
| 17 | int b43_sdio_request_irq(struct b43_wldev *dev, | ||
| 18 | void (*handler)(struct b43_wldev *dev)); | ||
| 19 | void b43_sdio_free_irq(struct b43_wldev *dev); | ||
| 20 | |||
| 21 | int b43_sdio_init(void); | ||
| 22 | void b43_sdio_exit(void); | ||
| 23 | |||
| 24 | |||
| 25 | #else /* CONFIG_B43_SDIO */ | ||
| 26 | |||
| 27 | |||
| 28 | int b43_sdio_request_irq(struct b43_wldev *dev, | ||
| 29 | void (*handler)(struct b43_wldev *dev)) | ||
| 30 | { | ||
| 31 | return -ENODEV; | ||
| 32 | } | ||
| 33 | void b43_sdio_free_irq(struct b43_wldev *dev) | ||
| 34 | { | ||
| 35 | } | ||
| 36 | static inline int b43_sdio_init(void) | ||
| 37 | { | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | static inline void b43_sdio_exit(void) | ||
| 41 | { | ||
| 42 | } | ||
| 43 | |||
| 44 | #endif /* CONFIG_B43_SDIO */ | ||
| 45 | #endif /* B43_SDIO_H_ */ | ||
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 14f541248b5c..ac9f600995e4 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
| @@ -690,8 +690,11 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
| 690 | } | 690 | } |
| 691 | 691 | ||
| 692 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | 692 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); |
| 693 | ieee80211_rx_irqsafe(dev->wl->hw, skb); | 693 | ieee80211_rx(dev->wl->hw, skb); |
| 694 | 694 | ||
| 695 | #if B43_DEBUG | ||
| 696 | dev->rx_count++; | ||
| 697 | #endif | ||
| 695 | return; | 698 | return; |
| 696 | drop: | 699 | drop: |
| 697 | b43dbg(dev->wl, "RX: Packet dropped\n"); | 700 | b43dbg(dev->wl, "RX: Packet dropped\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index ca61d3796cef..3259b8841544 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
| @@ -2021,6 +2021,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
| 2021 | agg->frame_count, txq_id, idx); | 2021 | agg->frame_count, txq_id, idx); |
| 2022 | 2022 | ||
| 2023 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | 2023 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); |
| 2024 | if (!hdr) { | ||
| 2025 | IWL_ERR(priv, | ||
| 2026 | "BUG_ON idx doesn't point to valid skb" | ||
| 2027 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
| 2028 | return -1; | ||
| 2029 | } | ||
| 2024 | 2030 | ||
| 2025 | sc = le16_to_cpu(hdr->seq_ctrl); | 2031 | sc = le16_to_cpu(hdr->seq_ctrl); |
| 2026 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | 2032 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 1d539e3b8db1..a6391c7fea53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
| @@ -1163,6 +1163,12 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | |||
| 1163 | agg->frame_count, txq_id, idx); | 1163 | agg->frame_count, txq_id, idx); |
| 1164 | 1164 | ||
| 1165 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | 1165 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); |
| 1166 | if (!hdr) { | ||
| 1167 | IWL_ERR(priv, | ||
| 1168 | "BUG_ON idx doesn't point to valid skb" | ||
| 1169 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
| 1170 | return -1; | ||
| 1171 | } | ||
| 1166 | 1172 | ||
| 1167 | sc = le16_to_cpu(hdr->seq_ctrl); | 1173 | sc = le16_to_cpu(hdr->seq_ctrl); |
| 1168 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | 1174 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b90adcb73b06..8e1bb53c0aa3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
| @@ -250,12 +250,20 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
| 250 | } | 250 | } |
| 251 | spin_unlock_irqrestore(&rxq->lock, flags); | 251 | spin_unlock_irqrestore(&rxq->lock, flags); |
| 252 | 252 | ||
| 253 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
| 254 | priority |= __GFP_NOWARN; | ||
| 253 | /* Alloc a new receive buffer */ | 255 | /* Alloc a new receive buffer */ |
| 254 | skb = alloc_skb(priv->hw_params.rx_buf_size + 256, | 256 | skb = alloc_skb(priv->hw_params.rx_buf_size + 256, |
| 255 | priority); | 257 | priority); |
| 256 | 258 | ||
| 257 | if (!skb) { | 259 | if (!skb) { |
| 258 | IWL_CRIT(priv, "Can not allocate SKB buffers\n"); | 260 | if (net_ratelimit()) |
| 261 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); | ||
| 262 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
| 263 | net_ratelimit()) | ||
| 264 | IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", | ||
| 265 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
| 266 | rxq->free_count); | ||
| 259 | /* We don't reschedule replenish work here -- we will | 267 | /* We don't reschedule replenish work here -- we will |
| 260 | * call the restock method and if it still needs | 268 | * call the restock method and if it still needs |
| 261 | * more buffers it will schedule replenish */ | 269 | * more buffers it will schedule replenish */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index a2b9ec82b965..c6633fec8216 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
| @@ -520,7 +520,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
| 520 | struct iwl_host_cmd cmd = { | 520 | struct iwl_host_cmd cmd = { |
| 521 | .id = REPLY_WEPKEY, | 521 | .id = REPLY_WEPKEY, |
| 522 | .data = wep_cmd, | 522 | .data = wep_cmd, |
| 523 | .flags = CMD_SYNC, | 523 | .flags = CMD_ASYNC, |
| 524 | }; | 524 | }; |
| 525 | 525 | ||
| 526 | memset(wep_cmd, 0, cmd_size + | 526 | memset(wep_cmd, 0, cmd_size + |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 090966837f3c..4f2d43937283 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
| @@ -1146,11 +1146,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
| 1146 | } | 1146 | } |
| 1147 | spin_unlock_irqrestore(&rxq->lock, flags); | 1147 | spin_unlock_irqrestore(&rxq->lock, flags); |
| 1148 | 1148 | ||
| 1149 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
| 1150 | priority |= __GFP_NOWARN; | ||
| 1149 | /* Alloc a new receive buffer */ | 1151 | /* Alloc a new receive buffer */ |
| 1150 | skb = alloc_skb(priv->hw_params.rx_buf_size, priority); | 1152 | skb = alloc_skb(priv->hw_params.rx_buf_size, priority); |
| 1151 | if (!skb) { | 1153 | if (!skb) { |
| 1152 | if (net_ratelimit()) | 1154 | if (net_ratelimit()) |
| 1153 | IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); | 1155 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); |
| 1156 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
| 1157 | net_ratelimit()) | ||
| 1158 | IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", | ||
| 1159 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
| 1160 | rxq->free_count); | ||
| 1154 | /* We don't reschedule replenish work here -- we will | 1161 | /* We don't reschedule replenish work here -- we will |
| 1155 | * call the restock method and if it still needs | 1162 | * call the restock method and if it still needs |
| 1156 | * more buffers it will schedule replenish */ | 1163 | * more buffers it will schedule replenish */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 5462cb5ad994..567f029a8cda 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
| @@ -380,7 +380,7 @@ static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, | |||
| 380 | { | 380 | { |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, | 383 | static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, |
| 384 | unsigned int header_length, | 384 | unsigned int header_length, |
| 385 | struct rxdone_entry_desc *rxdesc) | 385 | struct rxdone_entry_desc *rxdesc) |
| 386 | { | 386 | { |
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 7b14d5bc63d6..88060e117541 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | menuconfig WL12XX | 1 | menuconfig WL12XX |
| 2 | boolean "TI wl12xx driver support" | 2 | tristate "TI wl12xx driver support" |
| 3 | depends on MAC80211 && WLAN_80211 && EXPERIMENTAL | 3 | depends on MAC80211 && WLAN_80211 && EXPERIMENTAL |
| 4 | ---help--- | 4 | ---help--- |
| 5 | This will enable TI wl12xx driver support. The drivers make | 5 | This will enable TI wl12xx driver support. The drivers make |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 38688847d568..23a6a6d4863b 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
| @@ -1070,7 +1070,7 @@ static int eject_installer(struct usb_interface *intf) | |||
| 1070 | 1070 | ||
| 1071 | /* Find bulk out endpoint */ | 1071 | /* Find bulk out endpoint */ |
| 1072 | endpoint = &iface_desc->endpoint[1].desc; | 1072 | endpoint = &iface_desc->endpoint[1].desc; |
| 1073 | if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT && | 1073 | if (usb_endpoint_dir_out(endpoint) && |
| 1074 | usb_endpoint_xfer_bulk(endpoint)) { | 1074 | usb_endpoint_xfer_bulk(endpoint)) { |
| 1075 | bulk_out_ep = endpoint->bEndpointAddress; | 1075 | bulk_out_ep = endpoint->bEndpointAddress; |
| 1076 | } else { | 1076 | } else { |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 039901109fa1..71e10cabf811 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
| @@ -90,8 +90,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
| 90 | bss->dtim_period = tim_ie->dtim_period; | 90 | bss->dtim_period = tim_ie->dtim_period; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | /* set default value for buggy APs */ | 93 | /* set default value for buggy AP/no TIM element */ |
| 94 | if (!elems->tim || bss->dtim_period == 0) | 94 | if (bss->dtim_period == 0) |
| 95 | bss->dtim_period = 1; | 95 | bss->dtim_period = 1; |
| 96 | 96 | ||
| 97 | bss->supp_rates_len = 0; | 97 | bss->supp_rates_len = 0; |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index d16cd9ea4d00..bf725275eb8d 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
| @@ -26,11 +26,11 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | |||
| 26 | 26 | ||
| 27 | wdev->wext.connect.ie = wdev->wext.ie; | 27 | wdev->wext.connect.ie = wdev->wext.ie; |
| 28 | wdev->wext.connect.ie_len = wdev->wext.ie_len; | 28 | wdev->wext.connect.ie_len = wdev->wext.ie_len; |
| 29 | wdev->wext.connect.privacy = wdev->wext.default_key != -1; | ||
| 30 | 29 | ||
| 31 | if (wdev->wext.keys) { | 30 | if (wdev->wext.keys) { |
| 32 | wdev->wext.keys->def = wdev->wext.default_key; | 31 | wdev->wext.keys->def = wdev->wext.default_key; |
| 33 | wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; | 32 | wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; |
| 33 | wdev->wext.connect.privacy = true; | ||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | if (!wdev->wext.connect.ssid_len) | 36 | if (!wdev->wext.connect.ssid_len) |
