aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c40
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c51
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c55
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c45
8 files changed, 224 insertions, 54 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 1227ed2960fb..14a47c0a1583 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2786,11 +2786,50 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
2786 return 0; 2786 return 0;
2787} 2787}
2788 2788
2789#define IWL3945_UCODE_GET(item) \
2790static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\
2791 u32 api_ver) \
2792{ \
2793 return le32_to_cpu(ucode->u.v1.item); \
2794}
2795
2796static u32 iwl3945_ucode_get_header_size(u32 api_ver)
2797{
2798 return UCODE_HEADER_SIZE(1);
2799}
2800static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode,
2801 u32 api_ver)
2802{
2803 return 0;
2804}
2805static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode,
2806 u32 api_ver)
2807{
2808 return (u8 *) ucode->u.v1.data;
2809}
2810
2811IWL3945_UCODE_GET(inst_size);
2812IWL3945_UCODE_GET(data_size);
2813IWL3945_UCODE_GET(init_size);
2814IWL3945_UCODE_GET(init_data_size);
2815IWL3945_UCODE_GET(boot_size);
2816
2789static struct iwl_hcmd_ops iwl3945_hcmd = { 2817static struct iwl_hcmd_ops iwl3945_hcmd = {
2790 .rxon_assoc = iwl3945_send_rxon_assoc, 2818 .rxon_assoc = iwl3945_send_rxon_assoc,
2791 .commit_rxon = iwl3945_commit_rxon, 2819 .commit_rxon = iwl3945_commit_rxon,
2792}; 2820};
2793 2821
2822static struct iwl_ucode_ops iwl3945_ucode = {
2823 .get_header_size = iwl3945_ucode_get_header_size,
2824 .get_build = iwl3945_ucode_get_build,
2825 .get_inst_size = iwl3945_ucode_get_inst_size,
2826 .get_data_size = iwl3945_ucode_get_data_size,
2827 .get_init_size = iwl3945_ucode_get_init_size,
2828 .get_init_data_size = iwl3945_ucode_get_init_data_size,
2829 .get_boot_size = iwl3945_ucode_get_boot_size,
2830 .get_data = iwl3945_ucode_get_data,
2831};
2832
2794static struct iwl_lib_ops iwl3945_lib = { 2833static struct iwl_lib_ops iwl3945_lib = {
2795 .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, 2834 .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
2796 .txq_free_tfd = iwl3945_hw_txq_free_tfd, 2835 .txq_free_tfd = iwl3945_hw_txq_free_tfd,
@@ -2831,6 +2870,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
2831}; 2870};
2832 2871
2833static struct iwl_ops iwl3945_ops = { 2872static struct iwl_ops iwl3945_ops = {
2873 .ucode = &iwl3945_ucode,
2834 .lib = &iwl3945_lib, 2874 .lib = &iwl3945_lib,
2835 .hcmd = &iwl3945_hcmd, 2875 .hcmd = &iwl3945_hcmd,
2836 .utils = &iwl3945_hcmd_utils, 2876 .utils = &iwl3945_hcmd_utils,
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index edbb0bfd8cb7..f4eb683aa2d5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2221,12 +2221,50 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
2221 cancel_work_sync(&priv->txpower_work); 2221 cancel_work_sync(&priv->txpower_work);
2222} 2222}
2223 2223
2224#define IWL4965_UCODE_GET(item) \
2225static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\
2226 u32 api_ver) \
2227{ \
2228 return le32_to_cpu(ucode->u.v1.item); \
2229}
2230
2231static u32 iwl4965_ucode_get_header_size(u32 api_ver)
2232{
2233 return UCODE_HEADER_SIZE(1);
2234}
2235static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode,
2236 u32 api_ver)
2237{
2238 return 0;
2239}
2240static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode,
2241 u32 api_ver)
2242{
2243 return (u8 *) ucode->u.v1.data;
2244}
2245
2246IWL4965_UCODE_GET(inst_size);
2247IWL4965_UCODE_GET(data_size);
2248IWL4965_UCODE_GET(init_size);
2249IWL4965_UCODE_GET(init_data_size);
2250IWL4965_UCODE_GET(boot_size);
2251
2224static struct iwl_hcmd_ops iwl4965_hcmd = { 2252static struct iwl_hcmd_ops iwl4965_hcmd = {
2225 .rxon_assoc = iwl4965_send_rxon_assoc, 2253 .rxon_assoc = iwl4965_send_rxon_assoc,
2226 .commit_rxon = iwl_commit_rxon, 2254 .commit_rxon = iwl_commit_rxon,
2227 .set_rxon_chain = iwl_set_rxon_chain, 2255 .set_rxon_chain = iwl_set_rxon_chain,
2228}; 2256};
2229 2257
2258static struct iwl_ucode_ops iwl4965_ucode = {
2259 .get_header_size = iwl4965_ucode_get_header_size,
2260 .get_build = iwl4965_ucode_get_build,
2261 .get_inst_size = iwl4965_ucode_get_inst_size,
2262 .get_data_size = iwl4965_ucode_get_data_size,
2263 .get_init_size = iwl4965_ucode_get_init_size,
2264 .get_init_data_size = iwl4965_ucode_get_init_data_size,
2265 .get_boot_size = iwl4965_ucode_get_boot_size,
2266 .get_data = iwl4965_ucode_get_data,
2267};
2230static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { 2268static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
2231 .get_hcmd_size = iwl4965_get_hcmd_size, 2269 .get_hcmd_size = iwl4965_get_hcmd_size,
2232 .build_addsta_hcmd = iwl4965_build_addsta_hcmd, 2270 .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
@@ -2287,6 +2325,7 @@ static struct iwl_lib_ops iwl4965_lib = {
2287}; 2325};
2288 2326
2289static struct iwl_ops iwl4965_ops = { 2327static struct iwl_ops iwl4965_ops = {
2328 .ucode = &iwl4965_ucode,
2290 .lib = &iwl4965_lib, 2329 .lib = &iwl4965_lib,
2291 .hcmd = &iwl4965_hcmd, 2330 .hcmd = &iwl4965_hcmd,
2292 .utils = &iwl4965_hcmd_utils, 2331 .utils = &iwl4965_hcmd_utils,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 3f9da6e47108..74103cfcaceb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1456,6 +1456,44 @@ int iwl5000_calc_rssi(struct iwl_priv *priv,
1456 return max_rssi - agc - IWL49_RSSI_OFFSET; 1456 return max_rssi - agc - IWL49_RSSI_OFFSET;
1457} 1457}
1458 1458
1459#define IWL5000_UCODE_GET(item) \
1460static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\
1461 u32 api_ver) \
1462{ \
1463 if (api_ver <= 2) \
1464 return le32_to_cpu(ucode->u.v1.item); \
1465 return le32_to_cpu(ucode->u.v2.item); \
1466}
1467
1468static u32 iwl5000_ucode_get_header_size(u32 api_ver)
1469{
1470 if (api_ver <= 2)
1471 return UCODE_HEADER_SIZE(1);
1472 return UCODE_HEADER_SIZE(2);
1473}
1474
1475static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode,
1476 u32 api_ver)
1477{
1478 if (api_ver <= 2)
1479 return 0;
1480 return le32_to_cpu(ucode->u.v2.build);
1481}
1482
1483static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode,
1484 u32 api_ver)
1485{
1486 if (api_ver <= 2)
1487 return (u8 *) ucode->u.v1.data;
1488 return (u8 *) ucode->u.v2.data;
1489}
1490
1491IWL5000_UCODE_GET(inst_size);
1492IWL5000_UCODE_GET(data_size);
1493IWL5000_UCODE_GET(init_size);
1494IWL5000_UCODE_GET(init_data_size);
1495IWL5000_UCODE_GET(boot_size);
1496
1459struct iwl_hcmd_ops iwl5000_hcmd = { 1497struct iwl_hcmd_ops iwl5000_hcmd = {
1460 .rxon_assoc = iwl5000_send_rxon_assoc, 1498 .rxon_assoc = iwl5000_send_rxon_assoc,
1461 .commit_rxon = iwl_commit_rxon, 1499 .commit_rxon = iwl_commit_rxon,
@@ -1471,6 +1509,17 @@ struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
1471 .calc_rssi = iwl5000_calc_rssi, 1509 .calc_rssi = iwl5000_calc_rssi,
1472}; 1510};
1473 1511
1512struct iwl_ucode_ops iwl5000_ucode = {
1513 .get_header_size = iwl5000_ucode_get_header_size,
1514 .get_build = iwl5000_ucode_get_build,
1515 .get_inst_size = iwl5000_ucode_get_inst_size,
1516 .get_data_size = iwl5000_ucode_get_data_size,
1517 .get_init_size = iwl5000_ucode_get_init_size,
1518 .get_init_data_size = iwl5000_ucode_get_init_data_size,
1519 .get_boot_size = iwl5000_ucode_get_boot_size,
1520 .get_data = iwl5000_ucode_get_data,
1521};
1522
1474struct iwl_lib_ops iwl5000_lib = { 1523struct iwl_lib_ops iwl5000_lib = {
1475 .set_hw_params = iwl5000_hw_set_hw_params, 1524 .set_hw_params = iwl5000_hw_set_hw_params,
1476 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, 1525 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
@@ -1572,12 +1621,14 @@ static struct iwl_lib_ops iwl5150_lib = {
1572}; 1621};
1573 1622
1574struct iwl_ops iwl5000_ops = { 1623struct iwl_ops iwl5000_ops = {
1624 .ucode = &iwl5000_ucode,
1575 .lib = &iwl5000_lib, 1625 .lib = &iwl5000_lib,
1576 .hcmd = &iwl5000_hcmd, 1626 .hcmd = &iwl5000_hcmd,
1577 .utils = &iwl5000_hcmd_utils, 1627 .utils = &iwl5000_hcmd_utils,
1578}; 1628};
1579 1629
1580static struct iwl_ops iwl5150_ops = { 1630static struct iwl_ops iwl5150_ops = {
1631 .ucode = &iwl5000_ucode,
1581 .lib = &iwl5150_lib, 1632 .lib = &iwl5150_lib,
1582 .hcmd = &iwl5000_hcmd, 1633 .hcmd = &iwl5000_hcmd,
1583 .utils = &iwl5000_hcmd_utils, 1634 .utils = &iwl5000_hcmd_utils,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index bd438d8acf55..26c5d4a60d17 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -46,8 +46,8 @@
46#include "iwl-5000-hw.h" 46#include "iwl-5000-hw.h"
47 47
48/* Highest firmware API version supported */ 48/* Highest firmware API version supported */
49#define IWL6000_UCODE_API_MAX 2 49#define IWL6000_UCODE_API_MAX 3
50#define IWL6050_UCODE_API_MAX 2 50#define IWL6050_UCODE_API_MAX 3
51 51
52/* Lowest firmware API version supported */ 52/* Lowest firmware API version supported */
53#define IWL6000_UCODE_API_MIN 1 53#define IWL6000_UCODE_API_MIN 1
@@ -69,6 +69,7 @@ static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
69}; 69};
70 70
71static struct iwl_ops iwl6000_ops = { 71static struct iwl_ops iwl6000_ops = {
72 .ucode = &iwl5000_ucode,
72 .lib = &iwl5000_lib, 73 .lib = &iwl5000_lib,
73 .hcmd = &iwl5000_hcmd, 74 .hcmd = &iwl5000_hcmd,
74 .utils = &iwl6000_hcmd_utils, 75 .utils = &iwl6000_hcmd_utils,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index ad5002211ab4..6b874dab4120 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1284,7 +1284,7 @@ static void iwl_nic_start(struct iwl_priv *priv)
1284 */ 1284 */
1285static int iwl_read_ucode(struct iwl_priv *priv) 1285static int iwl_read_ucode(struct iwl_priv *priv)
1286{ 1286{
1287 struct iwl_ucode *ucode; 1287 struct iwl_ucode_header *ucode;
1288 int ret = -EINVAL, index; 1288 int ret = -EINVAL, index;
1289 const struct firmware *ucode_raw; 1289 const struct firmware *ucode_raw;
1290 const char *name_pre = priv->cfg->fw_name_pre; 1290 const char *name_pre = priv->cfg->fw_name_pre;
@@ -1293,7 +1293,8 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1293 char buf[25]; 1293 char buf[25];
1294 u8 *src; 1294 u8 *src;
1295 size_t len; 1295 size_t len;
1296 u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size; 1296 u32 api_ver, build;
1297 u32 inst_size, data_size, init_size, init_data_size, boot_size;
1297 1298
1298 /* Ask kernel firmware_class module to get the boot firmware off disk. 1299 /* Ask kernel firmware_class module to get the boot firmware off disk.
1299 * request_firmware() is synchronous, file is in memory on return. */ 1300 * request_firmware() is synchronous, file is in memory on return. */
@@ -1323,23 +1324,26 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1323 if (ret < 0) 1324 if (ret < 0)
1324 goto error; 1325 goto error;
1325 1326
1326 /* Make sure that we got at least our header! */ 1327 /* Make sure that we got at least the v1 header! */
1327 if (ucode_raw->size < sizeof(*ucode)) { 1328 if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
1328 IWL_ERR(priv, "File size way too small!\n"); 1329 IWL_ERR(priv, "File size way too small!\n");
1329 ret = -EINVAL; 1330 ret = -EINVAL;
1330 goto err_release; 1331 goto err_release;
1331 } 1332 }
1332 1333
1333 /* Data from ucode file: header followed by uCode images */ 1334 /* Data from ucode file: header followed by uCode images */
1334 ucode = (void *)ucode_raw->data; 1335 ucode = (struct iwl_ucode_header *)ucode_raw->data;
1335 1336
1336 priv->ucode_ver = le32_to_cpu(ucode->ver); 1337 priv->ucode_ver = le32_to_cpu(ucode->ver);
1337 api_ver = IWL_UCODE_API(priv->ucode_ver); 1338 api_ver = IWL_UCODE_API(priv->ucode_ver);
1338 inst_size = le32_to_cpu(ucode->inst_size); 1339 build = priv->cfg->ops->ucode->get_build(ucode, api_ver);
1339 data_size = le32_to_cpu(ucode->data_size); 1340 inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
1340 init_size = le32_to_cpu(ucode->init_size); 1341 data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
1341 init_data_size = le32_to_cpu(ucode->init_data_size); 1342 init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
1342 boot_size = le32_to_cpu(ucode->boot_size); 1343 init_data_size =
1344 priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
1345 boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
1346 src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
1343 1347
1344 /* api_ver should match the api version forming part of the 1348 /* api_ver should match the api version forming part of the
1345 * firmware filename ... but we don't check for that and only rely 1349 * firmware filename ... but we don't check for that and only rely
@@ -1365,6 +1369,9 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1365 IWL_UCODE_API(priv->ucode_ver), 1369 IWL_UCODE_API(priv->ucode_ver),
1366 IWL_UCODE_SERIAL(priv->ucode_ver)); 1370 IWL_UCODE_SERIAL(priv->ucode_ver));
1367 1371
1372 if (build)
1373 IWL_DEBUG_INFO(priv, "Build %u\n", build);
1374
1368 IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", 1375 IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
1369 priv->ucode_ver); 1376 priv->ucode_ver);
1370 IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", 1377 IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
@@ -1379,12 +1386,14 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1379 boot_size); 1386 boot_size);
1380 1387
1381 /* Verify size of file vs. image size info in file's header */ 1388 /* Verify size of file vs. image size info in file's header */
1382 if (ucode_raw->size < sizeof(*ucode) + 1389 if (ucode_raw->size !=
1390 priv->cfg->ops->ucode->get_header_size(api_ver) +
1383 inst_size + data_size + init_size + 1391 inst_size + data_size + init_size +
1384 init_data_size + boot_size) { 1392 init_data_size + boot_size) {
1385 1393
1386 IWL_DEBUG_INFO(priv, "uCode file size %d too small\n", 1394 IWL_DEBUG_INFO(priv,
1387 (int)ucode_raw->size); 1395 "uCode file size %d does not match expected size\n",
1396 (int)ucode_raw->size);
1388 ret = -EINVAL; 1397 ret = -EINVAL;
1389 goto err_release; 1398 goto err_release;
1390 } 1399 }
@@ -1464,42 +1473,42 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1464 /* Copy images into buffers for card's bus-master reads ... */ 1473 /* Copy images into buffers for card's bus-master reads ... */
1465 1474
1466 /* Runtime instructions (first block of data in file) */ 1475 /* Runtime instructions (first block of data in file) */
1467 src = &ucode->data[0]; 1476 len = inst_size;
1468 len = priv->ucode_code.len;
1469 IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); 1477 IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len);
1470 memcpy(priv->ucode_code.v_addr, src, len); 1478 memcpy(priv->ucode_code.v_addr, src, len);
1479 src += len;
1480
1471 IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", 1481 IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
1472 priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); 1482 priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
1473 1483
1474 /* Runtime data (2nd block) 1484 /* Runtime data (2nd block)
1475 * NOTE: Copy into backup buffer will be done in iwl_up() */ 1485 * NOTE: Copy into backup buffer will be done in iwl_up() */
1476 src = &ucode->data[inst_size]; 1486 len = data_size;
1477 len = priv->ucode_data.len;
1478 IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); 1487 IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len);
1479 memcpy(priv->ucode_data.v_addr, src, len); 1488 memcpy(priv->ucode_data.v_addr, src, len);
1480 memcpy(priv->ucode_data_backup.v_addr, src, len); 1489 memcpy(priv->ucode_data_backup.v_addr, src, len);
1490 src += len;
1481 1491
1482 /* Initialization instructions (3rd block) */ 1492 /* Initialization instructions (3rd block) */
1483 if (init_size) { 1493 if (init_size) {
1484 src = &ucode->data[inst_size + data_size]; 1494 len = init_size;
1485 len = priv->ucode_init.len;
1486 IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", 1495 IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n",
1487 len); 1496 len);
1488 memcpy(priv->ucode_init.v_addr, src, len); 1497 memcpy(priv->ucode_init.v_addr, src, len);
1498 src += len;
1489 } 1499 }
1490 1500
1491 /* Initialization data (4th block) */ 1501 /* Initialization data (4th block) */
1492 if (init_data_size) { 1502 if (init_data_size) {
1493 src = &ucode->data[inst_size + data_size + init_size]; 1503 len = init_data_size;
1494 len = priv->ucode_init_data.len;
1495 IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", 1504 IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n",
1496 len); 1505 len);
1497 memcpy(priv->ucode_init_data.v_addr, src, len); 1506 memcpy(priv->ucode_init_data.v_addr, src, len);
1507 src += len;
1498 } 1508 }
1499 1509
1500 /* Bootstrap instructions (5th block) */ 1510 /* Bootstrap instructions (5th block) */
1501 src = &ucode->data[inst_size + data_size + init_size + init_data_size]; 1511 len = boot_size;
1502 len = priv->ucode_boot.len;
1503 IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); 1512 IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len);
1504 memcpy(priv->ucode_boot.v_addr, src, len); 1513 memcpy(priv->ucode_boot.v_addr, src, len);
1505 1514
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 640c4644a165..c844fab95abb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -116,6 +116,17 @@ struct iwl_temp_ops {
116 void (*set_ct_kill)(struct iwl_priv *priv); 116 void (*set_ct_kill)(struct iwl_priv *priv);
117}; 117};
118 118
119struct iwl_ucode_ops {
120 u32 (*get_header_size)(u32);
121 u32 (*get_build)(const struct iwl_ucode_header *, u32);
122 u32 (*get_inst_size)(const struct iwl_ucode_header *, u32);
123 u32 (*get_data_size)(const struct iwl_ucode_header *, u32);
124 u32 (*get_init_size)(const struct iwl_ucode_header *, u32);
125 u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32);
126 u32 (*get_boot_size)(const struct iwl_ucode_header *, u32);
127 u8 * (*get_data)(const struct iwl_ucode_header *, u32);
128};
129
119struct iwl_lib_ops { 130struct iwl_lib_ops {
120 /* set hw dependent parameters */ 131 /* set hw dependent parameters */
121 int (*set_hw_params)(struct iwl_priv *priv); 132 int (*set_hw_params)(struct iwl_priv *priv);
@@ -171,6 +182,7 @@ struct iwl_lib_ops {
171}; 182};
172 183
173struct iwl_ops { 184struct iwl_ops {
185 const struct iwl_ucode_ops *ucode;
174 const struct iwl_lib_ops *lib; 186 const struct iwl_lib_ops *lib;
175 const struct iwl_hcmd_ops *hcmd; 187 const struct iwl_hcmd_ops *hcmd;
176 const struct iwl_hcmd_utils_ops *utils; 188 const struct iwl_hcmd_utils_ops *utils;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index b989d5c08d34..f4afd0c3265f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -66,6 +66,7 @@ extern struct iwl_cfg iwl1000_bgn_cfg;
66/* shared structures from iwl-5000.c */ 66/* shared structures from iwl-5000.c */
67extern struct iwl_mod_params iwl50_mod_params; 67extern struct iwl_mod_params iwl50_mod_params;
68extern struct iwl_ops iwl5000_ops; 68extern struct iwl_ops iwl5000_ops;
69extern struct iwl_ucode_ops iwl5000_ucode;
69extern struct iwl_lib_ops iwl5000_lib; 70extern struct iwl_lib_ops iwl5000_lib;
70extern struct iwl_hcmd_ops iwl5000_hcmd; 71extern struct iwl_hcmd_ops iwl5000_hcmd;
71extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; 72extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils;
@@ -525,15 +526,29 @@ struct fw_desc {
525}; 526};
526 527
527/* uCode file layout */ 528/* uCode file layout */
528struct iwl_ucode { 529struct iwl_ucode_header {
529 __le32 ver; /* major/minor/API/serial */ 530 __le32 ver; /* major/minor/API/serial */
530 __le32 inst_size; /* bytes of runtime instructions */ 531 union {
531 __le32 data_size; /* bytes of runtime data */ 532 struct {
532 __le32 init_size; /* bytes of initialization instructions */ 533 __le32 inst_size; /* bytes of runtime code */
533 __le32 init_data_size; /* bytes of initialization data */ 534 __le32 data_size; /* bytes of runtime data */
534 __le32 boot_size; /* bytes of bootstrap instructions */ 535 __le32 init_size; /* bytes of init code */
535 u8 data[0]; /* data in same order as "size" elements */ 536 __le32 init_data_size; /* bytes of init data */
537 __le32 boot_size; /* bytes of bootstrap code */
538 u8 data[0]; /* in same order as sizes */
539 } v1;
540 struct {
541 __le32 build; /* build number */
542 __le32 inst_size; /* bytes of runtime code */
543 __le32 data_size; /* bytes of runtime data */
544 __le32 init_size; /* bytes of init code */
545 __le32 init_data_size; /* bytes of init data */
546 __le32 boot_size; /* bytes of bootstrap code */
547 u8 data[0]; /* in same order as sizes */
548 } v2;
549 } u;
536}; 550};
551#define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28)
537 552
538struct iwl4965_ibss_seq { 553struct iwl4965_ibss_seq {
539 u8 mac[ETH_ALEN]; 554 u8 mac[ETH_ALEN];
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index c9b3ea927144..bd6a067b4881 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2041,7 +2041,7 @@ static void iwl3945_nic_start(struct iwl_priv *priv)
2041 */ 2041 */
2042static int iwl3945_read_ucode(struct iwl_priv *priv) 2042static int iwl3945_read_ucode(struct iwl_priv *priv)
2043{ 2043{
2044 struct iwl_ucode *ucode; 2044 const struct iwl_ucode_header *ucode;
2045 int ret = -EINVAL, index; 2045 int ret = -EINVAL, index;
2046 const struct firmware *ucode_raw; 2046 const struct firmware *ucode_raw;
2047 /* firmware file name contains uCode/driver compatibility version */ 2047 /* firmware file name contains uCode/driver compatibility version */
@@ -2082,22 +2082,24 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
2082 goto error; 2082 goto error;
2083 2083
2084 /* Make sure that we got at least our header! */ 2084 /* Make sure that we got at least our header! */
2085 if (ucode_raw->size < sizeof(*ucode)) { 2085 if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
2086 IWL_ERR(priv, "File size way too small!\n"); 2086 IWL_ERR(priv, "File size way too small!\n");
2087 ret = -EINVAL; 2087 ret = -EINVAL;
2088 goto err_release; 2088 goto err_release;
2089 } 2089 }
2090 2090
2091 /* Data from ucode file: header followed by uCode images */ 2091 /* Data from ucode file: header followed by uCode images */
2092 ucode = (void *)ucode_raw->data; 2092 ucode = (struct iwl_ucode_header *)ucode_raw->data;
2093 2093
2094 priv->ucode_ver = le32_to_cpu(ucode->ver); 2094 priv->ucode_ver = le32_to_cpu(ucode->ver);
2095 api_ver = IWL_UCODE_API(priv->ucode_ver); 2095 api_ver = IWL_UCODE_API(priv->ucode_ver);
2096 inst_size = le32_to_cpu(ucode->inst_size); 2096 inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
2097 data_size = le32_to_cpu(ucode->data_size); 2097 data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
2098 init_size = le32_to_cpu(ucode->init_size); 2098 init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
2099 init_data_size = le32_to_cpu(ucode->init_data_size); 2099 init_data_size =
2100 boot_size = le32_to_cpu(ucode->boot_size); 2100 priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
2101 boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
2102 src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
2101 2103
2102 /* api_ver should match the api version forming part of the 2104 /* api_ver should match the api version forming part of the
2103 * firmware filename ... but we don't check for that and only rely 2105 * firmware filename ... but we don't check for that and only rely
@@ -2138,12 +2140,13 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
2138 2140
2139 2141
2140 /* Verify size of file vs. image size info in file's header */ 2142 /* Verify size of file vs. image size info in file's header */
2141 if (ucode_raw->size < sizeof(*ucode) + 2143 if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
2142 inst_size + data_size + init_size + 2144 inst_size + data_size + init_size +
2143 init_data_size + boot_size) { 2145 init_data_size + boot_size) {
2144 2146
2145 IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n", 2147 IWL_DEBUG_INFO(priv,
2146 ucode_raw->size); 2148 "uCode file size %zd does not match expected size\n",
2149 ucode_raw->size);
2147 ret = -EINVAL; 2150 ret = -EINVAL;
2148 goto err_release; 2151 goto err_release;
2149 } 2152 }
@@ -2226,44 +2229,44 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
2226 /* Copy images into buffers for card's bus-master reads ... */ 2229 /* Copy images into buffers for card's bus-master reads ... */
2227 2230
2228 /* Runtime instructions (first block of data in file) */ 2231 /* Runtime instructions (first block of data in file) */
2229 src = &ucode->data[0]; 2232 len = inst_size;
2230 len = priv->ucode_code.len;
2231 IWL_DEBUG_INFO(priv, 2233 IWL_DEBUG_INFO(priv,
2232 "Copying (but not loading) uCode instr len %zd\n", len); 2234 "Copying (but not loading) uCode instr len %zd\n", len);
2233 memcpy(priv->ucode_code.v_addr, src, len); 2235 memcpy(priv->ucode_code.v_addr, src, len);
2236 src += len;
2237
2234 IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", 2238 IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
2235 priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); 2239 priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
2236 2240
2237 /* Runtime data (2nd block) 2241 /* Runtime data (2nd block)
2238 * NOTE: Copy into backup buffer will be done in iwl3945_up() */ 2242 * NOTE: Copy into backup buffer will be done in iwl3945_up() */
2239 src = &ucode->data[inst_size]; 2243 len = data_size;
2240 len = priv->ucode_data.len;
2241 IWL_DEBUG_INFO(priv, 2244 IWL_DEBUG_INFO(priv,
2242 "Copying (but not loading) uCode data len %zd\n", len); 2245 "Copying (but not loading) uCode data len %zd\n", len);
2243 memcpy(priv->ucode_data.v_addr, src, len); 2246 memcpy(priv->ucode_data.v_addr, src, len);
2244 memcpy(priv->ucode_data_backup.v_addr, src, len); 2247 memcpy(priv->ucode_data_backup.v_addr, src, len);
2248 src += len;
2245 2249
2246 /* Initialization instructions (3rd block) */ 2250 /* Initialization instructions (3rd block) */
2247 if (init_size) { 2251 if (init_size) {
2248 src = &ucode->data[inst_size + data_size]; 2252 len = init_size;
2249 len = priv->ucode_init.len;
2250 IWL_DEBUG_INFO(priv, 2253 IWL_DEBUG_INFO(priv,
2251 "Copying (but not loading) init instr len %zd\n", len); 2254 "Copying (but not loading) init instr len %zd\n", len);
2252 memcpy(priv->ucode_init.v_addr, src, len); 2255 memcpy(priv->ucode_init.v_addr, src, len);
2256 src += len;
2253 } 2257 }
2254 2258
2255 /* Initialization data (4th block) */ 2259 /* Initialization data (4th block) */
2256 if (init_data_size) { 2260 if (init_data_size) {
2257 src = &ucode->data[inst_size + data_size + init_size]; 2261 len = init_data_size;
2258 len = priv->ucode_init_data.len;
2259 IWL_DEBUG_INFO(priv, 2262 IWL_DEBUG_INFO(priv,
2260 "Copying (but not loading) init data len %zd\n", len); 2263 "Copying (but not loading) init data len %zd\n", len);
2261 memcpy(priv->ucode_init_data.v_addr, src, len); 2264 memcpy(priv->ucode_init_data.v_addr, src, len);
2265 src += len;
2262 } 2266 }
2263 2267
2264 /* Bootstrap instructions (5th block) */ 2268 /* Bootstrap instructions (5th block) */
2265 src = &ucode->data[inst_size + data_size + init_size + init_data_size]; 2269 len = boot_size;
2266 len = priv->ucode_boot.len;
2267 IWL_DEBUG_INFO(priv, 2270 IWL_DEBUG_INFO(priv,
2268 "Copying (but not loading) boot instr len %zd\n", len); 2271 "Copying (but not loading) boot instr len %zd\n", len);
2269 memcpy(priv->ucode_boot.v_addr, src, len); 2272 memcpy(priv->ucode_boot.v_addr, src, len);