aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Blumenstingl <martin.blumenstingl@googlemail.com>2015-10-31 08:57:32 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2015-12-08 09:50:18 -0500
commit6fa658fd5ab26a769ca7df7bfdd53c212a0ba852 (patch)
tree9fca9742418c07304b0389ae236ed0442dbe86f8
parentb057886524be060021e3cfad0ba8458c850330cd (diff)
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>
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c74
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c76
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c68
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c61
5 files changed, 123 insertions, 159 deletions
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index cc81482c934d..f8c5065e5f5f 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -138,6 +138,80 @@ bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
138 return ret; 138 return ret;
139} 139}
140 140
141int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
142{
143 u16 magic;
144 u16 *eepdata;
145 int i;
146 struct ath_common *common = ath9k_hw_common(ah);
147
148 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
149 ath_err(common, "Reading Magic # failed\n");
150 return -EIO;
151 }
152
153 if (magic == AR5416_EEPROM_MAGIC) {
154 *swap_needed = false;
155 } else if (swab16(magic) == AR5416_EEPROM_MAGIC) {
156 if (ah->ah_flags & AH_NO_EEP_SWAP) {
157 ath_info(common,
158 "Ignoring endianness difference in EEPROM magic bytes.\n");
159
160 *swap_needed = false;
161 } else {
162 *swap_needed = true;
163 }
164 } else {
165 ath_err(common,
166 "Invalid EEPROM Magic (0x%04x).\n", magic);
167 return -EINVAL;
168 }
169
170 eepdata = (u16 *)(&ah->eeprom);
171
172 if (*swap_needed) {
173 ath_dbg(common, EEPROM,
174 "EEPROM Endianness is not native.. Changing.\n");
175
176 for (i = 0; i < size; i++)
177 eepdata[i] = swab16(eepdata[i]);
178 }
179
180 return 0;
181}
182
183bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size)
184{
185 u32 i, sum = 0;
186 u16 *eepdata = (u16 *)(&ah->eeprom);
187 struct ath_common *common = ath9k_hw_common(ah);
188
189 for (i = 0; i < size; i++)
190 sum ^= eepdata[i];
191
192 if (sum != 0xffff) {
193 ath_err(common, "Bad EEPROM checksum 0x%x\n", sum);
194 return false;
195 }
196
197 return true;
198}
199
200bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev)
201{
202 struct ath_common *common = ath9k_hw_common(ah);
203
204 if (ah->eep_ops->get_eeprom_ver(ah) != version ||
205 ah->eep_ops->get_eeprom_rev(ah) < minrev) {
206 ath_err(common, "Bad EEPROM VER 0x%04x or REV 0x%04x\n",
207 ah->eep_ops->get_eeprom_ver(ah),
208 ah->eep_ops->get_eeprom_rev(ah));
209 return -EINVAL;
210 }
211
212 return true;
213}
214
141void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, 215void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
142 u8 *pVpdList, u16 numIntercepts, 216 u8 *pVpdList, u16 numIntercepts,
143 u8 *pRetVpdList) 217 u8 *pRetVpdList)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 40d4f62d0f16..4465c6566f20 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -664,6 +664,9 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
664bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, 664bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
665 u16 *indexL, u16 *indexR); 665 u16 *indexL, u16 *indexR);
666bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data); 666bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
667int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size);
668bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size);
669bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev);
667void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, 670void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
668 int eep_start_loc, int size); 671 int eep_start_loc, int size);
669void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, 672void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 4773da6dc6f2..5da0826bf1be 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -177,74 +177,30 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
177} 177}
178#endif 178#endif
179 179
180
181#undef SIZE_EEPROM_4K
182
183static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) 180static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
184{ 181{
185#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
186 struct ath_common *common = ath9k_hw_common(ah);
187 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; 182 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
188 u16 *eepdata, temp, magic, magic2; 183 u32 el;
189 u32 sum = 0, el; 184 bool need_swap;
190 bool need_swap = false; 185 int i, err;
191 int i, addr;
192 186
193 187 err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_4K);
194 if (!ath9k_hw_use_flash(ah)) { 188 if (err)
195 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, 189 return err;
196 &magic)) {
197 ath_err(common, "Reading Magic # failed\n");
198 return false;
199 }
200
201 ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
202
203 if (magic != AR5416_EEPROM_MAGIC) {
204 magic2 = swab16(magic);
205
206 if (magic2 == AR5416_EEPROM_MAGIC) {
207 need_swap = true;
208 eepdata = (u16 *) (&ah->eeprom);
209
210 for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
211 temp = swab16(*eepdata);
212 *eepdata = temp;
213 eepdata++;
214 }
215 } else {
216 ath_err(common,
217 "Invalid EEPROM Magic. Endianness mismatch.\n");
218 return -EINVAL;
219 }
220 }
221 }
222
223 ath_dbg(common, EEPROM, "need_swap = %s\n",
224 need_swap ? "True" : "False");
225 190
226 if (need_swap) 191 if (need_swap)
227 el = swab16(ah->eeprom.map4k.baseEepHeader.length); 192 el = swab16(eep->baseEepHeader.length);
228 else
229 el = ah->eeprom.map4k.baseEepHeader.length;
230
231 if (el > sizeof(struct ar5416_eeprom_4k))
232 el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
233 else 193 else
234 el = el / sizeof(u16); 194 el = eep->baseEepHeader.length;
235 195
236 eepdata = (u16 *)(&ah->eeprom); 196 el = min(el / sizeof(u16), SIZE_EEPROM_4K);
237 197 if (!ath9k_hw_nvram_validate_checksum(ah, el))
238 for (i = 0; i < el; i++) 198 return -EINVAL;
239 sum ^= *eepdata++;
240 199
241 if (need_swap) { 200 if (need_swap) {
242 u32 integer; 201 u32 integer;
243 u16 word; 202 u16 word;
244 203
245 ath_dbg(common, EEPROM,
246 "EEPROM Endianness is not native.. Changing\n");
247
248 word = swab16(eep->baseEepHeader.length); 204 word = swab16(eep->baseEepHeader.length);
249 eep->baseEepHeader.length = word; 205 eep->baseEepHeader.length = word;
250 206
@@ -283,17 +239,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
283 } 239 }
284 } 240 }
285 241
286 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || 242 if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
287 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { 243 AR5416_EEP_NO_BACK_VER))
288 ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
289 sum, ah->eep_ops->get_eeprom_ver(ah));
290 return -EINVAL; 244 return -EINVAL;
291 }
292 245
293 return 0; 246 return 0;
294#undef EEPROM_4K_SIZE
295} 247}
296 248
249#undef SIZE_EEPROM_4K
250
297static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, 251static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
298 enum eeprom_param param) 252 enum eeprom_param param)
299{ 253{
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 6ca33dfde1fd..1a019a39eda1 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -177,59 +177,24 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
177 177
178static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) 178static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
179{ 179{
180 u32 sum = 0, el, integer; 180 u32 el, integer;
181 u16 temp, word, magic, magic2, *eepdata; 181 u16 word;
182 int i, addr; 182 int i, err;
183 bool need_swap = false; 183 bool need_swap;
184 struct ar9287_eeprom *eep = &ah->eeprom.map9287; 184 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
185 struct ath_common *common = ath9k_hw_common(ah);
186
187 if (!ath9k_hw_use_flash(ah)) {
188 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
189 &magic)) {
190 ath_err(common, "Reading Magic # failed\n");
191 return false;
192 }
193
194 ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
195
196 if (magic != AR5416_EEPROM_MAGIC) {
197 magic2 = swab16(magic);
198
199 if (magic2 == AR5416_EEPROM_MAGIC) {
200 need_swap = true;
201 eepdata = (u16 *)(&ah->eeprom);
202
203 for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
204 temp = swab16(*eepdata);
205 *eepdata = temp;
206 eepdata++;
207 }
208 } else {
209 ath_err(common,
210 "Invalid EEPROM Magic. Endianness mismatch.\n");
211 return -EINVAL;
212 }
213 }
214 }
215 185
216 ath_dbg(common, EEPROM, "need_swap = %s\n", 186 err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287);
217 need_swap ? "True" : "False"); 187 if (err)
188 return err;
218 189
219 if (need_swap) 190 if (need_swap)
220 el = swab16(ah->eeprom.map9287.baseEepHeader.length); 191 el = swab16(eep->baseEepHeader.length);
221 else
222 el = ah->eeprom.map9287.baseEepHeader.length;
223
224 if (el > sizeof(struct ar9287_eeprom))
225 el = sizeof(struct ar9287_eeprom) / sizeof(u16);
226 else 192 else
227 el = el / sizeof(u16); 193 el = eep->baseEepHeader.length;
228
229 eepdata = (u16 *)(&ah->eeprom);
230 194
231 for (i = 0; i < el; i++) 195 el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
232 sum ^= *eepdata++; 196 if (!ath9k_hw_nvram_validate_checksum(ah, el))
197 return -EINVAL;
233 198
234 if (need_swap) { 199 if (need_swap) {
235 word = swab16(eep->baseEepHeader.length); 200 word = swab16(eep->baseEepHeader.length);
@@ -270,16 +235,15 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
270 } 235 }
271 } 236 }
272 237
273 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER 238 if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER,
274 || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { 239 AR5416_EEP_NO_BACK_VER))
275 ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
276 sum, ah->eep_ops->get_eeprom_ver(ah));
277 return -EINVAL; 240 return -EINVAL;
278 }
279 241
280 return 0; 242 return 0;
281} 243}
282 244
245#undef SIZE_EEPROM_AR9287
246
283static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, 247static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
284 enum eeprom_param param) 248 enum eeprom_param param)
285{ 249{
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 056f516bf017..959682f7909c 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -126,8 +126,6 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
126 return __ath9k_hw_def_fill_eeprom(ah); 126 return __ath9k_hw_def_fill_eeprom(ah);
127} 127}
128 128
129#undef SIZE_EEPROM_DEF
130
131#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) 129#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
132static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, 130static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
133 struct modal_eep_header *modal_hdr) 131 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,
257} 255}
258#endif 256#endif
259 257
260
261static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) 258static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
262{ 259{
263 struct ar5416_eeprom_def *eep = &ah->eeprom.def; 260 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
264 struct ath_common *common = ath9k_hw_common(ah); 261 struct ath_common *common = ath9k_hw_common(ah);
265 u16 *eepdata, temp, magic; 262 u32 el;
266 u32 sum = 0, el; 263 bool need_swap;
267 bool need_swap = false; 264 int i, err;
268 int i, addr, size;
269
270 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
271 ath_err(common, "Reading Magic # failed\n");
272 return false;
273 }
274
275 if (swab16(magic) == AR5416_EEPROM_MAGIC &&
276 !(ah->ah_flags & AH_NO_EEP_SWAP)) {
277 size = sizeof(struct ar5416_eeprom_def);
278 need_swap = true;
279 eepdata = (u16 *) (&ah->eeprom);
280
281 for (addr = 0; addr < size / sizeof(u16); addr++) {
282 temp = swab16(*eepdata);
283 *eepdata = temp;
284 eepdata++;
285 }
286 }
287 265
288 ath_dbg(common, EEPROM, "need_swap = %s\n", 266 err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF);
289 need_swap ? "True" : "False"); 267 if (err)
268 return err;
290 269
291 if (need_swap) 270 if (need_swap)
292 el = swab16(ah->eeprom.def.baseEepHeader.length); 271 el = swab16(eep->baseEepHeader.length);
293 else 272 else
294 el = ah->eeprom.def.baseEepHeader.length; 273 el = eep->baseEepHeader.length;
295 274
296 if (el > sizeof(struct ar5416_eeprom_def)) 275 el = min(el / sizeof(u16), SIZE_EEPROM_DEF);
297 el = sizeof(struct ar5416_eeprom_def) / sizeof(u16); 276 if (!ath9k_hw_nvram_validate_checksum(ah, el))
298 else 277 return -EINVAL;
299 el = el / sizeof(u16);
300
301 eepdata = (u16 *)(&ah->eeprom);
302
303 for (i = 0; i < el; i++)
304 sum ^= *eepdata++;
305 278
306 if (need_swap) { 279 if (need_swap) {
307 u32 integer, j; 280 u32 integer, j;
308 u16 word; 281 u16 word;
309 282
310 ath_dbg(common, EEPROM,
311 "EEPROM Endianness is not native.. Changing.\n");
312
313 word = swab16(eep->baseEepHeader.length); 283 word = swab16(eep->baseEepHeader.length);
314 eep->baseEepHeader.length = word; 284 eep->baseEepHeader.length = word;
315 285
@@ -356,12 +326,9 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
356 } 326 }
357 } 327 }
358 328
359 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || 329 if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
360 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { 330 AR5416_EEP_NO_BACK_VER))
361 ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
362 sum, ah->eep_ops->get_eeprom_ver(ah));
363 return -EINVAL; 331 return -EINVAL;
364 }
365 332
366 /* Enable fixup for AR_AN_TOP2 if necessary */ 333 /* Enable fixup for AR_AN_TOP2 if necessary */
367 if ((ah->hw_version.devid == AR9280_DEVID_PCI) && 334 if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
@@ -376,6 +343,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
376 return 0; 343 return 0;
377} 344}
378 345
346#undef SIZE_EEPROM_DEF
347
379static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, 348static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
380 enum eeprom_param param) 349 enum eeprom_param param)
381{ 350{