aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
authorReinette Chatre <reinette.chatre@intel.com>2008-12-02 15:14:06 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-12-05 09:35:56 -0500
commita0987a8d68c86562f267efa97be01314c490c496 (patch)
treebd2fe7c65c61fbbb9a94c5264b0690fddbcbe6d2 /drivers/net/wireless/iwlwifi/iwl-agn.c
parentc02b3acd29766c6f79c2411cb5b85e1ee72c4c8f (diff)
iwlwifi: rely on API version read from firmware
This adds the infrastructure to support older firmware APIs. The API version number is stored as part of the filename, we first try to load the most recent firmware and progressively try lower versions. The API version is also read from the firmware self and stored as part of the iwl_priv structure. Only firmware that is supported by driver will be loaded. The version number read from firmware is compared to supported versions in the driver not the API version used as part of filename. An example using this new infrastrucure: if (IWL_UCODE_API(priv->ucode_ver) >= 2) { Driver interacts with Firmware API version >= 2. } else { Driver interacts with Firmware API version 1. } 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.c62
1 files changed, 49 insertions, 13 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 5912cdec33a..b3c263d2724 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1570,24 +1570,40 @@ static void iwl_nic_start(struct iwl_priv *priv)
1570static int iwl_read_ucode(struct iwl_priv *priv) 1570static int iwl_read_ucode(struct iwl_priv *priv)
1571{ 1571{
1572 struct iwl_ucode *ucode; 1572 struct iwl_ucode *ucode;
1573 int ret; 1573 int ret = -EINVAL, index;
1574 const struct firmware *ucode_raw; 1574 const struct firmware *ucode_raw;
1575 const char *name = priv->cfg->fw_name; 1575 const char *name_pre = priv->cfg->fw_name_pre;
1576 const unsigned int api_max = priv->cfg->ucode_api_max;
1577 const unsigned int api_min = priv->cfg->ucode_api_min;
1578 char buf[25];
1576 u8 *src; 1579 u8 *src;
1577 size_t len; 1580 size_t len;
1578 u32 inst_size, data_size, init_size, init_data_size, boot_size; 1581 u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
1579 1582
1580 /* Ask kernel firmware_class module to get the boot firmware off disk. 1583 /* Ask kernel firmware_class module to get the boot firmware off disk.
1581 * request_firmware() is synchronous, file is in memory on return. */ 1584 * request_firmware() is synchronous, file is in memory on return. */
1582 ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); 1585 for (index = api_max; index >= api_min; index--) {
1583 if (ret < 0) { 1586 sprintf(buf, "%s%d%s", name_pre, index, ".ucode");
1584 IWL_ERROR("%s firmware file req failed: Reason %d\n", 1587 ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
1585 name, ret); 1588 if (ret < 0) {
1586 goto error; 1589 IWL_ERROR("%s firmware file req failed: Reason %d\n",
1590 buf, ret);
1591 if (ret == -ENOENT)
1592 continue;
1593 else
1594 goto error;
1595 } else {
1596 if (index < api_max)
1597 IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
1598 buf, api_max);
1599 IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
1600 buf, ucode_raw->size);
1601 break;
1602 }
1587 } 1603 }
1588 1604
1589 IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n", 1605 if (ret < 0)
1590 name, ucode_raw->size); 1606 goto error;
1591 1607
1592 /* Make sure that we got at least our header! */ 1608 /* Make sure that we got at least our header! */
1593 if (ucode_raw->size < sizeof(*ucode)) { 1609 if (ucode_raw->size < sizeof(*ucode)) {
@@ -1600,19 +1616,39 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1600 ucode = (void *)ucode_raw->data; 1616 ucode = (void *)ucode_raw->data;
1601 1617
1602 priv->ucode_ver = le32_to_cpu(ucode->ver); 1618 priv->ucode_ver = le32_to_cpu(ucode->ver);
1619 api_ver = IWL_UCODE_API(priv->ucode_ver);
1603 inst_size = le32_to_cpu(ucode->inst_size); 1620 inst_size = le32_to_cpu(ucode->inst_size);
1604 data_size = le32_to_cpu(ucode->data_size); 1621 data_size = le32_to_cpu(ucode->data_size);
1605 init_size = le32_to_cpu(ucode->init_size); 1622 init_size = le32_to_cpu(ucode->init_size);
1606 init_data_size = le32_to_cpu(ucode->init_data_size); 1623 init_data_size = le32_to_cpu(ucode->init_data_size);
1607 boot_size = le32_to_cpu(ucode->boot_size); 1624 boot_size = le32_to_cpu(ucode->boot_size);
1608 1625
1609 IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n", 1626 /* api_ver should match the api version forming part of the
1610 priv->ucode_ver); 1627 * firmware filename ... but we don't check for that and only rely
1611 IWL_DEBUG_INFO("f/w package hdr ucode version = %u.%u.%u.%u\n", 1628 * on the API version read from firware header from here on forward */
1629
1630 if (api_ver < api_min || api_ver > api_max) {
1631 IWL_ERROR("Driver unable to support your firmware API. "
1632 "Driver supports v%u, firmware is v%u.\n",
1633 api_max, api_ver);
1634 priv->ucode_ver = 0;
1635 ret = -EINVAL;
1636 goto err_release;
1637 }
1638 if (api_ver != api_max)
1639 IWL_ERROR("Firmware has old API version. Expected v%u, "
1640 "got v%u. New firmware can be obtained "
1641 "from http://www.intellinuxwireless.org.\n",
1642 api_max, api_ver);
1643
1644 printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n",
1612 IWL_UCODE_MAJOR(priv->ucode_ver), 1645 IWL_UCODE_MAJOR(priv->ucode_ver),
1613 IWL_UCODE_MINOR(priv->ucode_ver), 1646 IWL_UCODE_MINOR(priv->ucode_ver),
1614 IWL_UCODE_API(priv->ucode_ver), 1647 IWL_UCODE_API(priv->ucode_ver),
1615 IWL_UCODE_SERIAL(priv->ucode_ver)); 1648 IWL_UCODE_SERIAL(priv->ucode_ver));
1649
1650 IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
1651 priv->ucode_ver);
1616 IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", 1652 IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n",
1617 inst_size); 1653 inst_size);
1618 IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", 1654 IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n",