aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
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
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')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-core.h26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c46
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c62
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c64
8 files changed, 217 insertions, 56 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-core.h b/drivers/net/wireless/iwlwifi/iwl-3945-core.h
index bc12f97ba0b1..edac6c6a9110 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-core.h
@@ -71,9 +71,33 @@
71#define IWL_SKU_G 0x1 71#define IWL_SKU_G 0x1
72#define IWL_SKU_A 0x2 72#define IWL_SKU_A 0x2
73 73
74/**
75 * struct iwl_3945_cfg
76 * @fw_name_pre: Firmware filename prefix. The api version and extension
77 * (.ucode) will be added to filename before loading from disk. The
78 * filename is constructed as fw_name_pre<api>.ucode.
79 * @ucode_api_max: Highest version of uCode API supported by driver.
80 * @ucode_api_min: Lowest version of uCode API supported by driver.
81 *
82 * We enable the driver to be backward compatible wrt API version. The
83 * driver specifies which APIs it supports (with @ucode_api_max being the
84 * highest and @ucode_api_min the lowest). Firmware will only be loaded if
85 * it has a supported API version. The firmware's API version will be
86 * stored in @iwl_priv, enabling the driver to make runtime changes based
87 * on firmware version used.
88 *
89 * For example,
90 * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
91 * Driver interacts with Firmware API version >= 2.
92 * } else {
93 * Driver interacts with Firmware API version 1.
94 * }
95 */
74struct iwl_3945_cfg { 96struct iwl_3945_cfg {
75 const char *name; 97 const char *name;
76 const char *fw_name; 98 const char *fw_name_pre;
99 const unsigned int ucode_api_max;
100 const unsigned int ucode_api_min;
77 unsigned int sku; 101 unsigned int sku;
78}; 102};
79 103
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index d95a15fc2602..4e6b7154c223 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2508,13 +2508,17 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)
2508 2508
2509static struct iwl_3945_cfg iwl3945_bg_cfg = { 2509static struct iwl_3945_cfg iwl3945_bg_cfg = {
2510 .name = "3945BG", 2510 .name = "3945BG",
2511 .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode", 2511 .fw_name_pre = IWL3945_FW_PRE,
2512 .ucode_api_max = IWL3945_UCODE_API_MAX,
2513 .ucode_api_min = IWL3945_UCODE_API_MIN,
2512 .sku = IWL_SKU_G, 2514 .sku = IWL_SKU_G,
2513}; 2515};
2514 2516
2515static struct iwl_3945_cfg iwl3945_abg_cfg = { 2517static struct iwl_3945_cfg iwl3945_abg_cfg = {
2516 .name = "3945ABG", 2518 .name = "3945ABG",
2517 .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode", 2519 .fw_name_pre = IWL3945_FW_PRE,
2520 .ucode_api_max = IWL3945_UCODE_API_MAX,
2521 .ucode_api_min = IWL3945_UCODE_API_MIN,
2518 .sku = IWL_SKU_A|IWL_SKU_G, 2522 .sku = IWL_SKU_A|IWL_SKU_G,
2519}; 2523};
2520 2524
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 972c4542e5bc..d6502b426a06 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -50,11 +50,15 @@ extern struct pci_device_id iwl3945_hw_card_ids[];
50#include "iwl-3945-debug.h" 50#include "iwl-3945-debug.h"
51#include "iwl-3945-led.h" 51#include "iwl-3945-led.h"
52 52
53/* Change firmware file name, using "-" and incrementing number, 53/* Highest firmware API version supported */
54 * *only* when uCode interface or architecture changes so that it 54#define IWL3945_UCODE_API_MAX 1
55 * is not compatible with earlier drivers. 55
56 * This number will also appear in << 8 position of 1st dword of uCode file */ 56/* Lowest firmware API version supported */
57#define IWL3945_UCODE_API "-1" 57#define IWL3945_UCODE_API_MIN 1
58
59#define IWL3945_FW_PRE "iwlwifi-3945-"
60#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode"
61#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api)
58 62
59/* Default noise level to report when noise measurement is not available. 63/* Default noise level to report when noise measurement is not available.
60 * This may be because we're: 64 * This may be because we're:
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 93d3df87fdaa..87c7bb0d5044 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -48,12 +48,15 @@
48static int iwl4965_send_tx_power(struct iwl_priv *priv); 48static int iwl4965_send_tx_power(struct iwl_priv *priv);
49static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); 49static int iwl4965_hw_get_temperature(const struct iwl_priv *priv);
50 50
51/* Change firmware file name, using "-" and incrementing number, 51/* Highest firmware API version supported */
52 * *only* when uCode interface or architecture changes so that it 52#define IWL4965_UCODE_API_MAX 2
53 * is not compatible with earlier drivers. 53
54 * This number will also appear in << 8 position of 1st dword of uCode file */ 54/* Lowest firmware API version supported */
55#define IWL4965_UCODE_API "-2" 55#define IWL4965_UCODE_API_MIN 2
56#define IWL4965_MODULE_FIRMWARE "iwlwifi-4965" IWL4965_UCODE_API ".ucode" 56
57#define IWL4965_FW_PRE "iwlwifi-4965-"
58#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode"
59#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
57 60
58 61
59/* module parameters */ 62/* module parameters */
@@ -2336,7 +2339,9 @@ static struct iwl_ops iwl4965_ops = {
2336 2339
2337struct iwl_cfg iwl4965_agn_cfg = { 2340struct iwl_cfg iwl4965_agn_cfg = {
2338 .name = "4965AGN", 2341 .name = "4965AGN",
2339 .fw_name = IWL4965_MODULE_FIRMWARE, 2342 .fw_name_pre = IWL4965_FW_PRE,
2343 .ucode_api_max = IWL4965_UCODE_API_MAX,
2344 .ucode_api_min = IWL4965_UCODE_API_MIN,
2340 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, 2345 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
2341 .eeprom_size = IWL4965_EEPROM_IMG_SIZE, 2346 .eeprom_size = IWL4965_EEPROM_IMG_SIZE,
2342 .eeprom_ver = EEPROM_4965_EEPROM_VERSION, 2347 .eeprom_ver = EEPROM_4965_EEPROM_VERSION,
@@ -2346,7 +2351,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
2346}; 2351};
2347 2352
2348/* Module firmware */ 2353/* Module firmware */
2349MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE); 2354MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
2350 2355
2351module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); 2356module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
2352MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); 2357MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index f7a8df8dcaa7..438e4bd0a9a8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -44,11 +44,21 @@
44#include "iwl-helpers.h" 44#include "iwl-helpers.h"
45#include "iwl-5000-hw.h" 45#include "iwl-5000-hw.h"
46 46
47#define IWL5000_UCODE_API "-1" 47/* Highest firmware API version supported */
48#define IWL5150_UCODE_API "-1" 48#define IWL5000_UCODE_API_MAX 1
49#define IWL5150_UCODE_API_MAX 1
49 50
50#define IWL5000_MODULE_FIRMWARE "iwlwifi-5000" IWL5000_UCODE_API ".ucode" 51/* Lowest firmware API version supported */
51#define IWL5150_MODULE_FIRMWARE "iwlwifi-5150" IWL5150_UCODE_API ".ucode" 52#define IWL5000_UCODE_API_MIN 1
53#define IWL5150_UCODE_API_MIN 1
54
55#define IWL5000_FW_PRE "iwlwifi-5000-"
56#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
57#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api)
58
59#define IWL5150_FW_PRE "iwlwifi-5150-"
60#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
61#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api)
52 62
53static const u16 iwl5000_default_queue_to_tx_fifo[] = { 63static const u16 iwl5000_default_queue_to_tx_fifo[] = {
54 IWL_TX_FIFO_AC3, 64 IWL_TX_FIFO_AC3,
@@ -1532,7 +1542,9 @@ static struct iwl_mod_params iwl50_mod_params = {
1532 1542
1533struct iwl_cfg iwl5300_agn_cfg = { 1543struct iwl_cfg iwl5300_agn_cfg = {
1534 .name = "5300AGN", 1544 .name = "5300AGN",
1535 .fw_name = IWL5000_MODULE_FIRMWARE, 1545 .fw_name_pre = IWL5000_FW_PRE,
1546 .ucode_api_max = IWL5000_UCODE_API_MAX,
1547 .ucode_api_min = IWL5000_UCODE_API_MIN,
1536 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, 1548 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1537 .ops = &iwl5000_ops, 1549 .ops = &iwl5000_ops,
1538 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, 1550 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1543,7 +1555,9 @@ struct iwl_cfg iwl5300_agn_cfg = {
1543 1555
1544struct iwl_cfg iwl5100_bg_cfg = { 1556struct iwl_cfg iwl5100_bg_cfg = {
1545 .name = "5100BG", 1557 .name = "5100BG",
1546 .fw_name = IWL5000_MODULE_FIRMWARE, 1558 .fw_name_pre = IWL5000_FW_PRE,
1559 .ucode_api_max = IWL5000_UCODE_API_MAX,
1560 .ucode_api_min = IWL5000_UCODE_API_MIN,
1547 .sku = IWL_SKU_G, 1561 .sku = IWL_SKU_G,
1548 .ops = &iwl5000_ops, 1562 .ops = &iwl5000_ops,
1549 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, 1563 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1554,7 +1568,9 @@ struct iwl_cfg iwl5100_bg_cfg = {
1554 1568
1555struct iwl_cfg iwl5100_abg_cfg = { 1569struct iwl_cfg iwl5100_abg_cfg = {
1556 .name = "5100ABG", 1570 .name = "5100ABG",
1557 .fw_name = IWL5000_MODULE_FIRMWARE, 1571 .fw_name_pre = IWL5000_FW_PRE,
1572 .ucode_api_max = IWL5000_UCODE_API_MAX,
1573 .ucode_api_min = IWL5000_UCODE_API_MIN,
1558 .sku = IWL_SKU_A|IWL_SKU_G, 1574 .sku = IWL_SKU_A|IWL_SKU_G,
1559 .ops = &iwl5000_ops, 1575 .ops = &iwl5000_ops,
1560 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, 1576 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1565,7 +1581,9 @@ struct iwl_cfg iwl5100_abg_cfg = {
1565 1581
1566struct iwl_cfg iwl5100_agn_cfg = { 1582struct iwl_cfg iwl5100_agn_cfg = {
1567 .name = "5100AGN", 1583 .name = "5100AGN",
1568 .fw_name = IWL5000_MODULE_FIRMWARE, 1584 .fw_name_pre = IWL5000_FW_PRE,
1585 .ucode_api_max = IWL5000_UCODE_API_MAX,
1586 .ucode_api_min = IWL5000_UCODE_API_MIN,
1569 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, 1587 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1570 .ops = &iwl5000_ops, 1588 .ops = &iwl5000_ops,
1571 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, 1589 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1576,7 +1594,9 @@ struct iwl_cfg iwl5100_agn_cfg = {
1576 1594
1577struct iwl_cfg iwl5350_agn_cfg = { 1595struct iwl_cfg iwl5350_agn_cfg = {
1578 .name = "5350AGN", 1596 .name = "5350AGN",
1579 .fw_name = IWL5000_MODULE_FIRMWARE, 1597 .fw_name_pre = IWL5000_FW_PRE,
1598 .ucode_api_max = IWL5000_UCODE_API_MAX,
1599 .ucode_api_min = IWL5000_UCODE_API_MIN,
1580 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, 1600 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1581 .ops = &iwl5000_ops, 1601 .ops = &iwl5000_ops,
1582 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, 1602 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1587,7 +1607,9 @@ struct iwl_cfg iwl5350_agn_cfg = {
1587 1607
1588struct iwl_cfg iwl5150_agn_cfg = { 1608struct iwl_cfg iwl5150_agn_cfg = {
1589 .name = "5150AGN", 1609 .name = "5150AGN",
1590 .fw_name = IWL5150_MODULE_FIRMWARE, 1610 .fw_name_pre = IWL5150_FW_PRE,
1611 .ucode_api_max = IWL5150_UCODE_API_MAX,
1612 .ucode_api_min = IWL5150_UCODE_API_MIN,
1591 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, 1613 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1592 .ops = &iwl5000_ops, 1614 .ops = &iwl5000_ops,
1593 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, 1615 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1596,8 +1618,8 @@ struct iwl_cfg iwl5150_agn_cfg = {
1596 .mod_params = &iwl50_mod_params, 1618 .mod_params = &iwl50_mod_params,
1597}; 1619};
1598 1620
1599MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE); 1621MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
1600MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE); 1622MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
1601 1623
1602module_param_named(disable50, iwl50_mod_params.disable, int, 0444); 1624module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
1603MODULE_PARM_DESC(disable50, 1625MODULE_PARM_DESC(disable50,
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)
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",
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index f68883b3246e..81ddca077175 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -164,9 +164,39 @@ struct iwl_mod_params {
164 int restart_fw; /* def: 1 = restart firmware */ 164 int restart_fw; /* def: 1 = restart firmware */
165}; 165};
166 166
167/**
168 * struct iwl_cfg
169 * @fw_name_pre: Firmware filename prefix. The api version and extension
170 * (.ucode) will be added to filename before loading from disk. The
171 * filename is constructed as fw_name_pre<api>.ucode.
172 * @ucode_api_max: Highest version of uCode API supported by driver.
173 * @ucode_api_min: Lowest version of uCode API supported by driver.
174 *
175 * We enable the driver to be backward compatible wrt API version. The
176 * driver specifies which APIs it supports (with @ucode_api_max being the
177 * highest and @ucode_api_min the lowest). Firmware will only be loaded if
178 * it has a supported API version. The firmware's API version will be
179 * stored in @iwl_priv, enabling the driver to make runtime changes based
180 * on firmware version used.
181 *
182 * For example,
183 * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
184 * Driver interacts with Firmware API version >= 2.
185 * } else {
186 * Driver interacts with Firmware API version 1.
187 * }
188 *
189 * The ideal usage of this infrastructure is to treat a new ucode API
190 * release as a new hardware revision. That is, through utilizing the
191 * iwl_hcmd_utils_ops etc. we accommodate different command structures
192 * and flows between hardware versions (4965/5000) as well as their API
193 * versions.
194 */
167struct iwl_cfg { 195struct iwl_cfg {
168 const char *name; 196 const char *name;
169 const char *fw_name; 197 const char *fw_name_pre;
198 const unsigned int ucode_api_max;
199 const unsigned int ucode_api_min;
170 unsigned int sku; 200 unsigned int sku;
171 int eeprom_size; 201 int eeprom_size;
172 u16 eeprom_ver; 202 u16 eeprom_ver;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 03ff87fbe924..1d3efa9d01b4 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5296,25 +5296,41 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv)
5296static int iwl3945_read_ucode(struct iwl3945_priv *priv) 5296static int iwl3945_read_ucode(struct iwl3945_priv *priv)
5297{ 5297{
5298 struct iwl3945_ucode *ucode; 5298 struct iwl3945_ucode *ucode;
5299 int ret = 0; 5299 int ret = -EINVAL, index;
5300 const struct firmware *ucode_raw; 5300 const struct firmware *ucode_raw;
5301 /* firmware file name contains uCode/driver compatibility version */ 5301 /* firmware file name contains uCode/driver compatibility version */
5302 const char *name = priv->cfg->fw_name; 5302 const char *name_pre = priv->cfg->fw_name_pre;
5303 const unsigned int api_max = priv->cfg->ucode_api_max;
5304 const unsigned int api_min = priv->cfg->ucode_api_min;
5305 char buf[25];
5303 u8 *src; 5306 u8 *src;
5304 size_t len; 5307 size_t len;
5305 u32 inst_size, data_size, init_size, init_data_size, boot_size; 5308 u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
5306 5309
5307 /* Ask kernel firmware_class module to get the boot firmware off disk. 5310 /* Ask kernel firmware_class module to get the boot firmware off disk.
5308 * request_firmware() is synchronous, file is in memory on return. */ 5311 * request_firmware() is synchronous, file is in memory on return. */
5309 ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); 5312 for (index = api_max; index >= api_min; index--) {
5310 if (ret < 0) { 5313 sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
5311 IWL_ERROR("%s firmware file req failed: Reason %d\n", 5314 ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
5312 name, ret); 5315 if (ret < 0) {
5313 goto error; 5316 IWL_ERROR("%s firmware file req failed: Reason %d\n",
5317 buf, ret);
5318 if (ret == -ENOENT)
5319 continue;
5320 else
5321 goto error;
5322 } else {
5323 if (index < api_max)
5324 IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
5325 buf, api_max);
5326 IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
5327 buf, ucode_raw->size);
5328 break;
5329 }
5314 } 5330 }
5315 5331
5316 IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n", 5332 if (ret < 0)
5317 name, ucode_raw->size); 5333 goto error;
5318 5334
5319 /* Make sure that we got at least our header! */ 5335 /* Make sure that we got at least our header! */
5320 if (ucode_raw->size < sizeof(*ucode)) { 5336 if (ucode_raw->size < sizeof(*ucode)) {
@@ -5327,25 +5343,45 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
5327 ucode = (void *)ucode_raw->data; 5343 ucode = (void *)ucode_raw->data;
5328 5344
5329 priv->ucode_ver = le32_to_cpu(ucode->ver); 5345 priv->ucode_ver = le32_to_cpu(ucode->ver);
5346 api_ver = IWL_UCODE_API(priv->ucode_ver);
5330 inst_size = le32_to_cpu(ucode->inst_size); 5347 inst_size = le32_to_cpu(ucode->inst_size);
5331 data_size = le32_to_cpu(ucode->data_size); 5348 data_size = le32_to_cpu(ucode->data_size);
5332 init_size = le32_to_cpu(ucode->init_size); 5349 init_size = le32_to_cpu(ucode->init_size);
5333 init_data_size = le32_to_cpu(ucode->init_data_size); 5350 init_data_size = le32_to_cpu(ucode->init_data_size);
5334 boot_size = le32_to_cpu(ucode->boot_size); 5351 boot_size = le32_to_cpu(ucode->boot_size);
5335 5352
5336 IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n", 5353 /* api_ver should match the api version forming part of the
5337 priv->ucode_ver); 5354 * firmware filename ... but we don't check for that and only rely
5338 IWL_DEBUG_INFO("f/w package hdr ucode version = %u.%u.%u.%u\n", 5355 * on the API version read from firware header from here on forward */
5356
5357 if (api_ver < api_min || api_ver > api_max) {
5358 IWL_ERROR("Driver unable to support your firmware API. "
5359 "Driver supports v%u, firmware is v%u.\n",
5360 api_max, api_ver);
5361 priv->ucode_ver = 0;
5362 ret = -EINVAL;
5363 goto err_release;
5364 }
5365 if (api_ver != api_max)
5366 IWL_ERROR("Firmware has old API version. Expected %u, "
5367 "got %u. New firmware can be obtained "
5368 "from http://www.intellinuxwireless.org.\n",
5369 api_max, api_ver);
5370
5371 printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n",
5339 IWL_UCODE_MAJOR(priv->ucode_ver), 5372 IWL_UCODE_MAJOR(priv->ucode_ver),
5340 IWL_UCODE_MINOR(priv->ucode_ver), 5373 IWL_UCODE_MINOR(priv->ucode_ver),
5341 IWL_UCODE_API(priv->ucode_ver), 5374 IWL_UCODE_API(priv->ucode_ver),
5342 IWL_UCODE_SERIAL(priv->ucode_ver)); 5375 IWL_UCODE_SERIAL(priv->ucode_ver));
5376 IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
5377 priv->ucode_ver);
5343 IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size); 5378 IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size);
5344 IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size); 5379 IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size);
5345 IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size); 5380 IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size);
5346 IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size); 5381 IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size);
5347 IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size); 5382 IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size);
5348 5383
5384
5349 /* Verify size of file vs. image size info in file's header */ 5385 /* Verify size of file vs. image size info in file's header */
5350 if (ucode_raw->size < sizeof(*ucode) + 5386 if (ucode_raw->size < sizeof(*ucode) +
5351 inst_size + data_size + init_size + 5387 inst_size + data_size + init_size +
@@ -8304,7 +8340,7 @@ static void __exit iwl3945_exit(void)
8304 iwl3945_rate_control_unregister(); 8340 iwl3945_rate_control_unregister();
8305} 8341}
8306 8342
8307MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode"); 8343MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
8308 8344
8309module_param_named(antenna, iwl3945_param_antenna, int, 0444); 8345module_param_named(antenna, iwl3945_param_antenna, int, 0444);
8310MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); 8346MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");