diff options
author | David S. Miller <davem@davemloft.net> | 2009-05-18 17:48:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-18 17:48:30 -0400 |
commit | 82d048186e403f36e083b37ad42aa90abb7dcaac (patch) | |
tree | dc0b92ace036ef435318f38ef35b8c6e6b84103a | |
parent | 62551d3ea05242d97d47f26fb517b2dfdb752310 (diff) | |
parent | d3707d9918d47c0997a6b1e4ae24e7ab55e43796 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
49 files changed, 1116 insertions, 1013 deletions
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 44fee5ae8925..a2fda702b620 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -694,7 +694,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
694 | #undef TMP_VAL_VPD_TABLE | 694 | #undef TMP_VAL_VPD_TABLE |
695 | } | 695 | } |
696 | 696 | ||
697 | static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | 697 | static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, |
698 | struct ath9k_channel *chan, | 698 | struct ath9k_channel *chan, |
699 | int16_t *pTxPowerIndexOffset) | 699 | int16_t *pTxPowerIndexOffset) |
700 | { | 700 | { |
@@ -805,11 +805,9 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
805 | } | 805 | } |
806 | 806 | ||
807 | *pTxPowerIndexOffset = 0; | 807 | *pTxPowerIndexOffset = 0; |
808 | |||
809 | return true; | ||
810 | } | 808 | } |
811 | 809 | ||
812 | static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | 810 | static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, |
813 | struct ath9k_channel *chan, | 811 | struct ath9k_channel *chan, |
814 | int16_t *ratesArray, | 812 | int16_t *ratesArray, |
815 | u16 cfgCtl, | 813 | u16 cfgCtl, |
@@ -1041,10 +1039,9 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | |||
1041 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | 1039 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; |
1042 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | 1040 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; |
1043 | } | 1041 | } |
1044 | return true; | ||
1045 | } | 1042 | } |
1046 | 1043 | ||
1047 | static int ath9k_hw_4k_set_txpower(struct ath_hw *ah, | 1044 | static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, |
1048 | struct ath9k_channel *chan, | 1045 | struct ath9k_channel *chan, |
1049 | u16 cfgCtl, | 1046 | u16 cfgCtl, |
1050 | u8 twiceAntennaReduction, | 1047 | u8 twiceAntennaReduction, |
@@ -1065,22 +1062,13 @@ static int ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
1065 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | 1062 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; |
1066 | } | 1063 | } |
1067 | 1064 | ||
1068 | if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan, | 1065 | ath9k_hw_set_4k_power_per_rate_table(ah, chan, |
1069 | &ratesArray[0], cfgCtl, | 1066 | &ratesArray[0], cfgCtl, |
1070 | twiceAntennaReduction, | 1067 | twiceAntennaReduction, |
1071 | twiceMaxRegulatoryPower, | 1068 | twiceMaxRegulatoryPower, |
1072 | powerLimit)) { | 1069 | powerLimit); |
1073 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1074 | "ath9k_hw_set_txpower: unable to set " | ||
1075 | "tx power per rate table\n"); | ||
1076 | return -EIO; | ||
1077 | } | ||
1078 | 1070 | ||
1079 | if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) { | 1071 | ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); |
1080 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1081 | "ath9k_hw_set_txpower: unable to set power table\n"); | ||
1082 | return -EIO; | ||
1083 | } | ||
1084 | 1072 | ||
1085 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | 1073 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
1086 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | 1074 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
@@ -1168,7 +1156,6 @@ static int ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
1168 | else | 1156 | else |
1169 | ah->regulatory.max_power_level = ratesArray[i]; | 1157 | ah->regulatory.max_power_level = ratesArray[i]; |
1170 | 1158 | ||
1171 | return 0; | ||
1172 | } | 1159 | } |
1173 | 1160 | ||
1174 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, | 1161 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, |
@@ -2103,7 +2090,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
2103 | return; | 2090 | return; |
2104 | } | 2091 | } |
2105 | 2092 | ||
2106 | static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | 2093 | static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, |
2107 | struct ath9k_channel *chan, | 2094 | struct ath9k_channel *chan, |
2108 | int16_t *pTxPowerIndexOffset) | 2095 | int16_t *pTxPowerIndexOffset) |
2109 | { | 2096 | { |
@@ -2255,13 +2242,11 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
2255 | } | 2242 | } |
2256 | 2243 | ||
2257 | *pTxPowerIndexOffset = 0; | 2244 | *pTxPowerIndexOffset = 0; |
2258 | |||
2259 | return true; | ||
2260 | #undef SM_PD_GAIN | 2245 | #undef SM_PD_GAIN |
2261 | #undef SM_PDGAIN_B | 2246 | #undef SM_PDGAIN_B |
2262 | } | 2247 | } |
2263 | 2248 | ||
2264 | static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | 2249 | static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, |
2265 | struct ath9k_channel *chan, | 2250 | struct ath9k_channel *chan, |
2266 | int16_t *ratesArray, | 2251 | int16_t *ratesArray, |
2267 | u16 cfgCtl, | 2252 | u16 cfgCtl, |
@@ -2549,10 +2534,9 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
2549 | targetPowerCckExt.tPow2x[0]; | 2534 | targetPowerCckExt.tPow2x[0]; |
2550 | } | 2535 | } |
2551 | } | 2536 | } |
2552 | return true; | ||
2553 | } | 2537 | } |
2554 | 2538 | ||
2555 | static int ath9k_hw_def_set_txpower(struct ath_hw *ah, | 2539 | static void ath9k_hw_def_set_txpower(struct ath_hw *ah, |
2556 | struct ath9k_channel *chan, | 2540 | struct ath9k_channel *chan, |
2557 | u16 cfgCtl, | 2541 | u16 cfgCtl, |
2558 | u8 twiceAntennaReduction, | 2542 | u8 twiceAntennaReduction, |
@@ -2575,22 +2559,13 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
2575 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | 2559 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; |
2576 | } | 2560 | } |
2577 | 2561 | ||
2578 | if (!ath9k_hw_set_def_power_per_rate_table(ah, chan, | 2562 | ath9k_hw_set_def_power_per_rate_table(ah, chan, |
2579 | &ratesArray[0], cfgCtl, | 2563 | &ratesArray[0], cfgCtl, |
2580 | twiceAntennaReduction, | 2564 | twiceAntennaReduction, |
2581 | twiceMaxRegulatoryPower, | 2565 | twiceMaxRegulatoryPower, |
2582 | powerLimit)) { | 2566 | powerLimit); |
2583 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2584 | "ath9k_hw_set_txpower: unable to set " | ||
2585 | "tx power per rate table\n"); | ||
2586 | return -EIO; | ||
2587 | } | ||
2588 | 2567 | ||
2589 | if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) { | 2568 | ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); |
2590 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2591 | "ath9k_hw_set_txpower: unable to set power table\n"); | ||
2592 | return -EIO; | ||
2593 | } | ||
2594 | 2569 | ||
2595 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | 2570 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
2596 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | 2571 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
@@ -2717,8 +2692,6 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
2717 | "Invalid chainmask configuration\n"); | 2692 | "Invalid chainmask configuration\n"); |
2718 | break; | 2693 | break; |
2719 | } | 2694 | } |
2720 | |||
2721 | return 0; | ||
2722 | } | 2695 | } |
2723 | 2696 | ||
2724 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, | 2697 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 7c59dc47f912..67b8bd12941a 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -494,7 +494,7 @@ struct eeprom_ops { | |||
494 | struct ath9k_channel *chan); | 494 | struct ath9k_channel *chan); |
495 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); | 495 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); |
496 | void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); | 496 | void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); |
497 | int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, | 497 | void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, |
498 | u16 cfgCtl, u8 twiceAntennaReduction, | 498 | u16 cfgCtl, u8 twiceAntennaReduction, |
499 | u8 twiceMaxRegulatoryPower, u8 powerLimit); | 499 | u8 twiceMaxRegulatoryPower, u8 powerLimit); |
500 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); | 500 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 5879c731e9e7..4acfab514916 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1274,7 +1274,6 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1274 | int i, regWrites = 0; | 1274 | int i, regWrites = 0; |
1275 | struct ieee80211_channel *channel = chan->chan; | 1275 | struct ieee80211_channel *channel = chan->chan; |
1276 | u32 modesIndex, freqIndex; | 1276 | u32 modesIndex, freqIndex; |
1277 | int status; | ||
1278 | 1277 | ||
1279 | switch (chan->chanmode) { | 1278 | switch (chan->chanmode) { |
1280 | case CHANNEL_A: | 1279 | case CHANNEL_A: |
@@ -1376,17 +1375,12 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1376 | if (OLC_FOR_AR9280_20_LATER) | 1375 | if (OLC_FOR_AR9280_20_LATER) |
1377 | ath9k_olc_init(ah); | 1376 | ath9k_olc_init(ah); |
1378 | 1377 | ||
1379 | status = ah->eep_ops->set_txpower(ah, chan, | 1378 | ah->eep_ops->set_txpower(ah, chan, |
1380 | ath9k_regd_get_ctl(&ah->regulatory, chan), | 1379 | ath9k_regd_get_ctl(&ah->regulatory, chan), |
1381 | channel->max_antenna_gain * 2, | 1380 | channel->max_antenna_gain * 2, |
1382 | channel->max_power * 2, | 1381 | channel->max_power * 2, |
1383 | min((u32) MAX_RATE_POWER, | 1382 | min((u32) MAX_RATE_POWER, |
1384 | (u32) ah->regulatory.power_limit)); | 1383 | (u32) ah->regulatory.power_limit)); |
1385 | if (status != 0) { | ||
1386 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
1387 | "Error initializing transmit power\n"); | ||
1388 | return -EIO; | ||
1389 | } | ||
1390 | 1384 | ||
1391 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { | 1385 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { |
1392 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 1386 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
@@ -1617,11 +1611,9 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) | |||
1617 | switch (type) { | 1611 | switch (type) { |
1618 | case ATH9K_RESET_POWER_ON: | 1612 | case ATH9K_RESET_POWER_ON: |
1619 | return ath9k_hw_set_reset_power_on(ah); | 1613 | return ath9k_hw_set_reset_power_on(ah); |
1620 | break; | ||
1621 | case ATH9K_RESET_WARM: | 1614 | case ATH9K_RESET_WARM: |
1622 | case ATH9K_RESET_COLD: | 1615 | case ATH9K_RESET_COLD: |
1623 | return ath9k_hw_set_reset(ah, type); | 1616 | return ath9k_hw_set_reset(ah, type); |
1624 | break; | ||
1625 | default: | 1617 | default: |
1626 | return false; | 1618 | return false; |
1627 | } | 1619 | } |
@@ -1703,11 +1695,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1703 | ath9k_hw_set_regs(ah, chan, macmode); | 1695 | ath9k_hw_set_regs(ah, chan, macmode); |
1704 | 1696 | ||
1705 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1697 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
1706 | if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { | 1698 | ath9k_hw_ar9280_set_channel(ah, chan); |
1707 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
1708 | "Failed to set channel\n"); | ||
1709 | return false; | ||
1710 | } | ||
1711 | } else { | 1699 | } else { |
1712 | if (!(ath9k_hw_set_channel(ah, chan))) { | 1700 | if (!(ath9k_hw_set_channel(ah, chan))) { |
1713 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 1701 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
@@ -1716,16 +1704,12 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1716 | } | 1704 | } |
1717 | } | 1705 | } |
1718 | 1706 | ||
1719 | if (ah->eep_ops->set_txpower(ah, chan, | 1707 | ah->eep_ops->set_txpower(ah, chan, |
1720 | ath9k_regd_get_ctl(&ah->regulatory, chan), | 1708 | ath9k_regd_get_ctl(&ah->regulatory, chan), |
1721 | channel->max_antenna_gain * 2, | 1709 | channel->max_antenna_gain * 2, |
1722 | channel->max_power * 2, | 1710 | channel->max_power * 2, |
1723 | min((u32) MAX_RATE_POWER, | 1711 | min((u32) MAX_RATE_POWER, |
1724 | (u32) ah->regulatory.power_limit)) != 0) { | 1712 | (u32) ah->regulatory.power_limit)); |
1725 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1726 | "Error initializing transmit power\n"); | ||
1727 | return false; | ||
1728 | } | ||
1729 | 1713 | ||
1730 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; | 1714 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; |
1731 | if (IS_CHAN_B(chan)) | 1715 | if (IS_CHAN_B(chan)) |
@@ -2313,13 +2297,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2313 | 2297 | ||
2314 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | 2298 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); |
2315 | 2299 | ||
2316 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 2300 | if (AR_SREV_9280_10_OR_LATER(ah)) |
2317 | if (!(ath9k_hw_ar9280_set_channel(ah, chan))) | 2301 | ath9k_hw_ar9280_set_channel(ah, chan); |
2318 | return -EIO; | 2302 | else |
2319 | } else { | ||
2320 | if (!(ath9k_hw_set_channel(ah, chan))) | 2303 | if (!(ath9k_hw_set_channel(ah, chan))) |
2321 | return -EIO; | 2304 | return -EIO; |
2322 | } | ||
2323 | 2305 | ||
2324 | for (i = 0; i < AR_NUM_DCU; i++) | 2306 | for (i = 0; i < AR_NUM_DCU; i++) |
2325 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | 2307 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); |
@@ -3750,22 +3732,19 @@ bool ath9k_hw_disable(struct ath_hw *ah) | |||
3750 | return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); | 3732 | return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); |
3751 | } | 3733 | } |
3752 | 3734 | ||
3753 | bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) | 3735 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) |
3754 | { | 3736 | { |
3755 | struct ath9k_channel *chan = ah->curchan; | 3737 | struct ath9k_channel *chan = ah->curchan; |
3756 | struct ieee80211_channel *channel = chan->chan; | 3738 | struct ieee80211_channel *channel = chan->chan; |
3757 | 3739 | ||
3758 | ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); | 3740 | ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); |
3759 | 3741 | ||
3760 | if (ah->eep_ops->set_txpower(ah, chan, | 3742 | ah->eep_ops->set_txpower(ah, chan, |
3761 | ath9k_regd_get_ctl(&ah->regulatory, chan), | 3743 | ath9k_regd_get_ctl(&ah->regulatory, chan), |
3762 | channel->max_antenna_gain * 2, | 3744 | channel->max_antenna_gain * 2, |
3763 | channel->max_power * 2, | 3745 | channel->max_power * 2, |
3764 | min((u32) MAX_RATE_POWER, | 3746 | min((u32) MAX_RATE_POWER, |
3765 | (u32) ah->regulatory.power_limit)) != 0) | 3747 | (u32) ah->regulatory.power_limit)); |
3766 | return false; | ||
3767 | |||
3768 | return true; | ||
3769 | } | 3748 | } |
3770 | 3749 | ||
3771 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) | 3750 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ddb24c47ebcf..dd8508ef6e05 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -590,7 +590,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah); | |||
590 | void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); | 590 | void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); |
591 | bool ath9k_hw_phy_disable(struct ath_hw *ah); | 591 | bool ath9k_hw_phy_disable(struct ath_hw *ah); |
592 | bool ath9k_hw_disable(struct ath_hw *ah); | 592 | bool ath9k_hw_disable(struct ath_hw *ah); |
593 | bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); | 593 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); |
594 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); | 594 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); |
595 | void ath9k_hw_setopmode(struct ath_hw *ah); | 595 | void ath9k_hw_setopmode(struct ath_hw *ah); |
596 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); | 596 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); |
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c index 5ec9ce91d979..aaa941561c36 100644 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c | |||
@@ -96,9 +96,8 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
96 | return true; | 96 | return true; |
97 | } | 97 | } |
98 | 98 | ||
99 | bool | 99 | void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, |
100 | ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | 100 | struct ath9k_channel *chan) |
101 | struct ath9k_channel *chan) | ||
102 | { | 101 | { |
103 | u16 bMode, fracMode, aModeRefSel = 0; | 102 | u16 bMode, fracMode, aModeRefSel = 0; |
104 | u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; | 103 | u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; |
@@ -169,8 +168,6 @@ ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | |||
169 | 168 | ||
170 | ah->curchan = chan; | 169 | ah->curchan = chan; |
171 | ah->curchan_rad_index = -1; | 170 | ah->curchan_rad_index = -1; |
172 | |||
173 | return true; | ||
174 | } | 171 | } |
175 | 172 | ||
176 | static void | 173 | static void |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 296d0e985f25..c70f530642f6 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -17,7 +17,7 @@ | |||
17 | #ifndef PHY_H | 17 | #ifndef PHY_H |
18 | #define PHY_H | 18 | #define PHY_H |
19 | 19 | ||
20 | bool ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | 20 | void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, |
21 | struct ath9k_channel | 21 | struct ath9k_channel |
22 | *chan); | 22 | *chan); |
23 | bool ath9k_hw_set_channel(struct ath_hw *ah, | 23 | bool ath9k_hw_set_channel(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 41f1d66cfeba..5b0c6e5bda92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -1110,6 +1110,11 @@ static void iwl3945_nic_config(struct iwl_priv *priv) | |||
1110 | 1110 | ||
1111 | spin_lock_irqsave(&priv->lock, flags); | 1111 | spin_lock_irqsave(&priv->lock, flags); |
1112 | 1112 | ||
1113 | /* Determine HW type */ | ||
1114 | pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); | ||
1115 | |||
1116 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); | ||
1117 | |||
1113 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) | 1118 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) |
1114 | IWL_DEBUG_INFO(priv, "RTP type \n"); | 1119 | IWL_DEBUG_INFO(priv, "RTP type \n"); |
1115 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { | 1120 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { |
@@ -1163,7 +1168,6 @@ static void iwl3945_nic_config(struct iwl_priv *priv) | |||
1163 | 1168 | ||
1164 | int iwl3945_hw_nic_init(struct iwl_priv *priv) | 1169 | int iwl3945_hw_nic_init(struct iwl_priv *priv) |
1165 | { | 1170 | { |
1166 | u8 rev_id; | ||
1167 | int rc; | 1171 | int rc; |
1168 | unsigned long flags; | 1172 | unsigned long flags; |
1169 | struct iwl_rx_queue *rxq = &priv->rxq; | 1173 | struct iwl_rx_queue *rxq = &priv->rxq; |
@@ -1172,12 +1176,6 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) | |||
1172 | priv->cfg->ops->lib->apm_ops.init(priv); | 1176 | priv->cfg->ops->lib->apm_ops.init(priv); |
1173 | spin_unlock_irqrestore(&priv->lock, flags); | 1177 | spin_unlock_irqrestore(&priv->lock, flags); |
1174 | 1178 | ||
1175 | /* Determine HW type */ | ||
1176 | rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); | ||
1177 | if (rc) | ||
1178 | return rc; | ||
1179 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); | ||
1180 | |||
1181 | rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | 1179 | rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); |
1182 | if (rc) | 1180 | if (rc) |
1183 | return rc; | 1181 | return rc; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 0a71bb55d0ee..4c88e8715df2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -100,6 +100,7 @@ struct iwl_scale_tbl_info { | |||
100 | u8 is_fat; /* 1 = 40 MHz channel width */ | 100 | u8 is_fat; /* 1 = 40 MHz channel width */ |
101 | u8 is_dup; /* 1 = duplicated data streams */ | 101 | u8 is_dup; /* 1 = duplicated data streams */ |
102 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | 102 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ |
103 | u8 max_search; /* maximun number of tables we can search */ | ||
103 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | 104 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ |
104 | u32 current_rate; /* rate_n_flags, uCode API format */ | 105 | u32 current_rate; /* rate_n_flags, uCode API format */ |
105 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | 106 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ |
@@ -160,6 +161,7 @@ struct iwl_lq_sta { | |||
160 | #ifdef CONFIG_MAC80211_DEBUGFS | 161 | #ifdef CONFIG_MAC80211_DEBUGFS |
161 | struct dentry *rs_sta_dbgfs_scale_table_file; | 162 | struct dentry *rs_sta_dbgfs_scale_table_file; |
162 | struct dentry *rs_sta_dbgfs_stats_table_file; | 163 | struct dentry *rs_sta_dbgfs_stats_table_file; |
164 | struct dentry *rs_sta_dbgfs_rate_scale_data_file; | ||
163 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | 165 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; |
164 | u32 dbg_fixed_rate; | 166 | u32 dbg_fixed_rate; |
165 | #endif | 167 | #endif |
@@ -579,6 +581,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
579 | tbl->is_dup = 0; | 581 | tbl->is_dup = 0; |
580 | tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); | 582 | tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); |
581 | tbl->lq_type = LQ_NONE; | 583 | tbl->lq_type = LQ_NONE; |
584 | tbl->max_search = IWL_MAX_SEARCH; | ||
582 | 585 | ||
583 | /* legacy rate format */ | 586 | /* legacy rate format */ |
584 | if (!(rate_n_flags & RATE_MCS_HT_MSK)) { | 587 | if (!(rate_n_flags & RATE_MCS_HT_MSK)) { |
@@ -612,8 +615,10 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
612 | tbl->lq_type = LQ_MIMO2; | 615 | tbl->lq_type = LQ_MIMO2; |
613 | /* MIMO3 */ | 616 | /* MIMO3 */ |
614 | } else { | 617 | } else { |
615 | if (num_of_ant == 3) | 618 | if (num_of_ant == 3) { |
619 | tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; | ||
616 | tbl->lq_type = LQ_MIMO3; | 620 | tbl->lq_type = LQ_MIMO3; |
621 | } | ||
617 | } | 622 | } |
618 | } | 623 | } |
619 | return 0; | 624 | return 0; |
@@ -771,6 +776,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
771 | 776 | ||
772 | tbl->is_fat = 0; | 777 | tbl->is_fat = 0; |
773 | tbl->is_SGI = 0; | 778 | tbl->is_SGI = 0; |
779 | tbl->max_search = IWL_MAX_SEARCH; | ||
774 | } | 780 | } |
775 | 781 | ||
776 | rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type); | 782 | rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type); |
@@ -1026,6 +1032,7 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, | |||
1026 | lq_sta->total_failed = 0; | 1032 | lq_sta->total_failed = 0; |
1027 | lq_sta->total_success = 0; | 1033 | lq_sta->total_success = 0; |
1028 | lq_sta->flush_timer = jiffies; | 1034 | lq_sta->flush_timer = jiffies; |
1035 | lq_sta->action_counter = 0; | ||
1029 | } | 1036 | } |
1030 | 1037 | ||
1031 | /* | 1038 | /* |
@@ -1205,6 +1212,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, | |||
1205 | tbl->lq_type = LQ_MIMO2; | 1212 | tbl->lq_type = LQ_MIMO2; |
1206 | tbl->is_dup = lq_sta->is_dup; | 1213 | tbl->is_dup = lq_sta->is_dup; |
1207 | tbl->action = 0; | 1214 | tbl->action = 0; |
1215 | tbl->max_search = IWL_MAX_SEARCH; | ||
1208 | rate_mask = lq_sta->active_mimo2_rate; | 1216 | rate_mask = lq_sta->active_mimo2_rate; |
1209 | 1217 | ||
1210 | if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) | 1218 | if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) |
@@ -1270,6 +1278,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, | |||
1270 | tbl->lq_type = LQ_MIMO3; | 1278 | tbl->lq_type = LQ_MIMO3; |
1271 | tbl->is_dup = lq_sta->is_dup; | 1279 | tbl->is_dup = lq_sta->is_dup; |
1272 | tbl->action = 0; | 1280 | tbl->action = 0; |
1281 | tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; | ||
1273 | rate_mask = lq_sta->active_mimo3_rate; | 1282 | rate_mask = lq_sta->active_mimo3_rate; |
1274 | 1283 | ||
1275 | if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) | 1284 | if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) |
@@ -1328,6 +1337,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, | |||
1328 | tbl->is_dup = lq_sta->is_dup; | 1337 | tbl->is_dup = lq_sta->is_dup; |
1329 | tbl->lq_type = LQ_SISO; | 1338 | tbl->lq_type = LQ_SISO; |
1330 | tbl->action = 0; | 1339 | tbl->action = 0; |
1340 | tbl->max_search = IWL_MAX_SEARCH; | ||
1331 | rate_mask = lq_sta->active_siso_rate; | 1341 | rate_mask = lq_sta->active_siso_rate; |
1332 | 1342 | ||
1333 | if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) | 1343 | if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) |
@@ -1384,15 +1394,15 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1384 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1394 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1385 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1395 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1386 | int ret = 0; | 1396 | int ret = 0; |
1397 | u8 update_search_tbl_counter = 0; | ||
1387 | 1398 | ||
1388 | for (; ;) { | 1399 | for (; ;) { |
1400 | lq_sta->action_counter++; | ||
1389 | switch (tbl->action) { | 1401 | switch (tbl->action) { |
1390 | case IWL_LEGACY_SWITCH_ANTENNA1: | 1402 | case IWL_LEGACY_SWITCH_ANTENNA1: |
1391 | case IWL_LEGACY_SWITCH_ANTENNA2: | 1403 | case IWL_LEGACY_SWITCH_ANTENNA2: |
1392 | IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n"); | 1404 | IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n"); |
1393 | 1405 | ||
1394 | lq_sta->action_counter++; | ||
1395 | |||
1396 | if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && | 1406 | if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && |
1397 | tx_chains_num <= 1) || | 1407 | tx_chains_num <= 1) || |
1398 | (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && | 1408 | (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && |
@@ -1408,6 +1418,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1408 | 1418 | ||
1409 | if (rs_toggle_antenna(valid_tx_ant, | 1419 | if (rs_toggle_antenna(valid_tx_ant, |
1410 | &search_tbl->current_rate, search_tbl)) { | 1420 | &search_tbl->current_rate, search_tbl)) { |
1421 | update_search_tbl_counter = 1; | ||
1411 | rs_set_expected_tpt_table(lq_sta, search_tbl); | 1422 | rs_set_expected_tpt_table(lq_sta, search_tbl); |
1412 | goto out; | 1423 | goto out; |
1413 | } | 1424 | } |
@@ -1489,6 +1500,8 @@ out: | |||
1489 | tbl->action++; | 1500 | tbl->action++; |
1490 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) | 1501 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) |
1491 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | 1502 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; |
1503 | if (update_search_tbl_counter) | ||
1504 | search_tbl->action = tbl->action; | ||
1492 | return 0; | 1505 | return 0; |
1493 | 1506 | ||
1494 | } | 1507 | } |
@@ -1511,6 +1524,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1511 | u8 start_action = tbl->action; | 1524 | u8 start_action = tbl->action; |
1512 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1525 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1513 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1526 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1527 | u8 update_search_tbl_counter = 0; | ||
1514 | int ret; | 1528 | int ret; |
1515 | 1529 | ||
1516 | for (;;) { | 1530 | for (;;) { |
@@ -1531,8 +1545,10 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1531 | 1545 | ||
1532 | memcpy(search_tbl, tbl, sz); | 1546 | memcpy(search_tbl, tbl, sz); |
1533 | if (rs_toggle_antenna(valid_tx_ant, | 1547 | if (rs_toggle_antenna(valid_tx_ant, |
1534 | &search_tbl->current_rate, search_tbl)) | 1548 | &search_tbl->current_rate, search_tbl)) { |
1549 | update_search_tbl_counter = 1; | ||
1535 | goto out; | 1550 | goto out; |
1551 | } | ||
1536 | break; | 1552 | break; |
1537 | case IWL_SISO_SWITCH_MIMO2_AB: | 1553 | case IWL_SISO_SWITCH_MIMO2_AB: |
1538 | case IWL_SISO_SWITCH_MIMO2_AC: | 1554 | case IWL_SISO_SWITCH_MIMO2_AC: |
@@ -1586,6 +1602,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1586 | search_tbl->current_rate = | 1602 | search_tbl->current_rate = |
1587 | rate_n_flags_from_tbl(priv, search_tbl, | 1603 | rate_n_flags_from_tbl(priv, search_tbl, |
1588 | index, is_green); | 1604 | index, is_green); |
1605 | update_search_tbl_counter = 1; | ||
1589 | goto out; | 1606 | goto out; |
1590 | case IWL_SISO_SWITCH_MIMO3_ABC: | 1607 | case IWL_SISO_SWITCH_MIMO3_ABC: |
1591 | IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n"); | 1608 | IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n"); |
@@ -1617,6 +1634,9 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1617 | tbl->action++; | 1634 | tbl->action++; |
1618 | if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC) | 1635 | if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC) |
1619 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1636 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1637 | if (update_search_tbl_counter) | ||
1638 | search_tbl->action = tbl->action; | ||
1639 | |||
1620 | return 0; | 1640 | return 0; |
1621 | } | 1641 | } |
1622 | 1642 | ||
@@ -1638,6 +1658,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1638 | u8 start_action = tbl->action; | 1658 | u8 start_action = tbl->action; |
1639 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1659 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1640 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1660 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1661 | u8 update_search_tbl_counter = 0; | ||
1641 | int ret; | 1662 | int ret; |
1642 | 1663 | ||
1643 | for (;;) { | 1664 | for (;;) { |
@@ -1655,8 +1676,10 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1655 | 1676 | ||
1656 | memcpy(search_tbl, tbl, sz); | 1677 | memcpy(search_tbl, tbl, sz); |
1657 | if (rs_toggle_antenna(valid_tx_ant, | 1678 | if (rs_toggle_antenna(valid_tx_ant, |
1658 | &search_tbl->current_rate, search_tbl)) | 1679 | &search_tbl->current_rate, search_tbl)) { |
1680 | update_search_tbl_counter = 1; | ||
1659 | goto out; | 1681 | goto out; |
1682 | } | ||
1660 | break; | 1683 | break; |
1661 | case IWL_MIMO2_SWITCH_SISO_A: | 1684 | case IWL_MIMO2_SWITCH_SISO_A: |
1662 | case IWL_MIMO2_SWITCH_SISO_B: | 1685 | case IWL_MIMO2_SWITCH_SISO_B: |
@@ -1713,6 +1736,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1713 | search_tbl->current_rate = | 1736 | search_tbl->current_rate = |
1714 | rate_n_flags_from_tbl(priv, search_tbl, | 1737 | rate_n_flags_from_tbl(priv, search_tbl, |
1715 | index, is_green); | 1738 | index, is_green); |
1739 | update_search_tbl_counter = 1; | ||
1716 | goto out; | 1740 | goto out; |
1717 | 1741 | ||
1718 | case IWL_MIMO2_SWITCH_MIMO3_ABC: | 1742 | case IWL_MIMO2_SWITCH_MIMO3_ABC: |
@@ -1745,6 +1769,9 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1745 | tbl->action++; | 1769 | tbl->action++; |
1746 | if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) | 1770 | if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) |
1747 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | 1771 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; |
1772 | if (update_search_tbl_counter) | ||
1773 | search_tbl->action = tbl->action; | ||
1774 | |||
1748 | return 0; | 1775 | return 0; |
1749 | 1776 | ||
1750 | } | 1777 | } |
@@ -1768,6 +1795,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1768 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1795 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1769 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1796 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1770 | int ret; | 1797 | int ret; |
1798 | u8 update_search_tbl_counter = 0; | ||
1771 | 1799 | ||
1772 | for (;;) { | 1800 | for (;;) { |
1773 | lq_sta->action_counter++; | 1801 | lq_sta->action_counter++; |
@@ -1866,6 +1894,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1866 | search_tbl->current_rate = | 1894 | search_tbl->current_rate = |
1867 | rate_n_flags_from_tbl(priv, search_tbl, | 1895 | rate_n_flags_from_tbl(priv, search_tbl, |
1868 | index, is_green); | 1896 | index, is_green); |
1897 | update_search_tbl_counter = 1; | ||
1869 | goto out; | 1898 | goto out; |
1870 | } | 1899 | } |
1871 | tbl->action++; | 1900 | tbl->action++; |
@@ -1882,6 +1911,9 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1882 | tbl->action++; | 1911 | tbl->action++; |
1883 | if (tbl->action > IWL_MIMO3_SWITCH_GI) | 1912 | if (tbl->action > IWL_MIMO3_SWITCH_GI) |
1884 | tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; | 1913 | tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; |
1914 | if (update_search_tbl_counter) | ||
1915 | search_tbl->action = tbl->action; | ||
1916 | |||
1885 | return 0; | 1917 | return 0; |
1886 | 1918 | ||
1887 | } | 1919 | } |
@@ -2326,8 +2358,7 @@ lq_update: | |||
2326 | * before next round of mode comparisons. */ | 2358 | * before next round of mode comparisons. */ |
2327 | tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); | 2359 | tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); |
2328 | if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) && | 2360 | if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) && |
2329 | lq_sta->action_counter >= 1) { | 2361 | lq_sta->action_counter > tbl1->max_search) { |
2330 | lq_sta->action_counter = 0; | ||
2331 | IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n"); | 2362 | IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n"); |
2332 | rs_set_stay_in_table(priv, 1, lq_sta); | 2363 | rs_set_stay_in_table(priv, 1, lq_sta); |
2333 | } | 2364 | } |
@@ -2336,7 +2367,7 @@ lq_update: | |||
2336 | * have been tried and compared, stay in this best modulation | 2367 | * have been tried and compared, stay in this best modulation |
2337 | * mode for a while before next round of mode comparisons. */ | 2368 | * mode for a while before next round of mode comparisons. */ |
2338 | if (lq_sta->enable_counter && | 2369 | if (lq_sta->enable_counter && |
2339 | (lq_sta->action_counter >= IWL_ACTION_LIMIT)) { | 2370 | (lq_sta->action_counter >= tbl1->max_search)) { |
2340 | if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && | 2371 | if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && |
2341 | (lq_sta->tx_agg_tid_en & (1 << tid)) && | 2372 | (lq_sta->tx_agg_tid_en & (1 << tid)) && |
2342 | (tid != MAX_TID_COUNT)) { | 2373 | (tid != MAX_TID_COUNT)) { |
@@ -2350,7 +2381,6 @@ lq_update: | |||
2350 | lq_sta, sta); | 2381 | lq_sta, sta); |
2351 | } | 2382 | } |
2352 | } | 2383 | } |
2353 | lq_sta->action_counter = 0; | ||
2354 | rs_set_stay_in_table(priv, 0, lq_sta); | 2384 | rs_set_stay_in_table(priv, 0, lq_sta); |
2355 | } | 2385 | } |
2356 | } | 2386 | } |
@@ -2955,6 +2985,43 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = { | |||
2955 | .open = open_file_generic, | 2985 | .open = open_file_generic, |
2956 | }; | 2986 | }; |
2957 | 2987 | ||
2988 | static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, | ||
2989 | char __user *user_buf, size_t count, loff_t *ppos) | ||
2990 | { | ||
2991 | char buff[120]; | ||
2992 | int desc = 0; | ||
2993 | ssize_t ret; | ||
2994 | |||
2995 | struct iwl_lq_sta *lq_sta = file->private_data; | ||
2996 | struct iwl_priv *priv; | ||
2997 | struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; | ||
2998 | |||
2999 | priv = lq_sta->drv; | ||
3000 | |||
3001 | if (is_Ht(tbl->lq_type)) | ||
3002 | desc += sprintf(buff+desc, | ||
3003 | "Bit Rate= %d Mb/s\n", | ||
3004 | tbl->expected_tpt[lq_sta->last_txrate_idx]); | ||
3005 | else | ||
3006 | desc += sprintf(buff+desc, | ||
3007 | "Bit Rate= %d Mb/s\n", | ||
3008 | iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); | ||
3009 | desc += sprintf(buff+desc, | ||
3010 | "Signal Level= %d dBm\tNoise Level= %d dBm\n", | ||
3011 | priv->last_rx_rssi, priv->last_rx_noise); | ||
3012 | desc += sprintf(buff+desc, | ||
3013 | "Tsf= 0x%llx\tBeacon time= 0x%08X\n", | ||
3014 | priv->last_tsf, priv->last_beacon_time); | ||
3015 | |||
3016 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); | ||
3017 | return ret; | ||
3018 | } | ||
3019 | |||
3020 | static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { | ||
3021 | .read = rs_sta_dbgfs_rate_scale_data_read, | ||
3022 | .open = open_file_generic, | ||
3023 | }; | ||
3024 | |||
2958 | static void rs_add_debugfs(void *priv, void *priv_sta, | 3025 | static void rs_add_debugfs(void *priv, void *priv_sta, |
2959 | struct dentry *dir) | 3026 | struct dentry *dir) |
2960 | { | 3027 | { |
@@ -2965,6 +3032,9 @@ static void rs_add_debugfs(void *priv, void *priv_sta, | |||
2965 | lq_sta->rs_sta_dbgfs_stats_table_file = | 3032 | lq_sta->rs_sta_dbgfs_stats_table_file = |
2966 | debugfs_create_file("rate_stats_table", 0600, dir, | 3033 | debugfs_create_file("rate_stats_table", 0600, dir, |
2967 | lq_sta, &rs_sta_dbgfs_stats_table_ops); | 3034 | lq_sta, &rs_sta_dbgfs_stats_table_ops); |
3035 | lq_sta->rs_sta_dbgfs_rate_scale_data_file = | ||
3036 | debugfs_create_file("rate_scale_data", 0600, dir, | ||
3037 | lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); | ||
2968 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = | 3038 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = |
2969 | debugfs_create_u8("tx_agg_tid_enable", 0600, dir, | 3039 | debugfs_create_u8("tx_agg_tid_enable", 0600, dir, |
2970 | &lq_sta->tx_agg_tid_en); | 3040 | &lq_sta->tx_agg_tid_en); |
@@ -2976,6 +3046,7 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) | |||
2976 | struct iwl_lq_sta *lq_sta = priv_sta; | 3046 | struct iwl_lq_sta *lq_sta = priv_sta; |
2977 | debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); | 3047 | debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); |
2978 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); | 3048 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); |
3049 | debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file); | ||
2979 | debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); | 3050 | debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); |
2980 | } | 3051 | } |
2981 | #endif | 3052 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index f875136bc5dc..25050bf315a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -275,6 +275,8 @@ enum { | |||
275 | #define IWL_MIMO3_SWITCH_GI 8 | 275 | #define IWL_MIMO3_SWITCH_GI 8 |
276 | 276 | ||
277 | 277 | ||
278 | #define IWL_MAX_11N_MIMO3_SEARCH IWL_MIMO3_SWITCH_GI | ||
279 | #define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_MIMO3_ABC | ||
278 | 280 | ||
279 | /*FIXME:RS:add possible actions for MIMO3*/ | 281 | /*FIXME:RS:add possible actions for MIMO3*/ |
280 | 282 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6cdee0b4b486..3ebf6cf53a51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -190,8 +190,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
190 | 190 | ||
191 | priv->cfg->ops->smgmt->clear_station_table(priv); | 191 | priv->cfg->ops->smgmt->clear_station_table(priv); |
192 | 192 | ||
193 | if (!priv->error_recovering) | 193 | priv->start_calib = 0; |
194 | priv->start_calib = 0; | ||
195 | 194 | ||
196 | /* Add the broadcast address so we can send broadcast frames */ | 195 | /* Add the broadcast address so we can send broadcast frames */ |
197 | if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == | 196 | if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == |
@@ -967,23 +966,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv) | |||
967 | tasklet_kill(&priv->irq_tasklet); | 966 | tasklet_kill(&priv->irq_tasklet); |
968 | } | 967 | } |
969 | 968 | ||
970 | static void iwl_error_recovery(struct iwl_priv *priv) | ||
971 | { | ||
972 | unsigned long flags; | ||
973 | |||
974 | memcpy(&priv->staging_rxon, &priv->recovery_rxon, | ||
975 | sizeof(priv->staging_rxon)); | ||
976 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
977 | iwlcore_commit_rxon(priv); | ||
978 | |||
979 | iwl_rxon_add_station(priv, priv->bssid, 1); | ||
980 | |||
981 | spin_lock_irqsave(&priv->lock, flags); | ||
982 | priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id); | ||
983 | priv->error_recovering = 0; | ||
984 | spin_unlock_irqrestore(&priv->lock, flags); | ||
985 | } | ||
986 | |||
987 | static void iwl_irq_tasklet(struct iwl_priv *priv) | 969 | static void iwl_irq_tasklet(struct iwl_priv *priv) |
988 | { | 970 | { |
989 | u32 inta, handled = 0; | 971 | u32 inta, handled = 0; |
@@ -1514,9 +1496,6 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
1514 | set_bit(STATUS_READY, &priv->status); | 1496 | set_bit(STATUS_READY, &priv->status); |
1515 | wake_up_interruptible(&priv->wait_command_queue); | 1497 | wake_up_interruptible(&priv->wait_command_queue); |
1516 | 1498 | ||
1517 | if (priv->error_recovering) | ||
1518 | iwl_error_recovery(priv); | ||
1519 | |||
1520 | iwl_power_update_mode(priv, 1); | 1499 | iwl_power_update_mode(priv, 1); |
1521 | 1500 | ||
1522 | /* reassociate for ADHOC mode */ | 1501 | /* reassociate for ADHOC mode */ |
@@ -1715,9 +1694,6 @@ static int __iwl_up(struct iwl_priv *priv) | |||
1715 | continue; | 1694 | continue; |
1716 | } | 1695 | } |
1717 | 1696 | ||
1718 | /* Clear out the uCode error bit if it is set */ | ||
1719 | clear_bit(STATUS_FW_ERROR, &priv->status); | ||
1720 | |||
1721 | /* start card; "initialize" will load runtime ucode */ | 1697 | /* start card; "initialize" will load runtime ucode */ |
1722 | iwl_nic_start(priv); | 1698 | iwl_nic_start(priv); |
1723 | 1699 | ||
@@ -1812,8 +1788,17 @@ static void iwl_bg_restart(struct work_struct *data) | |||
1812 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 1788 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
1813 | return; | 1789 | return; |
1814 | 1790 | ||
1815 | iwl_down(priv); | 1791 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { |
1816 | queue_work(priv->workqueue, &priv->up); | 1792 | mutex_lock(&priv->mutex); |
1793 | priv->vif = NULL; | ||
1794 | priv->is_open = 0; | ||
1795 | mutex_unlock(&priv->mutex); | ||
1796 | iwl_down(priv); | ||
1797 | ieee80211_restart_hw(priv->hw); | ||
1798 | } else { | ||
1799 | iwl_down(priv); | ||
1800 | queue_work(priv->workqueue, &priv->up); | ||
1801 | } | ||
1817 | } | 1802 | } |
1818 | 1803 | ||
1819 | static void iwl_bg_rx_replenish(struct work_struct *data) | 1804 | static void iwl_bg_rx_replenish(struct work_struct *data) |
@@ -1853,7 +1838,6 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
1853 | if (!priv->vif || !priv->is_open) | 1838 | if (!priv->vif || !priv->is_open) |
1854 | return; | 1839 | return; |
1855 | 1840 | ||
1856 | iwl_power_cancel_timeout(priv); | ||
1857 | iwl_scan_cancel_timeout(priv, 200); | 1841 | iwl_scan_cancel_timeout(priv, 200); |
1858 | 1842 | ||
1859 | conf = ieee80211_get_hw_conf(priv->hw); | 1843 | conf = ieee80211_get_hw_conf(priv->hw); |
@@ -1929,7 +1913,7 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
1929 | * If chain noise has already been run, then we need to enable | 1913 | * If chain noise has already been run, then we need to enable |
1930 | * power management here */ | 1914 | * power management here */ |
1931 | if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) | 1915 | if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) |
1932 | iwl_power_enable_management(priv); | 1916 | iwl_power_update_mode(priv, 0); |
1933 | 1917 | ||
1934 | /* Enable Rx differential gain and sensitivity calibrations */ | 1918 | /* Enable Rx differential gain and sensitivity calibrations */ |
1935 | iwl_chain_noise_reset(priv); | 1919 | iwl_chain_noise_reset(priv); |
@@ -2007,10 +1991,8 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) | |||
2007 | 1991 | ||
2008 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 1992 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2009 | 1993 | ||
2010 | if (!priv->is_open) { | 1994 | if (!priv->is_open) |
2011 | IWL_DEBUG_MAC80211(priv, "leave - skip\n"); | ||
2012 | return; | 1995 | return; |
2013 | } | ||
2014 | 1996 | ||
2015 | priv->is_open = 0; | 1997 | priv->is_open = 0; |
2016 | 1998 | ||
@@ -2482,32 +2464,37 @@ static ssize_t show_power_level(struct device *d, | |||
2482 | { | 2464 | { |
2483 | struct iwl_priv *priv = dev_get_drvdata(d); | 2465 | struct iwl_priv *priv = dev_get_drvdata(d); |
2484 | int mode = priv->power_data.user_power_setting; | 2466 | int mode = priv->power_data.user_power_setting; |
2485 | int system = priv->power_data.system_power_setting; | ||
2486 | int level = priv->power_data.power_mode; | 2467 | int level = priv->power_data.power_mode; |
2487 | char *p = buf; | 2468 | char *p = buf; |
2488 | 2469 | ||
2489 | switch (system) { | 2470 | p += sprintf(p, "INDEX:%d\t", level); |
2490 | case IWL_POWER_SYS_AUTO: | 2471 | p += sprintf(p, "USER:%d\n", mode); |
2491 | p += sprintf(p, "SYSTEM:auto"); | ||
2492 | break; | ||
2493 | case IWL_POWER_SYS_AC: | ||
2494 | p += sprintf(p, "SYSTEM:ac"); | ||
2495 | break; | ||
2496 | case IWL_POWER_SYS_BATTERY: | ||
2497 | p += sprintf(p, "SYSTEM:battery"); | ||
2498 | break; | ||
2499 | } | ||
2500 | |||
2501 | p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ? | ||
2502 | "fixed" : "auto"); | ||
2503 | p += sprintf(p, "\tINDEX:%d", level); | ||
2504 | p += sprintf(p, "\n"); | ||
2505 | return p - buf + 1; | 2472 | return p - buf + 1; |
2506 | } | 2473 | } |
2507 | 2474 | ||
2508 | static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, | 2475 | static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, |
2509 | store_power_level); | 2476 | store_power_level); |
2510 | 2477 | ||
2478 | static ssize_t show_qos(struct device *d, | ||
2479 | struct device_attribute *attr, char *buf) | ||
2480 | { | ||
2481 | struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; | ||
2482 | char *p = buf; | ||
2483 | int q; | ||
2484 | |||
2485 | for (q = 0; q < AC_NUM; q++) { | ||
2486 | p += sprintf(p, "\tcw_min\tcw_max\taifsn\ttxop\n"); | ||
2487 | p += sprintf(p, "AC[%d]\t%u\t%u\t%u\t%u\n", q, | ||
2488 | priv->qos_data.def_qos_parm.ac[q].cw_min, | ||
2489 | priv->qos_data.def_qos_parm.ac[q].cw_max, | ||
2490 | priv->qos_data.def_qos_parm.ac[q].aifsn, | ||
2491 | priv->qos_data.def_qos_parm.ac[q].edca_txop); | ||
2492 | } | ||
2493 | |||
2494 | return p - buf + 1; | ||
2495 | } | ||
2496 | |||
2497 | static DEVICE_ATTR(qos, S_IRUGO, show_qos, NULL); | ||
2511 | 2498 | ||
2512 | static ssize_t show_statistics(struct device *d, | 2499 | static ssize_t show_statistics(struct device *d, |
2513 | struct device_attribute *attr, char *buf) | 2500 | struct device_attribute *attr, char *buf) |
@@ -2570,7 +2557,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
2570 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); | 2557 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); |
2571 | 2558 | ||
2572 | iwl_setup_scan_deferred_work(priv); | 2559 | iwl_setup_scan_deferred_work(priv); |
2573 | iwl_setup_power_deferred_work(priv); | ||
2574 | 2560 | ||
2575 | if (priv->cfg->ops->lib->setup_deferred_work) | 2561 | if (priv->cfg->ops->lib->setup_deferred_work) |
2576 | priv->cfg->ops->lib->setup_deferred_work(priv); | 2562 | priv->cfg->ops->lib->setup_deferred_work(priv); |
@@ -2590,7 +2576,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
2590 | 2576 | ||
2591 | cancel_delayed_work_sync(&priv->init_alive_start); | 2577 | cancel_delayed_work_sync(&priv->init_alive_start); |
2592 | cancel_delayed_work(&priv->scan_check); | 2578 | cancel_delayed_work(&priv->scan_check); |
2593 | cancel_delayed_work_sync(&priv->set_power_save); | ||
2594 | cancel_delayed_work(&priv->alive_start); | 2579 | cancel_delayed_work(&priv->alive_start); |
2595 | cancel_work_sync(&priv->beacon_update); | 2580 | cancel_work_sync(&priv->beacon_update); |
2596 | del_timer_sync(&priv->statistics_periodic); | 2581 | del_timer_sync(&priv->statistics_periodic); |
@@ -2607,7 +2592,7 @@ static struct attribute *iwl_sysfs_entries[] = { | |||
2607 | &dev_attr_debug_level.attr, | 2592 | &dev_attr_debug_level.attr, |
2608 | #endif | 2593 | #endif |
2609 | &dev_attr_version.attr, | 2594 | &dev_attr_version.attr, |
2610 | 2595 | &dev_attr_qos.attr, | |
2611 | NULL | 2596 | NULL |
2612 | }; | 2597 | }; |
2613 | 2598 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 735f3f19928c..a5d63672ad39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -857,7 +857,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
857 | priv->cfg->ops->lib->update_chain_flags(priv); | 857 | priv->cfg->ops->lib->update_chain_flags(priv); |
858 | 858 | ||
859 | data->state = IWL_CHAIN_NOISE_DONE; | 859 | data->state = IWL_CHAIN_NOISE_DONE; |
860 | iwl_power_enable_management(priv); | 860 | iwl_power_update_mode(priv, 0); |
861 | } | 861 | } |
862 | EXPORT_SYMBOL(iwl_chain_noise_calibration); | 862 | EXPORT_SYMBOL(iwl_chain_noise_calibration); |
863 | 863 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 1366222bb50a..5393fb3f452c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -273,6 +273,14 @@ void iwl_activate_qos(struct iwl_priv *priv, u8 force) | |||
273 | } | 273 | } |
274 | EXPORT_SYMBOL(iwl_activate_qos); | 274 | EXPORT_SYMBOL(iwl_activate_qos); |
275 | 275 | ||
276 | /* | ||
277 | * AC CWmin CW max AIFSN TXOP Limit TXOP Limit | ||
278 | * (802.11b) (802.11a/g) | ||
279 | * AC_BK 15 1023 7 0 0 | ||
280 | * AC_BE 15 1023 3 0 0 | ||
281 | * AC_VI 7 15 2 6.016ms 3.008ms | ||
282 | * AC_VO 3 7 2 3.264ms 1.504ms | ||
283 | */ | ||
276 | void iwl_reset_qos(struct iwl_priv *priv) | 284 | void iwl_reset_qos(struct iwl_priv *priv) |
277 | { | 285 | { |
278 | u16 cw_min = 15; | 286 | u16 cw_min = 15; |
@@ -304,6 +312,7 @@ void iwl_reset_qos(struct iwl_priv *priv) | |||
304 | if (priv->qos_data.qos_active) | 312 | if (priv->qos_data.qos_active) |
305 | aifs = 3; | 313 | aifs = 3; |
306 | 314 | ||
315 | /* AC_BE */ | ||
307 | priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); | 316 | priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); |
308 | priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); | 317 | priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); |
309 | priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; | 318 | priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; |
@@ -311,6 +320,7 @@ void iwl_reset_qos(struct iwl_priv *priv) | |||
311 | priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; | 320 | priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; |
312 | 321 | ||
313 | if (priv->qos_data.qos_active) { | 322 | if (priv->qos_data.qos_active) { |
323 | /* AC_BK */ | ||
314 | i = 1; | 324 | i = 1; |
315 | priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); | 325 | priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); |
316 | priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); | 326 | priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); |
@@ -318,11 +328,12 @@ void iwl_reset_qos(struct iwl_priv *priv) | |||
318 | priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; | 328 | priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; |
319 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | 329 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; |
320 | 330 | ||
331 | /* AC_VI */ | ||
321 | i = 2; | 332 | i = 2; |
322 | priv->qos_data.def_qos_parm.ac[i].cw_min = | 333 | priv->qos_data.def_qos_parm.ac[i].cw_min = |
323 | cpu_to_le16((cw_min + 1) / 2 - 1); | 334 | cpu_to_le16((cw_min + 1) / 2 - 1); |
324 | priv->qos_data.def_qos_parm.ac[i].cw_max = | 335 | priv->qos_data.def_qos_parm.ac[i].cw_max = |
325 | cpu_to_le16(cw_max); | 336 | cpu_to_le16(cw_min); |
326 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; | 337 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; |
327 | if (is_legacy) | 338 | if (is_legacy) |
328 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | 339 | priv->qos_data.def_qos_parm.ac[i].edca_txop = |
@@ -332,11 +343,12 @@ void iwl_reset_qos(struct iwl_priv *priv) | |||
332 | cpu_to_le16(3008); | 343 | cpu_to_le16(3008); |
333 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | 344 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; |
334 | 345 | ||
346 | /* AC_VO */ | ||
335 | i = 3; | 347 | i = 3; |
336 | priv->qos_data.def_qos_parm.ac[i].cw_min = | 348 | priv->qos_data.def_qos_parm.ac[i].cw_min = |
337 | cpu_to_le16((cw_min + 1) / 4 - 1); | 349 | cpu_to_le16((cw_min + 1) / 4 - 1); |
338 | priv->qos_data.def_qos_parm.ac[i].cw_max = | 350 | priv->qos_data.def_qos_parm.ac[i].cw_max = |
339 | cpu_to_le16((cw_max + 1) / 2 - 1); | 351 | cpu_to_le16((cw_min + 1) / 2 - 1); |
340 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; | 352 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; |
341 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | 353 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; |
342 | if (is_legacy) | 354 | if (is_legacy) |
@@ -960,10 +972,10 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
960 | if (iwl_is_monitor_mode(priv) && | 972 | if (iwl_is_monitor_mode(priv) && |
961 | !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && | 973 | !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && |
962 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { | 974 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { |
963 | rx_chain = 0x07 << RXON_RX_CHAIN_VALID_POS; | 975 | rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; |
964 | rx_chain |= 0x06 << RXON_RX_CHAIN_FORCE_SEL_POS; | 976 | rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; |
965 | rx_chain |= 0x07 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 977 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
966 | rx_chain |= 0x01 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 978 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
967 | } | 979 | } |
968 | 980 | ||
969 | priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); | 981 | priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); |
@@ -1120,7 +1132,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) | |||
1120 | } | 1132 | } |
1121 | EXPORT_SYMBOL(iwl_connection_init_rx_config); | 1133 | EXPORT_SYMBOL(iwl_connection_init_rx_config); |
1122 | 1134 | ||
1123 | void iwl_set_rate(struct iwl_priv *priv) | 1135 | static void iwl_set_rate(struct iwl_priv *priv) |
1124 | { | 1136 | { |
1125 | const struct ieee80211_supported_band *hw = NULL; | 1137 | const struct ieee80211_supported_band *hw = NULL; |
1126 | struct ieee80211_rate *rate; | 1138 | struct ieee80211_rate *rate; |
@@ -1166,7 +1178,6 @@ void iwl_set_rate(struct iwl_priv *priv) | |||
1166 | priv->staging_rxon.ofdm_basic_rates = | 1178 | priv->staging_rxon.ofdm_basic_rates = |
1167 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 1179 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
1168 | } | 1180 | } |
1169 | EXPORT_SYMBOL(iwl_set_rate); | ||
1170 | 1181 | ||
1171 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1182 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
1172 | { | 1183 | { |
@@ -1230,11 +1241,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1230 | IWL_DEBUG(priv, IWL_DL_FW_ERRORS, | 1241 | IWL_DEBUG(priv, IWL_DL_FW_ERRORS, |
1231 | "Restarting adapter due to uCode error.\n"); | 1242 | "Restarting adapter due to uCode error.\n"); |
1232 | 1243 | ||
1233 | if (iwl_is_associated(priv)) { | ||
1234 | memcpy(&priv->recovery_rxon, &priv->active_rxon, | ||
1235 | sizeof(priv->recovery_rxon)); | ||
1236 | priv->error_recovering = 1; | ||
1237 | } | ||
1238 | if (priv->cfg->mod_params->restart_fw) | 1244 | if (priv->cfg->mod_params->restart_fw) |
1239 | queue_work(priv->workqueue, &priv->restart); | 1245 | queue_work(priv->workqueue, &priv->restart); |
1240 | } | 1246 | } |
@@ -1358,7 +1364,6 @@ int iwl_init_drv(struct iwl_priv *priv) | |||
1358 | priv->ibss_beacon = NULL; | 1364 | priv->ibss_beacon = NULL; |
1359 | 1365 | ||
1360 | spin_lock_init(&priv->lock); | 1366 | spin_lock_init(&priv->lock); |
1361 | spin_lock_init(&priv->power_data.lock); | ||
1362 | spin_lock_init(&priv->sta_lock); | 1367 | spin_lock_init(&priv->sta_lock); |
1363 | spin_lock_init(&priv->hcmd_lock); | 1368 | spin_lock_init(&priv->hcmd_lock); |
1364 | 1369 | ||
@@ -2226,9 +2231,9 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
2226 | 2231 | ||
2227 | iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; | 2232 | iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; |
2228 | iwl_conf->ht_protection = | 2233 | iwl_conf->ht_protection = |
2229 | bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | 2234 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; |
2230 | iwl_conf->non_GF_STA_present = | 2235 | iwl_conf->non_GF_STA_present = |
2231 | !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | 2236 | !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); |
2232 | 2237 | ||
2233 | rcu_read_unlock(); | 2238 | rcu_read_unlock(); |
2234 | 2239 | ||
@@ -2582,14 +2587,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2582 | iwl_set_rate(priv); | 2587 | iwl_set_rate(priv); |
2583 | } | 2588 | } |
2584 | 2589 | ||
2585 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 2590 | if (changed & IEEE80211_CONF_CHANGE_PS && |
2586 | if (conf->flags & IEEE80211_CONF_PS) | 2591 | priv->iw_mode == NL80211_IFTYPE_STATION) { |
2587 | ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); | 2592 | priv->power_data.power_disabled = |
2588 | else | 2593 | !(conf->flags & IEEE80211_CONF_PS); |
2589 | ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); | 2594 | ret = iwl_power_update_mode(priv, 0); |
2590 | if (ret) | 2595 | if (ret) |
2591 | IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); | 2596 | IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); |
2592 | |||
2593 | } | 2597 | } |
2594 | 2598 | ||
2595 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 2599 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
@@ -2725,21 +2729,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2725 | iwlcore_commit_rxon(priv); | 2729 | iwlcore_commit_rxon(priv); |
2726 | } | 2730 | } |
2727 | 2731 | ||
2728 | iwl_power_update_mode(priv, 0); | ||
2729 | |||
2730 | /* Per mac80211.h: This is only used in IBSS mode... */ | ||
2731 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { | 2732 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { |
2732 | |||
2733 | /* switch to CAM during association period. | ||
2734 | * the ucode will block any association/authentication | ||
2735 | * frome during assiciation period if it can not hear | ||
2736 | * the AP because of PM. the timer enable PM back is | ||
2737 | * association do not complete | ||
2738 | */ | ||
2739 | if (priv->hw->conf.channel->flags & | ||
2740 | (IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_RADAR)) | ||
2741 | iwl_power_disable_management(priv, 3000); | ||
2742 | |||
2743 | IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); | 2733 | IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); |
2744 | mutex_unlock(&priv->mutex); | 2734 | mutex_unlock(&priv->mutex); |
2745 | return; | 2735 | return; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index bd7f9d9616bc..f3544ea559a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -363,8 +363,6 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); | |||
363 | 363 | ||
364 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); | 364 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); |
365 | 365 | ||
366 | void iwl_set_rate(struct iwl_priv *priv); | ||
367 | |||
368 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); | 366 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); |
369 | 367 | ||
370 | static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) | 368 | static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5aa76a706320..3049ba25c3fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -933,7 +933,6 @@ struct iwl_priv { | |||
933 | const struct iwl_rxon_cmd active_rxon; | 933 | const struct iwl_rxon_cmd active_rxon; |
934 | struct iwl_rxon_cmd staging_rxon; | 934 | struct iwl_rxon_cmd staging_rxon; |
935 | 935 | ||
936 | int error_recovering; | ||
937 | struct iwl_rxon_cmd recovery_rxon; | 936 | struct iwl_rxon_cmd recovery_rxon; |
938 | 937 | ||
939 | /* 1st responses from initialize and runtime uCode images. | 938 | /* 1st responses from initialize and runtime uCode images. |
@@ -1076,7 +1075,6 @@ struct iwl_priv { | |||
1076 | 1075 | ||
1077 | struct tasklet_struct irq_tasklet; | 1076 | struct tasklet_struct irq_tasklet; |
1078 | 1077 | ||
1079 | struct delayed_work set_power_save; | ||
1080 | struct delayed_work init_alive_start; | 1078 | struct delayed_work init_alive_start; |
1081 | struct delayed_work alive_start; | 1079 | struct delayed_work alive_start; |
1082 | struct delayed_work scan_check; | 1080 | struct delayed_work scan_check; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 75517d05df08..401438aec19c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -285,7 +285,7 @@ int iwl_eeprom_check_version(struct iwl_priv *priv) | |||
285 | 285 | ||
286 | return 0; | 286 | return 0; |
287 | err: | 287 | err: |
288 | IWL_ERR(priv, "Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", | 288 | IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", |
289 | eeprom_ver, priv->cfg->eeprom_ver, | 289 | eeprom_ver, priv->cfg->eeprom_ver, |
290 | calib_ver, priv->cfg->eeprom_calib_ver); | 290 | calib_ver, priv->cfg->eeprom_calib_ver); |
291 | return -EINVAL; | 291 | return -EINVAL; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 47c894530eb5..f2ea3f05f6e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -41,38 +41,33 @@ | |||
41 | #include "iwl-power.h" | 41 | #include "iwl-power.h" |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Setting power level allow the card to go to sleep when not busy | 44 | * Setting power level allow the card to go to sleep when not busy. |
45 | * there are three factor that decide the power level to go to, they | ||
46 | * are list here with its priority | ||
47 | * 1- critical_power_setting this will be set according to card temperature. | ||
48 | * 2- system_power_setting this will be set by system PM manager. | ||
49 | * 3- user_power_setting this will be set by user either by writing to sys or | ||
50 | * mac80211 | ||
51 | * | 45 | * |
52 | * if system_power_setting and user_power_setting is set to auto | 46 | * The power level is set to INDEX_1 (the least deep state) by |
53 | * the power level will be decided according to association status and battery | 47 | * default, and will, in the future, be the deepest state unless |
54 | * status. | 48 | * otherwise required by pm_qos network latency requirements. |
55 | * | 49 | * |
50 | * Using INDEX_1 without pm_qos is ok because mac80211 will disable | ||
51 | * PS when even checking every beacon for the TIM bit would exceed | ||
52 | * the required latency. | ||
56 | */ | 53 | */ |
57 | 54 | ||
58 | #define MSEC_TO_USEC 1024 | ||
59 | #define IWL_POWER_RANGE_0_MAX (2) | 55 | #define IWL_POWER_RANGE_0_MAX (2) |
60 | #define IWL_POWER_RANGE_1_MAX (10) | 56 | #define IWL_POWER_RANGE_1_MAX (10) |
61 | 57 | ||
62 | 58 | ||
63 | 59 | #define NOSLP cpu_to_le16(0), 0, 0 | |
64 | #define IWL_POWER_ON_BATTERY IWL_POWER_INDEX_5 | 60 | #define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 |
65 | #define IWL_POWER_ON_AC_DISASSOC IWL_POWER_MODE_CAM | 61 | #define TU_TO_USEC 1024 |
66 | #define IWL_POWER_ON_AC_ASSOC IWL_POWER_MODE_CAM | 62 | #define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC) |
67 | 63 | #define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ | |
68 | 64 | cpu_to_le32(X1), \ | |
69 | #define IWL_CT_KILL_TEMPERATURE 110 | 65 | cpu_to_le32(X2), \ |
70 | #define IWL_MIN_POWER_TEMPERATURE 100 | 66 | cpu_to_le32(X3), \ |
71 | #define IWL_REDUCED_POWER_TEMPERATURE 95 | 67 | cpu_to_le32(X4)} |
72 | |||
73 | /* default power management (not Tx power) table values */ | 68 | /* default power management (not Tx power) table values */ |
74 | /* for TIM 0-10 */ | 69 | /* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */ |
75 | static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { | 70 | static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { |
76 | {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, | 71 | {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, |
77 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, | 72 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, |
78 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, | 73 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, |
@@ -82,8 +77,8 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { | |||
82 | }; | 77 | }; |
83 | 78 | ||
84 | 79 | ||
85 | /* for TIM = 3-10 */ | 80 | /* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */ |
86 | static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { | 81 | static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { |
87 | {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, | 82 | {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, |
88 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, | 83 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, |
89 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, | 84 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, |
@@ -92,8 +87,8 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { | |||
92 | {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} | 87 | {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} |
93 | }; | 88 | }; |
94 | 89 | ||
95 | /* for TIM > 11 */ | 90 | /* for DTIM period > IWL_POWER_RANGE_1_MAX */ |
96 | static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { | 91 | static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { |
97 | {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, | 92 | {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, |
98 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, | 93 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, |
99 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, | 94 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, |
@@ -106,39 +101,15 @@ static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { | |||
106 | /* set card power command */ | 101 | /* set card power command */ |
107 | static int iwl_set_power(struct iwl_priv *priv, void *cmd) | 102 | static int iwl_set_power(struct iwl_priv *priv, void *cmd) |
108 | { | 103 | { |
109 | return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, | 104 | return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, |
110 | sizeof(struct iwl_powertable_cmd), | 105 | sizeof(struct iwl_powertable_cmd), cmd); |
111 | cmd, NULL); | ||
112 | } | ||
113 | /* decide the right power level according to association status | ||
114 | * and battery status | ||
115 | */ | ||
116 | static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) | ||
117 | { | ||
118 | u16 mode; | ||
119 | |||
120 | switch (priv->power_data.user_power_setting) { | ||
121 | case IWL_POWER_AUTO: | ||
122 | /* if running on battery */ | ||
123 | if (priv->power_data.is_battery_active) | ||
124 | mode = IWL_POWER_ON_BATTERY; | ||
125 | else if (iwl_is_associated(priv)) | ||
126 | mode = IWL_POWER_ON_AC_ASSOC; | ||
127 | else | ||
128 | mode = IWL_POWER_ON_AC_DISASSOC; | ||
129 | break; | ||
130 | default: | ||
131 | mode = priv->power_data.user_power_setting; | ||
132 | break; | ||
133 | } | ||
134 | return mode; | ||
135 | } | 106 | } |
136 | 107 | ||
137 | /* initialize to default */ | 108 | /* initialize to default */ |
138 | static void iwl_power_init_handle(struct iwl_priv *priv) | 109 | static void iwl_power_init_handle(struct iwl_priv *priv) |
139 | { | 110 | { |
140 | struct iwl_power_mgr *pow_data; | 111 | struct iwl_power_mgr *pow_data; |
141 | int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; | 112 | int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM; |
142 | struct iwl_powertable_cmd *cmd; | 113 | struct iwl_powertable_cmd *cmd; |
143 | int i; | 114 | int i; |
144 | u16 lctl; | 115 | u16 lctl; |
@@ -157,7 +128,7 @@ static void iwl_power_init_handle(struct iwl_priv *priv) | |||
157 | 128 | ||
158 | IWL_DEBUG_POWER(priv, "adjust power command flags\n"); | 129 | IWL_DEBUG_POWER(priv, "adjust power command flags\n"); |
159 | 130 | ||
160 | for (i = 0; i < IWL_POWER_MAX; i++) { | 131 | for (i = 0; i < IWL_POWER_NUM; i++) { |
161 | cmd = &pow_data->pwr_range_0[i].cmd; | 132 | cmd = &pow_data->pwr_range_0[i].cmd; |
162 | 133 | ||
163 | if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN) | 134 | if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN) |
@@ -247,33 +218,12 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
247 | update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || | 218 | update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || |
248 | priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; | 219 | priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; |
249 | 220 | ||
250 | /* If on battery, set to 3, | 221 | final_mode = priv->power_data.user_power_setting; |
251 | * if plugged into AC power, set to CAM ("continuously aware mode"), | ||
252 | * else user level */ | ||
253 | |||
254 | switch (setting->system_power_setting) { | ||
255 | case IWL_POWER_SYS_AUTO: | ||
256 | final_mode = iwl_get_auto_power_mode(priv); | ||
257 | break; | ||
258 | case IWL_POWER_SYS_BATTERY: | ||
259 | final_mode = IWL_POWER_INDEX_3; | ||
260 | break; | ||
261 | case IWL_POWER_SYS_AC: | ||
262 | final_mode = IWL_POWER_MODE_CAM; | ||
263 | break; | ||
264 | default: | ||
265 | final_mode = IWL_POWER_INDEX_3; | ||
266 | WARN_ON(1); | ||
267 | } | ||
268 | |||
269 | if (setting->critical_power_setting > final_mode) | ||
270 | final_mode = setting->critical_power_setting; | ||
271 | 222 | ||
272 | /* driver only support CAM for non STA network */ | 223 | if (setting->power_disabled) |
273 | if (priv->iw_mode != NL80211_IFTYPE_STATION) | ||
274 | final_mode = IWL_POWER_MODE_CAM; | 224 | final_mode = IWL_POWER_MODE_CAM; |
275 | 225 | ||
276 | if (iwl_is_ready_rf(priv) && !setting->power_disabled && | 226 | if (iwl_is_ready_rf(priv) && |
277 | ((setting->power_mode != final_mode) || force)) { | 227 | ((setting->power_mode != final_mode) || force)) { |
278 | struct iwl_powertable_cmd cmd; | 228 | struct iwl_powertable_cmd cmd; |
279 | 229 | ||
@@ -290,8 +240,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
290 | 240 | ||
291 | if (final_mode == IWL_POWER_MODE_CAM) | 241 | if (final_mode == IWL_POWER_MODE_CAM) |
292 | clear_bit(STATUS_POWER_PMI, &priv->status); | 242 | clear_bit(STATUS_POWER_PMI, &priv->status); |
293 | else | ||
294 | set_bit(STATUS_POWER_PMI, &priv->status); | ||
295 | 243 | ||
296 | if (priv->cfg->ops->lib->update_chain_flags && update_chains) | 244 | if (priv->cfg->ops->lib->update_chain_flags && update_chains) |
297 | priv->cfg->ops->lib->update_chain_flags(priv); | 245 | priv->cfg->ops->lib->update_chain_flags(priv); |
@@ -307,51 +255,10 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
307 | } | 255 | } |
308 | EXPORT_SYMBOL(iwl_power_update_mode); | 256 | EXPORT_SYMBOL(iwl_power_update_mode); |
309 | 257 | ||
310 | /* Allow other iwl code to disable/enable power management active | ||
311 | * this will be useful for rate scale to disable PM during heavy | ||
312 | * Tx/Rx activities | ||
313 | */ | ||
314 | int iwl_power_disable_management(struct iwl_priv *priv, u32 ms) | ||
315 | { | ||
316 | u16 prev_mode; | ||
317 | int ret = 0; | ||
318 | |||
319 | if (priv->power_data.power_disabled) | ||
320 | return -EBUSY; | ||
321 | |||
322 | prev_mode = priv->power_data.user_power_setting; | ||
323 | priv->power_data.user_power_setting = IWL_POWER_MODE_CAM; | ||
324 | ret = iwl_power_update_mode(priv, 0); | ||
325 | priv->power_data.power_disabled = 1; | ||
326 | priv->power_data.user_power_setting = prev_mode; | ||
327 | cancel_delayed_work(&priv->set_power_save); | ||
328 | if (ms) | ||
329 | queue_delayed_work(priv->workqueue, &priv->set_power_save, | ||
330 | msecs_to_jiffies(ms)); | ||
331 | |||
332 | |||
333 | return ret; | ||
334 | } | ||
335 | EXPORT_SYMBOL(iwl_power_disable_management); | ||
336 | |||
337 | /* Allow other iwl code to disable/enable power management active | ||
338 | * this will be useful for rate scale to disable PM during high | ||
339 | * volume activities | ||
340 | */ | ||
341 | int iwl_power_enable_management(struct iwl_priv *priv) | ||
342 | { | ||
343 | int ret = 0; | ||
344 | |||
345 | priv->power_data.power_disabled = 0; | ||
346 | ret = iwl_power_update_mode(priv, 0); | ||
347 | return ret; | ||
348 | } | ||
349 | EXPORT_SYMBOL(iwl_power_enable_management); | ||
350 | |||
351 | /* set user_power_setting */ | 258 | /* set user_power_setting */ |
352 | int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) | 259 | int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) |
353 | { | 260 | { |
354 | if (mode > IWL_POWER_MAX) | 261 | if (mode >= IWL_POWER_NUM) |
355 | return -EINVAL; | 262 | return -EINVAL; |
356 | 263 | ||
357 | priv->power_data.user_power_setting = mode; | 264 | priv->power_data.user_power_setting = mode; |
@@ -360,86 +267,12 @@ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) | |||
360 | } | 267 | } |
361 | EXPORT_SYMBOL(iwl_power_set_user_mode); | 268 | EXPORT_SYMBOL(iwl_power_set_user_mode); |
362 | 269 | ||
363 | /* set system_power_setting. This should be set by over all | ||
364 | * PM application. | ||
365 | */ | ||
366 | int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode) | ||
367 | { | ||
368 | if (mode < IWL_POWER_SYS_MAX) | ||
369 | priv->power_data.system_power_setting = mode; | ||
370 | else | ||
371 | return -EINVAL; | ||
372 | return iwl_power_update_mode(priv, 0); | ||
373 | } | ||
374 | EXPORT_SYMBOL(iwl_power_set_system_mode); | ||
375 | |||
376 | /* initialize to default */ | 270 | /* initialize to default */ |
377 | void iwl_power_initialize(struct iwl_priv *priv) | 271 | void iwl_power_initialize(struct iwl_priv *priv) |
378 | { | 272 | { |
379 | iwl_power_init_handle(priv); | 273 | iwl_power_init_handle(priv); |
380 | priv->power_data.user_power_setting = IWL_POWER_AUTO; | 274 | priv->power_data.user_power_setting = IWL_POWER_INDEX_1; |
381 | priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO; | 275 | /* default to disabled until mac80211 says otherwise */ |
382 | priv->power_data.power_disabled = 0; | 276 | priv->power_data.power_disabled = 1; |
383 | priv->power_data.is_battery_active = 0; | ||
384 | priv->power_data.critical_power_setting = 0; | ||
385 | } | 277 | } |
386 | EXPORT_SYMBOL(iwl_power_initialize); | 278 | EXPORT_SYMBOL(iwl_power_initialize); |
387 | |||
388 | /* set critical_power_setting according to temperature value */ | ||
389 | int iwl_power_temperature_change(struct iwl_priv *priv) | ||
390 | { | ||
391 | int ret = 0; | ||
392 | s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature); | ||
393 | u16 new_critical = priv->power_data.critical_power_setting; | ||
394 | |||
395 | if (temperature > IWL_CT_KILL_TEMPERATURE) | ||
396 | return 0; | ||
397 | else if (temperature > IWL_MIN_POWER_TEMPERATURE) | ||
398 | new_critical = IWL_POWER_INDEX_5; | ||
399 | else if (temperature > IWL_REDUCED_POWER_TEMPERATURE) | ||
400 | new_critical = IWL_POWER_INDEX_3; | ||
401 | else | ||
402 | new_critical = IWL_POWER_MODE_CAM; | ||
403 | |||
404 | if (new_critical != priv->power_data.critical_power_setting) | ||
405 | priv->power_data.critical_power_setting = new_critical; | ||
406 | |||
407 | if (priv->power_data.critical_power_setting > | ||
408 | priv->power_data.power_mode) | ||
409 | ret = iwl_power_update_mode(priv, 0); | ||
410 | |||
411 | return ret; | ||
412 | } | ||
413 | EXPORT_SYMBOL(iwl_power_temperature_change); | ||
414 | |||
415 | static void iwl_bg_set_power_save(struct work_struct *work) | ||
416 | { | ||
417 | struct iwl_priv *priv = container_of(work, | ||
418 | struct iwl_priv, set_power_save.work); | ||
419 | IWL_DEBUG_POWER(priv, "update power\n"); | ||
420 | |||
421 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
422 | return; | ||
423 | |||
424 | mutex_lock(&priv->mutex); | ||
425 | |||
426 | /* on starting association we disable power management | ||
427 | * until association, if association failed then this | ||
428 | * timer will expire and enable PM again. | ||
429 | */ | ||
430 | if (!iwl_is_associated(priv)) | ||
431 | iwl_power_enable_management(priv); | ||
432 | |||
433 | mutex_unlock(&priv->mutex); | ||
434 | } | ||
435 | void iwl_setup_power_deferred_work(struct iwl_priv *priv) | ||
436 | { | ||
437 | INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save); | ||
438 | } | ||
439 | EXPORT_SYMBOL(iwl_setup_power_deferred_work); | ||
440 | |||
441 | void iwl_power_cancel_timeout(struct iwl_priv *priv) | ||
442 | { | ||
443 | cancel_delayed_work(&priv->set_power_save); | ||
444 | } | ||
445 | EXPORT_SYMBOL(iwl_power_cancel_timeout); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 18963392121e..37ba3bb7a25a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h | |||
@@ -40,56 +40,29 @@ enum { | |||
40 | IWL_POWER_INDEX_3, | 40 | IWL_POWER_INDEX_3, |
41 | IWL_POWER_INDEX_4, | 41 | IWL_POWER_INDEX_4, |
42 | IWL_POWER_INDEX_5, | 42 | IWL_POWER_INDEX_5, |
43 | IWL_POWER_AUTO, | 43 | IWL_POWER_NUM |
44 | IWL_POWER_MAX = IWL_POWER_AUTO, | ||
45 | }; | 44 | }; |
46 | 45 | ||
47 | enum { | ||
48 | IWL_POWER_SYS_AUTO, | ||
49 | IWL_POWER_SYS_AC, | ||
50 | IWL_POWER_SYS_BATTERY, | ||
51 | IWL_POWER_SYS_MAX, | ||
52 | }; | ||
53 | |||
54 | |||
55 | /* Power management (not Tx power) structures */ | 46 | /* Power management (not Tx power) structures */ |
56 | 47 | ||
57 | #define NOSLP cpu_to_le16(0), 0, 0 | ||
58 | #define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 | ||
59 | #define SLP_TOUT(T) cpu_to_le32((T) * MSEC_TO_USEC) | ||
60 | #define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ | ||
61 | cpu_to_le32(X1), \ | ||
62 | cpu_to_le32(X2), \ | ||
63 | cpu_to_le32(X3), \ | ||
64 | cpu_to_le32(X4)} | ||
65 | struct iwl_power_vec_entry { | 48 | struct iwl_power_vec_entry { |
66 | struct iwl_powertable_cmd cmd; | 49 | struct iwl_powertable_cmd cmd; |
67 | u8 no_dtim; | 50 | u8 no_dtim; |
68 | }; | 51 | }; |
69 | 52 | ||
70 | struct iwl_power_mgr { | 53 | struct iwl_power_mgr { |
71 | spinlock_t lock; | 54 | struct iwl_power_vec_entry pwr_range_0[IWL_POWER_NUM]; |
72 | struct iwl_power_vec_entry pwr_range_0[IWL_POWER_MAX]; | 55 | struct iwl_power_vec_entry pwr_range_1[IWL_POWER_NUM]; |
73 | struct iwl_power_vec_entry pwr_range_1[IWL_POWER_MAX]; | 56 | struct iwl_power_vec_entry pwr_range_2[IWL_POWER_NUM]; |
74 | struct iwl_power_vec_entry pwr_range_2[IWL_POWER_MAX]; | ||
75 | u32 dtim_period; | 57 | u32 dtim_period; |
76 | /* final power level that used to calculate final power command */ | 58 | /* final power level that used to calculate final power command */ |
77 | u8 power_mode; | 59 | u8 power_mode; |
78 | u8 user_power_setting; /* set by user through mac80211 or sysfs */ | 60 | u8 user_power_setting; /* set by user through sysfs */ |
79 | u8 system_power_setting; /* set by kernel system tools */ | 61 | u8 power_disabled; /* set by mac80211's CONF_PS */ |
80 | u8 critical_power_setting; /* set if driver over heated */ | ||
81 | u8 is_battery_active; /* DC/AC power */ | ||
82 | u8 power_disabled; /* flag to disable using power saving level */ | ||
83 | }; | 62 | }; |
84 | 63 | ||
85 | void iwl_setup_power_deferred_work(struct iwl_priv *priv); | ||
86 | void iwl_power_cancel_timeout(struct iwl_priv *priv); | ||
87 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); | 64 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); |
88 | int iwl_power_disable_management(struct iwl_priv *priv, u32 ms); | ||
89 | int iwl_power_enable_management(struct iwl_priv *priv); | ||
90 | int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode); | 65 | int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode); |
91 | int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode); | ||
92 | void iwl_power_initialize(struct iwl_priv *priv); | 66 | void iwl_power_initialize(struct iwl_priv *priv); |
93 | int iwl_power_temperature_change(struct iwl_priv *priv); | ||
94 | 67 | ||
95 | #endif /* __iwl_power_setting_h__ */ | 68 | #endif /* __iwl_power_setting_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index dd8766b80b34..065214b55895 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -580,9 +580,10 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
580 | int ret = 0; | 580 | int ret = 0; |
581 | u32 rate_flags = 0; | 581 | u32 rate_flags = 0; |
582 | u16 cmd_len; | 582 | u16 cmd_len; |
583 | u16 rx_chain = 0; | ||
583 | enum ieee80211_band band; | 584 | enum ieee80211_band band; |
584 | u8 n_probes = 0; | 585 | u8 n_probes = 0; |
585 | u8 rx_chain = priv->hw_params.valid_rx_ant; | 586 | u8 rx_ant = priv->hw_params.valid_rx_ant; |
586 | u8 rate; | 587 | u8 rate; |
587 | bool is_active = false; | 588 | bool is_active = false; |
588 | 589 | ||
@@ -723,7 +724,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
723 | * Avoid A (0x1) because of its off-channel reception on A-band. | 724 | * Avoid A (0x1) because of its off-channel reception on A-band. |
724 | */ | 725 | */ |
725 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 726 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) |
726 | rx_chain = 0x6; | 727 | rx_ant = ANT_BC; |
727 | } else { | 728 | } else { |
728 | IWL_WARN(priv, "Invalid scan band count\n"); | 729 | IWL_WARN(priv, "Invalid scan band count\n"); |
729 | goto done; | 730 | goto done; |
@@ -735,10 +736,11 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
735 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | 736 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); |
736 | 737 | ||
737 | /* MIMO is not used here, but value is required */ | 738 | /* MIMO is not used here, but value is required */ |
738 | scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | | 739 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS; |
739 | cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | | 740 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
740 | (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) | | 741 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; |
741 | (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); | 742 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
743 | scan->rx_chain = cpu_to_le16(rx_chain); | ||
742 | cmd_len = iwl_fill_probe_req(priv, | 744 | cmd_len = iwl_fill_probe_req(priv, |
743 | (struct ieee80211_mgmt *)scan->data, | 745 | (struct ieee80211_mgmt *)scan->data, |
744 | priv->scan_request->ie, | 746 | priv->scan_request->ie, |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f6c1489a0c4a..c32ec809053f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1837,23 +1837,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | |||
1837 | iwl_release_nic_access(priv); | 1837 | iwl_release_nic_access(priv); |
1838 | } | 1838 | } |
1839 | 1839 | ||
1840 | static void iwl3945_error_recovery(struct iwl_priv *priv) | ||
1841 | { | ||
1842 | unsigned long flags; | ||
1843 | |||
1844 | memcpy(&priv->staging_rxon, &priv->recovery_rxon, | ||
1845 | sizeof(priv->staging_rxon)); | ||
1846 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
1847 | iwlcore_commit_rxon(priv); | ||
1848 | |||
1849 | priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 1, 0, NULL); | ||
1850 | |||
1851 | spin_lock_irqsave(&priv->lock, flags); | ||
1852 | priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id); | ||
1853 | priv->error_recovering = 0; | ||
1854 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1855 | } | ||
1856 | |||
1857 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) | 1840 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) |
1858 | { | 1841 | { |
1859 | u32 inta, handled = 0; | 1842 | u32 inta, handled = 0; |
@@ -2683,9 +2666,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2683 | /* After the ALIVE response, we can send commands to 3945 uCode */ | 2666 | /* After the ALIVE response, we can send commands to 3945 uCode */ |
2684 | set_bit(STATUS_ALIVE, &priv->status); | 2667 | set_bit(STATUS_ALIVE, &priv->status); |
2685 | 2668 | ||
2686 | /* Clear out the uCode error bit if it is set */ | ||
2687 | clear_bit(STATUS_FW_ERROR, &priv->status); | ||
2688 | |||
2689 | if (iwl_is_rfkill(priv)) | 2669 | if (iwl_is_rfkill(priv)) |
2690 | return; | 2670 | return; |
2691 | 2671 | ||
@@ -2722,9 +2702,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2722 | set_bit(STATUS_READY, &priv->status); | 2702 | set_bit(STATUS_READY, &priv->status); |
2723 | wake_up_interruptible(&priv->wait_command_queue); | 2703 | wake_up_interruptible(&priv->wait_command_queue); |
2724 | 2704 | ||
2725 | if (priv->error_recovering) | ||
2726 | iwl3945_error_recovery(priv); | ||
2727 | |||
2728 | /* reassociate for ADHOC mode */ | 2705 | /* reassociate for ADHOC mode */ |
2729 | if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { | 2706 | if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { |
2730 | struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, | 2707 | struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, |
@@ -3231,8 +3208,17 @@ static void iwl3945_bg_restart(struct work_struct *data) | |||
3231 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3208 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
3232 | return; | 3209 | return; |
3233 | 3210 | ||
3234 | iwl3945_down(priv); | 3211 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { |
3235 | queue_work(priv->workqueue, &priv->up); | 3212 | mutex_lock(&priv->mutex); |
3213 | priv->vif = NULL; | ||
3214 | priv->is_open = 0; | ||
3215 | mutex_unlock(&priv->mutex); | ||
3216 | iwl3945_down(priv); | ||
3217 | ieee80211_restart_hw(priv->hw); | ||
3218 | } else { | ||
3219 | iwl3945_down(priv); | ||
3220 | queue_work(priv->workqueue, &priv->up); | ||
3221 | } | ||
3236 | } | 3222 | } |
3237 | 3223 | ||
3238 | static void iwl3945_bg_rx_replenish(struct work_struct *data) | 3224 | static void iwl3945_bg_rx_replenish(struct work_struct *data) |
@@ -3859,26 +3845,11 @@ static ssize_t show_power_level(struct device *d, | |||
3859 | { | 3845 | { |
3860 | struct iwl_priv *priv = dev_get_drvdata(d); | 3846 | struct iwl_priv *priv = dev_get_drvdata(d); |
3861 | int mode = priv->power_data.user_power_setting; | 3847 | int mode = priv->power_data.user_power_setting; |
3862 | int system = priv->power_data.system_power_setting; | ||
3863 | int level = priv->power_data.power_mode; | 3848 | int level = priv->power_data.power_mode; |
3864 | char *p = buf; | 3849 | char *p = buf; |
3865 | 3850 | ||
3866 | switch (system) { | 3851 | p += sprintf(p, "INDEX:%d\t", level); |
3867 | case IWL_POWER_SYS_AUTO: | 3852 | p += sprintf(p, "USER:%d\n", mode); |
3868 | p += sprintf(p, "SYSTEM:auto"); | ||
3869 | break; | ||
3870 | case IWL_POWER_SYS_AC: | ||
3871 | p += sprintf(p, "SYSTEM:ac"); | ||
3872 | break; | ||
3873 | case IWL_POWER_SYS_BATTERY: | ||
3874 | p += sprintf(p, "SYSTEM:battery"); | ||
3875 | break; | ||
3876 | } | ||
3877 | |||
3878 | p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ? | ||
3879 | "fixed" : "auto"); | ||
3880 | p += sprintf(p, "\tINDEX:%d", level); | ||
3881 | p += sprintf(p, "\n"); | ||
3882 | return p - buf + 1; | 3853 | return p - buf + 1; |
3883 | } | 3854 | } |
3884 | 3855 | ||
@@ -4122,7 +4093,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
4122 | priv->ibss_beacon = NULL; | 4093 | priv->ibss_beacon = NULL; |
4123 | 4094 | ||
4124 | spin_lock_init(&priv->lock); | 4095 | spin_lock_init(&priv->lock); |
4125 | spin_lock_init(&priv->power_data.lock); | ||
4126 | spin_lock_init(&priv->sta_lock); | 4096 | spin_lock_init(&priv->sta_lock); |
4127 | spin_lock_init(&priv->hcmd_lock); | 4097 | spin_lock_init(&priv->hcmd_lock); |
4128 | 4098 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index b1213b6a6b9f..61a4ad7cc1c2 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -642,7 +642,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
642 | if (changed & BSS_CHANGED_HT) { | 642 | if (changed & BSS_CHANGED_HT) { |
643 | printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", | 643 | printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", |
644 | wiphy_name(hw->wiphy), | 644 | wiphy_name(hw->wiphy), |
645 | info->ht.operation_mode); | 645 | info->ht_operation_mode); |
646 | } | 646 | } |
647 | 647 | ||
648 | if (changed & BSS_CHANGED_BASIC_RATES) { | 648 | if (changed & BSS_CHANGED_BASIC_RATES) { |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 46b288dc8f4d..a263d5c84c08 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -2369,7 +2369,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, | |||
2369 | if (info->use_cts_prot) { | 2369 | if (info->use_cts_prot) { |
2370 | prot_mode = MWL8K_FRAME_PROT_11G; | 2370 | prot_mode = MWL8K_FRAME_PROT_11G; |
2371 | } else { | 2371 | } else { |
2372 | switch (info->ht.operation_mode & | 2372 | switch (info->ht_operation_mode & |
2373 | IEEE80211_HT_OP_MODE_PROTECTION) { | 2373 | IEEE80211_HT_OP_MODE_PROTECTION) { |
2374 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | 2374 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: |
2375 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; | 2375 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d10af3687a8e..270dd4e59f7f 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1847,7 +1847,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1847 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); | 1847 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); |
1848 | 1848 | ||
1849 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || | 1849 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || |
1850 | !rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { | 1850 | rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { |
1851 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1851 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1852 | return -ENODEV; | 1852 | return -ENODEV; |
1853 | } | 1853 | } |
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 20a9633569f2..a82c4cd436d8 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config WL12XX | 1 | config WL12XX |
2 | tristate "TI wl1251/wl1271 support" | 2 | tristate "TI wl1251/wl1271 support" |
3 | depends on MAC80211 && WLAN_80211 && SPI_MASTER && EXPERIMENTAL | 3 | depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS && EXPERIMENTAL |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | select CRC7 | 5 | select CRC7 |
6 | ---help--- | 6 | ---help--- |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index dc92359f37e6..05c29c01174c 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1068,8 +1068,12 @@ enum ieee80211_category { | |||
1068 | WLAN_CATEGORY_DLS = 2, | 1068 | WLAN_CATEGORY_DLS = 2, |
1069 | WLAN_CATEGORY_BACK = 3, | 1069 | WLAN_CATEGORY_BACK = 3, |
1070 | WLAN_CATEGORY_PUBLIC = 4, | 1070 | WLAN_CATEGORY_PUBLIC = 4, |
1071 | WLAN_CATEGORY_HT = 7, | ||
1071 | WLAN_CATEGORY_SA_QUERY = 8, | 1072 | WLAN_CATEGORY_SA_QUERY = 8, |
1073 | WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, | ||
1072 | WLAN_CATEGORY_WMM = 17, | 1074 | WLAN_CATEGORY_WMM = 17, |
1075 | WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, | ||
1076 | WLAN_CATEGORY_VENDOR_SPECIFIC = 127, | ||
1073 | }; | 1077 | }; |
1074 | 1078 | ||
1075 | /* SPECTRUM_MGMT action code */ | 1079 | /* SPECTRUM_MGMT action code */ |
@@ -1261,7 +1265,9 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) | |||
1261 | if (ieee80211_has_protected(hdr->frame_control)) | 1265 | if (ieee80211_has_protected(hdr->frame_control)) |
1262 | return true; | 1266 | return true; |
1263 | category = ((u8 *) hdr) + 24; | 1267 | category = ((u8 *) hdr) + 24; |
1264 | return *category != WLAN_CATEGORY_PUBLIC; | 1268 | return *category != WLAN_CATEGORY_PUBLIC && |
1269 | *category != WLAN_CATEGORY_HT && | ||
1270 | *category != WLAN_CATEGORY_VENDOR_SPECIFIC; | ||
1265 | } | 1271 | } |
1266 | 1272 | ||
1267 | return false; | 1273 | return false; |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index e9fd13aa79f0..dbea93b694e5 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -25,6 +25,8 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/types.h> | ||
29 | |||
28 | /** | 30 | /** |
29 | * DOC: Station handling | 31 | * DOC: Station handling |
30 | * | 32 | * |
@@ -77,8 +79,8 @@ | |||
77 | * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, | 79 | * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, |
78 | * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. | 80 | * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. |
79 | * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, | 81 | * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, |
80 | * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER | 82 | * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, |
81 | * attributes. | 83 | * and %NL80211_ATTR_KEY_SEQ attributes. |
82 | * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX | 84 | * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX |
83 | * or %NL80211_ATTR_MAC. | 85 | * or %NL80211_ATTR_MAC. |
84 | * | 86 | * |
@@ -380,7 +382,7 @@ enum nl80211_commands { | |||
380 | * | 382 | * |
381 | * @NL80211_ATTR_STA_AID: Association ID for the station (u16) | 383 | * @NL80211_ATTR_STA_AID: Association ID for the station (u16) |
382 | * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of | 384 | * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of |
383 | * &enum nl80211_sta_flags. | 385 | * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2) |
384 | * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by | 386 | * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by |
385 | * IEEE 802.11 7.3.1.6 (u16). | 387 | * IEEE 802.11 7.3.1.6 (u16). |
386 | * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported | 388 | * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported |
@@ -494,6 +496,21 @@ enum nl80211_commands { | |||
494 | * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this | 496 | * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this |
495 | * is used, e.g., with %NL80211_CMD_AUTHENTICATE event | 497 | * is used, e.g., with %NL80211_CMD_AUTHENTICATE event |
496 | * | 498 | * |
499 | * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is | ||
500 | * used for the association (&enum nl80211_mfp, represented as a u32); | ||
501 | * this attribute can be used | ||
502 | * with %NL80211_CMD_ASSOCIATE request | ||
503 | * | ||
504 | * @NL80211_ATTR_STA_FLAGS2: Attribute containing a | ||
505 | * &struct nl80211_sta_flag_update. | ||
506 | * | ||
507 | * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls | ||
508 | * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in | ||
509 | * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE | ||
510 | * request, the driver will assume that the port is unauthorized until | ||
511 | * authorized by user space. Otherwise, port is marked authorized by | ||
512 | * default in station mode. | ||
513 | * | ||
497 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 514 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
498 | * @__NL80211_ATTR_AFTER_LAST: internal use | 515 | * @__NL80211_ATTR_AFTER_LAST: internal use |
499 | */ | 516 | */ |
@@ -596,6 +613,12 @@ enum nl80211_attrs { | |||
596 | 613 | ||
597 | NL80211_ATTR_TIMED_OUT, | 614 | NL80211_ATTR_TIMED_OUT, |
598 | 615 | ||
616 | NL80211_ATTR_USE_MFP, | ||
617 | |||
618 | NL80211_ATTR_STA_FLAGS2, | ||
619 | |||
620 | NL80211_ATTR_CONTROL_PORT, | ||
621 | |||
599 | /* add attributes here, update the policy in nl80211.c */ | 622 | /* add attributes here, update the policy in nl80211.c */ |
600 | 623 | ||
601 | __NL80211_ATTR_AFTER_LAST, | 624 | __NL80211_ATTR_AFTER_LAST, |
@@ -685,6 +708,18 @@ enum nl80211_sta_flags { | |||
685 | }; | 708 | }; |
686 | 709 | ||
687 | /** | 710 | /** |
711 | * struct nl80211_sta_flag_update - station flags mask/set | ||
712 | * @mask: mask of station flags to set | ||
713 | * @set: which values to set them to | ||
714 | * | ||
715 | * Both mask and set contain bits as per &enum nl80211_sta_flags. | ||
716 | */ | ||
717 | struct nl80211_sta_flag_update { | ||
718 | __u32 mask; | ||
719 | __u32 set; | ||
720 | } __attribute__((packed)); | ||
721 | |||
722 | /** | ||
688 | * enum nl80211_rate_info - bitrate information | 723 | * enum nl80211_rate_info - bitrate information |
689 | * | 724 | * |
690 | * These attribute types are used with %NL80211_STA_INFO_TXRATE | 725 | * These attribute types are used with %NL80211_STA_INFO_TXRATE |
@@ -1179,4 +1214,14 @@ enum nl80211_key_type { | |||
1179 | NL80211_KEYTYPE_PEERKEY, | 1214 | NL80211_KEYTYPE_PEERKEY, |
1180 | }; | 1215 | }; |
1181 | 1216 | ||
1217 | /** | ||
1218 | * enum nl80211_mfp - Management frame protection state | ||
1219 | * @NL80211_MFP_NO: Management frame protection not used | ||
1220 | * @NL80211_MFP_REQUIRED: Management frame protection required | ||
1221 | */ | ||
1222 | enum nl80211_mfp { | ||
1223 | NL80211_MFP_NO, | ||
1224 | NL80211_MFP_REQUIRED, | ||
1225 | }; | ||
1226 | |||
1182 | #endif /* __LINUX_NL80211_H */ | 1227 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b8a76764e1c5..9e17a83d3432 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -252,27 +252,6 @@ struct beacon_parameters { | |||
252 | }; | 252 | }; |
253 | 253 | ||
254 | /** | 254 | /** |
255 | * enum station_flags - station flags | ||
256 | * | ||
257 | * Station capability flags. Note that these must be the bits | ||
258 | * according to the nl80211 flags. | ||
259 | * | ||
260 | * @STATION_FLAG_CHANGED: station flags were changed | ||
261 | * @STATION_FLAG_AUTHORIZED: station is authorized to send frames (802.1X) | ||
262 | * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames | ||
263 | * with short preambles | ||
264 | * @STATION_FLAG_WME: station is WME/QoS capable | ||
265 | * @STATION_FLAG_MFP: station uses management frame protection | ||
266 | */ | ||
267 | enum station_flags { | ||
268 | STATION_FLAG_CHANGED = 1<<0, | ||
269 | STATION_FLAG_AUTHORIZED = 1<<NL80211_STA_FLAG_AUTHORIZED, | ||
270 | STATION_FLAG_SHORT_PREAMBLE = 1<<NL80211_STA_FLAG_SHORT_PREAMBLE, | ||
271 | STATION_FLAG_WME = 1<<NL80211_STA_FLAG_WME, | ||
272 | STATION_FLAG_MFP = 1<<NL80211_STA_FLAG_MFP, | ||
273 | }; | ||
274 | |||
275 | /** | ||
276 | * enum plink_action - actions to perform in mesh peers | 255 | * enum plink_action - actions to perform in mesh peers |
277 | * | 256 | * |
278 | * @PLINK_ACTION_INVALID: action 0 is reserved | 257 | * @PLINK_ACTION_INVALID: action 0 is reserved |
@@ -294,14 +273,17 @@ enum plink_actions { | |||
294 | * @supported_rates: supported rates in IEEE 802.11 format | 273 | * @supported_rates: supported rates in IEEE 802.11 format |
295 | * (or NULL for no change) | 274 | * (or NULL for no change) |
296 | * @supported_rates_len: number of supported rates | 275 | * @supported_rates_len: number of supported rates |
297 | * @station_flags: station flags (see &enum station_flags) | 276 | * @sta_flags_mask: station flags that changed |
277 | * (bitmask of BIT(NL80211_STA_FLAG_...)) | ||
278 | * @sta_flags_set: station flags values | ||
279 | * (bitmask of BIT(NL80211_STA_FLAG_...)) | ||
298 | * @listen_interval: listen interval or -1 for no change | 280 | * @listen_interval: listen interval or -1 for no change |
299 | * @aid: AID or zero for no change | 281 | * @aid: AID or zero for no change |
300 | */ | 282 | */ |
301 | struct station_parameters { | 283 | struct station_parameters { |
302 | u8 *supported_rates; | 284 | u8 *supported_rates; |
303 | struct net_device *vlan; | 285 | struct net_device *vlan; |
304 | u32 station_flags; | 286 | u32 sta_flags_mask, sta_flags_set; |
305 | int listen_interval; | 287 | int listen_interval; |
306 | u16 aid; | 288 | u16 aid; |
307 | u8 supported_rates_len; | 289 | u8 supported_rates_len; |
@@ -672,6 +654,11 @@ struct cfg80211_auth_request { | |||
672 | * @ssid_len: Length of ssid in octets | 654 | * @ssid_len: Length of ssid in octets |
673 | * @ie: Extra IEs to add to (Re)Association Request frame or %NULL | 655 | * @ie: Extra IEs to add to (Re)Association Request frame or %NULL |
674 | * @ie_len: Length of ie buffer in octets | 656 | * @ie_len: Length of ie buffer in octets |
657 | * @use_mfp: Use management frame protection (IEEE 802.11w) in this association | ||
658 | * @control_port: Whether user space controls IEEE 802.1X port, i.e., | ||
659 | * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is | ||
660 | * required to assume that the port is unauthorized until authorized by | ||
661 | * user space. Otherwise, port is marked authorized by default. | ||
675 | */ | 662 | */ |
676 | struct cfg80211_assoc_request { | 663 | struct cfg80211_assoc_request { |
677 | struct ieee80211_channel *chan; | 664 | struct ieee80211_channel *chan; |
@@ -680,6 +667,8 @@ struct cfg80211_assoc_request { | |||
680 | size_t ssid_len; | 667 | size_t ssid_len; |
681 | const u8 *ie; | 668 | const u8 *ie; |
682 | size_t ie_len; | 669 | size_t ie_len; |
670 | bool use_mfp; | ||
671 | bool control_port; | ||
683 | }; | 672 | }; |
684 | 673 | ||
685 | /** | 674 | /** |
@@ -858,13 +847,13 @@ struct cfg80211_ops { | |||
858 | struct vif_params *params); | 847 | struct vif_params *params); |
859 | 848 | ||
860 | int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, | 849 | int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, |
861 | u8 key_index, u8 *mac_addr, | 850 | u8 key_index, const u8 *mac_addr, |
862 | struct key_params *params); | 851 | struct key_params *params); |
863 | int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, | 852 | int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, |
864 | u8 key_index, u8 *mac_addr, void *cookie, | 853 | u8 key_index, const u8 *mac_addr, void *cookie, |
865 | void (*callback)(void *cookie, struct key_params*)); | 854 | void (*callback)(void *cookie, struct key_params*)); |
866 | int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, | 855 | int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, |
867 | u8 key_index, u8 *mac_addr); | 856 | u8 key_index, const u8 *mac_addr); |
868 | int (*set_default_key)(struct wiphy *wiphy, | 857 | int (*set_default_key)(struct wiphy *wiphy, |
869 | struct net_device *netdev, | 858 | struct net_device *netdev, |
870 | u8 key_index); | 859 | u8 key_index); |
@@ -1145,8 +1134,11 @@ struct wireless_dev { | |||
1145 | 1134 | ||
1146 | #ifdef CONFIG_WIRELESS_EXT | 1135 | #ifdef CONFIG_WIRELESS_EXT |
1147 | /* wext data */ | 1136 | /* wext data */ |
1148 | struct cfg80211_ibss_params wext; | 1137 | struct { |
1149 | u8 wext_bssid[ETH_ALEN]; | 1138 | struct cfg80211_ibss_params ibss; |
1139 | u8 bssid[ETH_ALEN]; | ||
1140 | s8 default_key, default_mgmt_key; | ||
1141 | } wext; | ||
1150 | #endif | 1142 | #endif |
1151 | }; | 1143 | }; |
1152 | 1144 | ||
@@ -1396,6 +1388,15 @@ int cfg80211_wext_siwretry(struct net_device *dev, | |||
1396 | int cfg80211_wext_giwretry(struct net_device *dev, | 1388 | int cfg80211_wext_giwretry(struct net_device *dev, |
1397 | struct iw_request_info *info, | 1389 | struct iw_request_info *info, |
1398 | struct iw_param *retry, char *extra); | 1390 | struct iw_param *retry, char *extra); |
1391 | int cfg80211_wext_siwencodeext(struct net_device *dev, | ||
1392 | struct iw_request_info *info, | ||
1393 | struct iw_point *erq, char *extra); | ||
1394 | int cfg80211_wext_siwencode(struct net_device *dev, | ||
1395 | struct iw_request_info *info, | ||
1396 | struct iw_point *erq, char *keybuf); | ||
1397 | int cfg80211_wext_giwencode(struct net_device *dev, | ||
1398 | struct iw_request_info *info, | ||
1399 | struct iw_point *erq, char *keybuf); | ||
1399 | 1400 | ||
1400 | /* | 1401 | /* |
1401 | * callbacks for asynchronous cfg80211 methods, notification | 1402 | * callbacks for asynchronous cfg80211 methods, notification |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 38dc1cd10270..d10ed1776fcd 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -73,22 +73,6 @@ | |||
73 | */ | 73 | */ |
74 | 74 | ||
75 | /** | 75 | /** |
76 | * struct ieee80211_ht_bss_info - describing BSS's HT characteristics | ||
77 | * | ||
78 | * This structure describes most essential parameters needed | ||
79 | * to describe 802.11n HT characteristics in a BSS. | ||
80 | * | ||
81 | * @primary_channel: channel number of primery channel | ||
82 | * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width) | ||
83 | * @bss_op_mode: 802.11n's BSS operation modes (e.g. HT protection) | ||
84 | */ | ||
85 | struct ieee80211_ht_bss_info { | ||
86 | u8 primary_channel; | ||
87 | u8 bss_cap; /* use IEEE80211_HT_IE_CHA_ */ | ||
88 | u8 bss_op_mode; /* use IEEE80211_HT_IE_ */ | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * enum ieee80211_max_queues - maximum number of queues | 76 | * enum ieee80211_max_queues - maximum number of queues |
93 | * | 77 | * |
94 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. | 78 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. |
@@ -171,14 +155,6 @@ enum ieee80211_bss_change { | |||
171 | }; | 155 | }; |
172 | 156 | ||
173 | /** | 157 | /** |
174 | * struct ieee80211_bss_ht_conf - BSS's changing HT configuration | ||
175 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) | ||
176 | */ | ||
177 | struct ieee80211_bss_ht_conf { | ||
178 | u16 operation_mode; | ||
179 | }; | ||
180 | |||
181 | /** | ||
182 | * struct ieee80211_bss_conf - holds the BSS's changing parameters | 158 | * struct ieee80211_bss_conf - holds the BSS's changing parameters |
183 | * | 159 | * |
184 | * This structure keeps information about a BSS (and an association | 160 | * This structure keeps information about a BSS (and an association |
@@ -203,6 +179,8 @@ struct ieee80211_bss_ht_conf { | |||
203 | * the current band. | 179 | * the current band. |
204 | * @bssid: The BSSID for this BSS | 180 | * @bssid: The BSSID for this BSS |
205 | * @enable_beacon: whether beaconing should be enabled or not | 181 | * @enable_beacon: whether beaconing should be enabled or not |
182 | * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info). | ||
183 | * This field is only valid when the channel type is one of the HT types. | ||
206 | */ | 184 | */ |
207 | struct ieee80211_bss_conf { | 185 | struct ieee80211_bss_conf { |
208 | const u8 *bssid; | 186 | const u8 *bssid; |
@@ -219,7 +197,7 @@ struct ieee80211_bss_conf { | |||
219 | u16 assoc_capability; | 197 | u16 assoc_capability; |
220 | u64 timestamp; | 198 | u64 timestamp; |
221 | u32 basic_rates; | 199 | u32 basic_rates; |
222 | struct ieee80211_bss_ht_conf ht; | 200 | u16 ht_operation_mode; |
223 | }; | 201 | }; |
224 | 202 | ||
225 | /** | 203 | /** |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d0ca6da33ca9..77e9ff5ec4f3 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -112,7 +112,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
112 | } | 112 | } |
113 | 113 | ||
114 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | 114 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
115 | u8 key_idx, u8 *mac_addr, | 115 | u8 key_idx, const u8 *mac_addr, |
116 | struct key_params *params) | 116 | struct key_params *params) |
117 | { | 117 | { |
118 | struct ieee80211_sub_if_data *sdata; | 118 | struct ieee80211_sub_if_data *sdata; |
@@ -141,7 +141,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
141 | return -EINVAL; | 141 | return -EINVAL; |
142 | } | 142 | } |
143 | 143 | ||
144 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key); | 144 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, |
145 | params->seq_len, params->seq); | ||
145 | if (!key) | 146 | if (!key) |
146 | return -ENOMEM; | 147 | return -ENOMEM; |
147 | 148 | ||
@@ -166,7 +167,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
166 | } | 167 | } |
167 | 168 | ||
168 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 169 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
169 | u8 key_idx, u8 *mac_addr) | 170 | u8 key_idx, const u8 *mac_addr) |
170 | { | 171 | { |
171 | struct ieee80211_sub_if_data *sdata; | 172 | struct ieee80211_sub_if_data *sdata; |
172 | struct sta_info *sta; | 173 | struct sta_info *sta; |
@@ -208,7 +209,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
208 | } | 209 | } |
209 | 210 | ||
210 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | 211 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, |
211 | u8 key_idx, u8 *mac_addr, void *cookie, | 212 | u8 key_idx, const u8 *mac_addr, void *cookie, |
212 | void (*callback)(void *cookie, | 213 | void (*callback)(void *cookie, |
213 | struct key_params *params)) | 214 | struct key_params *params)) |
214 | { | 215 | { |
@@ -629,34 +630,38 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
629 | int i, j; | 630 | int i, j; |
630 | struct ieee80211_supported_band *sband; | 631 | struct ieee80211_supported_band *sband; |
631 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 632 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
633 | u32 mask, set; | ||
632 | 634 | ||
633 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 635 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
634 | 636 | ||
635 | /* | 637 | spin_lock_bh(&sta->lock); |
636 | * FIXME: updating the flags is racy when this function is | 638 | mask = params->sta_flags_mask; |
637 | * called from ieee80211_change_station(), this will | 639 | set = params->sta_flags_set; |
638 | * be resolved in a future patch. | ||
639 | */ | ||
640 | 640 | ||
641 | if (params->station_flags & STATION_FLAG_CHANGED) { | 641 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
642 | spin_lock_bh(&sta->lock); | ||
643 | sta->flags &= ~WLAN_STA_AUTHORIZED; | 642 | sta->flags &= ~WLAN_STA_AUTHORIZED; |
644 | if (params->station_flags & STATION_FLAG_AUTHORIZED) | 643 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
645 | sta->flags |= WLAN_STA_AUTHORIZED; | 644 | sta->flags |= WLAN_STA_AUTHORIZED; |
645 | } | ||
646 | 646 | ||
647 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { | ||
647 | sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; | 648 | sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; |
648 | if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE) | 649 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) |
649 | sta->flags |= WLAN_STA_SHORT_PREAMBLE; | 650 | sta->flags |= WLAN_STA_SHORT_PREAMBLE; |
651 | } | ||
650 | 652 | ||
653 | if (mask & BIT(NL80211_STA_FLAG_WME)) { | ||
651 | sta->flags &= ~WLAN_STA_WME; | 654 | sta->flags &= ~WLAN_STA_WME; |
652 | if (params->station_flags & STATION_FLAG_WME) | 655 | if (set & BIT(NL80211_STA_FLAG_WME)) |
653 | sta->flags |= WLAN_STA_WME; | 656 | sta->flags |= WLAN_STA_WME; |
657 | } | ||
654 | 658 | ||
659 | if (mask & BIT(NL80211_STA_FLAG_MFP)) { | ||
655 | sta->flags &= ~WLAN_STA_MFP; | 660 | sta->flags &= ~WLAN_STA_MFP; |
656 | if (params->station_flags & STATION_FLAG_MFP) | 661 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
657 | sta->flags |= WLAN_STA_MFP; | 662 | sta->flags |= WLAN_STA_MFP; |
658 | spin_unlock_bh(&sta->lock); | ||
659 | } | 663 | } |
664 | spin_unlock_bh(&sta->lock); | ||
660 | 665 | ||
661 | /* | 666 | /* |
662 | * FIXME: updating the following information is racy when this | 667 | * FIXME: updating the following information is racy when this |
@@ -1253,6 +1258,19 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, | |||
1253 | if (ret) | 1258 | if (ret) |
1254 | return ret; | 1259 | return ret; |
1255 | 1260 | ||
1261 | if (req->use_mfp) { | ||
1262 | sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED; | ||
1263 | sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED; | ||
1264 | } else { | ||
1265 | sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED; | ||
1266 | sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED; | ||
1267 | } | ||
1268 | |||
1269 | if (req->control_port) | ||
1270 | sdata->u.mgd.flags |= IEEE80211_STA_CONTROL_PORT; | ||
1271 | else | ||
1272 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
1273 | |||
1256 | sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME; | 1274 | sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME; |
1257 | sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE; | 1275 | sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE; |
1258 | ieee80211_sta_req_auth(sdata); | 1276 | ieee80211_sta_req_auth(sdata); |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index ac793201b701..e7682fe1c590 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -135,6 +135,42 @@ static const struct file_operations reset_ops = { | |||
135 | .open = mac80211_open_file_generic, | 135 | .open = mac80211_open_file_generic, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static ssize_t noack_read(struct file *file, char __user *user_buf, | ||
139 | size_t count, loff_t *ppos) | ||
140 | { | ||
141 | struct ieee80211_local *local = file->private_data; | ||
142 | int res; | ||
143 | char buf[10]; | ||
144 | |||
145 | res = scnprintf(buf, sizeof(buf), "%d\n", local->wifi_wme_noack_test); | ||
146 | |||
147 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
148 | } | ||
149 | |||
150 | static ssize_t noack_write(struct file *file, | ||
151 | const char __user *user_buf, | ||
152 | size_t count, loff_t *ppos) | ||
153 | { | ||
154 | struct ieee80211_local *local = file->private_data; | ||
155 | char buf[10]; | ||
156 | size_t len; | ||
157 | |||
158 | len = min(count, sizeof(buf) - 1); | ||
159 | if (copy_from_user(buf, user_buf, len)) | ||
160 | return -EFAULT; | ||
161 | buf[len] = '\0'; | ||
162 | |||
163 | local->wifi_wme_noack_test = !!simple_strtoul(buf, NULL, 0); | ||
164 | |||
165 | return count; | ||
166 | } | ||
167 | |||
168 | static const struct file_operations noack_ops = { | ||
169 | .read = noack_read, | ||
170 | .write = noack_write, | ||
171 | .open = mac80211_open_file_generic | ||
172 | }; | ||
173 | |||
138 | /* statistics stuff */ | 174 | /* statistics stuff */ |
139 | 175 | ||
140 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ | 176 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ |
@@ -275,6 +311,7 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
275 | DEBUGFS_ADD(wep_iv); | 311 | DEBUGFS_ADD(wep_iv); |
276 | DEBUGFS_ADD(tsf); | 312 | DEBUGFS_ADD(tsf); |
277 | DEBUGFS_ADD_MODE(reset, 0200); | 313 | DEBUGFS_ADD_MODE(reset, 0200); |
314 | DEBUGFS_ADD(noack); | ||
278 | 315 | ||
279 | statsd = debugfs_create_dir("statistics", phyd); | 316 | statsd = debugfs_create_dir("statistics", phyd); |
280 | local->debugfs.statistics = statsd; | 317 | local->debugfs.statistics = statsd; |
@@ -330,6 +367,7 @@ void debugfs_hw_del(struct ieee80211_local *local) | |||
330 | DEBUGFS_DEL(wep_iv); | 367 | DEBUGFS_DEL(wep_iv); |
331 | DEBUGFS_DEL(tsf); | 368 | DEBUGFS_DEL(tsf); |
332 | DEBUGFS_DEL(reset); | 369 | DEBUGFS_DEL(reset); |
370 | DEBUGFS_DEL(noack); | ||
333 | 371 | ||
334 | DEBUGFS_STATS_DEL(transmitted_fragment_count); | 372 | DEBUGFS_STATS_DEL(transmitted_fragment_count); |
335 | DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); | 373 | DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index aa537681f87c..c236079ed38a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -63,19 +63,18 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
63 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 63 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
64 | const u8 *bssid, const int beacon_int, | 64 | const u8 *bssid, const int beacon_int, |
65 | struct ieee80211_channel *chan, | 65 | struct ieee80211_channel *chan, |
66 | const size_t supp_rates_len, | 66 | const u32 basic_rates, |
67 | const u8 *supp_rates, | ||
68 | const u16 capability, u64 tsf) | 67 | const u16 capability, u64 tsf) |
69 | { | 68 | { |
70 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 69 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
71 | struct ieee80211_local *local = sdata->local; | 70 | struct ieee80211_local *local = sdata->local; |
72 | int rates, i, j; | 71 | int rates, i; |
73 | struct sk_buff *skb; | 72 | struct sk_buff *skb; |
74 | struct ieee80211_mgmt *mgmt; | 73 | struct ieee80211_mgmt *mgmt; |
75 | u8 *pos; | 74 | u8 *pos; |
76 | struct ieee80211_supported_band *sband; | 75 | struct ieee80211_supported_band *sband; |
77 | u32 bss_change; | 76 | u32 bss_change; |
78 | 77 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | |
79 | 78 | ||
80 | /* Reset own TSF to allow time synchronization work. */ | 79 | /* Reset own TSF to allow time synchronization work. */ |
81 | drv_reset_tsf(local); | 80 | drv_reset_tsf(local); |
@@ -101,6 +100,16 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
101 | 100 | ||
102 | sband = local->hw.wiphy->bands[chan->band]; | 101 | sband = local->hw.wiphy->bands[chan->band]; |
103 | 102 | ||
103 | /* build supported rates array */ | ||
104 | pos = supp_rates; | ||
105 | for (i = 0; i < sband->n_bitrates; i++) { | ||
106 | int rate = sband->bitrates[i].bitrate; | ||
107 | u8 basic = 0; | ||
108 | if (basic_rates & BIT(i)) | ||
109 | basic = 0x80; | ||
110 | *pos++ = basic | (u8) (rate / 5); | ||
111 | } | ||
112 | |||
104 | /* Build IBSS probe response */ | 113 | /* Build IBSS probe response */ |
105 | mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 114 | mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
106 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 115 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
@@ -118,7 +127,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
118 | *pos++ = ifibss->ssid_len; | 127 | *pos++ = ifibss->ssid_len; |
119 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); | 128 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); |
120 | 129 | ||
121 | rates = supp_rates_len; | 130 | rates = sband->n_bitrates; |
122 | if (rates > 8) | 131 | if (rates > 8) |
123 | rates = 8; | 132 | rates = 8; |
124 | pos = skb_put(skb, 2 + rates); | 133 | pos = skb_put(skb, 2 + rates); |
@@ -140,8 +149,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
140 | *pos++ = 0; | 149 | *pos++ = 0; |
141 | *pos++ = 0; | 150 | *pos++ = 0; |
142 | 151 | ||
143 | if (supp_rates_len > 8) { | 152 | if (sband->n_bitrates > 8) { |
144 | rates = supp_rates_len - 8; | 153 | rates = sband->n_bitrates - 8; |
145 | pos = skb_put(skb, 2 + rates); | 154 | pos = skb_put(skb, 2 + rates); |
146 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 155 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
147 | *pos++ = rates; | 156 | *pos++ = rates; |
@@ -162,15 +171,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
162 | bss_change |= BSS_CHANGED_BEACON_ENABLED; | 171 | bss_change |= BSS_CHANGED_BEACON_ENABLED; |
163 | ieee80211_bss_info_change_notify(sdata, bss_change); | 172 | ieee80211_bss_info_change_notify(sdata, bss_change); |
164 | 173 | ||
165 | rates = 0; | 174 | ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); |
166 | for (i = 0; i < supp_rates_len; i++) { | ||
167 | int bitrate = (supp_rates[i] & 0x7f) * 5; | ||
168 | for (j = 0; j < sband->n_bitrates; j++) | ||
169 | if (sband->bitrates[j].bitrate == bitrate) | ||
170 | rates |= BIT(j); | ||
171 | } | ||
172 | |||
173 | ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates); | ||
174 | 175 | ||
175 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; | 176 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; |
176 | mod_timer(&ifibss->timer, | 177 | mod_timer(&ifibss->timer, |
@@ -184,15 +185,35 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
184 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 185 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
185 | struct ieee80211_bss *bss) | 186 | struct ieee80211_bss *bss) |
186 | { | 187 | { |
188 | struct ieee80211_supported_band *sband; | ||
189 | u32 basic_rates; | ||
190 | int i, j; | ||
187 | u16 beacon_int = bss->cbss.beacon_interval; | 191 | u16 beacon_int = bss->cbss.beacon_interval; |
188 | 192 | ||
189 | if (beacon_int < 10) | 193 | if (beacon_int < 10) |
190 | beacon_int = 10; | 194 | beacon_int = 10; |
191 | 195 | ||
196 | sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band]; | ||
197 | |||
198 | basic_rates = 0; | ||
199 | |||
200 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
201 | int rate = (bss->supp_rates[i] & 0x7f) * 5; | ||
202 | bool is_basic = !!(bss->supp_rates[i] & 0x80); | ||
203 | |||
204 | for (j = 0; j < sband->n_bitrates; j++) { | ||
205 | if (sband->bitrates[j].bitrate == rate) { | ||
206 | if (is_basic) | ||
207 | basic_rates |= BIT(j); | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | |||
192 | __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, | 213 | __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, |
193 | beacon_int, | 214 | beacon_int, |
194 | bss->cbss.channel, | 215 | bss->cbss.channel, |
195 | bss->supp_rates_len, bss->supp_rates, | 216 | basic_rates, |
196 | bss->cbss.capability, | 217 | bss->cbss.capability, |
197 | bss->cbss.tsf); | 218 | bss->cbss.tsf); |
198 | } | 219 | } |
@@ -449,9 +470,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
449 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 470 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
450 | struct ieee80211_local *local = sdata->local; | 471 | struct ieee80211_local *local = sdata->local; |
451 | struct ieee80211_supported_band *sband; | 472 | struct ieee80211_supported_band *sband; |
452 | u8 *pos; | ||
453 | u8 bssid[ETH_ALEN]; | 473 | u8 bssid[ETH_ALEN]; |
454 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | ||
455 | u16 capability; | 474 | u16 capability; |
456 | int i; | 475 | int i; |
457 | 476 | ||
@@ -480,15 +499,9 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
480 | else | 499 | else |
481 | sdata->drop_unencrypted = 0; | 500 | sdata->drop_unencrypted = 0; |
482 | 501 | ||
483 | pos = supp_rates; | ||
484 | for (i = 0; i < sband->n_bitrates; i++) { | ||
485 | int rate = sband->bitrates[i].bitrate; | ||
486 | *pos++ = (u8) (rate / 5); | ||
487 | } | ||
488 | |||
489 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, | 502 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, |
490 | ifibss->channel, sband->n_bitrates, | 503 | ifibss->channel, 3, /* first two are basic */ |
491 | supp_rates, capability, 0); | 504 | capability, 0); |
492 | } | 505 | } |
493 | 506 | ||
494 | static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | 507 | static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -499,6 +512,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
499 | struct ieee80211_channel *chan = NULL; | 512 | struct ieee80211_channel *chan = NULL; |
500 | const u8 *bssid = NULL; | 513 | const u8 *bssid = NULL; |
501 | int active_ibss; | 514 | int active_ibss; |
515 | u16 capability; | ||
502 | 516 | ||
503 | active_ibss = ieee80211_sta_active_ibss(sdata); | 517 | active_ibss = ieee80211_sta_active_ibss(sdata); |
504 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 518 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
@@ -509,6 +523,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
509 | if (active_ibss) | 523 | if (active_ibss) |
510 | return; | 524 | return; |
511 | 525 | ||
526 | capability = WLAN_CAPABILITY_IBSS; | ||
527 | if (sdata->default_key) | ||
528 | capability |= WLAN_CAPABILITY_PRIVACY; | ||
529 | |||
512 | if (ifibss->fixed_bssid) | 530 | if (ifibss->fixed_bssid) |
513 | bssid = ifibss->bssid; | 531 | bssid = ifibss->bssid; |
514 | if (ifibss->fixed_channel) | 532 | if (ifibss->fixed_channel) |
@@ -517,8 +535,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
517 | bssid = ifibss->bssid; | 535 | bssid = ifibss->bssid; |
518 | bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid, | 536 | bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid, |
519 | ifibss->ssid, ifibss->ssid_len, | 537 | ifibss->ssid, ifibss->ssid_len, |
520 | WLAN_CAPABILITY_IBSS, | 538 | capability, |
521 | WLAN_CAPABILITY_IBSS); | 539 | WLAN_CAPABILITY_IBSS | |
540 | WLAN_CAPABILITY_PRIVACY); | ||
522 | 541 | ||
523 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 542 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
524 | if (bss) | 543 | if (bss) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 03e0d22603c8..9d1514727f6e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -235,7 +235,7 @@ struct mesh_preq_queue { | |||
235 | #define IEEE80211_STA_ASSOCIATED BIT(4) | 235 | #define IEEE80211_STA_ASSOCIATED BIT(4) |
236 | #define IEEE80211_STA_PROBEREQ_POLL BIT(5) | 236 | #define IEEE80211_STA_PROBEREQ_POLL BIT(5) |
237 | #define IEEE80211_STA_CREATE_IBSS BIT(6) | 237 | #define IEEE80211_STA_CREATE_IBSS BIT(6) |
238 | /* hole at 7, please re-use */ | 238 | #define IEEE80211_STA_CONTROL_PORT BIT(7) |
239 | #define IEEE80211_STA_WMM_ENABLED BIT(8) | 239 | #define IEEE80211_STA_WMM_ENABLED BIT(8) |
240 | /* hole at 9, please re-use */ | 240 | /* hole at 9, please re-use */ |
241 | #define IEEE80211_STA_AUTO_SSID_SEL BIT(10) | 241 | #define IEEE80211_STA_AUTO_SSID_SEL BIT(10) |
@@ -427,6 +427,12 @@ struct ieee80211_sub_if_data { | |||
427 | 427 | ||
428 | int drop_unencrypted; | 428 | int drop_unencrypted; |
429 | 429 | ||
430 | /* | ||
431 | * keep track of whether the HT opmode (stored in | ||
432 | * vif.bss_info.ht_operation_mode) is valid. | ||
433 | */ | ||
434 | bool ht_opmode_valid; | ||
435 | |||
430 | /* Fragment table for host-based reassembly */ | 436 | /* Fragment table for host-based reassembly */ |
431 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 437 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
432 | unsigned int fragment_next; | 438 | unsigned int fragment_next; |
@@ -760,6 +766,7 @@ struct ieee80211_local { | |||
760 | struct dentry *wep_iv; | 766 | struct dentry *wep_iv; |
761 | struct dentry *tsf; | 767 | struct dentry *tsf; |
762 | struct dentry *reset; | 768 | struct dentry *reset; |
769 | struct dentry *noack; | ||
763 | struct dentry *statistics; | 770 | struct dentry *statistics; |
764 | struct local_debugfsdentries_statsdentries { | 771 | struct local_debugfsdentries_statsdentries { |
765 | struct dentry *transmitted_fragment_count; | 772 | struct dentry *transmitted_fragment_count; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8b6daf0219f4..8c9f1c722cdb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -964,5 +964,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) | |||
964 | mutex_lock(&local->iflist_mtx); | 964 | mutex_lock(&local->iflist_mtx); |
965 | chg = __ieee80211_recalc_idle(local); | 965 | chg = __ieee80211_recalc_idle(local); |
966 | mutex_unlock(&local->iflist_mtx); | 966 | mutex_unlock(&local->iflist_mtx); |
967 | ieee80211_hw_config(local, chg); | 967 | if (chg) |
968 | ieee80211_hw_config(local, chg); | ||
968 | } | 969 | } |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index b7e1350273bb..827ea8e6ee0a 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -290,9 +290,11 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
290 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 290 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, |
291 | int idx, | 291 | int idx, |
292 | size_t key_len, | 292 | size_t key_len, |
293 | const u8 *key_data) | 293 | const u8 *key_data, |
294 | size_t seq_len, const u8 *seq) | ||
294 | { | 295 | { |
295 | struct ieee80211_key *key; | 296 | struct ieee80211_key *key; |
297 | int i, j; | ||
296 | 298 | ||
297 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); | 299 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); |
298 | 300 | ||
@@ -318,14 +320,31 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
318 | case ALG_TKIP: | 320 | case ALG_TKIP: |
319 | key->conf.iv_len = TKIP_IV_LEN; | 321 | key->conf.iv_len = TKIP_IV_LEN; |
320 | key->conf.icv_len = TKIP_ICV_LEN; | 322 | key->conf.icv_len = TKIP_ICV_LEN; |
323 | if (seq && seq_len == 6) { | ||
324 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { | ||
325 | key->u.tkip.rx[i].iv32 = | ||
326 | get_unaligned_le32(&seq[2]); | ||
327 | key->u.tkip.rx[i].iv16 = | ||
328 | get_unaligned_le16(seq); | ||
329 | } | ||
330 | } | ||
321 | break; | 331 | break; |
322 | case ALG_CCMP: | 332 | case ALG_CCMP: |
323 | key->conf.iv_len = CCMP_HDR_LEN; | 333 | key->conf.iv_len = CCMP_HDR_LEN; |
324 | key->conf.icv_len = CCMP_MIC_LEN; | 334 | key->conf.icv_len = CCMP_MIC_LEN; |
335 | if (seq && seq_len == CCMP_PN_LEN) { | ||
336 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | ||
337 | for (j = 0; j < CCMP_PN_LEN; j++) | ||
338 | key->u.ccmp.rx_pn[i][j] = | ||
339 | seq[CCMP_PN_LEN - j - 1]; | ||
340 | } | ||
325 | break; | 341 | break; |
326 | case ALG_AES_CMAC: | 342 | case ALG_AES_CMAC: |
327 | key->conf.iv_len = 0; | 343 | key->conf.iv_len = 0; |
328 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | 344 | key->conf.icv_len = sizeof(struct ieee80211_mmie); |
345 | if (seq && seq_len == 6) | ||
346 | for (j = 0; j < 6; j++) | ||
347 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | ||
329 | break; | 348 | break; |
330 | } | 349 | } |
331 | memcpy(key->conf.key, key_data, key_len); | 350 | memcpy(key->conf.key, key_data, key_len); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 215d3ef42a4f..9572e00f532c 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -144,7 +144,8 @@ struct ieee80211_key { | |||
144 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 144 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, |
145 | int idx, | 145 | int idx, |
146 | size_t key_len, | 146 | size_t key_len, |
147 | const u8 *key_data); | 147 | const u8 *key_data, |
148 | size_t seq_len, const u8 *seq); | ||
148 | /* | 149 | /* |
149 | * Insert a key into data structures (sdata, sta if necessary) | 150 | * Insert a key into data structures (sdata, sta if necessary) |
150 | * to make it used, free old key. | 151 | * to make it used, free old key. |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b80bc80e46cf..76df5eabf268 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -154,15 +154,17 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev) | |||
154 | 154 | ||
155 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 155 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
156 | { | 156 | { |
157 | struct ieee80211_channel *chan; | 157 | struct ieee80211_channel *chan, *scan_chan; |
158 | int ret = 0; | 158 | int ret = 0; |
159 | int power; | 159 | int power; |
160 | enum nl80211_channel_type channel_type; | 160 | enum nl80211_channel_type channel_type; |
161 | 161 | ||
162 | might_sleep(); | 162 | might_sleep(); |
163 | 163 | ||
164 | if (local->sw_scanning) { | 164 | scan_chan = local->scan_channel; |
165 | chan = local->scan_channel; | 165 | |
166 | if (scan_chan) { | ||
167 | chan = scan_chan; | ||
166 | channel_type = NL80211_CHAN_NO_HT; | 168 | channel_type = NL80211_CHAN_NO_HT; |
167 | } else { | 169 | } else { |
168 | chan = local->oper_channel; | 170 | chan = local->oper_channel; |
@@ -176,7 +178,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
176 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 178 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
177 | } | 179 | } |
178 | 180 | ||
179 | if (local->sw_scanning) | 181 | if (scan_chan) |
180 | power = chan->max_power; | 182 | power = chan->max_power; |
181 | else | 183 | else |
182 | power = local->power_constr_level ? | 184 | power = local->power_constr_level ? |
@@ -859,8 +861,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
859 | if (!local->oper_channel) { | 861 | if (!local->oper_channel) { |
860 | /* init channel we're on */ | 862 | /* init channel we're on */ |
861 | local->hw.conf.channel = | 863 | local->hw.conf.channel = |
862 | local->oper_channel = | 864 | local->oper_channel = &sband->channels[0]; |
863 | local->scan_channel = &sband->channels[0]; | 865 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; |
864 | } | 866 | } |
865 | channels += sband->n_channels; | 867 | channels += sband->n_channels; |
866 | 868 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 75c487229f2e..ae030688771f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 33 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
34 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 34 | #define IEEE80211_ASSOC_MAX_TRIES 3 |
35 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) | 35 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) |
36 | #define IEEE80211_PROBE_WAIT (HZ / 20) | ||
36 | #define IEEE80211_PROBE_IDLE_TIME (60 * HZ) | 37 | #define IEEE80211_PROBE_IDLE_TIME (60 * HZ) |
37 | #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) | 38 | #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) |
38 | 39 | ||
@@ -95,16 +96,14 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
95 | struct ieee80211_local *local = sdata->local; | 96 | struct ieee80211_local *local = sdata->local; |
96 | struct ieee80211_supported_band *sband; | 97 | struct ieee80211_supported_band *sband; |
97 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 98 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
98 | struct ieee80211_bss_ht_conf ht; | ||
99 | struct sta_info *sta; | 99 | struct sta_info *sta; |
100 | u32 changed = 0; | 100 | u32 changed = 0; |
101 | u16 ht_opmode; | ||
101 | bool enable_ht = true, ht_changed; | 102 | bool enable_ht = true, ht_changed; |
102 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 103 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
103 | 104 | ||
104 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 105 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
105 | 106 | ||
106 | memset(&ht, 0, sizeof(ht)); | ||
107 | |||
108 | /* HT is not supported */ | 107 | /* HT is not supported */ |
109 | if (!sband->ht_cap.ht_supported) | 108 | if (!sband->ht_cap.ht_supported) |
110 | enable_ht = false; | 109 | enable_ht = false; |
@@ -148,19 +147,20 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
148 | IEEE80211_RC_HT_CHANGED); | 147 | IEEE80211_RC_HT_CHANGED); |
149 | 148 | ||
150 | rcu_read_unlock(); | 149 | rcu_read_unlock(); |
151 | |||
152 | } | 150 | } |
153 | 151 | ||
154 | /* disable HT */ | 152 | /* disable HT */ |
155 | if (!enable_ht) | 153 | if (!enable_ht) |
156 | return 0; | 154 | return 0; |
157 | 155 | ||
158 | ht.operation_mode = le16_to_cpu(hti->operation_mode); | 156 | ht_opmode = le16_to_cpu(hti->operation_mode); |
159 | 157 | ||
160 | /* if bss configuration changed store the new one */ | 158 | /* if bss configuration changed store the new one */ |
161 | if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) { | 159 | if (!sdata->ht_opmode_valid || |
160 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { | ||
162 | changed |= BSS_CHANGED_HT; | 161 | changed |= BSS_CHANGED_HT; |
163 | sdata->vif.bss_conf.ht = ht; | 162 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
163 | sdata->ht_opmode_valid = true; | ||
164 | } | 164 | } |
165 | 165 | ||
166 | return changed; | 166 | return changed; |
@@ -1043,11 +1043,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1043 | 1043 | ||
1044 | rcu_read_unlock(); | 1044 | rcu_read_unlock(); |
1045 | 1045 | ||
1046 | ieee80211_set_wmm_default(sdata); | ||
1047 | |||
1046 | ieee80211_recalc_idle(local); | 1048 | ieee80211_recalc_idle(local); |
1047 | 1049 | ||
1048 | /* channel(_type) changes are handled by ieee80211_hw_config */ | 1050 | /* channel(_type) changes are handled by ieee80211_hw_config */ |
1049 | local->oper_channel_type = NL80211_CHAN_NO_HT; | 1051 | local->oper_channel_type = NL80211_CHAN_NO_HT; |
1050 | 1052 | ||
1053 | /* on the next assoc, re-program HT parameters */ | ||
1054 | sdata->ht_opmode_valid = false; | ||
1055 | |||
1051 | local->power_constr_level = 0; | 1056 | local->power_constr_level = 0; |
1052 | 1057 | ||
1053 | del_timer_sync(&local->dynamic_ps_timer); | 1058 | del_timer_sync(&local->dynamic_ps_timer); |
@@ -1178,6 +1183,17 @@ void ieee80211_beacon_loss_work(struct work_struct *work) | |||
1178 | u.mgd.beacon_loss_work); | 1183 | u.mgd.beacon_loss_work); |
1179 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1184 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1180 | 1185 | ||
1186 | /* | ||
1187 | * The driver has already reported this event and we have | ||
1188 | * already sent a probe request. Maybe the AP died and the | ||
1189 | * driver keeps reporting until we disassociate... We have | ||
1190 | * to ignore that because otherwise we would continually | ||
1191 | * reset the timer and never check whether we received a | ||
1192 | * probe response! | ||
1193 | */ | ||
1194 | if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) | ||
1195 | return; | ||
1196 | |||
1181 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1197 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1182 | if (net_ratelimit()) { | 1198 | if (net_ratelimit()) { |
1183 | printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM " | 1199 | printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM " |
@@ -1190,7 +1206,7 @@ void ieee80211_beacon_loss_work(struct work_struct *work) | |||
1190 | ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, | 1206 | ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, |
1191 | ifmgd->ssid_len, NULL, 0); | 1207 | ifmgd->ssid_len, NULL, 0); |
1192 | 1208 | ||
1193 | mod_timer(&ifmgd->timer, jiffies + IEEE80211_MONITORING_INTERVAL); | 1209 | mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT); |
1194 | } | 1210 | } |
1195 | 1211 | ||
1196 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) | 1212 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) |
@@ -1227,7 +1243,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) | |||
1227 | } | 1243 | } |
1228 | 1244 | ||
1229 | if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) && | 1245 | if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) && |
1230 | time_after(jiffies, sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { | 1246 | time_after(jiffies, sta->last_rx + IEEE80211_PROBE_WAIT)) { |
1231 | printk(KERN_DEBUG "%s: no probe response from AP %pM " | 1247 | printk(KERN_DEBUG "%s: no probe response from AP %pM " |
1232 | "- disassociating\n", | 1248 | "- disassociating\n", |
1233 | sdata->dev->name, ifmgd->bssid); | 1249 | sdata->dev->name, ifmgd->bssid); |
@@ -1577,8 +1593,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1577 | * to between the sta_info_alloc() and sta_info_insert() above. | 1593 | * to between the sta_info_alloc() and sta_info_insert() above. |
1578 | */ | 1594 | */ |
1579 | 1595 | ||
1580 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | | 1596 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP); |
1581 | WLAN_STA_AUTHORIZED); | 1597 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
1598 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
1582 | 1599 | ||
1583 | rates = 0; | 1600 | rates = 0; |
1584 | basic_rates = 0; | 1601 | basic_rates = 0; |
@@ -1658,6 +1675,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1658 | if (elems.wmm_param) | 1675 | if (elems.wmm_param) |
1659 | ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, | 1676 | ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, |
1660 | elems.wmm_param_len); | 1677 | elems.wmm_param_len); |
1678 | else | ||
1679 | ieee80211_set_wmm_default(sdata); | ||
1661 | 1680 | ||
1662 | if (elems.ht_info_elem && elems.wmm_param && | 1681 | if (elems.ht_info_elem && elems.wmm_param && |
1663 | (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && | 1682 | (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d052f4004829..f962bd1b16e2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -630,15 +630,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
630 | * possible. | 630 | * possible. |
631 | */ | 631 | */ |
632 | 632 | ||
633 | if (!ieee80211_has_protected(hdr->frame_control)) { | ||
634 | if (!ieee80211_is_mgmt(hdr->frame_control) || | ||
635 | rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP)) | ||
636 | return RX_CONTINUE; | ||
637 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
638 | if (mmie_keyidx < 0) | ||
639 | return RX_CONTINUE; | ||
640 | } | ||
641 | |||
642 | /* | 633 | /* |
643 | * No point in finding a key and decrypting if the frame is neither | 634 | * No point in finding a key and decrypting if the frame is neither |
644 | * addressed to us nor a multicast frame. | 635 | * addressed to us nor a multicast frame. |
@@ -649,8 +640,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
649 | if (rx->sta) | 640 | if (rx->sta) |
650 | stakey = rcu_dereference(rx->sta->key); | 641 | stakey = rcu_dereference(rx->sta->key); |
651 | 642 | ||
643 | if (!ieee80211_has_protected(hdr->frame_control)) | ||
644 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
645 | |||
652 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 646 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
653 | rx->key = stakey; | 647 | rx->key = stakey; |
648 | /* Skip decryption if the frame is not protected. */ | ||
649 | if (!ieee80211_has_protected(hdr->frame_control)) | ||
650 | return RX_CONTINUE; | ||
654 | } else if (mmie_keyidx >= 0) { | 651 | } else if (mmie_keyidx >= 0) { |
655 | /* Broadcast/multicast robust management frame / BIP */ | 652 | /* Broadcast/multicast robust management frame / BIP */ |
656 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | 653 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && |
@@ -661,6 +658,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
661 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | 658 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) |
662 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | 659 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ |
663 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | 660 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); |
661 | } else if (!ieee80211_has_protected(hdr->frame_control)) { | ||
662 | /* | ||
663 | * The frame was not protected, so skip decryption. However, we | ||
664 | * need to set rx->key if there is a key that could have been | ||
665 | * used so that the frame may be dropped if encryption would | ||
666 | * have been expected. | ||
667 | */ | ||
668 | struct ieee80211_key *key = NULL; | ||
669 | if (ieee80211_is_mgmt(hdr->frame_control) && | ||
670 | is_multicast_ether_addr(hdr->addr1) && | ||
671 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) | ||
672 | rx->key = key; | ||
673 | else if ((key = rcu_dereference(rx->sdata->default_key))) | ||
674 | rx->key = key; | ||
675 | return RX_CONTINUE; | ||
664 | } else { | 676 | } else { |
665 | /* | 677 | /* |
666 | * The device doesn't give us the IV so we won't be | 678 | * The device doesn't give us the IV so we won't be |
@@ -1209,17 +1221,27 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1209 | /* Drop unencrypted frames if key is set. */ | 1221 | /* Drop unencrypted frames if key is set. */ |
1210 | if (unlikely(!ieee80211_has_protected(fc) && | 1222 | if (unlikely(!ieee80211_has_protected(fc) && |
1211 | !ieee80211_is_nullfunc(fc) && | 1223 | !ieee80211_is_nullfunc(fc) && |
1212 | (!ieee80211_is_mgmt(fc) || | 1224 | ieee80211_is_data(fc) && |
1213 | (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1214 | rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) && | ||
1215 | (rx->key || rx->sdata->drop_unencrypted))) | ||
1216 | return -EACCES; | ||
1217 | /* BIP does not use Protected field, so need to check MMIE */ | ||
1218 | if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) && | ||
1219 | ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | ||
1220 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | ||
1221 | (rx->key || rx->sdata->drop_unencrypted))) | 1225 | (rx->key || rx->sdata->drop_unencrypted))) |
1222 | return -EACCES; | 1226 | return -EACCES; |
1227 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | ||
1228 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1229 | rx->key)) | ||
1230 | return -EACCES; | ||
1231 | /* BIP does not use Protected field, so need to check MMIE */ | ||
1232 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) | ||
1233 | && ieee80211_get_mmie_keyidx(rx->skb) < 0 && | ||
1234 | rx->key)) | ||
1235 | return -EACCES; | ||
1236 | /* | ||
1237 | * When using MFP, Action frames are not allowed prior to | ||
1238 | * having configured keys. | ||
1239 | */ | ||
1240 | if (unlikely(ieee80211_is_action(fc) && !rx->key && | ||
1241 | ieee80211_is_robust_mgmt_frame( | ||
1242 | (struct ieee80211_hdr *) rx->skb->data))) | ||
1243 | return -EACCES; | ||
1244 | } | ||
1223 | 1245 | ||
1224 | return 0; | 1246 | return 0; |
1225 | } | 1247 | } |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index c99ef8d04d3d..e65d74ba404b 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -298,6 +298,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
298 | was_hw_scan = local->hw_scanning; | 298 | was_hw_scan = local->hw_scanning; |
299 | local->hw_scanning = false; | 299 | local->hw_scanning = false; |
300 | local->sw_scanning = false; | 300 | local->sw_scanning = false; |
301 | local->scan_channel = NULL; | ||
301 | 302 | ||
302 | /* we only have to protect scan_req and hw/sw scan */ | 303 | /* we only have to protect scan_req and hw/sw scan */ |
303 | mutex_unlock(&local->scan_mtx); | 304 | mutex_unlock(&local->scan_mtx); |
@@ -558,24 +559,39 @@ void ieee80211_scan_work(struct work_struct *work) | |||
558 | if (skip) | 559 | if (skip) |
559 | break; | 560 | break; |
560 | 561 | ||
561 | next_delay = IEEE80211_PROBE_DELAY + | 562 | /* |
562 | usecs_to_jiffies(local->hw.channel_change_time); | 563 | * Probe delay is used to update the NAV, cf. 11.1.3.2.2 |
564 | * (which unfortunately doesn't say _why_ step a) is done, | ||
565 | * but it waits for the probe delay or until a frame is | ||
566 | * received - and the received frame would update the NAV). | ||
567 | * For now, we do not support waiting until a frame is | ||
568 | * received. | ||
569 | * | ||
570 | * In any case, it is not necessary for a passive scan. | ||
571 | */ | ||
572 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
573 | !local->scan_req->n_ssids) { | ||
574 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
575 | break; | ||
576 | } | ||
577 | |||
578 | next_delay = IEEE80211_PROBE_DELAY; | ||
563 | local->scan_state = SCAN_SEND_PROBE; | 579 | local->scan_state = SCAN_SEND_PROBE; |
564 | break; | 580 | break; |
565 | case SCAN_SEND_PROBE: | 581 | case SCAN_SEND_PROBE: |
566 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
567 | local->scan_state = SCAN_SET_CHANNEL; | ||
568 | |||
569 | if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
570 | !local->scan_req->n_ssids) | ||
571 | break; | ||
572 | for (i = 0; i < local->scan_req->n_ssids; i++) | 582 | for (i = 0; i < local->scan_req->n_ssids; i++) |
573 | ieee80211_send_probe_req( | 583 | ieee80211_send_probe_req( |
574 | sdata, NULL, | 584 | sdata, NULL, |
575 | local->scan_req->ssids[i].ssid, | 585 | local->scan_req->ssids[i].ssid, |
576 | local->scan_req->ssids[i].ssid_len, | 586 | local->scan_req->ssids[i].ssid_len, |
577 | local->scan_req->ie, local->scan_req->ie_len); | 587 | local->scan_req->ie, local->scan_req->ie_len); |
588 | |||
589 | /* | ||
590 | * After sending probe requests, wait for probe responses | ||
591 | * on the channel. | ||
592 | */ | ||
578 | next_delay = IEEE80211_CHANNEL_TIME; | 593 | next_delay = IEEE80211_CHANNEL_TIME; |
594 | local->scan_state = SCAN_SET_CHANNEL; | ||
579 | break; | 595 | break; |
580 | } | 596 | } |
581 | 597 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 5f9a8d7af83d..8f68bf9746d0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1087,7 +1087,10 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1087 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 1087 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
1088 | } else { | 1088 | } else { |
1089 | tx->flags |= IEEE80211_TX_UNICAST; | 1089 | tx->flags |= IEEE80211_TX_UNICAST; |
1090 | info->flags &= ~IEEE80211_TX_CTL_NO_ACK; | 1090 | if (unlikely(local->wifi_wme_noack_test)) |
1091 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1092 | else | ||
1093 | info->flags &= ~IEEE80211_TX_CTL_NO_ACK; | ||
1091 | } | 1094 | } |
1092 | 1095 | ||
1093 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { | 1096 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 97b613affe08..0689a8fbd1e6 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -708,26 +708,62 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
708 | { | 708 | { |
709 | struct ieee80211_local *local = sdata->local; | 709 | struct ieee80211_local *local = sdata->local; |
710 | struct ieee80211_tx_queue_params qparam; | 710 | struct ieee80211_tx_queue_params qparam; |
711 | int i; | 711 | int queue; |
712 | bool use_11b; | ||
713 | int aCWmin, aCWmax; | ||
712 | 714 | ||
713 | if (!local->ops->conf_tx) | 715 | if (!local->ops->conf_tx) |
714 | return; | 716 | return; |
715 | 717 | ||
716 | memset(&qparam, 0, sizeof(qparam)); | 718 | memset(&qparam, 0, sizeof(qparam)); |
717 | 719 | ||
718 | qparam.aifs = 2; | 720 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && |
719 | 721 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | |
720 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
721 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | ||
722 | qparam.cw_min = 31; | ||
723 | else | ||
724 | qparam.cw_min = 15; | ||
725 | 722 | ||
726 | qparam.cw_max = 1023; | 723 | for (queue = 0; queue < local_to_hw(local)->queues; queue++) { |
727 | qparam.txop = 0; | 724 | /* Set defaults according to 802.11-2007 Table 7-37 */ |
725 | aCWmax = 1023; | ||
726 | if (use_11b) | ||
727 | aCWmin = 31; | ||
728 | else | ||
729 | aCWmin = 15; | ||
730 | |||
731 | switch (queue) { | ||
732 | case 3: /* AC_BK */ | ||
733 | qparam.cw_max = aCWmin; | ||
734 | qparam.cw_min = aCWmax; | ||
735 | qparam.txop = 0; | ||
736 | qparam.aifs = 7; | ||
737 | break; | ||
738 | default: /* never happens but let's not leave undefined */ | ||
739 | case 2: /* AC_BE */ | ||
740 | qparam.cw_max = aCWmin; | ||
741 | qparam.cw_min = aCWmax; | ||
742 | qparam.txop = 0; | ||
743 | qparam.aifs = 3; | ||
744 | break; | ||
745 | case 1: /* AC_VI */ | ||
746 | qparam.cw_max = aCWmin; | ||
747 | qparam.cw_min = (aCWmin + 1) / 2 - 1; | ||
748 | if (use_11b) | ||
749 | qparam.txop = 6016/32; | ||
750 | else | ||
751 | qparam.txop = 3008/32; | ||
752 | qparam.aifs = 2; | ||
753 | break; | ||
754 | case 0: /* AC_VO */ | ||
755 | qparam.cw_max = (aCWmin + 1) / 2 - 1; | ||
756 | qparam.cw_min = (aCWmin + 1) / 4 - 1; | ||
757 | if (use_11b) | ||
758 | qparam.txop = 3264/32; | ||
759 | else | ||
760 | qparam.txop = 1504/32; | ||
761 | qparam.aifs = 2; | ||
762 | break; | ||
763 | } | ||
728 | 764 | ||
729 | for (i = 0; i < local_to_hw(local)->queues; i++) | 765 | drv_conf_tx(local, queue, &qparam); |
730 | drv_conf_tx(local, i, &qparam); | 766 | } |
731 | } | 767 | } |
732 | 768 | ||
733 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 769 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 6b4eb8d43a4e..c14394744a9c 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -27,100 +27,6 @@ | |||
27 | #include "aes_ccm.h" | 27 | #include "aes_ccm.h" |
28 | 28 | ||
29 | 29 | ||
30 | static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr, | ||
31 | int idx, int alg, int remove, | ||
32 | int set_tx_key, const u8 *_key, | ||
33 | size_t key_len) | ||
34 | { | ||
35 | struct ieee80211_local *local = sdata->local; | ||
36 | struct sta_info *sta; | ||
37 | struct ieee80211_key *key; | ||
38 | int err; | ||
39 | |||
40 | if (alg == ALG_AES_CMAC) { | ||
41 | if (idx < NUM_DEFAULT_KEYS || | ||
42 | idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { | ||
43 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d " | ||
44 | "(BIP)\n", sdata->dev->name, idx); | ||
45 | return -EINVAL; | ||
46 | } | ||
47 | } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { | ||
48 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", | ||
49 | sdata->dev->name, idx); | ||
50 | return -EINVAL; | ||
51 | } | ||
52 | |||
53 | if (remove) { | ||
54 | rcu_read_lock(); | ||
55 | |||
56 | err = 0; | ||
57 | |||
58 | if (is_broadcast_ether_addr(sta_addr)) { | ||
59 | key = sdata->keys[idx]; | ||
60 | } else { | ||
61 | sta = sta_info_get(local, sta_addr); | ||
62 | if (!sta) { | ||
63 | err = -ENOENT; | ||
64 | goto out_unlock; | ||
65 | } | ||
66 | key = sta->key; | ||
67 | } | ||
68 | |||
69 | ieee80211_key_free(key); | ||
70 | } else { | ||
71 | key = ieee80211_key_alloc(alg, idx, key_len, _key); | ||
72 | if (!key) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | sta = NULL; | ||
76 | err = 0; | ||
77 | |||
78 | rcu_read_lock(); | ||
79 | |||
80 | if (!is_broadcast_ether_addr(sta_addr)) { | ||
81 | set_tx_key = 0; | ||
82 | /* | ||
83 | * According to the standard, the key index of a | ||
84 | * pairwise key must be zero. However, some AP are | ||
85 | * broken when it comes to WEP key indices, so we | ||
86 | * work around this. | ||
87 | */ | ||
88 | if (idx != 0 && alg != ALG_WEP) { | ||
89 | ieee80211_key_free(key); | ||
90 | err = -EINVAL; | ||
91 | goto out_unlock; | ||
92 | } | ||
93 | |||
94 | sta = sta_info_get(local, sta_addr); | ||
95 | if (!sta) { | ||
96 | ieee80211_key_free(key); | ||
97 | err = -ENOENT; | ||
98 | goto out_unlock; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | if (alg == ALG_WEP && | ||
103 | key_len != LEN_WEP40 && key_len != LEN_WEP104) { | ||
104 | ieee80211_key_free(key); | ||
105 | err = -EINVAL; | ||
106 | goto out_unlock; | ||
107 | } | ||
108 | |||
109 | ieee80211_key_link(key, sdata, sta); | ||
110 | |||
111 | if (set_tx_key || (!sta && !sdata->default_key && key)) | ||
112 | ieee80211_set_default_key(sdata, idx); | ||
113 | if (alg == ALG_AES_CMAC && | ||
114 | (set_tx_key || (!sta && !sdata->default_mgmt_key && key))) | ||
115 | ieee80211_set_default_mgmt_key(sdata, idx); | ||
116 | } | ||
117 | |||
118 | out_unlock: | ||
119 | rcu_read_unlock(); | ||
120 | |||
121 | return err; | ||
122 | } | ||
123 | |||
124 | static int ieee80211_ioctl_siwgenie(struct net_device *dev, | 30 | static int ieee80211_ioctl_siwgenie(struct net_device *dev, |
125 | struct iw_request_info *info, | 31 | struct iw_request_info *info, |
126 | struct iw_point *data, char *extra) | 32 | struct iw_point *data, char *extra) |
@@ -135,6 +41,7 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, | |||
135 | return ret; | 41 | return ret; |
136 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | 42 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; |
137 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | 43 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; |
44 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
138 | ieee80211_sta_req_auth(sdata); | 45 | ieee80211_sta_req_auth(sdata); |
139 | return 0; | 46 | return 0; |
140 | } | 47 | } |
@@ -218,6 +125,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
218 | return ret; | 125 | return ret; |
219 | 126 | ||
220 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | 127 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; |
128 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
221 | ieee80211_sta_req_auth(sdata); | 129 | ieee80211_sta_req_auth(sdata); |
222 | return 0; | 130 | return 0; |
223 | } | 131 | } |
@@ -275,6 +183,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
275 | if (ret) | 183 | if (ret) |
276 | return ret; | 184 | return ret; |
277 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | 185 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; |
186 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
278 | ieee80211_sta_req_auth(sdata); | 187 | ieee80211_sta_req_auth(sdata); |
279 | return 0; | 188 | return 0; |
280 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { | 189 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
@@ -472,109 +381,6 @@ static int ieee80211_ioctl_giwtxpower(struct net_device *dev, | |||
472 | return 0; | 381 | return 0; |
473 | } | 382 | } |
474 | 383 | ||
475 | static int ieee80211_ioctl_siwencode(struct net_device *dev, | ||
476 | struct iw_request_info *info, | ||
477 | struct iw_point *erq, char *keybuf) | ||
478 | { | ||
479 | struct ieee80211_sub_if_data *sdata; | ||
480 | int idx, i, alg = ALG_WEP; | ||
481 | u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
482 | int remove = 0, ret; | ||
483 | |||
484 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
485 | |||
486 | idx = erq->flags & IW_ENCODE_INDEX; | ||
487 | if (idx == 0) { | ||
488 | if (sdata->default_key) | ||
489 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
490 | if (sdata->default_key == sdata->keys[i]) { | ||
491 | idx = i; | ||
492 | break; | ||
493 | } | ||
494 | } | ||
495 | } else if (idx < 1 || idx > 4) | ||
496 | return -EINVAL; | ||
497 | else | ||
498 | idx--; | ||
499 | |||
500 | if (erq->flags & IW_ENCODE_DISABLED) | ||
501 | remove = 1; | ||
502 | else if (erq->length == 0) { | ||
503 | /* No key data - just set the default TX key index */ | ||
504 | ieee80211_set_default_key(sdata, idx); | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | ret = ieee80211_set_encryption( | ||
509 | sdata, bcaddr, | ||
510 | idx, alg, remove, | ||
511 | !sdata->default_key, | ||
512 | keybuf, erq->length); | ||
513 | |||
514 | if (!ret && sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
515 | if (remove) | ||
516 | sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED; | ||
517 | else | ||
518 | sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED; | ||
519 | } | ||
520 | |||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | |||
525 | static int ieee80211_ioctl_giwencode(struct net_device *dev, | ||
526 | struct iw_request_info *info, | ||
527 | struct iw_point *erq, char *key) | ||
528 | { | ||
529 | struct ieee80211_sub_if_data *sdata; | ||
530 | int idx, i; | ||
531 | |||
532 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
533 | |||
534 | idx = erq->flags & IW_ENCODE_INDEX; | ||
535 | if (idx < 1 || idx > 4) { | ||
536 | idx = -1; | ||
537 | if (!sdata->default_key) | ||
538 | idx = 0; | ||
539 | else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
540 | if (sdata->default_key == sdata->keys[i]) { | ||
541 | idx = i; | ||
542 | break; | ||
543 | } | ||
544 | } | ||
545 | if (idx < 0) | ||
546 | return -EINVAL; | ||
547 | } else | ||
548 | idx--; | ||
549 | |||
550 | erq->flags = idx + 1; | ||
551 | |||
552 | if (!sdata->keys[idx]) { | ||
553 | erq->length = 0; | ||
554 | erq->flags |= IW_ENCODE_DISABLED; | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | memcpy(key, sdata->keys[idx]->conf.key, | ||
559 | min_t(int, erq->length, sdata->keys[idx]->conf.keylen)); | ||
560 | erq->length = sdata->keys[idx]->conf.keylen; | ||
561 | erq->flags |= IW_ENCODE_ENABLED; | ||
562 | |||
563 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
564 | switch (sdata->u.mgd.auth_alg) { | ||
565 | case WLAN_AUTH_OPEN: | ||
566 | case WLAN_AUTH_LEAP: | ||
567 | erq->flags |= IW_ENCODE_OPEN; | ||
568 | break; | ||
569 | case WLAN_AUTH_SHARED_KEY: | ||
570 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
571 | break; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static int ieee80211_ioctl_siwpower(struct net_device *dev, | 384 | static int ieee80211_ioctl_siwpower(struct net_device *dev, |
579 | struct iw_request_info *info, | 385 | struct iw_request_info *info, |
580 | struct iw_param *wrq, | 386 | struct iw_param *wrq, |
@@ -809,82 +615,6 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev, | |||
809 | } | 615 | } |
810 | 616 | ||
811 | 617 | ||
812 | static int ieee80211_ioctl_siwencodeext(struct net_device *dev, | ||
813 | struct iw_request_info *info, | ||
814 | struct iw_point *erq, char *extra) | ||
815 | { | ||
816 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
817 | struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; | ||
818 | int uninitialized_var(alg), idx, i, remove = 0; | ||
819 | |||
820 | switch (ext->alg) { | ||
821 | case IW_ENCODE_ALG_NONE: | ||
822 | remove = 1; | ||
823 | break; | ||
824 | case IW_ENCODE_ALG_WEP: | ||
825 | alg = ALG_WEP; | ||
826 | break; | ||
827 | case IW_ENCODE_ALG_TKIP: | ||
828 | alg = ALG_TKIP; | ||
829 | break; | ||
830 | case IW_ENCODE_ALG_CCMP: | ||
831 | alg = ALG_CCMP; | ||
832 | break; | ||
833 | case IW_ENCODE_ALG_AES_CMAC: | ||
834 | alg = ALG_AES_CMAC; | ||
835 | break; | ||
836 | default: | ||
837 | return -EOPNOTSUPP; | ||
838 | } | ||
839 | |||
840 | if (erq->flags & IW_ENCODE_DISABLED) | ||
841 | remove = 1; | ||
842 | |||
843 | idx = erq->flags & IW_ENCODE_INDEX; | ||
844 | if (alg == ALG_AES_CMAC) { | ||
845 | if (idx < NUM_DEFAULT_KEYS + 1 || | ||
846 | idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { | ||
847 | idx = -1; | ||
848 | if (!sdata->default_mgmt_key) | ||
849 | idx = 0; | ||
850 | else for (i = NUM_DEFAULT_KEYS; | ||
851 | i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS; | ||
852 | i++) { | ||
853 | if (sdata->default_mgmt_key == sdata->keys[i]) | ||
854 | { | ||
855 | idx = i; | ||
856 | break; | ||
857 | } | ||
858 | } | ||
859 | if (idx < 0) | ||
860 | return -EINVAL; | ||
861 | } else | ||
862 | idx--; | ||
863 | } else { | ||
864 | if (idx < 1 || idx > 4) { | ||
865 | idx = -1; | ||
866 | if (!sdata->default_key) | ||
867 | idx = 0; | ||
868 | else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
869 | if (sdata->default_key == sdata->keys[i]) { | ||
870 | idx = i; | ||
871 | break; | ||
872 | } | ||
873 | } | ||
874 | if (idx < 0) | ||
875 | return -EINVAL; | ||
876 | } else | ||
877 | idx--; | ||
878 | } | ||
879 | |||
880 | return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, | ||
881 | remove, | ||
882 | ext->ext_flags & | ||
883 | IW_ENCODE_EXT_SET_TX_KEY, | ||
884 | ext->key, ext->key_len); | ||
885 | } | ||
886 | |||
887 | |||
888 | /* Structures to export the Wireless Handlers */ | 618 | /* Structures to export the Wireless Handlers */ |
889 | 619 | ||
890 | static const iw_handler ieee80211_handler[] = | 620 | static const iw_handler ieee80211_handler[] = |
@@ -931,8 +661,8 @@ static const iw_handler ieee80211_handler[] = | |||
931 | (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ | 661 | (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ |
932 | (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ | 662 | (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ |
933 | (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ | 663 | (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ |
934 | (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ | 664 | (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ |
935 | (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ | 665 | (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ |
936 | (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ | 666 | (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ |
937 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ | 667 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ |
938 | (iw_handler) NULL, /* -- hole -- */ | 668 | (iw_handler) NULL, /* -- hole -- */ |
@@ -941,7 +671,7 @@ static const iw_handler ieee80211_handler[] = | |||
941 | (iw_handler) NULL, /* SIOCGIWGENIE */ | 671 | (iw_handler) NULL, /* SIOCGIWGENIE */ |
942 | (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */ | 672 | (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */ |
943 | (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */ | 673 | (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */ |
944 | (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ | 674 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ |
945 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ | 675 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ |
946 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 676 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
947 | (iw_handler) NULL, /* -- hole -- */ | 677 | (iw_handler) NULL, /* -- hole -- */ |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 0b8ad1f4ecdd..45b74f38b867 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -133,7 +133,7 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | |||
133 | u8 *p = ieee80211_get_qos_ctl(hdr); | 133 | u8 *p = ieee80211_get_qos_ctl(hdr); |
134 | u8 ack_policy = 0; | 134 | u8 ack_policy = 0; |
135 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | 135 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
136 | if (local->wifi_wme_noack_test) | 136 | if (unlikely(local->wifi_wme_noack_test)) |
137 | ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << | 137 | ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << |
138 | QOS_CONTROL_ACK_POLICY_SHIFT; | 138 | QOS_CONTROL_ACK_POLICY_SHIFT; |
139 | /* qos header is 2 bytes, second reserved */ | 139 | /* qos header is 2 bytes, second reserved */ |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 2006a4ee60eb..47c20eb0c04d 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This is the linux wireless configuration interface. | 2 | * This is the linux wireless configuration interface. |
3 | * | 3 | * |
4 | * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/if.h> | 7 | #include <linux/if.h> |
@@ -457,6 +457,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
457 | "symlink to netdev!\n"); | 457 | "symlink to netdev!\n"); |
458 | } | 458 | } |
459 | dev->ieee80211_ptr->netdev = dev; | 459 | dev->ieee80211_ptr->netdev = dev; |
460 | #ifdef CONFIG_WIRELESS_EXT | ||
461 | dev->ieee80211_ptr->wext.default_key = -1; | ||
462 | dev->ieee80211_ptr->wext.default_mgmt_key = -1; | ||
463 | #endif | ||
460 | mutex_unlock(&rdev->devlist_mtx); | 464 | mutex_unlock(&rdev->devlist_mtx); |
461 | break; | 465 | break; |
462 | case NETDEV_GOING_DOWN: | 466 | case NETDEV_GOING_DOWN: |
@@ -470,9 +474,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
470 | #ifdef CONFIG_WIRELESS_EXT | 474 | #ifdef CONFIG_WIRELESS_EXT |
471 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) | 475 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) |
472 | break; | 476 | break; |
473 | if (!dev->ieee80211_ptr->wext.ssid_len) | 477 | if (!dev->ieee80211_ptr->wext.ibss.ssid_len) |
474 | break; | 478 | break; |
475 | cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext); | 479 | cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext.ibss); |
476 | break; | 480 | break; |
477 | #endif | 481 | #endif |
478 | case NETDEV_UNREGISTER: | 482 | case NETDEV_UNREGISTER: |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 3e49d3399311..f14b6c5f4221 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Wireless configuration interface internals. | 2 | * Wireless configuration interface internals. |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net> |
5 | */ | 5 | */ |
6 | #ifndef __NET_WIRELESS_CORE_H | 6 | #ifndef __NET_WIRELESS_CORE_H |
7 | #define __NET_WIRELESS_CORE_H | 7 | #define __NET_WIRELESS_CORE_H |
@@ -151,4 +151,8 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext); | |||
151 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 151 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
152 | struct net_device *dev, bool nowext); | 152 | struct net_device *dev, bool nowext); |
153 | 153 | ||
154 | /* internal helpers */ | ||
155 | int cfg80211_validate_key_settings(struct key_params *params, int key_idx, | ||
156 | const u8 *mac_addr); | ||
157 | |||
154 | #endif /* __NET_WIRELESS_CORE_H */ | 158 | #endif /* __NET_WIRELESS_CORE_H */ |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 3c38afaed28a..a4a1c3498ff2 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -63,7 +63,7 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
63 | return -EALREADY; | 63 | return -EALREADY; |
64 | 64 | ||
65 | #ifdef CONFIG_WIRELESS_EXT | 65 | #ifdef CONFIG_WIRELESS_EXT |
66 | wdev->wext.channel = params->channel; | 66 | wdev->wext.ibss.channel = params->channel; |
67 | #endif | 67 | #endif |
68 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); | 68 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); |
69 | 69 | ||
@@ -90,7 +90,7 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
90 | memset(wdev->bssid, 0, ETH_ALEN); | 90 | memset(wdev->bssid, 0, ETH_ALEN); |
91 | #ifdef CONFIG_WIRELESS_EXT | 91 | #ifdef CONFIG_WIRELESS_EXT |
92 | if (!nowext) | 92 | if (!nowext) |
93 | wdev->wext.ssid_len = 0; | 93 | wdev->wext.ibss.ssid_len = 0; |
94 | #endif | 94 | #endif |
95 | } | 95 | } |
96 | 96 | ||
@@ -116,11 +116,11 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
116 | enum ieee80211_band band; | 116 | enum ieee80211_band band; |
117 | int i; | 117 | int i; |
118 | 118 | ||
119 | if (!wdev->wext.beacon_interval) | 119 | if (!wdev->wext.ibss.beacon_interval) |
120 | wdev->wext.beacon_interval = 100; | 120 | wdev->wext.ibss.beacon_interval = 100; |
121 | 121 | ||
122 | /* try to find an IBSS channel if none requested ... */ | 122 | /* try to find an IBSS channel if none requested ... */ |
123 | if (!wdev->wext.channel) { | 123 | if (!wdev->wext.ibss.channel) { |
124 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 124 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
125 | struct ieee80211_supported_band *sband; | 125 | struct ieee80211_supported_band *sband; |
126 | struct ieee80211_channel *chan; | 126 | struct ieee80211_channel *chan; |
@@ -135,27 +135,27 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
135 | continue; | 135 | continue; |
136 | if (chan->flags & IEEE80211_CHAN_DISABLED) | 136 | if (chan->flags & IEEE80211_CHAN_DISABLED) |
137 | continue; | 137 | continue; |
138 | wdev->wext.channel = chan; | 138 | wdev->wext.ibss.channel = chan; |
139 | break; | 139 | break; |
140 | } | 140 | } |
141 | 141 | ||
142 | if (wdev->wext.channel) | 142 | if (wdev->wext.ibss.channel) |
143 | break; | 143 | break; |
144 | } | 144 | } |
145 | 145 | ||
146 | if (!wdev->wext.channel) | 146 | if (!wdev->wext.ibss.channel) |
147 | return -EINVAL; | 147 | return -EINVAL; |
148 | } | 148 | } |
149 | 149 | ||
150 | /* don't join -- SSID is not there */ | 150 | /* don't join -- SSID is not there */ |
151 | if (!wdev->wext.ssid_len) | 151 | if (!wdev->wext.ibss.ssid_len) |
152 | return 0; | 152 | return 0; |
153 | 153 | ||
154 | if (!netif_running(wdev->netdev)) | 154 | if (!netif_running(wdev->netdev)) |
155 | return 0; | 155 | return 0; |
156 | 156 | ||
157 | return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy), | 157 | return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy), |
158 | wdev->netdev, &wdev->wext); | 158 | wdev->netdev, &wdev->wext.ibss); |
159 | } | 159 | } |
160 | 160 | ||
161 | int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | 161 | int cfg80211_ibss_wext_siwfreq(struct net_device *dev, |
@@ -182,7 +182,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | |||
182 | chan->flags & IEEE80211_CHAN_DISABLED)) | 182 | chan->flags & IEEE80211_CHAN_DISABLED)) |
183 | return -EINVAL; | 183 | return -EINVAL; |
184 | 184 | ||
185 | if (wdev->wext.channel == chan) | 185 | if (wdev->wext.ibss.channel == chan) |
186 | return 0; | 186 | return 0; |
187 | 187 | ||
188 | if (wdev->ssid_len) { | 188 | if (wdev->ssid_len) { |
@@ -193,11 +193,11 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | |||
193 | } | 193 | } |
194 | 194 | ||
195 | if (chan) { | 195 | if (chan) { |
196 | wdev->wext.channel = chan; | 196 | wdev->wext.ibss.channel = chan; |
197 | wdev->wext.channel_fixed = true; | 197 | wdev->wext.ibss.channel_fixed = true; |
198 | } else { | 198 | } else { |
199 | /* cfg80211_ibss_wext_join will pick one if needed */ | 199 | /* cfg80211_ibss_wext_join will pick one if needed */ |
200 | wdev->wext.channel_fixed = false; | 200 | wdev->wext.ibss.channel_fixed = false; |
201 | } | 201 | } |
202 | 202 | ||
203 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 203 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); |
@@ -218,8 +218,8 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev, | |||
218 | 218 | ||
219 | if (wdev->current_bss) | 219 | if (wdev->current_bss) |
220 | chan = wdev->current_bss->channel; | 220 | chan = wdev->current_bss->channel; |
221 | else if (wdev->wext.channel) | 221 | else if (wdev->wext.ibss.channel) |
222 | chan = wdev->wext.channel; | 222 | chan = wdev->wext.ibss.channel; |
223 | 223 | ||
224 | if (chan) { | 224 | if (chan) { |
225 | freq->m = chan->center_freq; | 225 | freq->m = chan->center_freq; |
@@ -259,9 +259,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, | |||
259 | if (len > 0 && ssid[len - 1] == '\0') | 259 | if (len > 0 && ssid[len - 1] == '\0') |
260 | len--; | 260 | len--; |
261 | 261 | ||
262 | wdev->wext.ssid = wdev->ssid; | 262 | wdev->wext.ibss.ssid = wdev->ssid; |
263 | memcpy(wdev->wext.ssid, ssid, len); | 263 | memcpy(wdev->wext.ibss.ssid, ssid, len); |
264 | wdev->wext.ssid_len = len; | 264 | wdev->wext.ibss.ssid_len = len; |
265 | 265 | ||
266 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 266 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); |
267 | } | 267 | } |
@@ -284,10 +284,10 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev, | |||
284 | data->flags = 1; | 284 | data->flags = 1; |
285 | data->length = wdev->ssid_len; | 285 | data->length = wdev->ssid_len; |
286 | memcpy(ssid, wdev->ssid, data->length); | 286 | memcpy(ssid, wdev->ssid, data->length); |
287 | } else if (wdev->wext.ssid && wdev->wext.ssid_len) { | 287 | } else if (wdev->wext.ibss.ssid && wdev->wext.ibss.ssid_len) { |
288 | data->flags = 1; | 288 | data->flags = 1; |
289 | data->length = wdev->wext.ssid_len; | 289 | data->length = wdev->wext.ibss.ssid_len; |
290 | memcpy(ssid, wdev->wext.ssid, data->length); | 290 | memcpy(ssid, wdev->wext.ibss.ssid, data->length); |
291 | } | 291 | } |
292 | 292 | ||
293 | return 0; | 293 | return 0; |
@@ -318,12 +318,12 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, | |||
318 | bssid = NULL; | 318 | bssid = NULL; |
319 | 319 | ||
320 | /* both automatic */ | 320 | /* both automatic */ |
321 | if (!bssid && !wdev->wext.bssid) | 321 | if (!bssid && !wdev->wext.ibss.bssid) |
322 | return 0; | 322 | return 0; |
323 | 323 | ||
324 | /* fixed already - and no change */ | 324 | /* fixed already - and no change */ |
325 | if (wdev->wext.bssid && bssid && | 325 | if (wdev->wext.ibss.bssid && bssid && |
326 | compare_ether_addr(bssid, wdev->wext.bssid) == 0) | 326 | compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0) |
327 | return 0; | 327 | return 0; |
328 | 328 | ||
329 | if (wdev->ssid_len) { | 329 | if (wdev->ssid_len) { |
@@ -334,10 +334,10 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, | |||
334 | } | 334 | } |
335 | 335 | ||
336 | if (bssid) { | 336 | if (bssid) { |
337 | memcpy(wdev->wext_bssid, bssid, ETH_ALEN); | 337 | memcpy(wdev->wext.bssid, bssid, ETH_ALEN); |
338 | wdev->wext.bssid = wdev->wext_bssid; | 338 | wdev->wext.ibss.bssid = wdev->wext.bssid; |
339 | } else | 339 | } else |
340 | wdev->wext.bssid = NULL; | 340 | wdev->wext.ibss.bssid = NULL; |
341 | 341 | ||
342 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 342 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); |
343 | } | 343 | } |
@@ -356,8 +356,8 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev, | |||
356 | 356 | ||
357 | ap_addr->sa_family = ARPHRD_ETHER; | 357 | ap_addr->sa_family = ARPHRD_ETHER; |
358 | 358 | ||
359 | if (wdev->wext.bssid) { | 359 | if (wdev->wext.ibss.bssid) { |
360 | memcpy(ap_addr->sa_data, wdev->wext.bssid, ETH_ALEN); | 360 | memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN); |
361 | return 0; | 361 | return 0; |
362 | } | 362 | } |
363 | 363 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 3c53c5cbc3a9..f0fec2f49828 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This is the new netlink-based wireless configuration interface. | 2 | * This is the new netlink-based wireless configuration interface. |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/if.h> | 7 | #include <linux/if.h> |
@@ -122,6 +122,11 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
122 | [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, | 122 | [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, |
123 | [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG }, | 123 | [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG }, |
124 | [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG }, | 124 | [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG }, |
125 | [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 }, | ||
126 | [NL80211_ATTR_STA_FLAGS2] = { | ||
127 | .len = sizeof(struct nl80211_sta_flag_update), | ||
128 | }, | ||
129 | [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, | ||
125 | }; | 130 | }; |
126 | 131 | ||
127 | /* IE validation */ | 132 | /* IE validation */ |
@@ -1072,6 +1077,14 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1072 | } | 1077 | } |
1073 | 1078 | ||
1074 | err = func(&drv->wiphy, dev, key_idx); | 1079 | err = func(&drv->wiphy, dev, key_idx); |
1080 | #ifdef CONFIG_WIRELESS_EXT | ||
1081 | if (!err) { | ||
1082 | if (func == drv->ops->set_default_key) | ||
1083 | dev->ieee80211_ptr->wext.default_key = key_idx; | ||
1084 | else | ||
1085 | dev->ieee80211_ptr->wext.default_mgmt_key = key_idx; | ||
1086 | } | ||
1087 | #endif | ||
1075 | 1088 | ||
1076 | out: | 1089 | out: |
1077 | cfg80211_put_dev(drv); | 1090 | cfg80211_put_dev(drv); |
@@ -1102,6 +1115,11 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
1102 | params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); | 1115 | params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); |
1103 | } | 1116 | } |
1104 | 1117 | ||
1118 | if (info->attrs[NL80211_ATTR_KEY_SEQ]) { | ||
1119 | params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]); | ||
1120 | params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]); | ||
1121 | } | ||
1122 | |||
1105 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | 1123 | if (info->attrs[NL80211_ATTR_KEY_IDX]) |
1106 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 1124 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
1107 | 1125 | ||
@@ -1110,44 +1128,8 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
1110 | if (info->attrs[NL80211_ATTR_MAC]) | 1128 | if (info->attrs[NL80211_ATTR_MAC]) |
1111 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1129 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1112 | 1130 | ||
1113 | if (key_idx > 5) | 1131 | if (cfg80211_validate_key_settings(¶ms, key_idx, mac_addr)) |
1114 | return -EINVAL; | ||
1115 | |||
1116 | /* | ||
1117 | * Disallow pairwise keys with non-zero index unless it's WEP | ||
1118 | * (because current deployments use pairwise WEP keys with | ||
1119 | * non-zero indizes but 802.11i clearly specifies to use zero) | ||
1120 | */ | ||
1121 | if (mac_addr && key_idx && | ||
1122 | params.cipher != WLAN_CIPHER_SUITE_WEP40 && | ||
1123 | params.cipher != WLAN_CIPHER_SUITE_WEP104) | ||
1124 | return -EINVAL; | ||
1125 | |||
1126 | /* TODO: add definitions for the lengths to linux/ieee80211.h */ | ||
1127 | switch (params.cipher) { | ||
1128 | case WLAN_CIPHER_SUITE_WEP40: | ||
1129 | if (params.key_len != 5) | ||
1130 | return -EINVAL; | ||
1131 | break; | ||
1132 | case WLAN_CIPHER_SUITE_TKIP: | ||
1133 | if (params.key_len != 32) | ||
1134 | return -EINVAL; | ||
1135 | break; | ||
1136 | case WLAN_CIPHER_SUITE_CCMP: | ||
1137 | if (params.key_len != 16) | ||
1138 | return -EINVAL; | ||
1139 | break; | ||
1140 | case WLAN_CIPHER_SUITE_WEP104: | ||
1141 | if (params.key_len != 13) | ||
1142 | return -EINVAL; | ||
1143 | break; | ||
1144 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
1145 | if (params.key_len != 16) | ||
1146 | return -EINVAL; | ||
1147 | break; | ||
1148 | default: | ||
1149 | return -EINVAL; | 1132 | return -EINVAL; |
1150 | } | ||
1151 | 1133 | ||
1152 | rtnl_lock(); | 1134 | rtnl_lock(); |
1153 | 1135 | ||
@@ -1209,6 +1191,15 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
1209 | 1191 | ||
1210 | err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); | 1192 | err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); |
1211 | 1193 | ||
1194 | #ifdef CONFIG_WIRELESS_EXT | ||
1195 | if (!err) { | ||
1196 | if (key_idx == dev->ieee80211_ptr->wext.default_key) | ||
1197 | dev->ieee80211_ptr->wext.default_key = -1; | ||
1198 | else if (key_idx == dev->ieee80211_ptr->wext.default_mgmt_key) | ||
1199 | dev->ieee80211_ptr->wext.default_mgmt_key = -1; | ||
1200 | } | ||
1201 | #endif | ||
1202 | |||
1212 | out: | 1203 | out: |
1213 | cfg80211_put_dev(drv); | 1204 | cfg80211_put_dev(drv); |
1214 | dev_put(dev); | 1205 | dev_put(dev); |
@@ -1349,15 +1340,36 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | |||
1349 | [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG }, | 1340 | [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG }, |
1350 | [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, | 1341 | [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, |
1351 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, | 1342 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, |
1343 | [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, | ||
1352 | }; | 1344 | }; |
1353 | 1345 | ||
1354 | static int parse_station_flags(struct nlattr *nla, u32 *staflags) | 1346 | static int parse_station_flags(struct genl_info *info, |
1347 | struct station_parameters *params) | ||
1355 | { | 1348 | { |
1356 | struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; | 1349 | struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; |
1350 | struct nlattr *nla; | ||
1357 | int flag; | 1351 | int flag; |
1358 | 1352 | ||
1359 | *staflags = 0; | 1353 | /* |
1354 | * Try parsing the new attribute first so userspace | ||
1355 | * can specify both for older kernels. | ||
1356 | */ | ||
1357 | nla = info->attrs[NL80211_ATTR_STA_FLAGS2]; | ||
1358 | if (nla) { | ||
1359 | struct nl80211_sta_flag_update *sta_flags; | ||
1360 | |||
1361 | sta_flags = nla_data(nla); | ||
1362 | params->sta_flags_mask = sta_flags->mask; | ||
1363 | params->sta_flags_set = sta_flags->set; | ||
1364 | if ((params->sta_flags_mask | | ||
1365 | params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID)) | ||
1366 | return -EINVAL; | ||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1370 | /* if present, parse the old attribute */ | ||
1360 | 1371 | ||
1372 | nla = info->attrs[NL80211_ATTR_STA_FLAGS]; | ||
1361 | if (!nla) | 1373 | if (!nla) |
1362 | return 0; | 1374 | return 0; |
1363 | 1375 | ||
@@ -1365,11 +1377,12 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags) | |||
1365 | nla, sta_flags_policy)) | 1377 | nla, sta_flags_policy)) |
1366 | return -EINVAL; | 1378 | return -EINVAL; |
1367 | 1379 | ||
1368 | *staflags = STATION_FLAG_CHANGED; | 1380 | params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1; |
1381 | params->sta_flags_mask &= ~1; | ||
1369 | 1382 | ||
1370 | for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) | 1383 | for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) |
1371 | if (flags[flag]) | 1384 | if (flags[flag]) |
1372 | *staflags |= (1<<flag); | 1385 | params->sta_flags_set |= (1<<flag); |
1373 | 1386 | ||
1374 | return 0; | 1387 | return 0; |
1375 | } | 1388 | } |
@@ -1665,8 +1678,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
1665 | params.ht_capa = | 1678 | params.ht_capa = |
1666 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 1679 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
1667 | 1680 | ||
1668 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], | 1681 | if (parse_station_flags(info, ¶ms)) |
1669 | ¶ms.station_flags)) | ||
1670 | return -EINVAL; | 1682 | return -EINVAL; |
1671 | 1683 | ||
1672 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | 1684 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) |
@@ -1735,8 +1747,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1735 | params.ht_capa = | 1747 | params.ht_capa = |
1736 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 1748 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
1737 | 1749 | ||
1738 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], | 1750 | if (parse_station_flags(info, ¶ms)) |
1739 | ¶ms.station_flags)) | ||
1740 | return -EINVAL; | 1751 | return -EINVAL; |
1741 | 1752 | ||
1742 | rtnl_lock(); | 1753 | rtnl_lock(); |
@@ -1745,6 +1756,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1745 | if (err) | 1756 | if (err) |
1746 | goto out_rtnl; | 1757 | goto out_rtnl; |
1747 | 1758 | ||
1759 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | ||
1760 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | ||
1761 | err = -EINVAL; | ||
1762 | goto out; | ||
1763 | } | ||
1764 | |||
1748 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | 1765 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
1749 | if (err) | 1766 | if (err) |
1750 | goto out; | 1767 | goto out; |
@@ -1788,6 +1805,12 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
1788 | if (err) | 1805 | if (err) |
1789 | goto out_rtnl; | 1806 | goto out_rtnl; |
1790 | 1807 | ||
1808 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | ||
1809 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | ||
1810 | err = -EINVAL; | ||
1811 | goto out; | ||
1812 | } | ||
1813 | |||
1791 | if (!drv->ops->del_station) { | 1814 | if (!drv->ops->del_station) { |
1792 | err = -EOPNOTSUPP; | 1815 | err = -EOPNOTSUPP; |
1793 | goto out; | 1816 | goto out; |
@@ -3012,6 +3035,19 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3012 | req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3035 | req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3013 | } | 3036 | } |
3014 | 3037 | ||
3038 | if (info->attrs[NL80211_ATTR_USE_MFP]) { | ||
3039 | enum nl80211_mfp use_mfp = | ||
3040 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); | ||
3041 | if (use_mfp == NL80211_MFP_REQUIRED) | ||
3042 | req.use_mfp = true; | ||
3043 | else if (use_mfp != NL80211_MFP_NO) { | ||
3044 | err = -EINVAL; | ||
3045 | goto out; | ||
3046 | } | ||
3047 | } | ||
3048 | |||
3049 | req.control_port = info->attrs[NL80211_ATTR_CONTROL_PORT]; | ||
3050 | |||
3015 | err = drv->ops->assoc(&drv->wiphy, dev, &req); | 3051 | err = drv->ops->assoc(&drv->wiphy, dev, &req); |
3016 | 3052 | ||
3017 | out: | 3053 | out: |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 5f7e997195c7..beb226e78cd7 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -138,3 +138,48 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy) | |||
138 | if (wiphy->bands[band]) | 138 | if (wiphy->bands[band]) |
139 | set_mandatory_flags_band(wiphy->bands[band], band); | 139 | set_mandatory_flags_band(wiphy->bands[band], band); |
140 | } | 140 | } |
141 | |||
142 | int cfg80211_validate_key_settings(struct key_params *params, int key_idx, | ||
143 | const u8 *mac_addr) | ||
144 | { | ||
145 | if (key_idx > 5) | ||
146 | return -EINVAL; | ||
147 | |||
148 | /* | ||
149 | * Disallow pairwise keys with non-zero index unless it's WEP | ||
150 | * (because current deployments use pairwise WEP keys with | ||
151 | * non-zero indizes but 802.11i clearly specifies to use zero) | ||
152 | */ | ||
153 | if (mac_addr && key_idx && | ||
154 | params->cipher != WLAN_CIPHER_SUITE_WEP40 && | ||
155 | params->cipher != WLAN_CIPHER_SUITE_WEP104) | ||
156 | return -EINVAL; | ||
157 | |||
158 | /* TODO: add definitions for the lengths to linux/ieee80211.h */ | ||
159 | switch (params->cipher) { | ||
160 | case WLAN_CIPHER_SUITE_WEP40: | ||
161 | if (params->key_len != 5) | ||
162 | return -EINVAL; | ||
163 | break; | ||
164 | case WLAN_CIPHER_SUITE_TKIP: | ||
165 | if (params->key_len != 32) | ||
166 | return -EINVAL; | ||
167 | break; | ||
168 | case WLAN_CIPHER_SUITE_CCMP: | ||
169 | if (params->key_len != 16) | ||
170 | return -EINVAL; | ||
171 | break; | ||
172 | case WLAN_CIPHER_SUITE_WEP104: | ||
173 | if (params->key_len != 13) | ||
174 | return -EINVAL; | ||
175 | break; | ||
176 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
177 | if (params->key_len != 16) | ||
178 | return -EINVAL; | ||
179 | break; | ||
180 | default: | ||
181 | return -EINVAL; | ||
182 | } | ||
183 | |||
184 | return 0; | ||
185 | } | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 5ef82f2ca88f..f98090b90fbf 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -5,12 +5,13 @@ | |||
5 | * into cfg80211, when that happens all the exports here go away and | 5 | * into cfg80211, when that happens all the exports here go away and |
6 | * we directly assign the wireless handlers of wireless interfaces. | 6 | * we directly assign the wireless handlers of wireless interfaces. |
7 | * | 7 | * |
8 | * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> | 8 | * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/wireless.h> | 11 | #include <linux/wireless.h> |
12 | #include <linux/nl80211.h> | 12 | #include <linux/nl80211.h> |
13 | #include <linux/if_arp.h> | 13 | #include <linux/if_arp.h> |
14 | #include <linux/etherdevice.h> | ||
14 | #include <net/iw_handler.h> | 15 | #include <net/iw_handler.h> |
15 | #include <net/cfg80211.h> | 16 | #include <net/cfg80211.h> |
16 | #include "core.h" | 17 | #include "core.h" |
@@ -296,22 +297,34 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); | |||
296 | struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, | 297 | struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, |
297 | struct iw_freq *freq) | 298 | struct iw_freq *freq) |
298 | { | 299 | { |
300 | struct ieee80211_channel *chan; | ||
301 | int f; | ||
302 | |||
303 | /* | ||
304 | * Parse frequency - return NULL for auto and | ||
305 | * -EINVAL for impossible things. | ||
306 | */ | ||
299 | if (freq->e == 0) { | 307 | if (freq->e == 0) { |
300 | if (freq->m < 0) | 308 | if (freq->m < 0) |
301 | return NULL; | 309 | return NULL; |
302 | else | 310 | f = ieee80211_channel_to_frequency(freq->m); |
303 | return ieee80211_get_channel(wiphy, | ||
304 | ieee80211_channel_to_frequency(freq->m)); | ||
305 | } else { | 311 | } else { |
306 | int i, div = 1000000; | 312 | int i, div = 1000000; |
307 | for (i = 0; i < freq->e; i++) | 313 | for (i = 0; i < freq->e; i++) |
308 | div /= 10; | 314 | div /= 10; |
309 | if (div > 0) | 315 | if (div <= 0) |
310 | return ieee80211_get_channel(wiphy, freq->m / div); | ||
311 | else | ||
312 | return ERR_PTR(-EINVAL); | 316 | return ERR_PTR(-EINVAL); |
317 | f = freq->m / div; | ||
313 | } | 318 | } |
314 | 319 | ||
320 | /* | ||
321 | * Look up channel struct and return -EINVAL when | ||
322 | * it cannot be found. | ||
323 | */ | ||
324 | chan = ieee80211_get_channel(wiphy, f); | ||
325 | if (!chan) | ||
326 | return ERR_PTR(-EINVAL); | ||
327 | return chan; | ||
315 | } | 328 | } |
316 | EXPORT_SYMBOL_GPL(cfg80211_wext_freq); | 329 | EXPORT_SYMBOL_GPL(cfg80211_wext_freq); |
317 | 330 | ||
@@ -465,3 +478,262 @@ int cfg80211_wext_giwretry(struct net_device *dev, | |||
465 | return 0; | 478 | return 0; |
466 | } | 479 | } |
467 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); | 480 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); |
481 | |||
482 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | ||
483 | struct net_device *dev, const u8 *addr, | ||
484 | bool remove, bool tx_key, int idx, | ||
485 | struct key_params *params) | ||
486 | { | ||
487 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
488 | int err; | ||
489 | |||
490 | if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { | ||
491 | if (!rdev->ops->set_default_mgmt_key) | ||
492 | return -EOPNOTSUPP; | ||
493 | |||
494 | if (idx < 4 || idx > 5) | ||
495 | return -EINVAL; | ||
496 | } else if (idx < 0 || idx > 3) | ||
497 | return -EINVAL; | ||
498 | |||
499 | if (remove) { | ||
500 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); | ||
501 | if (!err) { | ||
502 | if (idx == wdev->wext.default_key) | ||
503 | wdev->wext.default_key = -1; | ||
504 | else if (idx == wdev->wext.default_mgmt_key) | ||
505 | wdev->wext.default_mgmt_key = -1; | ||
506 | } | ||
507 | return err; | ||
508 | } else { | ||
509 | if (addr) | ||
510 | tx_key = false; | ||
511 | |||
512 | if (cfg80211_validate_key_settings(params, idx, addr)) | ||
513 | return -EINVAL; | ||
514 | |||
515 | err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); | ||
516 | if (err) | ||
517 | return err; | ||
518 | |||
519 | if (tx_key || (!addr && wdev->wext.default_key == -1)) { | ||
520 | err = rdev->ops->set_default_key(&rdev->wiphy, | ||
521 | dev, idx); | ||
522 | if (!err) | ||
523 | wdev->wext.default_key = idx; | ||
524 | return err; | ||
525 | } | ||
526 | |||
527 | if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC && | ||
528 | (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) { | ||
529 | err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, | ||
530 | dev, idx); | ||
531 | if (!err) | ||
532 | wdev->wext.default_mgmt_key = idx; | ||
533 | return err; | ||
534 | } | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | int cfg80211_wext_siwencode(struct net_device *dev, | ||
541 | struct iw_request_info *info, | ||
542 | struct iw_point *erq, char *keybuf) | ||
543 | { | ||
544 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
545 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
546 | int idx, err; | ||
547 | bool remove = false; | ||
548 | struct key_params params; | ||
549 | |||
550 | /* no use -- only MFP (set_default_mgmt_key) is optional */ | ||
551 | if (!rdev->ops->del_key || | ||
552 | !rdev->ops->add_key || | ||
553 | !rdev->ops->set_default_key) | ||
554 | return -EOPNOTSUPP; | ||
555 | |||
556 | idx = erq->flags & IW_ENCODE_INDEX; | ||
557 | if (idx == 0) { | ||
558 | idx = wdev->wext.default_key; | ||
559 | if (idx < 0) | ||
560 | idx = 0; | ||
561 | } else if (idx < 1 || idx > 4) | ||
562 | return -EINVAL; | ||
563 | else | ||
564 | idx--; | ||
565 | |||
566 | if (erq->flags & IW_ENCODE_DISABLED) | ||
567 | remove = true; | ||
568 | else if (erq->length == 0) { | ||
569 | /* No key data - just set the default TX key index */ | ||
570 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx); | ||
571 | if (!err) | ||
572 | wdev->wext.default_key = idx; | ||
573 | return err; | ||
574 | } | ||
575 | |||
576 | memset(¶ms, 0, sizeof(params)); | ||
577 | params.key = keybuf; | ||
578 | params.key_len = erq->length; | ||
579 | if (erq->length == 5) | ||
580 | params.cipher = WLAN_CIPHER_SUITE_WEP40; | ||
581 | else if (erq->length == 13) | ||
582 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | ||
583 | else if (!remove) | ||
584 | return -EINVAL; | ||
585 | |||
586 | return cfg80211_set_encryption(rdev, dev, NULL, remove, | ||
587 | wdev->wext.default_key == -1, | ||
588 | idx, ¶ms); | ||
589 | } | ||
590 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode); | ||
591 | |||
592 | int cfg80211_wext_siwencodeext(struct net_device *dev, | ||
593 | struct iw_request_info *info, | ||
594 | struct iw_point *erq, char *extra) | ||
595 | { | ||
596 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
597 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
598 | struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; | ||
599 | const u8 *addr; | ||
600 | int idx; | ||
601 | bool remove = false; | ||
602 | struct key_params params; | ||
603 | u32 cipher; | ||
604 | |||
605 | /* no use -- only MFP (set_default_mgmt_key) is optional */ | ||
606 | if (!rdev->ops->del_key || | ||
607 | !rdev->ops->add_key || | ||
608 | !rdev->ops->set_default_key) | ||
609 | return -EOPNOTSUPP; | ||
610 | |||
611 | switch (ext->alg) { | ||
612 | case IW_ENCODE_ALG_NONE: | ||
613 | remove = true; | ||
614 | cipher = 0; | ||
615 | break; | ||
616 | case IW_ENCODE_ALG_WEP: | ||
617 | if (ext->key_len == 5) | ||
618 | cipher = WLAN_CIPHER_SUITE_WEP40; | ||
619 | else if (ext->key_len == 13) | ||
620 | cipher = WLAN_CIPHER_SUITE_WEP104; | ||
621 | else | ||
622 | return -EINVAL; | ||
623 | break; | ||
624 | case IW_ENCODE_ALG_TKIP: | ||
625 | cipher = WLAN_CIPHER_SUITE_TKIP; | ||
626 | break; | ||
627 | case IW_ENCODE_ALG_CCMP: | ||
628 | cipher = WLAN_CIPHER_SUITE_CCMP; | ||
629 | break; | ||
630 | case IW_ENCODE_ALG_AES_CMAC: | ||
631 | cipher = WLAN_CIPHER_SUITE_AES_CMAC; | ||
632 | break; | ||
633 | default: | ||
634 | return -EOPNOTSUPP; | ||
635 | } | ||
636 | |||
637 | if (erq->flags & IW_ENCODE_DISABLED) | ||
638 | remove = true; | ||
639 | |||
640 | idx = erq->flags & IW_ENCODE_INDEX; | ||
641 | if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) { | ||
642 | if (idx < 4 || idx > 5) { | ||
643 | idx = wdev->wext.default_mgmt_key; | ||
644 | if (idx < 0) | ||
645 | return -EINVAL; | ||
646 | } else | ||
647 | idx--; | ||
648 | } else { | ||
649 | if (idx < 1 || idx > 4) { | ||
650 | idx = wdev->wext.default_key; | ||
651 | if (idx < 0) | ||
652 | return -EINVAL; | ||
653 | } else | ||
654 | idx--; | ||
655 | } | ||
656 | |||
657 | addr = ext->addr.sa_data; | ||
658 | if (is_broadcast_ether_addr(addr)) | ||
659 | addr = NULL; | ||
660 | |||
661 | memset(¶ms, 0, sizeof(params)); | ||
662 | params.key = ext->key; | ||
663 | params.key_len = ext->key_len; | ||
664 | params.cipher = cipher; | ||
665 | |||
666 | if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { | ||
667 | params.seq = ext->rx_seq; | ||
668 | params.seq_len = 6; | ||
669 | } | ||
670 | |||
671 | return cfg80211_set_encryption( | ||
672 | rdev, dev, addr, remove, | ||
673 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, | ||
674 | idx, ¶ms); | ||
675 | } | ||
676 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); | ||
677 | |||
678 | struct giwencode_cookie { | ||
679 | size_t buflen; | ||
680 | char *keybuf; | ||
681 | }; | ||
682 | |||
683 | static void giwencode_get_key_cb(void *cookie, struct key_params *params) | ||
684 | { | ||
685 | struct giwencode_cookie *data = cookie; | ||
686 | |||
687 | if (!params->key) { | ||
688 | data->buflen = 0; | ||
689 | return; | ||
690 | } | ||
691 | |||
692 | data->buflen = min_t(size_t, data->buflen, params->key_len); | ||
693 | memcpy(data->keybuf, params->key, data->buflen); | ||
694 | } | ||
695 | |||
696 | int cfg80211_wext_giwencode(struct net_device *dev, | ||
697 | struct iw_request_info *info, | ||
698 | struct iw_point *erq, char *keybuf) | ||
699 | { | ||
700 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
701 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
702 | int idx, err; | ||
703 | struct giwencode_cookie data = { | ||
704 | .keybuf = keybuf, | ||
705 | .buflen = erq->length, | ||
706 | }; | ||
707 | |||
708 | if (!rdev->ops->get_key) | ||
709 | return -EOPNOTSUPP; | ||
710 | |||
711 | idx = erq->flags & IW_ENCODE_INDEX; | ||
712 | if (idx == 0) { | ||
713 | idx = wdev->wext.default_key; | ||
714 | if (idx < 0) | ||
715 | idx = 0; | ||
716 | } else if (idx < 1 || idx > 4) | ||
717 | return -EINVAL; | ||
718 | else | ||
719 | idx--; | ||
720 | |||
721 | erq->flags = idx + 1; | ||
722 | |||
723 | err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data, | ||
724 | giwencode_get_key_cb); | ||
725 | if (!err) { | ||
726 | erq->length = data.buflen; | ||
727 | erq->flags |= IW_ENCODE_ENABLED; | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | if (err == -ENOENT) { | ||
732 | erq->flags |= IW_ENCODE_DISABLED; | ||
733 | erq->length = 0; | ||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | return err; | ||
738 | } | ||
739 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); | ||
diff --git a/net/wireless/wext.c b/net/wireless/wext.c index cb6a5bb85d80..d3bbef70cc7c 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c | |||
@@ -649,14 +649,26 @@ static int wireless_seq_show(struct seq_file *seq, void *v) | |||
649 | return 0; | 649 | return 0; |
650 | } | 650 | } |
651 | 651 | ||
652 | static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) | ||
653 | { | ||
654 | rtnl_lock(); | ||
655 | return dev_seq_start(seq, pos); | ||
656 | } | ||
657 | |||
658 | static void wireless_dev_seq_stop(struct seq_file *seq, void *v) | ||
659 | { | ||
660 | dev_seq_stop(seq, v); | ||
661 | rtnl_unlock(); | ||
662 | } | ||
663 | |||
652 | static const struct seq_operations wireless_seq_ops = { | 664 | static const struct seq_operations wireless_seq_ops = { |
653 | .start = dev_seq_start, | 665 | .start = wireless_dev_seq_start, |
654 | .next = dev_seq_next, | 666 | .next = dev_seq_next, |
655 | .stop = dev_seq_stop, | 667 | .stop = wireless_dev_seq_stop, |
656 | .show = wireless_seq_show, | 668 | .show = wireless_seq_show, |
657 | }; | 669 | }; |
658 | 670 | ||
659 | static int wireless_seq_open(struct inode *inode, struct file *file) | 671 | static int seq_open_wireless(struct inode *inode, struct file *file) |
660 | { | 672 | { |
661 | return seq_open_net(inode, file, &wireless_seq_ops, | 673 | return seq_open_net(inode, file, &wireless_seq_ops, |
662 | sizeof(struct seq_net_private)); | 674 | sizeof(struct seq_net_private)); |
@@ -664,7 +676,7 @@ static int wireless_seq_open(struct inode *inode, struct file *file) | |||
664 | 676 | ||
665 | static const struct file_operations wireless_seq_fops = { | 677 | static const struct file_operations wireless_seq_fops = { |
666 | .owner = THIS_MODULE, | 678 | .owner = THIS_MODULE, |
667 | .open = wireless_seq_open, | 679 | .open = seq_open_wireless, |
668 | .read = seq_read, | 680 | .read = seq_read, |
669 | .llseek = seq_lseek, | 681 | .llseek = seq_lseek, |
670 | .release = seq_release_net, | 682 | .release = seq_release_net, |