Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6fa658fd authored by Martin Blumenstingl's avatar Martin Blumenstingl Committed by Kalle Valo
Browse files

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: default avatarMartin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent b0578865
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
@@ -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)
+3 −0
Original line number Diff line number Diff line
@@ -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,
+15 −61
Original line number Diff line number Diff line
@@ -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;


	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;
			}
		}
	}
	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_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;

@@ -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)
{
+16 −52
Original line number Diff line number Diff line
@@ -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);
		el = swab16(eep->baseEepHeader.length);
	else
		el = ah->eeprom.map9287.baseEepHeader.length;
		el = eep->baseEepHeader.length;

	if (el > sizeof(struct ar9287_eeprom))
		el = sizeof(struct ar9287_eeprom) / 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_AR9287);
	if (!ath9k_hw_nvram_validate_checksum(ah, el))
		return -EINVAL;

	if (need_swap) {
		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
	    || 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)
{
+15 −46
Original line number Diff line number Diff line
@@ -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)
@@ -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;

@@ -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) &&
@@ -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)
{