diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945-core.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 46 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 62 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 32 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 64 |
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 | */ | ||
74 | struct iwl_3945_cfg { | 96 | struct 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 | ||
2509 | static struct iwl_3945_cfg iwl3945_bg_cfg = { | 2509 | static 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 | ||
2515 | static struct iwl_3945_cfg iwl3945_abg_cfg = { | 2517 | static 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 @@ | |||
48 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 48 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
49 | static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); | 49 | static 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 | ||
2337 | struct iwl_cfg iwl4965_agn_cfg = { | 2340 | struct 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 */ |
2349 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE); | 2354 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); |
2350 | 2355 | ||
2351 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); | 2356 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); |
2352 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 2357 | MODULE_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 | ||
53 | static const u16 iwl5000_default_queue_to_tx_fifo[] = { | 63 | static 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 | ||
1533 | struct iwl_cfg iwl5300_agn_cfg = { | 1543 | struct 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 | ||
1544 | struct iwl_cfg iwl5100_bg_cfg = { | 1556 | struct 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 | ||
1555 | struct iwl_cfg iwl5100_abg_cfg = { | 1569 | struct 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 | ||
1566 | struct iwl_cfg iwl5100_agn_cfg = { | 1582 | struct 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 | ||
1577 | struct iwl_cfg iwl5350_agn_cfg = { | 1595 | struct 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 | ||
1588 | struct iwl_cfg iwl5150_agn_cfg = { | 1608 | struct 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 | ||
1599 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE); | 1621 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); |
1600 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE); | 1622 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); |
1601 | 1623 | ||
1602 | module_param_named(disable50, iwl50_mod_params.disable, int, 0444); | 1624 | module_param_named(disable50, iwl50_mod_params.disable, int, 0444); |
1603 | MODULE_PARM_DESC(disable50, | 1625 | MODULE_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) | |||
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", |
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 | */ | ||
167 | struct iwl_cfg { | 195 | struct 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) | |||
5296 | static int iwl3945_read_ucode(struct iwl3945_priv *priv) | 5296 | static 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 | ||
8307 | MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode"); | 8343 | MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); |
8308 | 8344 | ||
8309 | module_param_named(antenna, iwl3945_param_antenna, int, 0444); | 8345 | module_param_named(antenna, iwl3945_param_antenna, int, 0444); |
8310 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 8346 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |