diff options
author | Jay Sternberg <jay.e.sternberg@intel.com> | 2009-07-17 12:30:16 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:24 -0400 |
commit | cc0f555d511a5fe9d4519334c8f674a1dbab9e3a (patch) | |
tree | 33308c826deaf26796112df7ffb983b67146bb7f /drivers/net/wireless/iwlwifi/iwl-agn.c | |
parent | 244294e83f7637e31bbf64060301904860a32051 (diff) |
iwlwifi: Handle new firmware file with ucode build number in header
Adding new API version to account for change to ucode file format. New
header includes the build number of the ucode. This build number is the
SVN revision thus allowing for exact correlation to the code that
generated it.
The header adds the build number so that older ucode images can also be
enhanced to include the build in the future.
some cleanup in iwl_read_ucode needed to ensure old header not used and
reduce unnecessary references through pointer with the data is already
in heap variable.
Signed-off-by: Jay Sternberg <jay.e.sternberg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ad5002211ab4..6b874dab4120 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1284,7 +1284,7 @@ static void iwl_nic_start(struct iwl_priv *priv) | |||
1284 | */ | 1284 | */ |
1285 | static int iwl_read_ucode(struct iwl_priv *priv) | 1285 | static int iwl_read_ucode(struct iwl_priv *priv) |
1286 | { | 1286 | { |
1287 | struct iwl_ucode *ucode; | 1287 | struct iwl_ucode_header *ucode; |
1288 | int ret = -EINVAL, index; | 1288 | int ret = -EINVAL, index; |
1289 | const struct firmware *ucode_raw; | 1289 | const struct firmware *ucode_raw; |
1290 | const char *name_pre = priv->cfg->fw_name_pre; | 1290 | const char *name_pre = priv->cfg->fw_name_pre; |
@@ -1293,7 +1293,8 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1293 | char buf[25]; | 1293 | char buf[25]; |
1294 | u8 *src; | 1294 | u8 *src; |
1295 | size_t len; | 1295 | size_t len; |
1296 | u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size; | 1296 | u32 api_ver, build; |
1297 | u32 inst_size, data_size, init_size, init_data_size, boot_size; | ||
1297 | 1298 | ||
1298 | /* Ask kernel firmware_class module to get the boot firmware off disk. | 1299 | /* Ask kernel firmware_class module to get the boot firmware off disk. |
1299 | * request_firmware() is synchronous, file is in memory on return. */ | 1300 | * request_firmware() is synchronous, file is in memory on return. */ |
@@ -1323,23 +1324,26 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1323 | if (ret < 0) | 1324 | if (ret < 0) |
1324 | goto error; | 1325 | goto error; |
1325 | 1326 | ||
1326 | /* Make sure that we got at least our header! */ | 1327 | /* Make sure that we got at least the v1 header! */ |
1327 | if (ucode_raw->size < sizeof(*ucode)) { | 1328 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { |
1328 | IWL_ERR(priv, "File size way too small!\n"); | 1329 | IWL_ERR(priv, "File size way too small!\n"); |
1329 | ret = -EINVAL; | 1330 | ret = -EINVAL; |
1330 | goto err_release; | 1331 | goto err_release; |
1331 | } | 1332 | } |
1332 | 1333 | ||
1333 | /* Data from ucode file: header followed by uCode images */ | 1334 | /* Data from ucode file: header followed by uCode images */ |
1334 | ucode = (void *)ucode_raw->data; | 1335 | ucode = (struct iwl_ucode_header *)ucode_raw->data; |
1335 | 1336 | ||
1336 | priv->ucode_ver = le32_to_cpu(ucode->ver); | 1337 | priv->ucode_ver = le32_to_cpu(ucode->ver); |
1337 | api_ver = IWL_UCODE_API(priv->ucode_ver); | 1338 | api_ver = IWL_UCODE_API(priv->ucode_ver); |
1338 | inst_size = le32_to_cpu(ucode->inst_size); | 1339 | build = priv->cfg->ops->ucode->get_build(ucode, api_ver); |
1339 | data_size = le32_to_cpu(ucode->data_size); | 1340 | inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); |
1340 | init_size = le32_to_cpu(ucode->init_size); | 1341 | data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); |
1341 | init_data_size = le32_to_cpu(ucode->init_data_size); | 1342 | init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); |
1342 | boot_size = le32_to_cpu(ucode->boot_size); | 1343 | init_data_size = |
1344 | priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); | ||
1345 | boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); | ||
1346 | src = priv->cfg->ops->ucode->get_data(ucode, api_ver); | ||
1343 | 1347 | ||
1344 | /* api_ver should match the api version forming part of the | 1348 | /* api_ver should match the api version forming part of the |
1345 | * firmware filename ... but we don't check for that and only rely | 1349 | * firmware filename ... but we don't check for that and only rely |
@@ -1365,6 +1369,9 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1365 | IWL_UCODE_API(priv->ucode_ver), | 1369 | IWL_UCODE_API(priv->ucode_ver), |
1366 | IWL_UCODE_SERIAL(priv->ucode_ver)); | 1370 | IWL_UCODE_SERIAL(priv->ucode_ver)); |
1367 | 1371 | ||
1372 | if (build) | ||
1373 | IWL_DEBUG_INFO(priv, "Build %u\n", build); | ||
1374 | |||
1368 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | 1375 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", |
1369 | priv->ucode_ver); | 1376 | priv->ucode_ver); |
1370 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", | 1377 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", |
@@ -1379,12 +1386,14 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1379 | boot_size); | 1386 | boot_size); |
1380 | 1387 | ||
1381 | /* Verify size of file vs. image size info in file's header */ | 1388 | /* Verify size of file vs. image size info in file's header */ |
1382 | if (ucode_raw->size < sizeof(*ucode) + | 1389 | if (ucode_raw->size != |
1390 | priv->cfg->ops->ucode->get_header_size(api_ver) + | ||
1383 | inst_size + data_size + init_size + | 1391 | inst_size + data_size + init_size + |
1384 | init_data_size + boot_size) { | 1392 | init_data_size + boot_size) { |
1385 | 1393 | ||
1386 | IWL_DEBUG_INFO(priv, "uCode file size %d too small\n", | 1394 | IWL_DEBUG_INFO(priv, |
1387 | (int)ucode_raw->size); | 1395 | "uCode file size %d does not match expected size\n", |
1396 | (int)ucode_raw->size); | ||
1388 | ret = -EINVAL; | 1397 | ret = -EINVAL; |
1389 | goto err_release; | 1398 | goto err_release; |
1390 | } | 1399 | } |
@@ -1464,42 +1473,42 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1464 | /* Copy images into buffers for card's bus-master reads ... */ | 1473 | /* Copy images into buffers for card's bus-master reads ... */ |
1465 | 1474 | ||
1466 | /* Runtime instructions (first block of data in file) */ | 1475 | /* Runtime instructions (first block of data in file) */ |
1467 | src = &ucode->data[0]; | 1476 | len = inst_size; |
1468 | len = priv->ucode_code.len; | ||
1469 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); | 1477 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); |
1470 | memcpy(priv->ucode_code.v_addr, src, len); | 1478 | memcpy(priv->ucode_code.v_addr, src, len); |
1479 | src += len; | ||
1480 | |||
1471 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", | 1481 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", |
1472 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); | 1482 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); |
1473 | 1483 | ||
1474 | /* Runtime data (2nd block) | 1484 | /* Runtime data (2nd block) |
1475 | * NOTE: Copy into backup buffer will be done in iwl_up() */ | 1485 | * NOTE: Copy into backup buffer will be done in iwl_up() */ |
1476 | src = &ucode->data[inst_size]; | 1486 | len = data_size; |
1477 | len = priv->ucode_data.len; | ||
1478 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); | 1487 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); |
1479 | memcpy(priv->ucode_data.v_addr, src, len); | 1488 | memcpy(priv->ucode_data.v_addr, src, len); |
1480 | memcpy(priv->ucode_data_backup.v_addr, src, len); | 1489 | memcpy(priv->ucode_data_backup.v_addr, src, len); |
1490 | src += len; | ||
1481 | 1491 | ||
1482 | /* Initialization instructions (3rd block) */ | 1492 | /* Initialization instructions (3rd block) */ |
1483 | if (init_size) { | 1493 | if (init_size) { |
1484 | src = &ucode->data[inst_size + data_size]; | 1494 | len = init_size; |
1485 | len = priv->ucode_init.len; | ||
1486 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", | 1495 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", |
1487 | len); | 1496 | len); |
1488 | memcpy(priv->ucode_init.v_addr, src, len); | 1497 | memcpy(priv->ucode_init.v_addr, src, len); |
1498 | src += len; | ||
1489 | } | 1499 | } |
1490 | 1500 | ||
1491 | /* Initialization data (4th block) */ | 1501 | /* Initialization data (4th block) */ |
1492 | if (init_data_size) { | 1502 | if (init_data_size) { |
1493 | src = &ucode->data[inst_size + data_size + init_size]; | 1503 | len = init_data_size; |
1494 | len = priv->ucode_init_data.len; | ||
1495 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", | 1504 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", |
1496 | len); | 1505 | len); |
1497 | memcpy(priv->ucode_init_data.v_addr, src, len); | 1506 | memcpy(priv->ucode_init_data.v_addr, src, len); |
1507 | src += len; | ||
1498 | } | 1508 | } |
1499 | 1509 | ||
1500 | /* Bootstrap instructions (5th block) */ | 1510 | /* Bootstrap instructions (5th block) */ |
1501 | src = &ucode->data[inst_size + data_size + init_size + init_data_size]; | 1511 | len = boot_size; |
1502 | len = priv->ucode_boot.len; | ||
1503 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); | 1512 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); |
1504 | memcpy(priv->ucode_boot.v_addr, src, len); | 1513 | memcpy(priv->ucode_boot.v_addr, src, len); |
1505 | 1514 | ||