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

Commit ffdc4cbe authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville
Browse files

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: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9bff0bc4
Loading
Loading
Loading
Loading
+76 −98
Original line number Original line Diff line number Diff line
@@ -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]);
	eep->baseEepHeader.regDmn[0] = word;

	word = swab16(eep->baseEepHeader.regDmn[1]);
	eep->baseEepHeader.regDmn[1] = word;

	dword = swab32(eep->baseEepHeader.swreg);
	eep->baseEepHeader.swreg = dword;


	dword = swab32(eep->modalHeader2G.antCtrlCommon);
	if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
	eep->modalHeader2G.antCtrlCommon = dword;
		return false;


	dword = swab32(eep->modalHeader2G.antCtrlCommon2);
	*buffer = (val >> (8 * (address % 2))) & 0xff;
	eep->modalHeader2G.antCtrlCommon2 = dword;
	return true;
}


	dword = swab32(eep->modalHeader5G.antCtrlCommon);
static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
	eep->modalHeader5G.antCtrlCommon = dword;
				    u8 *buffer)
{
	u16 val;


	dword = swab32(eep->modalHeader5G.antCtrlCommon2);
	if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
	eep->modalHeader5G.antCtrlCommon2 = dword;
		return false;


	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
	buffer[0] = val >> 8;
		word = swab16(eep->modalHeader2G.antCtrlChain[i]);
	buffer[1] = val & 0xff;
		eep->modalHeader2G.antCtrlChain[i] = word;


		word = swab16(eep->modalHeader5G.antCtrlChain[i]);
	return true;
		eep->modalHeader5G.antCtrlChain[i] = word;
	}
}
}
#endif


static bool ar9300_hw_read_eeprom(struct ath_hw *ah,
static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
				  long address, u8 *buffer, int many)
			       int count)
{
{
	int i;
	u8 value[2];
	unsigned long eepAddr;
	unsigned long byteAddr;
	u16 *svalue;
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath_common *common = ath9k_hw_common(ah);
	int i;


	if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) {
	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;

		address -= 2;
		buffer += 2;
	}
	}


static bool ar9300_read_eeprom(struct ath_hw *ah,
	if (count % 2)
			       int address, u8 *buffer, int many)
		if (!ar9300_eeprom_read_byte(common, address, buffer))
{
			goto error;
	int it;


	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 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
 */
 */
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) {
		/* 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;
	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)
+5 −5
Original line number Original line Diff line number Diff line
@@ -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 */