mac80211: merge a bunch of pending fixes

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

SVN-Revision: 48536
This commit is contained in:
Felix Fietkau 2016-01-28 22:42:10 +00:00
parent c0edf30bdc
commit c1e6ef488f
5 changed files with 294 additions and 0 deletions

View file

@ -0,0 +1,27 @@
From: Michal Kazior <michal.kazior@tieto.com>
Date: Thu, 21 Jan 2016 14:23:07 +0100
Subject: [PATCH] mac80211: fix txq queue related crashes
The driver can access the queue simultanously
while mac80211 tears down the interface. Without
spinlock protection this could lead to corrupting
sk_buff_head and subsequently to an invalid
pointer dereference.
Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation")
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -977,7 +977,10 @@ static void ieee80211_do_stop(struct iee
if (sdata->vif.txq) {
struct txq_info *txqi = to_txq_info(sdata->vif.txq);
+ spin_lock_bh(&txqi->queue.lock);
ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
+ spin_unlock_bh(&txqi->queue.lock);
+
atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
}

View file

@ -0,0 +1,57 @@
From: Michal Kazior <michal.kazior@tieto.com>
Date: Mon, 25 Jan 2016 14:43:24 +0100
Subject: [PATCH] mac80211: fix unnecessary frame drops in mesh fwding
The ieee80211_queue_stopped() expects hw queue
number but it was given raw WMM AC number instead.
This could cause frame drops and problems with
traffic in some cases - most notably if driver
doesn't map AC numbers to queue numbers 1:1 and
uses ieee80211_stop_queues() and
ieee80211_wake_queue() only without ever calling
ieee80211_wake_queues().
On ath10k it was possible to hit this problem in
the following case:
1. wlan0 uses queue 0
(ath10k maps queues per vif)
2. offchannel uses queue 15
3. queues 1-14 are unused
4. ieee80211_stop_queues()
5. ieee80211_wake_queue(q=0)
6. ieee80211_wake_queue(q=15)
(other queues are not woken up because both
driver and mac80211 know other queues are
unused)
7. ieee80211_rx_h_mesh_fwding()
8. ieee80211_select_queue_80211() returns 2
9. ieee80211_queue_stopped(q=2) returns true
10. frame is dropped (oops!)
Fixes: d3c1597b8d1b ("mac80211: fix forwarded mesh frame queue mapping")
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2235,7 +2235,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- u16 q, hdrlen;
+ u16 ac, q, hdrlen;
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -2304,7 +2304,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
ether_addr_equal(sdata->vif.addr, hdr->addr3))
return RX_CONTINUE;
- q = ieee80211_select_queue_80211(sdata, skb, hdr);
+ ac = ieee80211_select_queue_80211(sdata, skb, hdr);
+ q = sdata->vif.hw_queue[ac];
if (ieee80211_queue_stopped(&local->hw, q)) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
return RX_DROP_MONITOR;

View file

@ -0,0 +1,103 @@
From: Sachin Kulkarni <Sachin.Kulkarni@imgtec.com>
Date: Tue, 12 Jan 2016 14:30:19 +0530
Subject: [PATCH] mac80211: Requeue work after scan complete for all VIF
types.
During a sw scan ieee80211_iface_work ignores work items for all vifs.
However after the scan complete work is requeued only for STA, ADHOC
and MESH iftypes.
This occasionally results in event processing getting delayed/not
processed for iftype AP when it coexists with a STA. This can result
in data halt and eventually disconnection on the AP interface.
Signed-off-by: Sachin Kulkarni <Sachin.Kulkarni@imgtec.com>
Cc: linux-wireless@vger.kernel.org
Cc: johannes@sipsolutions.net
---
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1731,7 +1731,6 @@ void ieee80211_ibss_notify_scan_complete
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
continue;
sdata->u.ibss.last_scan_completed = jiffies;
- ieee80211_queue_work(&local->hw, &sdata->work);
}
mutex_unlock(&local->iflist_mtx);
}
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1369,17 +1369,6 @@ out:
sdata_unlock(sdata);
}
-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
-{
- struct ieee80211_sub_if_data *sdata;
-
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list)
- if (ieee80211_vif_is_mesh(&sdata->vif) &&
- ieee80211_sdata_running(sdata))
- ieee80211_queue_work(&local->hw, &sdata->work);
- rcu_read_unlock();
-}
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
{
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -362,14 +362,10 @@ static inline bool mesh_path_sel_is_hwmp
return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP;
}
-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
-
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
void ieee80211s_stop(void);
#else
-static inline void
-ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
{ return false; }
static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3978,8 +3978,6 @@ static void ieee80211_restart_sta_timer(
if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
ieee80211_queue_work(&sdata->local->hw,
&sdata->u.mgd.monitor_work);
- /* and do all the other regular work too */
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
}
}
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -314,6 +314,7 @@ static void __ieee80211_scan_completed(s
bool was_scanning = local->scanning;
struct cfg80211_scan_request *scan_req;
struct ieee80211_sub_if_data *scan_sdata;
+ struct ieee80211_sub_if_data *sdata;
lockdep_assert_held(&local->mtx);
@@ -373,7 +374,15 @@ static void __ieee80211_scan_completed(s
ieee80211_mlme_notify_scan_completed(local);
ieee80211_ibss_notify_scan_completed(local);
- ieee80211_mesh_notify_scan_completed(local);
+
+ /* Requeue all the work that might have been ignored while
+ * the scan was in progress
+ */
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (ieee80211_sdata_running(sdata))
+ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ }
+
if (was_scanning)
ieee80211_start_next_roc(local);
}

View file

@ -0,0 +1,57 @@
From: Sara Sharon <sara.sharon@intel.com>
Date: Mon, 25 Jan 2016 15:46:35 +0200
Subject: [PATCH] mac80211: fix ibss scan parameters
When joining IBSS a full scan should be initiated in order to search
for existing cell, unless the fixed_channel parameter was set.
A default channel to create the IBSS on if no cell was found is
provided as well.
However - a scan is initiated only on the default channel provided
regardless of whether ifibss->fixed_channel is set or not, with the
obvious result of the cell not joining existing IBSS cell that is
on another channel.
Fixes: 76bed0f43b27 ("mac80211: IBSS fix scan request")
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -7,6 +7,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -1483,14 +1484,21 @@ static void ieee80211_sta_find_ibss(stru
sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
- num = ieee80211_ibss_setup_scan_channels(local->hw.wiphy,
- &ifibss->chandef,
- channels,
- ARRAY_SIZE(channels));
scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
- ieee80211_request_ibss_scan(sdata, ifibss->ssid,
- ifibss->ssid_len, channels, num,
- scan_width);
+
+ if (ifibss->fixed_channel) {
+ num = ieee80211_ibss_setup_scan_channels(local->hw.wiphy,
+ &ifibss->chandef,
+ channels,
+ ARRAY_SIZE(channels));
+ ieee80211_request_ibss_scan(sdata, ifibss->ssid,
+ ifibss->ssid_len, channels,
+ num, scan_width);
+ } else {
+ ieee80211_request_ibss_scan(sdata, ifibss->ssid,
+ ifibss->ssid_len, NULL,
+ 0, scan_width);
+ }
} else {
int interval = IEEE80211_SCAN_INTERVAL;

View file

@ -0,0 +1,50 @@
From: Chris Bainbridge <chris.bainbridge@gmail.com>
Date: Wed, 27 Jan 2016 15:46:18 +0000
Subject: [PATCH] net/mac80211/agg-rx.c: fix use of uninitialised values
Use kzalloc instead of kmalloc for struct tid_ampdu_rx. Fixes:
[ 7.976605] UBSAN: Undefined behaviour in net/mac80211/rx.c:932:29
[ 7.976608] load of value 2 is not a valid value for type '_Bool'
[ 7.976611] CPU: 3 PID: 1134 Comm: kworker/u16:7 Not tainted 4.5.0-rc1+ #265
[ 7.976613] Hardware name: Apple Inc. MacBookPro10,2/Mac-AFD8A9D944EA4843, BIOS MBP102.88Z.0106.B0A.1509130955 09/13/2015
[ 7.976616] Workqueue: phy0 rt2x00usb_work_rxdone
[ 7.976619] 0000000000000004 ffff880254a7ba50 ffffffff8181d866 0000000000000007
[ 7.976622] ffff880254a7ba78 ffff880254a7ba68 ffffffff8188422d ffffffff8379b500
[ 7.976626] ffff880254a7bab8 ffffffff81884747 0000000000000202 0000000348620032
[ 7.976629] Call Trace:
[ 7.976633] [<ffffffff8181d866>] dump_stack+0x45/0x5f
[ 7.976637] [<ffffffff8188422d>] ubsan_epilogue+0xd/0x40
[ 7.976642] [<ffffffff81884747>] __ubsan_handle_load_invalid_value+0x67/0x70
[ 7.976646] [<ffffffff82227b4d>] ieee80211_sta_reorder_release.isra.16+0x5ed/0x730
[ 7.976650] [<ffffffff8222ca14>] ieee80211_prepare_and_rx_handle+0xd04/0x1c00
[ 7.976654] [<ffffffff81cb27ce>] ? usb_hcd_map_urb_for_dma+0x65e/0x960
[ 7.976659] [<ffffffff8222db03>] __ieee80211_rx_handle_packet+0x1f3/0x750
[ 7.976663] [<ffffffff8222e4a7>] ieee80211_rx_napi+0x447/0x990
[ 7.976667] [<ffffffff81c5fb85>] rt2x00lib_rxdone+0x305/0xbd0
[ 7.976670] [<ffffffff811ac23f>] ? dequeue_task_fair+0x64f/0x1de0
[ 7.976674] [<ffffffff811a1516>] ? sched_clock_cpu+0xe6/0x150
[ 7.976678] [<ffffffff81c6c45c>] rt2x00usb_work_rxdone+0x7c/0x140
[ 7.976682] [<ffffffff8117aef6>] process_one_work+0x226/0x860
[ 7.976686] [<ffffffff8117b58c>] worker_thread+0x5c/0x680
[ 7.976690] [<ffffffff8117b530>] ? process_one_work+0x860/0x860
[ 7.976693] [<ffffffff81184f86>] kthread+0xf6/0x150
[ 7.976697] [<ffffffff81184e90>] ? kthread_worker_fn+0x310/0x310
[ 7.976700] [<ffffffff822a94df>] ret_from_fork+0x3f/0x70
[ 7.976703] [<ffffffff81184e90>] ? kthread_worker_fn+0x310/0x310
Link: https://lkml.org/lkml/2016/1/26/230
Signed-off-by: Chris Bainbridge <chris.bainbridge@gmail.com>
---
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -327,7 +327,7 @@ void __ieee80211_start_rx_ba_session(str
}
/* prepare A-MPDU MLME for Rx aggregation */
- tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
+ tid_agg_rx = kzalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
if (!tid_agg_rx)
goto end;