diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 40 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 39 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 51 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 55 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 31 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 45 |
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) \ | ||
2790 | static 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 | |||
2796 | static u32 iwl3945_ucode_get_header_size(u32 api_ver) | ||
2797 | { | ||
2798 | return UCODE_HEADER_SIZE(1); | ||
2799 | } | ||
2800 | static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
2801 | u32 api_ver) | ||
2802 | { | ||
2803 | return 0; | ||
2804 | } | ||
2805 | static 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 | |||
2811 | IWL3945_UCODE_GET(inst_size); | ||
2812 | IWL3945_UCODE_GET(data_size); | ||
2813 | IWL3945_UCODE_GET(init_size); | ||
2814 | IWL3945_UCODE_GET(init_data_size); | ||
2815 | IWL3945_UCODE_GET(boot_size); | ||
2816 | |||
2789 | static struct iwl_hcmd_ops iwl3945_hcmd = { | 2817 | static 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 | ||
2822 | static 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 | |||
2794 | static struct iwl_lib_ops iwl3945_lib = { | 2833 | static 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 | ||
2833 | static struct iwl_ops iwl3945_ops = { | 2872 | static 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) \ | ||
2225 | static 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 | |||
2231 | static u32 iwl4965_ucode_get_header_size(u32 api_ver) | ||
2232 | { | ||
2233 | return UCODE_HEADER_SIZE(1); | ||
2234 | } | ||
2235 | static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
2236 | u32 api_ver) | ||
2237 | { | ||
2238 | return 0; | ||
2239 | } | ||
2240 | static 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 | |||
2246 | IWL4965_UCODE_GET(inst_size); | ||
2247 | IWL4965_UCODE_GET(data_size); | ||
2248 | IWL4965_UCODE_GET(init_size); | ||
2249 | IWL4965_UCODE_GET(init_data_size); | ||
2250 | IWL4965_UCODE_GET(boot_size); | ||
2251 | |||
2224 | static struct iwl_hcmd_ops iwl4965_hcmd = { | 2252 | static 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 | ||
2258 | static 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 | }; | ||
2230 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | 2268 | static 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 | ||
2289 | static struct iwl_ops iwl4965_ops = { | 2327 | static 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) \ | ||
1460 | static 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 | |||
1468 | static 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 | |||
1475 | static 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 | |||
1483 | static 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 | |||
1491 | IWL5000_UCODE_GET(inst_size); | ||
1492 | IWL5000_UCODE_GET(data_size); | ||
1493 | IWL5000_UCODE_GET(init_size); | ||
1494 | IWL5000_UCODE_GET(init_data_size); | ||
1495 | IWL5000_UCODE_GET(boot_size); | ||
1496 | |||
1459 | struct iwl_hcmd_ops iwl5000_hcmd = { | 1497 | struct 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 | ||
1512 | struct 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 | |||
1474 | struct iwl_lib_ops iwl5000_lib = { | 1523 | struct 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 | ||
1574 | struct iwl_ops iwl5000_ops = { | 1623 | struct 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 | ||
1580 | static struct iwl_ops iwl5150_ops = { | 1630 | static 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 | ||
71 | static struct iwl_ops iwl6000_ops = { | 71 | static 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 | */ |
1285 | static int iwl_read_ucode(struct iwl_priv *priv) | 1285 | static 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 | ||
119 | struct 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 | |||
119 | struct iwl_lib_ops { | 130 | struct 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 | ||
173 | struct iwl_ops { | 184 | struct 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 */ |
67 | extern struct iwl_mod_params iwl50_mod_params; | 67 | extern struct iwl_mod_params iwl50_mod_params; |
68 | extern struct iwl_ops iwl5000_ops; | 68 | extern struct iwl_ops iwl5000_ops; |
69 | extern struct iwl_ucode_ops iwl5000_ucode; | ||
69 | extern struct iwl_lib_ops iwl5000_lib; | 70 | extern struct iwl_lib_ops iwl5000_lib; |
70 | extern struct iwl_hcmd_ops iwl5000_hcmd; | 71 | extern struct iwl_hcmd_ops iwl5000_hcmd; |
71 | extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; | 72 | extern 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 */ |
528 | struct iwl_ucode { | 529 | struct 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 | ||
538 | struct iwl4965_ibss_seq { | 553 | struct 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 | */ |
2042 | static int iwl3945_read_ucode(struct iwl_priv *priv) | 2042 | static 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); |