diff options
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 157 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 2 |
2 files changed, 81 insertions, 78 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6aeb82b6992f..47b021477967 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
| @@ -1463,59 +1463,66 @@ static void iwl_nic_start(struct iwl_priv *priv) | |||
| 1463 | } | 1463 | } |
| 1464 | 1464 | ||
| 1465 | 1465 | ||
| 1466 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | ||
| 1467 | static int iwl_mac_setup_register(struct iwl_priv *priv); | ||
| 1468 | |||
| 1469 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | ||
| 1470 | { | ||
| 1471 | const char *name_pre = priv->cfg->fw_name_pre; | ||
| 1472 | |||
| 1473 | if (first) | ||
| 1474 | priv->fw_index = priv->cfg->ucode_api_max; | ||
| 1475 | else | ||
| 1476 | priv->fw_index--; | ||
| 1477 | |||
| 1478 | if (priv->fw_index < priv->cfg->ucode_api_min) { | ||
| 1479 | IWL_ERR(priv, "no suitable firmware found!\n"); | ||
| 1480 | return -ENOENT; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | sprintf(priv->firmware_name, "%s%d%s", | ||
| 1484 | name_pre, priv->fw_index, ".ucode"); | ||
| 1485 | |||
| 1486 | IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n", | ||
| 1487 | priv->firmware_name); | ||
| 1488 | |||
| 1489 | return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, | ||
| 1490 | &priv->pci_dev->dev, GFP_KERNEL, priv, | ||
| 1491 | iwl_ucode_callback); | ||
| 1492 | } | ||
| 1493 | |||
| 1466 | /** | 1494 | /** |
| 1467 | * iwl_read_ucode - Read uCode images from disk file. | 1495 | * iwl_ucode_callback - callback when firmware was loaded |
| 1468 | * | 1496 | * |
| 1469 | * Copy into buffers for card to fetch via bus-mastering | 1497 | * If loaded successfully, copies the firmware into buffers |
| 1498 | * for the card to fetch (via DMA). | ||
| 1470 | */ | 1499 | */ |
| 1471 | static int iwl_read_ucode(struct iwl_priv *priv) | 1500 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) |
| 1472 | { | 1501 | { |
| 1502 | struct iwl_priv *priv = context; | ||
| 1473 | struct iwl_ucode_header *ucode; | 1503 | struct iwl_ucode_header *ucode; |
| 1474 | int ret = -EINVAL, index; | ||
| 1475 | const struct firmware *ucode_raw; | ||
| 1476 | const char *name_pre = priv->cfg->fw_name_pre; | ||
| 1477 | const unsigned int api_max = priv->cfg->ucode_api_max; | 1504 | const unsigned int api_max = priv->cfg->ucode_api_max; |
| 1478 | const unsigned int api_min = priv->cfg->ucode_api_min; | 1505 | const unsigned int api_min = priv->cfg->ucode_api_min; |
| 1479 | char buf[25]; | ||
| 1480 | u8 *src; | 1506 | u8 *src; |
| 1481 | size_t len; | 1507 | size_t len; |
| 1482 | u32 api_ver, build; | 1508 | u32 api_ver, build; |
| 1483 | u32 inst_size, data_size, init_size, init_data_size, boot_size; | 1509 | u32 inst_size, data_size, init_size, init_data_size, boot_size; |
| 1510 | int err; | ||
| 1484 | u16 eeprom_ver; | 1511 | u16 eeprom_ver; |
| 1485 | 1512 | ||
| 1486 | /* Ask kernel firmware_class module to get the boot firmware off disk. | 1513 | if (!ucode_raw) { |
| 1487 | * request_firmware() is synchronous, file is in memory on return. */ | 1514 | IWL_ERR(priv, "request for firmware file '%s' failed.\n", |
| 1488 | for (index = api_max; index >= api_min; index--) { | 1515 | priv->firmware_name); |
| 1489 | sprintf(buf, "%s%d%s", name_pre, index, ".ucode"); | 1516 | goto try_again; |
| 1490 | ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); | ||
| 1491 | if (ret < 0) { | ||
| 1492 | IWL_ERR(priv, "%s firmware file req failed: %d\n", | ||
| 1493 | buf, ret); | ||
| 1494 | if (ret == -ENOENT) | ||
| 1495 | continue; | ||
| 1496 | else | ||
| 1497 | goto error; | ||
| 1498 | } else { | ||
| 1499 | if (index < api_max) | ||
| 1500 | IWL_ERR(priv, "Loaded firmware %s, " | ||
| 1501 | "which is deprecated. " | ||
| 1502 | "Please use API v%u instead.\n", | ||
| 1503 | buf, api_max); | ||
| 1504 | |||
| 1505 | IWL_DEBUG_INFO(priv, "Got firmware '%s' file (%zd bytes) from disk\n", | ||
| 1506 | buf, ucode_raw->size); | ||
| 1507 | break; | ||
| 1508 | } | ||
| 1509 | } | 1517 | } |
| 1510 | 1518 | ||
| 1511 | if (ret < 0) | 1519 | IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", |
| 1512 | goto error; | 1520 | priv->firmware_name, ucode_raw->size); |
| 1513 | 1521 | ||
| 1514 | /* Make sure that we got at least the v1 header! */ | 1522 | /* Make sure that we got at least the v1 header! */ |
| 1515 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { | 1523 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { |
| 1516 | IWL_ERR(priv, "File size way too small!\n"); | 1524 | IWL_ERR(priv, "File size way too small!\n"); |
| 1517 | ret = -EINVAL; | 1525 | goto try_again; |
| 1518 | goto err_release; | ||
| 1519 | } | 1526 | } |
| 1520 | 1527 | ||
| 1521 | /* Data from ucode file: header followed by uCode images */ | 1528 | /* Data from ucode file: header followed by uCode images */ |
| @@ -1540,10 +1547,9 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
| 1540 | IWL_ERR(priv, "Driver unable to support your firmware API. " | 1547 | IWL_ERR(priv, "Driver unable to support your firmware API. " |
| 1541 | "Driver supports v%u, firmware is v%u.\n", | 1548 | "Driver supports v%u, firmware is v%u.\n", |
| 1542 | api_max, api_ver); | 1549 | api_max, api_ver); |
| 1543 | priv->ucode_ver = 0; | 1550 | goto try_again; |
| 1544 | ret = -EINVAL; | ||
| 1545 | goto err_release; | ||
| 1546 | } | 1551 | } |
| 1552 | |||
| 1547 | if (api_ver != api_max) | 1553 | if (api_ver != api_max) |
| 1548 | IWL_ERR(priv, "Firmware has old API version. Expected v%u, " | 1554 | IWL_ERR(priv, "Firmware has old API version. Expected v%u, " |
| 1549 | "got v%u. New firmware can be obtained " | 1555 | "got v%u. New firmware can be obtained " |
| @@ -1585,6 +1591,12 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
| 1585 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", | 1591 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", |
| 1586 | boot_size); | 1592 | boot_size); |
| 1587 | 1593 | ||
| 1594 | /* | ||
| 1595 | * For any of the failures below (before allocating pci memory) | ||
| 1596 | * we will try to load a version with a smaller API -- maybe the | ||
| 1597 | * user just got a corrupted version of the latest API. | ||
| 1598 | */ | ||
| 1599 | |||
| 1588 | /* Verify size of file vs. image size info in file's header */ | 1600 | /* Verify size of file vs. image size info in file's header */ |
| 1589 | if (ucode_raw->size != | 1601 | if (ucode_raw->size != |
| 1590 | priv->cfg->ops->ucode->get_header_size(api_ver) + | 1602 | priv->cfg->ops->ucode->get_header_size(api_ver) + |
| @@ -1594,41 +1606,35 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
| 1594 | IWL_DEBUG_INFO(priv, | 1606 | IWL_DEBUG_INFO(priv, |
| 1595 | "uCode file size %d does not match expected size\n", | 1607 | "uCode file size %d does not match expected size\n", |
| 1596 | (int)ucode_raw->size); | 1608 | (int)ucode_raw->size); |
| 1597 | ret = -EINVAL; | 1609 | goto try_again; |
| 1598 | goto err_release; | ||
| 1599 | } | 1610 | } |
| 1600 | 1611 | ||
| 1601 | /* Verify that uCode images will fit in card's SRAM */ | 1612 | /* Verify that uCode images will fit in card's SRAM */ |
| 1602 | if (inst_size > priv->hw_params.max_inst_size) { | 1613 | if (inst_size > priv->hw_params.max_inst_size) { |
| 1603 | IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", | 1614 | IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", |
| 1604 | inst_size); | 1615 | inst_size); |
| 1605 | ret = -EINVAL; | 1616 | goto try_again; |
| 1606 | goto err_release; | ||
| 1607 | } | 1617 | } |
| 1608 | 1618 | ||
| 1609 | if (data_size > priv->hw_params.max_data_size) { | 1619 | if (data_size > priv->hw_params.max_data_size) { |
| 1610 | IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", | 1620 | IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", |
| 1611 | data_size); | 1621 | data_size); |
| 1612 | ret = -EINVAL; | 1622 | goto try_again; |
| 1613 | goto err_release; | ||
| 1614 | } | 1623 | } |
| 1615 | if (init_size > priv->hw_params.max_inst_size) { | 1624 | if (init_size > priv->hw_params.max_inst_size) { |
| 1616 | IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", | 1625 | IWL_INFO |
