aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c133
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h58
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c4
4 files changed, 187 insertions, 9 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 65ae636eae3e..97184e14a775 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1505,9 +1505,13 @@ static void iwl_nic_start(struct iwl_priv *priv)
1505 iwl_write32(priv, CSR_RESET, 0); 1505 iwl_write32(priv, CSR_RESET, 0);
1506} 1506}
1507 1507
1508struct iwlagn_ucode_capabilities {
1509 u32 max_probe_length;
1510};
1508 1511
1509static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); 1512static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
1510static int iwl_mac_setup_register(struct iwl_priv *priv); 1513static int iwl_mac_setup_register(struct iwl_priv *priv,
1514 struct iwlagn_ucode_capabilities *capa);
1511 1515
1512static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) 1516static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
1513{ 1517{
@@ -1619,6 +1623,114 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
1619 return 0; 1623 return 0;
1620} 1624}
1621 1625
1626static int iwlagn_wanted_ucode_alternative = 1;
1627
1628static int iwlagn_load_firmware(struct iwl_priv *priv,
1629 const struct firmware *ucode_raw,
1630 struct iwlagn_firmware_pieces *pieces,
1631 struct iwlagn_ucode_capabilities *capa)
1632{
1633 struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
1634 struct iwl_ucode_tlv *tlv;
1635 size_t len = ucode_raw->size;
1636 const u8 *data;
1637 int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp;
1638 u64 alternatives;
1639
1640 if (len < sizeof(*ucode))
1641 return -EINVAL;
1642
1643 if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC))
1644 return -EINVAL;
1645
1646 /*
1647 * Check which alternatives are present, and "downgrade"
1648 * when the chosen alternative is not present, warning
1649 * the user when that happens. Some files may not have
1650 * any alternatives, so don't warn in that case.
1651 */
1652 alternatives = le64_to_cpu(ucode->alternatives);
1653 tmp = wanted_alternative;
1654 if (wanted_alternative > 63)
1655 wanted_alternative = 63;
1656 while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
1657 wanted_alternative--;
1658 if (wanted_alternative && wanted_alternative != tmp)
1659 IWL_WARN(priv,
1660 "uCode alternative %d not available, choosing %d\n",
1661 tmp, wanted_alternative);
1662
1663 priv->ucode_ver = le32_to_cpu(ucode->ver);
1664 pieces->build = le32_to_cpu(ucode->build);
1665 data = ucode->data;
1666
1667 len -= sizeof(*ucode);
1668
1669 while (len >= sizeof(*tlv)) {
1670 u32 tlv_len;
1671 enum iwl_ucode_tlv_type tlv_type;
1672 u16 tlv_alt;
1673 const u8 *tlv_data;
1674
1675 len -= sizeof(*tlv);
1676 tlv = (void *)data;
1677
1678 tlv_len = le32_to_cpu(tlv->length);
1679 tlv_type = le16_to_cpu(tlv->type);
1680 tlv_alt = le16_to_cpu(tlv->alternative);
1681 tlv_data = tlv->data;
1682
1683 if (len < tlv_len)
1684 return -EINVAL;
1685 len -= ALIGN(tlv_len, 4);
1686 data += sizeof(*tlv) + ALIGN(tlv_len, 4);
1687
1688 /*
1689 * Alternative 0 is always valid.
1690 *
1691 * Skip alternative TLVs that are not selected.
1692 */
1693 if (tlv_alt != 0 && tlv_alt != wanted_alternative)
1694 continue;
1695
1696 switch (tlv_type) {
1697 case IWL_UCODE_TLV_INST:
1698 pieces->inst = tlv_data;
1699 pieces->inst_size = tlv_len;
1700 break;
1701 case IWL_UCODE_TLV_DATA:
1702 pieces->data = tlv_data;
1703 pieces->data_size = tlv_len;
1704 break;
1705 case IWL_UCODE_TLV_INIT:
1706 pieces->init = tlv_data;
1707 pieces->init_size = tlv_len;
1708 break;
1709 case IWL_UCODE_TLV_INIT_DATA:
1710 pieces->init_data = tlv_data;
1711 pieces->init_data_size = tlv_len;
1712 break;
1713 case IWL_UCODE_TLV_BOOT:
1714 pieces->boot = tlv_data;
1715 pieces->boot_size = tlv_len;
1716 break;
1717 case IWL_UCODE_TLV_PROBE_MAX_LEN:
1718 if (tlv_len != 4)
1719 return -EINVAL;
1720 capa->max_probe_length =
1721 le32_to_cpup((__le32 *)tlv_data);
1722 break;
1723 default:
1724 break;
1725 }
1726 }
1727
1728 if (len)
1729 return -EINVAL;
1730
1731 return 0;
1732}
1733
1622/** 1734/**
1623 * iwl_ucode_callback - callback when firmware was loaded 1735 * iwl_ucode_callback - callback when firmware was loaded
1624 * 1736 *
@@ -1636,6 +1748,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1636 u32 api_ver; 1748 u32 api_ver;
1637 char buildstr[25]; 1749 char buildstr[25];
1638 u32 build; 1750 u32 build;
1751 struct iwlagn_ucode_capabilities ucode_capa = {
1752 .max_probe_length = 200,
1753 };
1639 1754
1640 memset(&pieces, 0, sizeof(pieces)); 1755 memset(&pieces, 0, sizeof(pieces));
1641 1756
@@ -1660,7 +1775,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1660 if (ucode->ver) 1775 if (ucode->ver)
1661 err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); 1776 err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces);
1662 else 1777 else
1663 err = -EINVAL; 1778 err = iwlagn_load_firmware(priv, ucode_raw, &pieces,
1779 &ucode_capa);
1664 1780
1665 if (err) 1781 if (err)
1666 goto try_again; 1782 goto try_again;
@@ -1757,7 +1873,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1757 goto try_again; 1873 goto try_again;
1758 } 1874 }
1759 1875
1760
1761 /* Allocate ucode buffers for card's bus-master loading ... */ 1876 /* Allocate ucode buffers for card's bus-master loading ... */
1762 1877
1763 /* Runtime instructions and 2 copies of data: 1878 /* Runtime instructions and 2 copies of data:
@@ -1841,7 +1956,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1841 * 1956 *
1842 * 9. Setup and register with mac80211 and debugfs 1957 * 9. Setup and register with mac80211 and debugfs
1843 **************************************************/ 1958 **************************************************/
1844 err = iwl_mac_setup_register(priv); 1959 err = iwl_mac_setup_register(priv, &ucode_capa);
1845 if (err) 1960 if (err)
1846 goto out_unbind; 1961 goto out_unbind;
1847 1962
@@ -2716,7 +2831,8 @@ void iwl_post_associate(struct iwl_priv *priv)
2716 * Not a mac80211 entry point function, but it fits in with all the 2831 * Not a mac80211 entry point function, but it fits in with all the
2717 * other mac80211 functions grouped here. 2832 * other mac80211 functions grouped here.
2718 */ 2833 */
2719static int iwl_mac_setup_register(struct iwl_priv *priv) 2834static int iwl_mac_setup_register(struct iwl_priv *priv,
2835 struct iwlagn_ucode_capabilities *capa)
2720{ 2836{
2721 int ret; 2837 int ret;
2722 struct ieee80211_hw *hw = priv->hw; 2838 struct ieee80211_hw *hw = priv->hw;
@@ -2751,7 +2867,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv)
2751 2867
2752 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; 2868 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
2753 /* we create the 802.11 header and a zero-length SSID element */ 2869 /* we create the 802.11 header and a zero-length SSID element */
2754 hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; 2870 hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2;
2755 2871
2756 /* Default value; 4 EDCA QOS priorities */ 2872 /* Default value; 4 EDCA QOS priorities */
2757 hw->queues = 4; 2873 hw->queues = 4;
@@ -3974,3 +4090,8 @@ MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
3974module_param_named( 4090module_param_named(
3975 disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); 4091 disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO);
3976MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); 4092MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
4093
4094module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int,
4095 S_IRUGO);
4096MODULE_PARM_DESC(ucode_alternative,
4097 "specify ucode alternative to use from ucode file");
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 0086019b7a15..449d41f058b8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2668,7 +2668,6 @@ struct iwl_ssid_ie {
2668#define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) 2668#define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff)
2669#define IWL_MAX_SCAN_SIZE 1024 2669#define IWL_MAX_SCAN_SIZE 1024
2670#define IWL_MAX_CMD_SIZE 4096 2670#define IWL_MAX_CMD_SIZE 4096
2671#define IWL_MAX_PROBE_REQUEST 200
2672 2671
2673/* 2672/*
2674 * REPLY_SCAN_CMD = 0x80 (command) 2673 * REPLY_SCAN_CMD = 0x80 (command)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index fe938d9e43cb..19a5c895f1a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -518,7 +518,7 @@ struct fw_desc {
518 u32 len; /* bytes */ 518 u32 len; /* bytes */
519}; 519};
520 520
521/* uCode file layout */ 521/* v1/v2 uCode file layout */
522struct iwl_ucode_header { 522struct iwl_ucode_header {
523 __le32 ver; /* major/minor/API/serial */ 523 __le32 ver; /* major/minor/API/serial */
524 union { 524 union {
@@ -542,6 +542,62 @@ struct iwl_ucode_header {
542 } u; 542 } u;
543}; 543};
544 544
545/*
546 * new TLV uCode file layout
547 *
548 * The new TLV file format contains TLVs, that each specify
549 * some piece of data. To facilitate "groups", for example
550 * different instruction image with different capabilities,
551 * bundled with the same init image, an alternative mechanism
552 * is provided:
553 * When the alternative field is 0, that means that the item
554 * is always valid. When it is non-zero, then it is only
555 * valid in conjunction with items of the same alternative,
556 * in which case the driver (user) selects one alternative
557 * to use.
558 */
559
560enum iwl_ucode_tlv_type {
561 IWL_UCODE_TLV_INVALID = 0, /* unused */
562 IWL_UCODE_TLV_INST = 1,
563 IWL_UCODE_TLV_DATA = 2,
564 IWL_UCODE_TLV_INIT = 3,
565 IWL_UCODE_TLV_INIT_DATA = 4,
566 IWL_UCODE_TLV_BOOT = 5,
567 IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */
568};
569
570struct iwl_ucode_tlv {
571 __le16 type; /* see above */
572 __le16 alternative; /* see comment */
573 __le32 length; /* not including type/length fields */
574 u8 data[0];
575} __attribute__ ((packed));
576
577#define IWL_TLV_UCODE_MAGIC 0x0a4c5749
578
579struct iwl_tlv_ucode_header {
580 /*
581 * The TLV style ucode header is distinguished from
582 * the v1/v2 style header by first four bytes being
583 * zero, as such is an invalid combination of
584 * major/minor/API/serial versions.
585 */
586 __le32 zero;
587 __le32 magic;
588 u8 human_readable[64];
589 __le32 ver; /* major/minor/API/serial */
590 __le32 build;
591 __le64 alternatives; /* bitmask of valid alternatives */
592 /*
593 * The data contained herein has a TLV layout,
594 * see above for the TLV header and types.
595 * Note that each TLV is padded to a length
596 * that is a multiple of 4 for alignment.
597 */
598 u8 data[0];
599};
600
545struct iwl4965_ibss_seq { 601struct iwl4965_ibss_seq {
546 u8 mac[ETH_ALEN]; 602 u8 mac[ETH_ALEN];
547 u16 seq_num; 603 u16 seq_num;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 59c85f55e625..77ab00b98778 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3875,6 +3875,8 @@ err:
3875 return ret; 3875 return ret;
3876} 3876}
3877 3877
3878#define IWL3945_MAX_PROBE_REQUEST 200
3879
3878static int iwl3945_setup_mac(struct iwl_priv *priv) 3880static int iwl3945_setup_mac(struct iwl_priv *priv)
3879{ 3881{
3880 int ret; 3882 int ret;
@@ -3900,7 +3902,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
3900 3902
3901 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; 3903 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
3902 /* we create the 802.11 header and a zero-length SSID element */ 3904 /* we create the 802.11 header and a zero-length SSID element */
3903 hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; 3905 hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
3904 3906
3905 /* Default value; 4 EDCA QOS priorities */ 3907 /* Default value; 4 EDCA QOS priorities */
3906 hw->queues = 4; 3908 hw->queues = 4;