diff options
author | David S. Miller <davem@davemloft.net> | 2018-06-30 08:08:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-06-30 08:08:12 -0400 |
commit | 8365da2c0570f02615e7f1d2d729d854029202b0 (patch) | |
tree | 223ab9641411c401269e5da80f260cafaf40eedc | |
parent | a1be5a20f137bdf436bab86c18998229908ce951 (diff) | |
parent | a4217750586975dee7d6dd8829a1be24a7678b3d (diff) |
Merge tag 'mac80211-next-for-davem-2018-06-29' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Small merge conflict in net/mac80211/scan.c, I preserved
the kcalloc() conversion. -DaveM
Johannes Berg says:
====================
This round's updates:
* finally some of the promised HE code, but it turns
out to be small - but everything kept changing, so
one part I did in the driver was >30 patches for
what was ultimately <200 lines of code ... similar
here for this code.
* improved scan privacy support - can now specify scan
flags for randomizing the sequence number as well as
reducing the probe request element content
* rfkill cleanups
* a timekeeping cleanup from Arnd
* various other cleanups
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
38 files changed, 1939 insertions, 249 deletions
diff --git a/Documentation/ABI/stable/sysfs-class-rfkill b/Documentation/ABI/stable/sysfs-class-rfkill index e1ba4a104753..80151a409d67 100644 --- a/Documentation/ABI/stable/sysfs-class-rfkill +++ b/Documentation/ABI/stable/sysfs-class-rfkill | |||
@@ -11,7 +11,7 @@ KernelVersion: v2.6.22 | |||
11 | Contact: linux-wireless@vger.kernel.org, | 11 | Contact: linux-wireless@vger.kernel.org, |
12 | Description: The rfkill class subsystem folder. | 12 | Description: The rfkill class subsystem folder. |
13 | Each registered rfkill driver is represented by an rfkillX | 13 | Each registered rfkill driver is represented by an rfkillX |
14 | subfolder (X being an integer > 0). | 14 | subfolder (X being an integer >= 0). |
15 | 15 | ||
16 | 16 | ||
17 | What: /sys/class/rfkill/rfkill[0-9]+/name | 17 | What: /sys/class/rfkill/rfkill[0-9]+/name |
@@ -48,8 +48,8 @@ Contact: linux-wireless@vger.kernel.org | |||
48 | Description: Current state of the transmitter. | 48 | Description: Current state of the transmitter. |
49 | This file was scheduled to be removed in 2014, but due to its | 49 | This file was scheduled to be removed in 2014, but due to its |
50 | large number of users it will be sticking around for a bit | 50 | large number of users it will be sticking around for a bit |
51 | longer. Despite it being marked as stabe, the newer "hard" and | 51 | longer. Despite it being marked as stable, the newer "hard" and |
52 | "soft" interfaces should be preffered, since it is not possible | 52 | "soft" interfaces should be preferred, since it is not possible |
53 | to express the 'soft and hard block' state of the rfkill driver | 53 | to express the 'soft and hard block' state of the rfkill driver |
54 | through this interface. There will likely be another attempt to | 54 | through this interface. There will likely be another attempt to |
55 | remove it in the future. | 55 | remove it in the future. |
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index a289285d2412..7d3684e81df6 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt | |||
@@ -9,7 +9,7 @@ rfkill - RF kill switch support | |||
9 | Introduction | 9 | Introduction |
10 | ============ | 10 | ============ |
11 | 11 | ||
12 | The rfkill subsystem provides a generic interface to disabling any radio | 12 | The rfkill subsystem provides a generic interface for disabling any radio |
13 | transmitter in the system. When a transmitter is blocked, it shall not | 13 | transmitter in the system. When a transmitter is blocked, it shall not |
14 | radiate any power. | 14 | radiate any power. |
15 | 15 | ||
@@ -45,7 +45,7 @@ The rfkill subsystem is composed of three main components: | |||
45 | * the rfkill drivers. | 45 | * the rfkill drivers. |
46 | 46 | ||
47 | The rfkill core provides API for kernel drivers to register their radio | 47 | The rfkill core provides API for kernel drivers to register their radio |
48 | transmitter with the kernel, methods for turning it on and off and, letting | 48 | transmitter with the kernel, methods for turning it on and off, and letting |
49 | the system know about hardware-disabled states that may be implemented on | 49 | the system know about hardware-disabled states that may be implemented on |
50 | the device. | 50 | the device. |
51 | 51 | ||
@@ -54,7 +54,7 @@ ways for userspace to query the current states. See the "Userspace support" | |||
54 | section below. | 54 | section below. |
55 | 55 | ||
56 | When the device is hard-blocked (either by a call to rfkill_set_hw_state() | 56 | When the device is hard-blocked (either by a call to rfkill_set_hw_state() |
57 | or from query_hw_block) set_block() will be invoked for additional software | 57 | or from query_hw_block), set_block() will be invoked for additional software |
58 | block, but drivers can ignore the method call since they can use the return | 58 | block, but drivers can ignore the method call since they can use the return |
59 | value of the function rfkill_set_hw_state() to sync the software state | 59 | value of the function rfkill_set_hw_state() to sync the software state |
60 | instead of keeping track of calls to set_block(). In fact, drivers should | 60 | instead of keeping track of calls to set_block(). In fact, drivers should |
@@ -65,7 +65,6 @@ keeps track of soft and hard block separately. | |||
65 | Kernel API | 65 | Kernel API |
66 | ========== | 66 | ========== |
67 | 67 | ||
68 | |||
69 | Drivers for radio transmitters normally implement an rfkill driver. | 68 | Drivers for radio transmitters normally implement an rfkill driver. |
70 | 69 | ||
71 | Platform drivers might implement input devices if the rfkill button is just | 70 | Platform drivers might implement input devices if the rfkill button is just |
@@ -75,14 +74,14 @@ a way to turn on/off the transmitter(s). | |||
75 | 74 | ||
76 | For some platforms, it is possible that the hardware state changes during | 75 | For some platforms, it is possible that the hardware state changes during |
77 | suspend/hibernation, in which case it will be necessary to update the rfkill | 76 | suspend/hibernation, in which case it will be necessary to update the rfkill |
78 | core with the current state is at resume time. | 77 | core with the current state at resume time. |
79 | 78 | ||
80 | To create an rfkill driver, driver's Kconfig needs to have:: | 79 | To create an rfkill driver, driver's Kconfig needs to have:: |
81 | 80 | ||
82 | depends on RFKILL || !RFKILL | 81 | depends on RFKILL || !RFKILL |
83 | 82 | ||
84 | to ensure the driver cannot be built-in when rfkill is modular. The !RFKILL | 83 | to ensure the driver cannot be built-in when rfkill is modular. The !RFKILL |
85 | case allows the driver to be built when rfkill is not configured, which | 84 | case allows the driver to be built when rfkill is not configured, in which |
86 | case all rfkill API can still be used but will be provided by static inlines | 85 | case all rfkill API can still be used but will be provided by static inlines |
87 | which compile to almost nothing. | 86 | which compile to almost nothing. |
88 | 87 | ||
@@ -91,7 +90,7 @@ rfkill drivers that control devices that can be hard-blocked unless they also | |||
91 | assign the poll_hw_block() callback (then the rfkill core will poll the | 90 | assign the poll_hw_block() callback (then the rfkill core will poll the |
92 | device). Don't do this unless you cannot get the event in any other way. | 91 | device). Don't do this unless you cannot get the event in any other way. |
93 | 92 | ||
94 | RFKill provides per-switch LED triggers, which can be used to drive LEDs | 93 | rfkill provides per-switch LED triggers, which can be used to drive LEDs |
95 | according to the switch state (LED_FULL when blocked, LED_OFF otherwise). | 94 | according to the switch state (LED_FULL when blocked, LED_OFF otherwise). |
96 | 95 | ||
97 | 96 | ||
@@ -114,7 +113,7 @@ a specified type) into a state which also updates the default state for | |||
114 | hotplugged devices. | 113 | hotplugged devices. |
115 | 114 | ||
116 | After an application opens /dev/rfkill, it can read the current state of all | 115 | After an application opens /dev/rfkill, it can read the current state of all |
117 | devices. Changes can be either obtained by either polling the descriptor for | 116 | devices. Changes can be obtained by either polling the descriptor for |
118 | hotplug or state change events or by listening for uevents emitted by the | 117 | hotplug or state change events or by listening for uevents emitted by the |
119 | rfkill core framework. | 118 | rfkill core framework. |
120 | 119 | ||
@@ -127,8 +126,7 @@ environment variables set:: | |||
127 | RFKILL_STATE | 126 | RFKILL_STATE |
128 | RFKILL_TYPE | 127 | RFKILL_TYPE |
129 | 128 | ||
130 | The contents of these variables corresponds to the "name", "state" and | 129 | The content of these variables corresponds to the "name", "state" and |
131 | "type" sysfs files explained above. | 130 | "type" sysfs files explained above. |
132 | 131 | ||
133 | |||
134 | For further details consult Documentation/ABI/stable/sysfs-class-rfkill. | 132 | For further details consult Documentation/ABI/stable/sysfs-class-rfkill. |
diff --git a/MAINTAINERS b/MAINTAINERS index f3e766e504d8..3b2e592aa521 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -12156,6 +12156,8 @@ S: Maintained | |||
12156 | F: Documentation/rfkill.txt | 12156 | F: Documentation/rfkill.txt |
12157 | F: Documentation/ABI/stable/sysfs-class-rfkill | 12157 | F: Documentation/ABI/stable/sysfs-class-rfkill |
12158 | F: net/rfkill/ | 12158 | F: net/rfkill/ |
12159 | F: include/linux/rfkill.h | ||
12160 | F: include/uapi/linux/rfkill.h | ||
12159 | 12161 | ||
12160 | RHASHTABLE | 12162 | RHASHTABLE |
12161 | M: Thomas Graf <tgraf@suug.ch> | 12163 | M: Thomas Graf <tgraf@suug.ch> |
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 39c817eddd78..31bd6f714052 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c | |||
@@ -1904,7 +1904,7 @@ void rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv) | |||
1904 | reject_agg, ctrl_agg_size, agg_size); | 1904 | reject_agg, ctrl_agg_size, agg_size); |
1905 | 1905 | ||
1906 | rtlpriv->hw->max_rx_aggregation_subframes = | 1906 | rtlpriv->hw->max_rx_aggregation_subframes = |
1907 | (ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF); | 1907 | (ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF_HT); |
1908 | } | 1908 | } |
1909 | EXPORT_SYMBOL(rtl_rx_ampdu_apply); | 1909 | EXPORT_SYMBOL(rtl_rx_ampdu_apply); |
1910 | 1910 | ||
diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index 084a246eec19..6790b7c8cfb1 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h | |||
@@ -575,7 +575,6 @@ enum ht_cap_ampdu_factor { | |||
575 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) | 575 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) |
576 | */ | 576 | */ |
577 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | 577 | #define IEEE80211_MIN_AMPDU_BUF 0x8 |
578 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | ||
579 | 578 | ||
580 | 579 | ||
581 | #define OP_MODE_PURE 0 | 580 | #define OP_MODE_PURE 0 |
diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 0ed2f44ab4e9..00a4302e9983 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h | |||
@@ -574,7 +574,6 @@ struct ieee80211_ht_addt_info { | |||
574 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) | 574 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) |
575 | */ | 575 | */ |
576 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | 576 | #define IEEE80211_MIN_AMPDU_BUF 0x8 |
577 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | ||
578 | 577 | ||
579 | 578 | ||
580 | /* Spatial Multiplexing Power Save Modes */ | 579 | /* Spatial Multiplexing Power Save Modes */ |
diff --git a/drivers/staging/rtl8723bs/include/wifi.h b/drivers/staging/rtl8723bs/include/wifi.h index 08bc79840b23..559bf2606fb7 100644 --- a/drivers/staging/rtl8723bs/include/wifi.h +++ b/drivers/staging/rtl8723bs/include/wifi.h | |||
@@ -799,7 +799,6 @@ enum HT_CAP_AMPDU_FACTOR { | |||
799 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) | 799 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) |
800 | */ | 800 | */ |
801 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | 801 | #define IEEE80211_MIN_AMPDU_BUF 0x8 |
802 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | ||
803 | 802 | ||
804 | 803 | ||
805 | /* Spatial Multiplexing Power Save Modes */ | 804 | /* Spatial Multiplexing Power Save Modes */ |
diff --git a/drivers/staging/rtlwifi/base.c b/drivers/staging/rtlwifi/base.c index e46e47d93d7d..094827c1879a 100644 --- a/drivers/staging/rtlwifi/base.c +++ b/drivers/staging/rtlwifi/base.c | |||
@@ -1838,7 +1838,7 @@ void rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv) | |||
1838 | reject_agg, ctrl_agg_size, agg_size); | 1838 | reject_agg, ctrl_agg_size, agg_size); |
1839 | 1839 | ||
1840 | rtlpriv->hw->max_rx_aggregation_subframes = | 1840 | rtlpriv->hw->max_rx_aggregation_subframes = |
1841 | (ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF); | 1841 | (ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF_HT); |
1842 | } | 1842 | } |
1843 | 1843 | ||
1844 | /********************************************************* | 1844 | /********************************************************* |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 8fe7e4306816..9c03a7d5e400 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1433,11 +1433,13 @@ struct ieee80211_ht_operation { | |||
1433 | #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 | 1433 | #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 |
1434 | 1434 | ||
1435 | /* | 1435 | /* |
1436 | * A-PMDU buffer sizes | 1436 | * A-MPDU buffer sizes |
1437 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) | 1437 | * According to HT size varies from 8 to 64 frames |
1438 | * HE adds the ability to have up to 256 frames. | ||
1438 | */ | 1439 | */ |
1439 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | 1440 | #define IEEE80211_MIN_AMPDU_BUF 0x8 |
1440 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | 1441 | #define IEEE80211_MAX_AMPDU_BUF_HT 0x40 |
1442 | #define IEEE80211_MAX_AMPDU_BUF 0x100 | ||
1441 | 1443 | ||
1442 | 1444 | ||
1443 | /* Spatial Multiplexing Power Save Modes (for capability) */ | 1445 | /* Spatial Multiplexing Power Save Modes (for capability) */ |
@@ -1539,6 +1541,106 @@ struct ieee80211_vht_operation { | |||
1539 | __le16 basic_mcs_set; | 1541 | __le16 basic_mcs_set; |
1540 | } __packed; | 1542 | } __packed; |
1541 | 1543 | ||
1544 | /** | ||
1545 | * struct ieee80211_he_cap_elem - HE capabilities element | ||
1546 | * | ||
1547 | * This structure is the "HE capabilities element" fixed fields as | ||
1548 | * described in P802.11ax_D2.0 section 9.4.2.237.2 and 9.4.2.237.3 | ||
1549 | */ | ||
1550 | struct ieee80211_he_cap_elem { | ||
1551 | u8 mac_cap_info[5]; | ||
1552 | u8 phy_cap_info[9]; | ||
1553 | } __packed; | ||
1554 | |||
1555 | #define IEEE80211_TX_RX_MCS_NSS_DESC_MAX_LEN 5 | ||
1556 | |||
1557 | /** | ||
1558 | * enum ieee80211_he_mcs_support - HE MCS support definitions | ||
1559 | * @IEEE80211_HE_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the | ||
1560 | * number of streams | ||
1561 | * @IEEE80211_HE_MCS_SUPPORT_0_9: MCSes 0-9 are supported | ||
1562 | * @IEEE80211_HE_MCS_SUPPORT_0_11: MCSes 0-11 are supported | ||
1563 | * @IEEE80211_HE_MCS_NOT_SUPPORTED: This number of streams isn't supported | ||
1564 | * | ||
1565 | * These definitions are used in each 2-bit subfield of the rx_mcs_* | ||
1566 | * and tx_mcs_* fields of &struct ieee80211_he_mcs_nss_supp, which are | ||
1567 | * both split into 8 subfields by number of streams. These values indicate | ||
1568 | * which MCSes are supported for the number of streams the value appears | ||
1569 | * for. | ||
1570 | */ | ||
1571 | enum ieee80211_he_mcs_support { | ||
1572 | IEEE80211_HE_MCS_SUPPORT_0_7 = 0, | ||
1573 | IEEE80211_HE_MCS_SUPPORT_0_9 = 1, | ||
1574 | IEEE80211_HE_MCS_SUPPORT_0_11 = 2, | ||
1575 | IEEE80211_HE_MCS_NOT_SUPPORTED = 3, | ||
1576 | }; | ||
1577 | |||
1578 | /** | ||
1579 | * struct ieee80211_he_mcs_nss_supp - HE Tx/Rx HE MCS NSS Support Field | ||
1580 | * | ||
1581 | * This structure holds the data required for the Tx/Rx HE MCS NSS Support Field | ||
1582 | * described in P802.11ax_D2.0 section 9.4.2.237.4 | ||
1583 | * | ||
1584 | * @rx_mcs_80: Rx MCS map 2 bits for each stream, total 8 streams, for channel | ||
1585 | * widths less than 80MHz. | ||
1586 | * @tx_mcs_80: Tx MCS map 2 bits for each stream, total 8 streams, for channel | ||
1587 | * widths less than 80MHz. | ||
1588 | * @rx_mcs_160: Rx MCS map 2 bits for each stream, total 8 streams, for channel | ||
1589 | * width 160MHz. | ||
1590 | * @tx_mcs_160: Tx MCS map 2 bits for each stream, total 8 streams, for channel | ||
1591 | * width 160MHz. | ||
1592 | * @rx_mcs_80p80: Rx MCS map 2 bits for each stream, total 8 streams, for | ||
1593 | * channel width 80p80MHz. | ||
1594 | * @tx_mcs_80p80: Tx MCS map 2 bits for each stream, total 8 streams, for | ||
1595 | * channel width 80p80MHz. | ||
1596 | */ | ||
1597 | struct ieee80211_he_mcs_nss_supp { | ||
1598 | __le16 rx_mcs_80; | ||
1599 | __le16 tx_mcs_80; | ||
1600 | __le16 rx_mcs_160; | ||
1601 | __le16 tx_mcs_160; | ||
1602 | __le16 rx_mcs_80p80; | ||
1603 | __le16 tx_mcs_80p80; | ||
1604 | } __packed; | ||
1605 | |||
1606 | /** | ||
1607 | * struct ieee80211_he_operation - HE capabilities element | ||
1608 | * | ||
1609 | * This structure is the "HE operation element" fields as | ||
1610 | * described in P802.11ax_D2.0 section 9.4.2.238 | ||
1611 | */ | ||
1612 | struct ieee80211_he_operation { | ||
1613 | __le32 he_oper_params; | ||
1614 | __le16 he_mcs_nss_set; | ||
1615 | /* Optional 0,1,3 or 4 bytes: depends on @he_oper_params */ | ||
1616 | u8 optional[0]; | ||
1617 | } __packed; | ||
1618 | |||
1619 | /** | ||
1620 | * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field | ||
1621 | * | ||
1622 | * This structure is the "MU AC Parameter Record" fields as | ||
1623 | * described in P802.11ax_D2.0 section 9.4.2.240 | ||
1624 | */ | ||
1625 | struct ieee80211_he_mu_edca_param_ac_rec { | ||
1626 | u8 aifsn; | ||
1627 | u8 ecw_min_max; | ||
1628 | u8 mu_edca_timer; | ||
1629 | } __packed; | ||
1630 | |||
1631 | /** | ||
1632 | * struct ieee80211_mu_edca_param_set - MU EDCA Parameter Set element | ||
1633 | * | ||
1634 | * This structure is the "MU EDCA Parameter Set element" fields as | ||
1635 | * described in P802.11ax_D2.0 section 9.4.2.240 | ||
1636 | */ | ||
1637 | struct ieee80211_mu_edca_param_set { | ||
1638 | u8 mu_qos_info; | ||
1639 | struct ieee80211_he_mu_edca_param_ac_rec ac_be; | ||
1640 | struct ieee80211_he_mu_edca_param_ac_rec ac_bk; | ||
1641 | struct ieee80211_he_mu_edca_param_ac_rec ac_vi; | ||
1642 | struct ieee80211_he_mu_edca_param_ac_rec ac_vo; | ||
1643 | } __packed; | ||
1542 | 1644 | ||
1543 | /* 802.11ac VHT Capabilities */ | 1645 | /* 802.11ac VHT Capabilities */ |
1544 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 | 1646 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 |
@@ -1577,6 +1679,328 @@ struct ieee80211_vht_operation { | |||
1577 | #define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 | 1679 | #define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 |
1578 | #define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 | 1680 | #define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 |
1579 | 1681 | ||
1682 | /* 802.11ax HE MAC capabilities */ | ||
1683 | #define IEEE80211_HE_MAC_CAP0_HTC_HE 0x01 | ||
1684 | #define IEEE80211_HE_MAC_CAP0_TWT_REQ 0x02 | ||
1685 | #define IEEE80211_HE_MAC_CAP0_TWT_RES 0x04 | ||
1686 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_NOT_SUPP 0x00 | ||
1687 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_1 0x08 | ||
1688 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_2 0x10 | ||
1689 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_3 0x18 | ||
1690 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK 0x18 | ||
1691 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_1 0x00 | ||
1692 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_2 0x20 | ||
1693 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_4 0x40 | ||
1694 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_8 0x60 | ||
1695 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_16 0x80 | ||
1696 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_32 0xa0 | ||
1697 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_64 0xc0 | ||
1698 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_UNLIMITED 0xe0 | ||
1699 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_MASK 0xe0 | ||
1700 | |||
1701 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_UNLIMITED 0x00 | ||
1702 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_128 0x01 | ||
1703 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_256 0x02 | ||
1704 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_512 0x03 | ||
1705 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_MASK 0x03 | ||
1706 | #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_0US 0x00 | ||
1707 | #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_8US 0x04 | ||
1708 | #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US 0x08 | ||
1709 | #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK 0x0c | ||
1710 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_1 0x00 | ||
1711 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_2 0x10 | ||
1712 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_3 0x20 | ||
1713 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_4 0x30 | ||
1714 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_5 0x40 | ||
1715 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_6 0x50 | ||
1716 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_7 0x60 | ||
1717 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_8 0x70 | ||
1718 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_MASK 0x70 | ||
1719 | |||
1720 | /* Link adaptation is split between byte HE_MAC_CAP1 and | ||
1721 | * HE_MAC_CAP2. It should be set only if IEEE80211_HE_MAC_CAP0_HTC_HE | ||
1722 | * in which case the following values apply: | ||
1723 | * 0 = No feedback. | ||
1724 | * 1 = reserved. | ||
1725 | * 2 = Unsolicited feedback. | ||
1726 | * 3 = both | ||
1727 | */ | ||
1728 | #define IEEE80211_HE_MAC_CAP1_LINK_ADAPTATION 0x80 | ||
1729 | |||
1730 | #define IEEE80211_HE_MAC_CAP2_LINK_ADAPTATION 0x01 | ||
1731 | #define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02 | ||
1732 | #define IEEE80211_HE_MAC_CAP2_UL_MU_RESP_SCHED 0x04 | ||
1733 | #define IEEE80211_HE_MAC_CAP2_BSR 0x08 | ||
1734 | #define IEEE80211_HE_MAC_CAP2_BCAST_TWT 0x10 | ||
1735 | #define IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP 0x20 | ||
1736 | #define IEEE80211_HE_MAC_CAP2_MU_CASCADING 0x40 | ||
1737 | #define IEEE80211_HE_MAC_CAP2_ACK_EN 0x80 | ||
1738 | |||
1739 | #define IEEE80211_HE_MAC_CAP3_GRP_ADDR_MULTI_STA_BA_DL_MU 0x01 | ||
1740 | #define IEEE80211_HE_MAC_CAP3_OMI_CONTROL 0x02 | ||
1741 | #define IEEE80211_HE_MAC_CAP3_OFDMA_RA 0x04 | ||
1742 | |||
1743 | /* The maximum length of an A-MDPU is defined by the combination of the Maximum | ||
1744 | * A-MDPU Length Exponent field in the HT capabilities, VHT capabilities and the | ||
1745 | * same field in the HE capabilities. | ||
1746 | */ | ||
1747 | #define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_USE_VHT 0x00 | ||
1748 | #define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_1 0x08 | ||
1749 | #define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_2 0x10 | ||
1750 | #define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_RESERVED 0x18 | ||
1751 | #define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_MASK 0x18 | ||
1752 | #define IEEE80211_HE_MAC_CAP3_A_AMSDU_FRAG 0x20 | ||
1753 | #define IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED 0x40 | ||
1754 | #define IEEE80211_HE_MAC_CAP3_RX_CTRL_FRAME_TO_MULTIBSS 0x80 | ||
1755 | |||
1756 | #define IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG 0x01 | ||
1757 | #define IEEE80211_HE_MAC_CAP4_QTP 0x02 | ||
1758 | #define IEEE80211_HE_MAC_CAP4_BQR 0x04 | ||
1759 | #define IEEE80211_HE_MAC_CAP4_SR_RESP 0x08 | ||
1760 | #define IEEE80211_HE_MAC_CAP4_NDP_FB_REP 0x10 | ||
1761 | #define IEEE80211_HE_MAC_CAP4_OPS 0x20 | ||
1762 | #define IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU 0x40 | ||
1763 | |||
1764 | /* 802.11ax HE PHY capabilities */ | ||
1765 | #define IEEE80211_HE_PHY_CAP0_DUAL_BAND 0x01 | ||
1766 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 | ||
1767 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04 | ||
1768 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G 0x08 | ||
1769 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G 0x10 | ||
1770 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G 0x20 | ||
1771 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G 0x40 | ||
1772 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK 0xfe | ||
1773 | |||
1774 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_20MHZ 0x01 | ||
1775 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_40MHZ 0x02 | ||
1776 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_20MHZ 0x04 | ||
1777 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_40MHZ 0x08 | ||
1778 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK 0x0f | ||
1779 | #define IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A 0x10 | ||
1780 | #define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD 0x20 | ||
1781 | #define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US 0x40 | ||
1782 | /* Midamble RX Max NSTS is split between byte #2 and byte #3 */ | ||
1783 | #define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_MAX_NSTS 0x80 | ||
1784 | |||
1785 | #define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_MAX_NSTS 0x01 | ||
1786 | #define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US 0x02 | ||
1787 | #define IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ 0x04 | ||
1788 | #define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ 0x08 | ||
1789 | #define IEEE80211_HE_PHY_CAP2_DOPPLER_TX 0x10 | ||
1790 | #define IEEE80211_HE_PHY_CAP2_DOPPLER_RX 0x20 | ||
1791 | |||
1792 | /* Note that the meaning of UL MU below is different between an AP and a non-AP | ||
1793 | * sta, where in the AP case it indicates support for Rx and in the non-AP sta | ||
1794 | * case it indicates support for Tx. | ||
1795 | */ | ||
1796 | #define IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO 0x40 | ||
1797 | #define IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO 0x80 | ||
1798 | |||
1799 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM 0x00 | ||
1800 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK 0x01 | ||
1801 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK 0x02 | ||
1802 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM 0x03 | ||
1803 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK 0x03 | ||
1804 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 0x00 | ||
1805 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2 0x04 | ||
1806 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM 0x00 | ||
1807 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK 0x08 | ||
1808 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK 0x10 | ||
1809 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM 0x18 | ||
1810 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK 0x18 | ||
1811 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00 | ||
1812 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_2 0x20 | ||
1813 | #define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA 0x40 | ||
1814 | #define IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER 0x80 | ||
1815 | |||
1816 | #define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01 | ||
1817 | #define IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER 0x02 | ||
1818 | |||
1819 | /* Minimal allowed value of Max STS under 80MHz is 3 */ | ||
1820 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 0x0c | ||
1821 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5 0x10 | ||
1822 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_6 0x14 | ||
1823 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_7 0x18 | ||
1824 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8 0x1c | ||
1825 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK 0x1c | ||
1826 | |||
1827 | /* Minimal allowed value of Max STS above 80MHz is 3 */ | ||
1828 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4 0x60 | ||
1829 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5 0x80 | ||
1830 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_6 0xa0 | ||
1831 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_7 0xc0 | ||
1832 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8 0xe0 | ||
1833 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK 0xe0 | ||
1834 | |||
1835 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_1 0x00 | ||
1836 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 0x01 | ||
1837 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_3 0x02 | ||
1838 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_4 0x03 | ||
1839 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_5 0x04 | ||
1840 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_6 0x05 | ||
1841 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_7 0x06 | ||
1842 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_8 0x07 | ||
1843 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK 0x07 | ||
1844 | |||
1845 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_1 0x00 | ||
1846 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2 0x08 | ||
1847 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_3 0x10 | ||
1848 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_4 0x18 | ||
1849 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_5 0x20 | ||
1850 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_6 0x28 | ||
1851 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_7 0x30 | ||
1852 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_8 0x38 | ||
1853 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK 0x38 | ||
1854 | |||
1855 | #define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK 0x40 | ||
1856 | #define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK 0x80 | ||
1857 | |||
1858 | #define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU 0x01 | ||
1859 | #define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU 0x02 | ||
1860 | #define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB 0x04 | ||
1861 | #define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB 0x08 | ||
1862 | #define IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB 0x10 | ||
1863 | #define IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE 0x20 | ||
1864 | #define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO 0x40 | ||
1865 | #define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT 0x80 | ||
1866 | |||
1867 | #define IEEE80211_HE_PHY_CAP7_SRP_BASED_SR 0x01 | ||
1868 | #define IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR 0x02 | ||
1869 | #define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI 0x04 | ||
1870 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_1 0x08 | ||
1871 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_2 0x10 | ||
1872 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_3 0x18 | ||
1873 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_4 0x20 | ||
1874 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_5 0x28 | ||
1875 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_6 0x30 | ||
1876 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_7 0x38 | ||
1877 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_MASK 0x38 | ||
1878 | #define IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ 0x40 | ||
1879 | #define IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ 0x80 | ||
1880 | |||
1881 | #define IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI 0x01 | ||
1882 | #define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G 0x02 | ||
1883 | #define IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU 0x04 | ||
1884 | #define IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU 0x08 | ||
1885 | #define IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI 0x10 | ||
1886 | #define IEEE80211_HE_PHY_CAP8_MIDAMBLE_RX_2X_AND_1XLTF 0x20 | ||
1887 | |||
1888 | /* 802.11ax HE TX/RX MCS NSS Support */ | ||
1889 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_HIGHEST_MCS_POS (3) | ||
1890 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_POS (6) | ||
1891 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_POS (11) | ||
1892 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_MASK 0x07c0 | ||
1893 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_MASK 0xf800 | ||
1894 | |||
1895 | /* TX/RX HE MCS Support field Highest MCS subfield encoding */ | ||
1896 | enum ieee80211_he_highest_mcs_supported_subfield_enc { | ||
1897 | HIGHEST_MCS_SUPPORTED_MCS7 = 0, | ||
1898 | HIGHEST_MCS_SUPPORTED_MCS8, | ||
1899 | HIGHEST_MCS_SUPPORTED_MCS9, | ||
1900 | HIGHEST_MCS_SUPPORTED_MCS10, | ||
1901 | HIGHEST_MCS_SUPPORTED_MCS11, | ||
1902 | }; | ||
1903 | |||
1904 | /* Calculate 802.11ax HE capabilities IE Tx/Rx HE MCS NSS Support Field size */ | ||
1905 | static inline u8 | ||
1906 | ieee80211_he_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap) | ||
1907 | { | ||
1908 | u8 count = 4; | ||
1909 | |||
1910 | if (he_cap->phy_cap_info[0] & | ||
1911 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) | ||
1912 | count += 4; | ||
1913 | |||
1914 | if (he_cap->phy_cap_info[0] & | ||
1915 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) | ||
1916 | count += 4; | ||
1917 | |||
1918 | return count; | ||
1919 | } | ||
1920 | |||
1921 | /* 802.11ax HE PPE Thresholds */ | ||
1922 | #define IEEE80211_PPE_THRES_NSS_SUPPORT_2NSS (1) | ||
1923 | #define IEEE80211_PPE_THRES_NSS_POS (0) | ||
1924 | #define IEEE80211_PPE_THRES_NSS_MASK (7) | ||
1925 | #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_2x966_AND_966_RU \ | ||
1926 | (BIT(5) | BIT(6)) | ||
1927 | #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK 0x78 | ||
1928 | #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS (3) | ||
1929 | #define IEEE80211_PPE_THRES_INFO_PPET_SIZE (3) | ||
1930 | |||
1931 | /* | ||
1932 | * Calculate 802.11ax HE capabilities IE PPE field size | ||
1933 | * Input: Header byte of ppe_thres (first byte), and HE capa IE's PHY cap u8* | ||
1934 | */ | ||
1935 | static inline u8 | ||
1936 | ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) | ||
1937 | { | ||
1938 | u8 n; | ||
1939 | |||
1940 | if ((phy_cap_info[6] & | ||
1941 | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0) | ||
1942 | return 0; | ||
1943 | |||
1944 | n = hweight8(ppe_thres_hdr & | ||
1945 | IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK); | ||
1946 | n *= (1 + ((ppe_thres_hdr & IEEE80211_PPE_THRES_NSS_MASK) >> | ||
1947 | IEEE80211_PPE_THRES_NSS_POS)); | ||
1948 | |||
1949 | /* | ||
1950 | * Each pair is 6 bits, and we need to add the 7 "header" bits to the | ||
1951 | * total size. | ||
1952 | */ | ||
1953 | n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7; | ||
1954 | n = DIV_ROUND_UP(n, 8); | ||
1955 | |||
1956 | return n; | ||
1957 | } | ||
1958 | |||
1959 | /* HE Operation defines */ | ||
1960 | #define IEEE80211_HE_OPERATION_BSS_COLOR_MASK 0x0000003f | ||
1961 | #define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK 0x000001c0 | ||
1962 | #define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_OFFSET 6 | ||
1963 | #define IEEE80211_HE_OPERATION_TWT_REQUIRED 0x00000200 | ||
1964 | #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK 0x000ffc00 | ||
1965 | #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_OFFSET 10 | ||
1966 | #define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR 0x000100000 | ||
1967 | #define IEEE80211_HE_OPERATION_VHT_OPER_INFO 0x000200000 | ||
1968 | #define IEEE80211_HE_OPERATION_MULTI_BSSID_AP 0x10000000 | ||
1969 | #define IEEE80211_HE_OPERATION_TX_BSSID_INDICATOR 0x20000000 | ||
1970 | #define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED 0x40000000 | ||
1971 | |||
1972 | /* | ||
1973 | * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size | ||
1974 | * @he_oper_ie: byte data of the He Operations IE, stating from the the byte | ||
1975 | * after the ext ID byte. It is assumed that he_oper_ie has at least | ||
1976 | * sizeof(struct ieee80211_he_operation) bytes, checked already in | ||
1977 | * ieee802_11_parse_elems_crc() | ||
1978 | * @return the actual size of the IE data (not including header), or 0 on error | ||
1979 | */ | ||
1980 | static inline u8 | ||
1981 | ieee80211_he_oper_size(const u8 *he_oper_ie) | ||
1982 | { | ||
1983 | struct ieee80211_he_operation *he_oper = (void *)he_oper_ie; | ||
1984 | u8 oper_len = sizeof(struct ieee80211_he_operation); | ||
1985 | u32 he_oper_params; | ||
1986 | |||
1987 | /* Make sure the input is not NULL */ | ||
1988 | if (!he_oper_ie) | ||
1989 | return 0; | ||
1990 | |||
1991 | /* Calc required length */ | ||
1992 | he_oper_params = le32_to_cpu(he_oper->he_oper_params); | ||
1993 | if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO) | ||
1994 | oper_len += 3; | ||
1995 | if (he_oper_params & IEEE80211_HE_OPERATION_MULTI_BSSID_AP) | ||
1996 | oper_len++; | ||
1997 | |||
1998 | /* Add the first byte (extension ID) to the total length */ | ||
1999 | oper_len++; | ||
2000 | |||
2001 | return oper_len; | ||
2002 | } | ||
2003 | |||
1580 | /* Authentication algorithms */ | 2004 | /* Authentication algorithms */ |
1581 | #define WLAN_AUTH_OPEN 0 | 2005 | #define WLAN_AUTH_OPEN 0 |
1582 | #define WLAN_AUTH_SHARED_KEY 1 | 2006 | #define WLAN_AUTH_SHARED_KEY 1 |
@@ -1992,6 +2416,11 @@ enum ieee80211_eid_ext { | |||
1992 | WLAN_EID_EXT_FILS_WRAPPED_DATA = 8, | 2416 | WLAN_EID_EXT_FILS_WRAPPED_DATA = 8, |
1993 | WLAN_EID_EXT_FILS_PUBLIC_KEY = 12, | 2417 | WLAN_EID_EXT_FILS_PUBLIC_KEY = 12, |
1994 | WLAN_EID_EXT_FILS_NONCE = 13, | 2418 | WLAN_EID_EXT_FILS_NONCE = 13, |
2419 | WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE = 14, | ||
2420 | WLAN_EID_EXT_HE_CAPABILITY = 35, | ||
2421 | WLAN_EID_EXT_HE_OPERATION = 36, | ||
2422 | WLAN_EID_EXT_UORA = 37, | ||
2423 | WLAN_EID_EXT_HE_MU_EDCA = 38, | ||
1995 | }; | 2424 | }; |
1996 | 2425 | ||
1997 | /* Action category code */ | 2426 | /* Action category code */ |
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index e6a0031d1b1f..8ad2487a86d5 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h | |||
@@ -66,7 +66,7 @@ struct rfkill_ops { | |||
66 | 66 | ||
67 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | 67 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
68 | /** | 68 | /** |
69 | * rfkill_alloc - allocate rfkill structure | 69 | * rfkill_alloc - Allocate rfkill structure |
70 | * @name: name of the struct -- the string is not copied internally | 70 | * @name: name of the struct -- the string is not copied internally |
71 | * @parent: device that has rf switch on it | 71 | * @parent: device that has rf switch on it |
72 | * @type: type of the switch (RFKILL_TYPE_*) | 72 | * @type: type of the switch (RFKILL_TYPE_*) |
@@ -112,7 +112,7 @@ void rfkill_pause_polling(struct rfkill *rfkill); | |||
112 | /** | 112 | /** |
113 | * rfkill_resume_polling(struct rfkill *rfkill) | 113 | * rfkill_resume_polling(struct rfkill *rfkill) |
114 | * | 114 | * |
115 | * Pause polling -- say transmitter is off for other reasons. | 115 | * Resume polling |
116 | * NOTE: not necessary for suspend/resume -- in that case the | 116 | * NOTE: not necessary for suspend/resume -- in that case the |
117 | * core stops polling anyway | 117 | * core stops polling anyway |
118 | */ | 118 | */ |
@@ -130,7 +130,7 @@ void rfkill_resume_polling(struct rfkill *rfkill); | |||
130 | void rfkill_unregister(struct rfkill *rfkill); | 130 | void rfkill_unregister(struct rfkill *rfkill); |
131 | 131 | ||
132 | /** | 132 | /** |
133 | * rfkill_destroy - free rfkill structure | 133 | * rfkill_destroy - Free rfkill structure |
134 | * @rfkill: rfkill structure to be destroyed | 134 | * @rfkill: rfkill structure to be destroyed |
135 | * | 135 | * |
136 | * Destroys the rfkill structure. | 136 | * Destroys the rfkill structure. |
@@ -140,7 +140,7 @@ void rfkill_destroy(struct rfkill *rfkill); | |||
140 | /** | 140 | /** |
141 | * rfkill_set_hw_state - Set the internal rfkill hardware block state | 141 | * rfkill_set_hw_state - Set the internal rfkill hardware block state |
142 | * @rfkill: pointer to the rfkill class to modify. | 142 | * @rfkill: pointer to the rfkill class to modify. |
143 | * @state: the current hardware block state to set | 143 | * @blocked: the current hardware block state to set |
144 | * | 144 | * |
145 | * rfkill drivers that get events when the hard-blocked state changes | 145 | * rfkill drivers that get events when the hard-blocked state changes |
146 | * use this function to notify the rfkill core (and through that also | 146 | * use this function to notify the rfkill core (and through that also |
@@ -161,7 +161,7 @@ bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked); | |||
161 | /** | 161 | /** |
162 | * rfkill_set_sw_state - Set the internal rfkill software block state | 162 | * rfkill_set_sw_state - Set the internal rfkill software block state |
163 | * @rfkill: pointer to the rfkill class to modify. | 163 | * @rfkill: pointer to the rfkill class to modify. |
164 | * @state: the current software block state to set | 164 | * @blocked: the current software block state to set |
165 | * | 165 | * |
166 | * rfkill drivers that get events when the soft-blocked state changes | 166 | * rfkill drivers that get events when the soft-blocked state changes |
167 | * (yes, some platforms directly act on input but allow changing again) | 167 | * (yes, some platforms directly act on input but allow changing again) |
@@ -183,7 +183,7 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked); | |||
183 | /** | 183 | /** |
184 | * rfkill_init_sw_state - Initialize persistent software block state | 184 | * rfkill_init_sw_state - Initialize persistent software block state |
185 | * @rfkill: pointer to the rfkill class to modify. | 185 | * @rfkill: pointer to the rfkill class to modify. |
186 | * @state: the current software block state to set | 186 | * @blocked: the current software block state to set |
187 | * | 187 | * |
188 | * rfkill drivers that preserve their software block state over power off | 188 | * rfkill drivers that preserve their software block state over power off |
189 | * use this function to notify the rfkill core (and through that also | 189 | * use this function to notify the rfkill core (and through that also |
@@ -208,17 +208,17 @@ void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked); | |||
208 | void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw); | 208 | void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw); |
209 | 209 | ||
210 | /** | 210 | /** |
211 | * rfkill_blocked - query rfkill block | 211 | * rfkill_blocked - Query rfkill block state |
212 | * | 212 | * |
213 | * @rfkill: rfkill struct to query | 213 | * @rfkill: rfkill struct to query |
214 | */ | 214 | */ |
215 | bool rfkill_blocked(struct rfkill *rfkill); | 215 | bool rfkill_blocked(struct rfkill *rfkill); |
216 | 216 | ||
217 | /** | 217 | /** |
218 | * rfkill_find_type - Helpper for finding rfkill type by name | 218 | * rfkill_find_type - Helper for finding rfkill type by name |
219 | * @name: the name of the type | 219 | * @name: the name of the type |
220 | * | 220 | * |
221 | * Returns enum rfkill_type that conrresponds the name. | 221 | * Returns enum rfkill_type that corresponds to the name. |
222 | */ | 222 | */ |
223 | enum rfkill_type rfkill_find_type(const char *name); | 223 | enum rfkill_type rfkill_find_type(const char *name); |
224 | 224 | ||
@@ -296,7 +296,7 @@ static inline enum rfkill_type rfkill_find_type(const char *name) | |||
296 | const char *rfkill_get_led_trigger_name(struct rfkill *rfkill); | 296 | const char *rfkill_get_led_trigger_name(struct rfkill *rfkill); |
297 | 297 | ||
298 | /** | 298 | /** |
299 | * rfkill_set_led_trigger_name -- set the LED trigger name | 299 | * rfkill_set_led_trigger_name - Set the LED trigger name |
300 | * @rfkill: rfkill struct | 300 | * @rfkill: rfkill struct |
301 | * @name: LED trigger name | 301 | * @name: LED trigger name |
302 | * | 302 | * |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5fbfe61f41c6..9ba1f289c439 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -285,6 +285,41 @@ struct ieee80211_sta_vht_cap { | |||
285 | struct ieee80211_vht_mcs_info vht_mcs; | 285 | struct ieee80211_vht_mcs_info vht_mcs; |
286 | }; | 286 | }; |
287 | 287 | ||
288 | #define IEEE80211_HE_PPE_THRES_MAX_LEN 25 | ||
289 | |||
290 | /** | ||
291 | * struct ieee80211_sta_he_cap - STA's HE capabilities | ||
292 | * | ||
293 | * This structure describes most essential parameters needed | ||
294 | * to describe 802.11ax HE capabilities for a STA. | ||
295 | * | ||
296 | * @has_he: true iff HE data is valid. | ||
297 | * @he_cap_elem: Fixed portion of the HE capabilities element. | ||
298 | * @he_mcs_nss_supp: The supported NSS/MCS combinations. | ||
299 | * @ppe_thres: Holds the PPE Thresholds data. | ||
300 | */ | ||
301 | struct ieee80211_sta_he_cap { | ||
302 | bool has_he; | ||
303 | struct ieee80211_he_cap_elem he_cap_elem; | ||
304 | struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; | ||
305 | u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; | ||
306 | }; | ||
307 | |||
308 | /** | ||
309 | * struct ieee80211_sband_iftype_data | ||
310 | * | ||
311 | * This structure encapsulates sband data that is relevant for the | ||
312 | * interface types defined in @types_mask. Each type in the | ||
313 | * @types_mask must be unique across all instances of iftype_data. | ||
314 | * | ||
315 | * @types_mask: interface types mask | ||
316 | * @he_cap: holds the HE capabilities | ||
317 | */ | ||
318 | struct ieee80211_sband_iftype_data { | ||
319 | u16 types_mask; | ||
320 | struct ieee80211_sta_he_cap he_cap; | ||
321 | }; | ||
322 | |||
288 | /** | 323 | /** |
289 | * struct ieee80211_supported_band - frequency band definition | 324 | * struct ieee80211_supported_band - frequency band definition |
290 | * | 325 | * |
@@ -301,6 +336,11 @@ struct ieee80211_sta_vht_cap { | |||
301 | * @n_bitrates: Number of bitrates in @bitrates | 336 | * @n_bitrates: Number of bitrates in @bitrates |
302 | * @ht_cap: HT capabilities in this band | 337 | * @ht_cap: HT capabilities in this band |
303 | * @vht_cap: VHT capabilities in this band | 338 | * @vht_cap: VHT capabilities in this band |
339 | * @n_iftype_data: number of iftype data entries | ||
340 | * @iftype_data: interface type data entries. Note that the bits in | ||
341 | * @types_mask inside this structure cannot overlap (i.e. only | ||
342 | * one occurrence of each type is allowed across all instances of | ||
343 | * iftype_data). | ||
304 | */ | 344 | */ |
305 | struct ieee80211_supported_band { | 345 | struct ieee80211_supported_band { |
306 | struct ieee80211_channel *channels; | 346 | struct ieee80211_channel *channels; |
@@ -310,9 +350,56 @@ struct ieee80211_supported_band { | |||
310 | int n_bitrates; | 350 | int n_bitrates; |
311 | struct ieee80211_sta_ht_cap ht_cap; | 351 | struct ieee80211_sta_ht_cap ht_cap; |
312 | struct ieee80211_sta_vht_cap vht_cap; | 352 | struct ieee80211_sta_vht_cap vht_cap; |
353 | u16 n_iftype_data; | ||
354 | const struct ieee80211_sband_iftype_data *iftype_data; | ||
313 | }; | 355 | }; |
314 | 356 | ||
315 | /** | 357 | /** |
358 | * ieee80211_get_sband_iftype_data - return sband data for a given iftype | ||
359 | * @sband: the sband to search for the STA on | ||
360 | * @iftype: enum nl80211_iftype | ||
361 | * | ||
362 | * Return: pointer to struct ieee80211_sband_iftype_data, or NULL is none found | ||
363 | */ | ||
364 | static inline const struct ieee80211_sband_iftype_data * | ||
365 | ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband, | ||
366 | u8 iftype) | ||
367 | { | ||
368 | int i; | ||
369 | |||
370 | if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) | ||
371 | return NULL; | ||
372 | |||
373 | for (i = 0; i < sband->n_iftype_data; i++) { | ||
374 | const struct ieee80211_sband_iftype_data *data = | ||
375 | &sband->iftype_data[i]; | ||
376 | |||
377 | if (data->types_mask & BIT(iftype)) | ||
378 | return data; | ||
379 | } | ||
380 | |||
381 | return NULL; | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * ieee80211_get_he_sta_cap - return HE capabilities for an sband's STA | ||
386 | * @sband: the sband to search for the STA on | ||
387 | * | ||
388 | * Return: pointer to the struct ieee80211_sta_he_cap, or NULL is none found | ||
389 | */ | ||
390 | static inline const struct ieee80211_sta_he_cap * | ||
391 | ieee80211_get_he_sta_cap(const struct ieee80211_supported_band *sband) | ||
392 | { | ||
393 | const struct ieee80211_sband_iftype_data *data = | ||
394 | ieee80211_get_sband_iftype_data(sband, NL80211_IFTYPE_STATION); | ||
395 | |||
396 | if (data && data->he_cap.has_he) | ||
397 | return &data->he_cap; | ||
398 | |||
399 | return NULL; | ||
400 | } | ||
401 | |||
402 | /** | ||
316 | * wiphy_read_of_freq_limits - read frequency limits from device tree | 403 | * wiphy_read_of_freq_limits - read frequency limits from device tree |
317 | * | 404 | * |
318 | * @wiphy: the wireless device to get extra limits for | 405 | * @wiphy: the wireless device to get extra limits for |
@@ -899,6 +986,8 @@ enum station_parameters_apply_mask { | |||
899 | * @opmode_notif: operating mode field from Operating Mode Notification | 986 | * @opmode_notif: operating mode field from Operating Mode Notification |
900 | * @opmode_notif_used: information if operating mode field is used | 987 | * @opmode_notif_used: information if operating mode field is used |
901 | * @support_p2p_ps: information if station supports P2P PS mechanism | 988 | * @support_p2p_ps: information if station supports P2P PS mechanism |
989 | * @he_capa: HE capabilities of station | ||
990 | * @he_capa_len: the length of the HE capabilities | ||
902 | */ | 991 | */ |
903 | struct station_parameters { | 992 | struct station_parameters { |
904 | const u8 *supported_rates; | 993 | const u8 *supported_rates; |
@@ -926,6 +1015,8 @@ struct station_parameters { | |||
926 | u8 opmode_notif; | 1015 | u8 opmode_notif; |
927 | bool opmode_notif_used; | 1016 | bool opmode_notif_used; |
928 | int support_p2p_ps; | 1017 | int support_p2p_ps; |
1018 | const struct ieee80211_he_cap_elem *he_capa; | ||
1019 | u8 he_capa_len; | ||
929 | }; | 1020 | }; |
930 | 1021 | ||
931 | /** | 1022 | /** |
@@ -1000,12 +1091,14 @@ int cfg80211_check_station_change(struct wiphy *wiphy, | |||
1000 | * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS | 1091 | * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS |
1001 | * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval | 1092 | * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval |
1002 | * @RATE_INFO_FLAGS_60G: 60GHz MCS | 1093 | * @RATE_INFO_FLAGS_60G: 60GHz MCS |
1094 | * @RATE_INFO_FLAGS_HE_MCS: HE MCS information | ||
1003 | */ | 1095 | */ |
1004 | enum rate_info_flags { | 1096 | enum rate_info_flags { |
1005 | RATE_INFO_FLAGS_MCS = BIT(0), | 1097 | RATE_INFO_FLAGS_MCS = BIT(0), |
1006 | RATE_INFO_FLAGS_VHT_MCS = BIT(1), | 1098 | RATE_INFO_FLAGS_VHT_MCS = BIT(1), |
1007 | RATE_INFO_FLAGS_SHORT_GI = BIT(2), | 1099 | RATE_INFO_FLAGS_SHORT_GI = BIT(2), |
1008 | RATE_INFO_FLAGS_60G = BIT(3), | 1100 | RATE_INFO_FLAGS_60G = BIT(3), |
1101 | RATE_INFO_FLAGS_HE_MCS = BIT(4), | ||
1009 | }; | 1102 | }; |
1010 | 1103 | ||
1011 | /** | 1104 | /** |
@@ -1019,6 +1112,7 @@ enum rate_info_flags { | |||
1019 | * @RATE_INFO_BW_40: 40 MHz bandwidth | 1112 | * @RATE_INFO_BW_40: 40 MHz bandwidth |
1020 | * @RATE_INFO_BW_80: 80 MHz bandwidth | 1113 | * @RATE_INFO_BW_80: 80 MHz bandwidth |
1021 | * @RATE_INFO_BW_160: 160 MHz bandwidth | 1114 | * @RATE_INFO_BW_160: 160 MHz bandwidth |
1115 | * @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation | ||
1022 | */ | 1116 | */ |
1023 | enum rate_info_bw { | 1117 | enum rate_info_bw { |
1024 | RATE_INFO_BW_20 = 0, | 1118 | RATE_INFO_BW_20 = 0, |
@@ -1027,6 +1121,7 @@ enum rate_info_bw { | |||
1027 | RATE_INFO_BW_40, | 1121 | RATE_INFO_BW_40, |
1028 | RATE_INFO_BW_80, | 1122 | RATE_INFO_BW_80, |
1029 | RATE_INFO_BW_160, | 1123 | RATE_INFO_BW_160, |
1124 | RATE_INFO_BW_HE_RU, | ||
1030 | }; | 1125 | }; |
1031 | 1126 | ||
1032 | /** | 1127 | /** |
@@ -1035,10 +1130,14 @@ enum rate_info_bw { | |||
1035 | * Information about a receiving or transmitting bitrate | 1130 | * Information about a receiving or transmitting bitrate |
1036 | * | 1131 | * |
1037 | * @flags: bitflag of flags from &enum rate_info_flags | 1132 | * @flags: bitflag of flags from &enum rate_info_flags |
1038 | * @mcs: mcs index if struct describes a 802.11n bitrate | 1133 | * @mcs: mcs index if struct describes an HT/VHT/HE rate |
1039 | * @legacy: bitrate in 100kbit/s for 802.11abg | 1134 | * @legacy: bitrate in 100kbit/s for 802.11abg |
1040 | * @nss: number of streams (VHT only) | 1135 | * @nss: number of streams (VHT & HE only) |
1041 | * @bw: bandwidth (from &enum rate_info_bw) | 1136 | * @bw: bandwidth (from &enum rate_info_bw) |
1137 | * @he_gi: HE guard interval (from &enum nl80211_he_gi) | ||
1138 | * @he_dcm: HE DCM value | ||
1139 | * @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc, | ||
1140 | * only valid if bw is %RATE_INFO_BW_HE_RU) | ||
1042 | */ | 1141 | */ |
1043 | struct rate_info { | 1142 | struct rate_info { |
1044 | u8 flags; | 1143 | u8 flags; |
@@ -1046,6 +1145,9 @@ struct rate_info { | |||
1046 | u16 legacy; | 1145 | u16 legacy; |
1047 | u8 nss; | 1146 | u8 nss; |
1048 | u8 bw; | 1147 | u8 bw; |
1148 | u8 he_gi; | ||
1149 | u8 he_dcm; | ||
1150 | u8 he_ru_alloc; | ||
1049 | }; | 1151 | }; |
1050 | 1152 | ||
1051 | /** | 1153 | /** |
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 960236fb1681..feef706e1158 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2017 Intel Deutschland GmbH | 2 | * Copyright (c) 2017 Intel Deutschland GmbH |
3 | * Copyright (c) 2018 Intel Corporation | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -72,6 +73,8 @@ enum ieee80211_radiotap_presence { | |||
72 | IEEE80211_RADIOTAP_AMPDU_STATUS = 20, | 73 | IEEE80211_RADIOTAP_AMPDU_STATUS = 20, |
73 | IEEE80211_RADIOTAP_VHT = 21, | 74 | IEEE80211_RADIOTAP_VHT = 21, |
74 | IEEE80211_RADIOTAP_TIMESTAMP = 22, | 75 | IEEE80211_RADIOTAP_TIMESTAMP = 22, |
76 | IEEE80211_RADIOTAP_HE = 23, | ||
77 | IEEE80211_RADIOTAP_HE_MU = 24, | ||
75 | 78 | ||
76 | /* valid in every it_present bitmap, even vendor namespaces */ | 79 | /* valid in every it_present bitmap, even vendor namespaces */ |
77 | IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, | 80 | IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, |
@@ -202,6 +205,126 @@ enum ieee80211_radiotap_timestamp_flags { | |||
202 | IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02, | 205 | IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02, |
203 | }; | 206 | }; |
204 | 207 | ||
208 | struct ieee80211_radiotap_he { | ||
209 | __le16 data1, data2, data3, data4, data5, data6; | ||
210 | }; | ||
211 | |||
212 | enum ieee80211_radiotap_he_bits { | ||
213 | IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3, | ||
214 | IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0, | ||
215 | IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1, | ||
216 | IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2, | ||
217 | IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3, | ||
218 | |||
219 | IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004, | ||
220 | IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008, | ||
221 | IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010, | ||
222 | IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020, | ||
223 | IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040, | ||
224 | IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080, | ||
225 | IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100, | ||
226 | IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200, | ||
227 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400, | ||
228 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800, | ||
229 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000, | ||
230 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000, | ||
231 | IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000, | ||
232 | IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000, | ||
233 | |||
234 | IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001, | ||
235 | IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002, | ||
236 | IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004, | ||
237 | IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008, | ||
238 | IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010, | ||
239 | IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020, | ||
240 | IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040, | ||
241 | IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080, | ||
242 | IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00, | ||
243 | IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000, | ||
244 | IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000, | ||
245 | |||
246 | IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f, | ||
247 | IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040, | ||
248 | IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080, | ||
249 | IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00, | ||
250 | IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000, | ||
251 | IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000, | ||
252 | IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000, | ||
253 | IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000, | ||
254 | |||
255 | IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f, | ||
256 | IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0, | ||
257 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f, | ||
258 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0, | ||
259 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00, | ||
260 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000, | ||
261 | |||
262 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f, | ||
263 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0, | ||
264 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1, | ||
265 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2, | ||
266 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3, | ||
267 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4, | ||
268 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5, | ||
269 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6, | ||
270 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7, | ||
271 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8, | ||
272 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9, | ||
273 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10, | ||
274 | |||
275 | IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030, | ||
276 | IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0, | ||
277 | IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1, | ||
278 | IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2, | ||
279 | |||
280 | IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0, | ||
281 | IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0, | ||
282 | IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1, | ||
283 | IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2, | ||
284 | IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3, | ||
285 | IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700, | ||
286 | IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000, | ||
287 | IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000, | ||
288 | IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000, | ||
289 | |||
290 | IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f, | ||
291 | IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010, | ||
292 | IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00, | ||
293 | IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000, | ||
294 | }; | ||
295 | |||
296 | struct ieee80211_radiotap_he_mu { | ||
297 | __le16 flags1, flags2; | ||
298 | u8 ru_ch1[4]; | ||
299 | u8 ru_ch2[4]; | ||
300 | }; | ||
301 | |||
302 | enum ieee80211_radiotap_he_mu_bits { | ||
303 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f, | ||
304 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010, | ||
305 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020, | ||
306 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040, | ||
307 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080, | ||
308 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100, | ||
309 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200, | ||
310 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000, | ||
311 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000, | ||
312 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000, | ||
313 | IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000, | ||
314 | |||
315 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003, | ||
316 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000, | ||
317 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001, | ||
318 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002, | ||
319 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003, | ||
320 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004, | ||
321 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008, | ||
322 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0, | ||
323 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300, | ||
324 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN= 0x0400, | ||
325 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800, | ||
326 | }; | ||
327 | |||
205 | /** | 328 | /** |
206 | * ieee80211_get_radiotap_len - get radiotap header length | 329 | * ieee80211_get_radiotap_len - get radiotap header length |
207 | */ | 330 | */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 851a5e19ae32..5790f55c241d 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/ieee80211.h> | 23 | #include <linux/ieee80211.h> |
24 | #include <net/cfg80211.h> | 24 | #include <net/cfg80211.h> |
25 | #include <net/codel.h> | 25 | #include <net/codel.h> |
26 | #include <net/ieee80211_radiotap.h> | ||
26 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
27 | 28 | ||
28 | /** | 29 | /** |
@@ -162,6 +163,8 @@ enum ieee80211_ac_numbers { | |||
162 | * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled | 163 | * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled |
163 | * @acm: is mandatory admission control required for the access category | 164 | * @acm: is mandatory admission control required for the access category |
164 | * @uapsd: is U-APSD mode enabled for the queue | 165 | * @uapsd: is U-APSD mode enabled for the queue |
166 | * @mu_edca: is the MU EDCA configured | ||
167 | * @mu_edca_param_rec: MU EDCA Parameter Record for HE | ||
165 | */ | 168 | */ |
166 | struct ieee80211_tx_queue_params { | 169 | struct ieee80211_tx_queue_params { |
167 | u16 txop; | 170 | u16 txop; |
@@ -170,6 +173,8 @@ struct ieee80211_tx_queue_params { | |||
170 | u8 aifs; | 173 | u8 aifs; |
171 | bool acm; | 174 | bool acm; |
172 | bool uapsd; | 175 | bool uapsd; |
176 | bool mu_edca; | ||
177 | struct ieee80211_he_mu_edca_param_ac_rec mu_edca_param_rec; | ||
173 | }; | 178 | }; |
174 | 179 | ||
175 | struct ieee80211_low_level_stats { | 180 | struct ieee80211_low_level_stats { |
@@ -463,6 +468,15 @@ struct ieee80211_mu_group_data { | |||
463 | * This structure keeps information about a BSS (and an association | 468 | * This structure keeps information about a BSS (and an association |
464 | * to that BSS) that can change during the lifetime of the BSS. | 469 | * to that BSS) that can change during the lifetime of the BSS. |
465 | * | 470 | * |
471 | * @bss_color: 6-bit value to mark inter-BSS frame, if BSS supports HE | ||
472 | * @htc_trig_based_pkt_ext: default PE in 4us units, if BSS supports HE | ||
473 | * @multi_sta_back_32bit: supports BA bitmap of 32-bits in Multi-STA BACK | ||
474 | * @uora_exists: is the UORA element advertised by AP | ||
475 | * @ack_enabled: indicates support to receive a multi-TID that solicits either | ||
476 | * ACK, BACK or both | ||
477 | * @uora_ocw_range: UORA element's OCW Range field | ||
478 | * @frame_time_rts_th: HE duration RTS threshold, in units of 32us | ||
479 | * @he_support: does this BSS support HE | ||
466 | * @assoc: association status | 480 | * @assoc: association status |
467 | * @ibss_joined: indicates whether this station is part of an IBSS | 481 | * @ibss_joined: indicates whether this station is part of an IBSS |
468 | * or not | 482 | * or not |
@@ -550,6 +564,14 @@ struct ieee80211_mu_group_data { | |||
550 | */ | 564 | */ |
551 | struct ieee80211_bss_conf { | 565 | struct ieee80211_bss_conf { |
552 | const u8 *bssid; | 566 | const u8 *bssid; |
567 | u8 bss_color; | ||
568 | u8 htc_trig_based_pkt_ext; | ||
569 | bool multi_sta_back_32bit; | ||
570 | bool uora_exists; | ||
571 | bool ack_enabled; | ||
572 | u8 uora_ocw_range; | ||
573 | u16 frame_time_rts_th; | ||
574 | bool he_support; | ||
553 | /* association related data */ | 575 | /* association related data */ |
554 | bool assoc, ibss_joined; | 576 | bool assoc, ibss_joined; |
555 | bool ibss_creator; | 577 | bool ibss_creator; |
@@ -1106,6 +1128,18 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) | |||
1106 | * @RX_FLAG_AMPDU_EOF_BIT: Value of the EOF bit in the A-MPDU delimiter for this | 1128 | * @RX_FLAG_AMPDU_EOF_BIT: Value of the EOF bit in the A-MPDU delimiter for this |
1107 | * frame | 1129 | * frame |
1108 | * @RX_FLAG_AMPDU_EOF_BIT_KNOWN: The EOF value is known | 1130 | * @RX_FLAG_AMPDU_EOF_BIT_KNOWN: The EOF value is known |
1131 | * @RX_FLAG_RADIOTAP_HE: HE radiotap data is present | ||
1132 | * (&struct ieee80211_radiotap_he, mac80211 will fill in | ||
1133 | * - DATA3_DATA_MCS | ||
1134 | * - DATA3_DATA_DCM | ||
1135 | * - DATA3_CODING | ||
1136 | * - DATA5_GI | ||
1137 | * - DATA5_DATA_BW_RU_ALLOC | ||
1138 | * - DATA6_NSTS | ||
1139 | * - DATA3_STBC | ||
1140 | * from the RX info data, so leave those zeroed when building this data) | ||
1141 | * @RX_FLAG_RADIOTAP_HE_MU: HE MU radiotap data is present | ||
1142 | * (&struct ieee80211_radiotap_he_mu) | ||
1109 | */ | 1143 | */ |
1110 | enum mac80211_rx_flags { | 1144 | enum mac80211_rx_flags { |
1111 | RX_FLAG_MMIC_ERROR = BIT(0), | 1145 | RX_FLAG_MMIC_ERROR = BIT(0), |
@@ -1134,6 +1168,8 @@ enum mac80211_rx_flags { | |||
1134 | RX_FLAG_ICV_STRIPPED = BIT(23), | 1168 | RX_FLAG_ICV_STRIPPED = BIT(23), |
1135 | RX_FLAG_AMPDU_EOF_BIT = BIT(24), | 1169 | RX_FLAG_AMPDU_EOF_BIT = BIT(24), |
1136 | RX_FLAG_AMPDU_EOF_BIT_KNOWN = BIT(25), | 1170 | RX_FLAG_AMPDU_EOF_BIT_KNOWN = BIT(25), |
1171 | RX_FLAG_RADIOTAP_HE = BIT(26), | ||
1172 | RX_FLAG_RADIOTAP_HE_MU = BIT(27), | ||
1137 | }; | 1173 | }; |
1138 | 1174 | ||
1139 | /** | 1175 | /** |
@@ -1164,6 +1200,7 @@ enum mac80211_rx_encoding { | |||
1164 | RX_ENC_LEGACY = 0, | 1200 | RX_ENC_LEGACY = 0, |
1165 | RX_ENC_HT, | 1201 | RX_ENC_HT, |
1166 | RX_ENC_VHT, | 1202 | RX_ENC_VHT, |
1203 | RX_ENC_HE, | ||
1167 | }; | 1204 | }; |
1168 | 1205 | ||
1169 | /** | 1206 | /** |
@@ -1198,6 +1235,9 @@ enum mac80211_rx_encoding { | |||
1198 | * @encoding: &enum mac80211_rx_encoding | 1235 | * @encoding: &enum mac80211_rx_encoding |
1199 | * @bw: &enum rate_info_bw | 1236 | * @bw: &enum rate_info_bw |
1200 | * @enc_flags: uses bits from &enum mac80211_rx_encoding_flags | 1237 | * @enc_flags: uses bits from &enum mac80211_rx_encoding_flags |
1238 | * @he_ru: HE RU, from &enum nl80211_he_ru_alloc | ||
1239 | * @he_gi: HE GI, from &enum nl80211_he_gi | ||
1240 | * @he_dcm: HE DCM value | ||
1201 | * @rx_flags: internal RX flags for mac80211 | 1241 | * @rx_flags: internal RX flags for mac80211 |
1202 | * @ampdu_reference: A-MPDU reference number, must be a different value for | 1242 | * @ampdu_reference: A-MPDU reference number, must be a different value for |
1203 | * each A-MPDU but the same for each subframe within one A-MPDU | 1243 | * each A-MPDU but the same for each subframe within one A-MPDU |
@@ -1211,7 +1251,8 @@ struct ieee80211_rx_status { | |||
1211 | u32 flag; | 1251 | u32 flag; |
1212 | u16 freq; | 1252 | u16 freq; |
1213 | u8 enc_flags; | 1253 | u8 enc_flags; |
1214 | u8 encoding:2, bw:3; | 1254 | u8 encoding:2, bw:3, he_ru:3; |
1255 | u8 he_gi:2, he_dcm:1; | ||
1215 | u8 rate_idx; | 1256 | u8 rate_idx; |
1216 | u8 nss; | 1257 | u8 nss; |
1217 | u8 rx_flags; | 1258 | u8 rx_flags; |
@@ -1770,6 +1811,7 @@ struct ieee80211_sta_rates { | |||
1770 | * @supp_rates: Bitmap of supported rates (per band) | 1811 | * @supp_rates: Bitmap of supported rates (per band) |
1771 | * @ht_cap: HT capabilities of this STA; restricted to our own capabilities | 1812 | * @ht_cap: HT capabilities of this STA; restricted to our own capabilities |
1772 | * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities | 1813 | * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities |
1814 | * @he_cap: HE capabilities of this STA | ||
1773 | * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU | 1815 | * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU |
1774 | * that this station is allowed to transmit to us. | 1816 | * that this station is allowed to transmit to us. |
1775 | * Can be modified by driver. | 1817 | * Can be modified by driver. |
@@ -1805,7 +1847,8 @@ struct ieee80211_sta { | |||
1805 | u16 aid; | 1847 | u16 aid; |
1806 | struct ieee80211_sta_ht_cap ht_cap; | 1848 | struct ieee80211_sta_ht_cap ht_cap; |
1807 | struct ieee80211_sta_vht_cap vht_cap; | 1849 | struct ieee80211_sta_vht_cap vht_cap; |
1808 | u8 max_rx_aggregation_subframes; | 1850 | struct ieee80211_sta_he_cap he_cap; |
1851 | u16 max_rx_aggregation_subframes; | ||
1809 | bool wme; | 1852 | bool wme; |
1810 | u8 uapsd_queues; | 1853 | u8 uapsd_queues; |
1811 | u8 max_sp; | 1854 | u8 max_sp; |
@@ -2196,10 +2239,11 @@ enum ieee80211_hw_flags { | |||
2196 | * it shouldn't be set. | 2239 | * it shouldn't be set. |
2197 | * | 2240 | * |
2198 | * @max_tx_aggregation_subframes: maximum number of subframes in an | 2241 | * @max_tx_aggregation_subframes: maximum number of subframes in an |
2199 | * aggregate an HT driver will transmit. Though ADDBA will advertise | 2242 | * aggregate an HT/HE device will transmit. In HT AddBA we'll |
2200 | * a constant value of 64 as some older APs can crash if the window | 2243 | * advertise a constant value of 64 as some older APs crash if |
2201 | * size is smaller (an example is LinkSys WRT120N with FW v1.0.07 | 2244 | * the window size is smaller (an example is LinkSys WRT120N |
2202 | * build 002 Jun 18 2012). | 2245 | * with FW v1.0.07 build 002 Jun 18 2012). |
2246 | * For AddBA to HE capable peers this value will be used. | ||
2203 | * | 2247 | * |
2204 | * @max_tx_fragments: maximum number of tx buffers per (A)-MSDU, sum | 2248 | * @max_tx_fragments: maximum number of tx buffers per (A)-MSDU, sum |
2205 | * of 1 + skb_shinfo(skb)->nr_frags for each skb in the frag_list. | 2249 | * of 1 + skb_shinfo(skb)->nr_frags for each skb in the frag_list. |
@@ -2216,6 +2260,8 @@ enum ieee80211_hw_flags { | |||
2216 | * the default is _GI | _BANDWIDTH. | 2260 | * the default is _GI | _BANDWIDTH. |
2217 | * Use the %IEEE80211_RADIOTAP_VHT_KNOWN_\* values. | 2261 | * Use the %IEEE80211_RADIOTAP_VHT_KNOWN_\* values. |
2218 | * | 2262 | * |
2263 | * @radiotap_he: HE radiotap validity flags | ||
2264 | * | ||
2219 | * @radiotap_timestamp: Information for the radiotap timestamp field; if the | 2265 | * @radiotap_timestamp: Information for the radiotap timestamp field; if the |
2220 | * 'units_pos' member is set to a non-negative value it must be set to | 2266 | * 'units_pos' member is set to a non-negative value it must be set to |
2221 | * a combination of a IEEE80211_RADIOTAP_TIMESTAMP_UNIT_* and a | 2267 | * a combination of a IEEE80211_RADIOTAP_TIMESTAMP_UNIT_* and a |
@@ -2263,8 +2309,8 @@ struct ieee80211_hw { | |||
2263 | u8 max_rates; | 2309 | u8 max_rates; |
2264 | u8 max_report_rates; | 2310 | u8 max_report_rates; |
2265 | u8 max_rate_tries; | 2311 | u8 max_rate_tries; |
2266 | u8 max_rx_aggregation_subframes; | 2312 | u16 max_rx_aggregation_subframes; |
2267 | u8 max_tx_aggregation_subframes; | 2313 | u16 max_tx_aggregation_subframes; |
2268 | u8 max_tx_fragments; | 2314 | u8 max_tx_fragments; |
2269 | u8 offchannel_tx_hw_queue; | 2315 | u8 offchannel_tx_hw_queue; |
2270 | u8 radiotap_mcs_details; | 2316 | u8 radiotap_mcs_details; |
@@ -2904,7 +2950,7 @@ struct ieee80211_ampdu_params { | |||
2904 | struct ieee80211_sta *sta; | 2950 | struct ieee80211_sta *sta; |
2905 | u16 tid; | 2951 | u16 tid; |
2906 | u16 ssn; | 2952 | u16 ssn; |
2907 | u8 buf_size; | 2953 | u16 buf_size; |
2908 | bool amsdu; | 2954 | bool amsdu; |
2909 | u16 timeout; | 2955 | u16 timeout; |
2910 | }; | 2956 | }; |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 27e4e441caac..7acc16f34942 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -2237,6 +2237,9 @@ enum nl80211_commands { | |||
2237 | * enforced. | 2237 | * enforced. |
2238 | * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes | 2238 | * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes |
2239 | * a flow is assigned on each round of the DRR scheduler. | 2239 | * a flow is assigned on each round of the DRR scheduler. |
2240 | * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from | ||
2241 | * association request when used with NL80211_CMD_NEW_STATION). Can be set | ||
2242 | * only if %NL80211_STA_FLAG_WME is set. | ||
2240 | * | 2243 | * |
2241 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available | 2244 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
2242 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 2245 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
@@ -2677,6 +2680,8 @@ enum nl80211_attrs { | |||
2677 | NL80211_ATTR_TXQ_MEMORY_LIMIT, | 2680 | NL80211_ATTR_TXQ_MEMORY_LIMIT, |
2678 | NL80211_ATTR_TXQ_QUANTUM, | 2681 | NL80211_ATTR_TXQ_QUANTUM, |
2679 | 2682 | ||
2683 | NL80211_ATTR_HE_CAPABILITY, | ||
2684 | |||
2680 | /* add attributes here, update the policy in nl80211.c */ | 2685 | /* add attributes here, update the policy in nl80211.c */ |
2681 | 2686 | ||
2682 | __NL80211_ATTR_AFTER_LAST, | 2687 | __NL80211_ATTR_AFTER_LAST, |
@@ -2726,7 +2731,8 @@ enum nl80211_attrs { | |||
2726 | #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 | 2731 | #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 |
2727 | #define NL80211_HT_CAPABILITY_LEN 26 | 2732 | #define NL80211_HT_CAPABILITY_LEN 26 |
2728 | #define NL80211_VHT_CAPABILITY_LEN 12 | 2733 | #define NL80211_VHT_CAPABILITY_LEN 12 |
2729 | 2734 | #define NL80211_HE_MIN_CAPABILITY_LEN 16 | |
2735 | #define NL80211_HE_MAX_CAPABILITY_LEN 51 | ||
2730 | #define NL80211_MAX_NR_CIPHER_SUITES 5 | 2736 | #define NL80211_MAX_NR_CIPHER_SUITES 5 |
2731 | #define NL80211_MAX_NR_AKM_SUITES 2 | 2737 | #define NL80211_MAX_NR_AKM_SUITES 2 |
2732 | 2738 | ||
@@ -2854,6 +2860,38 @@ struct nl80211_sta_flag_update { | |||
2854 | } __attribute__((packed)); | 2860 | } __attribute__((packed)); |
2855 | 2861 | ||
2856 | /** | 2862 | /** |
2863 | * enum nl80211_he_gi - HE guard interval | ||
2864 | * @NL80211_RATE_INFO_HE_GI_0_8: 0.8 usec | ||
2865 | * @NL80211_RATE_INFO_HE_GI_1_6: 1.6 usec | ||
2866 | * @NL80211_RATE_INFO_HE_GI_3_2: 3.2 usec | ||
2867 | */ | ||
2868 | enum nl80211_he_gi { | ||
2869 | NL80211_RATE_INFO_HE_GI_0_8, | ||
2870 | NL80211_RATE_INFO_HE_GI_1_6, | ||
2871 | NL80211_RATE_INFO_HE_GI_3_2, | ||
2872 | }; | ||
2873 | |||
2874 | /** | ||
2875 | * enum nl80211_he_ru_alloc - HE RU allocation values | ||
2876 | * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation | ||
2877 | * @NL80211_RATE_INFO_HE_RU_ALLOC_52: 52-tone RU allocation | ||
2878 | * @NL80211_RATE_INFO_HE_RU_ALLOC_106: 106-tone RU allocation | ||
2879 | * @NL80211_RATE_INFO_HE_RU_ALLOC_242: 242-tone RU allocation | ||
2880 | * @NL80211_RATE_INFO_HE_RU_ALLOC_484: 484-tone RU allocation | ||
2881 | * @NL80211_RATE_INFO_HE_RU_ALLOC_996: 996-tone RU allocation | ||
2882 | * @NL80211_RATE_INFO_HE_RU_ALLOC_2x996: 2x996-tone RU allocation | ||
2883 | */ | ||
2884 | enum nl80211_he_ru_alloc { | ||
2885 | NL80211_RATE_INFO_HE_RU_ALLOC_26, | ||
2886 | NL80211_RATE_INFO_HE_RU_ALLOC_52, | ||
2887 | NL80211_RATE_INFO_HE_RU_ALLOC_106, | ||
2888 | NL80211_RATE_INFO_HE_RU_ALLOC_242, | ||
2889 | NL80211_RATE_INFO_HE_RU_ALLOC_484, | ||
2890 | NL80211_RATE_INFO_HE_RU_ALLOC_996, | ||
2891 | NL80211_RATE_INFO_HE_RU_ALLOC_2x996, | ||
2892 | }; | ||
2893 | |||
2894 | /** | ||
2857 | * enum nl80211_rate_info - bitrate information | 2895 | * enum nl80211_rate_info - bitrate information |
2858 | * | 2896 | * |
2859 | * These attribute types are used with %NL80211_STA_INFO_TXRATE | 2897 | * These attribute types are used with %NL80211_STA_INFO_TXRATE |
@@ -2885,6 +2923,13 @@ struct nl80211_sta_flag_update { | |||
2885 | * @NL80211_RATE_INFO_5_MHZ_WIDTH: 5 MHz width - note that this is | 2923 | * @NL80211_RATE_INFO_5_MHZ_WIDTH: 5 MHz width - note that this is |
2886 | * a legacy rate and will be reported as the actual bitrate, i.e. | 2924 | * a legacy rate and will be reported as the actual bitrate, i.e. |
2887 | * a quarter of the base (20 MHz) rate | 2925 | * a quarter of the base (20 MHz) rate |
2926 | * @NL80211_RATE_INFO_HE_MCS: HE MCS index (u8, 0-11) | ||
2927 | * @NL80211_RATE_INFO_HE_NSS: HE NSS value (u8, 1-8) | ||
2928 | * @NL80211_RATE_INFO_HE_GI: HE guard interval identifier | ||
2929 | * (u8, see &enum nl80211_he_gi) | ||
2930 | * @NL80211_RATE_INFO_HE_DCM: HE DCM value (u8, 0/1) | ||
2931 | * @NL80211_RATE_INFO_RU_ALLOC: HE RU allocation, if not present then | ||
2932 | * non-OFDMA was used (u8, see &enum nl80211_he_ru_alloc) | ||
2888 | * @__NL80211_RATE_INFO_AFTER_LAST: internal use | 2933 | * @__NL80211_RATE_INFO_AFTER_LAST: internal use |
2889 | */ | 2934 | */ |
2890 | enum nl80211_rate_info { | 2935 | enum nl80211_rate_info { |
@@ -2901,6 +2946,11 @@ enum nl80211_rate_info { | |||
2901 | NL80211_RATE_INFO_160_MHZ_WIDTH, | 2946 | NL80211_RATE_INFO_160_MHZ_WIDTH, |
2902 | NL80211_RATE_INFO_10_MHZ_WIDTH, | 2947 | NL80211_RATE_INFO_10_MHZ_WIDTH, |
2903 | NL80211_RATE_INFO_5_MHZ_WIDTH, | 2948 | NL80211_RATE_INFO_5_MHZ_WIDTH, |
2949 | NL80211_RATE_INFO_HE_MCS, | ||
2950 | NL80211_RATE_INFO_HE_NSS, | ||
2951 | NL80211_RATE_INFO_HE_GI, | ||
2952 | NL80211_RATE_INFO_HE_DCM, | ||
2953 | NL80211_RATE_INFO_HE_RU_ALLOC, | ||
2904 | 2954 | ||
2905 | /* keep last */ | 2955 | /* keep last */ |
2906 | __NL80211_RATE_INFO_AFTER_LAST, | 2956 | __NL80211_RATE_INFO_AFTER_LAST, |
@@ -3167,6 +3217,38 @@ enum nl80211_mpath_info { | |||
3167 | }; | 3217 | }; |
3168 | 3218 | ||
3169 | /** | 3219 | /** |
3220 | * enum nl80211_band_iftype_attr - Interface type data attributes | ||
3221 | * | ||
3222 | * @__NL80211_BAND_IFTYPE_ATTR_INVALID: attribute number 0 is reserved | ||
3223 | * @NL80211_BAND_IFTYPE_ATTR_IFTYPES: nested attribute containing a flag attribute | ||
3224 | * for each interface type that supports the band data | ||
3225 | * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC: HE MAC capabilities as in HE | ||
3226 | * capabilities IE | ||
3227 | * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY: HE PHY capabilities as in HE | ||
3228 | * capabilities IE | ||
3229 | * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET: HE supported NSS/MCS as in HE | ||
3230 | * capabilities IE | ||
3231 | * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE: HE PPE thresholds information as | ||
3232 | * defined in HE capabilities IE | ||
3233 | * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently | ||
3234 | * defined | ||
3235 | * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use | ||
3236 | */ | ||
3237 | enum nl80211_band_iftype_attr { | ||
3238 | __NL80211_BAND_IFTYPE_ATTR_INVALID, | ||
3239 | |||
3240 | NL80211_BAND_IFTYPE_ATTR_IFTYPES, | ||
3241 | NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, | ||
3242 | NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, | ||
3243 | NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, | ||
3244 | NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, | ||
3245 | |||
3246 | /* keep last */ | ||
3247 | __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, | ||
3248 | NL80211_BAND_IFTYPE_ATTR_MAX = __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST - 1 | ||
3249 | }; | ||
3250 | |||
3251 | /** | ||
3170 | * enum nl80211_band_attr - band attributes | 3252 | * enum nl80211_band_attr - band attributes |
3171 | * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved | 3253 | * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved |
3172 | * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, | 3254 | * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, |
@@ -3181,6 +3263,8 @@ enum nl80211_mpath_info { | |||
3181 | * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as | 3263 | * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as |
3182 | * defined in 802.11ac | 3264 | * defined in 802.11ac |
3183 | * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE | 3265 | * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE |
3266 | * @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each entry using | ||
3267 | * attributes from &enum nl80211_band_iftype_attr | ||
3184 | * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined | 3268 | * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined |
3185 | * @__NL80211_BAND_ATTR_AFTER_LAST: internal use | 3269 | * @__NL80211_BAND_ATTR_AFTER_LAST: internal use |
3186 | */ | 3270 | */ |
@@ -3196,6 +3280,7 @@ enum nl80211_band_attr { | |||
3196 | 3280 | ||
3197 | NL80211_BAND_ATTR_VHT_MCS_SET, | 3281 | NL80211_BAND_ATTR_VHT_MCS_SET, |
3198 | NL80211_BAND_ATTR_VHT_CAPA, | 3282 | NL80211_BAND_ATTR_VHT_CAPA, |
3283 | NL80211_BAND_ATTR_IFTYPE_DATA, | ||
3199 | 3284 | ||
3200 | /* keep last */ | 3285 | /* keep last */ |
3201 | __NL80211_BAND_ATTR_AFTER_LAST, | 3286 | __NL80211_BAND_ATTR_AFTER_LAST, |
@@ -5133,6 +5218,11 @@ enum nl80211_feature_flags { | |||
5133 | * support to nl80211. | 5218 | * support to nl80211. |
5134 | * @NL80211_EXT_FEATURE_TXQS: Driver supports FQ-CoDel-enabled intermediate | 5219 | * @NL80211_EXT_FEATURE_TXQS: Driver supports FQ-CoDel-enabled intermediate |
5135 | * TXQs. | 5220 | * TXQs. |
5221 | * @NL80211_EXT_FEATURE_SCAN_RANDOM_SN: Driver/device supports randomizing the | ||
5222 | * SN in probe request frames if requested by %NL80211_SCAN_FLAG_RANDOM_SN. | ||
5223 | * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data | ||
5224 | * except for supported rates from the probe request content if requested | ||
5225 | * by the %NL80211_SCAN_FLAG_MIN_PREQ_CONTENT flag. | ||
5136 | * | 5226 | * |
5137 | * @NUM_NL80211_EXT_FEATURES: number of extended features. | 5227 | * @NUM_NL80211_EXT_FEATURES: number of extended features. |
5138 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. | 5228 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. |
@@ -5167,6 +5257,8 @@ enum nl80211_ext_feature_index { | |||
5167 | NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211, | 5257 | NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211, |
5168 | NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT, | 5258 | NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT, |
5169 | NL80211_EXT_FEATURE_TXQS, | 5259 | NL80211_EXT_FEATURE_TXQS, |
5260 | NL80211_EXT_FEATURE_SCAN_RANDOM_SN, | ||
5261 | NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT, | ||
5170 | 5262 | ||
5171 | /* add new features before the definition below */ | 5263 | /* add new features before the definition below */ |
5172 | NUM_NL80211_EXT_FEATURES, | 5264 | NUM_NL80211_EXT_FEATURES, |
@@ -5272,6 +5364,12 @@ enum nl80211_timeout_reason { | |||
5272 | * possible scan results. This flag hints the driver to use the best | 5364 | * possible scan results. This flag hints the driver to use the best |
5273 | * possible scan configuration to improve the accuracy in scanning. | 5365 | * possible scan configuration to improve the accuracy in scanning. |
5274 | * Latency and power use may get impacted with this flag. | 5366 | * Latency and power use may get impacted with this flag. |
5367 | * @NL80211_SCAN_FLAG_RANDOM_SN: randomize the sequence number in probe | ||
5368 | * request frames from this scan to avoid correlation/tracking being | ||
5369 | * possible. | ||
5370 | * @NL80211_SCAN_FLAG_MIN_PREQ_CONTENT: minimize probe request content to | ||
5371 | * only have supported rates and no additional capabilities (unless | ||
5372 | * added by userspace explicitly.) | ||
5275 | */ | 5373 | */ |
5276 | enum nl80211_scan_flags { | 5374 | enum nl80211_scan_flags { |
5277 | NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, | 5375 | NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, |
@@ -5285,6 +5383,8 @@ enum nl80211_scan_flags { | |||
5285 | NL80211_SCAN_FLAG_LOW_SPAN = 1<<8, | 5383 | NL80211_SCAN_FLAG_LOW_SPAN = 1<<8, |
5286 | NL80211_SCAN_FLAG_LOW_POWER = 1<<9, | 5384 | NL80211_SCAN_FLAG_LOW_POWER = 1<<9, |
5287 | NL80211_SCAN_FLAG_HIGH_ACCURACY = 1<<10, | 5385 | NL80211_SCAN_FLAG_HIGH_ACCURACY = 1<<10, |
5386 | NL80211_SCAN_FLAG_RANDOM_SN = 1<<11, | ||
5387 | NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12, | ||
5288 | }; | 5388 | }; |
5289 | 5389 | ||
5290 | /** | 5390 | /** |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index e3589ade62e0..bb707789ef2b 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -12,6 +12,7 @@ mac80211-y := \ | |||
12 | scan.o offchannel.o \ | 12 | scan.o offchannel.o \ |
13 | ht.o agg-tx.o agg-rx.o \ | 13 | ht.o agg-tx.o agg-rx.o \ |
14 | vht.o \ | 14 | vht.o \ |
15 | he.o \ | ||
15 | ibss.o \ | 16 | ibss.o \ |
16 | iface.o \ | 17 | iface.o \ |
17 | rate.o \ | 18 | rate.o \ |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index e83c19d4c292..6a4f154c99f6 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -245,6 +245,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta, | |||
245 | }; | 245 | }; |
246 | int i, ret = -EOPNOTSUPP; | 246 | int i, ret = -EOPNOTSUPP; |
247 | u16 status = WLAN_STATUS_REQUEST_DECLINED; | 247 | u16 status = WLAN_STATUS_REQUEST_DECLINED; |
248 | u16 max_buf_size; | ||
248 | 249 | ||
249 | if (tid >= IEEE80211_FIRST_TSPEC_TSID) { | 250 | if (tid >= IEEE80211_FIRST_TSPEC_TSID) { |
250 | ht_dbg(sta->sdata, | 251 | ht_dbg(sta->sdata, |
@@ -268,13 +269,18 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta, | |||
268 | goto end; | 269 | goto end; |
269 | } | 270 | } |
270 | 271 | ||
272 | if (sta->sta.he_cap.has_he) | ||
273 | max_buf_size = IEEE80211_MAX_AMPDU_BUF; | ||
274 | else | ||
275 | max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT; | ||
276 | |||
271 | /* sanity check for incoming parameters: | 277 | /* sanity check for incoming parameters: |
272 | * check if configuration can support the BA policy | 278 | * check if configuration can support the BA policy |
273 | * and if buffer size does not exceeds max value */ | 279 | * and if buffer size does not exceeds max value */ |
274 | /* XXX: check own ht delayed BA capability?? */ | 280 | /* XXX: check own ht delayed BA capability?? */ |
275 | if (((ba_policy != 1) && | 281 | if (((ba_policy != 1) && |
276 | (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) || | 282 | (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) || |
277 | (buf_size > IEEE80211_MAX_AMPDU_BUF)) { | 283 | (buf_size > max_buf_size)) { |
278 | status = WLAN_STATUS_INVALID_QOS_PARAM; | 284 | status = WLAN_STATUS_INVALID_QOS_PARAM; |
279 | ht_dbg_ratelimited(sta->sdata, | 285 | ht_dbg_ratelimited(sta->sdata, |
280 | "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n", | 286 | "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n", |
@@ -283,7 +289,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta, | |||
283 | } | 289 | } |
284 | /* determine default buffer size */ | 290 | /* determine default buffer size */ |
285 | if (buf_size == 0) | 291 | if (buf_size == 0) |
286 | buf_size = IEEE80211_MAX_AMPDU_BUF; | 292 | buf_size = max_buf_size; |
287 | 293 | ||
288 | /* make sure the size doesn't exceed the maximum supported by the hw */ | 294 | /* make sure the size doesn't exceed the maximum supported by the hw */ |
289 | if (buf_size > sta->sta.max_rx_aggregation_subframes) | 295 | if (buf_size > sta->sta.max_rx_aggregation_subframes) |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index ac4295296514..69e831bc317b 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -463,6 +463,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
463 | .timeout = 0, | 463 | .timeout = 0, |
464 | }; | 464 | }; |
465 | int ret; | 465 | int ret; |
466 | u16 buf_size; | ||
466 | 467 | ||
467 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 468 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
468 | 469 | ||
@@ -511,11 +512,22 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
511 | sta->ampdu_mlme.addba_req_num[tid]++; | 512 | sta->ampdu_mlme.addba_req_num[tid]++; |
512 | spin_unlock_bh(&sta->lock); | 513 | spin_unlock_bh(&sta->lock); |
513 | 514 | ||
515 | if (sta->sta.he_cap.has_he) { | ||
516 | buf_size = local->hw.max_tx_aggregation_subframes; | ||
517 | } else { | ||
518 | /* | ||
519 | * We really should use what the driver told us it will | ||
520 | * transmit as the maximum, but certain APs (e.g. the | ||
521 | * LinkSys WRT120N with FW v1.0.07 build 002 Jun 18 2012) | ||
522 | * will crash when we use a lower number. | ||
523 | */ | ||
524 | buf_size = IEEE80211_MAX_AMPDU_BUF_HT; | ||
525 | } | ||
526 | |||
514 | /* send AddBA request */ | 527 | /* send AddBA request */ |
515 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | 528 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
516 | tid_tx->dialog_token, params.ssn, | 529 | tid_tx->dialog_token, params.ssn, |
517 | IEEE80211_MAX_AMPDU_BUF, | 530 | buf_size, tid_tx->timeout); |
518 | tid_tx->timeout); | ||
519 | } | 531 | } |
520 | 532 | ||
521 | /* | 533 | /* |
@@ -905,8 +917,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
905 | { | 917 | { |
906 | struct tid_ampdu_tx *tid_tx; | 918 | struct tid_ampdu_tx *tid_tx; |
907 | struct ieee80211_txq *txq; | 919 | struct ieee80211_txq *txq; |
908 | u16 capab, tid; | 920 | u16 capab, tid, buf_size; |
909 | u8 buf_size; | ||
910 | bool amsdu; | 921 | bool amsdu; |
911 | 922 | ||
912 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 923 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index bdf6fa78d0d2..02f3672e7b5e 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1412,6 +1412,11 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1412 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1412 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
1413 | params->vht_capa, sta); | 1413 | params->vht_capa, sta); |
1414 | 1414 | ||
1415 | if (params->he_capa) | ||
1416 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, | ||
1417 | (void *)params->he_capa, | ||
1418 | params->he_capa_len, sta); | ||
1419 | |||
1415 | if (params->opmode_notif_used) { | 1420 | if (params->opmode_notif_used) { |
1416 | /* returned value is only needed for rc update, but the | 1421 | /* returned value is only needed for rc update, but the |
1417 | * rc isn't initialized here yet, so ignore it | 1422 | * rc isn't initialized here yet, so ignore it |
@@ -3486,7 +3491,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3486 | } | 3491 | } |
3487 | 3492 | ||
3488 | local_bh_disable(); | 3493 | local_bh_disable(); |
3489 | ieee80211_xmit(sdata, sta, skb); | 3494 | ieee80211_xmit(sdata, sta, skb, 0); |
3490 | local_bh_enable(); | 3495 | local_bh_enable(); |
3491 | 3496 | ||
3492 | ret = 0; | 3497 | ret = 0; |
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c index 690c142a7a44..5ac743816b59 100644 --- a/net/mac80211/ethtool.c +++ b/net/mac80211/ethtool.c | |||
@@ -116,16 +116,16 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
116 | data[i++] = sta->sta_state; | 116 | data[i++] = sta->sta_state; |
117 | 117 | ||
118 | 118 | ||
119 | if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) | 119 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) |
120 | data[i] = 100000ULL * | 120 | data[i] = 100000ULL * |
121 | cfg80211_calculate_bitrate(&sinfo.txrate); | 121 | cfg80211_calculate_bitrate(&sinfo.txrate); |
122 | i++; | 122 | i++; |
123 | if (sinfo.filled & BIT(NL80211_STA_INFO_RX_BITRATE)) | 123 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) |
124 | data[i] = 100000ULL * | 124 | data[i] = 100000ULL * |
125 | cfg80211_calculate_bitrate(&sinfo.rxrate); | 125 | cfg80211_calculate_bitrate(&sinfo.rxrate); |
126 | i++; | 126 | i++; |
127 | 127 | ||
128 | if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL_AVG)) | 128 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG)) |
129 | data[i] = (u8)sinfo.signal_avg; | 129 | data[i] = (u8)sinfo.signal_avg; |
130 | i++; | 130 | i++; |
131 | } else { | 131 | } else { |
diff --git a/net/mac80211/he.c b/net/mac80211/he.c new file mode 100644 index 000000000000..769078ed5a12 --- /dev/null +++ b/net/mac80211/he.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * HE handling | ||
3 | * | ||
4 | * Copyright(c) 2017 Intel Deutschland GmbH | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include "ieee80211_i.h" | ||
12 | |||
13 | void | ||
14 | ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, | ||
15 | struct ieee80211_supported_band *sband, | ||
16 | const u8 *he_cap_ie, u8 he_cap_len, | ||
17 | struct sta_info *sta) | ||
18 | { | ||
19 | struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap; | ||
20 | struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie; | ||
21 | u8 he_ppe_size; | ||
22 | u8 mcs_nss_size; | ||
23 | u8 he_total_size; | ||
24 | |||
25 | memset(he_cap, 0, sizeof(*he_cap)); | ||
26 | |||
27 | if (!he_cap_ie || !ieee80211_get_he_sta_cap(sband)) | ||
28 | return; | ||
29 | |||
30 | /* Make sure size is OK */ | ||
31 | mcs_nss_size = ieee80211_he_mcs_nss_size(he_cap_ie_elem); | ||
32 | he_ppe_size = | ||
33 | ieee80211_he_ppe_size(he_cap_ie[sizeof(he_cap->he_cap_elem) + | ||
34 | mcs_nss_size], | ||
35 | he_cap_ie_elem->phy_cap_info); | ||
36 | he_total_size = sizeof(he_cap->he_cap_elem) + mcs_nss_size + | ||
37 | he_ppe_size; | ||
38 | if (he_cap_len < he_total_size) | ||
39 | return; | ||
40 | |||
41 | memcpy(&he_cap->he_cap_elem, he_cap_ie, sizeof(he_cap->he_cap_elem)); | ||
42 | |||
43 | /* HE Tx/Rx HE MCS NSS Support Field */ | ||
44 | memcpy(&he_cap->he_mcs_nss_supp, | ||
45 | &he_cap_ie[sizeof(he_cap->he_cap_elem)], mcs_nss_size); | ||
46 | |||
47 | /* Check if there are (optional) PPE Thresholds */ | ||
48 | if (he_cap->he_cap_elem.phy_cap_info[6] & | ||
49 | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) | ||
50 | memcpy(he_cap->ppe_thres, | ||
51 | &he_cap_ie[sizeof(he_cap->he_cap_elem) + mcs_nss_size], | ||
52 | he_ppe_size); | ||
53 | |||
54 | he_cap->has_he = true; | ||
55 | } | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 26a7ba3b698f..f849ea814993 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -352,7 +352,7 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
352 | test_and_clear_bit(tid, | 352 | test_and_clear_bit(tid, |
353 | sta->ampdu_mlme.tid_rx_manage_offl)) | 353 | sta->ampdu_mlme.tid_rx_manage_offl)) |
354 | ___ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid, | 354 | ___ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid, |
355 | IEEE80211_MAX_AMPDU_BUF, | 355 | IEEE80211_MAX_AMPDU_BUF_HT, |
356 | false, true); | 356 | false, true); |
357 | 357 | ||
358 | if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS, | 358 | if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d1978aa1c15d..172aeae21ae9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -165,6 +165,7 @@ typedef unsigned __bitwise ieee80211_tx_result; | |||
165 | #define TX_DROP ((__force ieee80211_tx_result) 1u) | 165 | #define TX_DROP ((__force ieee80211_tx_result) 1u) |
166 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) | 166 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) |
167 | 167 | ||
168 | #define IEEE80211_TX_NO_SEQNO BIT(0) | ||
168 | #define IEEE80211_TX_UNICAST BIT(1) | 169 | #define IEEE80211_TX_UNICAST BIT(1) |
169 | #define IEEE80211_TX_PS_BUFFERED BIT(2) | 170 | #define IEEE80211_TX_PS_BUFFERED BIT(2) |
170 | 171 | ||
@@ -364,6 +365,7 @@ enum ieee80211_sta_flags { | |||
364 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), | 365 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), |
365 | IEEE80211_STA_DISABLE_WMM = BIT(14), | 366 | IEEE80211_STA_DISABLE_WMM = BIT(14), |
366 | IEEE80211_STA_ENABLE_RRM = BIT(15), | 367 | IEEE80211_STA_ENABLE_RRM = BIT(15), |
368 | IEEE80211_STA_DISABLE_HE = BIT(16), | ||
367 | }; | 369 | }; |
368 | 370 | ||
369 | struct ieee80211_mgd_auth_data { | 371 | struct ieee80211_mgd_auth_data { |
@@ -1453,6 +1455,10 @@ struct ieee802_11_elems { | |||
1453 | const struct ieee80211_vht_cap *vht_cap_elem; | 1455 | const struct ieee80211_vht_cap *vht_cap_elem; |
1454 | const struct ieee80211_vht_operation *vht_operation; | 1456 | const struct ieee80211_vht_operation *vht_operation; |
1455 | const struct ieee80211_meshconf_ie *mesh_config; | 1457 | const struct ieee80211_meshconf_ie *mesh_config; |
1458 | const u8 *he_cap; | ||
1459 | const struct ieee80211_he_operation *he_operation; | ||
1460 | const struct ieee80211_mu_edca_param_set *mu_edca_param_set; | ||
1461 | const u8 *uora_element; | ||
1456 | const u8 *mesh_id; | 1462 | const u8 *mesh_id; |
1457 | const u8 *peering; | 1463 | const u8 *peering; |
1458 | const __le16 *awake_window; | 1464 | const __le16 *awake_window; |
@@ -1482,6 +1488,7 @@ struct ieee802_11_elems { | |||
1482 | u8 ext_supp_rates_len; | 1488 | u8 ext_supp_rates_len; |
1483 | u8 wmm_info_len; | 1489 | u8 wmm_info_len; |
1484 | u8 wmm_param_len; | 1490 | u8 wmm_param_len; |
1491 | u8 he_cap_len; | ||
1485 | u8 mesh_id_len; | 1492 | u8 mesh_id_len; |
1486 | u8 peering_len; | 1493 | u8 peering_len; |
1487 | u8 preq_len; | 1494 | u8 preq_len; |
@@ -1824,6 +1831,13 @@ void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, | |||
1824 | enum nl80211_chan_width | 1831 | enum nl80211_chan_width |
1825 | ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta); | 1832 | ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta); |
1826 | 1833 | ||
1834 | /* HE */ | ||
1835 | void | ||
1836 | ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, | ||
1837 | struct ieee80211_supported_band *sband, | ||
1838 | const u8 *he_cap_ie, u8 he_cap_len, | ||
1839 | struct sta_info *sta); | ||
1840 | |||
1827 | /* Spectrum management */ | 1841 | /* Spectrum management */ |
1828 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1842 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
1829 | struct ieee80211_mgmt *mgmt, | 1843 | struct ieee80211_mgmt *mgmt, |
@@ -1880,19 +1894,20 @@ void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
1880 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | 1894 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
1881 | bool bss_notify, bool enable_qos); | 1895 | bool bss_notify, bool enable_qos); |
1882 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | 1896 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, |
1883 | struct sta_info *sta, struct sk_buff *skb); | 1897 | struct sta_info *sta, struct sk_buff *skb, |
1898 | u32 txdata_flags); | ||
1884 | 1899 | ||
1885 | void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, | 1900 | void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, |
1886 | struct sk_buff *skb, int tid, | 1901 | struct sk_buff *skb, int tid, |
1887 | enum nl80211_band band); | 1902 | enum nl80211_band band, u32 txdata_flags); |
1888 | 1903 | ||
1889 | static inline void | 1904 | static inline void |
1890 | ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, | 1905 | ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, |
1891 | struct sk_buff *skb, int tid, | 1906 | struct sk_buff *skb, int tid, |
1892 | enum nl80211_band band) | 1907 | enum nl80211_band band, u32 txdata_flags) |
1893 | { | 1908 | { |
1894 | rcu_read_lock(); | 1909 | rcu_read_lock(); |
1895 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, band); | 1910 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, band, txdata_flags); |
1896 | rcu_read_unlock(); | 1911 | rcu_read_unlock(); |
1897 | } | 1912 | } |
1898 | 1913 | ||
@@ -1910,7 +1925,7 @@ static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | |||
1910 | } | 1925 | } |
1911 | 1926 | ||
1912 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, | 1927 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, |
1913 | chanctx_conf->def.chan->band); | 1928 | chanctx_conf->def.chan->band, 0); |
1914 | rcu_read_unlock(); | 1929 | rcu_read_unlock(); |
1915 | } | 1930 | } |
1916 | 1931 | ||
@@ -2031,26 +2046,27 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
2031 | void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 2046 | void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
2032 | const u8 *bssid, u16 stype, u16 reason, | 2047 | const u8 *bssid, u16 stype, u16 reason, |
2033 | bool send_frame, u8 *frame_buf); | 2048 | bool send_frame, u8 *frame_buf); |
2049 | |||
2050 | enum { | ||
2051 | IEEE80211_PROBE_FLAG_DIRECTED = BIT(0), | ||
2052 | IEEE80211_PROBE_FLAG_MIN_CONTENT = BIT(1), | ||
2053 | IEEE80211_PROBE_FLAG_RANDOM_SN = BIT(2), | ||
2054 | }; | ||
2055 | |||
2034 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 2056 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
2035 | size_t buffer_len, | 2057 | size_t buffer_len, |
2036 | struct ieee80211_scan_ies *ie_desc, | 2058 | struct ieee80211_scan_ies *ie_desc, |
2037 | const u8 *ie, size_t ie_len, | 2059 | const u8 *ie, size_t ie_len, |
2038 | u8 bands_used, u32 *rate_masks, | 2060 | u8 bands_used, u32 *rate_masks, |
2039 | struct cfg80211_chan_def *chandef); | 2061 | struct cfg80211_chan_def *chandef, |
2062 | u32 flags); | ||
2040 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 2063 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
2041 | const u8 *src, const u8 *dst, | 2064 | const u8 *src, const u8 *dst, |
2042 | u32 ratemask, | 2065 | u32 ratemask, |
2043 | struct ieee80211_channel *chan, | 2066 | struct ieee80211_channel *chan, |
2044 | const u8 *ssid, size_t ssid_len, | 2067 | const u8 *ssid, size_t ssid_len, |
2045 | const u8 *ie, size_t ie_len, | 2068 | const u8 *ie, size_t ie_len, |
2046 | bool directed); | 2069 | u32 flags); |
2047 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, | ||
2048 | const u8 *src, const u8 *dst, | ||
2049 | const u8 *ssid, size_t ssid_len, | ||
2050 | const u8 *ie, size_t ie_len, | ||
2051 | u32 ratemask, bool directed, u32 tx_flags, | ||
2052 | struct ieee80211_channel *channel, bool scan); | ||
2053 | |||
2054 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | 2070 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, |
2055 | struct ieee802_11_elems *elems, | 2071 | struct ieee802_11_elems *elems, |
2056 | enum nl80211_band band, u32 *basic_rates); | 2072 | enum nl80211_band band, u32 *basic_rates); |
@@ -2073,6 +2089,9 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | |||
2073 | u32 cap); | 2089 | u32 cap); |
2074 | u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 2090 | u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, |
2075 | const struct cfg80211_chan_def *chandef); | 2091 | const struct cfg80211_chan_def *chandef); |
2092 | u8 *ieee80211_ie_build_he_cap(u8 *pos, | ||
2093 | const struct ieee80211_sta_he_cap *he_cap, | ||
2094 | u8 *end); | ||
2076 | int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, | 2095 | int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, |
2077 | const struct ieee80211_supported_band *sband, | 2096 | const struct ieee80211_supported_band *sband, |
2078 | const u8 *srates, int srates_len, u32 *rates); | 2097 | const u8 *srates, int srates_len, u32 *rates); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index fb73451ed85e..4fb2709cb527 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 5 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
6 | * Copyright (C) 2017 Intel Deutschland GmbH | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -557,10 +558,19 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, | |||
557 | wiphy_ext_feature_set(wiphy, | 558 | wiphy_ext_feature_set(wiphy, |
558 | NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211); | 559 | NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211); |
559 | 560 | ||
560 | if (!ops->hw_scan) | 561 | if (!ops->hw_scan) { |
561 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | | 562 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | |
562 | NL80211_FEATURE_AP_SCAN; | 563 | NL80211_FEATURE_AP_SCAN; |
563 | 564 | /* | |
565 | * if the driver behaves correctly using the probe request | ||
566 | * (template) from mac80211, then both of these should be | ||
567 | * supported even with hw scan - but let drivers opt in. | ||
568 | */ | ||
569 | wiphy_ext_feature_set(wiphy, | ||
570 | NL80211_EXT_FEATURE_SCAN_RANDOM_SN); | ||
571 | wiphy_ext_feature_set(wiphy, | ||
572 | NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT); | ||
573 | } | ||
564 | 574 | ||
565 | if (!ops->set_key) | 575 | if (!ops->set_key) |
566 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 576 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
@@ -588,8 +598,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, | |||
588 | local->hw.queues = 1; | 598 | local->hw.queues = 1; |
589 | local->hw.max_rates = 1; | 599 | local->hw.max_rates = 1; |
590 | local->hw.max_report_rates = 0; | 600 | local->hw.max_report_rates = 0; |
591 | local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; | 601 | local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HT; |
592 | local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; | 602 | local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HT; |
593 | local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE; | 603 | local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE; |
594 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 604 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
595 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 605 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
@@ -816,7 +826,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
816 | int result, i; | 826 | int result, i; |
817 | enum nl80211_band band; | 827 | enum nl80211_band band; |
818 | int channels, max_bitrates; | 828 | int channels, max_bitrates; |
819 | bool supp_ht, supp_vht; | 829 | bool supp_ht, supp_vht, supp_he; |
820 | netdev_features_t feature_whitelist; | 830 | netdev_features_t feature_whitelist; |
821 | struct cfg80211_chan_def dflt_chandef = {}; | 831 | struct cfg80211_chan_def dflt_chandef = {}; |
822 | 832 | ||
@@ -896,6 +906,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
896 | max_bitrates = 0; | 906 | max_bitrates = 0; |
897 | supp_ht = false; | 907 | supp_ht = false; |
898 | supp_vht = false; | 908 | supp_vht = false; |
909 | supp_he = false; | ||
899 | for (band = 0; band < NUM_NL80211_BANDS; band++) { | 910 | for (band = 0; band < NUM_NL80211_BANDS; band++) { |
900 | struct ieee80211_supported_band *sband; | 911 | struct ieee80211_supported_band *sband; |
901 | 912 | ||
@@ -922,6 +933,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
922 | supp_ht = supp_ht || sband->ht_cap.ht_supported; | 933 | supp_ht = supp_ht || sband->ht_cap.ht_supported; |
923 | supp_vht = supp_vht || sband->vht_cap.vht_supported; | 934 | supp_vht = supp_vht || sband->vht_cap.vht_supported; |
924 | 935 | ||
936 | if (!supp_he) | ||
937 | supp_he = !!ieee80211_get_he_sta_cap(sband); | ||
938 | |||
925 | if (!sband->ht_cap.ht_supported) | 939 | if (!sband->ht_cap.ht_supported) |
926 | continue; | 940 | continue; |
927 | 941 | ||
@@ -1011,6 +1025,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1011 | local->scan_ies_len += | 1025 | local->scan_ies_len += |
1012 | 2 + sizeof(struct ieee80211_vht_cap); | 1026 | 2 + sizeof(struct ieee80211_vht_cap); |
1013 | 1027 | ||
1028 | /* HE cap element is variable in size - set len to allow max size */ | ||
1029 | /* | ||
1030 | * TODO: 1 is added at the end of the calculation to accommodate for | ||
1031 | * the temporary placing of the HE capabilities IE under EXT. | ||
1032 | * Remove it once it is placed in the final place. | ||
1033 | */ | ||
1034 | if (supp_he) | ||
1035 | local->scan_ies_len += | ||
1036 | 2 + sizeof(struct ieee80211_he_cap_elem) + | ||
1037 | sizeof(struct ieee80211_he_mcs_nss_supp) + | ||
1038 | IEEE80211_HE_PPE_THRES_MAX_LEN + 1; | ||
1039 | |||
1014 | if (!local->ops->hw_scan) { | 1040 | if (!local->ops->hw_scan) { |
1015 | /* For hw_scan, driver needs to set these up. */ | 1041 | /* For hw_scan, driver needs to set these up. */ |
1016 | local->hw.wiphy->max_scan_ssids = 4; | 1042 | local->hw.wiphy->max_scan_ssids = 4; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a59187c016e0..7fb9957359a3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -149,6 +149,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
149 | struct ieee80211_channel *channel, | 149 | struct ieee80211_channel *channel, |
150 | const struct ieee80211_ht_operation *ht_oper, | 150 | const struct ieee80211_ht_operation *ht_oper, |
151 | const struct ieee80211_vht_operation *vht_oper, | 151 | const struct ieee80211_vht_operation *vht_oper, |
152 | const struct ieee80211_he_operation *he_oper, | ||
152 | struct cfg80211_chan_def *chandef, bool tracking) | 153 | struct cfg80211_chan_def *chandef, bool tracking) |
153 | { | 154 | { |
154 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 155 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -207,7 +208,27 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
207 | } | 208 | } |
208 | 209 | ||
209 | vht_chandef = *chandef; | 210 | vht_chandef = *chandef; |
210 | if (!ieee80211_chandef_vht_oper(vht_oper, &vht_chandef)) { | 211 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && he_oper && |
212 | (le32_to_cpu(he_oper->he_oper_params) & | ||
213 | IEEE80211_HE_OPERATION_VHT_OPER_INFO)) { | ||
214 | struct ieee80211_vht_operation he_oper_vht_cap; | ||
215 | |||
216 | /* | ||
217 | * Set only first 3 bytes (other 2 aren't used in | ||
218 | * ieee80211_chandef_vht_oper() anyway) | ||
219 | */ | ||
220 | memcpy(&he_oper_vht_cap, he_oper->optional, 3); | ||
221 | he_oper_vht_cap.basic_mcs_set = cpu_to_le16(0); | ||
222 | |||
223 | if (!ieee80211_chandef_vht_oper(&he_oper_vht_cap, | ||
224 | &vht_chandef)) { | ||
225 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) | ||
226 | sdata_info(sdata, | ||
227 | "HE AP VHT information is invalid, disable HE\n"); | ||
228 | ret = IEEE80211_STA_DISABLE_HE; | ||
229 | goto out; | ||
230 | } | ||
231 | } else if (!ieee80211_chandef_vht_oper(vht_oper, &vht_chandef)) { | ||
211 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | 232 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
212 | sdata_info(sdata, | 233 | sdata_info(sdata, |
213 | "AP VHT information is invalid, disable VHT\n"); | 234 | "AP VHT information is invalid, disable VHT\n"); |
@@ -300,12 +321,14 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
300 | const struct ieee80211_ht_cap *ht_cap, | 321 | const struct ieee80211_ht_cap *ht_cap, |
301 | const struct ieee80211_ht_operation *ht_oper, | 322 | const struct ieee80211_ht_operation *ht_oper, |
302 | const struct ieee80211_vht_operation *vht_oper, | 323 | const struct ieee80211_vht_operation *vht_oper, |
324 | const struct ieee80211_he_operation *he_oper, | ||
303 | const u8 *bssid, u32 *changed) | 325 | const u8 *bssid, u32 *changed) |
304 | { | 326 | { |
305 | struct ieee80211_local *local = sdata->local; | 327 | struct ieee80211_local *local = sdata->local; |
306 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 328 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
307 | struct ieee80211_supported_band *sband; | 329 | struct ieee80211_channel *chan = sdata->vif.bss_conf.chandef.chan; |
308 | struct ieee80211_channel *chan; | 330 | struct ieee80211_supported_band *sband = |
331 | local->hw.wiphy->bands[chan->band]; | ||
309 | struct cfg80211_chan_def chandef; | 332 | struct cfg80211_chan_def chandef; |
310 | u16 ht_opmode; | 333 | u16 ht_opmode; |
311 | u32 flags; | 334 | u32 flags; |
@@ -320,6 +343,11 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
320 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) | 343 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) |
321 | vht_oper = NULL; | 344 | vht_oper = NULL; |
322 | 345 | ||
346 | /* don't check HE if we associated as non-HE station */ | ||
347 | if (ifmgd->flags & IEEE80211_STA_DISABLE_HE || | ||
348 | !ieee80211_get_he_sta_cap(sband)) | ||
349 | he_oper = NULL; | ||
350 | |||
323 | if (WARN_ON_ONCE(!sta)) | 351 | if (WARN_ON_ONCE(!sta)) |
324 | return -EINVAL; | 352 | return -EINVAL; |
325 | 353 | ||
@@ -333,12 +361,9 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
333 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | 361 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
334 | } | 362 | } |
335 | 363 | ||
336 | chan = sdata->vif.bss_conf.chandef.chan; | 364 | /* calculate new channel (type) based on HT/VHT/HE operation IEs */ |
337 | sband = local->hw.wiphy->bands[chan->band]; | ||
338 | |||
339 | /* calculate new channel (type) based on HT/VHT operation IEs */ | ||
340 | flags = ieee80211_determine_chantype(sdata, sband, chan, | 365 | flags = ieee80211_determine_chantype(sdata, sband, chan, |
341 | ht_oper, vht_oper, | 366 | ht_oper, vht_oper, he_oper, |
342 | &chandef, true); | 367 | &chandef, true); |
343 | 368 | ||
344 | /* | 369 | /* |
@@ -582,6 +607,34 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
582 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); | 607 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); |
583 | } | 608 | } |
584 | 609 | ||
610 | /* This function determines HE capability flags for the association | ||
611 | * and builds the IE. | ||
612 | */ | ||
613 | static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata, | ||
614 | struct sk_buff *skb, | ||
615 | struct ieee80211_supported_band *sband) | ||
616 | { | ||
617 | u8 *pos; | ||
618 | const struct ieee80211_sta_he_cap *he_cap = NULL; | ||
619 | u8 he_cap_size; | ||
620 | |||
621 | he_cap = ieee80211_get_he_sta_cap(sband); | ||
622 | if (!he_cap) | ||
623 | return; | ||
624 | |||
625 | /* | ||
626 | * TODO: the 1 added is because this temporarily is under the EXTENSION | ||
627 | * IE. Get rid of it when it moves. | ||
628 | */ | ||
629 | he_cap_size = | ||
630 | 2 + 1 + sizeof(he_cap->he_cap_elem) + | ||
631 | ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem) + | ||
632 | ieee80211_he_ppe_size(he_cap->ppe_thres[0], | ||
633 | he_cap->he_cap_elem.phy_cap_info); | ||
634 | pos = skb_put(skb, he_cap_size); | ||
635 | ieee80211_ie_build_he_cap(pos, he_cap, pos + he_cap_size); | ||
636 | } | ||
637 | |||
585 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | 638 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) |
586 | { | 639 | { |
587 | struct ieee80211_local *local = sdata->local; | 640 | struct ieee80211_local *local = sdata->local; |
@@ -643,6 +696,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
643 | 2 + 2 * sband->n_channels + /* supported channels */ | 696 | 2 + 2 * sband->n_channels + /* supported channels */ |
644 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ | 697 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ |
645 | 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */ | 698 | 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */ |
699 | 2 + 1 + sizeof(struct ieee80211_he_cap_elem) + /* HE */ | ||
700 | sizeof(struct ieee80211_he_mcs_nss_supp) + | ||
701 | IEEE80211_HE_PPE_THRES_MAX_LEN + | ||
646 | assoc_data->ie_len + /* extra IEs */ | 702 | assoc_data->ie_len + /* extra IEs */ |
647 | (assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) + | 703 | (assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) + |
648 | 9, /* WMM */ | 704 | 9, /* WMM */ |
@@ -827,11 +883,41 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
827 | offset = noffset; | 883 | offset = noffset; |
828 | } | 884 | } |
829 | 885 | ||
886 | /* if present, add any custom IEs that go before HE */ | ||
887 | if (assoc_data->ie_len) { | ||
888 | static const u8 before_he[] = { | ||
889 | /* | ||
890 | * no need to list the ones split off before VHT | ||
891 | * or generated here | ||
892 | */ | ||
893 | WLAN_EID_OPMODE_NOTIF, | ||
894 | WLAN_EID_EXTENSION, WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE, | ||
895 | /* 11ai elements */ | ||
896 | WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_SESSION, | ||
897 | WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_PUBLIC_KEY, | ||
898 | WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_KEY_CONFIRM, | ||
899 | WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_HLP_CONTAINER, | ||
900 | WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN, | ||
901 | /* TODO: add 11ah/11aj/11ak elements */ | ||
902 | }; | ||
903 | |||
904 | /* RIC already taken above, so no need to handle here anymore */ | ||
905 | noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, | ||
906 | before_he, ARRAY_SIZE(before_he), | ||
907 | offset); | ||
908 | pos = skb_put(skb, noffset - offset); | ||
909 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | ||
910 | offset = noffset; | ||
911 | } | ||
912 | |||
830 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | 913 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
831 | ieee80211_add_vht_ie(sdata, skb, sband, | 914 | ieee80211_add_vht_ie(sdata, skb, sband, |
832 | &assoc_data->ap_vht_cap); | 915 | &assoc_data->ap_vht_cap); |
833 | 916 | ||
834 | /* if present, add any custom non-vendor IEs that go after HT */ | 917 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) |
918 | ieee80211_add_he_ie(sdata, skb, sband); | ||
919 | |||
920 | /* if present, add any custom non-vendor IEs that go after HE */ | ||
835 | if (assoc_data->ie_len) { | 921 | if (assoc_data->ie_len) { |
836 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, | 922 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, |
837 | assoc_data->ie_len, | 923 | assoc_data->ie_len, |
@@ -898,6 +984,11 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
898 | struct ieee80211_hdr_3addr *nullfunc; | 984 | struct ieee80211_hdr_3addr *nullfunc; |
899 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 985 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
900 | 986 | ||
987 | /* Don't send NDPs when STA is connected HE */ | ||
988 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
989 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) | ||
990 | return; | ||
991 | |||
901 | skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif, | 992 | skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif, |
902 | !ieee80211_hw_check(&local->hw, DOESNT_SUPPORT_QOS_NDP)); | 993 | !ieee80211_hw_check(&local->hw, DOESNT_SUPPORT_QOS_NDP)); |
903 | if (!skb) | 994 | if (!skb) |
@@ -929,6 +1020,10 @@ static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, | |||
929 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | 1020 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) |
930 | return; | 1021 | return; |
931 | 1022 | ||
1023 | /* Don't send NDPs when connected HE */ | ||
1024 | if (!(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE)) | ||
1025 | return; | ||
1026 | |||
932 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); | 1027 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); |
933 | if (!skb) | 1028 | if (!skb) |
934 | return; | 1029 | return; |
@@ -1700,9 +1795,11 @@ static void ieee80211_sta_handle_tspec_ac_params_wk(struct work_struct *work) | |||
1700 | } | 1795 | } |
1701 | 1796 | ||
1702 | /* MLME */ | 1797 | /* MLME */ |
1703 | static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, | 1798 | static bool |
1704 | struct ieee80211_sub_if_data *sdata, | 1799 | ieee80211_sta_wmm_params(struct ieee80211_local *local, |
1705 | const u8 *wmm_param, size_t wmm_param_len) | 1800 | struct ieee80211_sub_if_data *sdata, |
1801 | const u8 *wmm_param, size_t wmm_param_len, | ||
1802 | const struct ieee80211_mu_edca_param_set *mu_edca) | ||
1706 | { | 1803 | { |
1707 | struct ieee80211_tx_queue_params params[IEEE80211_NUM_ACS]; | 1804 | struct ieee80211_tx_queue_params params[IEEE80211_NUM_ACS]; |
1708 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1805 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -1749,6 +1846,9 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1749 | sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ | 1846 | sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ |
1750 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) | 1847 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) |
1751 | uapsd = true; | 1848 | uapsd = true; |
1849 | params[ac].mu_edca = !!mu_edca; | ||
1850 | if (mu_edca) | ||
1851 | params[ac].mu_edca_param_rec = mu_edca->ac_bk; | ||
1752 | break; | 1852 | break; |
1753 | case 2: /* AC_VI */ | 1853 | case 2: /* AC_VI */ |
1754 | ac = IEEE80211_AC_VI; | 1854 | ac = IEEE80211_AC_VI; |
@@ -1756,6 +1856,9 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1756 | sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ | 1856 | sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ |
1757 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) | 1857 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) |
1758 | uapsd = true; | 1858 | uapsd = true; |
1859 | params[ac].mu_edca = !!mu_edca; | ||
1860 | if (mu_edca) | ||
1861 | params[ac].mu_edca_param_rec = mu_edca->ac_vi; | ||
1759 | break; | 1862 | break; |
1760 | case 3: /* AC_VO */ | 1863 | case 3: /* AC_VO */ |
1761 | ac = IEEE80211_AC_VO; | 1864 | ac = IEEE80211_AC_VO; |
@@ -1763,6 +1866,9 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1763 | sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ | 1866 | sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ |
1764 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) | 1867 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) |
1765 | uapsd = true; | 1868 | uapsd = true; |
1869 | params[ac].mu_edca = !!mu_edca; | ||
1870 | if (mu_edca) | ||
1871 | params[ac].mu_edca_param_rec = mu_edca->ac_vo; | ||
1766 | break; | 1872 | break; |
1767 | case 0: /* AC_BE */ | 1873 | case 0: /* AC_BE */ |
1768 | default: | 1874 | default: |
@@ -1771,6 +1877,9 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1771 | sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ | 1877 | sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ |
1772 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) | 1878 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) |
1773 | uapsd = true; | 1879 | uapsd = true; |
1880 | params[ac].mu_edca = !!mu_edca; | ||
1881 | if (mu_edca) | ||
1882 | params[ac].mu_edca_param_rec = mu_edca->ac_be; | ||
1774 | break; | 1883 | break; |
1775 | } | 1884 | } |
1776 | 1885 | ||
@@ -2219,6 +2328,20 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | |||
2219 | ieee80211_sta_reset_conn_monitor(sdata); | 2328 | ieee80211_sta_reset_conn_monitor(sdata); |
2220 | } | 2329 | } |
2221 | 2330 | ||
2331 | static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata, | ||
2332 | const u8 *src, const u8 *dst, | ||
2333 | const u8 *ssid, size_t ssid_len, | ||
2334 | struct ieee80211_channel *channel) | ||
2335 | { | ||
2336 | struct sk_buff *skb; | ||
2337 | |||
2338 | skb = ieee80211_build_probe_req(sdata, src, dst, (u32)-1, channel, | ||
2339 | ssid, ssid_len, NULL, 0, | ||
2340 | IEEE80211_PROBE_FLAG_DIRECTED); | ||
2341 | if (skb) | ||
2342 | ieee80211_tx_skb(sdata, skb); | ||
2343 | } | ||
2344 | |||
2222 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | 2345 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) |
2223 | { | 2346 | { |
2224 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2347 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -2265,10 +2388,9 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
2265 | else | 2388 | else |
2266 | ssid_len = ssid[1]; | 2389 | ssid_len = ssid[1]; |
2267 | 2390 | ||
2268 | ieee80211_send_probe_req(sdata, sdata->vif.addr, dst, | 2391 | ieee80211_mlme_send_probe_req(sdata, sdata->vif.addr, dst, |
2269 | ssid + 2, ssid_len, NULL, | 2392 | ssid + 2, ssid_len, |
2270 | 0, (u32) -1, true, 0, | 2393 | ifmgd->associated->channel); |
2271 | ifmgd->associated->channel, false); | ||
2272 | rcu_read_unlock(); | 2394 | rcu_read_unlock(); |
2273 | } | 2395 | } |
2274 | 2396 | ||
@@ -2370,7 +2492,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
2370 | skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid, | 2492 | skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid, |
2371 | (u32) -1, cbss->channel, | 2493 | (u32) -1, cbss->channel, |
2372 | ssid + 2, ssid_len, | 2494 | ssid + 2, ssid_len, |
2373 | NULL, 0, true); | 2495 | NULL, 0, IEEE80211_PROBE_FLAG_DIRECTED); |
2374 | rcu_read_unlock(); | 2496 | rcu_read_unlock(); |
2375 | 2497 | ||
2376 | return skb; | 2498 | return skb; |
@@ -3008,6 +3130,25 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
3008 | goto out; | 3130 | goto out; |
3009 | } | 3131 | } |
3010 | 3132 | ||
3133 | /* | ||
3134 | * If AP doesn't support HT, or it doesn't have HE mandatory IEs, mark | ||
3135 | * HE as disabled. If on the 5GHz band, make sure it supports VHT. | ||
3136 | */ | ||
3137 | if (ifmgd->flags & IEEE80211_STA_DISABLE_HT || | ||
3138 | (sband->band == NL80211_BAND_5GHZ && | ||
3139 | ifmgd->flags & IEEE80211_STA_DISABLE_VHT) || | ||
3140 | (!elems.he_cap && !elems.he_operation)) | ||
3141 | ifmgd->flags |= IEEE80211_STA_DISABLE_HE; | ||
3142 | |||
3143 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && | ||
3144 | (!elems.he_cap || !elems.he_operation)) { | ||
3145 | mutex_unlock(&sdata->local->sta_mtx); | ||
3146 | sdata_info(sdata, | ||
3147 | "HE AP is missing HE capability/operation\n"); | ||
3148 | ret = false; | ||
3149 | goto out; | ||
3150 | } | ||
3151 | |||
3011 | /* Set up internal HT/VHT capabilities */ | 3152 | /* Set up internal HT/VHT capabilities */ |
3012 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) | 3153 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
3013 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 3154 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
@@ -3017,6 +3158,48 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
3017 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 3158 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
3018 | elems.vht_cap_elem, sta); | 3159 | elems.vht_cap_elem, sta); |
3019 | 3160 | ||
3161 | if (elems.he_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && | ||
3162 | elems.he_cap) { | ||
3163 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, | ||
3164 | elems.he_cap, | ||
3165 | elems.he_cap_len, | ||
3166 | sta); | ||
3167 | |||
3168 | bss_conf->he_support = sta->sta.he_cap.has_he; | ||
3169 | } else { | ||
3170 | bss_conf->he_support = false; | ||
3171 | } | ||
3172 | |||
3173 | if (bss_conf->he_support) { | ||
3174 | u32 he_oper_params = | ||
3175 | le32_to_cpu(elems.he_operation->he_oper_params); | ||
3176 | |||
3177 | bss_conf->bss_color = he_oper_params & | ||
3178 | IEEE80211_HE_OPERATION_BSS_COLOR_MASK; | ||
3179 | bss_conf->htc_trig_based_pkt_ext = | ||
3180 | (he_oper_params & | ||
3181 | IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK) << | ||
3182 | IEEE80211_HE_OPERATION_DFLT_PE_DURATION_OFFSET; | ||
3183 | bss_conf->frame_time_rts_th = | ||
3184 | (he_oper_params & | ||
3185 | IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK) << | ||
3186 | IEEE80211_HE_OPERATION_RTS_THRESHOLD_OFFSET; | ||
3187 | |||
3188 | bss_conf->multi_sta_back_32bit = | ||
3189 | sta->sta.he_cap.he_cap_elem.mac_cap_info[2] & | ||
3190 | IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP; | ||
3191 | |||
3192 | bss_conf->ack_enabled = | ||
3193 | sta->sta.he_cap.he_cap_elem.mac_cap_info[2] & | ||
3194 | IEEE80211_HE_MAC_CAP2_ACK_EN; | ||
3195 | |||
3196 | bss_conf->uora_exists = !!elems.uora_element; | ||
3197 | if (elems.uora_element) | ||
3198 | bss_conf->uora_ocw_range = elems.uora_element[0]; | ||
3199 | |||
3200 | /* TODO: OPEN: what happens if BSS color disable is set? */ | ||
3201 | } | ||
3202 | |||
3020 | /* | 3203 | /* |
3021 | * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data | 3204 | * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data |
3022 | * in their association response, so ignore that data for our own | 3205 | * in their association response, so ignore that data for our own |
@@ -3076,7 +3259,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
3076 | if (ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { | 3259 | if (ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { |
3077 | ieee80211_set_wmm_default(sdata, false, false); | 3260 | ieee80211_set_wmm_default(sdata, false, false); |
3078 | } else if (!ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 3261 | } else if (!ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, |
3079 | elems.wmm_param_len)) { | 3262 | elems.wmm_param_len, |
3263 | elems.mu_edca_param_set)) { | ||
3080 | /* still enable QoS since we might have HT/VHT */ | 3264 | /* still enable QoS since we might have HT/VHT */ |
3081 | ieee80211_set_wmm_default(sdata, false, true); | 3265 | ieee80211_set_wmm_default(sdata, false, true); |
3082 | /* set the disable-WMM flag in this case to disable | 3266 | /* set the disable-WMM flag in this case to disable |
@@ -3590,7 +3774,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3590 | 3774 | ||
3591 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && | 3775 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && |
3592 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 3776 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, |
3593 | elems.wmm_param_len)) | 3777 | elems.wmm_param_len, |
3778 | elems.mu_edca_param_set)) | ||
3594 | changed |= BSS_CHANGED_QOS; | 3779 | changed |= BSS_CHANGED_QOS; |
3595 | 3780 | ||
3596 | /* | 3781 | /* |
@@ -3629,7 +3814,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3629 | 3814 | ||
3630 | if (ieee80211_config_bw(sdata, sta, | 3815 | if (ieee80211_config_bw(sdata, sta, |
3631 | elems.ht_cap_elem, elems.ht_operation, | 3816 | elems.ht_cap_elem, elems.ht_operation, |
3632 | elems.vht_operation, bssid, &changed)) { | 3817 | elems.vht_operation, elems.he_operation, |
3818 | bssid, &changed)) { | ||
3633 | mutex_unlock(&local->sta_mtx); | 3819 | mutex_unlock(&local->sta_mtx); |
3634 | sdata_info(sdata, | 3820 | sdata_info(sdata, |
3635 | "failed to follow AP %pM bandwidth change, disconnect\n", | 3821 | "failed to follow AP %pM bandwidth change, disconnect\n", |
@@ -4266,6 +4452,68 @@ static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata, | |||
4266 | return chains; | 4452 | return chains; |
4267 | } | 4453 | } |
4268 | 4454 | ||
4455 | static bool | ||
4456 | ieee80211_verify_sta_he_mcs_support(struct ieee80211_supported_band *sband, | ||
4457 | const struct ieee80211_he_operation *he_op) | ||
4458 | { | ||
4459 | const struct ieee80211_sta_he_cap *sta_he_cap = | ||
4460 | ieee80211_get_he_sta_cap(sband); | ||
4461 | u16 ap_min_req_set; | ||
4462 | int i; | ||
4463 | |||
4464 | if (!sta_he_cap || !he_op) | ||
4465 | return false; | ||
4466 | |||
4467 | ap_min_req_set = le16_to_cpu(he_op->he_mcs_nss_set); | ||
4468 | |||
4469 | /* Need to go over for 80MHz, 160MHz and for 80+80 */ | ||
4470 | for (i = 0; i < 3; i++) { | ||
4471 | const struct ieee80211_he_mcs_nss_supp *sta_mcs_nss_supp = | ||
4472 | &sta_he_cap->he_mcs_nss_supp; | ||
4473 | u16 sta_mcs_map_rx = | ||
4474 | le16_to_cpu(((__le16 *)sta_mcs_nss_supp)[2 * i]); | ||
4475 | u16 sta_mcs_map_tx = | ||
4476 | le16_to_cpu(((__le16 *)sta_mcs_nss_supp)[2 * i + 1]); | ||
4477 | u8 nss; | ||
4478 | bool verified = true; | ||
4479 | |||
4480 | /* | ||
4481 | * For each band there is a maximum of 8 spatial streams | ||
4482 | * possible. Each of the sta_mcs_map_* is a 16-bit struct built | ||
4483 | * of 2 bits per NSS (1-8), with the values defined in enum | ||
4484 | * ieee80211_he_mcs_support. Need to make sure STA TX and RX | ||
4485 | * capabilities aren't less than the AP's minimum requirements | ||
4486 | * for this HE BSS per SS. | ||
4487 | * It is enough to find one such band that meets the reqs. | ||
4488 | */ | ||
4489 | for (nss = 8; nss > 0; nss--) { | ||
4490 | u8 sta_rx_val = (sta_mcs_map_rx >> (2 * (nss - 1))) & 3; | ||
4491 | u8 sta_tx_val = (sta_mcs_map_tx >> (2 * (nss - 1))) & 3; | ||
4492 | u8 ap_val = (ap_min_req_set >> (2 * (nss - 1))) & 3; | ||
4493 | |||
4494 | if (ap_val == IEEE80211_HE_MCS_NOT_SUPPORTED) | ||
4495 | continue; | ||
4496 | |||
4497 | /* | ||
4498 | * Make sure the HE AP doesn't require MCSs that aren't | ||
4499 | * supported by the client | ||
4500 | */ | ||
4501 | if (sta_rx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || | ||
4502 | sta_tx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || | ||
4503 | (ap_val > sta_rx_val) || (ap_val > sta_tx_val)) { | ||
4504 | verified = false; | ||
4505 | break; | ||
4506 | } | ||
4507 | } | ||
4508 | |||
4509 | if (verified) | ||
4510 | return true; | ||
4511 | } | ||
4512 | |||
4513 | /* If here, STA doesn't meet AP's HE min requirements */ | ||
4514 | return false; | ||
4515 | } | ||
4516 | |||
4269 | static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | 4517 | static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, |
4270 | struct cfg80211_bss *cbss) | 4518 | struct cfg80211_bss *cbss) |
4271 | { | 4519 | { |
@@ -4274,6 +4522,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
4274 | const struct ieee80211_ht_cap *ht_cap = NULL; | 4522 | const struct ieee80211_ht_cap *ht_cap = NULL; |
4275 | const struct ieee80211_ht_operation *ht_oper = NULL; | 4523 | const struct ieee80211_ht_operation *ht_oper = NULL; |
4276 | const struct ieee80211_vht_operation *vht_oper = NULL; | 4524 | const struct ieee80211_vht_operation *vht_oper = NULL; |
4525 | const struct ieee80211_he_operation *he_oper = NULL; | ||
4277 | struct ieee80211_supported_band *sband; | 4526 | struct ieee80211_supported_band *sband; |
4278 | struct cfg80211_chan_def chandef; | 4527 | struct cfg80211_chan_def chandef; |
4279 | int ret; | 4528 | int ret; |
@@ -4329,6 +4578,24 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
4329 | } | 4578 | } |
4330 | } | 4579 | } |
4331 | 4580 | ||
4581 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && | ||
4582 | ieee80211_get_he_sta_cap(sband)) { | ||
4583 | const struct cfg80211_bss_ies *ies; | ||
4584 | const u8 *he_oper_ie; | ||
4585 | |||
4586 | ies = rcu_dereference(cbss->ies); | ||
4587 | he_oper_ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION, | ||
4588 | ies->data, ies->len); | ||
4589 | if (he_oper_ie && | ||
4590 | he_oper_ie[1] == ieee80211_he_oper_size(&he_oper_ie[3])) | ||
4591 | he_oper = (void *)(he_oper_ie + 3); | ||
4592 | else | ||
4593 | he_oper = NULL; | ||
4594 | |||
4595 | if (!ieee80211_verify_sta_he_mcs_support(sband, he_oper)) | ||
4596 | ifmgd->flags |= IEEE80211_STA_DISABLE_HE; | ||
4597 | } | ||
4598 | |||
4332 | /* Allow VHT if at least one channel on the sband supports 80 MHz */ | 4599 | /* Allow VHT if at least one channel on the sband supports 80 MHz */ |
4333 | have_80mhz = false; | 4600 | have_80mhz = false; |
4334 | for (i = 0; i < sband->n_channels; i++) { | 4601 | for (i = 0; i < sband->n_channels; i++) { |
@@ -4345,7 +4612,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
4345 | 4612 | ||
4346 | ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, | 4613 | ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, |
4347 | cbss->channel, | 4614 | cbss->channel, |
4348 | ht_oper, vht_oper, | 4615 | ht_oper, vht_oper, he_oper, |
4349 | &chandef, false); | 4616 | &chandef, false); |
4350 | 4617 | ||
4351 | sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), | 4618 | sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), |
@@ -4751,8 +5018,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4751 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { | 5018 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { |
4752 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | 5019 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
4753 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 5020 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
5021 | ifmgd->flags |= IEEE80211_STA_DISABLE_HE; | ||
4754 | netdev_info(sdata->dev, | 5022 | netdev_info(sdata->dev, |
4755 | "disabling HT/VHT due to WEP/TKIP use\n"); | 5023 | "disabling HE/HT/VHT due to WEP/TKIP use\n"); |
4756 | } | 5024 | } |
4757 | } | 5025 | } |
4758 | 5026 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index f1d40b6645ff..8ef4153cd299 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -262,7 +262,7 @@ static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc, | |||
262 | if (roc->mgmt_tx_cookie) { | 262 | if (roc->mgmt_tx_cookie) { |
263 | if (!WARN_ON(!roc->frame)) { | 263 | if (!WARN_ON(!roc->frame)) { |
264 | ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7, | 264 | ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7, |
265 | roc->chan->band); | 265 | roc->chan->band, 0); |
266 | roc->frame = NULL; | 266 | roc->frame = NULL; |
267 | } | 267 | } |
268 | } else { | 268 | } else { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0a38cc1cbebc..a16ba568e2a3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -175,6 +175,20 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local, | |||
175 | len += 12; | 175 | len += 12; |
176 | } | 176 | } |
177 | 177 | ||
178 | if (status->encoding == RX_ENC_HE && | ||
179 | status->flag & RX_FLAG_RADIOTAP_HE) { | ||
180 | len = ALIGN(len, 2); | ||
181 | len += 12; | ||
182 | BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he) != 12); | ||
183 | } | ||
184 | |||
185 | if (status->encoding == RX_ENC_HE && | ||
186 | status->flag & RX_FLAG_RADIOTAP_HE_MU) { | ||
187 | len = ALIGN(len, 2); | ||
188 | len += 12; | ||
189 | BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) != 12); | ||
190 | } | ||
191 | |||
178 | if (status->chains) { | 192 | if (status->chains) { |
179 | /* antenna and antenna signal fields */ | 193 | /* antenna and antenna signal fields */ |
180 | len += 2 * hweight8(status->chains); | 194 | len += 2 * hweight8(status->chains); |
@@ -263,6 +277,19 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
263 | int mpdulen, chain; | 277 | int mpdulen, chain; |
264 | unsigned long chains = status->chains; | 278 | unsigned long chains = status->chains; |
265 | struct ieee80211_vendor_radiotap rtap = {}; | 279 | struct ieee80211_vendor_radiotap rtap = {}; |
280 | struct ieee80211_radiotap_he he = {}; | ||
281 | struct ieee80211_radiotap_he_mu he_mu = {}; | ||
282 | |||
283 | if (status->flag & RX_FLAG_RADIOTAP_HE) { | ||
284 | he = *(struct ieee80211_radiotap_he *)skb->data; | ||
285 | skb_pull(skb, sizeof(he)); | ||
286 | WARN_ON_ONCE(status->encoding != RX_ENC_HE); | ||
287 | } | ||
288 | |||
289 | if (status->flag & RX_FLAG_RADIOTAP_HE_MU) { | ||
290 | he_mu = *(struct ieee80211_radiotap_he_mu *)skb->data; | ||
291 | skb_pull(skb, sizeof(he_mu)); | ||
292 | } | ||
266 | 293 | ||
267 | if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) { | 294 | if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) { |
268 | rtap = *(struct ieee80211_vendor_radiotap *)skb->data; | 295 | rtap = *(struct ieee80211_vendor_radiotap *)skb->data; |
@@ -520,6 +547,89 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
520 | *pos++ = flags; | 547 | *pos++ = flags; |
521 | } | 548 | } |
522 | 549 | ||
550 | if (status->encoding == RX_ENC_HE && | ||
551 | status->flag & RX_FLAG_RADIOTAP_HE) { | ||
552 | #define HE_PREP(f, val) cpu_to_le16(FIELD_PREP(IEEE80211_RADIOTAP_HE_##f, val)) | ||
553 | |||
554 | if (status->enc_flags & RX_ENC_FLAG_STBC_MASK) { | ||
555 | he.data6 |= HE_PREP(DATA6_NSTS, | ||
556 | FIELD_GET(RX_ENC_FLAG_STBC_MASK, | ||
557 | status->enc_flags)); | ||
558 | he.data3 |= HE_PREP(DATA3_STBC, 1); | ||
559 | } else { | ||
560 | he.data6 |= HE_PREP(DATA6_NSTS, status->nss); | ||
561 | } | ||
562 | |||
563 | #define CHECK_GI(s) \ | ||
564 | BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_GI_##s != \ | ||
565 | (int)NL80211_RATE_INFO_HE_GI_##s) | ||
566 | |||
567 | CHECK_GI(0_8); | ||
568 | CHECK_GI(1_6); | ||
569 | CHECK_GI(3_2); | ||
570 | |||
571 | he.data3 |= HE_PREP(DATA3_DATA_MCS, status->rate_idx); | ||
572 | he.data3 |= HE_PREP(DATA3_DATA_DCM, status->he_dcm); | ||
573 | he.data3 |= HE_PREP(DATA3_CODING, | ||
574 | !!(status->enc_flags & RX_ENC_FLAG_LDPC)); | ||
575 | |||
576 | he.data5 |= HE_PREP(DATA5_GI, status->he_gi); | ||
577 | |||
578 | switch (status->bw) { | ||
579 | case RATE_INFO_BW_20: | ||
580 | he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, | ||
581 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ); | ||
582 | break; | ||
583 | case RATE_INFO_BW_40: | ||
584 | he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, | ||
585 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ); | ||
586 | break; | ||
587 | case RATE_INFO_BW_80: | ||
588 | he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, | ||
589 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ); | ||
590 | break; | ||
591 | case RATE_INFO_BW_160: | ||
592 | he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, | ||
593 | IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ); | ||
594 | break; | ||
595 | case RATE_INFO_BW_HE_RU: | ||
596 | #define CHECK_RU_ALLOC(s) \ | ||
597 | BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_##s##T != \ | ||
598 | NL80211_RATE_INFO_HE_RU_ALLOC_##s + 4) | ||
599 | |||
600 | CHECK_RU_ALLOC(26); | ||
601 | CHECK_RU_ALLOC(52); | ||
602 | CHECK_RU_ALLOC(106); | ||
603 | CHECK_RU_ALLOC(242); | ||
604 | CHECK_RU_ALLOC(484); | ||
605 | CHECK_RU_ALLOC(996); | ||
606 | CHECK_RU_ALLOC(2x996); | ||
607 | |||
608 | he.data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, | ||
609 | status->he_ru + 4); | ||
610 | break; | ||
611 | default: | ||
612 | WARN_ONCE(1, "Invalid SU BW %d\n", status->bw); | ||
613 | } | ||
614 | |||
615 | /* ensure 2 byte alignment */ | ||
616 | while ((pos - (u8 *)rthdr) & 1) | ||
617 | pos++; | ||
618 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE); | ||
619 | memcpy(pos, &he, sizeof(he)); | ||
620 | pos += sizeof(he); | ||
621 | } | ||
622 | |||
623 | if (status->encoding == RX_ENC_HE && | ||
624 | status->flag & RX_FLAG_RADIOTAP_HE_MU) { | ||
625 | /* ensure 2 byte alignment */ | ||
626 | while ((pos - (u8 *)rthdr) & 1) | ||
627 | pos++; | ||
628 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE_MU); | ||
629 | memcpy(pos, &he_mu, sizeof(he_mu)); | ||
630 | pos += sizeof(he_mu); | ||
631 | } | ||
632 | |||
523 | for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { | 633 | for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { |
524 | *pos++ = status->chain_signal[chain]; | 634 | *pos++ = status->chain_signal[chain]; |
525 | *pos++ = chain; | 635 | *pos++ = chain; |
@@ -613,6 +723,12 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
613 | rcu_dereference(local->monitor_sdata); | 723 | rcu_dereference(local->monitor_sdata); |
614 | bool only_monitor = false; | 724 | bool only_monitor = false; |
615 | 725 | ||
726 | if (status->flag & RX_FLAG_RADIOTAP_HE) | ||
727 | rtap_space += sizeof(struct ieee80211_radiotap_he); | ||
728 | |||
729 | if (status->flag & RX_FLAG_RADIOTAP_HE_MU) | ||
730 | rtap_space += sizeof(struct ieee80211_radiotap_he_mu); | ||
731 | |||
616 | if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) { | 732 | if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) { |
617 | struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data; | 733 | struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data; |
618 | 734 | ||
@@ -3241,7 +3357,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) | |||
3241 | } | 3357 | } |
3242 | 3358 | ||
3243 | __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7, | 3359 | __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7, |
3244 | status->band); | 3360 | status->band, 0); |
3245 | } | 3361 | } |
3246 | dev_kfree_skb(rx->skb); | 3362 | dev_kfree_skb(rx->skb); |
3247 | return RX_QUEUED; | 3363 | return RX_QUEUED; |
@@ -3386,8 +3502,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
3386 | status = IEEE80211_SKB_RXCB((rx->skb)); | 3502 | status = IEEE80211_SKB_RXCB((rx->skb)); |
3387 | 3503 | ||
3388 | sband = rx->local->hw.wiphy->bands[status->band]; | 3504 | sband = rx->local->hw.wiphy->bands[status->band]; |
3389 | if (!(status->encoding == RX_ENC_HT) && | 3505 | if (status->encoding == RX_ENC_LEGACY) |
3390 | !(status->encoding == RX_ENC_VHT)) | ||
3391 | rate = &sband->bitrates[status->rate_idx]; | 3506 | rate = &sband->bitrates[status->rate_idx]; |
3392 | 3507 | ||
3393 | ieee80211_rx_cooked_monitor(rx, rate); | 3508 | ieee80211_rx_cooked_monitor(rx, rate); |
@@ -4386,6 +4501,14 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, | |||
4386 | status->rate_idx, status->nss)) | 4501 | status->rate_idx, status->nss)) |
4387 | goto drop; | 4502 | goto drop; |
4388 | break; | 4503 | break; |
4504 | case RX_ENC_HE: | ||
4505 | if (WARN_ONCE(status->rate_idx > 11 || | ||
4506 | !status->nss || | ||
4507 | status->nss > 8, | ||
4508 | "Rate marked as an HE rate but data is invalid: MCS: %d, NSS: %d\n", | ||
4509 | status->rate_idx, status->nss)) | ||
4510 | goto drop; | ||
4511 | break; | ||
4389 | default: | 4512 | default: |
4390 | WARN_ON_ONCE(1); | 4513 | WARN_ON_ONCE(1); |
4391 | /* fall through */ | 4514 | /* fall through */ |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 2e917a6d239d..5d2a11777718 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <net/sch_generic.h> | 20 | #include <net/sch_generic.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/export.h> | 22 | #include <linux/export.h> |
23 | #include <linux/random.h> | ||
23 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
24 | 25 | ||
25 | #include "ieee80211_i.h" | 26 | #include "ieee80211_i.h" |
@@ -293,6 +294,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
293 | struct cfg80211_chan_def chandef; | 294 | struct cfg80211_chan_def chandef; |
294 | u8 bands_used = 0; | 295 | u8 bands_used = 0; |
295 | int i, ielen, n_chans; | 296 | int i, ielen, n_chans; |
297 | u32 flags = 0; | ||
296 | 298 | ||
297 | req = rcu_dereference_protected(local->scan_req, | 299 | req = rcu_dereference_protected(local->scan_req, |
298 | lockdep_is_held(&local->mtx)); | 300 | lockdep_is_held(&local->mtx)); |
@@ -331,12 +333,16 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
331 | local->hw_scan_req->req.n_channels = n_chans; | 333 | local->hw_scan_req->req.n_channels = n_chans; |
332 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | 334 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); |
333 | 335 | ||
336 | if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) | ||
337 | flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT; | ||
338 | |||
334 | ielen = ieee80211_build_preq_ies(local, | 339 | ielen = ieee80211_build_preq_ies(local, |
335 | (u8 *)local->hw_scan_req->req.ie, | 340 | (u8 *)local->hw_scan_req->req.ie, |
336 | local->hw_scan_ies_bufsize, | 341 | local->hw_scan_ies_bufsize, |
337 | &local->hw_scan_req->ies, | 342 | &local->hw_scan_req->ies, |
338 | req->ie, req->ie_len, | 343 | req->ie, req->ie_len, |
339 | bands_used, req->rates, &chandef); | 344 | bands_used, req->rates, &chandef, |
345 | flags); | ||
340 | local->hw_scan_req->req.ie_len = ielen; | 346 | local->hw_scan_req->req.ie_len = ielen; |
341 | local->hw_scan_req->req.no_cck = req->no_cck; | 347 | local->hw_scan_req->req.no_cck = req->no_cck; |
342 | ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr); | 348 | ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr); |
@@ -528,6 +534,35 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local) | |||
528 | round_jiffies_relative(0)); | 534 | round_jiffies_relative(0)); |
529 | } | 535 | } |
530 | 536 | ||
537 | static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata, | ||
538 | const u8 *src, const u8 *dst, | ||
539 | const u8 *ssid, size_t ssid_len, | ||
540 | const u8 *ie, size_t ie_len, | ||
541 | u32 ratemask, u32 flags, u32 tx_flags, | ||
542 | struct ieee80211_channel *channel) | ||
543 | { | ||
544 | struct sk_buff *skb; | ||
545 | u32 txdata_flags = 0; | ||
546 | |||
547 | skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel, | ||
548 | ssid, ssid_len, | ||
549 | ie, ie_len, flags); | ||
550 | |||
551 | if (skb) { | ||
552 | if (flags & IEEE80211_PROBE_FLAG_RANDOM_SN) { | ||
553 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
554 | u16 sn = get_random_u32(); | ||
555 | |||
556 | txdata_flags |= IEEE80211_TX_NO_SEQNO; | ||
557 | hdr->seq_ctrl = | ||
558 | cpu_to_le16(IEEE80211_SN_TO_SEQ(sn)); | ||
559 | } | ||
560 | IEEE80211_SKB_CB(skb)->flags |= tx_flags; | ||
561 | ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band, | ||
562 | txdata_flags); | ||
563 | } | ||
564 | } | ||
565 | |||
531 | static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | 566 | static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, |
532 | unsigned long *next_delay) | 567 | unsigned long *next_delay) |
533 | { | 568 | { |
@@ -535,7 +570,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
535 | struct ieee80211_sub_if_data *sdata; | 570 | struct ieee80211_sub_if_data *sdata; |
536 | struct cfg80211_scan_request *scan_req; | 571 | struct cfg80211_scan_request *scan_req; |
537 | enum nl80211_band band = local->hw.conf.chandef.chan->band; | 572 | enum nl80211_band band = local->hw.conf.chandef.chan->band; |
538 | u32 tx_flags; | 573 | u32 flags = 0, tx_flags; |
539 | 574 | ||
540 | scan_req = rcu_dereference_protected(local->scan_req, | 575 | scan_req = rcu_dereference_protected(local->scan_req, |
541 | lockdep_is_held(&local->mtx)); | 576 | lockdep_is_held(&local->mtx)); |
@@ -543,17 +578,21 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
543 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | 578 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; |
544 | if (scan_req->no_cck) | 579 | if (scan_req->no_cck) |
545 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | 580 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; |
581 | if (scan_req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) | ||
582 | flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT; | ||
583 | if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_SN) | ||
584 | flags |= IEEE80211_PROBE_FLAG_RANDOM_SN; | ||
546 | 585 | ||
547 | sdata = rcu_dereference_protected(local->scan_sdata, | 586 | sdata = rcu_dereference_protected(local->scan_sdata, |
548 | lockdep_is_held(&local->mtx)); | 587 | lockdep_is_held(&local->mtx)); |
549 | 588 | ||
550 | for (i = 0; i < scan_req->n_ssids; i++) | 589 | for (i = 0; i < scan_req->n_ssids; i++) |
551 | ieee80211_send_probe_req( | 590 | ieee80211_send_scan_probe_req( |
552 | sdata, local->scan_addr, scan_req->bssid, | 591 | sdata, local->scan_addr, scan_req->bssid, |
553 | scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, | 592 | scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, |
554 | scan_req->ie, scan_req->ie_len, | 593 | scan_req->ie, scan_req->ie_len, |
555 | scan_req->rates[band], false, | 594 | scan_req->rates[band], flags, |
556 | tx_flags, local->hw.conf.chandef.chan, true); | 595 | tx_flags, local->hw.conf.chandef.chan); |
557 | 596 | ||
558 | /* | 597 | /* |
559 | * After sending probe requests, wait for probe responses | 598 | * After sending probe requests, wait for probe responses |
@@ -1141,6 +1180,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
1141 | u32 rate_masks[NUM_NL80211_BANDS] = {}; | 1180 | u32 rate_masks[NUM_NL80211_BANDS] = {}; |
1142 | u8 bands_used = 0; | 1181 | u8 bands_used = 0; |
1143 | u8 *ie; | 1182 | u8 *ie; |
1183 | u32 flags = 0; | ||
1144 | 1184 | ||
1145 | iebufsz = local->scan_ies_len + req->ie_len; | 1185 | iebufsz = local->scan_ies_len + req->ie_len; |
1146 | 1186 | ||
@@ -1157,6 +1197,9 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
1157 | } | 1197 | } |
1158 | } | 1198 | } |
1159 | 1199 | ||
1200 | if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) | ||
1201 | flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT; | ||
1202 | |||
1160 | ie = kcalloc(iebufsz, num_bands, GFP_KERNEL); | 1203 | ie = kcalloc(iebufsz, num_bands, GFP_KERNEL); |
1161 | if (!ie) { | 1204 | if (!ie) { |
1162 | ret = -ENOMEM; | 1205 | ret = -ENOMEM; |
@@ -1167,7 +1210,8 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
1167 | 1210 | ||
1168 | ieee80211_build_preq_ies(local, ie, num_bands * iebufsz, | 1211 | ieee80211_build_preq_ies(local, ie, num_bands * iebufsz, |
1169 | &sched_scan_ies, req->ie, | 1212 | &sched_scan_ies, req->ie, |
1170 | req->ie_len, bands_used, rate_masks, &chandef); | 1213 | req->ie_len, bands_used, rate_masks, &chandef, |
1214 | flags); | ||
1171 | 1215 | ||
1172 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 1216 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
1173 | if (ret == 0) { | 1217 | if (ret == 0) { |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 6428f1ac37b6..f34202242d24 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1323,6 +1323,11 @@ static void ieee80211_send_null_response(struct sta_info *sta, int tid, | |||
1323 | struct ieee80211_tx_info *info; | 1323 | struct ieee80211_tx_info *info; |
1324 | struct ieee80211_chanctx_conf *chanctx_conf; | 1324 | struct ieee80211_chanctx_conf *chanctx_conf; |
1325 | 1325 | ||
1326 | /* Don't send NDPs when STA is connected HE */ | ||
1327 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
1328 | !(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE)) | ||
1329 | return; | ||
1330 | |||
1326 | if (qos) { | 1331 | if (qos) { |
1327 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | | 1332 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | |
1328 | IEEE80211_STYPE_QOS_NULLFUNC | | 1333 | IEEE80211_STYPE_QOS_NULLFUNC | |
@@ -1391,7 +1396,7 @@ static void ieee80211_send_null_response(struct sta_info *sta, int tid, | |||
1391 | } | 1396 | } |
1392 | 1397 | ||
1393 | info->band = chanctx_conf->def.chan->band; | 1398 | info->band = chanctx_conf->def.chan->band; |
1394 | ieee80211_xmit(sdata, sta, skb); | 1399 | ieee80211_xmit(sdata, sta, skb, 0); |
1395 | rcu_read_unlock(); | 1400 | rcu_read_unlock(); |
1396 | } | 1401 | } |
1397 | 1402 | ||
@@ -1968,7 +1973,7 @@ sta_get_last_rx_stats(struct sta_info *sta) | |||
1968 | return stats; | 1973 | return stats; |
1969 | } | 1974 | } |
1970 | 1975 | ||
1971 | static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, | 1976 | static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate, |
1972 | struct rate_info *rinfo) | 1977 | struct rate_info *rinfo) |
1973 | { | 1978 | { |
1974 | rinfo->bw = STA_STATS_GET(BW, rate); | 1979 | rinfo->bw = STA_STATS_GET(BW, rate); |
@@ -2005,6 +2010,14 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, | |||
2005 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); | 2010 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); |
2006 | break; | 2011 | break; |
2007 | } | 2012 | } |
2013 | case STA_STATS_RATE_TYPE_HE: | ||
2014 | rinfo->flags = RATE_INFO_FLAGS_HE_MCS; | ||
2015 | rinfo->mcs = STA_STATS_GET(HE_MCS, rate); | ||
2016 | rinfo->nss = STA_STATS_GET(HE_NSS, rate); | ||
2017 | rinfo->he_gi = STA_STATS_GET(HE_GI, rate); | ||
2018 | rinfo->he_ru_alloc = STA_STATS_GET(HE_RU, rate); | ||
2019 | rinfo->he_dcm = STA_STATS_GET(HE_DCM, rate); | ||
2020 | break; | ||
2008 | } | 2021 | } |
2009 | } | 2022 | } |
2010 | 2023 | ||
@@ -2101,38 +2114,38 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, | |||
2101 | 2114 | ||
2102 | drv_sta_statistics(local, sdata, &sta->sta, sinfo); | 2115 | drv_sta_statistics(local, sdata, &sta->sta, sinfo); |
2103 | 2116 | ||
2104 | sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) | | 2117 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) | |
2105 | BIT(NL80211_STA_INFO_STA_FLAGS) | | 2118 | BIT_ULL(NL80211_STA_INFO_STA_FLAGS) | |
2106 | BIT(NL80211_STA_INFO_BSS_PARAM) | | 2119 | BIT_ULL(NL80211_STA_INFO_BSS_PARAM) | |
2107 | BIT(NL80211_STA_INFO_CONNECTED_TIME) | | 2120 | BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME) | |
2108 | BIT(NL80211_STA_INFO_RX_DROP_MISC); | 2121 | BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC); |
2109 | 2122 | ||
2110 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 2123 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
2111 | sinfo->beacon_loss_count = sdata->u.mgd.beacon_loss_count; | 2124 | sinfo->beacon_loss_count = sdata->u.mgd.beacon_loss_count; |
2112 | sinfo->filled |= BIT(NL80211_STA_INFO_BEACON_LOSS); | 2125 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_LOSS); |
2113 | } | 2126 | } |
2114 | 2127 | ||
2115 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; | 2128 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; |
2116 | sinfo->inactive_time = | 2129 | sinfo->inactive_time = |
2117 | jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta)); | 2130 | jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta)); |
2118 | 2131 | ||
2119 | if (!(sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES64) | | 2132 | if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | |
2120 | BIT(NL80211_STA_INFO_TX_BYTES)))) { | 2133 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { |
2121 | sinfo->tx_bytes = 0; | 2134 | sinfo->tx_bytes = 0; |
2122 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 2135 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
2123 | sinfo->tx_bytes += sta->tx_stats.bytes[ac]; | 2136 | sinfo->tx_bytes += sta->tx_stats.bytes[ac]; |
2124 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); | 2137 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); |
2125 | } | 2138 | } |
2126 | 2139 | ||
2127 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_PACKETS))) { | 2140 | if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_PACKETS))) { |
2128 | sinfo->tx_packets = 0; | 2141 | sinfo->tx_packets = 0; |
2129 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 2142 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
2130 | sinfo->tx_packets += sta->tx_stats.packets[ac]; | 2143 | sinfo->tx_packets += sta->tx_stats.packets[ac]; |
2131 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); | 2144 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); |
2132 | } | 2145 | } |
2133 | 2146 | ||
2134 | if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) | | 2147 | if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) | |
2135 | BIT(NL80211_STA_INFO_RX_BYTES)))) { | 2148 | BIT_ULL(NL80211_STA_INFO_RX_BYTES)))) { |
2136 | sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats); | 2149 | sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats); |
2137 | 2150 | ||
2138 | if (sta->pcpu_rx_stats) { | 2151 | if (sta->pcpu_rx_stats) { |
@@ -2144,10 +2157,10 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, | |||
2144 | } | 2157 | } |
2145 | } | 2158 | } |
2146 | 2159 | ||
2147 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); | 2160 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64); |
2148 | } | 2161 | } |
2149 | 2162 | ||
2150 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_PACKETS))) { | 2163 | if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_PACKETS))) { |
2151 | sinfo->rx_packets = sta->rx_stats.packets; | 2164 | sinfo->rx_packets = sta->rx_stats.packets; |
2152 | if (sta->pcpu_rx_stats) { | 2165 | if (sta->pcpu_rx_stats) { |
2153 | for_each_possible_cpu(cpu) { | 2166 | for_each_possible_cpu(cpu) { |
@@ -2157,17 +2170,17 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, | |||
2157 | sinfo->rx_packets += cpurxs->packets; | 2170 | sinfo->rx_packets += cpurxs->packets; |
2158 | } | 2171 | } |
2159 | } | 2172 | } |
2160 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); | 2173 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS); |
2161 | } | 2174 | } |
2162 | 2175 | ||
2163 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_RETRIES))) { | 2176 | if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_RETRIES))) { |
2164 | sinfo->tx_retries = sta->status_stats.retry_count; | 2177 | sinfo->tx_retries = sta->status_stats.retry_count; |
2165 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_RETRIES); | 2178 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); |
2166 | } | 2179 | } |
2167 | 2180 | ||
2168 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_FAILED))) { | 2181 | if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))) { |
2169 | sinfo->tx_failed = sta->status_stats.retry_failed; | 2182 | sinfo->tx_failed = sta->status_stats.retry_failed; |
2170 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); | 2183 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); |
2171 | } | 2184 | } |
2172 | 2185 | ||
2173 | sinfo->rx_dropped_misc = sta->rx_stats.dropped; | 2186 | sinfo->rx_dropped_misc = sta->rx_stats.dropped; |
@@ -2182,23 +2195,23 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, | |||
2182 | 2195 | ||
2183 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 2196 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
2184 | !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) { | 2197 | !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) { |
2185 | sinfo->filled |= BIT(NL80211_STA_INFO_BEACON_RX) | | 2198 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX) | |
2186 | BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG); | 2199 | BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG); |
2187 | sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif); | 2200 | sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif); |
2188 | } | 2201 | } |
2189 | 2202 | ||
2190 | if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) || | 2203 | if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) || |
2191 | ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) { | 2204 | ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) { |
2192 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) { | 2205 | if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL))) { |
2193 | sinfo->signal = (s8)last_rxstats->last_signal; | 2206 | sinfo->signal = (s8)last_rxstats->last_signal; |
2194 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); | 2207 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); |
2195 | } | 2208 | } |
2196 | 2209 | ||
2197 | if (!sta->pcpu_rx_stats && | 2210 | if (!sta->pcpu_rx_stats && |
2198 | !(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) { | 2211 | !(sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG))) { |
2199 | sinfo->signal_avg = | 2212 | sinfo->signal_avg = |
2200 | -ewma_signal_read(&sta->rx_stats_avg.signal); | 2213 | -ewma_signal_read(&sta->rx_stats_avg.signal); |
2201 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG); | 2214 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); |
2202 | } | 2215 | } |
2203 | } | 2216 | } |
2204 | 2217 | ||
@@ -2207,11 +2220,11 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, | |||
2207 | * pcpu statistics | 2220 | * pcpu statistics |
2208 | */ | 2221 | */ |
2209 | if (last_rxstats->chains && | 2222 | if (last_rxstats->chains && |
2210 | !(sinfo->filled & (BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | | 2223 | !(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL) | |
2211 | BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) { | 2224 | BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) { |
2212 | sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL); | 2225 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL); |
2213 | if (!sta->pcpu_rx_stats) | 2226 | if (!sta->pcpu_rx_stats) |
2214 | sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); | 2227 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); |
2215 | 2228 | ||
2216 | sinfo->chains = last_rxstats->chains; | 2229 | sinfo->chains = last_rxstats->chains; |
2217 | 2230 | ||
@@ -2223,15 +2236,15 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, | |||
2223 | } | 2236 | } |
2224 | } | 2237 | } |
2225 | 2238 | ||
2226 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE))) { | 2239 | if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) { |
2227 | sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, | 2240 | sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, |
2228 | &sinfo->txrate); | 2241 | &sinfo->txrate); |
2229 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); | 2242 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
2230 | } | 2243 | } |
2231 | 2244 | ||
2232 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE))) { | 2245 | if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE))) { |
2233 | if (sta_set_rate_info_rx(sta, &sinfo->rxrate) == 0) | 2246 | if (sta_set_rate_info_rx(sta, &sinfo->rxrate) == 0) |
2234 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); | 2247 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); |
2235 | } | 2248 | } |
2236 | 2249 | ||
2237 | if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) { | 2250 | if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) { |
@@ -2244,18 +2257,18 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, | |||
2244 | 2257 | ||
2245 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 2258 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
2246 | #ifdef CONFIG_MAC80211_MESH | 2259 | #ifdef CONFIG_MAC80211_MESH |
2247 | sinfo->filled |= BIT(NL80211_STA_INFO_LLID) | | 2260 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_LLID) | |
2248 | BIT(NL80211_STA_INFO_PLID) | | 2261 | BIT_ULL(NL80211_STA_INFO_PLID) | |
2249 | BIT(NL80211_STA_INFO_PLINK_STATE) | | 2262 | BIT_ULL(NL80211_STA_INFO_PLINK_STATE) | |
2250 | BIT(NL80211_STA_INFO_LOCAL_PM) | | 2263 | BIT_ULL(NL80211_STA_INFO_LOCAL_PM) | |
2251 | BIT(NL80211_STA_INFO_PEER_PM) | | 2264 | BIT_ULL(NL80211_STA_INFO_PEER_PM) | |
2252 | BIT(NL80211_STA_INFO_NONPEER_PM); | 2265 | BIT_ULL(NL80211_STA_INFO_NONPEER_PM); |
2253 | 2266 | ||
2254 | sinfo->llid = sta->mesh->llid; | 2267 | sinfo->llid = sta->mesh->llid; |
2255 | sinfo->plid = sta->mesh->plid; | 2268 | sinfo->plid = sta->mesh->plid; |
2256 | sinfo->plink_state = sta->mesh->plink_state; | 2269 | sinfo->plink_state = sta->mesh->plink_state; |
2257 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | 2270 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { |
2258 | sinfo->filled |= BIT(NL80211_STA_INFO_T_OFFSET); | 2271 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_T_OFFSET); |
2259 | sinfo->t_offset = sta->mesh->t_offset; | 2272 | sinfo->t_offset = sta->mesh->t_offset; |
2260 | } | 2273 | } |
2261 | sinfo->local_pm = sta->mesh->local_pm; | 2274 | sinfo->local_pm = sta->mesh->local_pm; |
@@ -2300,7 +2313,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, | |||
2300 | thr = sta_get_expected_throughput(sta); | 2313 | thr = sta_get_expected_throughput(sta); |
2301 | 2314 | ||
2302 | if (thr != 0) { | 2315 | if (thr != 0) { |
2303 | sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT); | 2316 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT); |
2304 | sinfo->expected_throughput = thr; | 2317 | sinfo->expected_throughput = thr; |
2305 | } | 2318 | } |
2306 | 2319 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 81b35f623792..9a04327d71d1 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -170,7 +170,7 @@ struct tid_ampdu_tx { | |||
170 | u8 dialog_token; | 170 | u8 dialog_token; |
171 | u8 stop_initiator; | 171 | u8 stop_initiator; |
172 | bool tx_stop; | 172 | bool tx_stop; |
173 | u8 buf_size; | 173 | u16 buf_size; |
174 | 174 | ||
175 | u16 failed_bar_ssn; | 175 | u16 failed_bar_ssn; |
176 | bool bar_pending; | 176 | bool bar_pending; |
@@ -405,7 +405,7 @@ struct ieee80211_sta_rx_stats { | |||
405 | int last_signal; | 405 | int last_signal; |
406 | u8 chains; | 406 | u8 chains; |
407 | s8 chain_signal_last[IEEE80211_MAX_CHAINS]; | 407 | s8 chain_signal_last[IEEE80211_MAX_CHAINS]; |
408 | u16 last_rate; | 408 | u32 last_rate; |
409 | struct u64_stats_sync syncp; | 409 | struct u64_stats_sync syncp; |
410 | u64 bytes; | 410 | u64 bytes; |
411 | u64 msdu[IEEE80211_NUM_TIDS + 1]; | 411 | u64 msdu[IEEE80211_NUM_TIDS + 1]; |
@@ -764,6 +764,7 @@ enum sta_stats_type { | |||
764 | STA_STATS_RATE_TYPE_LEGACY, | 764 | STA_STATS_RATE_TYPE_LEGACY, |
765 | STA_STATS_RATE_TYPE_HT, | 765 | STA_STATS_RATE_TYPE_HT, |
766 | STA_STATS_RATE_TYPE_VHT, | 766 | STA_STATS_RATE_TYPE_VHT, |
767 | STA_STATS_RATE_TYPE_HE, | ||
767 | }; | 768 | }; |
768 | 769 | ||
769 | #define STA_STATS_FIELD_HT_MCS GENMASK( 7, 0) | 770 | #define STA_STATS_FIELD_HT_MCS GENMASK( 7, 0) |
@@ -771,9 +772,14 @@ enum sta_stats_type { | |||
771 | #define STA_STATS_FIELD_LEGACY_BAND GENMASK( 7, 4) | 772 | #define STA_STATS_FIELD_LEGACY_BAND GENMASK( 7, 4) |
772 | #define STA_STATS_FIELD_VHT_MCS GENMASK( 3, 0) | 773 | #define STA_STATS_FIELD_VHT_MCS GENMASK( 3, 0) |
773 | #define STA_STATS_FIELD_VHT_NSS GENMASK( 7, 4) | 774 | #define STA_STATS_FIELD_VHT_NSS GENMASK( 7, 4) |
775 | #define STA_STATS_FIELD_HE_MCS GENMASK( 3, 0) | ||
776 | #define STA_STATS_FIELD_HE_NSS GENMASK( 7, 4) | ||
774 | #define STA_STATS_FIELD_BW GENMASK(11, 8) | 777 | #define STA_STATS_FIELD_BW GENMASK(11, 8) |
775 | #define STA_STATS_FIELD_SGI GENMASK(12, 12) | 778 | #define STA_STATS_FIELD_SGI GENMASK(12, 12) |
776 | #define STA_STATS_FIELD_TYPE GENMASK(15, 13) | 779 | #define STA_STATS_FIELD_TYPE GENMASK(15, 13) |
780 | #define STA_STATS_FIELD_HE_RU GENMASK(18, 16) | ||
781 | #define STA_STATS_FIELD_HE_GI GENMASK(20, 19) | ||
782 | #define STA_STATS_FIELD_HE_DCM GENMASK(21, 21) | ||
777 | 783 | ||
778 | #define STA_STATS_FIELD(_n, _v) FIELD_PREP(STA_STATS_FIELD_ ## _n, _v) | 784 | #define STA_STATS_FIELD(_n, _v) FIELD_PREP(STA_STATS_FIELD_ ## _n, _v) |
779 | #define STA_STATS_GET(_n, _v) FIELD_GET(STA_STATS_FIELD_ ## _n, _v) | 785 | #define STA_STATS_GET(_n, _v) FIELD_GET(STA_STATS_FIELD_ ## _n, _v) |
@@ -782,7 +788,7 @@ enum sta_stats_type { | |||
782 | 788 | ||
783 | static inline u32 sta_stats_encode_rate(struct ieee80211_rx_status *s) | 789 | static inline u32 sta_stats_encode_rate(struct ieee80211_rx_status *s) |
784 | { | 790 | { |
785 | u16 r; | 791 | u32 r; |
786 | 792 | ||
787 | r = STA_STATS_FIELD(BW, s->bw); | 793 | r = STA_STATS_FIELD(BW, s->bw); |
788 | 794 | ||
@@ -804,6 +810,14 @@ static inline u32 sta_stats_encode_rate(struct ieee80211_rx_status *s) | |||
804 | r |= STA_STATS_FIELD(LEGACY_BAND, s->band); | 810 | r |= STA_STATS_FIELD(LEGACY_BAND, s->band); |
805 | r |= STA_STATS_FIELD(LEGACY_IDX, s->rate_idx); | 811 | r |= STA_STATS_FIELD(LEGACY_IDX, s->rate_idx); |
806 | break; | 812 | break; |
813 | case RX_ENC_HE: | ||
814 | r |= STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_HE); | ||
815 | r |= STA_STATS_FIELD(HE_NSS, s->nss); | ||
816 | r |= STA_STATS_FIELD(HE_MCS, s->rate_idx); | ||
817 | r |= STA_STATS_FIELD(HE_GI, s->he_gi); | ||
818 | r |= STA_STATS_FIELD(HE_RU, s->he_ru); | ||
819 | r |= STA_STATS_FIELD(HE_DCM, s->he_dcm); | ||
820 | break; | ||
807 | default: | 821 | default: |
808 | WARN_ON(1); | 822 | WARN_ON(1); |
809 | return STA_STATS_RATE_INVALID; | 823 | return STA_STATS_RATE_INVALID; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 80a7edf8d314..0ab69a1964f8 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -92,7 +92,7 @@ | |||
92 | STA_ENTRY \ | 92 | STA_ENTRY \ |
93 | __field(u16, tid) \ | 93 | __field(u16, tid) \ |
94 | __field(u16, ssn) \ | 94 | __field(u16, ssn) \ |
95 | __field(u8, buf_size) \ | 95 | __field(u16, buf_size) \ |
96 | __field(bool, amsdu) \ | 96 | __field(bool, amsdu) \ |
97 | __field(u16, timeout) \ | 97 | __field(u16, timeout) \ |
98 | __field(u16, action) | 98 | __field(u16, action) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 44b5dfe8727d..5b93bde248fd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -825,6 +825,8 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
825 | */ | 825 | */ |
826 | if (!ieee80211_is_data_qos(hdr->frame_control) || | 826 | if (!ieee80211_is_data_qos(hdr->frame_control) || |
827 | is_multicast_ether_addr(hdr->addr1)) { | 827 | is_multicast_ether_addr(hdr->addr1)) { |
828 | if (tx->flags & IEEE80211_TX_NO_SEQNO) | ||
829 | return TX_CONTINUE; | ||
828 | /* driver should assign sequence number */ | 830 | /* driver should assign sequence number */ |
829 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | 831 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; |
830 | /* for pure STA mode without beacons, we can do it */ | 832 | /* for pure STA mode without beacons, we can do it */ |
@@ -1854,7 +1856,7 @@ EXPORT_SYMBOL(ieee80211_tx_prepare_skb); | |||
1854 | */ | 1856 | */ |
1855 | static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | 1857 | static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, |
1856 | struct sta_info *sta, struct sk_buff *skb, | 1858 | struct sta_info *sta, struct sk_buff *skb, |
1857 | bool txpending) | 1859 | bool txpending, u32 txdata_flags) |
1858 | { | 1860 | { |
1859 | struct ieee80211_local *local = sdata->local; | 1861 | struct ieee80211_local *local = sdata->local; |
1860 | struct ieee80211_tx_data tx; | 1862 | struct ieee80211_tx_data tx; |
@@ -1872,6 +1874,8 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1872 | led_len = skb->len; | 1874 | led_len = skb->len; |
1873 | res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb); | 1875 | res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb); |
1874 | 1876 | ||
1877 | tx.flags |= txdata_flags; | ||
1878 | |||
1875 | if (unlikely(res_prepare == TX_DROP)) { | 1879 | if (unlikely(res_prepare == TX_DROP)) { |
1876 | ieee80211_free_txskb(&local->hw, skb); | 1880 | ieee80211_free_txskb(&local->hw, skb); |
1877 | return true; | 1881 | return true; |
@@ -1933,7 +1937,8 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
1933 | } | 1937 | } |
1934 | 1938 | ||
1935 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | 1939 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, |
1936 | struct sta_info *sta, struct sk_buff *skb) | 1940 | struct sta_info *sta, struct sk_buff *skb, |
1941 | u32 txdata_flags) | ||
1937 | { | 1942 | { |
1938 | struct ieee80211_local *local = sdata->local; | 1943 | struct ieee80211_local *local = sdata->local; |
1939 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1944 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -1968,7 +1973,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1968 | } | 1973 | } |
1969 | 1974 | ||
1970 | ieee80211_set_qos_hdr(sdata, skb); | 1975 | ieee80211_set_qos_hdr(sdata, skb); |
1971 | ieee80211_tx(sdata, sta, skb, false); | 1976 | ieee80211_tx(sdata, sta, skb, false, txdata_flags); |
1972 | } | 1977 | } |
1973 | 1978 | ||
1974 | static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, | 1979 | static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, |
@@ -2289,7 +2294,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
2289 | if (!ieee80211_parse_tx_radiotap(local, skb)) | 2294 | if (!ieee80211_parse_tx_radiotap(local, skb)) |
2290 | goto fail_rcu; | 2295 | goto fail_rcu; |
2291 | 2296 | ||
2292 | ieee80211_xmit(sdata, NULL, skb); | 2297 | ieee80211_xmit(sdata, NULL, skb, 0); |
2293 | rcu_read_unlock(); | 2298 | rcu_read_unlock(); |
2294 | 2299 | ||
2295 | return NETDEV_TX_OK; | 2300 | return NETDEV_TX_OK; |
@@ -3648,7 +3653,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
3648 | 3653 | ||
3649 | ieee80211_tx_stats(dev, skb->len); | 3654 | ieee80211_tx_stats(dev, skb->len); |
3650 | 3655 | ||
3651 | ieee80211_xmit(sdata, sta, skb); | 3656 | ieee80211_xmit(sdata, sta, skb, 0); |
3652 | } | 3657 | } |
3653 | goto out; | 3658 | goto out; |
3654 | out_free: | 3659 | out_free: |
@@ -3867,7 +3872,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
3867 | return true; | 3872 | return true; |
3868 | } | 3873 | } |
3869 | info->band = chanctx_conf->def.chan->band; | 3874 | info->band = chanctx_conf->def.chan->band; |
3870 | result = ieee80211_tx(sdata, NULL, skb, true); | 3875 | result = ieee80211_tx(sdata, NULL, skb, true, 0); |
3871 | } else { | 3876 | } else { |
3872 | struct sk_buff_head skbs; | 3877 | struct sk_buff_head skbs; |
3873 | 3878 | ||
@@ -4783,7 +4788,7 @@ EXPORT_SYMBOL(ieee80211_unreserve_tid); | |||
4783 | 4788 | ||
4784 | void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, | 4789 | void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, |
4785 | struct sk_buff *skb, int tid, | 4790 | struct sk_buff *skb, int tid, |
4786 | enum nl80211_band band) | 4791 | enum nl80211_band band, u32 txdata_flags) |
4787 | { | 4792 | { |
4788 | int ac = ieee80211_ac_from_tid(tid); | 4793 | int ac = ieee80211_ac_from_tid(tid); |
4789 | 4794 | ||
@@ -4800,7 +4805,7 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, | |||
4800 | */ | 4805 | */ |
4801 | local_bh_disable(); | 4806 | local_bh_disable(); |
4802 | IEEE80211_SKB_CB(skb)->band = band; | 4807 | IEEE80211_SKB_CB(skb)->band = band; |
4803 | ieee80211_xmit(sdata, NULL, skb); | 4808 | ieee80211_xmit(sdata, NULL, skb, txdata_flags); |
4804 | local_bh_enable(); | 4809 | local_bh_enable(); |
4805 | } | 4810 | } |
4806 | 4811 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5e2e511c4a6f..3e68132a41fa 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1095,6 +1095,21 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | |||
1095 | if (elen >= sizeof(*elems->max_idle_period_ie)) | 1095 | if (elen >= sizeof(*elems->max_idle_period_ie)) |
1096 | elems->max_idle_period_ie = (void *)pos; | 1096 | elems->max_idle_period_ie = (void *)pos; |
1097 | break; | 1097 | break; |
1098 | case WLAN_EID_EXTENSION: | ||
1099 | if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA && | ||
1100 | elen >= (sizeof(*elems->mu_edca_param_set) + 1)) { | ||
1101 | elems->mu_edca_param_set = (void *)&pos[1]; | ||
1102 | } else if (pos[0] == WLAN_EID_EXT_HE_CAPABILITY) { | ||
1103 | elems->he_cap = (void *)&pos[1]; | ||
1104 | elems->he_cap_len = elen - 1; | ||
1105 | } else if (pos[0] == WLAN_EID_EXT_HE_OPERATION && | ||
1106 | elen >= sizeof(*elems->he_operation) && | ||
1107 | elen >= ieee80211_he_oper_size(&pos[1])) { | ||
1108 | elems->he_operation = (void *)&pos[1]; | ||
1109 | } else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) { | ||
1110 | elems->uora_element = (void *)&pos[1]; | ||
1111 | } | ||
1112 | break; | ||
1098 | default: | 1113 | default: |
1099 | break; | 1114 | break; |
1100 | } | 1115 | } |
@@ -1353,9 +1368,10 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, | |||
1353 | enum nl80211_band band, | 1368 | enum nl80211_band band, |
1354 | u32 rate_mask, | 1369 | u32 rate_mask, |
1355 | struct cfg80211_chan_def *chandef, | 1370 | struct cfg80211_chan_def *chandef, |
1356 | size_t *offset) | 1371 | size_t *offset, u32 flags) |
1357 | { | 1372 | { |
1358 | struct ieee80211_supported_band *sband; | 1373 | struct ieee80211_supported_band *sband; |
1374 | const struct ieee80211_sta_he_cap *he_cap; | ||
1359 | u8 *pos = buffer, *end = buffer + buffer_len; | 1375 | u8 *pos = buffer, *end = buffer + buffer_len; |
1360 | size_t noffset; | 1376 | size_t noffset; |
1361 | int supp_rates_len, i; | 1377 | int supp_rates_len, i; |
@@ -1433,6 +1449,9 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, | |||
1433 | chandef->chan->center_freq); | 1449 | chandef->chan->center_freq); |
1434 | } | 1450 | } |
1435 | 1451 | ||
1452 | if (flags & IEEE80211_PROBE_FLAG_MIN_CONTENT) | ||
1453 | goto done; | ||
1454 | |||
1436 | /* insert custom IEs that go before HT */ | 1455 | /* insert custom IEs that go before HT */ |
1437 | if (ie && ie_len) { | 1456 | if (ie && ie_len) { |
1438 | static const u8 before_ht[] = { | 1457 | static const u8 before_ht[] = { |
@@ -1460,11 +1479,6 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, | |||
1460 | sband->ht_cap.cap); | 1479 | sband->ht_cap.cap); |
1461 | } | 1480 | } |
1462 | 1481 | ||
1463 | /* | ||
1464 | * If adding more here, adjust code in main.c | ||
1465 | * that calculates local->scan_ies_len. | ||
1466 | */ | ||
1467 | |||
1468 | /* insert custom IEs that go before VHT */ | 1482 | /* insert custom IEs that go before VHT */ |
1469 | if (ie && ie_len) { | 1483 | if (ie && ie_len) { |
1470 | static const u8 before_vht[] = { | 1484 | static const u8 before_vht[] = { |
@@ -1507,9 +1521,43 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, | |||
1507 | sband->vht_cap.cap); | 1521 | sband->vht_cap.cap); |
1508 | } | 1522 | } |
1509 | 1523 | ||
1524 | /* insert custom IEs that go before HE */ | ||
1525 | if (ie && ie_len) { | ||
1526 | static const u8 before_he[] = { | ||
1527 | /* | ||
1528 | * no need to list the ones split off before VHT | ||
1529 | * or generated here | ||
1530 | */ | ||
1531 | WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_REQ_PARAMS, | ||
1532 | WLAN_EID_AP_CSN, | ||
1533 | /* TODO: add 11ah/11aj/11ak elements */ | ||
1534 | }; | ||
1535 | noffset = ieee80211_ie_split(ie, ie_len, | ||
1536 | before_he, ARRAY_SIZE(before_he), | ||
1537 | *offset); | ||
1538 | if (end - pos < noffset - *offset) | ||
1539 | goto out_err; | ||
1540 | memcpy(pos, ie + *offset, noffset - *offset); | ||
1541 | pos += noffset - *offset; | ||
1542 | *offset = noffset; | ||
1543 | } | ||
1544 | |||
1545 | he_cap = ieee80211_get_he_sta_cap(sband); | ||
1546 | if (he_cap) { | ||
1547 | pos = ieee80211_ie_build_he_cap(pos, he_cap, end); | ||
1548 | if (!pos) | ||
1549 | goto out_err; | ||
1550 | } | ||
1551 | |||
1552 | /* | ||
1553 | * If adding more here, adjust code in main.c | ||
1554 | * that calculates local->scan_ies_len. | ||
1555 | */ | ||
1556 | |||
1510 | return pos - buffer; | 1557 | return pos - buffer; |
1511 | out_err: | 1558 | out_err: |
1512 | WARN_ONCE(1, "not enough space for preq IEs\n"); | 1559 | WARN_ONCE(1, "not enough space for preq IEs\n"); |
1560 | done: | ||
1513 | return pos - buffer; | 1561 | return pos - buffer; |
1514 | } | 1562 | } |
1515 | 1563 | ||
@@ -1518,7 +1566,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1518 | struct ieee80211_scan_ies *ie_desc, | 1566 | struct ieee80211_scan_ies *ie_desc, |
1519 | const u8 *ie, size_t ie_len, | 1567 | const u8 *ie, size_t ie_len, |
1520 | u8 bands_used, u32 *rate_masks, | 1568 | u8 bands_used, u32 *rate_masks, |
1521 | struct cfg80211_chan_def *chandef) | 1569 | struct cfg80211_chan_def *chandef, |
1570 | u32 flags) | ||
1522 | { | 1571 | { |
1523 | size_t pos = 0, old_pos = 0, custom_ie_offset = 0; | 1572 | size_t pos = 0, old_pos = 0, custom_ie_offset = 0; |
1524 | int i; | 1573 | int i; |
@@ -1533,7 +1582,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1533 | ie, ie_len, i, | 1582 | ie, ie_len, i, |
1534 | rate_masks[i], | 1583 | rate_masks[i], |
1535 | chandef, | 1584 | chandef, |
1536 | &custom_ie_offset); | 1585 | &custom_ie_offset, |
1586 | flags); | ||
1537 | ie_desc->ies[i] = buffer + old_pos; | 1587 | ie_desc->ies[i] = buffer + old_pos; |
1538 | ie_desc->len[i] = pos - old_pos; | 1588 | ie_desc->len[i] = pos - old_pos; |
1539 | old_pos = pos; | 1589 | old_pos = pos; |
@@ -1561,7 +1611,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1561 | struct ieee80211_channel *chan, | 1611 | struct ieee80211_channel *chan, |
1562 | const u8 *ssid, size_t ssid_len, | 1612 | const u8 *ssid, size_t ssid_len, |
1563 | const u8 *ie, size_t ie_len, | 1613 | const u8 *ie, size_t ie_len, |
1564 | bool directed) | 1614 | u32 flags) |
1565 | { | 1615 | { |
1566 | struct ieee80211_local *local = sdata->local; | 1616 | struct ieee80211_local *local = sdata->local; |
1567 | struct cfg80211_chan_def chandef; | 1617 | struct cfg80211_chan_def chandef; |
@@ -1577,7 +1627,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1577 | * badly-behaved APs don't respond when this parameter is included. | 1627 | * badly-behaved APs don't respond when this parameter is included. |
1578 | */ | 1628 | */ |
1579 | chandef.width = sdata->vif.bss_conf.chandef.width; | 1629 | chandef.width = sdata->vif.bss_conf.chandef.width; |
1580 | if (directed) | 1630 | if (flags & IEEE80211_PROBE_FLAG_DIRECTED) |
1581 | chandef.chan = NULL; | 1631 | chandef.chan = NULL; |
1582 | else | 1632 | else |
1583 | chandef.chan = chan; | 1633 | chandef.chan = chan; |
@@ -1591,7 +1641,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1591 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), | 1641 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), |
1592 | skb_tailroom(skb), &dummy_ie_desc, | 1642 | skb_tailroom(skb), &dummy_ie_desc, |
1593 | ie, ie_len, BIT(chan->band), | 1643 | ie, ie_len, BIT(chan->band), |
1594 | rate_masks, &chandef); | 1644 | rate_masks, &chandef, flags); |
1595 | skb_put(skb, ies_len); | 1645 | skb_put(skb, ies_len); |
1596 | 1646 | ||
1597 | if (dst) { | 1647 | if (dst) { |
@@ -1605,27 +1655,6 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1605 | return skb; | 1655 | return skb; |
1606 | } | 1656 | } |
1607 | 1657 | ||
1608 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, | ||
1609 | const u8 *src, const u8 *dst, | ||
1610 | const u8 *ssid, size_t ssid_len, | ||
1611 | const u8 *ie, size_t ie_len, | ||
1612 | u32 ratemask, bool directed, u32 tx_flags, | ||
1613 | struct ieee80211_channel *channel, bool scan) | ||
1614 | { | ||
1615 | struct sk_buff *skb; | ||
1616 | |||
1617 | skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel, | ||
1618 | ssid, ssid_len, | ||
1619 | ie, ie_len, directed); | ||
1620 | if (skb) { | ||
1621 | IEEE80211_SKB_CB(skb)->flags |= tx_flags; | ||
1622 | if (scan) | ||
1623 | ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band); | ||
1624 | else | ||
1625 | ieee80211_tx_skb(sdata, skb); | ||
1626 | } | ||
1627 | } | ||
1628 | |||
1629 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | 1658 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, |
1630 | struct ieee802_11_elems *elems, | 1659 | struct ieee802_11_elems *elems, |
1631 | enum nl80211_band band, u32 *basic_rates) | 1660 | enum nl80211_band band, u32 *basic_rates) |
@@ -2412,6 +2441,72 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | |||
2412 | return pos; | 2441 | return pos; |
2413 | } | 2442 | } |
2414 | 2443 | ||
2444 | u8 *ieee80211_ie_build_he_cap(u8 *pos, | ||
2445 | const struct ieee80211_sta_he_cap *he_cap, | ||
2446 | u8 *end) | ||
2447 | { | ||
2448 | u8 n; | ||
2449 | u8 ie_len; | ||
2450 | u8 *orig_pos = pos; | ||
2451 | |||
2452 | /* Make sure we have place for the IE */ | ||
2453 | /* | ||
2454 | * TODO: the 1 added is because this temporarily is under the EXTENSION | ||
2455 | * IE. Get rid of it when it moves. | ||
2456 | */ | ||
2457 | if (!he_cap) | ||
2458 | return orig_pos; | ||
2459 | |||
2460 | n = ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem); | ||
2461 | ie_len = 2 + 1 + | ||
2462 | sizeof(he_cap->he_cap_elem) + n + | ||
2463 | ieee80211_he_ppe_size(he_cap->ppe_thres[0], | ||
2464 | he_cap->he_cap_elem.phy_cap_info); | ||
2465 | |||
2466 | if ((end - pos) < ie_len) | ||
2467 | return orig_pos; | ||
2468 | |||
2469 | *pos++ = WLAN_EID_EXTENSION; | ||
2470 | pos++; /* We'll set the size later below */ | ||
2471 | *pos++ = WLAN_EID_EXT_HE_CAPABILITY; | ||
2472 | |||
2473 | /* Fixed data */ | ||
2474 | memcpy(pos, &he_cap->he_cap_elem, sizeof(he_cap->he_cap_elem)); | ||
2475 | pos += sizeof(he_cap->he_cap_elem); | ||
2476 | |||
2477 | memcpy(pos, &he_cap->he_mcs_nss_supp, n); | ||
2478 | pos += n; | ||
2479 | |||
2480 | /* Check if PPE Threshold should be present */ | ||
2481 | if ((he_cap->he_cap_elem.phy_cap_info[6] & | ||
2482 | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0) | ||
2483 | goto end; | ||
2484 | |||
2485 | /* | ||
2486 | * Calculate how many PPET16/PPET8 pairs are to come. Algorithm: | ||
2487 | * (NSS_M1 + 1) x (num of 1 bits in RU_INDEX_BITMASK) | ||
2488 | */ | ||
2489 | n = hweight8(he_cap->ppe_thres[0] & | ||
2490 | IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK); | ||
2491 | n *= (1 + ((he_cap->ppe_thres[0] & IEEE80211_PPE_THRES_NSS_MASK) >> | ||
2492 | IEEE80211_PPE_THRES_NSS_POS)); | ||
2493 | |||
2494 | /* | ||
2495 | * Each pair is 6 bits, and we need to add the 7 "header" bits to the | ||
2496 | * total size. | ||
2497 | */ | ||
2498 | n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7; | ||
2499 | n = DIV_ROUND_UP(n, 8); | ||
2500 | |||
2501 | /* Copy PPE Thresholds */ | ||
2502 | memcpy(pos, &he_cap->ppe_thres, n); | ||
2503 | pos += n; | ||
2504 | |||
2505 | end: | ||
2506 | orig_pos[1] = (pos - orig_pos) - 2; | ||
2507 | return pos; | ||
2508 | } | ||
2509 | |||
2415 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 2510 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
2416 | const struct cfg80211_chan_def *chandef, | 2511 | const struct cfg80211_chan_def *chandef, |
2417 | u16 prot_mode, bool rifs_mode) | 2512 | u16 prot_mode, bool rifs_mode) |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 48e8097339ab..a88551f3bc43 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
5 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 5 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
6 | * Copyright 2015 Intel Deutschland GmbH | 6 | * Copyright 2015-2017 Intel Deutschland GmbH |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
@@ -744,6 +744,8 @@ int wiphy_register(struct wiphy *wiphy) | |||
744 | 744 | ||
745 | /* sanity check supported bands/channels */ | 745 | /* sanity check supported bands/channels */ |
746 | for (band = 0; band < NUM_NL80211_BANDS; band++) { | 746 | for (band = 0; band < NUM_NL80211_BANDS; band++) { |
747 | u16 types = 0; | ||
748 | |||
747 | sband = wiphy->bands[band]; | 749 | sband = wiphy->bands[band]; |
748 | if (!sband) | 750 | if (!sband) |
749 | continue; | 751 | continue; |
@@ -788,6 +790,23 @@ int wiphy_register(struct wiphy *wiphy) | |||
788 | sband->channels[i].band = band; | 790 | sband->channels[i].band = band; |
789 | } | 791 | } |
790 | 792 | ||
793 | for (i = 0; i < sband->n_iftype_data; i++) { | ||
794 | const struct ieee80211_sband_iftype_data *iftd; | ||
795 | |||
796 | iftd = &sband->iftype_data[i]; | ||
797 | |||
798 | if (WARN_ON(!iftd->types_mask)) | ||
799 | return -EINVAL; | ||
800 | if (WARN_ON(types & iftd->types_mask)) | ||
801 | return -EINVAL; | ||
802 | |||
803 | /* at least one piece of information must be present */ | ||
804 | if (WARN_ON(!iftd->he_cap.has_he)) | ||
805 | return -EINVAL; | ||
806 | |||
807 | types |= iftd->types_mask; | ||
808 | } | ||
809 | |||
791 | have_band = true; | 810 | have_band = true; |
792 | } | 811 | } |
793 | 812 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index 63eb1b5fdd04..7f52ef569320 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -76,7 +76,7 @@ struct cfg80211_registered_device { | |||
76 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ | 76 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ |
77 | struct sk_buff *scan_msg; | 77 | struct sk_buff *scan_msg; |
78 | struct list_head sched_scan_req_list; | 78 | struct list_head sched_scan_req_list; |
79 | unsigned long suspend_at; | 79 | time64_t suspend_at; |
80 | struct work_struct scan_done_wk; | 80 | struct work_struct scan_done_wk; |
81 | 81 | ||
82 | struct genl_info *cur_cmd_info; | 82 | struct genl_info *cur_cmd_info; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c7bbe5f0aae8..8db59129c095 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -428,6 +428,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | |||
428 | [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 }, | 428 | [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 }, |
429 | [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 }, | 429 | [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 }, |
430 | [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 }, | 430 | [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 }, |
431 | [NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY, | ||
432 | .len = NL80211_HE_MAX_CAPABILITY_LEN }, | ||
431 | }; | 433 | }; |
432 | 434 | ||
433 | /* policy for the key attributes */ | 435 | /* policy for the key attributes */ |
@@ -1324,6 +1326,34 @@ static int nl80211_send_coalesce(struct sk_buff *msg, | |||
1324 | return 0; | 1326 | return 0; |
1325 | } | 1327 | } |
1326 | 1328 | ||
1329 | static int | ||
1330 | nl80211_send_iftype_data(struct sk_buff *msg, | ||
1331 | const struct ieee80211_sband_iftype_data *iftdata) | ||
1332 | { | ||
1333 | const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap; | ||
1334 | |||
1335 | if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES, | ||
1336 | iftdata->types_mask)) | ||
1337 | return -ENOBUFS; | ||
1338 | |||
1339 | if (he_cap->has_he) { | ||
1340 | if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, | ||
1341 | sizeof(he_cap->he_cap_elem.mac_cap_info), | ||
1342 | he_cap->he_cap_elem.mac_cap_info) || | ||
1343 | nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, | ||
1344 | sizeof(he_cap->he_cap_elem.phy_cap_info), | ||
1345 | he_cap->he_cap_elem.phy_cap_info) || | ||
1346 | nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, | ||
1347 | sizeof(he_cap->he_mcs_nss_supp), | ||
1348 | &he_cap->he_mcs_nss_supp) || | ||
1349 | nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, | ||
1350 | sizeof(he_cap->ppe_thres), he_cap->ppe_thres)) | ||
1351 | return -ENOBUFS; | ||
1352 | } | ||
1353 | |||
1354 | return 0; | ||
1355 | } | ||
1356 | |||
1327 | static int nl80211_send_band_rateinfo(struct sk_buff *msg, | 1357 | static int nl80211_send_band_rateinfo(struct sk_buff *msg, |
1328 | struct ieee80211_supported_band *sband) | 1358 | struct ieee80211_supported_band *sband) |
1329 | { | 1359 | { |
@@ -1353,6 +1383,32 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg, | |||
1353 | sband->vht_cap.cap))) | 1383 | sband->vht_cap.cap))) |
1354 | return -ENOBUFS; | 1384 | return -ENOBUFS; |
1355 | 1385 | ||
1386 | if (sband->n_iftype_data) { | ||
1387 | struct nlattr *nl_iftype_data = | ||
1388 | nla_nest_start(msg, NL80211_BAND_ATTR_IFTYPE_DATA); | ||
1389 | int err; | ||
1390 | |||
1391 | if (!nl_iftype_data) | ||
1392 | return -ENOBUFS; | ||
1393 | |||
1394 | for (i = 0; i < sband->n_iftype_data; i++) { | ||
1395 | struct nlattr *iftdata; | ||
1396 | |||
1397 | iftdata = nla_nest_start(msg, i + 1); | ||
1398 | if (!iftdata) | ||
1399 | return -ENOBUFS; | ||
1400 | |||
1401 | err = nl80211_send_iftype_data(msg, | ||
1402 | &sband->iftype_data[i]); | ||
1403 | if (err) | ||
1404 | return err; | ||
1405 | |||
1406 | nla_nest_end(msg, iftdata); | ||
1407 | } | ||
1408 | |||
1409 | nla_nest_end(msg, nl_iftype_data); | ||
1410 | } | ||
1411 | |||
1356 | /* add bitrates */ | 1412 | /* add bitrates */ |
1357 | nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); | 1413 | nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); |
1358 | if (!nl_rates) | 1414 | if (!nl_rates) |
@@ -2757,7 +2813,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
2757 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) || | 2813 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) || |
2758 | nla_put_u32(msg, NL80211_ATTR_GENERATION, | 2814 | nla_put_u32(msg, NL80211_ATTR_GENERATION, |
2759 | rdev->devlist_generation ^ | 2815 | rdev->devlist_generation ^ |
2760 | (cfg80211_rdev_list_generation << 2))) | 2816 | (cfg80211_rdev_list_generation << 2)) || |
2817 | nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr)) | ||
2761 | goto nla_put_failure; | 2818 | goto nla_put_failure; |
2762 | 2819 | ||
2763 | if (rdev->ops->get_channel) { | 2820 | if (rdev->ops->get_channel) { |
@@ -4471,6 +4528,9 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
4471 | case RATE_INFO_BW_160: | 4528 | case RATE_INFO_BW_160: |
4472 | rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH; | 4529 | rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH; |
4473 | break; | 4530 | break; |
4531 | case RATE_INFO_BW_HE_RU: | ||
4532 | rate_flg = 0; | ||
4533 | WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS)); | ||
4474 | } | 4534 | } |
4475 | 4535 | ||
4476 | if (rate_flg && nla_put_flag(msg, rate_flg)) | 4536 | if (rate_flg && nla_put_flag(msg, rate_flg)) |
@@ -4490,6 +4550,19 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
4490 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && | 4550 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && |
4491 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) | 4551 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) |
4492 | return false; | 4552 | return false; |
4553 | } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) { | ||
4554 | if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs)) | ||
4555 | return false; | ||
4556 | if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss)) | ||
4557 | return false; | ||
4558 | if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi)) | ||
4559 | return false; | ||
4560 | if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm)) | ||
4561 | return false; | ||
4562 | if (info->bw == RATE_INFO_BW_HE_RU && | ||
4563 | nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC, | ||
4564 | info->he_ru_alloc)) | ||
4565 | return false; | ||
4493 | } | 4566 | } |
4494 | 4567 | ||
4495 | nla_nest_end(msg, rate); | 4568 | nla_nest_end(msg, rate); |
@@ -4546,13 +4619,13 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, | |||
4546 | 4619 | ||
4547 | #define PUT_SINFO(attr, memb, type) do { \ | 4620 | #define PUT_SINFO(attr, memb, type) do { \ |
4548 | BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \ | 4621 | BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \ |
4549 | if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \ | 4622 | if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \ |
4550 | nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \ | 4623 | nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \ |
4551 | sinfo->memb)) \ | 4624 | sinfo->memb)) \ |
4552 | goto nla_put_failure; \ | 4625 | goto nla_put_failure; \ |
4553 | } while (0) | 4626 | } while (0) |
4554 | #define PUT_SINFO_U64(attr, memb) do { \ | 4627 | #define PUT_SINFO_U64(attr, memb) do { \ |
4555 | if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \ | 4628 | if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \ |
4556 | nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \ | 4629 | nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \ |
4557 | sinfo->memb, NL80211_STA_INFO_PAD)) \ | 4630 | sinfo->memb, NL80211_STA_INFO_PAD)) \ |
4558 | goto nla_put_failure; \ | 4631 | goto nla_put_failure; \ |
@@ -4561,14 +4634,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, | |||
4561 | PUT_SINFO(CONNECTED_TIME, connected_time, u32); | 4634 | PUT_SINFO(CONNECTED_TIME, connected_time, u32); |
4562 | PUT_SINFO(INACTIVE_TIME, inactive_time, u32); | 4635 | PUT_SINFO(INACTIVE_TIME, inactive_time, u32); |
4563 | 4636 | ||
4564 | if (sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES) | | 4637 | if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) | |
4565 | BIT(NL80211_STA_INFO_RX_BYTES64)) && | 4638 | BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) && |
4566 | nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES, | 4639 | nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES, |
4567 | (u32)sinfo->rx_bytes)) | 4640 | (u32)sinfo->rx_bytes)) |
4568 | goto nla_put_failure; | 4641 | goto nla_put_failure; |
4569 | 4642 | ||
4570 | if (sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES) | | 4643 | if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) | |
4571 | BIT(NL80211_STA_INFO_TX_BYTES64)) && | 4644 | BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) && |
4572 | nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, | 4645 | nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, |
4573 | (u32)sinfo->tx_bytes)) | 4646 | (u32)sinfo->tx_bytes)) |
4574 | goto nla_put_failure; | 4647 | goto nla_put_failure; |
@@ -4588,24 +4661,24 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, | |||
4588 | default: | 4661 | default: |
4589 | break; | 4662 | break; |
4590 | } | 4663 | } |
4591 | if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL)) { | 4664 | if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) { |
4592 | if (!nl80211_put_signal(msg, sinfo->chains, | 4665 | if (!nl80211_put_signal(msg, sinfo->chains, |
4593 | sinfo->chain_signal, | 4666 | sinfo->chain_signal, |
4594 | NL80211_STA_INFO_CHAIN_SIGNAL)) | 4667 | NL80211_STA_INFO_CHAIN_SIGNAL)) |
4595 | goto nla_put_failure; | 4668 | goto nla_put_failure; |
4596 | } | 4669 | } |
4597 | if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) { | 4670 | if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) { |
4598 | if (!nl80211_put_signal(msg, sinfo->chains, | 4671 | if (!nl80211_put_signal(msg, sinfo->chains, |
4599 | sinfo->chain_signal_avg, | 4672 | sinfo->chain_signal_avg, |
4600 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) | 4673 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) |
4601 | goto nla_put_failure; | 4674 | goto nla_put_failure; |
4602 | } | 4675 | } |
4603 | if (sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE)) { | 4676 | if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) { |
4604 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, | 4677 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, |
4605 | NL80211_STA_INFO_TX_BITRATE)) | 4678 | NL80211_STA_INFO_TX_BITRATE)) |
4606 | goto nla_put_failure; | 4679 | goto nla_put_failure; |
4607 | } | 4680 | } |
4608 | if (sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE)) { | 4681 | if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) { |
4609 | if (!nl80211_put_sta_rate(msg, &sinfo->rxrate, | 4682 | if (!nl80211_put_sta_rate(msg, &sinfo->rxrate, |
4610 | NL80211_STA_INFO_RX_BITRATE)) | 4683 | NL80211_STA_INFO_RX_BITRATE)) |
4611 | goto nla_put_failure; | 4684 | goto nla_put_failure; |
@@ -4621,7 +4694,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, | |||
4621 | PUT_SINFO(PEER_PM, peer_pm, u32); | 4694 | PUT_SINFO(PEER_PM, peer_pm, u32); |
4622 | PUT_SINFO(NONPEER_PM, nonpeer_pm, u32); | 4695 | PUT_SINFO(NONPEER_PM, nonpeer_pm, u32); |
4623 | 4696 | ||
4624 | if (sinfo->filled & BIT(NL80211_STA_INFO_BSS_PARAM)) { | 4697 | if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) { |
4625 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); | 4698 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); |
4626 | if (!bss_param) | 4699 | if (!bss_param) |
4627 | goto nla_put_failure; | 4700 | goto nla_put_failure; |
@@ -4640,7 +4713,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, | |||
4640 | 4713 | ||
4641 | nla_nest_end(msg, bss_param); | 4714 | nla_nest_end(msg, bss_param); |
4642 | } | 4715 | } |
4643 | if ((sinfo->filled & BIT(NL80211_STA_INFO_STA_FLAGS)) && | 4716 | if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) && |
4644 | nla_put(msg, NL80211_STA_INFO_STA_FLAGS, | 4717 | nla_put(msg, NL80211_STA_INFO_STA_FLAGS, |
4645 | sizeof(struct nl80211_sta_flag_update), | 4718 | sizeof(struct nl80211_sta_flag_update), |
4646 | &sinfo->sta_flags)) | 4719 | &sinfo->sta_flags)) |
@@ -4886,7 +4959,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy, | |||
4886 | return -EINVAL; | 4959 | return -EINVAL; |
4887 | if (params->supported_rates) | 4960 | if (params->supported_rates) |
4888 | return -EINVAL; | 4961 | return -EINVAL; |
4889 | if (params->ext_capab || params->ht_capa || params->vht_capa) | 4962 | if (params->ext_capab || params->ht_capa || params->vht_capa || |
4963 | params->he_capa) | ||
4890 | return -EINVAL; | 4964 | return -EINVAL; |
4891 | } | 4965 | } |
4892 | 4966 | ||
@@ -5092,6 +5166,15 @@ static int nl80211_set_station_tdls(struct genl_info *info, | |||
5092 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | 5166 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) |
5093 | params->vht_capa = | 5167 | params->vht_capa = |
5094 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | 5168 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); |
5169 | if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) { | ||
5170 | params->he_capa = | ||
5171 | nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]); | ||
5172 | params->he_capa_len = | ||
5173 | nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]); | ||
5174 | |||
5175 | if (params->he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN) | ||
5176 | return -EINVAL; | ||
5177 | } | ||
5095 | 5178 | ||
5096 | err = nl80211_parse_sta_channel_info(info, params); | 5179 | err = nl80211_parse_sta_channel_info(info, params); |
5097 | if (err) | 5180 | if (err) |
@@ -5319,6 +5402,17 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
5319 | params.vht_capa = | 5402 | params.vht_capa = |
5320 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | 5403 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); |
5321 | 5404 | ||
5405 | if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) { | ||
5406 | params.he_capa = | ||
5407 | nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]); | ||
5408 | params.he_capa_len = | ||
5409 | nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]); | ||
5410 | |||
5411 | /* max len is validated in nla policy */ | ||
5412 | if (params.he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN) | ||
5413 | return -EINVAL; | ||
5414 | } | ||
5415 | |||
5322 | if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) { | 5416 | if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) { |
5323 | params.opmode_notif_used = true; | 5417 | params.opmode_notif_used = true; |
5324 | params.opmode_notif = | 5418 | params.opmode_notif = |
@@ -5351,6 +5445,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
5351 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) { | 5445 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) { |
5352 | params.ht_capa = NULL; | 5446 | params.ht_capa = NULL; |
5353 | params.vht_capa = NULL; | 5447 | params.vht_capa = NULL; |
5448 | |||
5449 | /* HE requires WME */ | ||
5450 | if (params.he_capa_len) | ||
5451 | return -EINVAL; | ||
5354 | } | 5452 | } |
5355 | 5453 | ||
5356 | /* When you run into this, adjust the code below for the new flag */ | 5454 | /* When you run into this, adjust the code below for the new flag */ |
@@ -6861,6 +6959,16 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev) | |||
6861 | return regulatory_pre_cac_allowed(wdev->wiphy); | 6959 | return regulatory_pre_cac_allowed(wdev->wiphy); |
6862 | } | 6960 | } |
6863 | 6961 | ||
6962 | static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag, | ||
6963 | enum nl80211_ext_feature_index feat) | ||
6964 | { | ||
6965 | if (!(flags & flag)) | ||
6966 | return true; | ||
6967 | if (wiphy_ext_feature_isset(wiphy, feat)) | ||
6968 | return true; | ||
6969 | return false; | ||
6970 | } | ||
6971 | |||
6864 | static int | 6972 | static int |
6865 | nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev, | 6973 | nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev, |
6866 | void *request, struct nlattr **attrs, | 6974 | void *request, struct nlattr **attrs, |
@@ -6895,15 +7003,33 @@ nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
6895 | 7003 | ||
6896 | if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | 7004 | if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && |
6897 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) || | 7005 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) || |
6898 | ((*flags & NL80211_SCAN_FLAG_LOW_SPAN) && | 7006 | !nl80211_check_scan_feat(wiphy, *flags, |
6899 | !wiphy_ext_feature_isset(wiphy, | 7007 | NL80211_SCAN_FLAG_LOW_SPAN, |
6900 | NL80211_EXT_FEATURE_LOW_SPAN_SCAN)) || | 7008 | NL80211_EXT_FEATURE_LOW_SPAN_SCAN) || |
6901 | ((*flags & NL80211_SCAN_FLAG_LOW_POWER) && | 7009 | !nl80211_check_scan_feat(wiphy, *flags, |
6902 | !wiphy_ext_feature_isset(wiphy, | 7010 | NL80211_SCAN_FLAG_LOW_POWER, |
6903 | NL80211_EXT_FEATURE_LOW_POWER_SCAN)) || | 7011 | NL80211_EXT_FEATURE_LOW_POWER_SCAN) || |
6904 | ((*flags & NL80211_SCAN_FLAG_HIGH_ACCURACY) && | 7012 | !nl80211_check_scan_feat(wiphy, *flags, |
6905 | !wiphy_ext_feature_isset(wiphy, | 7013 | NL80211_SCAN_FLAG_HIGH_ACCURACY, |
6906 | NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN))) | 7014 | NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) || |
7015 | !nl80211_check_scan_feat(wiphy, *flags, | ||
7016 | NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME, | ||
7017 | NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) || | ||
7018 | !nl80211_check_scan_feat(wiphy, *flags, | ||
7019 | NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP, | ||
7020 | NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) || | ||
7021 | !nl80211_check_scan_feat(wiphy, *flags, | ||
7022 | NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION, | ||
7023 | NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) || | ||
7024 | !nl80211_check_scan_feat(wiphy, *flags, | ||
7025 | NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE, | ||
7026 | NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) || | ||
7027 | !nl80211_check_scan_feat(wiphy, *flags, | ||
7028 | NL80211_SCAN_FLAG_RANDOM_SN, | ||
7029 | NL80211_EXT_FEATURE_SCAN_RANDOM_SN) || | ||
7030 | !nl80211_check_scan_feat(wiphy, *flags, | ||
7031 | NL80211_SCAN_FLAG_MIN_PREQ_CONTENT, | ||
7032 | NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT)) | ||
6907 | return -EOPNOTSUPP; | 7033 | return -EOPNOTSUPP; |
6908 | 7034 | ||
6909 | if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { | 7035 | if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { |
@@ -6918,26 +7044,6 @@ nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
6918 | return err; | 7044 | return err; |
6919 | } | 7045 | } |
6920 | 7046 | ||
6921 | if ((*flags & NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME) && | ||
6922 | !wiphy_ext_feature_isset(wiphy, | ||
6923 | NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME)) | ||
6924 | return -EOPNOTSUPP; | ||
6925 | |||
6926 | if ((*flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP) && | ||
6927 | !wiphy_ext_feature_isset(wiphy, | ||
6928 | NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP)) | ||
6929 | return -EOPNOTSUPP; | ||
6930 | |||
6931 | if ((*flags & NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) && | ||
6932 | !wiphy_ext_feature_isset(wiphy, | ||
6933 | NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION)) | ||
6934 | return -EOPNOTSUPP; | ||
6935 | |||
6936 | if ((*flags & NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE) && | ||
6937 | !wiphy_ext_feature_isset(wiphy, | ||
6938 | NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE)) | ||
6939 | return -EOPNOTSUPP; | ||
6940 | |||
6941 | return 0; | 7047 | return 0; |
6942 | } | 7048 | } |
6943 | 7049 | ||
@@ -10160,7 +10266,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, | |||
10160 | if (err) | 10266 | if (err) |
10161 | return err; | 10267 | return err; |
10162 | 10268 | ||
10163 | if (sinfo.filled & BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) | 10269 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) |
10164 | wdev->cqm_config->last_rssi_event_value = | 10270 | wdev->cqm_config->last_rssi_event_value = |
10165 | (s8) sinfo.rx_beacon_signal_avg; | 10271 | (s8) sinfo.rx_beacon_signal_avg; |
10166 | } | 10272 | } |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 570a2b67ca10..6ab32f6a1961 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -102,7 +102,7 @@ static int wiphy_suspend(struct device *dev) | |||
102 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); | 102 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); |
103 | int ret = 0; | 103 | int ret = 0; |
104 | 104 | ||
105 | rdev->suspend_at = get_seconds(); | 105 | rdev->suspend_at = ktime_get_boottime_seconds(); |
106 | 106 | ||
107 | rtnl_lock(); | 107 | rtnl_lock(); |
108 | if (rdev->wiphy.registered) { | 108 | if (rdev->wiphy.registered) { |
@@ -130,7 +130,7 @@ static int wiphy_resume(struct device *dev) | |||
130 | int ret = 0; | 130 | int ret = 0; |
131 | 131 | ||
132 | /* Age scan results with time spent in suspend */ | 132 | /* Age scan results with time spent in suspend */ |
133 | cfg80211_bss_age(rdev, get_seconds() - rdev->suspend_at); | 133 | cfg80211_bss_age(rdev, ktime_get_boottime_seconds() - rdev->suspend_at); |
134 | 134 | ||
135 | rtnl_lock(); | 135 | rtnl_lock(); |
136 | if (rdev->wiphy.registered && rdev->ops->resume) | 136 | if (rdev->wiphy.registered && rdev->ops->resume) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 3c654cd7ba56..e0825a019e9f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net> |
6 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 6 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
7 | * Copyright 2017 Intel Deutschland GmbH | ||
7 | */ | 8 | */ |
8 | #include <linux/export.h> | 9 | #include <linux/export.h> |
9 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
@@ -1142,6 +1143,85 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) | |||
1142 | return 0; | 1143 | return 0; |
1143 | } | 1144 | } |
1144 | 1145 | ||
1146 | static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate) | ||
1147 | { | ||
1148 | #define SCALE 2048 | ||
1149 | u16 mcs_divisors[12] = { | ||
1150 | 34133, /* 16.666666... */ | ||
1151 | 17067, /* 8.333333... */ | ||
1152 | 11378, /* 5.555555... */ | ||
1153 | 8533, /* 4.166666... */ | ||
1154 | 5689, /* 2.777777... */ | ||
1155 | 4267, /* 2.083333... */ | ||
1156 | 3923, /* 1.851851... */ | ||
1157 | 3413, /* 1.666666... */ | ||
1158 | 2844, /* 1.388888... */ | ||
1159 | 2560, /* 1.250000... */ | ||
1160 | 2276, /* 1.111111... */ | ||
1161 | 2048, /* 1.000000... */ | ||
1162 | }; | ||
1163 | u32 rates_160M[3] = { 960777777, 907400000, 816666666 }; | ||
1164 | u32 rates_969[3] = { 480388888, 453700000, 408333333 }; | ||
1165 | u32 rates_484[3] = { 229411111, 216666666, 195000000 }; | ||
1166 | u32 rates_242[3] = { 114711111, 108333333, 97500000 }; | ||
1167 | u32 rates_106[3] = { 40000000, 37777777, 34000000 }; | ||
1168 | u32 rates_52[3] = { 18820000, 17777777, 16000000 }; | ||
1169 | u32 rates_26[3] = { 9411111, 8888888, 8000000 }; | ||
1170 | u64 tmp; | ||
1171 | u32 result; | ||
1172 | |||
1173 | if (WARN_ON_ONCE(rate->mcs > 11)) | ||
1174 | return 0; | ||
1175 | |||
1176 | if (WARN_ON_ONCE(rate->he_gi > NL80211_RATE_INFO_HE_GI_3_2)) | ||
1177 | return 0; | ||
1178 | if (WARN_ON_ONCE(rate->he_ru_alloc > | ||
1179 | NL80211_RATE_INFO_HE_RU_ALLOC_2x996)) | ||
1180 | return 0; | ||
1181 | if (WARN_ON_ONCE(rate->nss < 1 || rate->nss > 8)) | ||
1182 | return 0; | ||
1183 | |||
1184 | if (rate->bw == RATE_INFO_BW_160) | ||
1185 | result = rates_160M[rate->he_gi]; | ||
1186 | else if (rate->bw == RATE_INFO_BW_80 || | ||
1187 | (rate->bw == RATE_INFO_BW_HE_RU && | ||
1188 | rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_996)) | ||
1189 | result = rates_969[rate->he_gi]; | ||
1190 | else if (rate->bw == RATE_INFO_BW_40 || | ||
1191 | (rate->bw == RATE_INFO_BW_HE_RU && | ||
1192 | rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_484)) | ||
1193 | result = rates_484[rate->he_gi]; | ||
1194 | else if (rate->bw == RATE_INFO_BW_20 || | ||
1195 | (rate->bw == RATE_INFO_BW_HE_RU && | ||
1196 | rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_242)) | ||
1197 | result = rates_242[rate->he_gi]; | ||
1198 | else if (rate->bw == RATE_INFO_BW_HE_RU && | ||
1199 | rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_106) | ||
1200 | result = rates_106[rate->he_gi]; | ||
1201 | else if (rate->bw == RATE_INFO_BW_HE_RU && | ||
1202 | rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_52) | ||
1203 | result = rates_52[rate->he_gi]; | ||
1204 | else if (rate->bw == RATE_INFO_BW_HE_RU && | ||
1205 | rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_26) | ||
1206 | result = rates_26[rate->he_gi]; | ||
1207 | else if (WARN(1, "invalid HE MCS: bw:%d, ru:%d\n", | ||
1208 | rate->bw, rate->he_ru_alloc)) | ||
1209 | return 0; | ||
1210 | |||
1211 | /* now scale to the appropriate MCS */ | ||
1212 | tmp = result; | ||
1213 | tmp *= SCALE; | ||
1214 | do_div(tmp, mcs_divisors[rate->mcs]); | ||
1215 | result = tmp; | ||
1216 | |||
1217 | /* and take NSS, DCM into account */ | ||
1218 | result = (result * rate->nss) / 8; | ||
1219 | if (rate->he_dcm) | ||
1220 | result /= 2; | ||
1221 | |||
1222 | return result; | ||
1223 | } | ||
1224 | |||
1145 | u32 cfg80211_calculate_bitrate(struct rate_info *rate) | 1225 | u32 cfg80211_calculate_bitrate(struct rate_info *rate) |
1146 | { | 1226 | { |
1147 | if (rate->flags & RATE_INFO_FLAGS_MCS) | 1227 | if (rate->flags & RATE_INFO_FLAGS_MCS) |
@@ -1150,6 +1230,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) | |||
1150 | return cfg80211_calculate_bitrate_60g(rate); | 1230 | return cfg80211_calculate_bitrate_60g(rate); |
1151 | if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) | 1231 | if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) |
1152 | return cfg80211_calculate_bitrate_vht(rate); | 1232 | return cfg80211_calculate_bitrate_vht(rate); |
1233 | if (rate->flags & RATE_INFO_FLAGS_HE_MCS) | ||
1234 | return cfg80211_calculate_bitrate_he(rate); | ||
1153 | 1235 | ||
1154 | return rate->legacy; | 1236 | return rate->legacy; |
1155 | } | 1237 | } |
@@ -1791,8 +1873,9 @@ bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range, | |||
1791 | 1873 | ||
1792 | int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp) | 1874 | int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp) |
1793 | { | 1875 | { |
1794 | sinfo->pertid = kcalloc(sizeof(*(sinfo->pertid)), | 1876 | sinfo->pertid = kcalloc(IEEE80211_NUM_TIDS + 1, |
1795 | IEEE80211_NUM_TIDS + 1, gfp); | 1877 | sizeof(*(sinfo->pertid)), |
1878 | gfp); | ||
1796 | if (!sinfo->pertid) | 1879 | if (!sinfo->pertid) |
1797 | return -ENOMEM; | 1880 | return -ENOMEM; |
1798 | 1881 | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 05186a47878f..167f7025ac98 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -1278,7 +1278,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev, | |||
1278 | if (err) | 1278 | if (err) |
1279 | return err; | 1279 | return err; |
1280 | 1280 | ||
1281 | if (!(sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))) | 1281 | if (!(sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) |
1282 | return -EOPNOTSUPP; | 1282 | return -EOPNOTSUPP; |
1283 | 1283 | ||
1284 | rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); | 1284 | rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); |
@@ -1320,7 +1320,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
1320 | 1320 | ||
1321 | switch (rdev->wiphy.signal_type) { | 1321 | switch (rdev->wiphy.signal_type) { |
1322 | case CFG80211_SIGNAL_TYPE_MBM: | 1322 | case CFG80211_SIGNAL_TYPE_MBM: |
1323 | if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) { | 1323 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) { |
1324 | int sig = sinfo.signal; | 1324 | int sig = sinfo.signal; |
1325 | wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; | 1325 | wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; |
1326 | wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; | 1326 | wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; |
@@ -1334,7 +1334,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
1334 | break; | 1334 | break; |
1335 | } | 1335 | } |
1336 | case CFG80211_SIGNAL_TYPE_UNSPEC: | 1336 | case CFG80211_SIGNAL_TYPE_UNSPEC: |
1337 | if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) { | 1337 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) { |
1338 | wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; | 1338 | wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; |
1339 | wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; | 1339 | wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; |
1340 | wstats.qual.level = sinfo.signal; | 1340 | wstats.qual.level = sinfo.signal; |
@@ -1347,9 +1347,9 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
1347 | } | 1347 | } |
1348 | 1348 | ||
1349 | wstats.qual.updated |= IW_QUAL_NOISE_INVALID; | 1349 | wstats.qual.updated |= IW_QUAL_NOISE_INVALID; |
1350 | if (sinfo.filled & BIT(NL80211_STA_INFO_RX_DROP_MISC)) | 1350 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC)) |
1351 | wstats.discard.misc = sinfo.rx_dropped_misc; | 1351 | wstats.discard.misc = sinfo.rx_dropped_misc; |
1352 | if (sinfo.filled & BIT(NL80211_STA_INFO_TX_FAILED)) | 1352 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED)) |
1353 | wstats.discard.retries = sinfo.tx_failed; | 1353 | wstats.discard.retries = sinfo.tx_failed; |
1354 | 1354 | ||
1355 | return &wstats; | 1355 | return &wstats; |