aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/nvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/nvm.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c101
1 files changed, 67 insertions, 34 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index edb94ea31654..2beffd028b67 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -77,7 +77,7 @@ static const int nvm_to_read[] = {
77 77
78/* Default NVM size to read */ 78/* Default NVM size to read */
79#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) 79#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
80#define IWL_MAX_NVM_SECTION_SIZE 6000 80#define IWL_MAX_NVM_SECTION_SIZE 7000
81 81
82#define NVM_WRITE_OPCODE 1 82#define NVM_WRITE_OPCODE 1
83#define NVM_READ_OPCODE 0 83#define NVM_READ_OPCODE 0
@@ -259,6 +259,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
259#define MAX_NVM_FILE_LEN 16384 259#define MAX_NVM_FILE_LEN 16384
260 260
261/* 261/*
262 * Reads external NVM from a file into mvm->nvm_sections
263 *
262 * HOW TO CREATE THE NVM FILE FORMAT: 264 * HOW TO CREATE THE NVM FILE FORMAT:
263 * ------------------------------ 265 * ------------------------------
264 * 1. create hex file, format: 266 * 1. create hex file, format:
@@ -277,20 +279,23 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
277 * 279 *
278 * 4. save as "iNVM_xxx.bin" under /lib/firmware 280 * 4. save as "iNVM_xxx.bin" under /lib/firmware
279 */ 281 */
280static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm) 282static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
281{ 283{
282 int ret, section_id, section_size; 284 int ret, section_size;
285 u16 section_id;
283 const struct firmware *fw_entry; 286 const struct firmware *fw_entry;
284 const struct { 287 const struct {
285 __le16 word1; 288 __le16 word1;
286 __le16 word2; 289 __le16 word2;
287 u8 data[]; 290 u8 data[];
288 } *file_sec; 291 } *file_sec;
289 const u8 *eof; 292 const u8 *eof, *temp;
290 293
291#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) 294#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
292#define NVM_WORD2_ID(x) (x >> 12) 295#define NVM_WORD2_ID(x) (x >> 12)
293 296
297 IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
298
294 /* 299 /*
295 * Obtain NVM image via request_firmware. Since we already used 300 * Obtain NVM image via request_firmware. Since we already used
296 * request_firmware_nowait() for the firmware binary load and only 301 * request_firmware_nowait() for the firmware binary load and only
@@ -362,12 +367,18 @@ static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm)
362 break; 367 break;
363 } 368 }
364 369
365 ret = iwl_nvm_write_section(mvm, section_id, file_sec->data, 370 temp = kmemdup(file_sec->data, section_size, GFP_KERNEL);
366 section_size); 371 if (!temp) {
367 if (ret < 0) { 372 ret = -ENOMEM;
368 IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); 373 break;
374 }
375 if (WARN_ON(section_id >= NVM_NUM_OF_SECTIONS)) {
376 IWL_ERR(mvm, "Invalid NVM section ID\n");
377 ret = -EINVAL;
369 break; 378 break;
370 } 379 }
380 mvm->nvm_sections[section_id].data = temp;
381 mvm->nvm_sections[section_id].length = section_size;
371 382
372 /* advance to the next section */ 383 /* advance to the next section */
373 file_sec = (void *)(file_sec->data + section_size); 384 file_sec = (void *)(file_sec->data + section_size);
@@ -377,6 +388,28 @@ out:
377 return ret; 388 return ret;
378} 389}
379 390
391/* Loads the NVM data stored in mvm->nvm_sections into the NIC */
392int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
393{
394 int i, ret;
395 u16 section_id;
396 struct iwl_nvm_section *sections = mvm->nvm_sections;
397
398 IWL_DEBUG_EEPROM(mvm->trans->dev, "'Write to NVM\n");
399
400 for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
401 section_id = nvm_to_read[i];
402 ret = iwl_nvm_write_section(mvm, section_id,
403 sections[section_id].data,
404 sections[section_id].length);
405 if (ret < 0) {
406 IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret);
407 break;
408 }
409 }
410 return ret;
411}
412
380int iwl_nvm_init(struct iwl_mvm *mvm) 413int iwl_nvm_init(struct iwl_mvm *mvm)
381{ 414{
382 int ret, i, section; 415 int ret, i, section;
@@ -385,36 +418,36 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
385 /* load external NVM if configured */ 418 /* load external NVM if configured */
386 if (iwlwifi_mod_params.nvm_file) { 419 if (iwlwifi_mod_params.nvm_file) {
387 /* move to External NVM flow */ 420 /* move to External NVM flow */
388 ret = iwl_mvm_load_external_nvm(mvm); 421 ret = iwl_mvm_read_external_nvm(mvm);
389 if (ret) 422 if (ret)
390 return ret; 423 return ret;
391 } 424 } else {
392 425 /* Read From FW NVM */
393 /* Read From FW NVM */ 426 IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
394 IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); 427
395 428 /* TODO: find correct NVM max size for a section */
396 /* TODO: find correct NVM max size for a section */ 429 nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
397 nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, 430 GFP_KERNEL);
398 GFP_KERNEL); 431 if (!nvm_buffer)
399 if (!nvm_buffer) 432 return -ENOMEM;
400 return -ENOMEM; 433 for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
401 for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { 434 section = nvm_to_read[i];
402 section = nvm_to_read[i]; 435 /* we override the constness for initial read */
403 /* we override the constness for initial read */ 436 ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
404 ret = iwl_nvm_read_section(mvm, section, nvm_buffer); 437 if (ret < 0)
405 if (ret < 0) 438 break;
406 break; 439 temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
407 temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); 440 if (!temp) {
408 if (!temp) { 441 ret = -ENOMEM;
409 ret = -ENOMEM; 442 break;
410 break; 443 }
444 mvm->nvm_sections[section].data = temp;
445 mvm->nvm_sections[section].length = ret;
411 } 446 }
412 mvm->nvm_sections[section].data = temp; 447 kfree(nvm_buffer);
413 mvm->nvm_sections[section].length = ret; 448 if (ret < 0)
449 return ret;
414 } 450 }
415 kfree(nvm_buffer);
416 if (ret < 0)
417 return ret;
418 451
419 mvm->nvm_data = iwl_parse_nvm_sections(mvm); 452 mvm->nvm_data = iwl_parse_nvm_sections(mvm);
420 if (!mvm->nvm_data) 453 if (!mvm->nvm_data)