Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mwifiex: fix regression issue for usb interface

PATCH "mwifiex: scan delay timer cleanup in unload path" adds code
to cancel scan delay timer in unload path. It causes a regression
for USB interface.

USB8797 card gets enumerated twice. First enumeration is for
firmware download and second enumeration expects firmware
initialization.

It was observed that we are trying del_timer_sync() without setting
up the timer when remove handler is called after first enumeration.

This patch moves setup_timer() call to appropriate place so that
timer is setup for both the enumerations.

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>

authored by

Amitkumar Karwar and committed by
John W. Linville
df810083 705802bf

+82 -81
-81
drivers/net/wireless/mwifiex/init.c
··· 52 52 return 0; 53 53 } 54 54 55 - static void scan_delay_timer_fn(unsigned long data) 56 - { 57 - struct mwifiex_private *priv = (struct mwifiex_private *)data; 58 - struct mwifiex_adapter *adapter = priv->adapter; 59 - struct cmd_ctrl_node *cmd_node, *tmp_node; 60 - unsigned long flags; 61 - 62 - if (adapter->surprise_removed) 63 - return; 64 - 65 - if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { 66 - /* 67 - * Abort scan operation by cancelling all pending scan 68 - * commands 69 - */ 70 - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 71 - list_for_each_entry_safe(cmd_node, tmp_node, 72 - &adapter->scan_pending_q, list) { 73 - list_del(&cmd_node->list); 74 - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); 75 - } 76 - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); 77 - 78 - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); 79 - adapter->scan_processing = false; 80 - adapter->scan_delay_cnt = 0; 81 - adapter->empty_tx_q_cnt = 0; 82 - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); 83 - 84 - if (priv->scan_request) { 85 - dev_dbg(adapter->dev, "info: aborting scan\n"); 86 - cfg80211_scan_done(priv->scan_request, 1); 87 - priv->scan_request = NULL; 88 - } else { 89 - priv->scan_aborting = false; 90 - dev_dbg(adapter->dev, "info: scan already aborted\n"); 91 - } 92 - goto done; 93 - } 94 - 95 - if (!atomic_read(&priv->adapter->is_tx_received)) { 96 - adapter->empty_tx_q_cnt++; 97 - if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) { 98 - /* 99 - * No Tx traffic for 200msec. Get scan command from 100 - * scan pending queue and put to cmd pending queue to 101 - * resume scan operation 102 - */ 103 - adapter->scan_delay_cnt = 0; 104 - adapter->empty_tx_q_cnt = 0; 105 - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 106 - cmd_node = list_first_entry(&adapter->scan_pending_q, 107 - struct cmd_ctrl_node, list); 108 - list_del(&cmd_node->list); 109 - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, 110 - flags); 111 - 112 - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, 113 - true); 114 - queue_work(adapter->workqueue, &adapter->main_work); 115 - goto done; 116 - } 117 - } else { 118 - adapter->empty_tx_q_cnt = 0; 119 - } 120 - 121 - /* Delay scan operation further by 20msec */ 122 - mod_timer(&priv->scan_delay_timer, jiffies + 123 - msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); 124 - adapter->scan_delay_cnt++; 125 - 126 - done: 127 - if (atomic_read(&priv->adapter->is_tx_received)) 128 - atomic_set(&priv->adapter->is_tx_received, false); 129 - 130 - return; 131 - } 132 - 133 55 /* 134 56 * This function initializes the private structure and sets default 135 57 * values to the members. ··· 132 210 memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg)); 133 211 134 212 priv->scan_block = false; 135 - 136 - setup_timer(&priv->scan_delay_timer, scan_delay_timer_fn, 137 - (unsigned long)priv); 138 213 139 214 return mwifiex_add_bss_prio_tbl(priv); 140 215 }
+82
drivers/net/wireless/mwifiex/main.c
··· 28 28 static char *cal_data_cfg; 29 29 module_param(cal_data_cfg, charp, 0); 30 30 31 + static void scan_delay_timer_fn(unsigned long data) 32 + { 33 + struct mwifiex_private *priv = (struct mwifiex_private *)data; 34 + struct mwifiex_adapter *adapter = priv->adapter; 35 + struct cmd_ctrl_node *cmd_node, *tmp_node; 36 + unsigned long flags; 37 + 38 + if (adapter->surprise_removed) 39 + return; 40 + 41 + if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { 42 + /* 43 + * Abort scan operation by cancelling all pending scan 44 + * commands 45 + */ 46 + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 47 + list_for_each_entry_safe(cmd_node, tmp_node, 48 + &adapter->scan_pending_q, list) { 49 + list_del(&cmd_node->list); 50 + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); 51 + } 52 + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); 53 + 54 + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); 55 + adapter->scan_processing = false; 56 + adapter->scan_delay_cnt = 0; 57 + adapter->empty_tx_q_cnt = 0; 58 + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); 59 + 60 + if (priv->scan_request) { 61 + dev_dbg(adapter->dev, "info: aborting scan\n"); 62 + cfg80211_scan_done(priv->scan_request, 1); 63 + priv->scan_request = NULL; 64 + } else { 65 + priv->scan_aborting = false; 66 + dev_dbg(adapter->dev, "info: scan already aborted\n"); 67 + } 68 + goto done; 69 + } 70 + 71 + if (!atomic_read(&priv->adapter->is_tx_received)) { 72 + adapter->empty_tx_q_cnt++; 73 + if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) { 74 + /* 75 + * No Tx traffic for 200msec. Get scan command from 76 + * scan pending queue and put to cmd pending queue to 77 + * resume scan operation 78 + */ 79 + adapter->scan_delay_cnt = 0; 80 + adapter->empty_tx_q_cnt = 0; 81 + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 82 + cmd_node = list_first_entry(&adapter->scan_pending_q, 83 + struct cmd_ctrl_node, list); 84 + list_del(&cmd_node->list); 85 + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, 86 + flags); 87 + 88 + mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, 89 + true); 90 + queue_work(adapter->workqueue, &adapter->main_work); 91 + goto done; 92 + } 93 + } else { 94 + adapter->empty_tx_q_cnt = 0; 95 + } 96 + 97 + /* Delay scan operation further by 20msec */ 98 + mod_timer(&priv->scan_delay_timer, jiffies + 99 + msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); 100 + adapter->scan_delay_cnt++; 101 + 102 + done: 103 + if (atomic_read(&priv->adapter->is_tx_received)) 104 + atomic_set(&priv->adapter->is_tx_received, false); 105 + 106 + return; 107 + } 108 + 31 109 /* 32 110 * This function registers the device and performs all the necessary 33 111 * initializations. ··· 153 75 154 76 adapter->priv[i]->adapter = adapter; 155 77 adapter->priv_num++; 78 + 79 + setup_timer(&adapter->priv[i]->scan_delay_timer, 80 + scan_delay_timer_fn, 81 + (unsigned long)adapter->priv[i]); 156 82 } 157 83 mwifiex_init_lock_list(adapter); 158 84