summaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.1/0007-libertas-clean-up-scan-thread-handling.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.1/0007-libertas-clean-up-scan-thread-handling.patch')
-rw-r--r--recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.1/0007-libertas-clean-up-scan-thread-handling.patch86
1 files changed, 86 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.1/0007-libertas-clean-up-scan-thread-handling.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.1/0007-libertas-clean-up-scan-thread-handling.patch
new file mode 100644
index 00000000..38fbce3c
--- /dev/null
+++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.1/0007-libertas-clean-up-scan-thread-handling.patch
@@ -0,0 +1,86 @@
1From 3184baa0e69e6ad327808b91e0d915090c59b99b Mon Sep 17 00:00:00 2001
2From: Andres Salomon <dilinger@queued.net>
3Date: Mon, 19 Dec 2011 12:22:58 -0800
4Subject: [PATCH 07/49] libertas: clean up scan thread handling
5
6commit afbca95f95f2bf7283a72670c24c1f6de00b1cb5 upstream.
7
8The libertas scan thread expects priv->scan_req to be non-NULL. In theory,
9it should always be set. In practice, we've seen the following oops:
10
11[ 8363.067444] Unable to handle kernel NULL pointer dereference at virtual address 00000004
12[ 8363.067490] pgd = c0004000
13[ 8363.078393] [00000004] *pgd=00000000
14[ 8363.086711] Internal error: Oops: 17 [#1] PREEMPT
15[ 8363.091375] Modules linked in: fuse libertas_sdio libertas psmouse mousedev ov7670 mmp_camera joydev videobuf2_core videobuf2_dma_sg videobuf2_memops [last unloaded: scsi_wait_scan]
16[ 8363.107490] CPU: 0 Not tainted (3.0.0-gf7ccc69 #671)
17[ 8363.112799] PC is at lbs_scan_worker+0x108/0x5a4 [libertas]
18[ 8363.118326] LR is at 0x0
19[ 8363.120836] pc : [<bf03a854>] lr : [<00000000>] psr: 60000113
20[ 8363.120845] sp : ee66bf48 ip : 00000000 fp : 00000000
21[ 8363.120845] r10: ee2c2088 r9 : c04e2efc r8 : eef97005
22[ 8363.132231] r7 : eee0716f r6 : ee2c02c0 r5 : ee2c2088 r4 : eee07160
23[ 8363.137419] r3 : 00000000 r2 : a0000113 r1 : 00000001 r0 : eee07160
24[ 8363.143896] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
25[ 8363.157630] Control: 10c5387d Table: 2e754019 DAC: 00000015
26[ 8363.163334] Process kworker/u:1 (pid: 25, stack limit = 0xee66a2f8)
27
28While I've not found a smoking gun, there are two places that raised red flags
29for me. The first is in _internal_start_scan, when we queue up a scan; we
30first queue the worker, and then set priv->scan_req. There's theoretically
31a 50mS delay which should be plenty, but doing things that way just seems
32racy (and not in the good way).
33
34The second is in the scan worker thread itself. Depending on the state of
35priv->scan_channel, we cancel pending scan runs and then requeue a run in
36300mS. We then send the scan command down to the hardware, sleep, and if
37we get scan results for all the desired channels, we set priv->scan_req to
38NULL. However, it that's happened in less than 300mS, what happens with
39the pending scan run?
40
41This patch addresses both of those concerns. With the patch applied, we
42have not seen the oops in the past two weeks.
43
44Signed-off-by: Andres Salomon <dilinger@queued.net>
45Signed-off-by: John W. Linville <linville@tuxdriver.com>
46Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
47---
48 drivers/net/wireless/libertas/cfg.c | 10 ++++++----
49 1 files changed, 6 insertions(+), 4 deletions(-)
50
51diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
52index a7f1ab2..db64ef1 100644
53--- a/drivers/net/wireless/libertas/cfg.c
54+++ b/drivers/net/wireless/libertas/cfg.c
55@@ -728,9 +728,11 @@ static void lbs_scan_worker(struct work_struct *work)
56 le16_to_cpu(scan_cmd->hdr.size),
57 lbs_ret_scan, 0);
58
59- if (priv->scan_channel >= priv->scan_req->n_channels)
60+ if (priv->scan_channel >= priv->scan_req->n_channels) {
61 /* Mark scan done */
62+ cancel_delayed_work(&priv->scan_work);
63 lbs_scan_done(priv);
64+ }
65
66 /* Restart network */
67 if (carrier)
68@@ -759,12 +761,12 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal,
69 request->n_ssids, request->n_channels, request->ie_len);
70
71 priv->scan_channel = 0;
72- queue_delayed_work(priv->work_thread, &priv->scan_work,
73- msecs_to_jiffies(50));
74-
75 priv->scan_req = request;
76 priv->internal_scan = internal;
77
78+ queue_delayed_work(priv->work_thread, &priv->scan_work,
79+ msecs_to_jiffies(50));
80+
81 lbs_deb_leave(LBS_DEB_CFG80211);
82 }
83
84--
851.7.7.4
86