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>
This commit is contained in:
parent
9bff0bc401
commit
ffdc4cbe5b
2 changed files with 86 additions and 108 deletions
|
@ -38,6 +38,9 @@
|
||||||
#define AR_SWITCH_TABLE_ALL (0xfff)
|
#define AR_SWITCH_TABLE_ALL (0xfff)
|
||||||
#define AR_SWITCH_TABLE_ALL_S (0)
|
#define AR_SWITCH_TABLE_ALL_S (0)
|
||||||
|
|
||||||
|
#define LE16(x) __constant_cpu_to_le16(x)
|
||||||
|
#define LE32(x) __constant_cpu_to_le32(x)
|
||||||
|
|
||||||
static const struct ar9300_eeprom ar9300_default = {
|
static const struct ar9300_eeprom ar9300_default = {
|
||||||
.eepromVersion = 2,
|
.eepromVersion = 2,
|
||||||
.templateVersion = 2,
|
.templateVersion = 2,
|
||||||
|
@ -45,7 +48,7 @@ static const struct ar9300_eeprom ar9300_default = {
|
||||||
.custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
.custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
.baseEepHeader = {
|
.baseEepHeader = {
|
||||||
.regDmn = {0, 0x1f},
|
.regDmn = { LE16(0), LE16(0x1f) },
|
||||||
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
|
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
|
||||||
.opCapFlags = {
|
.opCapFlags = {
|
||||||
.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
|
.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
|
||||||
|
@ -76,15 +79,15 @@ static const struct ar9300_eeprom ar9300_default = {
|
||||||
.modalHeader2G = {
|
.modalHeader2G = {
|
||||||
/* ar9300_modal_eep_header 2g */
|
/* ar9300_modal_eep_header 2g */
|
||||||
/* 4 idle,t1,t2,b(4 bits per setting) */
|
/* 4 idle,t1,t2,b(4 bits per setting) */
|
||||||
.antCtrlCommon = 0x110,
|
.antCtrlCommon = LE32(0x110),
|
||||||
/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
|
/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
|
||||||
.antCtrlCommon2 = 0x22222,
|
.antCtrlCommon2 = LE32(0x22222),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
|
* antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
|
||||||
* rx1, rx12, b (2 bits each)
|
* rx1, rx12, b (2 bits each)
|
||||||
*/
|
*/
|
||||||
.antCtrlChain = {0x150, 0x150, 0x150},
|
.antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
|
* xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
|
||||||
|
@ -287,12 +290,12 @@ static const struct ar9300_eeprom ar9300_default = {
|
||||||
},
|
},
|
||||||
.modalHeader5G = {
|
.modalHeader5G = {
|
||||||
/* 4 idle,t1,t2,b (4 bits per setting) */
|
/* 4 idle,t1,t2,b (4 bits per setting) */
|
||||||
.antCtrlCommon = 0x110,
|
.antCtrlCommon = LE32(0x110),
|
||||||
/* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
|
/* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
|
||||||
.antCtrlCommon2 = 0x22222,
|
.antCtrlCommon2 = LE32(0x22222),
|
||||||
/* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
|
/* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
|
||||||
.antCtrlChain = {
|
.antCtrlChain = {
|
||||||
0x000, 0x000, 0x000,
|
LE16(0x000), LE16(0x000), LE16(0x000),
|
||||||
},
|
},
|
||||||
/* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
|
/* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
|
||||||
.xatten1DB = {0, 0, 0},
|
.xatten1DB = {0, 0, 0},
|
||||||
|
@ -620,9 +623,9 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
|
||||||
case EEP_MAC_MSW:
|
case EEP_MAC_MSW:
|
||||||
return eep->macAddr[4] << 8 | eep->macAddr[5];
|
return eep->macAddr[4] << 8 | eep->macAddr[5];
|
||||||
case EEP_REG_0:
|
case EEP_REG_0:
|
||||||
return pBase->regDmn[0];
|
return le16_to_cpu(pBase->regDmn[0]);
|
||||||
case EEP_REG_1:
|
case EEP_REG_1:
|
||||||
return pBase->regDmn[1];
|
return le16_to_cpu(pBase->regDmn[1]);
|
||||||
case EEP_OP_CAP:
|
case EEP_OP_CAP:
|
||||||
return pBase->deviceCap;
|
return pBase->deviceCap;
|
||||||
case EEP_OP_MODE:
|
case EEP_OP_MODE:
|
||||||
|
@ -640,93 +643,80 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
|
||||||
/* Bit 4 is internal regulator flag */
|
/* Bit 4 is internal regulator flag */
|
||||||
return (pBase->featureEnable & 0x10) >> 4;
|
return (pBase->featureEnable & 0x10) >> 4;
|
||||||
case EEP_SWREG:
|
case EEP_SWREG:
|
||||||
return pBase->swreg;
|
return le32_to_cpu(pBase->swreg);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN
|
static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
|
||||||
static void ar9300_swap_eeprom(struct ar9300_eeprom *eep)
|
u8 *buffer)
|
||||||
{
|
{
|
||||||
u32 dword;
|
u16 val;
|
||||||
u16 word;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
word = swab16(eep->baseEepHeader.regDmn[0]);
|
if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
|
||||||
eep->baseEepHeader.regDmn[0] = word;
|
return false;
|
||||||
|
|
||||||
word = swab16(eep->baseEepHeader.regDmn[1]);
|
*buffer = (val >> (8 * (address % 2))) & 0xff;
|
||||||
eep->baseEepHeader.regDmn[1] = word;
|
return true;
|
||||||
|
|
||||||
dword = swab32(eep->baseEepHeader.swreg);
|
|
||||||
eep->baseEepHeader.swreg = dword;
|
|
||||||
|
|
||||||
dword = swab32(eep->modalHeader2G.antCtrlCommon);
|
|
||||||
eep->modalHeader2G.antCtrlCommon = dword;
|
|
||||||
|
|
||||||
dword = swab32(eep->modalHeader2G.antCtrlCommon2);
|
|
||||||
eep->modalHeader2G.antCtrlCommon2 = dword;
|
|
||||||
|
|
||||||
dword = swab32(eep->modalHeader5G.antCtrlCommon);
|
|
||||||
eep->modalHeader5G.antCtrlCommon = dword;
|
|
||||||
|
|
||||||
dword = swab32(eep->modalHeader5G.antCtrlCommon2);
|
|
||||||
eep->modalHeader5G.antCtrlCommon2 = dword;
|
|
||||||
|
|
||||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
|
||||||
word = swab16(eep->modalHeader2G.antCtrlChain[i]);
|
|
||||||
eep->modalHeader2G.antCtrlChain[i] = word;
|
|
||||||
|
|
||||||
word = swab16(eep->modalHeader5G.antCtrlChain[i]);
|
|
||||||
eep->modalHeader5G.antCtrlChain[i] = word;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool ar9300_hw_read_eeprom(struct ath_hw *ah,
|
static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
|
||||||
long address, u8 *buffer, int many)
|
u8 *buffer)
|
||||||
{
|
{
|
||||||
int i;
|
u16 val;
|
||||||
u8 value[2];
|
|
||||||
unsigned long eepAddr;
|
|
||||||
unsigned long byteAddr;
|
|
||||||
u16 *svalue;
|
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
|
||||||
|
|
||||||
if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) {
|
if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
buffer[0] = val >> 8;
|
||||||
|
buffer[1] = val & 0xff;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
|
||||||
ath_print(common, ATH_DBG_EEPROM,
|
ath_print(common, ATH_DBG_EEPROM,
|
||||||
"eeprom address not in range\n");
|
"eeprom address not in range\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < many; i++) {
|
/*
|
||||||
eepAddr = (u16) (address + i) / 2;
|
* Since we're reading the bytes in reverse order from a little-endian
|
||||||
byteAddr = (u16) (address + i) % 2;
|
* word stream, an even address means we only use the lower half of
|
||||||
svalue = (u16 *) value;
|
* the 16-bit word at that address
|
||||||
if (!ath9k_hw_nvram_read(common, eepAddr, svalue)) {
|
*/
|
||||||
ath_print(common, ATH_DBG_EEPROM,
|
if (address % 2 == 0) {
|
||||||
"unable to read eeprom region\n");
|
if (!ar9300_eeprom_read_byte(common, address--, buffer++))
|
||||||
return false;
|
goto error;
|
||||||
}
|
|
||||||
*svalue = le16_to_cpu(*svalue);
|
count--;
|
||||||
buffer[i] = value[byteAddr];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
for (i = 0; i < count / 2; i++) {
|
||||||
}
|
if (!ar9300_eeprom_read_word(common, address, buffer))
|
||||||
|
goto error;
|
||||||
|
|
||||||
static bool ar9300_read_eeprom(struct ath_hw *ah,
|
address -= 2;
|
||||||
int address, u8 *buffer, int many)
|
buffer += 2;
|
||||||
{
|
}
|
||||||
int it;
|
|
||||||
|
if (count % 2)
|
||||||
|
if (!ar9300_eeprom_read_byte(common, address, buffer))
|
||||||
|
goto error;
|
||||||
|
|
||||||
for (it = 0; it < many; it++)
|
|
||||||
if (!ar9300_hw_read_eeprom(ah,
|
|
||||||
(address - it),
|
|
||||||
(buffer + it), 1))
|
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ath_print(common, ATH_DBG_EEPROM,
|
||||||
|
"unable to read eeprom region at offset %d\n", address);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
|
static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
|
||||||
|
@ -927,30 +917,13 @@ fail:
|
||||||
*/
|
*/
|
||||||
static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
|
static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
u8 *mptr = NULL;
|
u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
|
||||||
int mdata_size;
|
|
||||||
|
|
||||||
mptr = (u8 *) &ah->eeprom.ar9300_eep;
|
if (ar9300_eeprom_restore_internal(ah, mptr,
|
||||||
mdata_size = sizeof(struct ar9300_eeprom);
|
sizeof(struct ar9300_eeprom)) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (mptr && mdata_size > 0) {
|
return true;
|
||||||
/* At this point, mptr points to the eeprom data structure
|
|
||||||
* in it's "default" state. If this is big endian, swap the
|
|
||||||
* data structures back to "little endian"
|
|
||||||
*/
|
|
||||||
/* First swap, default to Little Endian */
|
|
||||||
#ifdef __BIG_ENDIAN
|
|
||||||
ar9300_swap_eeprom((struct ar9300_eeprom *)mptr);
|
|
||||||
#endif
|
|
||||||
if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/* Second Swap, back to Big Endian */
|
|
||||||
#ifdef __BIG_ENDIAN
|
|
||||||
ar9300_swap_eeprom((struct ar9300_eeprom *)mptr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: review hardware docs */
|
/* XXX: review hardware docs */
|
||||||
|
@ -998,21 +971,25 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
|
||||||
static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
|
static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
|
||||||
{
|
{
|
||||||
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
||||||
|
__le32 val;
|
||||||
|
|
||||||
if (is2ghz)
|
if (is2ghz)
|
||||||
return eep->modalHeader2G.antCtrlCommon;
|
val = eep->modalHeader2G.antCtrlCommon;
|
||||||
else
|
else
|
||||||
return eep->modalHeader5G.antCtrlCommon;
|
val = eep->modalHeader5G.antCtrlCommon;
|
||||||
|
return le32_to_cpu(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
|
static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
|
||||||
{
|
{
|
||||||
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
||||||
|
__le32 val;
|
||||||
|
|
||||||
if (is2ghz)
|
if (is2ghz)
|
||||||
return eep->modalHeader2G.antCtrlCommon2;
|
val = eep->modalHeader2G.antCtrlCommon2;
|
||||||
else
|
else
|
||||||
return eep->modalHeader5G.antCtrlCommon2;
|
val = eep->modalHeader5G.antCtrlCommon2;
|
||||||
|
return le32_to_cpu(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
|
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,
|
||||||
bool is2ghz)
|
bool is2ghz)
|
||||||
{
|
{
|
||||||
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
||||||
|
__le16 val = 0;
|
||||||
|
|
||||||
if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
|
if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
|
||||||
if (is2ghz)
|
if (is2ghz)
|
||||||
return eep->modalHeader2G.antCtrlChain[chain];
|
val = eep->modalHeader2G.antCtrlChain[chain];
|
||||||
else
|
else
|
||||||
return eep->modalHeader5G.antCtrlChain[chain];
|
val = eep->modalHeader5G.antCtrlChain[chain];
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return le16_to_cpu(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
|
static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
|
||||||
|
|
|
@ -169,7 +169,7 @@ enum CompressAlgorithm {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ar9300_base_eep_hdr {
|
struct ar9300_base_eep_hdr {
|
||||||
u16 regDmn[2];
|
__le16 regDmn[2];
|
||||||
/* 4 bits tx and 4 bits rx */
|
/* 4 bits tx and 4 bits rx */
|
||||||
u8 txrxMask;
|
u8 txrxMask;
|
||||||
struct eepFlags opCapFlags;
|
struct eepFlags opCapFlags;
|
||||||
|
@ -199,16 +199,16 @@ struct ar9300_base_eep_hdr {
|
||||||
u8 rxBandSelectGpio;
|
u8 rxBandSelectGpio;
|
||||||
u8 txrxgain;
|
u8 txrxgain;
|
||||||
/* SW controlled internal regulator fields */
|
/* SW controlled internal regulator fields */
|
||||||
u32 swreg;
|
__le32 swreg;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct ar9300_modal_eep_header {
|
struct ar9300_modal_eep_header {
|
||||||
/* 4 idle, t1, t2, b (4 bits per setting) */
|
/* 4 idle, t1, t2, b (4 bits per setting) */
|
||||||
u32 antCtrlCommon;
|
__le32 antCtrlCommon;
|
||||||
/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
|
/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
|
||||||
u32 antCtrlCommon2;
|
__le32 antCtrlCommon2;
|
||||||
/* 6 idle, t, r, rx1, rx12, b (2 bits each) */
|
/* 6 idle, t, r, rx1, rx12, b (2 bits each) */
|
||||||
u16 antCtrlChain[AR9300_MAX_CHAINS];
|
__le16 antCtrlChain[AR9300_MAX_CHAINS];
|
||||||
/* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
|
/* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
|
||||||
u8 xatten1DB[AR9300_MAX_CHAINS];
|
u8 xatten1DB[AR9300_MAX_CHAINS];
|
||||||
/* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */
|
/* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue