aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi.org>2008-10-28 22:28:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-11-10 15:11:57 -0500
commitf07a6c495e88ae0143e3c20b1ed666314197277f (patch)
tree995d21adcd0a029b44b3c1d5e89dfcbf357fbec0 /drivers/net/wireless
parent2c706002fc147decdba2658ea48e4436faca3af2 (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.h3
-rw-r--r--drivers/net/wireless/ath5k/pcu.c111
-rw-r--r--drivers/net/wireless/ath5k/reg.h12
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 */
258int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) 275int 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 */
900int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) 960int 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