From 8a006c24809cf2e2a368fdd13d42c55c56b9772b Mon Sep 17 00:00:00 2001 From: Koen Vandeputte Date: Fri, 21 Sep 2018 13:48:53 +0200 Subject: mac80211: backport upstream fixes Backport most significant upstream fixes (excl. hwsim fixes) Refreshed all patches. Contains important fixes for CSA (Channel Switch Announcement) and A-MSDU frames. [slightly altered to apply cleanly] Signed-off-by: Koen Vandeputte --- ...-rt2800-use-TXOP_BACKOFF-for-probe-frames.patch | 3 - ...n-TXQ-teardown-code-before-de-registering.patch | 38 ++++++++ ...sh-fix-HWMP-sequence-numbering-to-follow-.patch | 28 ++++++ ...oid-kernel-panic-when-building-AMSDU-from.patch | 102 +++++++++++++++++++++ ...80211_update_ft_ies-to-validate-NL80211_A.patch | 27 ++++++ ...-not-convert-to-A-MSDU-if-frag-subframe-l.patch | 37 ++++++++ ...-always-account-for-A-MSDU-header-changes.patch | 51 +++++++++++ ...x-an-off-by-one-issue-in-A-MSDU-max_subfr.patch | 26 ++++++ ...x-a-type-issue-in-ieee80211_chandef_to_op.patch | 33 +++++++ ...-fix-a-race-between-restart-and-CSA-flows.patch | 86 +++++++++++++++++ ...x-station-bandwidth-setting-after-channel.patch | 96 +++++++++++++++++++ ...n-t-Tx-a-deauth-frame-if-the-AP-forbade-T.patch | 78 ++++++++++++++++ ...-mac80211-shorten-the-IBSS-debug-messages.patch | 74 +++++++++++++++ .../522-mac80211_configure_antenna_gain.patch | 2 +- .../602-rt2x00-introduce-rt2x00eeprom.patch | 2 +- ...-controlling-support-for-various-chipsets.patch | 74 +++++---------- 16 files changed, 702 insertions(+), 55 deletions(-) create mode 100644 package/kernel/mac80211/patches/382-mac80211-Run-TXQ-teardown-code-before-de-registering.patch create mode 100644 package/kernel/mac80211/patches/383-mac80211-mesh-fix-HWMP-sequence-numbering-to-follow-.patch create mode 100644 package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch create mode 100644 package/kernel/mac80211/patches/385-cfg80211-nl80211_update_ft_ies-to-validate-NL80211_A.patch create mode 100644 package/kernel/mac80211/patches/386-mac80211-do-not-convert-to-A-MSDU-if-frag-subframe-l.patch create mode 100644 package/kernel/mac80211/patches/387-mac80211-always-account-for-A-MSDU-header-changes.patch create mode 100644 package/kernel/mac80211/patches/388-mac80211-fix-an-off-by-one-issue-in-A-MSDU-max_subfr.patch create mode 100644 package/kernel/mac80211/patches/389-cfg80211-fix-a-type-issue-in-ieee80211_chandef_to_op.patch create mode 100644 package/kernel/mac80211/patches/390-mac80211-fix-a-race-between-restart-and-CSA-flows.patch create mode 100644 package/kernel/mac80211/patches/391-mac80211-Fix-station-bandwidth-setting-after-channel.patch create mode 100644 package/kernel/mac80211/patches/392-mac80211-don-t-Tx-a-deauth-frame-if-the-AP-forbade-T.patch create mode 100644 package/kernel/mac80211/patches/393-mac80211-shorten-the-IBSS-debug-messages.patch diff --git a/package/kernel/mac80211/patches/090-Revert-rt2800-use-TXOP_BACKOFF-for-probe-frames.patch b/package/kernel/mac80211/patches/090-Revert-rt2800-use-TXOP_BACKOFF-for-probe-frames.patch index 82a7cb6f46..57b4a727eb 100644 --- a/package/kernel/mac80211/patches/090-Revert-rt2800-use-TXOP_BACKOFF-for-probe-frames.patch +++ b/package/kernel/mac80211/patches/090-Revert-rt2800-use-TXOP_BACKOFF-for-probe-frames.patch @@ -38,6 +38,3 @@ Signed-off-by: Kalle Valo txdesc->u.ht.txop = TXOP_BACKOFF; else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) txdesc->u.ht.txop = TXOP_SIFS; --- -2.17.1 - diff --git a/package/kernel/mac80211/patches/382-mac80211-Run-TXQ-teardown-code-before-de-registering.patch b/package/kernel/mac80211/patches/382-mac80211-Run-TXQ-teardown-code-before-de-registering.patch new file mode 100644 index 0000000000..ad282f9892 --- /dev/null +++ b/package/kernel/mac80211/patches/382-mac80211-Run-TXQ-teardown-code-before-de-registering.patch @@ -0,0 +1,38 @@ +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Mon, 13 Aug 2018 14:16:25 +0200 +Subject: [PATCH] mac80211: Run TXQ teardown code before de-registering + interfaces +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The TXQ teardown code can reference the vif data structures that are +stored in the netdev private memory area if there are still packets on +the queue when it is being freed. Since the TXQ teardown code is run +after the netdevs are freed, this can lead to a use-after-free. Fix this +by moving the TXQ teardown code to earlier in ieee80211_unregister_hw(). + +Reported-by: Ben Greear +Tested-by: Ben Greear +Signed-off-by: Toke Høiland-Jørgensen +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1172,6 +1172,7 @@ void ieee80211_unregister_hw(struct ieee + #if IS_ENABLED(__disabled__CONFIG_IPV6) + unregister_inet6addr_notifier(&local->ifa6_notifier); + #endif ++ ieee80211_txq_teardown_flows(local); + + rtnl_lock(); + +@@ -1200,7 +1201,6 @@ void ieee80211_unregister_hw(struct ieee + skb_queue_purge(&local->skb_queue); + skb_queue_purge(&local->skb_queue_unreliable); + skb_queue_purge(&local->skb_queue_tdls_chsw); +- ieee80211_txq_teardown_flows(local); + + destroy_workqueue(local->workqueue); + wiphy_unregister(local->hw.wiphy); diff --git a/package/kernel/mac80211/patches/383-mac80211-mesh-fix-HWMP-sequence-numbering-to-follow-.patch b/package/kernel/mac80211/patches/383-mac80211-mesh-fix-HWMP-sequence-numbering-to-follow-.patch new file mode 100644 index 0000000000..e7b279af55 --- /dev/null +++ b/package/kernel/mac80211/patches/383-mac80211-mesh-fix-HWMP-sequence-numbering-to-follow-.patch @@ -0,0 +1,28 @@ +From: Yuan-Chi Pang +Date: Wed, 29 Aug 2018 09:30:08 +0800 +Subject: [PATCH] mac80211: mesh: fix HWMP sequence numbering to follow + standard + +IEEE 802.11-2016 14.10.8.3 HWMP sequence numbering says: +If it is a target mesh STA, it shall update its own HWMP SN to +maximum (current HWMP SN, target HWMP SN in the PREQ element) + 1 +immediately before it generates a PREP element in response to a +PREQ element. + +Signed-off-by: Yuan-Chi Pang +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/mesh_hwmp.c ++++ b/net/mac80211/mesh_hwmp.c +@@ -572,6 +572,10 @@ static void hwmp_preq_frame_process(stru + forward = false; + reply = true; + target_metric = 0; ++ ++ if (SN_GT(target_sn, ifmsh->sn)) ++ ifmsh->sn = target_sn; ++ + if (time_after(jiffies, ifmsh->last_sn_update + + net_traversal_jiffies(sdata)) || + time_before(jiffies, ifmsh->last_sn_update)) { diff --git a/package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch b/package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch new file mode 100644 index 0000000000..66993839ee --- /dev/null +++ b/package/kernel/mac80211/patches/384-mac80211-avoid-kernel-panic-when-building-AMSDU-from.patch @@ -0,0 +1,102 @@ +From: Sara Sharon +Date: Wed, 29 Aug 2018 08:57:02 +0200 +Subject: [PATCH] mac80211: avoid kernel panic when building AMSDU from + non-linear SKB + +When building building AMSDU from non-linear SKB, we hit a +kernel panic when trying to push the padding to the tail. +Instead, put the padding at the head of the next subframe. +This also fixes the A-MSDU subframes to not have the padding +accounted in the length field and not have pad at all for +the last subframe, both required by the spec. + +Fixes: 6e0456b54545 ("mac80211: add A-MSDU tx support") +Signed-off-by: Sara Sharon +Reviewed-by: Lorenzo Bianconi +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3064,27 +3064,18 @@ void ieee80211_clear_fast_xmit(struct st + } + + static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local, +- struct sk_buff *skb, int headroom, +- int *subframe_len) ++ struct sk_buff *skb, int headroom) + { +- int amsdu_len = *subframe_len + sizeof(struct ethhdr); +- int padding = (4 - amsdu_len) & 3; +- +- if (skb_headroom(skb) < headroom || skb_tailroom(skb) < padding) { ++ if (skb_headroom(skb) < headroom) { + I802_DEBUG_INC(local->tx_expand_skb_head); + +- if (pskb_expand_head(skb, headroom, padding, GFP_ATOMIC)) { ++ if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { + wiphy_debug(local->hw.wiphy, + "failed to reallocate TX buffer\n"); + return false; + } + } + +- if (padding) { +- *subframe_len += padding; +- skb_put_zero(skb, padding); +- } +- + return true; + } + +@@ -3108,8 +3099,7 @@ static bool ieee80211_amsdu_prepare_head + if (info->control.flags & IEEE80211_TX_CTRL_AMSDU) + return true; + +- if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr), +- &subframe_len)) ++ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr))) + return false; + + data = skb_push(skb, sizeof(*amsdu_hdr)); +@@ -3176,7 +3166,8 @@ static bool ieee80211_amsdu_aggregate(st + void *data; + bool ret = false; + unsigned int orig_len; +- int n = 1, nfrags; ++ int n = 1, nfrags, pad = 0; ++ u16 hdrlen; + + if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) + return false; +@@ -3228,8 +3219,19 @@ static bool ieee80211_amsdu_aggregate(st + if (max_frags && nfrags > max_frags) + goto out; + +- if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) + 2, +- &subframe_len)) ++ /* ++ * Pad out the previous subframe to a multiple of 4 by adding the ++ * padding to the next one, that's being added. Note that head->len ++ * is the length of the full A-MSDU, but that works since each time ++ * we add a new subframe we pad out the previous one to a multiple ++ * of 4 and thus it no longer matters in the next round. ++ */ ++ hdrlen = fast_tx->hdr_len - sizeof(rfc1042_header); ++ if ((head->len - hdrlen) & 3) ++ pad = 4 - ((head->len - hdrlen) & 3); ++ ++ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) + ++ 2 + pad)) + goto out; + + ret = true; +@@ -3241,6 +3243,8 @@ static bool ieee80211_amsdu_aggregate(st + memcpy(data, &len, 2); + memcpy(data + 2, rfc1042_header, sizeof(rfc1042_header)); + ++ memset(skb_push(skb, pad), 0, pad); ++ + head->len += skb->len; + head->data_len += skb->len; + *frag_tail = skb; diff --git a/package/kernel/mac80211/patches/385-cfg80211-nl80211_update_ft_ies-to-validate-NL80211_A.patch b/package/kernel/mac80211/patches/385-cfg80211-nl80211_update_ft_ies-to-validate-NL80211_A.patch new file mode 100644 index 0000000000..f4b14506a6 --- /dev/null +++ b/package/kernel/mac80211/patches/385-cfg80211-nl80211_update_ft_ies-to-validate-NL80211_A.patch @@ -0,0 +1,27 @@ +From: Arunk Khandavalli +Date: Thu, 30 Aug 2018 00:40:16 +0300 +Subject: [PATCH] cfg80211: nl80211_update_ft_ies() to validate + NL80211_ATTR_IE + +nl80211_update_ft_ies() tried to validate NL80211_ATTR_IE with +is_valid_ie_attr() before dereferencing it, but that helper function +returns true in case of NULL pointer (i.e., attribute not included). +This can result to dereferencing a NULL pointer. Fix that by explicitly +checking that NL80211_ATTR_IE is included. + +Fixes: 355199e02b83 ("cfg80211: Extend support for IEEE 802.11r Fast BSS Transition") +Signed-off-by: Arunk Khandavalli +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +--- + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -11763,6 +11763,7 @@ static int nl80211_update_ft_ies(struct + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_MDID] || ++ !info->attrs[NL80211_ATTR_IE] || + !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + diff --git a/package/kernel/mac80211/patches/386-mac80211-do-not-convert-to-A-MSDU-if-frag-subframe-l.patch b/package/kernel/mac80211/patches/386-mac80211-do-not-convert-to-A-MSDU-if-frag-subframe-l.patch new file mode 100644 index 0000000000..1d88902251 --- /dev/null +++ b/package/kernel/mac80211/patches/386-mac80211-do-not-convert-to-A-MSDU-if-frag-subframe-l.patch @@ -0,0 +1,37 @@ +From: Lorenzo Bianconi +Date: Wed, 29 Aug 2018 21:03:25 +0200 +Subject: [PATCH] mac80211: do not convert to A-MSDU if frag/subframe + limited + +Do not start to aggregate packets in a A-MSDU frame (converting the +first subframe to A-MSDU, adding the header) if max_tx_fragments or +max_amsdu_subframes limits are already exceeded by it. In particular, +this happens when drivers set the limit to 1 to avoid A-MSDUs at all. + +Signed-off-by: Lorenzo Bianconi +[reword commit message to be more precise] +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3201,9 +3201,6 @@ static bool ieee80211_amsdu_aggregate(st + if (skb->len + head->len > max_amsdu_len) + goto unlock; + +- if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head)) +- goto out; +- + nfrags = 1 + skb_shinfo(skb)->nr_frags; + nfrags += 1 + skb_shinfo(head)->nr_frags; + frag_tail = &skb_shinfo(head)->frag_list; +@@ -3219,6 +3216,9 @@ static bool ieee80211_amsdu_aggregate(st + if (max_frags && nfrags > max_frags) + goto out; + ++ if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head)) ++ goto out; ++ + /* + * Pad out the previous subframe to a multiple of 4 by adding the + * padding to the next one, that's being added. Note that head->len diff --git a/package/kernel/mac80211/patches/387-mac80211-always-account-for-A-MSDU-header-changes.patch b/package/kernel/mac80211/patches/387-mac80211-always-account-for-A-MSDU-header-changes.patch new file mode 100644 index 0000000000..47942116bc --- /dev/null +++ b/package/kernel/mac80211/patches/387-mac80211-always-account-for-A-MSDU-header-changes.patch @@ -0,0 +1,51 @@ +From: Johannes Berg +Date: Thu, 30 Aug 2018 10:55:49 +0200 +Subject: [PATCH] mac80211: always account for A-MSDU header changes + +In the error path of changing the SKB headroom of the second +A-MSDU subframe, we would not account for the already-changed +length of the first frame that just got converted to be in +A-MSDU format and thus is a bit longer now. + +Fix this by doing the necessary accounting. + +It would be possible to reorder the operations, but that would +make the code more complex (to calculate the necessary pad), +and the headroom expansion should not fail frequently enough +to make that worthwhile. + +Fixes: 6e0456b54545 ("mac80211: add A-MSDU tx support") +Signed-off-by: Johannes Berg +Acked-by: Lorenzo Bianconi +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3232,7 +3232,7 @@ static bool ieee80211_amsdu_aggregate(st + + if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) + + 2 + pad)) +- goto out; ++ goto out_recalc; + + ret = true; + data = skb_push(skb, ETH_ALEN + 2); +@@ -3249,11 +3249,13 @@ static bool ieee80211_amsdu_aggregate(st + head->data_len += skb->len; + *frag_tail = skb; + +- flow->backlog += head->len - orig_len; +- tin->backlog_bytes += head->len - orig_len; +- +- fq_recalc_backlog(fq, tin, flow); ++out_recalc: ++ if (head->len != orig_len) { ++ flow->backlog += head->len - orig_len; ++ tin->backlog_bytes += head->len - orig_len; + ++ fq_recalc_backlog(fq, tin, flow); ++ } + out: + fq->memory_usage += head->truesize - orig_truesize; + diff --git a/package/kernel/mac80211/patches/388-mac80211-fix-an-off-by-one-issue-in-A-MSDU-max_subfr.patch b/package/kernel/mac80211/patches/388-mac80211-fix-an-off-by-one-issue-in-A-MSDU-max_subfr.patch new file mode 100644 index 0000000000..455fa29831 --- /dev/null +++ b/package/kernel/mac80211/patches/388-mac80211-fix-an-off-by-one-issue-in-A-MSDU-max_subfr.patch @@ -0,0 +1,26 @@ +From: Lorenzo Bianconi +Date: Fri, 31 Aug 2018 01:04:13 +0200 +Subject: [PATCH] mac80211: fix an off-by-one issue in A-MSDU + max_subframe computation + +Initialize 'n' to 2 in order to take into account also the first +packet in the estimation of max_subframe limit for a given A-MSDU +since frag_tail pointer is NULL when ieee80211_amsdu_aggregate +routine analyzes the second frame. + +Fixes: 6e0456b54545 ("mac80211: add A-MSDU tx support") +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3166,7 +3166,7 @@ static bool ieee80211_amsdu_aggregate(st + void *data; + bool ret = false; + unsigned int orig_len; +- int n = 1, nfrags, pad = 0; ++ int n = 2, nfrags, pad = 0; + u16 hdrlen; + + if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) diff --git a/package/kernel/mac80211/patches/389-cfg80211-fix-a-type-issue-in-ieee80211_chandef_to_op.patch b/package/kernel/mac80211/patches/389-cfg80211-fix-a-type-issue-in-ieee80211_chandef_to_op.patch new file mode 100644 index 0000000000..8437aad6a6 --- /dev/null +++ b/package/kernel/mac80211/patches/389-cfg80211-fix-a-type-issue-in-ieee80211_chandef_to_op.patch @@ -0,0 +1,33 @@ +From: Dan Carpenter +Date: Fri, 31 Aug 2018 11:10:55 +0300 +Subject: [PATCH] cfg80211: fix a type issue in + ieee80211_chandef_to_operating_class() + +The "chandef->center_freq1" variable is a u32 but "freq" is a u16 so we +are truncating away the high bits. I noticed this bug because in commit +9cf0a0b4b64a ("cfg80211: Add support for 60GHz band channels 5 and 6") +we made "freq <= 56160 + 2160 * 6" a valid requency when before it was +only "freq <= 56160 + 2160 * 4" that was valid. It introduces a static +checker warning: + + net/wireless/util.c:1571 ieee80211_chandef_to_operating_class() + warn: always true condition '(freq <= 56160 + 2160 * 6) => (0-u16max <= 69120)' + +But really we probably shouldn't have been truncating the high bits +away to begin with. + +Signed-off-by: Dan Carpenter +Signed-off-by: Johannes Berg +--- + +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -1377,7 +1377,7 @@ bool ieee80211_chandef_to_operating_clas + u8 *op_class) + { + u8 vht_opclass; +- u16 freq = chandef->center_freq1; ++ u32 freq = chandef->center_freq1; + + if (freq >= 2412 && freq <= 2472) { + if (chandef->width > NL80211_CHAN_WIDTH_40) diff --git a/package/kernel/mac80211/patches/390-mac80211-fix-a-race-between-restart-and-CSA-flows.patch b/package/kernel/mac80211/patches/390-mac80211-fix-a-race-between-restart-and-CSA-flows.patch new file mode 100644 index 0000000000..db2aa0443f --- /dev/null +++ b/package/kernel/mac80211/patches/390-mac80211-fix-a-race-between-restart-and-CSA-flows.patch @@ -0,0 +1,86 @@ +From: Emmanuel Grumbach +Date: Fri, 31 Aug 2018 11:31:06 +0300 +Subject: [PATCH] mac80211: fix a race between restart and CSA flows + +We hit a problem with iwlwifi that was caused by a bug in +mac80211. A bug in iwlwifi caused the firwmare to crash in +certain cases in channel switch. Because of that bug, +drv_pre_channel_switch would fail and trigger the restart +flow. +Now we had the hw restart worker which runs on the system's +workqueue and the csa_connection_drop_work worker that runs +on mac80211's workqueue that can run together. This is +obviously problematic since the restart work wants to +reconfigure the connection, while the csa_connection_drop_work +worker does the exact opposite: it tries to disconnect. + +Fix this by cancelling the csa_connection_drop_work worker +in the restart worker. + +Note that this can sound racy: we could have: + +driver iface_work CSA_work restart_work ++++++++++++++++++++++++++++++++++++++++++++++ + | + <--drv_cs ---| + +-CS FAILED--> + | | + | cancel_work(CSA) + schedule | + CSA work | + | | + Race between those 2 + +But this is not possible because we flush the workqueue +in the restart worker before we cancel the CSA worker. +That would be bullet proof if we could guarantee that +we schedule the CSA worker only from the iface_work +which runs on the workqueue (and not on the system's +workqueue), but unfortunately we do have an instance +in which we schedule the CSA work outside the context +of the workqueue (ieee80211_chswitch_done). + +Note also that we should probably cancel other workers +like beacon_connection_loss_work and possibly others +for different types of interfaces, at the very least, +IBSS should suffer from the exact same problem, but for +now, do the minimum to fix the actual bug that was actually +experienced and reproduced. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Luca Coelho +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -255,8 +255,27 @@ static void ieee80211_restart_work(struc + + flush_work(&local->radar_detected_work); + rtnl_lock(); +- list_for_each_entry(sdata, &local->interfaces, list) ++ list_for_each_entry(sdata, &local->interfaces, list) { ++ /* ++ * XXX: there may be more work for other vif types and even ++ * for station mode: a good thing would be to run most of ++ * the iface type's dependent _stop (ieee80211_mg_stop, ++ * ieee80211_ibss_stop) etc... ++ * For now, fix only the specific bug that was seen: race ++ * between csa_connection_drop_work and us. ++ */ ++ if (sdata->vif.type == NL80211_IFTYPE_STATION) { ++ /* ++ * This worker is scheduled from the iface worker that ++ * runs on mac80211's workqueue, so we can't be ++ * scheduling this worker after the cancel right here. ++ * The exception is ieee80211_chswitch_done. ++ * Then we can have a race... ++ */ ++ cancel_work_sync(&sdata->u.mgd.csa_connection_drop_work); ++ } + flush_delayed_work(&sdata->dec_tailroom_needed_wk); ++ } + ieee80211_scan_cancel(local); + + /* make sure any new ROC will consider local->in_reconfig */ diff --git a/package/kernel/mac80211/patches/391-mac80211-Fix-station-bandwidth-setting-after-channel.patch b/package/kernel/mac80211/patches/391-mac80211-Fix-station-bandwidth-setting-after-channel.patch new file mode 100644 index 0000000000..aa8db32e72 --- /dev/null +++ b/package/kernel/mac80211/patches/391-mac80211-Fix-station-bandwidth-setting-after-channel.patch @@ -0,0 +1,96 @@ +From: Ilan Peer +Date: Fri, 31 Aug 2018 11:31:10 +0300 +Subject: [PATCH] mac80211: Fix station bandwidth setting after channel + switch + +When performing a channel switch flow for a managed interface, the +flow did not update the bandwidth of the AP station and the rate +scale algorithm. In case of a channel width downgrade, this would +result with the rate scale algorithm using a bandwidth that does not +match the interface channel configuration. + +Fix this by updating the AP station bandwidth and rate scaling algorithm +before the actual channel change in case of a bandwidth downgrade, or +after the actual channel change in case of a bandwidth upgrade. + +Signed-off-by: Ilan Peer +Signed-off-by: Luca Coelho +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -975,6 +975,10 @@ static void ieee80211_chswitch_work(stru + */ + + if (sdata->reserved_chanctx) { ++ struct ieee80211_supported_band *sband = NULL; ++ struct sta_info *mgd_sta = NULL; ++ enum ieee80211_sta_rx_bandwidth bw = IEEE80211_STA_RX_BW_20; ++ + /* + * with multi-vif csa driver may call ieee80211_csa_finish() + * many times while waiting for other interfaces to use their +@@ -983,6 +987,48 @@ static void ieee80211_chswitch_work(stru + if (sdata->reserved_ready) + goto out; + ++ if (sdata->vif.bss_conf.chandef.width != ++ sdata->csa_chandef.width) { ++ /* ++ * For managed interface, we need to also update the AP ++ * station bandwidth and align the rate scale algorithm ++ * on the bandwidth change. Here we only consider the ++ * bandwidth of the new channel definition (as channel ++ * switch flow does not have the full HT/VHT/HE ++ * information), assuming that if additional changes are ++ * required they would be done as part of the processing ++ * of the next beacon from the AP. ++ */ ++ switch (sdata->csa_chandef.width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ default: ++ bw = IEEE80211_STA_RX_BW_20; ++ break; ++ case NL80211_CHAN_WIDTH_40: ++ bw = IEEE80211_STA_RX_BW_40; ++ break; ++ case NL80211_CHAN_WIDTH_80: ++ bw = IEEE80211_STA_RX_BW_80; ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ case NL80211_CHAN_WIDTH_160: ++ bw = IEEE80211_STA_RX_BW_160; ++ break; ++ } ++ ++ mgd_sta = sta_info_get(sdata, ifmgd->bssid); ++ sband = ++ local->hw.wiphy->bands[sdata->csa_chandef.chan->band]; ++ } ++ ++ if (sdata->vif.bss_conf.chandef.width > ++ sdata->csa_chandef.width) { ++ mgd_sta->sta.bandwidth = bw; ++ rate_control_rate_update(local, sband, mgd_sta, ++ IEEE80211_RC_BW_CHANGED); ++ } ++ + ret = ieee80211_vif_use_reserved_context(sdata); + if (ret) { + sdata_info(sdata, +@@ -993,6 +1039,13 @@ static void ieee80211_chswitch_work(stru + goto out; + } + ++ if (sdata->vif.bss_conf.chandef.width < ++ sdata->csa_chandef.width) { ++ mgd_sta->sta.bandwidth = bw; ++ rate_control_rate_update(local, sband, mgd_sta, ++ IEEE80211_RC_BW_CHANGED); ++ } ++ + goto out; + } + diff --git a/package/kernel/mac80211/patches/392-mac80211-don-t-Tx-a-deauth-frame-if-the-AP-forbade-T.patch b/package/kernel/mac80211/patches/392-mac80211-don-t-Tx-a-deauth-frame-if-the-AP-forbade-T.patch new file mode 100644 index 0000000000..74dd3d3775 --- /dev/null +++ b/package/kernel/mac80211/patches/392-mac80211-don-t-Tx-a-deauth-frame-if-the-AP-forbade-T.patch @@ -0,0 +1,78 @@ +From: Emmanuel Grumbach +Date: Fri, 31 Aug 2018 11:31:12 +0300 +Subject: [PATCH] mac80211: don't Tx a deauth frame if the AP forbade Tx + +If the driver fails to properly prepare for the channel +switch, mac80211 will disconnect. If the CSA IE had mode +set to 1, it means that the clients are not allowed to send +any Tx on the current channel, and that includes the +deauthentication frame. + +Make sure that we don't send the deauthentication frame in +this case. + +In iwlwifi, this caused a failure to flush queues since the +firmware already closed the queues after having parsed the +CSA IE. Then mac80211 would wait until the deauthentication +frame would go out (drv_flush(drop=false)) and that would +never happen. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Luca Coelho +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1267,6 +1267,16 @@ ieee80211_sta_process_chanswitch(struct + cbss->beacon_interval)); + return; + drop_connection: ++ /* ++ * This is just so that the disconnect flow will know that ++ * we were trying to switch channel and failed. In case the ++ * mode is 1 (we are not allowed to Tx), we will know not to ++ * send a deauthentication frame. Those two fields will be ++ * reset when the disconnection worker runs. ++ */ ++ sdata->vif.csa_active = true; ++ sdata->csa_block_tx = csa_ie.mode; ++ + ieee80211_queue_work(&local->hw, &ifmgd->csa_connection_drop_work); + mutex_unlock(&local->chanctx_mtx); + mutex_unlock(&local->mtx); +@@ -2437,6 +2447,7 @@ static void __ieee80211_disconnect(struc + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; ++ bool tx; + + sdata_lock(sdata); + if (!ifmgd->associated) { +@@ -2444,6 +2455,8 @@ static void __ieee80211_disconnect(struc + return; + } + ++ tx = !sdata->csa_block_tx; ++ + /* AP is probably out of range (or not reachable for another reason) so + * remove the bss struct for that AP. + */ +@@ -2451,7 +2464,7 @@ static void __ieee80211_disconnect(struc + + ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, +- true, frame_buf); ++ tx, frame_buf); + mutex_lock(&local->mtx); + sdata->vif.csa_active = false; + ifmgd->csa_waiting_bcn = false; +@@ -2462,7 +2475,7 @@ static void __ieee80211_disconnect(struc + } + mutex_unlock(&local->mtx); + +- ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, ++ ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx, + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); + + sdata_unlock(sdata); diff --git a/package/kernel/mac80211/patches/393-mac80211-shorten-the-IBSS-debug-messages.patch b/package/kernel/mac80211/patches/393-mac80211-shorten-the-IBSS-debug-messages.patch new file mode 100644 index 0000000000..fb5b282d1d --- /dev/null +++ b/package/kernel/mac80211/patches/393-mac80211-shorten-the-IBSS-debug-messages.patch @@ -0,0 +1,74 @@ +From: Emmanuel Grumbach +Date: Fri, 31 Aug 2018 11:31:13 +0300 +Subject: [PATCH] mac80211: shorten the IBSS debug messages + +When tracing is enabled, all the debug messages are recorded and must +not exceed MAX_MSG_LEN (100) columns. Longer debug messages grant the +user with: + +WARNING: CPU: 3 PID: 32642 at /tmp/wifi-core-20180806094828/src/iwlwifi-stack-dev/net/mac80211/./trace_msg.h:32 trace_event_raw_event_mac80211_msg_event+0xab/0xc0 [mac80211] +Workqueue: phy1 ieee80211_iface_work [mac80211] + RIP: 0010:trace_event_raw_event_mac80211_msg_event+0xab/0xc0 [mac80211] + Call Trace: + __sdata_dbg+0xbd/0x120 [mac80211] + ieee80211_ibss_rx_queued_mgmt+0x15f/0x510 [mac80211] + ieee80211_iface_work+0x21d/0x320 [mac80211] + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Luca Coelho +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -947,8 +947,8 @@ static void ieee80211_rx_mgmt_deauth_ibs + if (len < IEEE80211_DEAUTH_FRAME_LEN) + return; + +- ibss_dbg(sdata, "RX DeAuth SA=%pM DA=%pM BSSID=%pM (reason: %d)\n", +- mgmt->sa, mgmt->da, mgmt->bssid, reason); ++ ibss_dbg(sdata, "RX DeAuth SA=%pM DA=%pM\n", mgmt->sa, mgmt->da); ++ ibss_dbg(sdata, "\tBSSID=%pM (reason: %d)\n", mgmt->bssid, reason); + sta_info_destroy_addr(sdata, mgmt->sa); + } + +@@ -966,9 +966,9 @@ static void ieee80211_rx_mgmt_auth_ibss( + auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); + auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); + +- ibss_dbg(sdata, +- "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", +- mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); ++ ibss_dbg(sdata, "RX Auth SA=%pM DA=%pM\n", mgmt->sa, mgmt->da); ++ ibss_dbg(sdata, "\tBSSID=%pM (auth_transaction=%d)\n", ++ mgmt->bssid, auth_transaction); + + if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) + return; +@@ -1175,10 +1175,10 @@ static void ieee80211_rx_bss_info(struct + rx_timestamp = drv_get_tsf(local, sdata); + } + +- ibss_dbg(sdata, +- "RX beacon SA=%pM BSSID=%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", ++ ibss_dbg(sdata, "RX beacon SA=%pM BSSID=%pM TSF=0x%llx\n", + mgmt->sa, mgmt->bssid, +- (unsigned long long)rx_timestamp, ++ (unsigned long long)rx_timestamp); ++ ibss_dbg(sdata, "\tBCN=0x%llx diff=%lld @%lu\n", + (unsigned long long)beacon_timestamp, + (unsigned long long)(rx_timestamp - beacon_timestamp), + jiffies); +@@ -1537,9 +1537,9 @@ static void ieee80211_rx_mgmt_probe_req( + + tx_last_beacon = drv_tx_last_beacon(local); + +- ibss_dbg(sdata, +- "RX ProbeReq SA=%pM DA=%pM BSSID=%pM (tx_last_beacon=%d)\n", +- mgmt->sa, mgmt->da, mgmt->bssid, tx_last_beacon); ++ ibss_dbg(sdata, "RX ProbeReq SA=%pM DA=%pM\n", mgmt->sa, mgmt->da); ++ ibss_dbg(sdata, "\tBSSID=%pM (tx_last_beacon=%d)\n", ++ mgmt->bssid, tx_last_beacon); + + if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) + return; diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch index 19f0ff2ae9..b815f5f22a 100644 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -119,7 +119,7 @@ if (local->hw.conf.power_level != power) { changed |= IEEE80211_CONF_CHANGE_POWER; local->hw.conf.power_level = power; -@@ -592,6 +598,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ +@@ -611,6 +617,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ IEEE80211_RADIOTAP_MCS_HAVE_BW; local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; diff --git a/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00eeprom.patch index b0c5d5ba37..f95fa9540c 100644 --- a/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00eeprom.patch +++ b/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00eeprom.patch @@ -1,6 +1,6 @@ --- a/local-symbols +++ b/local-symbols -@@ -296,6 +296,7 @@ RT2X00_LIB_FIRMWARE= +@@ -298,6 +298,7 @@ RT2X00_LIB_FIRMWARE= RT2X00_LIB_CRYPTO= RT2X00_LIB_LEDS= RT2X00_LIB_DEBUGFS= diff --git a/package/kernel/mac80211/patches/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/package/kernel/mac80211/patches/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch index ee216529f6..fc7fe1edb0 100644 --- a/package/kernel/mac80211/patches/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch +++ b/package/kernel/mac80211/patches/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch @@ -83,10 +83,8 @@ v13: 12 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/ath/ath10k/leds.c create mode 100644 drivers/net/wireless/ath/ath10k/leds.h -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/Kconfig -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/Kconfig -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/Kconfig +--- a/drivers/net/wireless/ath/ath10k/Kconfig ++++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -56,6 +56,16 @@ config ATH10K_DEBUGFS If unsure, say Y to make it easier to debug problems. @@ -104,10 +102,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/Kconfig config ATH10K_SPECTRAL bool "Atheros ath10k spectral scan support" depends on ATH10K_DEBUGFS -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/Makefile -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/Makefile -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/Makefile +--- a/drivers/net/wireless/ath/ath10k/Makefile ++++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -18,6 +18,7 @@ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o @@ -116,10 +112,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/Makefile ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o ath10k_core-$(CONFIG_PM) += wow.o -Index: backports-2017-11-01/local-symbols -=================================================================== ---- backports-2017-11-01.orig/local-symbols -+++ backports-2017-11-01/local-symbols +--- a/local-symbols ++++ b/local-symbols @@ -143,6 +143,7 @@ ATH10K_USB= ATH10K_DEBUG= ATH10K_DEBUGFS= @@ -128,10 +122,8 @@ Index: backports-2017-11-01/local-symbols ATH10K_TRACING= ATH10K_DFS_CERTIFIED= WCN36XX= -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/core.c -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/core.c -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/core.c +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c @@ -32,6 +32,7 @@ #include "htt.h" #include "testmode.h" @@ -219,10 +211,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/core.c ath10k_thermal_unregister(ar); /* Stop spectral before unregistering from mac80211 to remove the * relayfs debugfs file cleanly. Otherwise the parent debugfs tree -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/core.h -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/core.h -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/core.h +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h @@ -24,6 +24,7 @@ #include #include @@ -253,10 +243,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/core.h /* protected by data_lock */ u32 fw_crash_counter; u32 fw_warm_reset_counter; -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/hw.h -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/hw.h -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/hw.h +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -490,6 +490,7 @@ struct ath10k_hw_params { const char *name; u32 patch_load_addr; @@ -265,10 +253,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/hw.h u32 otp_exe_param; /* Type of hw cycle counter wraparound logic, for more info -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/leds.c -=================================================================== --- /dev/null -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/leds.c ++++ b/drivers/net/wireless/ath/ath10k/leds.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. @@ -373,10 +359,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/leds.c + led_classdev_unregister(&ar->leds.cdev); +} + -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/leds.h -=================================================================== --- /dev/null -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/leds.h ++++ b/drivers/net/wireless/ath/ath10k/leds.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. @@ -419,10 +403,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/leds.h + +#endif +#endif /* _LEDS_H_ */ -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/mac.c -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/mac.c -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/mac.c +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -32,6 +32,7 @@ #include "wmi-tlv.h" #include "wmi-ops.h" @@ -431,10 +413,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/mac.c /*********/ /* Rates */ -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi-ops.h -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/wmi-ops.h -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi-ops.h +--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h ++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -197,6 +197,10 @@ struct wmi_ops { (struct ath10k *ar, enum wmi_bss_survey_req_type type); @@ -482,10 +462,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi-ops.h static inline int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level) { -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi-tlv.c -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/wmi-tlv.c -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi-tlv.c +--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c ++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3619,6 +3619,8 @@ static const struct wmi_ops wmi_tlv_ops .gen_echo = ath10k_wmi_tlv_op_gen_echo, .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf, @@ -495,10 +473,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi-tlv.c }; static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi.c -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/wmi.c -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi.c +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -6580,6 +6580,49 @@ ath10k_wmi_op_gen_peer_set_param(struct return skb; } @@ -595,10 +571,8 @@ Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi.c }; int ath10k_wmi_attach(struct ath10k *ar) -Index: backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi.h -=================================================================== ---- backports-2017-11-01.orig/drivers/net/wireless/ath/ath10k/wmi.h -+++ backports-2017-11-01/drivers/net/wireless/ath/ath10k/wmi.h +--- a/drivers/net/wireless/ath/ath10k/wmi.h ++++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -2899,6 +2899,41 @@ enum wmi_10_4_feature_mask { }; -- cgit v1.2.3