Skip to content

Commit

Permalink
mwifiex: fix corner case system hang issue
Browse files Browse the repository at this point in the history
Sometimes pending internal scan commands are delayed to give
preference to Tx traffic. 'scan_processing' flag has been
checked at the beginning of delay timer routine to know if in the
meantime scan operation has been cancelled.

There is a corner case where pending scan commands are emptied
after scan_processing flag check is passed. In this case
wrong pointer returned by list_first_entry() is passed to
list_del() which causes system hang.

This patch fixes the issue by adding list_empty() check.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Amitkumar Karwar authored and John W. Linville committed Jul 15, 2014
1 parent 2d70283 commit d5343f0
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions drivers/net/wireless/mwifiex/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ static void scan_delay_timer_fn(unsigned long data)
struct mwifiex_private *priv = (struct mwifiex_private *)data;
struct mwifiex_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *cmd_node, *tmp_node;
spinlock_t *scan_q_lock = &adapter->scan_pending_q_lock;
unsigned long flags;

if (adapter->surprise_removed)
Expand All @@ -44,13 +45,13 @@ static void scan_delay_timer_fn(unsigned long data)
* Abort scan operation by cancelling all pending scan
* commands
*/
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
spin_lock_irqsave(scan_q_lock, flags);
list_for_each_entry_safe(cmd_node, tmp_node,
&adapter->scan_pending_q, list) {
list_del(&cmd_node->list);
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
}
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
spin_unlock_irqrestore(scan_q_lock, flags);

spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
Expand Down Expand Up @@ -79,12 +80,17 @@ static void scan_delay_timer_fn(unsigned long data)
*/
adapter->scan_delay_cnt = 0;
adapter->empty_tx_q_cnt = 0;
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
spin_lock_irqsave(scan_q_lock, flags);

if (list_empty(&adapter->scan_pending_q)) {
spin_unlock_irqrestore(scan_q_lock, flags);
goto done;
}

cmd_node = list_first_entry(&adapter->scan_pending_q,
struct cmd_ctrl_node, list);
list_del(&cmd_node->list);
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
spin_unlock_irqrestore(scan_q_lock, flags);

mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);
Expand Down

0 comments on commit d5343f0

Please sign in to comment.