aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-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])");