diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 62 |
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 5912cdec33a7..b3c263d2724f 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) | |||
1570 | static int iwl_read_ucode(struct iwl_priv *priv) | 1570 | static 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", |