diff options
author | Idan Kahlon <idanx.kahlon@intel.com> | 2014-11-13 08:47:20 -0500 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-12-01 05:04:43 -0500 |
commit | a4e5df283c9a84b29100a046e64f35bfb1660a9c (patch) | |
tree | 416f101c74ae1c2331b25ea4aa2d92483beca537 | |
parent | 8ed4e659f34c963f7398ca1c92a1ab9593afba83 (diff) |
iwlwifi: mvm: support NVM file with header
Handle NVM file header. When NVM header detected, skip
the header and reading only the sections data.
Signed-off-by: Idan Kahlon <idanx.kahlon@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/nvm.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index af074563e770..d55fd8e3654c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -339,11 +339,15 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
339 | } *file_sec; | 339 | } *file_sec; |
340 | const u8 *eof, *temp; | 340 | const u8 *eof, *temp; |
341 | int max_section_size; | 341 | int max_section_size; |
342 | const __le32 *dword_buff; | ||
342 | 343 | ||
343 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) | 344 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) |
344 | #define NVM_WORD2_ID(x) (x >> 12) | 345 | #define NVM_WORD2_ID(x) (x >> 12) |
345 | #define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8)) | 346 | #define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8)) |
346 | #define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4) | 347 | #define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4) |
348 | #define NVM_HEADER_0 (0x2A504C54) | ||
349 | #define NVM_HEADER_1 (0x4E564D2A) | ||
350 | #define NVM_HEADER_SIZE (4 * sizeof(u32)) | ||
347 | 351 | ||
348 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); | 352 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); |
349 | 353 | ||
@@ -372,12 +376,6 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
372 | IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n", | 376 | IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n", |
373 | mvm->nvm_file_name, fw_entry->size); | 377 | mvm->nvm_file_name, fw_entry->size); |
374 | 378 | ||
375 | if (fw_entry->size < sizeof(*file_sec)) { | ||
376 | IWL_ERR(mvm, "NVM file too small\n"); | ||
377 | ret = -EINVAL; | ||
378 | goto out; | ||
379 | } | ||
380 | |||
381 | if (fw_entry->size > MAX_NVM_FILE_LEN) { | 379 | if (fw_entry->size > MAX_NVM_FILE_LEN) { |
382 | IWL_ERR(mvm, "NVM file too large\n"); | 380 | IWL_ERR(mvm, "NVM file too large\n"); |
383 | ret = -EINVAL; | 381 | ret = -EINVAL; |
@@ -385,8 +383,25 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
385 | } | 383 | } |
386 | 384 | ||
387 | eof = fw_entry->data + fw_entry->size; | 385 | eof = fw_entry->data + fw_entry->size; |
388 | 386 | dword_buff = (__le32 *)fw_entry->data; | |
389 | file_sec = (void *)fw_entry->data; | 387 | |
388 | /* some NVM file will contain a header. | ||
389 | * The header is identified by 2 dwords header as follow: | ||
390 | * dword[0] = 0x2A504C54 | ||
391 | * dword[1] = 0x4E564D2A | ||
392 | * | ||
393 | * This header must be skipped when providing the NVM data to the FW. | ||
394 | */ | ||
395 | if (fw_entry->size > NVM_HEADER_SIZE && | ||
396 | dword_buff[0] == cpu_to_le32(NVM_HEADER_0) && | ||
397 | dword_buff[1] == cpu_to_le32(NVM_HEADER_1)) { | ||
398 | file_sec = (void *)(fw_entry->data + NVM_HEADER_SIZE); | ||
399 | IWL_INFO(mvm, "NVM Version %08X\n", le32_to_cpu(dword_buff[2])); | ||
400 | IWL_INFO(mvm, "NVM Manufacturing date %08X\n", | ||
401 | le32_to_cpu(dword_buff[3])); | ||
402 | } else { | ||
403 | file_sec = (void *)fw_entry->data; | ||
404 | } | ||
390 | 405 | ||
391 | while (true) { | 406 | while (true) { |
392 | if (file_sec->data > eof) { | 407 | if (file_sec->data > eof) { |