diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-05-17 13:57:43 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-05-17 13:57:43 -0400 |
commit | 6fe70aae0d128339febfabc073ba4c4a03de4f45 (patch) | |
tree | 711dff90df5ca4e07b5bddf11b2819e5cf2b7a93 /drivers/net/wireless/iwlwifi/iwl-agn.c | |
parent | 278554bd6579206921f5d8a523649a7a57f8850d (diff) | |
parent | 0c348d7c1422d59a86d6fb37b53d75788043e50b (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 556 |
1 files changed, 381 insertions, 175 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a672d3379cfd..dc747ad988b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -157,7 +157,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
157 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); | 157 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); |
158 | return ret; | 158 | return ret; |
159 | } | 159 | } |
160 | iwl_clear_ucode_stations(priv, false); | 160 | iwl_clear_ucode_stations(priv); |
161 | iwl_restore_stations(priv); | 161 | iwl_restore_stations(priv); |
162 | ret = iwl_restore_default_wep_keys(priv); | 162 | ret = iwl_restore_default_wep_keys(priv); |
163 | if (ret) { | 163 | if (ret) { |
@@ -189,7 +189,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
189 | } | 189 | } |
190 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); | 190 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); |
191 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 191 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
192 | iwl_clear_ucode_stations(priv, false); | 192 | iwl_clear_ucode_stations(priv); |
193 | iwl_restore_stations(priv); | 193 | iwl_restore_stations(priv); |
194 | ret = iwl_restore_default_wep_keys(priv); | 194 | ret = iwl_restore_default_wep_keys(priv); |
195 | if (ret) { | 195 | if (ret) { |
@@ -1506,9 +1506,13 @@ static void iwl_nic_start(struct iwl_priv *priv) | |||
1506 | iwl_write32(priv, CSR_RESET, 0); | 1506 | iwl_write32(priv, CSR_RESET, 0); |
1507 | } | 1507 | } |
1508 | 1508 | ||
1509 | struct iwlagn_ucode_capabilities { | ||
1510 | u32 max_probe_length; | ||
1511 | }; | ||
1509 | 1512 | ||
1510 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | 1513 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); |
1511 | static int iwl_mac_setup_register(struct iwl_priv *priv); | 1514 | static int iwl_mac_setup_register(struct iwl_priv *priv, |
1515 | struct iwlagn_ucode_capabilities *capa); | ||
1512 | 1516 | ||
1513 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | 1517 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) |
1514 | { | 1518 | { |
@@ -1535,6 +1539,199 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | |||
1535 | iwl_ucode_callback); | 1539 | iwl_ucode_callback); |
1536 | } | 1540 | } |
1537 | 1541 | ||
1542 | struct iwlagn_firmware_pieces { | ||
1543 | const void *inst, *data, *init, *init_data, *boot; | ||
1544 | size_t inst_size, data_size, init_size, init_data_size, boot_size; | ||
1545 | |||
1546 | u32 build; | ||
1547 | }; | ||
1548 | |||
1549 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, | ||
1550 | const struct firmware *ucode_raw, | ||
1551 | struct iwlagn_firmware_pieces *pieces) | ||
1552 | { | ||
1553 | struct iwl_ucode_header *ucode = (void *)ucode_raw->data; | ||
1554 | u32 api_ver, hdr_size; | ||
1555 | const u8 *src; | ||
1556 | |||
1557 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
1558 | api_ver = IWL_UCODE_API(priv->ucode_ver); | ||
1559 | |||
1560 | switch (api_ver) { | ||
1561 | default: | ||
1562 | /* | ||
1563 | * 4965 doesn't revision the firmware file format | ||
1564 | * along with the API version, it always uses v1 | ||
1565 | * file format. | ||
1566 | */ | ||
1567 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != | ||
1568 | CSR_HW_REV_TYPE_4965) { | ||
1569 | hdr_size = 28; | ||
1570 | if (ucode_raw->size < hdr_size) { | ||
1571 | IWL_ERR(priv, "File size too small!\n"); | ||
1572 | return -EINVAL; | ||
1573 | } | ||
1574 | pieces->build = le32_to_cpu(ucode->u.v2.build); | ||
1575 | pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); | ||
1576 | pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); | ||
1577 | pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); | ||
1578 | pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); | ||
1579 | pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size); | ||
1580 | src = ucode->u.v2.data; | ||
1581 | break; | ||
1582 | } | ||
1583 | /* fall through for 4965 */ | ||
1584 | case 0: | ||
1585 | case 1: | ||
1586 | case 2: | ||
1587 | hdr_size = 24; | ||
1588 | if (ucode_raw->size < hdr_size) { | ||
1589 | IWL_ERR(priv, "File size too small!\n"); | ||
1590 | return -EINVAL; | ||
1591 | } | ||
1592 | pieces->build = 0; | ||
1593 | pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); | ||
1594 | pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); | ||
1595 | pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); | ||
1596 | pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); | ||
1597 | pieces->boot_size = le32_to_cpu(ucode->u.v1.boot_size); | ||
1598 | src = ucode->u.v1.data; | ||
1599 | break; | ||
1600 | } | ||
1601 | |||
1602 | /* Verify size of file vs. image size info in file's header */ | ||
1603 | if (ucode_raw->size != hdr_size + pieces->inst_size + | ||
1604 | pieces->data_size + pieces->init_size + | ||
1605 | pieces->init_data_size + pieces->boot_size) { | ||
1606 | |||
1607 | IWL_ERR(priv, | ||
1608 | "uCode file size %d does not match expected size\n", | ||
1609 | (int)ucode_raw->size); | ||
1610 | return -EINVAL; | ||
1611 | } | ||
1612 | |||
1613 | pieces->inst = src; | ||
1614 | src += pieces->inst_size; | ||
1615 | pieces->data = src; | ||
1616 | src += pieces->data_size; | ||
1617 | pieces->init = src; | ||
1618 | src += pieces->init_size; | ||
1619 | pieces->init_data = src; | ||
1620 | src += pieces->init_data_size; | ||
1621 | pieces->boot = src; | ||
1622 | src += pieces->boot_size; | ||
1623 | |||
1624 | return 0; | ||
1625 | } | ||
1626 | |||
1627 | static int iwlagn_wanted_ucode_alternative = 1; | ||
1628 | |||
1629 | static int iwlagn_load_firmware(struct iwl_priv *priv, | ||
1630 | const struct firmware *ucode_raw, | ||
1631 | struct iwlagn_firmware_pieces *pieces, | ||
1632 | struct iwlagn_ucode_capabilities *capa) | ||
1633 | { | ||
1634 | struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; | ||
1635 | struct iwl_ucode_tlv *tlv; | ||
1636 | size_t len = ucode_raw->size; | ||
1637 | const u8 *data; | ||
1638 | int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; | ||
1639 | u64 alternatives; | ||
1640 | |||
1641 | if (len < sizeof(*ucode)) | ||
1642 | return -EINVAL; | ||
1643 | |||
1644 | if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) | ||
1645 | return -EINVAL; | ||
1646 | |||
1647 | /* | ||
1648 | * Check which alternatives are present, and "downgrade" | ||
1649 | * when the chosen alternative is not present, warning | ||
1650 | * the user when that happens. Some files may not have | ||
1651 | * any alternatives, so don't warn in that case. | ||
1652 | */ | ||
1653 | alternatives = le64_to_cpu(ucode->alternatives); | ||
1654 | tmp = wanted_alternative; | ||
1655 | if (wanted_alternative > 63) | ||
1656 | wanted_alternative = 63; | ||
1657 | while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) | ||
1658 | wanted_alternative--; | ||
1659 | if (wanted_alternative && wanted_alternative != tmp) | ||
1660 | IWL_WARN(priv, | ||
1661 | "uCode alternative %d not available, choosing %d\n", | ||
1662 | tmp, wanted_alternative); | ||
1663 | |||
1664 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
1665 | pieces->build = le32_to_cpu(ucode->build); | ||
1666 | data = ucode->data; | ||
1667 | |||
1668 | len -= sizeof(*ucode); | ||
1669 | |||
1670 | while (len >= sizeof(*tlv)) { | ||
1671 | u32 tlv_len; | ||
1672 | enum iwl_ucode_tlv_type tlv_type; | ||
1673 | u16 tlv_alt; | ||
1674 | const u8 *tlv_data; | ||
1675 | |||
1676 | len -= sizeof(*tlv); | ||
1677 | tlv = (void *)data; | ||
1678 | |||
1679 | tlv_len = le32_to_cpu(tlv->length); | ||
1680 | tlv_type = le16_to_cpu(tlv->type); | ||
1681 | tlv_alt = le16_to_cpu(tlv->alternative); | ||
1682 | tlv_data = tlv->data; | ||
1683 | |||
1684 | if (len < tlv_len) | ||
1685 | return -EINVAL; | ||
1686 | len -= ALIGN(tlv_len, 4); | ||
1687 | data += sizeof(*tlv) + ALIGN(tlv_len, 4); | ||
1688 | |||
1689 | /* | ||
1690 | * Alternative 0 is always valid. | ||
1691 | * | ||
1692 | * Skip alternative TLVs that are not selected. | ||
1693 | */ | ||
1694 | if (tlv_alt != 0 && tlv_alt != wanted_alternative) | ||
1695 | continue; | ||
1696 | |||
1697 | switch (tlv_type) { | ||
1698 | case IWL_UCODE_TLV_INST: | ||
1699 | pieces->inst = tlv_data; | ||
1700 | pieces->inst_size = tlv_len; | ||
1701 | break; | ||
1702 | case IWL_UCODE_TLV_DATA: | ||
1703 | pieces->data = tlv_data; | ||
1704 | pieces->data_size = tlv_len; | ||
1705 | break; | ||
1706 | case IWL_UCODE_TLV_INIT: | ||
1707 | pieces->init = tlv_data; | ||
1708 | pieces->init_size = tlv_len; | ||
1709 | break; | ||
1710 | case IWL_UCODE_TLV_INIT_DATA: | ||
1711 | pieces->init_data = tlv_data; | ||
1712 | pieces->init_data_size = tlv_len; | ||
1713 | break; | ||
1714 | case IWL_UCODE_TLV_BOOT: | ||
1715 | pieces->boot = tlv_data; | ||
1716 | pieces->boot_size = tlv_len; | ||
1717 | break; | ||
1718 | case IWL_UCODE_TLV_PROBE_MAX_LEN: | ||
1719 | if (tlv_len != 4) | ||
1720 | return -EINVAL; | ||
1721 | capa->max_probe_length = | ||
1722 | le32_to_cpup((__le32 *)tlv_data); | ||
1723 | break; | ||
1724 | default: | ||
1725 | break; | ||
1726 | } | ||
1727 | } | ||
1728 | |||
1729 | if (len) | ||
1730 | return -EINVAL; | ||
1731 | |||
1732 | return 0; | ||
1733 | } | ||
1734 | |||
1538 | /** | 1735 | /** |
1539 | * iwl_ucode_callback - callback when firmware was loaded | 1736 | * iwl_ucode_callback - callback when firmware was loaded |
1540 | * | 1737 | * |
@@ -1545,14 +1742,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1545 | { | 1742 | { |
1546 | struct iwl_priv *priv = context; | 1743 | struct iwl_priv *priv = context; |
1547 | struct iwl_ucode_header *ucode; | 1744 | struct iwl_ucode_header *ucode; |
1745 | int err; | ||
1746 | struct iwlagn_firmware_pieces pieces; | ||
1548 | const unsigned int api_max = priv->cfg->ucode_api_max; | 1747 | const unsigned int api_max = priv->cfg->ucode_api_max; |
1549 | const unsigned int api_min = priv->cfg->ucode_api_min; | 1748 | const unsigned int api_min = priv->cfg->ucode_api_min; |
1550 | u8 *src; | 1749 | u32 api_ver; |
1551 | size_t len; | 1750 | char buildstr[25]; |
1552 | u32 api_ver, build; | 1751 | u32 build; |
1553 | u32 inst_size, data_size, init_size, init_data_size, boot_size; | 1752 | struct iwlagn_ucode_capabilities ucode_capa = { |
1554 | int err; | 1753 | .max_probe_length = 200, |
1555 | u16 eeprom_ver; | 1754 | }; |
1755 | |||
1756 | memset(&pieces, 0, sizeof(pieces)); | ||
1556 | 1757 | ||
1557 | if (!ucode_raw) { | 1758 | if (!ucode_raw) { |
1558 | IWL_ERR(priv, "request for firmware file '%s' failed.\n", | 1759 | IWL_ERR(priv, "request for firmware file '%s' failed.\n", |
@@ -1563,8 +1764,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1563 | IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", | 1764 | IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", |
1564 | priv->firmware_name, ucode_raw->size); | 1765 | priv->firmware_name, ucode_raw->size); |
1565 | 1766 | ||
1566 | /* Make sure that we got at least the v1 header! */ | 1767 | /* Make sure that we got at least the API version number */ |
1567 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { | 1768 | if (ucode_raw->size < 4) { |
1568 | IWL_ERR(priv, "File size way too small!\n"); | 1769 | IWL_ERR(priv, "File size way too small!\n"); |
1569 | goto try_again; | 1770 | goto try_again; |
1570 | } | 1771 | } |
@@ -1572,21 +1773,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1572 | /* Data from ucode file: header followed by uCode images */ | 1773 | /* Data from ucode file: header followed by uCode images */ |
1573 | ucode = (struct iwl_ucode_header *)ucode_raw->data; | 1774 | ucode = (struct iwl_ucode_header *)ucode_raw->data; |
1574 | 1775 | ||
1575 | priv->ucode_ver = le32_to_cpu(ucode->ver); | 1776 | if (ucode->ver) |
1777 | err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); | ||
1778 | else | ||
1779 | err = iwlagn_load_firmware(priv, ucode_raw, &pieces, | ||
1780 | &ucode_capa); | ||
1781 | |||
1782 | if (err) | ||
1783 | goto try_again; | ||
1784 | |||
1576 | api_ver = IWL_UCODE_API(priv->ucode_ver); | 1785 | api_ver = IWL_UCODE_API(priv->ucode_ver); |
1577 | build = priv->cfg->ops->ucode->get_build(ucode, api_ver); | 1786 | build = pieces.build; |
1578 | inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); | ||
1579 | data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); | ||
1580 | init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); | ||
1581 | init_data_size = | ||
1582 | priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); | ||
1583 | boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); | ||
1584 | src = priv->cfg->ops->ucode->get_data(ucode, api_ver); | ||
1585 | |||
1586 | /* api_ver should match the api version forming part of the | ||
1587 | * firmware filename ... but we don't check for that and only rely | ||
1588 | * on the API version read from firmware header from here on forward */ | ||
1589 | 1787 | ||
1788 | /* | ||
1789 | * api_ver should match the api version forming part of the | ||
1790 | * firmware filename ... but we don't check for that and only rely | ||
1791 | * on the API version read from firmware header from here on forward | ||
1792 | */ | ||
1590 | if (api_ver < api_min || api_ver > api_max) { | 1793 | if (api_ver < api_min || api_ver > api_max) { |
1591 | IWL_ERR(priv, "Driver unable to support your firmware API. " | 1794 | IWL_ERR(priv, "Driver unable to support your firmware API. " |
1592 | "Driver supports v%u, firmware is v%u.\n", | 1795 | "Driver supports v%u, firmware is v%u.\n", |
@@ -1600,40 +1803,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1600 | "from http://www.intellinuxwireless.org.\n", | 1803 | "from http://www.intellinuxwireless.org.\n", |
1601 | api_max, api_ver); | 1804 | api_max, api_ver); |
1602 | 1805 | ||
1603 | IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n", | 1806 | if (build) |
1604 | IWL_UCODE_MAJOR(priv->ucode_ver), | 1807 | sprintf(buildstr, " build %u", build); |
1605 | IWL_UCODE_MINOR(priv->ucode_ver), | 1808 | else |
1606 | IWL_UCODE_API(priv->ucode_ver), | 1809 | buildstr[0] = '\0'; |
1607 | IWL_UCODE_SERIAL(priv->ucode_ver)); | 1810 | |
1811 | IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n", | ||
1812 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
1813 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
1814 | IWL_UCODE_API(priv->ucode_ver), | ||
1815 | IWL_UCODE_SERIAL(priv->ucode_ver), | ||
1816 | buildstr); | ||
1608 | 1817 | ||
1609 | snprintf(priv->hw->wiphy->fw_version, | 1818 | snprintf(priv->hw->wiphy->fw_version, |
1610 | sizeof(priv->hw->wiphy->fw_version), | 1819 | sizeof(priv->hw->wiphy->fw_version), |
1611 | "%u.%u.%u.%u", | 1820 | "%u.%u.%u.%u%s", |
1612 | IWL_UCODE_MAJOR(priv->ucode_ver), | 1821 | IWL_UCODE_MAJOR(priv->ucode_ver), |
1613 | IWL_UCODE_MINOR(priv->ucode_ver), | 1822 | IWL_UCODE_MINOR(priv->ucode_ver), |
1614 | IWL_UCODE_API(priv->ucode_ver), | 1823 | IWL_UCODE_API(priv->ucode_ver), |
1615 | IWL_UCODE_SERIAL(priv->ucode_ver)); | 1824 | IWL_UCODE_SERIAL(priv->ucode_ver), |
1616 | 1825 | buildstr); | |
1617 | if (build) | ||
1618 | IWL_DEBUG_INFO(priv, "Build %u\n", build); | ||
1619 | |||
1620 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
1621 | IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", | ||
1622 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
1623 | ? "OTP" : "EEPROM", eeprom_ver); | ||
1624 | |||
1625 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | ||
1626 | priv->ucode_ver); | ||
1627 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", | ||
1628 | inst_size); | ||
1629 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n", | ||
1630 | data_size); | ||
1631 | IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n", | ||
1632 | init_size); | ||
1633 | IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n", | ||
1634 | init_data_size); | ||
1635 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", | ||
1636 | boot_size); | ||
1637 | 1826 | ||
1638 | /* | 1827 | /* |
1639 | * For any of the failures below (before allocating pci memory) | 1828 | * For any of the failures below (before allocating pci memory) |
@@ -1641,43 +1830,47 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1641 | * user just got a corrupted version of the latest API. | 1830 | * user just got a corrupted version of the latest API. |
1642 | */ | 1831 | */ |
1643 | 1832 | ||
1644 | /* Verify size of file vs. image size info in file's header */ | 1833 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", |
1645 | if (ucode_raw->size != | 1834 | priv->ucode_ver); |
1646 | priv->cfg->ops->ucode->get_header_size(api_ver) + | 1835 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n", |
1647 | inst_size + data_size + init_size + | 1836 | pieces.inst_size); |
1648 | init_data_size + boot_size) { | 1837 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n", |
1649 | 1838 | pieces.data_size); | |
1650 | IWL_DEBUG_INFO(priv, | 1839 | IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n", |
1651 | "uCode file size %d does not match expected size\n", | 1840 | pieces.init_size); |
1652 | (int)ucode_raw->size); | 1841 | IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", |
1653 | goto try_again; | 1842 | pieces.init_data_size); |
1654 | } | 1843 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n", |
1844 | pieces.boot_size); | ||
1655 | 1845 | ||
1656 | /* Verify that uCode images will fit in card's SRAM */ | 1846 | /* Verify that uCode images will fit in card's SRAM */ |
1657 | if (inst_size > priv->hw_params.max_inst_size) { | 1847 | if (pieces.inst_size > priv->hw_params.max_inst_size) { |
1658 | IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", | 1848 | IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", |
1659 | inst_size); | 1849 | pieces.inst_size); |
1660 | goto try_again; | 1850 | goto try_again; |
1661 | } | 1851 | } |
1662 | 1852 | ||
1663 | if (data_size > priv->hw_params.max_data_size) { | 1853 | if (pieces.data_size > priv->hw_params.max_data_size) { |
1664 | IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", | 1854 | IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", |
1665 | data_size); | 1855 | pieces.data_size); |
1666 | goto try_again; | 1856 | goto try_again; |
1667 | } | 1857 | } |
1668 | if (init_size > priv->hw_params.max_inst_size) { | 1858 | |
1669 | IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", | 1859 | if (pieces.init_size > priv->hw_params.max_inst_size) { |
1670 | init_size); | 1860 | IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", |
1861 | pieces.init_size); | ||
1671 | goto try_again; | 1862 | goto try_again; |
1672 | } | 1863 | } |
1673 | if (init_data_size > priv->hw_params.max_data_size) { | 1864 | |
1674 | IWL_INFO(priv, "uCode init data len %d too large to fit in\n", | 1865 | if (pieces.init_data_size > priv->hw_params.max_data_size) { |
1675 | init_data_size); | 1866 | IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", |
1867 | pieces.init_data_size); | ||
1676 | goto try_again; | 1868 | goto try_again; |
1677 | } | 1869 | } |
1678 | if (boot_size > priv->hw_params.max_bsm_size) { | 1870 | |
1679 | IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", | 1871 | if (pieces.boot_size > priv->hw_params.max_bsm_size) { |
1680 | boot_size); | 1872 | IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n", |
1873 | pieces.boot_size); | ||
1681 | goto try_again; | 1874 | goto try_again; |
1682 | } | 1875 | } |
1683 | 1876 | ||
@@ -1686,13 +1879,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1686 | /* Runtime instructions and 2 copies of data: | 1879 | /* Runtime instructions and 2 copies of data: |
1687 | * 1) unmodified from disk | 1880 | * 1) unmodified from disk |
1688 | * 2) backup cache for save/restore during power-downs */ | 1881 | * 2) backup cache for save/restore during power-downs */ |
1689 | priv->ucode_code.len = inst_size; | 1882 | priv->ucode_code.len = pieces.inst_size; |
1690 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); | 1883 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); |
1691 | 1884 | ||
1692 | priv->ucode_data.len = data_size; | 1885 | priv->ucode_data.len = pieces.data_size; |
1693 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); | 1886 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); |
1694 | 1887 | ||
1695 | priv->ucode_data_backup.len = data_size; | 1888 | priv->ucode_data_backup.len = pieces.data_size; |
1696 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); | 1889 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); |
1697 | 1890 | ||
1698 | if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || | 1891 | if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || |
@@ -1700,11 +1893,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1700 | goto err_pci_alloc; | 1893 | goto err_pci_alloc; |
1701 | 1894 | ||
1702 | /* Initialization instructions and data */ | 1895 | /* Initialization instructions and data */ |
1703 | if (init_size && init_data_size) { | 1896 | if (pieces.init_size && pieces.init_data_size) { |
1704 | priv->ucode_init.len = init_size; | 1897 | priv->ucode_init.len = pieces.init_size; |
1705 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); | 1898 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); |
1706 | 1899 | ||
1707 | priv->ucode_init_data.len = init_data_size; | 1900 | priv->ucode_init_data.len = pieces.init_data_size; |
1708 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); | 1901 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); |
1709 | 1902 | ||
1710 | if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) | 1903 | if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) |
@@ -1712,8 +1905,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1712 | } | 1905 | } |
1713 | 1906 | ||
1714 | /* Bootstrap (instructions only, no data) */ | 1907 | /* Bootstrap (instructions only, no data) */ |
1715 | if (boot_size) { | 1908 | if (pieces.boot_size) { |
1716 | priv->ucode_boot.len = boot_size; | 1909 | priv->ucode_boot.len = pieces.boot_size; |
1717 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); | 1910 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); |
1718 | 1911 | ||
1719 | if (!priv->ucode_boot.v_addr) | 1912 | if (!priv->ucode_boot.v_addr) |
@@ -1723,51 +1916,48 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1723 | /* Copy images into buffers for card's bus-master reads ... */ | 1916 | /* Copy images into buffers for card's bus-master reads ... */ |
1724 | 1917 | ||
1725 | /* Runtime instructions (first block of data in file) */ | 1918 | /* Runtime instructions (first block of data in file) */ |
1726 | len = inst_size; | 1919 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", |
1727 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); | 1920 | pieces.inst_size); |
1728 | memcpy(priv->ucode_code.v_addr, src, len); | 1921 | memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size); |
1729 | src += len; | ||
1730 | 1922 | ||
1731 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", | 1923 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", |
1732 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); | 1924 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); |
1733 | 1925 | ||
1734 | /* Runtime data (2nd block) | 1926 | /* |
1735 | * NOTE: Copy into backup buffer will be done in iwl_up() */ | 1927 | * Runtime data |
1736 | len = data_size; | 1928 | * NOTE: Copy into backup buffer will be done in iwl_up() |
1737 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); | 1929 | */ |
1738 | memcpy(priv->ucode_data.v_addr, src, len); | 1930 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", |
1739 | memcpy(priv->ucode_data_backup.v_addr, src, len); | 1931 | pieces.data_size); |
1740 | src += len; | 1932 | memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size); |
1741 | 1933 | memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size); | |
1742 | /* Initialization instructions (3rd block) */ | 1934 | |
1743 | if (init_size) { | 1935 | /* Initialization instructions */ |
1744 | len = init_size; | 1936 | if (pieces.init_size) { |
1745 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", | 1937 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", |
1746 | len); | 1938 | pieces.init_size); |
1747 | memcpy(priv->ucode_init.v_addr, src, len); | 1939 | memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size); |
1748 | src += len; | ||
1749 | } | 1940 | } |
1750 | 1941 | ||
1751 | /* Initialization data (4th block) */ | 1942 | /* Initialization data */ |
1752 | if (init_data_size) { | 1943 | if (pieces.init_data_size) { |
1753 | len = init_data_size; | ||
1754 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", | 1944 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", |
1755 | len); | 1945 | pieces.init_data_size); |
1756 | memcpy(priv->ucode_init_data.v_addr, src, len); | 1946 | memcpy(priv->ucode_init_data.v_addr, pieces.init_data, |
1757 | src += len; | 1947 | pieces.init_data_size); |
1758 | } | 1948 | } |
1759 | 1949 | ||
1760 | /* Bootstrap instructions (5th block) */ | 1950 | /* Bootstrap instructions */ |
1761 | len = boot_size; | 1951 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", |
1762 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); | 1952 | pieces.boot_size); |
1763 | memcpy(priv->ucode_boot.v_addr, src, len); | 1953 | memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size); |
1764 | 1954 | ||
1765 | /************************************************** | 1955 | /************************************************** |
1766 | * This is still part of probe() in a sense... | 1956 | * This is still part of probe() in a sense... |
1767 | * | 1957 | * |
1768 | * 9. Setup and register with mac80211 and debugfs | 1958 | * 9. Setup and register with mac80211 and debugfs |
1769 | **************************************************/ | 1959 | **************************************************/ |
1770 | err = iwl_mac_setup_register(priv); | 1960 | err = iwl_mac_setup_register(priv, &ucode_capa); |
1771 | if (err) | 1961 | if (err) |
1772 | goto out_unbind; | 1962 | goto out_unbind; |
1773 | 1963 | ||
@@ -1777,6 +1967,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1777 | 1967 | ||
1778 | /* We have our copies now, allow OS release its copies */ | 1968 | /* We have our copies now, allow OS release its copies */ |
1779 | release_firmware(ucode_raw); | 1969 | release_firmware(ucode_raw); |
1970 | complete(&priv->_agn.firmware_loading_complete); | ||
1780 | return; | 1971 | return; |
1781 | 1972 | ||
1782 | try_again: | 1973 | try_again: |
@@ -1790,6 +1981,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1790 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 1981 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
1791 | iwl_dealloc_ucode_pci(priv); | 1982 | iwl_dealloc_ucode_pci(priv); |
1792 | out_unbind: | 1983 | out_unbind: |
1984 | complete(&priv->_agn.firmware_loading_complete); | ||
1793 | device_release_driver(&priv->pci_dev->dev); | 1985 | device_release_driver(&priv->pci_dev->dev); |
1794 | release_firmware(ucode_raw); | 1986 | release_firmware(ucode_raw); |
1795 | } | 1987 | } |
@@ -2165,7 +2357,7 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2165 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2357 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2166 | } else { | 2358 | } else { |
2167 | /* Initialize our rx_config data */ | 2359 | /* Initialize our rx_config data */ |
2168 | iwl_connection_init_rx_config(priv, priv->iw_mode); | 2360 | iwl_connection_init_rx_config(priv, NULL); |
2169 | 2361 | ||
2170 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2362 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2171 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2363 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
@@ -2212,7 +2404,9 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2212 | if (!exit_pending) | 2404 | if (!exit_pending) |
2213 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2405 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2214 | 2406 | ||
2215 | iwl_clear_ucode_stations(priv, true); | 2407 | iwl_clear_ucode_stations(priv); |
2408 | iwl_dealloc_bcast_station(priv); | ||
2409 | iwl_clear_driver_stations(priv); | ||
2216 | 2410 | ||
2217 | /* Unblock any waiting calls */ | 2411 | /* Unblock any waiting calls */ |
2218 | wake_up_interruptible_all(&priv->wait_command_queue); | 2412 | wake_up_interruptible_all(&priv->wait_command_queue); |
@@ -2359,6 +2553,10 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2359 | return -EIO; | 2553 | return -EIO; |
2360 | } | 2554 | } |
2361 | 2555 | ||
2556 | ret = iwl_alloc_bcast_station(priv, true); | ||
2557 | if (ret) | ||
2558 | return ret; | ||
2559 | |||
2362 | iwl_prepare_card_hw(priv); | 2560 | iwl_prepare_card_hw(priv); |
2363 | 2561 | ||
2364 | if (!priv->hw_ready) { | 2562 | if (!priv->hw_ready) { |
@@ -2538,12 +2736,15 @@ static void iwl_bg_rx_replenish(struct work_struct *data) | |||
2538 | 2736 | ||
2539 | #define IWL_DELAY_NEXT_SCAN (HZ*2) | 2737 | #define IWL_DELAY_NEXT_SCAN (HZ*2) |
2540 | 2738 | ||
2541 | void iwl_post_associate(struct iwl_priv *priv) | 2739 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2542 | { | 2740 | { |
2543 | struct ieee80211_conf *conf = NULL; | 2741 | struct ieee80211_conf *conf = NULL; |
2544 | int ret = 0; | 2742 | int ret = 0; |
2545 | 2743 | ||
2546 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | 2744 | if (!vif || !priv->is_open) |
2745 | return; | ||
2746 | |||
2747 | if (vif->type == NL80211_IFTYPE_AP) { | ||
2547 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | 2748 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); |
2548 | return; | 2749 | return; |
2549 | } | 2750 | } |
@@ -2551,10 +2752,6 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2551 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2752 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2552 | return; | 2753 | return; |
2553 | 2754 | ||
2554 | |||
2555 | if (!priv->vif || !priv->is_open) | ||
2556 | return; | ||
2557 | |||
2558 | iwl_scan_cancel_timeout(priv, 200); | 2755 | iwl_scan_cancel_timeout(priv, 200); |
2559 | 2756 | ||
2560 | conf = ieee80211_get_hw_conf(priv->hw); | 2757 | conf = ieee80211_get_hw_conf(priv->hw); |
@@ -2562,7 +2759,7 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2562 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2759 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2563 | iwlcore_commit_rxon(priv); | 2760 | iwlcore_commit_rxon(priv); |
2564 | 2761 | ||
2565 | iwl_setup_rxon_timing(priv); | 2762 | iwl_setup_rxon_timing(priv, vif); |
2566 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 2763 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, |
2567 | sizeof(priv->rxon_timing), &priv->rxon_timing); | 2764 | sizeof(priv->rxon_timing), &priv->rxon_timing); |
2568 | if (ret) | 2765 | if (ret) |
@@ -2576,49 +2773,41 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2576 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2773 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2577 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2774 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2578 | 2775 | ||
2579 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 2776 | priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); |
2580 | 2777 | ||
2581 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 2778 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
2582 | priv->assoc_id, priv->beacon_int); | 2779 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
2583 | 2780 | ||
2584 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 2781 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) |
2585 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 2782 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2586 | else | 2783 | else |
2587 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 2784 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2588 | 2785 | ||
2589 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 2786 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2590 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 2787 | if (vif->bss_conf.assoc_capability & |
2788 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
2591 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 2789 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2592 | else | 2790 | else |
2593 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2791 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2594 | 2792 | ||
2595 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 2793 | if (vif->type == NL80211_IFTYPE_ADHOC) |
2596 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2794 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2597 | |||
2598 | } | 2795 | } |
2599 | 2796 | ||
2600 | iwlcore_commit_rxon(priv); | 2797 | iwlcore_commit_rxon(priv); |
2601 | 2798 | ||
2602 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | 2799 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", |
2603 | priv->assoc_id, priv->active_rxon.bssid_addr); | 2800 | vif->bss_conf.aid, priv->active_rxon.bssid_addr); |
2604 | 2801 | ||
2605 | switch (priv->iw_mode) { | 2802 | switch (vif->type) { |
2606 | case NL80211_IFTYPE_STATION: | 2803 | case NL80211_IFTYPE_STATION: |
2607 | break; | 2804 | break; |
2608 | |||
2609 | case NL80211_IFTYPE_ADHOC: | 2805 | case NL80211_IFTYPE_ADHOC: |
2610 | |||
2611 | /* assume default assoc id */ | ||
2612 | priv->assoc_id = 1; | ||
2613 | |||
2614 | iwl_add_local_station(priv, priv->bssid, true); | ||
2615 | iwl_send_beacon_cmd(priv); | 2806 | iwl_send_beacon_cmd(priv); |
2616 | |||
2617 | break; | 2807 | break; |
2618 | |||
2619 | default: | 2808 | default: |
2620 | IWL_ERR(priv, "%s Should not be called in %d mode\n", | 2809 | IWL_ERR(priv, "%s Should not be called in %d mode\n", |
2621 | __func__, priv->iw_mode); | 2810 | __func__, vif->type); |
2622 | break; | 2811 | break; |
2623 | } | 2812 | } |
2624 | 2813 | ||
@@ -2646,7 +2835,8 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2646 | * Not a mac80211 entry point function, but it fits in with all the | 2835 | * Not a mac80211 entry point function, but it fits in with all the |
2647 | * other mac80211 functions grouped here. | 2836 | * other mac80211 functions grouped here. |
2648 | */ | 2837 | */ |
2649 | static int iwl_mac_setup_register(struct iwl_priv *priv) | 2838 | static int iwl_mac_setup_register(struct iwl_priv *priv, |
2839 | struct iwlagn_ucode_capabilities *capa) | ||
2650 | { | 2840 | { |
2651 | int ret; | 2841 | int ret; |
2652 | struct ieee80211_hw *hw = priv->hw; | 2842 | struct ieee80211_hw *hw = priv->hw; |
@@ -2666,6 +2856,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) | |||
2666 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 2856 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
2667 | 2857 | ||
2668 | hw->sta_data_size = sizeof(struct iwl_station_priv); | 2858 | hw->sta_data_size = sizeof(struct iwl_station_priv); |
2859 | hw->vif_data_size = sizeof(struct iwl_vif_priv); | ||
2860 | |||
2669 | hw->wiphy->interface_modes = | 2861 | hw->wiphy->interface_modes = |
2670 | BIT(NL80211_IFTYPE_STATION) | | 2862 | BIT(NL80211_IFTYPE_STATION) | |
2671 | BIT(NL80211_IFTYPE_ADHOC); | 2863 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2681,7 +2873,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) | |||
2681 | 2873 | ||
2682 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 2874 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
2683 | /* we create the 802.11 header and a zero-length SSID element */ | 2875 | /* we create the 802.11 header and a zero-length SSID element */ |
2684 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | 2876 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; |
2685 | 2877 | ||
2686 | /* Default value; 4 EDCA QOS priorities */ | 2878 | /* Default value; 4 EDCA QOS priorities */ |
2687 | hw->queues = 4; | 2879 | hw->queues = 4; |
@@ -2794,7 +2986,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2794 | return NETDEV_TX_OK; | 2986 | return NETDEV_TX_OK; |
2795 | } | 2987 | } |
2796 | 2988 | ||
2797 | void iwl_config_ap(struct iwl_priv *priv) | 2989 | void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2798 | { | 2990 | { |
2799 | int ret = 0; | 2991 | int ret = 0; |
2800 | 2992 | ||
@@ -2809,7 +3001,7 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2809 | iwlcore_commit_rxon(priv); | 3001 | iwlcore_commit_rxon(priv); |
2810 | 3002 | ||
2811 | /* RXON Timing */ | 3003 | /* RXON Timing */ |
2812 | iwl_setup_rxon_timing(priv); | 3004 | iwl_setup_rxon_timing(priv, vif); |
2813 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 3005 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, |
2814 | sizeof(priv->rxon_timing), &priv->rxon_timing); | 3006 | sizeof(priv->rxon_timing), &priv->rxon_timing); |
2815 | if (ret) | 3007 | if (ret) |
@@ -2823,9 +3015,10 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2823 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3015 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2824 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 3016 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2825 | 3017 | ||
2826 | /* FIXME: what should be the assoc_id for AP? */ | 3018 | priv->staging_rxon.assoc_id = 0; |
2827 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 3019 | |
2828 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3020 | if (vif->bss_conf.assoc_capability & |
3021 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
2829 | priv->staging_rxon.flags |= | 3022 | priv->staging_rxon.flags |= |
2830 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3023 | RXON_FLG_SHORT_PREAMBLE_MSK; |
2831 | else | 3024 | else |
@@ -2833,22 +3026,21 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2833 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3026 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2834 | 3027 | ||
2835 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3028 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2836 | if (priv->assoc_capability & | 3029 | if (vif->bss_conf.assoc_capability & |
2837 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | 3030 | WLAN_CAPABILITY_SHORT_SLOT_TIME) |
2838 | priv->staging_rxon.flags |= | 3031 | priv->staging_rxon.flags |= |
2839 | RXON_FLG_SHORT_SLOT_MSK; | 3032 | RXON_FLG_SHORT_SLOT_MSK; |
2840 | else | 3033 | else |
2841 | priv->staging_rxon.flags &= | 3034 | priv->staging_rxon.flags &= |
2842 | ~RXON_FLG_SHORT_SLOT_MSK; | 3035 | ~RXON_FLG_SHORT_SLOT_MSK; |
2843 | 3036 | ||
2844 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 3037 | if (vif->type == NL80211_IFTYPE_ADHOC) |
2845 | priv->staging_rxon.flags &= | 3038 | priv->staging_rxon.flags &= |
2846 | ~RXON_FLG_SHORT_SLOT_MSK; | 3039 | ~RXON_FLG_SHORT_SLOT_MSK; |
2847 | } | 3040 | } |
2848 | /* restore RXON assoc */ | 3041 | /* restore RXON assoc */ |
2849 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3042 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2850 | iwlcore_commit_rxon(priv); | 3043 | iwlcore_commit_rxon(priv); |
2851 | iwl_add_bcast_station(priv); | ||
2852 | } | 3044 | } |
2853 | iwl_send_beacon_cmd(priv); | 3045 | iwl_send_beacon_cmd(priv); |
2854 | 3046 | ||
@@ -2867,8 +3059,7 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
2867 | struct iwl_priv *priv = hw->priv; | 3059 | struct iwl_priv *priv = hw->priv; |
2868 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 3060 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2869 | 3061 | ||
2870 | iwl_update_tkip_key(priv, keyconf, | 3062 | iwl_update_tkip_key(priv, keyconf, sta, |
2871 | sta ? sta->addr : iwl_bcast_addr, | ||
2872 | iv32, phase1key); | 3063 | iv32, phase1key); |
2873 | 3064 | ||
2874 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3065 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -2880,7 +3071,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2880 | struct ieee80211_key_conf *key) | 3071 | struct ieee80211_key_conf *key) |
2881 | { | 3072 | { |
2882 | struct iwl_priv *priv = hw->priv; | 3073 | struct iwl_priv *priv = hw->priv; |
2883 | const u8 *addr; | ||
2884 | int ret; | 3074 | int ret; |
2885 | u8 sta_id; | 3075 | u8 sta_id; |
2886 | bool is_default_wep_key = false; | 3076 | bool is_default_wep_key = false; |
@@ -2891,13 +3081,17 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2891 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); | 3081 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); |
2892 | return -EOPNOTSUPP; | 3082 | return -EOPNOTSUPP; |
2893 | } | 3083 | } |
2894 | addr = sta ? sta->addr : iwl_bcast_addr; | ||
2895 | sta_id = iwl_find_station(priv, addr); | ||
2896 | if (sta_id == IWL_INVALID_STATION) { | ||
2897 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
2898 | addr); | ||
2899 | return -EINVAL; | ||
2900 | 3084 | ||
3085 | if (sta) { | ||
3086 | sta_id = iwl_sta_id(sta); | ||
3087 | |||
3088 | if (sta_id == IWL_INVALID_STATION) { | ||
3089 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
3090 | sta->addr); | ||
3091 | return -EINVAL; | ||
3092 | } | ||
3093 | } else { | ||
3094 | sta_id = priv->hw_params.bcast_sta_id; | ||
2901 | } | 3095 | } |
2902 | 3096 | ||
2903 | mutex_lock(&priv->mutex); | 3097 | mutex_lock(&priv->mutex); |
@@ -2946,8 +3140,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2946 | 3140 | ||
2947 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | 3141 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, |
2948 | struct ieee80211_vif *vif, | 3142 | struct ieee80211_vif *vif, |
2949 | enum ieee80211_ampdu_mlme_action action, | 3143 | enum ieee80211_ampdu_mlme_action action, |
2950 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 3144 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2951 | { | 3145 | { |
2952 | struct iwl_priv *priv = hw->priv; | 3146 | struct iwl_priv *priv = hw->priv; |
2953 | int ret; | 3147 | int ret; |
@@ -2961,17 +3155,17 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2961 | switch (action) { | 3155 | switch (action) { |
2962 | case IEEE80211_AMPDU_RX_START: | 3156 | case IEEE80211_AMPDU_RX_START: |
2963 | IWL_DEBUG_HT(priv, "start Rx\n"); | 3157 | IWL_DEBUG_HT(priv, "start Rx\n"); |
2964 | return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); | 3158 | return iwl_sta_rx_agg_start(priv, sta, tid, *ssn); |
2965 | case IEEE80211_AMPDU_RX_STOP: | 3159 | case IEEE80211_AMPDU_RX_STOP: |
2966 | IWL_DEBUG_HT(priv, "stop Rx\n"); | 3160 | IWL_DEBUG_HT(priv, "stop Rx\n"); |
2967 | ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid); | 3161 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); |
2968 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3162 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2969 | return 0; | 3163 | return 0; |
2970 | else | 3164 | else |
2971 | return ret; | 3165 | return ret; |
2972 | case IEEE80211_AMPDU_TX_START: | 3166 | case IEEE80211_AMPDU_TX_START: |
2973 | IWL_DEBUG_HT(priv, "start Tx\n"); | 3167 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2974 | ret = iwlagn_tx_agg_start(priv, sta->addr, tid, ssn); | 3168 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); |
2975 | if (ret == 0) { | 3169 | if (ret == 0) { |
2976 | priv->_agn.agg_tids_count++; | 3170 | priv->_agn.agg_tids_count++; |
2977 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | 3171 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", |
@@ -2980,7 +3174,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2980 | return ret; | 3174 | return ret; |
2981 | case IEEE80211_AMPDU_TX_STOP: | 3175 | case IEEE80211_AMPDU_TX_STOP: |
2982 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 3176 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2983 | ret = iwlagn_tx_agg_stop(priv, sta->addr, tid); | 3177 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); |
2984 | if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { | 3178 | if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { |
2985 | priv->_agn.agg_tids_count--; | 3179 | priv->_agn.agg_tids_count--; |
2986 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | 3180 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", |
@@ -3022,7 +3216,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
3022 | if (!sta_priv->asleep) | 3216 | if (!sta_priv->asleep) |
3023 | break; | 3217 | break; |
3024 | sta_priv->asleep = false; | 3218 | sta_priv->asleep = false; |
3025 | sta_id = iwl_find_station(priv, sta->addr); | 3219 | sta_id = iwl_sta_id(sta); |
3026 | if (sta_id != IWL_INVALID_STATION) | 3220 | if (sta_id != IWL_INVALID_STATION) |
3027 | iwl_sta_modify_ps_wake(priv, sta_id); | 3221 | iwl_sta_modify_ps_wake(priv, sta_id); |
3028 | break; | 3222 | break; |
@@ -3037,10 +3231,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3037 | { | 3231 | { |
3038 | struct iwl_priv *priv = hw->priv; | 3232 | struct iwl_priv *priv = hw->priv; |
3039 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 3233 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
3040 | bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; | 3234 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; |
3041 | int ret; | 3235 | int ret; |
3042 | u8 sta_id; | 3236 | u8 sta_id; |
3043 | 3237 | ||
3238 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3239 | |||
3044 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | 3240 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", |
3045 | sta->addr); | 3241 | sta->addr); |
3046 | 3242 | ||
@@ -3057,12 +3253,14 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3057 | return ret; | 3253 | return ret; |
3058 | } | 3254 | } |
3059 | 3255 | ||
3256 | sta_priv->common.sta_id = sta_id; | ||
3257 | |||
3060 | /* Initialize rate scaling */ | 3258 | /* Initialize rate scaling */ |
3061 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | 3259 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", |
3062 | sta->addr); | 3260 | sta->addr); |
3063 | iwl_rs_rate_init(priv, sta, sta_id); | 3261 | iwl_rs_rate_init(priv, sta, sta_id); |
3064 | 3262 | ||
3065 | return ret; | 3263 | return 0; |
3066 | } | 3264 | } |
3067 | 3265 | ||
3068 | /***************************************************************************** | 3266 | /***************************************************************************** |
@@ -3587,6 +3785,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3587 | iwl_power_initialize(priv); | 3785 | iwl_power_initialize(priv); |
3588 | iwl_tt_initialize(priv); | 3786 | iwl_tt_initialize(priv); |
3589 | 3787 | ||
3788 | init_completion(&priv->_agn.firmware_loading_complete); | ||
3789 | |||
3590 | err = iwl_request_firmware(priv, true); | 3790 | err = iwl_request_firmware(priv, true); |
3591 | if (err) | 3791 | if (err) |
3592 | goto out_remove_sysfs; | 3792 | goto out_remove_sysfs; |
@@ -3627,6 +3827,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3627 | if (!priv) | 3827 | if (!priv) |
3628 | return; | 3828 | return; |
3629 | 3829 | ||
3830 | wait_for_completion(&priv->_agn.firmware_loading_complete); | ||
3831 | |||
3630 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); | 3832 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); |
3631 | 3833 | ||
3632 | iwl_dbgfs_unregister(priv); | 3834 | iwl_dbgfs_unregister(priv); |
@@ -3784,11 +3986,10 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
3784 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, | 3986 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, |
3785 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | 3987 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, |
3786 | 3988 | ||
3787 | /* 6x00 Series Gen2 */ | 3989 | /* 6x00 Series Gen2a */ |
3788 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2_2agn_cfg)}, | 3990 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, |
3789 | {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2_2agn_cfg)}, | 3991 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, |
3790 | {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2_2agn_cfg)}, | 3992 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, |
3791 | {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2_2agn_cfg)}, | ||
3792 | 3993 | ||
3793 | /* 6x50 WiFi/WiMax Series */ | 3994 | /* 6x50 WiFi/WiMax Series */ |
3794 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 3995 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
@@ -3901,3 +4102,8 @@ MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | |||
3901 | module_param_named( | 4102 | module_param_named( |
3902 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); | 4103 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); |
3903 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 4104 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
4105 | |||
4106 | module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, | ||
4107 | S_IRUGO); | ||
4108 | MODULE_PARM_DESC(ucode_alternative, | ||
4109 | "specify ucode alternative to use from ucode file"); | ||