Commit df810083 authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville

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: 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 705802bf
...@@ -52,84 +52,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) ...@@ -52,84 +52,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
return 0; return 0;
} }
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;
unsigned long flags;
if (adapter->surprise_removed)
return;
if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
/*
* Abort scan operation by cancelling all pending scan
* commands
*/
spin_lock_irqsave(&adapter->scan_pending_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_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
adapter->scan_delay_cnt = 0;
adapter->empty_tx_q_cnt = 0;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
if (priv->scan_request) {
dev_dbg(adapter->dev, "info: aborting scan\n");
cfg80211_scan_done(priv->scan_request, 1);
priv->scan_request = NULL;
} else {
priv->scan_aborting = false;
dev_dbg(adapter->dev, "info: scan already aborted\n");
}
goto done;
}
if (!atomic_read(&priv->adapter->is_tx_received)) {
adapter->empty_tx_q_cnt++;
if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) {
/*
* No Tx traffic for 200msec. Get scan command from
* scan pending queue and put to cmd pending queue to
* resume scan operation
*/
adapter->scan_delay_cnt = 0;
adapter->empty_tx_q_cnt = 0;
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
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);
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);
queue_work(adapter->workqueue, &adapter->main_work);
goto done;
}
} else {
adapter->empty_tx_q_cnt = 0;
}
/* Delay scan operation further by 20msec */
mod_timer(&priv->scan_delay_timer, jiffies +
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
adapter->scan_delay_cnt++;
done:
if (atomic_read(&priv->adapter->is_tx_received))
atomic_set(&priv->adapter->is_tx_received, false);
return;
}
/* /*
* This function initializes the private structure and sets default * This function initializes the private structure and sets default
* values to the members. * values to the members.
...@@ -211,9 +133,6 @@ int mwifiex_init_priv(struct mwifiex_private *priv) ...@@ -211,9 +133,6 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
priv->scan_block = false; priv->scan_block = false;
setup_timer(&priv->scan_delay_timer, scan_delay_timer_fn,
(unsigned long)priv);
return mwifiex_add_bss_prio_tbl(priv); return mwifiex_add_bss_prio_tbl(priv);
} }
......
...@@ -28,6 +28,84 @@ const char driver_version[] = "mwifiex " VERSION " (%s) "; ...@@ -28,6 +28,84 @@ const char driver_version[] = "mwifiex " VERSION " (%s) ";
static char *cal_data_cfg; static char *cal_data_cfg;
module_param(cal_data_cfg, charp, 0); module_param(cal_data_cfg, charp, 0);
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;
unsigned long flags;
if (adapter->surprise_removed)
return;
if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
/*
* Abort scan operation by cancelling all pending scan
* commands
*/
spin_lock_irqsave(&adapter->scan_pending_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_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
adapter->scan_delay_cnt = 0;
adapter->empty_tx_q_cnt = 0;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
if (priv->scan_request) {
dev_dbg(adapter->dev, "info: aborting scan\n");
cfg80211_scan_done(priv->scan_request, 1);
priv->scan_request = NULL;
} else {
priv->scan_aborting = false;
dev_dbg(adapter->dev, "info: scan already aborted\n");
}
goto done;
}
if (!atomic_read(&priv->adapter->is_tx_received)) {
adapter->empty_tx_q_cnt++;
if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) {
/*
* No Tx traffic for 200msec. Get scan command from
* scan pending queue and put to cmd pending queue to
* resume scan operation
*/
adapter->scan_delay_cnt = 0;
adapter->empty_tx_q_cnt = 0;
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
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);
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);
queue_work(adapter->workqueue, &adapter->main_work);
goto done;
}
} else {
adapter->empty_tx_q_cnt = 0;
}
/* Delay scan operation further by 20msec */
mod_timer(&priv->scan_delay_timer, jiffies +
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
adapter->scan_delay_cnt++;
done:
if (atomic_read(&priv->adapter->is_tx_received))
atomic_set(&priv->adapter->is_tx_received, false);
return;
}
/* /*
* This function registers the device and performs all the necessary * This function registers the device and performs all the necessary
* initializations. * initializations.
...@@ -75,6 +153,10 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, ...@@ -75,6 +153,10 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
adapter->priv[i]->adapter = adapter; adapter->priv[i]->adapter = adapter;
adapter->priv_num++; adapter->priv_num++;
setup_timer(&adapter->priv[i]->scan_delay_timer,
scan_delay_timer_fn,
(unsigned long)adapter->priv[i]);
} }
mwifiex_init_lock_list(adapter); mwifiex_init_lock_list(adapter);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment