summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorCathy Luo <cluo@marvell.com>2016-09-20 17:19:03 +0200
committerKalle Valo <kvalo@codeaurora.org>2016-09-26 19:39:42 +0200
commit5476f8030d9a9f7082ba5a4d4f0a1bfbf6936800 (patch)
tree478d84df8e7fc531d7fdb4df11bf6e8162168508 /drivers/net/wireless
parentmwifiex: fix kernel crash for USB chipsets (diff)
downloadlinux-5476f8030d9a9f7082ba5a4d4f0a1bfbf6936800.tar.xz
linux-5476f8030d9a9f7082ba5a4d4f0a1bfbf6936800.zip
mwifiex: fix race condition causing tx timeout
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 <cluo@marvell.com> Signed-off-by: Shengzhen Li <szli@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/marvell/mwifiex/usb.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index e8283dc1f088..8fd51e42ea5e 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;
}
}