diff options
author | David S. Miller <davem@davemloft.net> | 2010-05-18 00:09:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-18 00:09:11 -0400 |
commit | 820ae8a80eb59962aefbbd4908dfe144ec0f9edb (patch) | |
tree | 6c0f7356afff14e1c7d266de644810cd2de7caa9 /drivers/net/wireless/iwlwifi/iwl-agn.c | |
parent | 380fefb2ddabd4cd5f14dbe090481f0544e65078 (diff) | |
parent | 6fe70aae0d128339febfabc073ba4c4a03de4f45 (diff) |
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
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 cc15e929a987..aef4f71f1981 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) { |
@@ -2537,12 +2735,15 @@ static void iwl_bg_rx_replenish(struct work_struct *data) | |||
2537 | 2735 | ||
2538 | #define IWL_DELAY_NEXT_SCAN (HZ*2) | 2736 | #define IWL_DELAY_NEXT_SCAN (HZ*2) |
2539 | 2737 | ||
2540 | void iwl_post_associate(struct iwl_priv *priv) | 2738 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2541 | { | 2739 | { |
2542 | struct ieee80211_conf *conf = NULL; | 2740 | struct ieee80211_conf *conf = NULL; |
2543 | int ret = 0; | 2741 | int ret = 0; |
2544 | 2742 | ||
2545 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | 2743 | if (!vif || !priv->is_open) |
2744 | return; | ||
2745 | |||
2746 | if (vif->type == NL80211_IFTYPE_AP) { | ||
2546 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | 2747 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); |
2547 | return; | 2748 | return; |
2548 | } | 2749 | } |
@@ -2550,10 +2751,6 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2550 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2751 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2551 | return; | 2752 | return; |
2552 | 2753 | ||
2553 | |||
2554 | if (!priv->vif || !priv->is_open) | ||
2555 | return; | ||
2556 | |||
2557 | iwl_scan_cancel_timeout(priv, 200); | 2754 | iwl_scan_cancel_timeout(priv, 200); |
2558 | 2755 | ||
2559 | conf = ieee80211_get_hw_conf(priv->hw); | 2756 | conf = ieee80211_get_hw_conf(priv->hw); |
@@ -2561,7 +2758,7 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2561 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2758 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2562 | iwlcore_commit_rxon(priv); | 2759 | iwlcore_commit_rxon(priv); |
2563 | 2760 | ||
2564 | iwl_setup_rxon_timing(priv); | 2761 | iwl_setup_rxon_timing(priv, vif); |
2565 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 2762 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, |
2566 | sizeof(priv->rxon_timing), &priv->rxon_timing); | 2763 | sizeof(priv->rxon_timing), &priv->rxon_timing); |
2567 | if (ret) | 2764 | if (ret) |
@@ -2575,49 +2772,41 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2575 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2772 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2576 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2773 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2577 | 2774 | ||
2578 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 2775 | priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); |
2579 | 2776 | ||
2580 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 2777 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
2581 | priv->assoc_id, priv->beacon_int); | 2778 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
2582 | 2779 | ||
2583 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 2780 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) |
2584 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 2781 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2585 | else | 2782 | else |
2586 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 2783 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2587 | 2784 | ||
2588 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 2785 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2589 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 2786 | if (vif->bss_conf.assoc_capability & |
2787 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
2590 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 2788 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2591 | else | 2789 | else |
2592 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2790 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2593 | 2791 | ||
2594 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 2792 | if (vif->type == NL80211_IFTYPE_ADHOC) |
2595 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2793 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2596 | |||
2597 | } | 2794 | } |
2598 | 2795 | ||
2599 | iwlcore_commit_rxon(priv); | 2796 | iwlcore_commit_rxon(priv); |
2600 | 2797 | ||
2601 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | 2798 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", |
2602 | priv->assoc_id, priv->active_rxon.bssid_addr); | 2799 | vif->bss_conf.aid, priv->active_rxon.bssid_addr); |
2603 | 2800 | ||
2604 | switch (priv->iw_mode) { | 2801 | switch (vif->type) { |
2605 | case NL80211_IFTYPE_STATION: | 2802 | case NL80211_IFTYPE_STATION: |
2606 | break; | 2803 | break; |
2607 | |||
2608 | case NL80211_IFTYPE_ADHOC: | 2804 | case NL80211_IFTYPE_ADHOC: |
2609 | |||
2610 | /* assume default assoc id */ | ||
2611 | priv->assoc_id = 1; | ||
2612 | |||
2613 | iwl_add_local_station(priv, priv->bssid, true); | ||
2614 | iwl_send_beacon_cmd(priv); | 2805 | iwl_send_beacon_cmd(priv); |
2615 | |||
2616 | break; | 2806 | break; |
2617 | |||
2618 | default: | 2807 | default: |
2619 | IWL_ERR(priv, "%s Should not be called in %d mode\n", | 2808 | IWL_ERR(priv, "%s Should not be called in %d mode\n", |
2620 | __func__, priv->iw_mode); | 2809 | __func__, vif->type); |
2621 | break; | 2810 | break; |
2622 | } | 2811 | } |
2623 | 2812 | ||
@@ -2645,7 +2834,8 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2645 | * Not a mac80211 entry point function, but it fits in with all the | 2834 | * Not a mac80211 entry point function, but it fits in with all the |
2646 | * other mac80211 functions grouped here. | 2835 | * other mac80211 functions grouped here. |
2647 | */ | 2836 | */ |
2648 | static int iwl_mac_setup_register(struct iwl_priv *priv) | 2837 | static int iwl_mac_setup_register(struct iwl_priv *priv, |
2838 | struct iwlagn_ucode_capabilities *capa) | ||
2649 | { | 2839 | { |
2650 | int ret; | 2840 | int ret; |
2651 | struct ieee80211_hw *hw = priv->hw; | 2841 | struct ieee80211_hw *hw = priv->hw; |
@@ -2665,6 +2855,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) | |||
2665 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 2855 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
2666 | 2856 | ||
2667 | hw->sta_data_size = sizeof(struct iwl_station_priv); | 2857 | hw->sta_data_size = sizeof(struct iwl_station_priv); |
2858 | hw->vif_data_size = sizeof(struct iwl_vif_priv); | ||
2859 | |||
2668 | hw->wiphy->interface_modes = | 2860 | hw->wiphy->interface_modes = |
2669 | BIT(NL80211_IFTYPE_STATION) | | 2861 | BIT(NL80211_IFTYPE_STATION) | |
2670 | BIT(NL80211_IFTYPE_ADHOC); | 2862 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2680,7 +2872,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) | |||
2680 | 2872 | ||
2681 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 2873 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
2682 | /* we create the 802.11 header and a zero-length SSID element */ | 2874 | /* we create the 802.11 header and a zero-length SSID element */ |
2683 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | 2875 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; |
2684 | 2876 | ||
2685 | /* Default value; 4 EDCA QOS priorities */ | 2877 | /* Default value; 4 EDCA QOS priorities */ |
2686 | hw->queues = 4; | 2878 | hw->queues = 4; |
@@ -2793,7 +2985,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2793 | return NETDEV_TX_OK; | 2985 | return NETDEV_TX_OK; |
2794 | } | 2986 | } |
2795 | 2987 | ||
2796 | void iwl_config_ap(struct iwl_priv *priv) | 2988 | void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2797 | { | 2989 | { |
2798 | int ret = 0; | 2990 | int ret = 0; |
2799 | 2991 | ||
@@ -2808,7 +3000,7 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2808 | iwlcore_commit_rxon(priv); | 3000 | iwlcore_commit_rxon(priv); |
2809 | 3001 | ||
2810 | /* RXON Timing */ | 3002 | /* RXON Timing */ |
2811 | iwl_setup_rxon_timing(priv); | 3003 | iwl_setup_rxon_timing(priv, vif); |
2812 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 3004 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, |
2813 | sizeof(priv->rxon_timing), &priv->rxon_timing); | 3005 | sizeof(priv->rxon_timing), &priv->rxon_timing); |
2814 | if (ret) | 3006 | if (ret) |
@@ -2822,9 +3014,10 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2822 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3014 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2823 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 3015 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2824 | 3016 | ||
2825 | /* FIXME: what should be the assoc_id for AP? */ | 3017 | priv->staging_rxon.assoc_id = 0; |
2826 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 3018 | |
2827 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3019 | if (vif->bss_conf.assoc_capability & |
3020 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
2828 | priv->staging_rxon.flags |= | 3021 | priv->staging_rxon.flags |= |
2829 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3022 | RXON_FLG_SHORT_PREAMBLE_MSK; |
2830 | else | 3023 | else |
@@ -2832,22 +3025,21 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2832 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3025 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2833 | 3026 | ||
2834 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3027 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2835 | if (priv->assoc_capability & | 3028 | if (vif->bss_conf.assoc_capability & |
2836 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | 3029 | WLAN_CAPABILITY_SHORT_SLOT_TIME) |
2837 | priv->staging_rxon.flags |= | 3030 | priv->staging_rxon.flags |= |
2838 | RXON_FLG_SHORT_SLOT_MSK; | 3031 | RXON_FLG_SHORT_SLOT_MSK; |
2839 | else | 3032 | else |
2840 | priv->staging_rxon.flags &= | 3033 | priv->staging_rxon.flags &= |
2841 | ~RXON_FLG_SHORT_SLOT_MSK; | 3034 | ~RXON_FLG_SHORT_SLOT_MSK; |
2842 | 3035 | ||
2843 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 3036 | if (vif->type == NL80211_IFTYPE_ADHOC) |
2844 | priv->staging_rxon.flags &= | 3037 | priv->staging_rxon.flags &= |
2845 | ~RXON_FLG_SHORT_SLOT_MSK; | 3038 | ~RXON_FLG_SHORT_SLOT_MSK; |
2846 | } | 3039 | } |
2847 | /* restore RXON assoc */ | 3040 | /* restore RXON assoc */ |
2848 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3041 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2849 | iwlcore_commit_rxon(priv); | 3042 | iwlcore_commit_rxon(priv); |
2850 | iwl_add_bcast_station(priv); | ||
2851 | } | 3043 | } |
2852 | iwl_send_beacon_cmd(priv); | 3044 | iwl_send_beacon_cmd(priv); |
2853 | 3045 | ||
@@ -2866,8 +3058,7 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
2866 | struct iwl_priv *priv = hw->priv; | 3058 | struct iwl_priv *priv = hw->priv; |
2867 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 3059 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2868 | 3060 | ||
2869 | iwl_update_tkip_key(priv, keyconf, | 3061 | iwl_update_tkip_key(priv, keyconf, sta, |
2870 | sta ? sta->addr : iwl_bcast_addr, | ||
2871 | iv32, phase1key); | 3062 | iv32, phase1key); |
2872 | 3063 | ||
2873 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3064 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -2879,7 +3070,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2879 | struct ieee80211_key_conf *key) | 3070 | struct ieee80211_key_conf *key) |
2880 | { | 3071 | { |
2881 | struct iwl_priv *priv = hw->priv; | 3072 | struct iwl_priv *priv = hw->priv; |
2882 | const u8 *addr; | ||
2883 | int ret; | 3073 | int ret; |
2884 | u8 sta_id; | 3074 | u8 sta_id; |
2885 | bool is_default_wep_key = false; | 3075 | bool is_default_wep_key = false; |
@@ -2890,13 +3080,17 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2890 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); | 3080 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); |
2891 | return -EOPNOTSUPP; | 3081 | return -EOPNOTSUPP; |
2892 | } | 3082 | } |
2893 | addr = sta ? sta->addr : iwl_bcast_addr; | ||
2894 | sta_id = iwl_find_station(priv, addr); | ||
2895 | if (sta_id == IWL_INVALID_STATION) { | ||
2896 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
2897 | addr); | ||
2898 | return -EINVAL; | ||
2899 | 3083 | ||
3084 | if (sta) { | ||
3085 | sta_id = iwl_sta_id(sta); | ||
3086 | |||
3087 | if (sta_id == IWL_INVALID_STATION) { | ||
3088 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
3089 | sta->addr); | ||
3090 | return -EINVAL; | ||
3091 | } | ||
3092 | } else { | ||
3093 | sta_id = priv->hw_params.bcast_sta_id; | ||
2900 | } | 3094 | } |
2901 | 3095 | ||
2902 | mutex_lock(&priv->mutex); | 3096 | mutex_lock(&priv->mutex); |
@@ -2945,8 +3139,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2945 | 3139 | ||
2946 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | 3140 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, |
2947 | struct ieee80211_vif *vif, | 3141 | struct ieee80211_vif *vif, |
2948 | enum ieee80211_ampdu_mlme_action action, | 3142 | enum ieee80211_ampdu_mlme_action action, |
2949 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 3143 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2950 | { | 3144 | { |
2951 | struct iwl_priv *priv = hw->priv; | 3145 | struct iwl_priv *priv = hw->priv; |
2952 | int ret; | 3146 | int ret; |
@@ -2960,17 +3154,17 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2960 | switch (action) { | 3154 | switch (action) { |
2961 | case IEEE80211_AMPDU_RX_START: | 3155 | case IEEE80211_AMPDU_RX_START: |
2962 | IWL_DEBUG_HT(priv, "start Rx\n"); | 3156 | IWL_DEBUG_HT(priv, "start Rx\n"); |
2963 | return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); | 3157 | return iwl_sta_rx_agg_start(priv, sta, tid, *ssn); |
2964 | case IEEE80211_AMPDU_RX_STOP: | 3158 | case IEEE80211_AMPDU_RX_STOP: |
2965 | IWL_DEBUG_HT(priv, "stop Rx\n"); | 3159 | IWL_DEBUG_HT(priv, "stop Rx\n"); |
2966 | ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid); | 3160 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); |
2967 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3161 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2968 | return 0; | 3162 | return 0; |
2969 | else | 3163 | else |
2970 | return ret; | 3164 | return ret; |
2971 | case IEEE80211_AMPDU_TX_START: | 3165 | case IEEE80211_AMPDU_TX_START: |
2972 | IWL_DEBUG_HT(priv, "start Tx\n"); | 3166 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2973 | ret = iwlagn_tx_agg_start(priv, sta->addr, tid, ssn); | 3167 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); |
2974 | if (ret == 0) { | 3168 | if (ret == 0) { |
2975 | priv->_agn.agg_tids_count++; | 3169 | priv->_agn.agg_tids_count++; |
2976 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | 3170 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", |
@@ -2979,7 +3173,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2979 | return ret; | 3173 | return ret; |
2980 | case IEEE80211_AMPDU_TX_STOP: | 3174 | case IEEE80211_AMPDU_TX_STOP: |
2981 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 3175 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2982 | ret = iwlagn_tx_agg_stop(priv, sta->addr, tid); | 3176 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); |
2983 | if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { | 3177 | if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { |
2984 | priv->_agn.agg_tids_count--; | 3178 | priv->_agn.agg_tids_count--; |
2985 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | 3179 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", |
@@ -3021,7 +3215,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
3021 | if (!sta_priv->asleep) | 3215 | if (!sta_priv->asleep) |
3022 | break; | 3216 | break; |
3023 | sta_priv->asleep = false; | 3217 | sta_priv->asleep = false; |
3024 | sta_id = iwl_find_station(priv, sta->addr); | 3218 | sta_id = iwl_sta_id(sta); |
3025 | if (sta_id != IWL_INVALID_STATION) | 3219 | if (sta_id != IWL_INVALID_STATION) |
3026 | iwl_sta_modify_ps_wake(priv, sta_id); | 3220 | iwl_sta_modify_ps_wake(priv, sta_id); |
3027 | break; | 3221 | break; |
@@ -3036,10 +3230,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3036 | { | 3230 | { |
3037 | struct iwl_priv *priv = hw->priv; | 3231 | struct iwl_priv *priv = hw->priv; |
3038 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 3232 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
3039 | bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; | 3233 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; |
3040 | int ret; | 3234 | int ret; |
3041 | u8 sta_id; | 3235 | u8 sta_id; |
3042 | 3236 | ||
3237 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3238 | |||
3043 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | 3239 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", |
3044 | sta->addr); | 3240 | sta->addr); |
3045 | 3241 | ||
@@ -3056,12 +3252,14 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3056 | return ret; | 3252 | return ret; |
3057 | } | 3253 | } |
3058 | 3254 | ||
3255 | sta_priv->common.sta_id = sta_id; | ||
3256 | |||
3059 | /* Initialize rate scaling */ | 3257 | /* Initialize rate scaling */ |
3060 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | 3258 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", |
3061 | sta->addr); | 3259 | sta->addr); |
3062 | iwl_rs_rate_init(priv, sta, sta_id); | 3260 | iwl_rs_rate_init(priv, sta, sta_id); |
3063 | 3261 | ||
3064 | return ret; | 3262 | return 0; |
3065 | } | 3263 | } |
3066 | 3264 | ||
3067 | /***************************************************************************** | 3265 | /***************************************************************************** |
@@ -3586,6 +3784,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3586 | iwl_power_initialize(priv); | 3784 | iwl_power_initialize(priv); |
3587 | iwl_tt_initialize(priv); | 3785 | iwl_tt_initialize(priv); |
3588 | 3786 | ||
3787 | init_completion(&priv->_agn.firmware_loading_complete); | ||
3788 | |||
3589 | err = iwl_request_firmware(priv, true); | 3789 | err = iwl_request_firmware(priv, true); |
3590 | if (err) | 3790 | if (err) |
3591 | goto out_remove_sysfs; | 3791 | goto out_remove_sysfs; |
@@ -3626,6 +3826,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3626 | if (!priv) | 3826 | if (!priv) |
3627 | return; | 3827 | return; |
3628 | 3828 | ||
3829 | wait_for_completion(&priv->_agn.firmware_loading_complete); | ||
3830 | |||
3629 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); | 3831 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); |
3630 | 3832 | ||
3631 | iwl_dbgfs_unregister(priv); | 3833 | iwl_dbgfs_unregister(priv); |
@@ -3783,11 +3985,10 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
3783 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, | 3985 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, |
3784 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | 3986 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, |
3785 | 3987 | ||
3786 | /* 6x00 Series Gen2 */ | 3988 | /* 6x00 Series Gen2a */ |
3787 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2_2agn_cfg)}, | 3989 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, |
3788 | {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2_2agn_cfg)}, | 3990 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, |
3789 | {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2_2agn_cfg)}, | 3991 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, |
3790 | {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2_2agn_cfg)}, | ||
3791 | 3992 | ||
3792 | /* 6x50 WiFi/WiMax Series */ | 3993 | /* 6x50 WiFi/WiMax Series */ |
3793 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 3994 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
@@ -3900,3 +4101,8 @@ MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | |||
3900 | module_param_named( | 4101 | module_param_named( |
3901 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); | 4102 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); |
3902 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 4103 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
4104 | |||
4105 | module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, | ||
4106 | S_IRUGO); | ||
4107 | MODULE_PARM_DESC(ucode_alternative, | ||
4108 | "specify ucode alternative to use from ucode file"); | ||