aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
authorJay Sternberg <jay.e.sternberg@intel.com>2009-07-17 12:30:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-24 15:05:24 -0400
commitcc0f555d511a5fe9d4519334c8f674a1dbab9e3a (patch)
tree33308c826deaf26796112df7ffb983b67146bb7f /drivers/net/wireless/iwlwifi/iwl-agn.c
parent244294e83f7637e31bbf64060301904860a32051 (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.c55
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 */
1285static int iwl_read_ucode(struct iwl_priv *priv) 1285static 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