Skip to content

Commit

Permalink
ath9k: Simplify and fix eeprom endianness swapping
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Martin Blumenstingl authored and Kalle Valo committed Dec 8, 2015
1 parent b057886 commit 6fa658f
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 159 deletions.
74 changes: 74 additions & 0 deletions drivers/net/wireless/ath/ath9k/eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,80 @@ bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
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,
u8 *pVpdList, u16 numIntercepts,
u8 *pRetVpdList)
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/ath/ath9k/eeprom.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
u16 *indexL, u16 *indexR);
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,
int eep_start_loc, int size);
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
Expand Down
76 changes: 15 additions & 61 deletions drivers/net/wireless/ath/ath9k/eeprom_4k.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,74 +177,30 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
}
#endif


#undef SIZE_EEPROM_4K

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;
u16 *eepdata, temp, magic, magic2;
u32 sum = 0, el;
bool need_swap = false;
int i, addr;
u32 el;
bool need_swap;
int i, err;


if (!ath9k_hw_use_flash(ah)) {
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
&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");
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_4K);
if (err)
return err;

if (need_swap)
el = swab16(ah->eeprom.map4k.baseEepHeader.length);
else
el = ah->eeprom.map4k.baseEepHeader.length;

if (el > sizeof(struct ar5416_eeprom_4k))
el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
el = swab16(eep->baseEepHeader.length);
else
el = el / sizeof(u16);
el = eep->baseEepHeader.length;

eepdata = (u16 *)(&ah->eeprom);

for (i = 0; i < el; i++)
sum ^= *eepdata++;
el = min(el / sizeof(u16), SIZE_EEPROM_4K);
if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL;

if (need_swap) {
u32 integer;
u16 word;

ath_dbg(common, EEPROM,
"EEPROM Endianness is not native.. Changing\n");

word = swab16(eep->baseEepHeader.length);
eep->baseEepHeader.length = word;

Expand Down Expand Up @@ -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 ||
ah->eep_ops->get_eeprom_rev(ah) < 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));
if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
AR5416_EEP_NO_BACK_VER))
return -EINVAL;
}

return 0;
#undef EEPROM_4K_SIZE
}

#undef SIZE_EEPROM_4K

static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{
Expand Down
68 changes: 16 additions & 52 deletions drivers/net/wireless/ath/ath9k/eeprom_9287.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
u32 sum = 0, el, integer;
u16 temp, word, magic, magic2, *eepdata;
int i, addr;
bool need_swap = false;
u32 el, integer;
u16 word;
int i, err;
bool need_swap;
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
struct ath_common *common = ath9k_hw_common(ah);

if (!ath9k_hw_use_flash(ah)) {
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
&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 < 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");
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287);
if (err)
return err;

if (need_swap)
el = swab16(ah->eeprom.map9287.baseEepHeader.length);
else
el = ah->eeprom.map9287.baseEepHeader.length;

if (el > sizeof(struct ar9287_eeprom))
el = sizeof(struct ar9287_eeprom) / sizeof(u16);
el = swab16(eep->baseEepHeader.length);
else
el = el / sizeof(u16);

eepdata = (u16 *)(&ah->eeprom);
el = eep->baseEepHeader.length;

for (i = 0; i < el; i++)
sum ^= *eepdata++;
el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL;

if (need_swap) {
word = swab16(eep->baseEepHeader.length);
Expand Down Expand Up @@ -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
|| ah->eep_ops->get_eeprom_rev(ah) < 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));
if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER,
AR5416_EEP_NO_BACK_VER))
return -EINVAL;
}

return 0;
}

#undef SIZE_EEPROM_AR9287

static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{
Expand Down
61 changes: 15 additions & 46 deletions drivers/net/wireless/ath/ath9k/eeprom_def.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
return __ath9k_hw_def_fill_eeprom(ah);
}

#undef SIZE_EEPROM_DEF

#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_header *modal_hdr)
Expand Down Expand Up @@ -257,59 +255,31 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
}
#endif


static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct ath_common *common = ath9k_hw_common(ah);
u16 *eepdata, temp, magic;
u32 sum = 0, el;
bool need_swap = false;
int i, addr, size;

if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
ath_err(common, "Reading Magic # failed\n");
return false;
}

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++;
}
}
u32 el;
bool need_swap;
int i, err;

ath_dbg(common, EEPROM, "need_swap = %s\n",
need_swap ? "True" : "False");
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF);
if (err)
return err;

if (need_swap)
el = swab16(ah->eeprom.def.baseEepHeader.length);
el = swab16(eep->baseEepHeader.length);
else
el = ah->eeprom.def.baseEepHeader.length;
el = eep->baseEepHeader.length;

if (el > sizeof(struct ar5416_eeprom_def))
el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
else
el = el / sizeof(u16);

eepdata = (u16 *)(&ah->eeprom);

for (i = 0; i < el; i++)
sum ^= *eepdata++;
el = min(el / sizeof(u16), SIZE_EEPROM_DEF);
if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL;

if (need_swap) {
u32 integer, j;
u16 word;

ath_dbg(common, EEPROM,
"EEPROM Endianness is not native.. Changing.\n");

word = swab16(eep->baseEepHeader.length);
eep->baseEepHeader.length = word;

Expand Down Expand Up @@ -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 ||
ah->eep_ops->get_eeprom_rev(ah) < 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));
if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
AR5416_EEP_NO_BACK_VER))
return -EINVAL;
}

/* Enable fixup for AR_AN_TOP2 if necessary */
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
Expand All @@ -376,6 +343,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
return 0;
}

#undef SIZE_EEPROM_DEF

static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{
Expand Down

0 comments on commit 6fa658f

Please sign in to comment.