Skip to content

Commit

Permalink
libertas: handle command timeout in main thread instead of directly i…
Browse files Browse the repository at this point in the history
…n timer

And handle the case where it times out more than once, too, instead of
locking up for ever.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
David Woodhouse authored and David S. Miller committed Jan 28, 2008
1 parent 9fae899 commit 2a34509
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 22 deletions.
6 changes: 6 additions & 0 deletions drivers/net/wireless/libertas/cmdresp.c
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,12 @@ int lbs_process_rx_command(struct lbs_private *priv)

/* Now we got response from FW, cancel the command timer */
del_timer(&priv->command_timer);
priv->cmd_timed_out = 0;
if (priv->nr_retries) {
lbs_pr_info("Received result %x to command %x after %d retries\n",
result, curcmd, priv->nr_retries);
priv->nr_retries = 0;
}

/* Store the response code to cur_cmd_retcode. */
priv->cur_cmd_retcode = result;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/libertas/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ struct lbs_private {

/** Timers */
struct timer_list command_timer;
int nr_retries;
int cmd_timed_out;

u8 hisregcpy;

Expand Down
52 changes: 30 additions & 22 deletions drivers/net/wireless/libertas/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,8 @@ static int lbs_thread(void *data)
shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */
else if (priv->intcounter)
shouldsleep = 0; /* Interrupt pending. Deal with it now */
else if (priv->cmd_timed_out)
shouldsleep = 0; /* Command timed out. Recover */
else if (!priv->fw_ready)
shouldsleep = 1; /* Firmware not ready. We're waiting for it */
else if (priv->dnld_sent)
Expand Down Expand Up @@ -740,6 +742,26 @@ static int lbs_thread(void *data)
spin_lock_irq(&priv->driver_lock);
}

if (priv->cmd_timed_out && priv->cur_cmd) {
struct cmd_ctrl_node *cmdnode = priv->cur_cmd;

if (++priv->nr_retries > 10) {
lbs_pr_info("Excessive timeouts submitting command %x\n",
le16_to_cpu(cmdnode->cmdbuf->command));
lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
priv->nr_retries = 0;
} else {
priv->cur_cmd = NULL;
lbs_pr_info("requeueing command %x due to timeout (#%d)\n",
le16_to_cpu(cmdnode->cmdbuf->command), priv->nr_retries);

/* Stick it back at the _top_ of the pending queue
for immediate resubmission */
list_add(&cmdnode->list, &priv->cmdpendingq);
}
}
priv->cmd_timed_out = 0;

/* Any Card Event */
if (priv->hisregcpy & MRVDRV_CARDEVENT) {
lbs_deb_thread("main-thread: Card Event Activity\n");
Expand Down Expand Up @@ -922,35 +944,21 @@ static int lbs_setup_firmware(struct lbs_private *priv)
static void command_timer_fn(unsigned long data)
{
struct lbs_private *priv = (struct lbs_private *)data;
struct cmd_ctrl_node *node;
unsigned long flags;

node = priv->cur_cmd;
if (node == NULL) {
lbs_deb_fw("ptempnode empty\n");
return;
}
spin_lock_irqsave(&priv->driver_lock, flags);

if (!node->cmdbuf) {
lbs_deb_fw("cmd is NULL\n");
return;
if (!priv->cur_cmd) {
lbs_pr_info("Command timer expired; no pending command\n");
goto out;
}

lbs_pr_info("command %x timed out\n", le16_to_cpu(node->cmdbuf->command));

if (!priv->fw_ready)
return;

spin_lock_irqsave(&priv->driver_lock, flags);
priv->cur_cmd = NULL;
spin_unlock_irqrestore(&priv->driver_lock, flags);

lbs_deb_fw("re-sending same command because of timeout\n");
lbs_queue_cmd(priv, node, 0);
lbs_pr_info("Command %x timed out\n", le16_to_cpu(priv->cur_cmd->cmdbuf->command));

priv->cmd_timed_out = 1;
wake_up_interruptible(&priv->waitq);

return;
out:
spin_unlock_irqrestore(&priv->driver_lock, flags);
}

static int lbs_init_adapter(struct lbs_private *priv)
Expand Down

0 comments on commit 2a34509

Please sign in to comment.