]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Oct 2017 08:57:59 +0000 (10:57 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Oct 2017 08:57:59 +0000 (10:57 +0200)
added patches:
genirq-fix-cpumask-check-in-__irq_startup_managed.patch
genirq-make-sparse_irq_lock-protect-what-it-should-protect.patch
genirq-msi-fix-populating-multiple-interrupts.patch
mac80211-fix-deadlock-in-driver-managed-rx-ba-session-start.patch
mac80211-fix-vlan-handling-with-txqs.patch
mac80211-flush-hw_roc_start-work-before-cancelling-the-roc.patch
mac80211_hwsim-use-proper-tx-power.patch

queue-4.13/genirq-fix-cpumask-check-in-__irq_startup_managed.patch [new file with mode: 0644]
queue-4.13/genirq-make-sparse_irq_lock-protect-what-it-should-protect.patch [new file with mode: 0644]
queue-4.13/genirq-msi-fix-populating-multiple-interrupts.patch [new file with mode: 0644]
queue-4.13/mac80211-fix-deadlock-in-driver-managed-rx-ba-session-start.patch [new file with mode: 0644]
queue-4.13/mac80211-fix-vlan-handling-with-txqs.patch [new file with mode: 0644]
queue-4.13/mac80211-flush-hw_roc_start-work-before-cancelling-the-roc.patch [new file with mode: 0644]
queue-4.13/mac80211_hwsim-use-proper-tx-power.patch [new file with mode: 0644]

diff --git a/queue-4.13/genirq-fix-cpumask-check-in-__irq_startup_managed.patch b/queue-4.13/genirq-fix-cpumask-check-in-__irq_startup_managed.patch
new file mode 100644 (file)
index 0000000..1a7948b
--- /dev/null
@@ -0,0 +1,50 @@
+From 9cb067ef8a10bb13112e4d1c0ea996ec96527422 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 13 Sep 2017 23:29:03 +0200
+Subject: genirq: Fix cpumask check in __irq_startup_managed()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 9cb067ef8a10bb13112e4d1c0ea996ec96527422 upstream.
+
+The result of cpumask_any_and() is invalid when result greater or equal
+nr_cpu_ids. The current check is checking for greater only. Fix it.
+
+Fixes: 761ea388e8c4 ("genirq: Handle managed irqs gracefully in irq_startup()")
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Cc: Juergen Gross <jgross@suse.com>
+Cc: Tony Luck <tony.luck@intel.com>
+Cc: Chen Yu <yu.c.chen@intel.com>
+Cc: Marc Zyngier <marc.zyngier@arm.com>
+Cc: Alok Kataria <akataria@vmware.com>
+Cc: Joerg Roedel <joro@8bytes.org>
+Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Rui Zhang <rui.zhang@intel.com>
+Cc: "K. Y. Srinivasan" <kys@microsoft.com>
+Cc: Arjan van de Ven <arjan@linux.intel.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: Len Brown <lenb@kernel.org>
+Link: http://lkml.kernel.org/r/20170913213152.272283444@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/irq/chip.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/irq/chip.c
++++ b/kernel/irq/chip.c
+@@ -202,7 +202,7 @@ __irq_startup_managed(struct irq_desc *d
+       irqd_clr_managed_shutdown(d);
+-      if (cpumask_any_and(aff, cpu_online_mask) > nr_cpu_ids) {
++      if (cpumask_any_and(aff, cpu_online_mask) >= nr_cpu_ids) {
+               /*
+                * Catch code which fiddles with enable_irq() on a managed
+                * and potentially shutdown IRQ. Chained interrupt
diff --git a/queue-4.13/genirq-make-sparse_irq_lock-protect-what-it-should-protect.patch b/queue-4.13/genirq-make-sparse_irq_lock-protect-what-it-should-protect.patch
new file mode 100644 (file)
index 0000000..f26c047
--- /dev/null
@@ -0,0 +1,119 @@
+From 12ac1d0f6c3e95732d144ffa65c8b20fbd9aa462 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 5 Sep 2017 10:12:20 +0200
+Subject: genirq: Make sparse_irq_lock protect what it should protect
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 12ac1d0f6c3e95732d144ffa65c8b20fbd9aa462 upstream.
+
+for_each_active_irq() iterates the sparse irq allocation bitmap. The caller
+must hold sparse_irq_lock. Several code pathes expect that an active bit in
+the sparse bitmap also has a valid interrupt descriptor.
+
+Unfortunately that's not true. The (de)allocation is a two step process,
+which holds the sparse_irq_lock only across the queue/remove from the radix
+tree and the set/clear in the allocation bitmap.
+
+If a iteration locks sparse_irq_lock between the two steps, then it might
+see an active bit but the corresponding irq descriptor is NULL. If that is
+dereferenced unconditionally, then the kernel oopses. Of course, all
+iterator sites could be audited and fixed, but....
+
+There is no reason why the sparse_irq_lock needs to be dropped between the
+two steps, in fact the code becomes simpler when the mutex is held across
+both and the semantics become more straight forward, so future problems of
+missing NULL pointer checks in the iteration are avoided and all existing
+sites are fixed in one go.
+
+Expand the lock held sections so both operations are covered and the bitmap
+and the radixtree are in sync.
+
+Fixes: a05a900a51c7 ("genirq: Make sparse_lock a mutex")
+Reported-and-tested-by: Huang Ying <ying.huang@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/irq/irqdesc.c |   24 +++++++-----------------
+ 1 file changed, 7 insertions(+), 17 deletions(-)
+
+--- a/kernel/irq/irqdesc.c
++++ b/kernel/irq/irqdesc.c
+@@ -421,10 +421,8 @@ static void free_desc(unsigned int irq)
+        * The sysfs entry must be serialized against a concurrent
+        * irq_sysfs_init() as well.
+        */
+-      mutex_lock(&sparse_irq_lock);
+       kobject_del(&desc->kobj);
+       delete_irq_desc(irq);
+-      mutex_unlock(&sparse_irq_lock);
+       /*
+        * We free the descriptor, masks and stat fields via RCU. That
+@@ -462,20 +460,15 @@ static int alloc_descs(unsigned int star
+               desc = alloc_desc(start + i, node, flags, mask, owner);
+               if (!desc)
+                       goto err;
+-              mutex_lock(&sparse_irq_lock);
+               irq_insert_desc(start + i, desc);
+               irq_sysfs_add(start + i, desc);
+-              mutex_unlock(&sparse_irq_lock);
+       }
++      bitmap_set(allocated_irqs, start, cnt);
+       return start;
+ err:
+       for (i--; i >= 0; i--)
+               free_desc(start + i);
+-
+-      mutex_lock(&sparse_irq_lock);
+-      bitmap_clear(allocated_irqs, start, cnt);
+-      mutex_unlock(&sparse_irq_lock);
+       return -ENOMEM;
+ }
+@@ -575,6 +568,7 @@ static inline int alloc_descs(unsigned i
+               desc->owner = owner;
+       }
++      bitmap_set(allocated_irqs, start, cnt);
+       return start;
+ }
+@@ -670,10 +664,10 @@ void irq_free_descs(unsigned int from, u
+       if (from >= nr_irqs || (from + cnt) > nr_irqs)
+               return;
++      mutex_lock(&sparse_irq_lock);
+       for (i = 0; i < cnt; i++)
+               free_desc(from + i);
+-      mutex_lock(&sparse_irq_lock);
+       bitmap_clear(allocated_irqs, from, cnt);
+       mutex_unlock(&sparse_irq_lock);
+ }
+@@ -720,19 +714,15 @@ __irq_alloc_descs(int irq, unsigned int
+                                          from, cnt, 0);
+       ret = -EEXIST;
+       if (irq >=0 && start != irq)
+-              goto err;
++              goto unlock;
+       if (start + cnt > nr_irqs) {
+               ret = irq_expand_nr_irqs(start + cnt);
+               if (ret)
+-                      goto err;
++                      goto unlock;
+       }
+-
+-      bitmap_set(allocated_irqs, start, cnt);
+-      mutex_unlock(&sparse_irq_lock);
+-      return alloc_descs(start, cnt, node, affinity, owner);
+-
+-err:
++      ret = alloc_descs(start, cnt, node, affinity, owner);
++unlock:
+       mutex_unlock(&sparse_irq_lock);
+       return ret;
+ }
diff --git a/queue-4.13/genirq-msi-fix-populating-multiple-interrupts.patch b/queue-4.13/genirq-msi-fix-populating-multiple-interrupts.patch
new file mode 100644 (file)
index 0000000..8ab5163
--- /dev/null
@@ -0,0 +1,49 @@
+From 596a7a1d0989c621c3ae49be73a1d1f9de22eb5a Mon Sep 17 00:00:00 2001
+From: John Keeping <john@metanate.com>
+Date: Wed, 6 Sep 2017 10:35:40 +0100
+Subject: genirq/msi: Fix populating multiple interrupts
+
+From: John Keeping <john@metanate.com>
+
+commit 596a7a1d0989c621c3ae49be73a1d1f9de22eb5a upstream.
+
+On allocating the interrupts routed via a wire-to-MSI bridge, the allocator
+iterates over the MSI descriptors to build the hierarchy, but fails to use
+the descriptor interrupt number, and instead uses the base number,
+generating the wrong IRQ domain mappings.
+
+The fix is to use the MSI descriptor interrupt number when setting up
+the interrupt instead of the base interrupt for the allocation range.
+
+The only saving grace is that although the MSI descriptors are allocated
+in bulk, the wired interrupts are only allocated one by one (so
+desc->irq == virq) and the bug went unnoticed so far.
+
+Fixes: 2145ac9310b60 ("genirq/msi: Add msi_domain_populate_irqs")
+Signed-off-by: John Keeping <john@metanate.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
+Link: http://lkml.kernel.org/r/20170906103540.373864a2.john@metanate.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/irq/msi.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/kernel/irq/msi.c
++++ b/kernel/irq/msi.c
+@@ -315,11 +315,12 @@ int msi_domain_populate_irqs(struct irq_
+               ops->set_desc(arg, desc);
+               /* Assumes the domain mutex is held! */
+-              ret = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg);
++              ret = irq_domain_alloc_irqs_hierarchy(domain, desc->irq, 1,
++                                                    arg);
+               if (ret)
+                       break;
+-              irq_set_msi_desc_off(virq, 0, desc);
++              irq_set_msi_desc_off(desc->irq, 0, desc);
+       }
+       if (ret) {
diff --git a/queue-4.13/mac80211-fix-deadlock-in-driver-managed-rx-ba-session-start.patch b/queue-4.13/mac80211-fix-deadlock-in-driver-managed-rx-ba-session-start.patch
new file mode 100644 (file)
index 0000000..2e398e0
--- /dev/null
@@ -0,0 +1,146 @@
+From bde59c475e0883e4c4294bcd9b9c7e08ae18c828 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Wed, 6 Sep 2017 15:01:42 +0200
+Subject: mac80211: fix deadlock in driver-managed RX BA session start
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit bde59c475e0883e4c4294bcd9b9c7e08ae18c828 upstream.
+
+When an RX BA session is started by the driver, and it has to tell
+mac80211 about it, the corresponding bit in tid_rx_manage_offl gets
+set and the BA session work is scheduled. Upon testing this bit, it
+will call __ieee80211_start_rx_ba_session(), thus deadlocking as it
+already holds the ampdu_mlme.mtx, which that acquires again.
+
+Fix this by adding ___ieee80211_start_rx_ba_session(), a version of
+the function that requires the mutex already held.
+
+Fixes: 699cb58c8a52 ("mac80211: manage RX BA session offload without SKB queue")
+Reported-by: Matteo Croce <mcroce@redhat.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/agg-rx.c      |   32 +++++++++++++++++++++-----------
+ net/mac80211/ht.c          |    6 +++---
+ net/mac80211/ieee80211_i.h |    4 ++++
+ 3 files changed, 28 insertions(+), 14 deletions(-)
+
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -245,10 +245,10 @@ static void ieee80211_send_addba_resp(st
+       ieee80211_tx_skb(sdata, skb);
+ }
+-void __ieee80211_start_rx_ba_session(struct sta_info *sta,
+-                                   u8 dialog_token, u16 timeout,
+-                                   u16 start_seq_num, u16 ba_policy, u16 tid,
+-                                   u16 buf_size, bool tx, bool auto_seq)
++void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
++                                    u8 dialog_token, u16 timeout,
++                                    u16 start_seq_num, u16 ba_policy, u16 tid,
++                                    u16 buf_size, bool tx, bool auto_seq)
+ {
+       struct ieee80211_local *local = sta->sdata->local;
+       struct tid_ampdu_rx *tid_agg_rx;
+@@ -267,7 +267,7 @@ void __ieee80211_start_rx_ba_session(str
+               ht_dbg(sta->sdata,
+                      "STA %pM requests BA session on unsupported tid %d\n",
+                      sta->sta.addr, tid);
+-              goto end_no_lock;
++              goto end;
+       }
+       if (!sta->sta.ht_cap.ht_supported) {
+@@ -275,14 +275,14 @@ void __ieee80211_start_rx_ba_session(str
+                      "STA %pM erroneously requests BA session on tid %d w/o QoS\n",
+                      sta->sta.addr, tid);
+               /* send a response anyway, it's an error case if we get here */
+-              goto end_no_lock;
++              goto end;
+       }
+       if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
+               ht_dbg(sta->sdata,
+                      "Suspend in progress - Denying ADDBA request (%pM tid %d)\n",
+                      sta->sta.addr, tid);
+-              goto end_no_lock;
++              goto end;
+       }
+       /* sanity check for incoming parameters:
+@@ -296,7 +296,7 @@ void __ieee80211_start_rx_ba_session(str
+               ht_dbg_ratelimited(sta->sdata,
+                                  "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
+                                  sta->sta.addr, tid, ba_policy, buf_size);
+-              goto end_no_lock;
++              goto end;
+       }
+       /* determine default buffer size */
+       if (buf_size == 0)
+@@ -311,7 +311,7 @@ void __ieee80211_start_rx_ba_session(str
+              buf_size, sta->sta.addr);
+       /* examine state machine */
+-      mutex_lock(&sta->ampdu_mlme.mtx);
++      lockdep_assert_held(&sta->ampdu_mlme.mtx);
+       if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
+               if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
+@@ -415,15 +415,25 @@ end:
+               __clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
+               sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
+       }
+-      mutex_unlock(&sta->ampdu_mlme.mtx);
+-end_no_lock:
+       if (tx)
+               ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
+                                         dialog_token, status, 1, buf_size,
+                                         timeout);
+ }
++void __ieee80211_start_rx_ba_session(struct sta_info *sta,
++                                   u8 dialog_token, u16 timeout,
++                                   u16 start_seq_num, u16 ba_policy, u16 tid,
++                                   u16 buf_size, bool tx, bool auto_seq)
++{
++      mutex_lock(&sta->ampdu_mlme.mtx);
++      ___ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
++                                       start_seq_num, ba_policy, tid,
++                                       buf_size, tx, auto_seq);
++      mutex_unlock(&sta->ampdu_mlme.mtx);
++}
++
+ void ieee80211_process_addba_request(struct ieee80211_local *local,
+                                    struct sta_info *sta,
+                                    struct ieee80211_mgmt *mgmt,
+--- a/net/mac80211/ht.c
++++ b/net/mac80211/ht.c
+@@ -333,9 +333,9 @@ void ieee80211_ba_session_work(struct wo
+               if (test_and_clear_bit(tid,
+                                      sta->ampdu_mlme.tid_rx_manage_offl))
+-                      __ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
+-                                                      IEEE80211_MAX_AMPDU_BUF,
+-                                                      false, true);
++                      ___ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
++                                                       IEEE80211_MAX_AMPDU_BUF,
++                                                       false, true);
+               if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS,
+                                      sta->ampdu_mlme.tid_rx_manage_offl))
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1760,6 +1760,10 @@ void __ieee80211_start_rx_ba_session(str
+                                    u8 dialog_token, u16 timeout,
+                                    u16 start_seq_num, u16 ba_policy, u16 tid,
+                                    u16 buf_size, bool tx, bool auto_seq);
++void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
++                                    u8 dialog_token, u16 timeout,
++                                    u16 start_seq_num, u16 ba_policy, u16 tid,
++                                    u16 buf_size, bool tx, bool auto_seq);
+ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
+                                        enum ieee80211_agg_stop_reason reason);
+ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
diff --git a/queue-4.13/mac80211-fix-vlan-handling-with-txqs.patch b/queue-4.13/mac80211-fix-vlan-handling-with-txqs.patch
new file mode 100644 (file)
index 0000000..0a32b5e
--- /dev/null
@@ -0,0 +1,167 @@
+From 53168215909281a09d3afc6fb51a9d4f81f74d39 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 22 Jun 2017 12:20:30 +0200
+Subject: mac80211: fix VLAN handling with TXQs
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 53168215909281a09d3afc6fb51a9d4f81f74d39 upstream.
+
+With TXQs, the AP_VLAN interfaces are resolved to their owner AP
+interface when enqueuing the frame, which makes sense since the
+frame really goes out on that as far as the driver is concerned.
+
+However, this introduces a problem: frames to be encrypted with
+a VLAN-specific GTK will now be encrypted with the AP GTK, since
+the information about which virtual interface to use to select
+the key is taken from the TXQ.
+
+Fix this by preserving info->control.vif and using that in the
+dequeue function. This now requires doing the driver-mapping
+in the dequeue as well.
+
+Since there's no way to filter the frames that are sitting on a
+TXQ, drop all frames, which may affect other interfaces, when an
+AP_VLAN is removed.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/mac80211.h |   15 ++-------------
+ net/mac80211/iface.c   |   17 +++++++++++++++--
+ net/mac80211/tx.c      |   36 +++++++++++++++++++++++++++++-------
+ 3 files changed, 46 insertions(+), 22 deletions(-)
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -919,21 +919,10 @@ struct ieee80211_tx_info {
+                               unsigned long jiffies;
+                       };
+                       /* NB: vif can be NULL for injected frames */
+-                      union {
+-                              /* NB: vif can be NULL for injected frames */
+-                              struct ieee80211_vif *vif;
+-
+-                              /* When packets are enqueued on txq it's easy
+-                               * to re-construct the vif pointer. There's no
+-                               * more space in tx_info so it can be used to
+-                               * store the necessary enqueue time for packet
+-                               * sojourn time computation.
+-                               */
+-                              codel_time_t enqueue_time;
+-                      };
++                      struct ieee80211_vif *vif;
+                       struct ieee80211_key_conf *hw_key;
+                       u32 flags;
+-                      /* 4 bytes free */
++                      codel_time_t enqueue_time;
+               } control;
+               struct {
+                       u64 cookie;
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -792,6 +792,7 @@ static int ieee80211_open(struct net_dev
+ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
+                             bool going_down)
+ {
++      struct ieee80211_sub_if_data *txq_sdata = sdata;
+       struct ieee80211_local *local = sdata->local;
+       struct fq *fq = &local->fq;
+       unsigned long flags;
+@@ -937,6 +938,9 @@ static void ieee80211_do_stop(struct iee
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_AP_VLAN:
++              txq_sdata = container_of(sdata->bss,
++                                       struct ieee80211_sub_if_data, u.ap);
++
+               mutex_lock(&local->mtx);
+               list_del(&sdata->u.vlan.list);
+               mutex_unlock(&local->mtx);
+@@ -1007,8 +1011,17 @@ static void ieee80211_do_stop(struct iee
+       }
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+-      if (sdata->vif.txq) {
+-              struct txq_info *txqi = to_txq_info(sdata->vif.txq);
++      if (txq_sdata->vif.txq) {
++              struct txq_info *txqi = to_txq_info(txq_sdata->vif.txq);
++
++              /*
++               * FIXME FIXME
++               *
++               * We really shouldn't purge the *entire* txqi since that
++               * contains frames for the other AP_VLANs (and possibly
++               * the AP itself) as well, but there's no API in FQ now
++               * to be able to filter.
++               */
+               spin_lock_bh(&fq->lock);
+               ieee80211_txq_purge(local, txqi);
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1276,11 +1276,6 @@ static void ieee80211_set_skb_enqueue_ti
+       IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time();
+ }
+-static void ieee80211_set_skb_vif(struct sk_buff *skb, struct txq_info *txqi)
+-{
+-      IEEE80211_SKB_CB(skb)->control.vif = txqi->txq.vif;
+-}
+-
+ static u32 codel_skb_len_func(const struct sk_buff *skb)
+ {
+       return skb->len;
+@@ -3414,6 +3409,7 @@ struct sk_buff *ieee80211_tx_dequeue(str
+       struct ieee80211_tx_info *info;
+       struct ieee80211_tx_data tx;
+       ieee80211_tx_result r;
++      struct ieee80211_vif *vif;
+       spin_lock_bh(&fq->lock);
+@@ -3430,8 +3426,6 @@ begin:
+       if (!skb)
+               goto out;
+-      ieee80211_set_skb_vif(skb, txqi);
+-
+       hdr = (struct ieee80211_hdr *)skb->data;
+       info = IEEE80211_SKB_CB(skb);
+@@ -3488,6 +3482,34 @@ begin:
+               }
+       }
++      switch (tx.sdata->vif.type) {
++      case NL80211_IFTYPE_MONITOR:
++              if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
++                      vif = &tx.sdata->vif;
++                      break;
++              }
++              tx.sdata = rcu_dereference(local->monitor_sdata);
++              if (tx.sdata) {
++                      vif = &tx.sdata->vif;
++                      info->hw_queue =
++                              vif->hw_queue[skb_get_queue_mapping(skb)];
++              } else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
++                      ieee80211_free_txskb(&local->hw, skb);
++                      goto begin;
++              } else {
++                      vif = NULL;
++              }
++              break;
++      case NL80211_IFTYPE_AP_VLAN:
++              tx.sdata = container_of(tx.sdata->bss,
++                                      struct ieee80211_sub_if_data, u.ap);
++              /* fall through */
++      default:
++              vif = &tx.sdata->vif;
++              break;
++      }
++
++      IEEE80211_SKB_CB(skb)->control.vif = vif;
+ out:
+       spin_unlock_bh(&fq->lock);
diff --git a/queue-4.13/mac80211-flush-hw_roc_start-work-before-cancelling-the-roc.patch b/queue-4.13/mac80211-flush-hw_roc_start-work-before-cancelling-the-roc.patch
new file mode 100644 (file)
index 0000000..1f0ce3c
--- /dev/null
@@ -0,0 +1,46 @@
+From 6e46d8ce894374fc135c96a8d1057c6af1fef237 Mon Sep 17 00:00:00 2001
+From: Avraham Stern <avraham.stern@intel.com>
+Date: Fri, 18 Aug 2017 15:33:57 +0300
+Subject: mac80211: flush hw_roc_start work before cancelling the ROC
+
+From: Avraham Stern <avraham.stern@intel.com>
+
+commit 6e46d8ce894374fc135c96a8d1057c6af1fef237 upstream.
+
+When HW ROC is supported it is possible that after the HW notified
+that the ROC has started, the ROC was cancelled and another ROC was
+added while the hw_roc_start worker is waiting on the mutex (since
+cancelling the ROC and adding another one also holds the same mutex).
+As a result, the hw_roc_start worker will continue to run after the
+new ROC is added but before it is actually started by the HW.
+This may result in notifying userspace that the ROC has started before
+it actually does, or in case of management tx ROC, in an attempt to
+tx while not on the right channel.
+
+In addition, when the driver will notify mac80211 that the second ROC
+has started, mac80211 will warn that this ROC has already been
+notified.
+
+Fix this by flushing the hw_roc_start work before cancelling an ROC.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Avraham Stern <avraham.stern@intel.com>
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/offchannel.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -707,6 +707,8 @@ static int ieee80211_cancel_roc(struct i
+       if (!cookie)
+               return -ENOENT;
++      flush_work(&local->hw_roc_start);
++
+       mutex_lock(&local->mtx);
+       list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
+               if (!mgmt_tx && roc->cookie != cookie)
diff --git a/queue-4.13/mac80211_hwsim-use-proper-tx-power.patch b/queue-4.13/mac80211_hwsim-use-proper-tx-power.patch
new file mode 100644 (file)
index 0000000..c6df279
--- /dev/null
@@ -0,0 +1,39 @@
+From 9de981f507474f326e42117858dc9a9321331ae5 Mon Sep 17 00:00:00 2001
+From: Beni Lev <beni.lev@intel.com>
+Date: Tue, 25 Jul 2017 11:25:25 +0300
+Subject: mac80211_hwsim: Use proper TX power
+
+From: Beni Lev <beni.lev@intel.com>
+
+commit 9de981f507474f326e42117858dc9a9321331ae5 upstream.
+
+In struct ieee80211_tx_info, control.vif pointer and rate_driver_data[0]
+falls on the same place, depending on the union usage.
+During the whole TX process, the union is referred to as a control struct,
+which holds the vif that is later used in the tx flow, especially in order
+to derive the used tx power.
+Referring direcly to rate_driver_data[0] and assigning a value to it,
+overwrites the vif pointer, hence making all later references irrelevant.
+Moreover, rate_driver_data[0] isn't used later in the flow in order to
+retrieve the channel that it is pointing to.
+
+Signed-off-by: Beni Lev <beni.lev@intel.com>
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mac80211_hwsim.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/net/wireless/mac80211_hwsim.c
++++ b/drivers/net/wireless/mac80211_hwsim.c
+@@ -1362,8 +1362,6 @@ static void mac80211_hwsim_tx(struct iee
+                                      txi->control.rates,
+                                      ARRAY_SIZE(txi->control.rates));
+-      txi->rate_driver_data[0] = channel;
+-
+       if (skb->len >= 24 + 8 &&
+           ieee80211_is_probe_resp(hdr->frame_control)) {
+               /* fake header transmission time */