2016-09-20 15:19:33

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 1/3] mwifiex: fix kernel crash for USB chipsets

From: Cathy Luo <[email protected]>

Following crash issue is observed during TCP traffic stress
test

[ 2253.625439] NMI watchdog: BUG: soft lockup - CPU#3 stuck for 22s!
[kworker/u17:1:5191]
[ 2253.625520] Call Trace:
[ 2253.625527] [<ffffffffc0b47030>] ? moal_spin_lock+0x30/0x30
[usb8xxx]
[ 2253.625533] [<ffffffffc0ac3ceb>] ? wlan_wmm_lists_empty+0xb/0xf0
[mlan]
[ 2253.625537] [<ffffffffc0ab0ea3>] mlan_main_process+0x1b3/0x720
[mlan]
[ 2253.625540] [<ffffffffc0b337f5>] woal_main_work_queue+0x45/0x80
[usb8xxx]
[ 2253.625543] [<ffffffff8108aaf0>] process_one_work+0x150/0x3f0
[ 2253.625545] [<ffffffff8108b1e1>] worker_thread+0x121/0x520
[ 2253.625547] [<ffffffff8108b0c0>] ? rescuer_thread+0x330/0x330
[ 2253.625549] [<ffffffff81090222>] kthread+0xd2/0xf0
[ 2253.625551] [<ffffffff81090150>] ?
kthread_create_on_node+0x1c0/0x1c0
[ 2253.625553] [<ffffffff8179423c>] ret_from_fork+0x7c/0xb0
[ 2253.625555] [<ffffffff81090150>] ?
kthread_create_on_node+0x1c0/0x1c0

In mwifiex_usb_tx_complete(), we are updating port->block_status first
and then freeing the skb attached to that URB. We may end up attaching
new skb to URB in a corner case and same will be freed. This results in
the kernel crash. The problem is solved by changing the sequence.

Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Shengzhen Li <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/usb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 8a20620..e8283dc 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -273,6 +273,8 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
} else {
mwifiex_dbg(adapter, DATA,
"%s: DATA\n", __func__);
+ mwifiex_write_data_complete(adapter, context->skb, 0,
+ urb->status ? -1 : 0);
for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
port = &card->port[i];
if (context->ep == port->tx_data_ep) {
@@ -282,8 +284,6 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
}
}
adapter->data_sent = false;
- mwifiex_write_data_complete(adapter, context->skb, 0,
- urb->status ? -1 : 0);
}

if (card->mc_resync_flag)
--
1.9.1


2016-09-20 15:19:51

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 2/3] mwifiex: fix race condition causing tx timeout

From: Cathy Luo <[email protected]>

It's been observed that in a corner case mwifiex_usb_tx_complete()
gets called before we exit from mwifiex_usb_host_to_card() after
submitting the urb. 'data_sent' flag remains set in this case. It
blocks further Tx packets and triggers watchdog timeout.

The problem is fixed by setting data_sent and port_block flag at
correct place.

Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Shengzhen Li <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/usb.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index e8283dc..8fd51e4 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -897,6 +897,13 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
else
atomic_inc(&port->tx_data_urb_pending);

+ if (ep != card->tx_cmd_ep &&
+ atomic_read(&port->tx_data_urb_pending) ==
+ MWIFIEX_TX_DATA_URB) {
+ port->block_status = true;
+ adapter->data_sent = mwifiex_usb_data_sent(adapter);
+ }
+
if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
mwifiex_dbg(adapter, ERROR,
"%s: usb_submit_urb failed\n", __func__);
@@ -905,6 +912,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
} else {
atomic_dec(&port->tx_data_urb_pending);
port->block_status = false;
+ adapter->data_sent = false;
if (port->tx_data_ix)
port->tx_data_ix--;
else
@@ -916,9 +924,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
if (ep != card->tx_cmd_ep &&
atomic_read(&port->tx_data_urb_pending) ==
MWIFIEX_TX_DATA_URB) {
- port->block_status = true;
- ret = -ENOSR;
- goto done;
+ return -ENOSR;
}
}

--
1.9.1

2016-09-20 15:19:50

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 3/3] mwifiex: code rearrangement in mwifiex_usb_host_to_card()

This patch helps get rid of goto statement and improves readability.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/usb.c | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 8fd51e4..73eb084 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -841,7 +841,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
struct usb_tx_data_port *port = NULL;
u8 *data = (u8 *)skb->data;
struct urb *tx_urb;
- int idx, ret;
+ int idx, ret = -EINPROGRESS;

if (adapter->is_suspended) {
mwifiex_dbg(adapter, ERROR,
@@ -865,8 +865,9 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
if (atomic_read(&port->tx_data_urb_pending)
>= MWIFIEX_TX_DATA_URB) {
port->block_status = true;
- ret = -EBUSY;
- goto done;
+ adapter->data_sent =
+ mwifiex_usb_data_sent(adapter);
+ return -EBUSY;
}
if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
port->tx_data_ix = 0;
@@ -902,6 +903,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
MWIFIEX_TX_DATA_URB) {
port->block_status = true;
adapter->data_sent = mwifiex_usb_data_sent(adapter);
+ ret = -ENOSR;
}

if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
@@ -918,22 +920,9 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
else
port->tx_data_ix = MWIFIEX_TX_DATA_URB;
}
-
- return -1;
- } else {
- if (ep != card->tx_cmd_ep &&
- atomic_read(&port->tx_data_urb_pending) ==
- MWIFIEX_TX_DATA_URB) {
- return -ENOSR;
- }
+ ret = -1;
}

- return -EINPROGRESS;
-
-done:
- if (ep != card->tx_cmd_ep)
- adapter->data_sent = mwifiex_usb_data_sent(adapter);
-
return ret;
}

--
1.9.1

2016-09-26 17:40:02

by Kalle Valo

[permalink] [raw]
Subject: Re: [1/3] mwifiex: fix kernel crash for USB chipsets

Amitkumar Karwar <[email protected]> wrote:
> From: Cathy Luo <[email protected]>
>
> Following crash issue is observed during TCP traffic stress
> test
>
> [ 2253.625439] NMI watchdog: BUG: soft lockup - CPU#3 stuck for 22s!
> [kworker/u17:1:5191]
> [ 2253.625520] Call Trace:
> [ 2253.625527] [<ffffffffc0b47030>] ? moal_spin_lock+0x30/0x30
> [usb8xxx]
> [ 2253.625533] [<ffffffffc0ac3ceb>] ? wlan_wmm_lists_empty+0xb/0xf0
> [mlan]
> [ 2253.625537] [<ffffffffc0ab0ea3>] mlan_main_process+0x1b3/0x720
> [mlan]
> [ 2253.625540] [<ffffffffc0b337f5>] woal_main_work_queue+0x45/0x80
> [usb8xxx]
> [ 2253.625543] [<ffffffff8108aaf0>] process_one_work+0x150/0x3f0
> [ 2253.625545] [<ffffffff8108b1e1>] worker_thread+0x121/0x520
> [ 2253.625547] [<ffffffff8108b0c0>] ? rescuer_thread+0x330/0x330
> [ 2253.625549] [<ffffffff81090222>] kthread+0xd2/0xf0
> [ 2253.625551] [<ffffffff81090150>] ?
> kthread_create_on_node+0x1c0/0x1c0
> [ 2253.625553] [<ffffffff8179423c>] ret_from_fork+0x7c/0xb0
> [ 2253.625555] [<ffffffff81090150>] ?
> kthread_create_on_node+0x1c0/0x1c0
>
> In mwifiex_usb_tx_complete(), we are updating port->block_status first
> and then freeing the skb attached to that URB. We may end up attaching
> new skb to URB in a corner case and same will be freed. This results in
> the kernel crash. The problem is solved by changing the sequence.
>
> Signed-off-by: Cathy Luo <[email protected]>
> Signed-off-by: Shengzhen Li <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

3 patches applied to wireless-drivers-next.git, thanks.

1afac196c167 mwifiex: fix kernel crash for USB chipsets
5476f8030d9a mwifiex: fix race condition causing tx timeout
ac3b561721e9 mwifiex: code rearrangement in mwifiex_usb_host_to_card()

--
https://patchwork.kernel.org/patch/9341883/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches