aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2010-01-29 14:54:56 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-03-02 14:31:51 -0500
commitb08dfd0435333818a03b38867c556ebcbb3abc02 (patch)
tree578ce4b1dead6f1c605d252955eae26d09d6fabc
parent535765179fd4e8af26b69d2240d7ec33702a370a (diff)
iwlwifi: load firmware asynchronously before mac80211 registration
At the wireless summit in Portland we discussed a way of loading firmware asynchronously from ->probe() before registration to mac80211, in order to register with the wireless subsystems with complete information in cases where firmware is required to know parameters. This is not yet the case in iwlwifi, but for some new features we're working on it will be the case since those will only be supported by new firmware images. Hence, to start with, convert iwlwifi to load firmware asynchronously from probe, unbinding the device when firmware loading fails, and only registering with the wireless subsystems after firmware has been loaded successfully. Future patches will hook into this to register the new firmware capabilities, depending on the firmware API version. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c157
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
2 files changed, 81 insertions, 78 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 6aeb82b6992f..47b021477967 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1463,59 +1463,66 @@ static void iwl_nic_start(struct iwl_priv *priv)
1463} 1463}
1464 1464
1465 1465
1466static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
1467static int iwl_mac_setup_register(struct iwl_priv *priv);
1468
1469static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
1470{
1471 const char *name_pre = priv->cfg->fw_name_pre;
1472
1473 if (first)
1474 priv->fw_index = priv->cfg->ucode_api_max;
1475 else
1476 priv->fw_index--;
1477
1478 if (priv->fw_index < priv->cfg->ucode_api_min) {
1479 IWL_ERR(priv, "no suitable firmware found!\n");
1480 return -ENOENT;
1481 }
1482
1483 sprintf(priv->firmware_name, "%s%d%s",
1484 name_pre, priv->fw_index, ".ucode");
1485
1486 IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n",
1487 priv->firmware_name);
1488
1489 return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
1490 &priv->pci_dev->dev, GFP_KERNEL, priv,
1491 iwl_ucode_callback);
1492}
1493
1466/** 1494/**
1467 * iwl_read_ucode - Read uCode images from disk file. 1495 * iwl_ucode_callback - callback when firmware was loaded
1468 * 1496 *
1469 * Copy into buffers for card to fetch via bus-mastering 1497 * If loaded successfully, copies the firmware into buffers
1498 * for the card to fetch (via DMA).
1470 */ 1499 */
1471static int iwl_read_ucode(struct iwl_priv *priv) 1500static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1472{ 1501{
1502 struct iwl_priv *priv = context;
1473 struct iwl_ucode_header *ucode; 1503 struct iwl_ucode_header *ucode;
1474 int ret = -EINVAL, index;
1475 const struct firmware *ucode_raw;
1476 const char *name_pre = priv->cfg->fw_name_pre;
1477 const unsigned int api_max = priv->cfg->ucode_api_max; 1504 const unsigned int api_max = priv->cfg->ucode_api_max;
1478 const unsigned int api_min = priv->cfg->ucode_api_min; 1505 const unsigned int api_min = priv->cfg->ucode_api_min;
1479 char buf[25];
1480 u8 *src; 1506 u8 *src;
1481 size_t len; 1507 size_t len;
1482 u32 api_ver, build; 1508 u32 api_ver, build;
1483 u32 inst_size, data_size, init_size, init_data_size, boot_size; 1509 u32 inst_size, data_size, init_size, init_data_size, boot_size;
1510 int err;
1484 u16 eeprom_ver; 1511 u16 eeprom_ver;
1485 1512
1486 /* Ask kernel firmware_class module to get the boot firmware off disk. 1513 if (!ucode_raw) {
1487 * request_firmware() is synchronous, file is in memory on return. */ 1514 IWL_ERR(priv, "request for firmware file '%s' failed.\n",
1488 for (index = api_max; index >= api_min; index--) { 1515 priv->firmware_name);
1489 sprintf(buf, "%s%d%s", name_pre, index, ".ucode"); 1516 goto try_again;
1490 ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
1491 if (ret < 0) {
1492 IWL_ERR(priv, "%s firmware file req failed: %d\n",
1493 buf, ret);
1494 if (ret == -ENOENT)
1495 continue;
1496 else
1497 goto error;
1498 } else {
1499 if (index < api_max)
1500 IWL_ERR(priv, "Loaded firmware %s, "
1501 "which is deprecated. "
1502 "Please use API v%u instead.\n",
1503 buf, api_max);
1504
1505 IWL_DEBUG_INFO(priv, "Got firmware '%s' file (%zd bytes) from disk\n",
1506 buf, ucode_raw->size);
1507 break;
1508 }
1509 } 1517 }
1510 1518
1511 if (ret < 0) 1519 IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
1512 goto error; 1520 priv->firmware_name, ucode_raw->size);
1513 1521
1514 /* Make sure that we got at least the v1 header! */ 1522 /* Make sure that we got at least the v1 header! */
1515 if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { 1523 if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
1516 IWL_ERR(priv, "File size way too small!\n"); 1524 IWL_ERR(priv, "File size way too small!\n");
1517 ret = -EINVAL; 1525 goto try_again;
1518 goto err_release;
1519 } 1526 }
1520 1527
1521 /* Data from ucode file: header followed by uCode images */ 1528 /* Data from ucode file: header followed by uCode images */
@@ -1540,10 +1547,9 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1540 IWL_ERR(priv, "Driver unable to support your firmware API. " 1547 IWL_ERR(priv, "Driver unable to support your firmware API. "
1541 "Driver supports v%u, firmware is v%u.\n", 1548 "Driver supports v%u, firmware is v%u.\n",
1542 api_max, api_ver); 1549 api_max, api_ver);
1543 priv->ucode_ver = 0; 1550 goto try_again;
1544 ret = -EINVAL;
1545 goto err_release;
1546 } 1551 }
1552
1547 if (api_ver != api_max) 1553 if (api_ver != api_max)
1548 IWL_ERR(priv, "Firmware has old API version. Expected v%u, " 1554 IWL_ERR(priv, "Firmware has old API version. Expected v%u, "
1549 "got v%u. New firmware can be obtained " 1555 "got v%u. New firmware can be obtained "
@@ -1585,6 +1591,12 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1585 IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", 1591 IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n",
1586 boot_size); 1592 boot_size);
1587 1593
1594 /*
1595 * For any of the failures below (before allocating pci memory)
1596 * we will try to load a version with a smaller API -- maybe the
1597 * user just got a corrupted version of the latest API.
1598 */
1599
1588 /* Verify size of file vs. image size info in file's header */ 1600 /* Verify size of file vs. image size info in file's header */
1589 if (ucode_raw->size != 1601 if (ucode_raw->size !=
1590 priv->cfg->ops->ucode->get_header_size(api_ver) + 1602 priv->cfg->ops->ucode->get_header_size(api_ver) +
@@ -1594,41 +1606,35 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1594 IWL_DEBUG_INFO(priv, 1606 IWL_DEBUG_INFO(priv,
1595 "uCode file size %d does not match expected size\n", 1607 "uCode file size %d does not match expected size\n",
1596 (int)ucode_raw->size); 1608 (int)ucode_raw->size);
1597 ret = -EINVAL; 1609 goto try_again;
1598 goto err_release;
1599 } 1610 }
1600 1611
1601 /* Verify that uCode images will fit in card's SRAM */ 1612 /* Verify that uCode images will fit in card's SRAM */
1602 if (inst_size > priv->hw_params.max_inst_size) { 1613 if (inst_size > priv->hw_params.max_inst_size) {
1603 IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", 1614 IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
1604 inst_size); 1615 inst_size);
1605 ret = -EINVAL; 1616 goto try_again;
1606 goto err_release;
1607 } 1617 }
1608 1618
1609 if (data_size > priv->hw_params.max_data_size) { 1619 if (data_size > priv->hw_params.max_data_size) {
1610 IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", 1620 IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
1611 data_size);