diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-05-11 11:23:03 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-05-12 16:39:07 -0400 |
commit | ffdc4cbe5b17c83af779f45de8536c6ece297e42 (patch) | |
tree | 07de5a7693a1b76fbd1f213e2a472ac346b82182 /drivers | |
parent | 9bff0bc4012c7f079b297eb45b47780e3713f367 (diff) |
ath9k_hw: clean up EEPROM endian handling on AR9003
Remove the double swapping of the descriptor data structure, instead
keep it little-endian (native format of the eeprom data), and byteswap
on access.
This allows sparse to verify endian access to the eeprom struct.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 174 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 10 |
2 files changed, 81 insertions, 103 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 8a79550dff71..23eb60ea5455 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -38,6 +38,9 @@ | |||
38 | #define AR_SWITCH_TABLE_ALL (0xfff) | 38 | #define AR_SWITCH_TABLE_ALL (0xfff) |
39 | #define AR_SWITCH_TABLE_ALL_S (0) | 39 | #define AR_SWITCH_TABLE_ALL_S (0) |
40 | 40 | ||
41 | #define LE16(x) __constant_cpu_to_le16(x) | ||
42 | #define LE32(x) __constant_cpu_to_le32(x) | ||
43 | |||
41 | static const struct ar9300_eeprom ar9300_default = { | 44 | static const struct ar9300_eeprom ar9300_default = { |
42 | .eepromVersion = 2, | 45 | .eepromVersion = 2, |
43 | .templateVersion = 2, | 46 | .templateVersion = 2, |
@@ -45,7 +48,7 @@ static const struct ar9300_eeprom ar9300_default = { | |||
45 | .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 48 | .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
46 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 49 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
47 | .baseEepHeader = { | 50 | .baseEepHeader = { |
48 | .regDmn = {0, 0x1f}, | 51 | .regDmn = { LE16(0), LE16(0x1f) }, |
49 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ | 52 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ |
50 | .opCapFlags = { | 53 | .opCapFlags = { |
51 | .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, | 54 | .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, |
@@ -76,15 +79,15 @@ static const struct ar9300_eeprom ar9300_default = { | |||
76 | .modalHeader2G = { | 79 | .modalHeader2G = { |
77 | /* ar9300_modal_eep_header 2g */ | 80 | /* ar9300_modal_eep_header 2g */ |
78 | /* 4 idle,t1,t2,b(4 bits per setting) */ | 81 | /* 4 idle,t1,t2,b(4 bits per setting) */ |
79 | .antCtrlCommon = 0x110, | 82 | .antCtrlCommon = LE32(0x110), |
80 | /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ | 83 | /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ |
81 | .antCtrlCommon2 = 0x22222, | 84 | .antCtrlCommon2 = LE32(0x22222), |
82 | 85 | ||
83 | /* | 86 | /* |
84 | * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, | 87 | * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, |
85 | * rx1, rx12, b (2 bits each) | 88 | * rx1, rx12, b (2 bits each) |
86 | */ | 89 | */ |
87 | .antCtrlChain = {0x150, 0x150, 0x150}, | 90 | .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) }, |
88 | 91 | ||
89 | /* | 92 | /* |
90 | * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db | 93 | * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db |
@@ -287,12 +290,12 @@ static const struct ar9300_eeprom ar9300_default = { | |||
287 | }, | 290 | }, |
288 | .modalHeader5G = { | 291 | .modalHeader5G = { |
289 | /* 4 idle,t1,t2,b (4 bits per setting) */ | 292 | /* 4 idle,t1,t2,b (4 bits per setting) */ |
290 | .antCtrlCommon = 0x110, | 293 | .antCtrlCommon = LE32(0x110), |
291 | /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ | 294 | /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ |
292 | .antCtrlCommon2 = 0x22222, | 295 | .antCtrlCommon2 = LE32(0x22222), |
293 | /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ | 296 | /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ |
294 | .antCtrlChain = { | 297 | .antCtrlChain = { |
295 | 0x000, 0x000, 0x000, | 298 | LE16(0x000), LE16(0x000), LE16(0x000), |
296 | }, | 299 | }, |
297 | /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ | 300 | /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ |
298 | .xatten1DB = {0, 0, 0}, | 301 | .xatten1DB = {0, 0, 0}, |
@@ -620,9 +623,9 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
620 | case EEP_MAC_MSW: | 623 | case EEP_MAC_MSW: |
621 | return eep->macAddr[4] << 8 | eep->macAddr[5]; | 624 | return eep->macAddr[4] << 8 | eep->macAddr[5]; |
622 | case EEP_REG_0: | 625 | case EEP_REG_0: |
623 | return pBase->regDmn[0]; | 626 | return le16_to_cpu(pBase->regDmn[0]); |
624 | case EEP_REG_1: | 627 | case EEP_REG_1: |
625 | return pBase->regDmn[1]; | 628 | return le16_to_cpu(pBase->regDmn[1]); |
626 | case EEP_OP_CAP: | 629 | case EEP_OP_CAP: |
627 | return pBase->deviceCap; | 630 | return pBase->deviceCap; |
628 | case EEP_OP_MODE: | 631 | case EEP_OP_MODE: |
@@ -640,93 +643,80 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
640 | /* Bit 4 is internal regulator flag */ | 643 | /* Bit 4 is internal regulator flag */ |
641 | return (pBase->featureEnable & 0x10) >> 4; | 644 | return (pBase->featureEnable & 0x10) >> 4; |
642 | case EEP_SWREG: | 645 | case EEP_SWREG: |
643 | return pBase->swreg; | 646 | return le32_to_cpu(pBase->swreg); |
644 | default: | 647 | default: |
645 | return 0; | 648 | return 0; |
646 | } | 649 | } |
647 | } | 650 | } |
648 | 651 | ||
649 | #ifdef __BIG_ENDIAN | 652 | static bool ar9300_eeprom_read_byte(struct ath_common *common, int address, |
650 | static void ar9300_swap_eeprom(struct ar9300_eeprom *eep) | 653 | u8 *buffer) |
651 | { | 654 | { |
652 | u32 dword; | 655 | u16 val; |
653 | u16 word; | ||
654 | int i; | ||
655 | |||
656 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
657 | eep->baseEepHeader.regDmn[0] = word; | ||
658 | |||
659 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
660 | eep->baseEepHeader.regDmn[1] = word; | ||
661 | |||
662 | dword = swab32(eep->baseEepHeader.swreg); | ||
663 | eep->baseEepHeader.swreg = dword; | ||
664 | 656 | ||
665 | dword = swab32(eep->modalHeader2G.antCtrlCommon); | 657 | if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val))) |
666 | eep->modalHeader2G.antCtrlCommon = dword; | 658 | return false; |
667 | 659 | ||
668 | dword = swab32(eep->modalHeader2G.antCtrlCommon2); | 660 | *buffer = (val >> (8 * (address % 2))) & 0xff; |
669 | eep->modalHeader2G.antCtrlCommon2 = dword; | 661 | return true; |
662 | } | ||
670 | 663 | ||
671 | dword = swab32(eep->modalHeader5G.antCtrlCommon); | 664 | static bool ar9300_eeprom_read_word(struct ath_common *common, int address, |
672 | eep->modalHeader5G.antCtrlCommon = dword; | 665 | u8 *buffer) |
666 | { | ||
667 | u16 val; | ||
673 | 668 | ||
674 | dword = swab32(eep->modalHeader5G.antCtrlCommon2); | 669 | if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val))) |
675 | eep->modalHeader5G.antCtrlCommon2 = dword; | 670 | return false; |
676 | 671 | ||
677 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 672 | buffer[0] = val >> 8; |
678 | word = swab16(eep->modalHeader2G.antCtrlChain[i]); | 673 | buffer[1] = val & 0xff; |
679 | eep->modalHeader2G.antCtrlChain[i] = word; | ||
680 | 674 | ||
681 | word = swab16(eep->modalHeader5G.antCtrlChain[i]); | 675 | return true; |
682 | eep->modalHeader5G.antCtrlChain[i] = word; | ||
683 | } | ||
684 | } | 676 | } |
685 | #endif | ||
686 | 677 | ||
687 | static bool ar9300_hw_read_eeprom(struct ath_hw *ah, | 678 | static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer, |
688 | long address, u8 *buffer, int many) | 679 | int count) |
689 | { | 680 | { |
690 | int i; | ||
691 | u8 value[2]; | ||
692 | unsigned long eepAddr; | ||
693 | unsigned long byteAddr; | ||
694 | u16 *svalue; | ||
695 | struct ath_common *common = ath9k_hw_common(ah); | 681 | struct ath_common *common = ath9k_hw_common(ah); |
682 | int i; | ||
696 | 683 | ||
697 | if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) { | 684 | if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) { |
698 | ath_print(common, ATH_DBG_EEPROM, | 685 | ath_print(common, ATH_DBG_EEPROM, |
699 | "eeprom address not in range\n"); | 686 | "eeprom address not in range\n"); |
700 | return false; | 687 | return false; |
701 | } | 688 | } |
702 | 689 | ||
703 | for (i = 0; i < many; i++) { | 690 | /* |
704 | eepAddr = (u16) (address + i) / 2; | 691 | * Since we're reading the bytes in reverse order from a little-endian |
705 | byteAddr = (u16) (address + i) % 2; | 692 | * word stream, an even address means we only use the lower half of |
706 | svalue = (u16 *) value; | 693 | * the 16-bit word at that address |
707 | if (!ath9k_hw_nvram_read(common, eepAddr, svalue)) { | 694 | */ |
708 | ath_print(common, ATH_DBG_EEPROM, | 695 | if (address % 2 == 0) { |
709 | "unable to read eeprom region\n"); | 696 | if (!ar9300_eeprom_read_byte(common, address--, buffer++)) |
710 | return false; | 697 | goto error; |
711 | } | 698 | |
712 | *svalue = le16_to_cpu(*svalue); | 699 | count--; |
713 | buffer[i] = value[byteAddr]; | ||
714 | } | 700 | } |
715 | 701 | ||
716 | return true; | 702 | for (i = 0; i < count / 2; i++) { |
717 | } | 703 | if (!ar9300_eeprom_read_word(common, address, buffer)) |
704 | goto error; | ||
718 | 705 | ||
719 | static bool ar9300_read_eeprom(struct ath_hw *ah, | 706 | address -= 2; |
720 | int address, u8 *buffer, int many) | 707 | buffer += 2; |
721 | { | 708 | } |
722 | int it; | 709 | |
710 | if (count % 2) | ||
711 | if (!ar9300_eeprom_read_byte(common, address, buffer)) | ||
712 | goto error; | ||
723 | 713 | ||
724 | for (it = 0; it < many; it++) | ||
725 | if (!ar9300_hw_read_eeprom(ah, | ||
726 | (address - it), | ||
727 | (buffer + it), 1)) | ||
728 | return false; | ||
729 | return true; | 714 | return true; |
715 | |||
716 | error: | ||
717 | ath_print(common, ATH_DBG_EEPROM, | ||
718 | "unable to read eeprom region at offset %d\n", address); | ||
719 | return false; | ||
730 | } | 720 | } |
731 | 721 | ||
732 | static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, | 722 | static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, |
@@ -927,30 +917,13 @@ fail: | |||
927 | */ | 917 | */ |
928 | static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah) | 918 | static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah) |
929 | { | 919 | { |
930 | u8 *mptr = NULL; | 920 | u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep; |
931 | int mdata_size; | ||
932 | 921 | ||
933 | mptr = (u8 *) &ah->eeprom.ar9300_eep; | 922 | if (ar9300_eeprom_restore_internal(ah, mptr, |
934 | mdata_size = sizeof(struct ar9300_eeprom); | 923 | sizeof(struct ar9300_eeprom)) < 0) |
924 | return false; | ||
935 | 925 | ||
936 | if (mptr && mdata_size > 0) { | 926 | return true; |
937 | /* At this point, mptr points to the eeprom data structure | ||
938 | * in it's "default" state. If this is big endian, swap the | ||
939 | * data structures back to "little endian" | ||
940 | */ | ||
941 | /* First swap, default to Little Endian */ | ||
942 | #ifdef __BIG_ENDIAN | ||
943 | ar9300_swap_eeprom((struct ar9300_eeprom *)mptr); | ||
944 | #endif | ||
945 | if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0) | ||
946 | return true; | ||
947 | |||
948 | /* Second Swap, back to Big Endian */ | ||
949 | #ifdef __BIG_ENDIAN | ||
950 | ar9300_swap_eeprom((struct ar9300_eeprom *)mptr); | ||
951 | #endif | ||
952 | } | ||
953 | return false; | ||
954 | } | 927 | } |
955 | 928 | ||
956 | /* XXX: review hardware docs */ | 929 | /* XXX: review hardware docs */ |
@@ -998,21 +971,25 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) | |||
998 | static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) | 971 | static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) |
999 | { | 972 | { |
1000 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 973 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
974 | __le32 val; | ||
1001 | 975 | ||
1002 | if (is2ghz) | 976 | if (is2ghz) |
1003 | return eep->modalHeader2G.antCtrlCommon; | 977 | val = eep->modalHeader2G.antCtrlCommon; |
1004 | else | 978 | else |
1005 | return eep->modalHeader5G.antCtrlCommon; | 979 | val = eep->modalHeader5G.antCtrlCommon; |
980 | return le32_to_cpu(val); | ||
1006 | } | 981 | } |
1007 | 982 | ||
1008 | static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz) | 983 | static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz) |
1009 | { | 984 | { |
1010 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 985 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
986 | __le32 val; | ||
1011 | 987 | ||
1012 | if (is2ghz) | 988 | if (is2ghz) |
1013 | return eep->modalHeader2G.antCtrlCommon2; | 989 | val = eep->modalHeader2G.antCtrlCommon2; |
1014 | else | 990 | else |
1015 | return eep->modalHeader5G.antCtrlCommon2; | 991 | val = eep->modalHeader5G.antCtrlCommon2; |
992 | return le32_to_cpu(val); | ||
1016 | } | 993 | } |
1017 | 994 | ||
1018 | static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, | 995 | static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, |
@@ -1020,15 +997,16 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, | |||
1020 | bool is2ghz) | 997 | bool is2ghz) |
1021 | { | 998 | { |
1022 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 999 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
1000 | __le16 val = 0; | ||
1023 | 1001 | ||
1024 | if (chain >= 0 && chain < AR9300_MAX_CHAINS) { | 1002 | if (chain >= 0 && chain < AR9300_MAX_CHAINS) { |
1025 | if (is2ghz) | 1003 | if (is2ghz) |
1026 | return eep->modalHeader2G.antCtrlChain[chain]; | 1004 | val = eep->modalHeader2G.antCtrlChain[chain]; |
1027 | else | 1005 | else |
1028 | return eep->modalHeader5G.antCtrlChain[chain]; | 1006 | val = eep->modalHeader5G.antCtrlChain[chain]; |
1029 | } | 1007 | } |
1030 | 1008 | ||
1031 | return 0; | 1009 | return le16_to_cpu(val); |
1032 | } | 1010 | } |
1033 | 1011 | ||
1034 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | 1012 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index d8c0318f416f..23fb353c3bba 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
@@ -169,7 +169,7 @@ enum CompressAlgorithm { | |||
169 | }; | 169 | }; |
170 | 170 | ||
171 | struct ar9300_base_eep_hdr { | 171 | struct ar9300_base_eep_hdr { |
172 | u16 regDmn[2]; | 172 | __le16 regDmn[2]; |
173 | /* 4 bits tx and 4 bits rx */ | 173 | /* 4 bits tx and 4 bits rx */ |
174 | u8 txrxMask; | 174 | u8 txrxMask; |
175 | struct eepFlags opCapFlags; | 175 | struct eepFlags opCapFlags; |
@@ -199,16 +199,16 @@ struct ar9300_base_eep_hdr { | |||
199 | u8 rxBandSelectGpio; | 199 | u8 rxBandSelectGpio; |
200 | u8 txrxgain; | 200 | u8 txrxgain; |
201 | /* SW controlled internal regulator fields */ | 201 | /* SW controlled internal regulator fields */ |
202 | u32 swreg; | 202 | __le32 swreg; |
203 | } __packed; | 203 | } __packed; |
204 | 204 | ||
205 | struct ar9300_modal_eep_header { | 205 | struct ar9300_modal_eep_header { |
206 | /* 4 idle, t1, t2, b (4 bits per setting) */ | 206 | /* 4 idle, t1, t2, b (4 bits per setting) */ |
207 | u32 antCtrlCommon; | 207 | __le32 antCtrlCommon; |
208 | /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ | 208 | /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ |
209 | u32 antCtrlCommon2; | 209 | __le32 antCtrlCommon2; |
210 | /* 6 idle, t, r, rx1, rx12, b (2 bits each) */ | 210 | /* 6 idle, t, r, rx1, rx12, b (2 bits each) */ |
211 | u16 antCtrlChain[AR9300_MAX_CHAINS]; | 211 | __le16 antCtrlChain[AR9300_MAX_CHAINS]; |
212 | /* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ | 212 | /* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ |
213 | u8 xatten1DB[AR9300_MAX_CHAINS]; | 213 | u8 xatten1DB[AR9300_MAX_CHAINS]; |
214 | /* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */ | 214 | /* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */ |