ath9k: Simplify and fix eeprom endianness swapping
The three eeprom implementations had quite some duplicate code when it came to endianness swapping. Additionally there was a bug in eeprom_4k and eeprom_9287 which prevented the endianness swapping from working correctly, because the swapping code was guarded within an "if (!ath9k_hw_use_flash(ah))". In eeprom_def this check did not exist, so it seems that eeprom_def was the only implementation where endianness swapping worked. This patch takes the duplicate code and moves it from eeprom_* to eeprom.c. The new code is derived from eeprom_def, while taking into account the specifics from the other implementations. Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
b057886524
commit
6fa658fd5a
|
@ -138,6 +138,80 @@ bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
|
||||||
|
{
|
||||||
|
u16 magic;
|
||||||
|
u16 *eepdata;
|
||||||
|
int i;
|
||||||
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
|
||||||
|
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
|
||||||
|
ath_err(common, "Reading Magic # failed\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (magic == AR5416_EEPROM_MAGIC) {
|
||||||
|
*swap_needed = false;
|
||||||
|
} else if (swab16(magic) == AR5416_EEPROM_MAGIC) {
|
||||||
|
if (ah->ah_flags & AH_NO_EEP_SWAP) {
|
||||||
|
ath_info(common,
|
||||||
|
"Ignoring endianness difference in EEPROM magic bytes.\n");
|
||||||
|
|
||||||
|
*swap_needed = false;
|
||||||
|
} else {
|
||||||
|
*swap_needed = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ath_err(common,
|
||||||
|
"Invalid EEPROM Magic (0x%04x).\n", magic);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
eepdata = (u16 *)(&ah->eeprom);
|
||||||
|
|
||||||
|
if (*swap_needed) {
|
||||||
|
ath_dbg(common, EEPROM,
|
||||||
|
"EEPROM Endianness is not native.. Changing.\n");
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
eepdata[i] = swab16(eepdata[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size)
|
||||||
|
{
|
||||||
|
u32 i, sum = 0;
|
||||||
|
u16 *eepdata = (u16 *)(&ah->eeprom);
|
||||||
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
sum ^= eepdata[i];
|
||||||
|
|
||||||
|
if (sum != 0xffff) {
|
||||||
|
ath_err(common, "Bad EEPROM checksum 0x%x\n", sum);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev)
|
||||||
|
{
|
||||||
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
|
||||||
|
if (ah->eep_ops->get_eeprom_ver(ah) != version ||
|
||||||
|
ah->eep_ops->get_eeprom_rev(ah) < minrev) {
|
||||||
|
ath_err(common, "Bad EEPROM VER 0x%04x or REV 0x%04x\n",
|
||||||
|
ah->eep_ops->get_eeprom_ver(ah),
|
||||||
|
ah->eep_ops->get_eeprom_rev(ah));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
|
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
|
||||||
u8 *pVpdList, u16 numIntercepts,
|
u8 *pVpdList, u16 numIntercepts,
|
||||||
u8 *pRetVpdList)
|
u8 *pRetVpdList)
|
||||||
|
|
|
@ -664,6 +664,9 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
|
||||||
bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
|
bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
|
||||||
u16 *indexL, u16 *indexR);
|
u16 *indexL, u16 *indexR);
|
||||||
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
|
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
|
||||||
|
int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size);
|
||||||
|
bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size);
|
||||||
|
bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev);
|
||||||
void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
|
void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
|
||||||
int eep_start_loc, int size);
|
int eep_start_loc, int size);
|
||||||
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
|
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
|
||||||
|
|
|
@ -177,74 +177,30 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#undef SIZE_EEPROM_4K
|
|
||||||
|
|
||||||
static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
|
static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
|
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
|
||||||
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
|
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
|
||||||
u16 *eepdata, temp, magic, magic2;
|
u32 el;
|
||||||
u32 sum = 0, el;
|
bool need_swap;
|
||||||
bool need_swap = false;
|
int i, err;
|
||||||
int i, addr;
|
|
||||||
|
|
||||||
|
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_4K);
|
||||||
if (!ath9k_hw_use_flash(ah)) {
|
if (err)
|
||||||
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
|
return err;
|
||||||
&magic)) {
|
|
||||||
ath_err(common, "Reading Magic # failed\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
|
|
||||||
|
|
||||||
if (magic != AR5416_EEPROM_MAGIC) {
|
|
||||||
magic2 = swab16(magic);
|
|
||||||
|
|
||||||
if (magic2 == AR5416_EEPROM_MAGIC) {
|
|
||||||
need_swap = true;
|
|
||||||
eepdata = (u16 *) (&ah->eeprom);
|
|
||||||
|
|
||||||
for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
|
|
||||||
temp = swab16(*eepdata);
|
|
||||||
*eepdata = temp;
|
|
||||||
eepdata++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ath_err(common,
|
|
||||||
"Invalid EEPROM Magic. Endianness mismatch.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ath_dbg(common, EEPROM, "need_swap = %s\n",
|
|
||||||
need_swap ? "True" : "False");
|
|
||||||
|
|
||||||
if (need_swap)
|
if (need_swap)
|
||||||
el = swab16(ah->eeprom.map4k.baseEepHeader.length);
|
el = swab16(eep->baseEepHeader.length);
|
||||||
else
|
else
|
||||||
el = ah->eeprom.map4k.baseEepHeader.length;
|
el = eep->baseEepHeader.length;
|
||||||
|
|
||||||
if (el > sizeof(struct ar5416_eeprom_4k))
|
el = min(el / sizeof(u16), SIZE_EEPROM_4K);
|
||||||
el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
|
if (!ath9k_hw_nvram_validate_checksum(ah, el))
|
||||||
else
|
return -EINVAL;
|
||||||
el = el / sizeof(u16);
|
|
||||||
|
|
||||||
eepdata = (u16 *)(&ah->eeprom);
|
|
||||||
|
|
||||||
for (i = 0; i < el; i++)
|
|
||||||
sum ^= *eepdata++;
|
|
||||||
|
|
||||||
if (need_swap) {
|
if (need_swap) {
|
||||||
u32 integer;
|
u32 integer;
|
||||||
u16 word;
|
u16 word;
|
||||||
|
|
||||||
ath_dbg(common, EEPROM,
|
|
||||||
"EEPROM Endianness is not native.. Changing\n");
|
|
||||||
|
|
||||||
word = swab16(eep->baseEepHeader.length);
|
word = swab16(eep->baseEepHeader.length);
|
||||||
eep->baseEepHeader.length = word;
|
eep->baseEepHeader.length = word;
|
||||||
|
|
||||||
|
@ -283,17 +239,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
|
if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
|
||||||
ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
|
AR5416_EEP_NO_BACK_VER))
|
||||||
ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
|
||||||
sum, ah->eep_ops->get_eeprom_ver(ah));
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#undef EEPROM_4K_SIZE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef SIZE_EEPROM_4K
|
||||||
|
|
||||||
static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
|
static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
|
||||||
enum eeprom_param param)
|
enum eeprom_param param)
|
||||||
{
|
{
|
||||||
|
|
|
@ -177,59 +177,24 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
|
||||||
|
|
||||||
static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
|
static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
u32 sum = 0, el, integer;
|
u32 el, integer;
|
||||||
u16 temp, word, magic, magic2, *eepdata;
|
u16 word;
|
||||||
int i, addr;
|
int i, err;
|
||||||
bool need_swap = false;
|
bool need_swap;
|
||||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
|
||||||
|
|
||||||
if (!ath9k_hw_use_flash(ah)) {
|
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287);
|
||||||
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
|
if (err)
|
||||||
&magic)) {
|
return err;
|
||||||
ath_err(common, "Reading Magic # failed\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
|
|
||||||
|
|
||||||
if (magic != AR5416_EEPROM_MAGIC) {
|
|
||||||
magic2 = swab16(magic);
|
|
||||||
|
|
||||||
if (magic2 == AR5416_EEPROM_MAGIC) {
|
|
||||||
need_swap = true;
|
|
||||||
eepdata = (u16 *)(&ah->eeprom);
|
|
||||||
|
|
||||||
for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
|
|
||||||
temp = swab16(*eepdata);
|
|
||||||
*eepdata = temp;
|
|
||||||
eepdata++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ath_err(common,
|
|
||||||
"Invalid EEPROM Magic. Endianness mismatch.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ath_dbg(common, EEPROM, "need_swap = %s\n",
|
|
||||||
need_swap ? "True" : "False");
|
|
||||||
|
|
||||||
if (need_swap)
|
if (need_swap)
|
||||||
el = swab16(ah->eeprom.map9287.baseEepHeader.length);
|
el = swab16(eep->baseEepHeader.length);
|
||||||
else
|
else
|
||||||
el = ah->eeprom.map9287.baseEepHeader.length;
|
el = eep->baseEepHeader.length;
|
||||||
|
|
||||||
if (el > sizeof(struct ar9287_eeprom))
|
el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
|
||||||
el = sizeof(struct ar9287_eeprom) / sizeof(u16);
|
if (!ath9k_hw_nvram_validate_checksum(ah, el))
|
||||||
else
|
return -EINVAL;
|
||||||
el = el / sizeof(u16);
|
|
||||||
|
|
||||||
eepdata = (u16 *)(&ah->eeprom);
|
|
||||||
|
|
||||||
for (i = 0; i < el; i++)
|
|
||||||
sum ^= *eepdata++;
|
|
||||||
|
|
||||||
if (need_swap) {
|
if (need_swap) {
|
||||||
word = swab16(eep->baseEepHeader.length);
|
word = swab16(eep->baseEepHeader.length);
|
||||||
|
@ -270,16 +235,15 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
|
if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER,
|
||||||
|| ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
|
AR5416_EEP_NO_BACK_VER))
|
||||||
ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
|
||||||
sum, ah->eep_ops->get_eeprom_ver(ah));
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef SIZE_EEPROM_AR9287
|
||||||
|
|
||||||
static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
|
static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
|
||||||
enum eeprom_param param)
|
enum eeprom_param param)
|
||||||
{
|
{
|
||||||
|
|
|
@ -126,8 +126,6 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
|
||||||
return __ath9k_hw_def_fill_eeprom(ah);
|
return __ath9k_hw_def_fill_eeprom(ah);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef SIZE_EEPROM_DEF
|
|
||||||
|
|
||||||
#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
|
#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
|
||||||
static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
|
static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
|
||||||
struct modal_eep_header *modal_hdr)
|
struct modal_eep_header *modal_hdr)
|
||||||
|
@ -257,59 +255,31 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
|
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
u16 *eepdata, temp, magic;
|
u32 el;
|
||||||
u32 sum = 0, el;
|
bool need_swap;
|
||||||
bool need_swap = false;
|
int i, err;
|
||||||
int i, addr, size;
|
|
||||||
|
|
||||||
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
|
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF);
|
||||||
ath_err(common, "Reading Magic # failed\n");
|
if (err)
|
||||||
return false;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
if (swab16(magic) == AR5416_EEPROM_MAGIC &&
|
|
||||||
!(ah->ah_flags & AH_NO_EEP_SWAP)) {
|
|
||||||
size = sizeof(struct ar5416_eeprom_def);
|
|
||||||
need_swap = true;
|
|
||||||
eepdata = (u16 *) (&ah->eeprom);
|
|
||||||
|
|
||||||
for (addr = 0; addr < size / sizeof(u16); addr++) {
|
|
||||||
temp = swab16(*eepdata);
|
|
||||||
*eepdata = temp;
|
|
||||||
eepdata++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ath_dbg(common, EEPROM, "need_swap = %s\n",
|
|
||||||
need_swap ? "True" : "False");
|
|
||||||
|
|
||||||
if (need_swap)
|
if (need_swap)
|
||||||
el = swab16(ah->eeprom.def.baseEepHeader.length);
|
el = swab16(eep->baseEepHeader.length);
|
||||||
else
|
else
|
||||||
el = ah->eeprom.def.baseEepHeader.length;
|
el = eep->baseEepHeader.length;
|
||||||
|
|
||||||
if (el > sizeof(struct ar5416_eeprom_def))
|
el = min(el / sizeof(u16), SIZE_EEPROM_DEF);
|
||||||
el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
|
if (!ath9k_hw_nvram_validate_checksum(ah, el))
|
||||||
else
|
return -EINVAL;
|
||||||
el = el / sizeof(u16);
|
|
||||||
|
|
||||||
eepdata = (u16 *)(&ah->eeprom);
|
|
||||||
|
|
||||||
for (i = 0; i < el; i++)
|
|
||||||
sum ^= *eepdata++;
|
|
||||||
|
|
||||||
if (need_swap) {
|
if (need_swap) {
|
||||||
u32 integer, j;
|
u32 integer, j;
|
||||||
u16 word;
|
u16 word;
|
||||||
|
|
||||||
ath_dbg(common, EEPROM,
|
|
||||||
"EEPROM Endianness is not native.. Changing.\n");
|
|
||||||
|
|
||||||
word = swab16(eep->baseEepHeader.length);
|
word = swab16(eep->baseEepHeader.length);
|
||||||
eep->baseEepHeader.length = word;
|
eep->baseEepHeader.length = word;
|
||||||
|
|
||||||
|
@ -356,12 +326,9 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
|
if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
|
||||||
ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
|
AR5416_EEP_NO_BACK_VER))
|
||||||
ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
|
||||||
sum, ah->eep_ops->get_eeprom_ver(ah));
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable fixup for AR_AN_TOP2 if necessary */
|
/* Enable fixup for AR_AN_TOP2 if necessary */
|
||||||
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
|
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
|
||||||
|
@ -376,6 +343,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef SIZE_EEPROM_DEF
|
||||||
|
|
||||||
static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
|
static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
|
||||||
enum eeprom_param param)
|
enum eeprom_param param)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue