diff options
author | Nick Kossifidis <mick@madwifi.org> | 2008-10-28 22:28:28 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-10 15:11:57 -0500 |
commit | f07a6c495e88ae0143e3c20b1ed666314197277f (patch) | |
tree | 995d21adcd0a029b44b3c1d5e89dfcbf357fbec0 /drivers/net/wireless | |
parent | 2c706002fc147decdba2658ea48e4436faca3af2 (diff) |
ath5k: Update PCU code
* In set_opmode don't handle antenna settings and preserve other STA_ID1 settings
(shouldn't matter because we call it during reset but it makes things cleaner)
Also set properly AP/ADHOC indicator flag on CFG while setting AP/ADHOC modes
and always enable key search mode.
* Properly set BSSID Mask during reset (cache it and reuse it durring set_associd)
* Update beacon_init to flush pending BMISS interrupts and handle setting of adhoc
beacon ATIM policy flag for ad-hoc mode. Also set TSF to 0 to start TSF increment
on AP mode. We need to handle sleep timers for AR5212 there + add support for PCF.
* Properly clean MIC key from keytable when TKIP is used (Bob is working on set_key
function etc so i leave it for now).
Tested on AR5212 (Hainan) and AR5413 and works fine
v2 Set PISR on AR5211+ and ISR on AR5210, got to sleep more ;-)
Changes-Licensed-under: ISC
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath5k/ath5k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/pcu.c | 111 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/reg.h | 12 |
3 files changed, 102 insertions, 24 deletions
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index b11792039911..a725bb94a52d 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -1093,10 +1093,11 @@ struct ath5k_hw { | |||
1093 | 1093 | ||
1094 | u8 ah_sta_id[ETH_ALEN]; | 1094 | u8 ah_sta_id[ETH_ALEN]; |
1095 | 1095 | ||
1096 | /* Current BSSID we are trying to assoc to / creating. | 1096 | /* Current BSSID we are trying to assoc to / create. |
1097 | * This is passed by mac80211 on config_interface() and cached here for | 1097 | * This is passed by mac80211 on config_interface() and cached here for |
1098 | * use in resets */ | 1098 | * use in resets */ |
1099 | u8 ah_bssid[ETH_ALEN]; | 1099 | u8 ah_bssid[ETH_ALEN]; |
1100 | u8 ah_bssid_mask[ETH_ALEN]; | ||
1100 | 1101 | ||
1101 | u32 ah_gpio[AR5K_MAX_GPIO]; | 1102 | u32 ah_gpio[AR5K_MAX_GPIO]; |
1102 | int ah_gpio_npins; | 1103 | int ah_gpio_npins; |
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index a47df9a24aa1..5674639f7bf8 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c | |||
@@ -46,34 +46,45 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
46 | { | 46 | { |
47 | u32 pcu_reg, beacon_reg, low_id, high_id; | 47 | u32 pcu_reg, beacon_reg, low_id, high_id; |
48 | 48 | ||
49 | pcu_reg = 0; | 49 | |
50 | /* Preserve rest settings */ | ||
51 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | ||
52 | pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP | ||
53 | | AR5K_STA_ID1_KEYSRCH_MODE | ||
54 | | (ah->ah_version == AR5K_AR5210 ? | ||
55 | (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); | ||
56 | |||
50 | beacon_reg = 0; | 57 | beacon_reg = 0; |
51 | 58 | ||
52 | ATH5K_TRACE(ah->ah_sc); | 59 | ATH5K_TRACE(ah->ah_sc); |
53 | 60 | ||
54 | switch (ah->ah_op_mode) { | 61 | switch (ah->ah_op_mode) { |
55 | case NL80211_IFTYPE_ADHOC: | 62 | case NL80211_IFTYPE_ADHOC: |
56 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA | | 63 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; |
57 | (ah->ah_version == AR5K_AR5210 ? | ||
58 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
59 | beacon_reg |= AR5K_BCR_ADHOC; | 64 | beacon_reg |= AR5K_BCR_ADHOC; |
65 | if (ah->ah_version == AR5K_AR5210) | ||
66 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
67 | else | ||
68 | AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC); | ||
60 | break; | 69 | break; |
61 | 70 | ||
62 | case NL80211_IFTYPE_AP: | 71 | case NL80211_IFTYPE_AP: |
63 | case NL80211_IFTYPE_MESH_POINT: | 72 | case NL80211_IFTYPE_MESH_POINT: |
64 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA | | 73 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; |
65 | (ah->ah_version == AR5K_AR5210 ? | ||
66 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
67 | beacon_reg |= AR5K_BCR_AP; | 74 | beacon_reg |= AR5K_BCR_AP; |
75 | if (ah->ah_version == AR5K_AR5210) | ||
76 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
77 | else | ||
78 | AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC); | ||
68 | break; | 79 | break; |
69 | 80 | ||
70 | case NL80211_IFTYPE_STATION: | 81 | case NL80211_IFTYPE_STATION: |
71 | pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | | 82 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE |
72 | (ah->ah_version == AR5K_AR5210 ? | 83 | | (ah->ah_version == AR5K_AR5210 ? |
73 | AR5K_STA_ID1_PWR_SV : 0); | 84 | AR5K_STA_ID1_PWR_SV : 0); |
74 | case NL80211_IFTYPE_MONITOR: | 85 | case NL80211_IFTYPE_MONITOR: |
75 | pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | | 86 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE |
76 | (ah->ah_version == AR5K_AR5210 ? | 87 | | (ah->ah_version == AR5K_AR5210 ? |
77 | AR5K_STA_ID1_NO_PSPOLL : 0); | 88 | AR5K_STA_ID1_NO_PSPOLL : 0); |
78 | break; | 89 | break; |
79 | 90 | ||
@@ -130,6 +141,8 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | |||
130 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | 141 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); |
131 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | 142 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); |
132 | } | 143 | } |
144 | |||
145 | /* TODO: Handle ANI stats */ | ||
133 | } | 146 | } |
134 | 147 | ||
135 | /** | 148 | /** |
@@ -254,6 +267,10 @@ void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | |||
254 | * @mac: The card's mac address | 267 | * @mac: The card's mac address |
255 | * | 268 | * |
256 | * Set station id on hw using the provided mac address | 269 | * Set station id on hw using the provided mac address |
270 | * | ||
271 | * NOTE: This is only called during attach, don't call it | ||
272 | * on reset because it overwrites all AR5K_STA_ID1 settings. | ||
273 | * We have set_opmode (above) for reset. | ||
257 | */ | 274 | */ |
258 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | 275 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) |
259 | { | 276 | { |
@@ -290,8 +307,10 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | |||
290 | * Set simple BSSID mask on 5212 | 307 | * Set simple BSSID mask on 5212 |
291 | */ | 308 | */ |
292 | if (ah->ah_version == AR5K_AR5212) { | 309 | if (ah->ah_version == AR5K_AR5212) { |
293 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0); | 310 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), |
294 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1); | 311 | AR5K_BSS_IDM0); |
312 | ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask), | ||
313 | AR5K_BSS_IDM1); | ||
295 | } | 314 | } |
296 | 315 | ||
297 | /* | 316 | /* |
@@ -415,6 +434,9 @@ int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
415 | u32 low_id, high_id; | 434 | u32 low_id, high_id; |
416 | ATH5K_TRACE(ah->ah_sc); | 435 | ATH5K_TRACE(ah->ah_sc); |
417 | 436 | ||
437 | /* Cache bssid mask so that we can restore it | ||
438 | * on reset */ | ||
439 | memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); | ||
418 | if (ah->ah_version == AR5K_AR5212) { | 440 | if (ah->ah_version == AR5K_AR5212) { |
419 | low_id = AR5K_LOW_ID(mask); | 441 | low_id = AR5K_LOW_ID(mask); |
420 | high_id = AR5K_HIGH_ID(mask); | 442 | high_id = AR5K_HIGH_ID(mask); |
@@ -576,7 +598,7 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
576 | filter |= AR5K_RX_FILTER_PROM; | 598 | filter |= AR5K_RX_FILTER_PROM; |
577 | } | 599 | } |
578 | 600 | ||
579 | /*Zero length DMA*/ | 601 | /*Zero length DMA (phy error reporting) */ |
580 | if (data) | 602 | if (data) |
581 | AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | 603 | AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); |
582 | else | 604 | else |
@@ -661,7 +683,12 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
661 | * Set the additional timers by mode | 683 | * Set the additional timers by mode |
662 | */ | 684 | */ |
663 | switch (ah->ah_op_mode) { | 685 | switch (ah->ah_op_mode) { |
686 | case NL80211_IFTYPE_MONITOR: | ||
664 | case NL80211_IFTYPE_STATION: | 687 | case NL80211_IFTYPE_STATION: |
688 | /* In STA mode timer1 is used as next wakeup | ||
689 | * timer and timer2 as next CFP duration start | ||
690 | * timer. Both in 1/8TUs. */ | ||
691 | /* TODO: PCF handling */ | ||
665 | if (ah->ah_version == AR5K_AR5210) { | 692 | if (ah->ah_version == AR5K_AR5210) { |
666 | timer1 = 0xffffffff; | 693 | timer1 = 0xffffffff; |
667 | timer2 = 0xffffffff; | 694 | timer2 = 0xffffffff; |
@@ -669,27 +696,60 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
669 | timer1 = 0x0000ffff; | 696 | timer1 = 0x0000ffff; |
670 | timer2 = 0x0007ffff; | 697 | timer2 = 0x0007ffff; |
671 | } | 698 | } |
699 | /* Mark associated AP as PCF incapable for now */ | ||
700 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF); | ||
672 | break; | 701 | break; |
673 | 702 | case NL80211_IFTYPE_ADHOC: | |
703 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); | ||
674 | default: | 704 | default: |
705 | /* On non-STA modes timer1 is used as next DMA | ||
706 | * beacon alert (DBA) timer and timer2 as next | ||
707 | * software beacon alert. Both in 1/8TUs. */ | ||
675 | timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; | 708 | timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; |
676 | timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; | 709 | timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; |
710 | break; | ||
677 | } | 711 | } |
678 | 712 | ||
713 | /* Timer3 marks the end of our ATIM window | ||
714 | * a zero length window is not allowed because | ||
715 | * we 'll get no beacons */ | ||
679 | timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); | 716 | timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); |
680 | 717 | ||
681 | /* | 718 | /* |
682 | * Set the beacon register and enable all timers. | 719 | * Set the beacon register and enable all timers. |
683 | * (next beacon, DMA beacon, software beacon, ATIM window time) | ||
684 | */ | 720 | */ |
685 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | 721 | /* When in AP mode zero timer0 to start TSF */ |
722 | if (ah->ah_op_mode == NL80211_IFTYPE_AP) | ||
723 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | ||
724 | else | ||
725 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | ||
686 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); | 726 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); |
687 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); | 727 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); |
688 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); | 728 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); |
689 | 729 | ||
730 | /* Force a TSF reset if requested and enable beacons */ | ||
731 | if (interval & AR5K_BEACON_RESET_TSF) | ||
732 | ath5k_hw_reset_tsf(ah); | ||
733 | |||
690 | ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | | 734 | ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | |
691 | AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE), | 735 | AR5K_BEACON_ENABLE), |
692 | AR5K_BEACON); | 736 | AR5K_BEACON); |
737 | |||
738 | /* Flush any pending BMISS interrupts on ISR by | ||
739 | * performing a clear-on-write operation on PISR | ||
740 | * register for the BMISS bit (writing a bit on | ||
741 | * ISR togles a reset for that bit and leaves | ||
742 | * the rest bits intact) */ | ||
743 | if (ah->ah_version == AR5K_AR5210) | ||
744 | ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR); | ||
745 | else | ||
746 | ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR); | ||
747 | |||
748 | /* TODO: Set enchanced sleep registers on AR5212 | ||
749 | * based on vif->bss_conf params, until then | ||
750 | * disable power save reporting.*/ | ||
751 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV); | ||
752 | |||
693 | } | 753 | } |
694 | 754 | ||
695 | #if 0 | 755 | #if 0 |
@@ -899,14 +959,25 @@ int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | |||
899 | */ | 959 | */ |
900 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | 960 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) |
901 | { | 961 | { |
902 | unsigned int i; | 962 | unsigned int i, type; |
903 | 963 | ||
904 | ATH5K_TRACE(ah->ah_sc); | 964 | ATH5K_TRACE(ah->ah_sc); |
905 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 965 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
906 | 966 | ||
967 | type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); | ||
968 | |||
907 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | 969 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) |
908 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | 970 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); |
909 | 971 | ||
972 | /* Reset associated MIC entry if TKIP | ||
973 | * is enabled located at offset (entry + 64) */ | ||
974 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { | ||
975 | entry = entry + AR5K_KEYTABLE_MIC_OFFSET; | ||
976 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
977 | for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) | ||
978 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | ||
979 | } | ||
980 | |||
910 | /* | 981 | /* |
911 | * Set NULL encryption on AR5212+ | 982 | * Set NULL encryption on AR5212+ |
912 | * | 983 | * |
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 0dae54d00f03..69755fc2f9be 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h | |||
@@ -1114,14 +1114,16 @@ | |||
1114 | #define AR5K_PCU_MAX 0x8fff | 1114 | #define AR5K_PCU_MAX 0x8fff |
1115 | 1115 | ||
1116 | /* | 1116 | /* |
1117 | * First station id register (MAC address in lower 32 bits) | 1117 | * First station id register (Lower 32 bits of MAC address) |
1118 | */ | 1118 | */ |
1119 | #define AR5K_STA_ID0 0x8000 | 1119 | #define AR5K_STA_ID0 0x8000 |
1120 | #define AR5K_STA_ID0_ARRD_L32 0xffffffff | ||
1120 | 1121 | ||
1121 | /* | 1122 | /* |
1122 | * Second station id register (MAC address in upper 16 bits) | 1123 | * Second station id register (Upper 16 bits of MAC address + PCU settings) |
1123 | */ | 1124 | */ |
1124 | #define AR5K_STA_ID1 0x8004 /* Register Address */ | 1125 | #define AR5K_STA_ID1 0x8004 /* Register Address */ |
1126 | #define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */ | ||
1125 | #define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ | 1127 | #define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ |
1126 | #define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ | 1128 | #define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ |
1127 | #define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ | 1129 | #define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ |
@@ -1811,6 +1813,10 @@ | |||
1811 | #define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7) | 1813 | #define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7) |
1812 | #define AR5K_KEYTABLE_VALID 0x00008000 | 1814 | #define AR5K_KEYTABLE_VALID 0x00008000 |
1813 | 1815 | ||
1816 | /* If key type is TKIP and MIC is enabled | ||
1817 | * MIC key goes in offset entry + 64 */ | ||
1818 | #define AR5K_KEYTABLE_MIC_OFFSET 64 | ||
1819 | |||
1814 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit | 1820 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit |
1815 | * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit | 1821 | * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit |
1816 | * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit | 1822 | * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit |