Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5343f06 authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville
Browse files

mwifiex: fix corner case system hang issue



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: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2d702830
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -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)
@@ -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;
@@ -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);