diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/libertas/cmdresp.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 52 |
3 files changed, 38 insertions, 22 deletions
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 4c22e7849515..ef63c376c552 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -667,6 +667,12 @@ int lbs_process_rx_command(struct lbs_private *priv) | |||
667 | 667 | ||
668 | /* Now we got response from FW, cancel the command timer */ | 668 | /* Now we got response from FW, cancel the command timer */ |
669 | del_timer(&priv->command_timer); | 669 | del_timer(&priv->command_timer); |
670 | priv->cmd_timed_out = 0; | ||
671 | if (priv->nr_retries) { | ||
672 | lbs_pr_info("Received result %x to command %x after %d retries\n", | ||
673 | result, curcmd, priv->nr_retries); | ||
674 | priv->nr_retries = 0; | ||
675 | } | ||
670 | 676 | ||
671 | /* Store the response code to cur_cmd_retcode. */ | 677 | /* Store the response code to cur_cmd_retcode. */ |
672 | priv->cur_cmd_retcode = result; | 678 | priv->cur_cmd_retcode = result; |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index e6f553d5d2cf..465080fd0607 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -201,6 +201,8 @@ struct lbs_private { | |||
201 | 201 | ||
202 | /** Timers */ | 202 | /** Timers */ |
203 | struct timer_list command_timer; | 203 | struct timer_list command_timer; |
204 | int nr_retries; | ||
205 | int cmd_timed_out; | ||
204 | 206 | ||
205 | u8 hisregcpy; | 207 | u8 hisregcpy; |
206 | 208 | ||
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 839ffe818c18..9677b0d77160 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -670,6 +670,8 @@ static int lbs_thread(void *data) | |||
670 | shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ | 670 | shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ |
671 | else if (priv->intcounter) | 671 | else if (priv->intcounter) |
672 | shouldsleep = 0; /* Interrupt pending. Deal with it now */ | 672 | shouldsleep = 0; /* Interrupt pending. Deal with it now */ |
673 | else if (priv->cmd_timed_out) | ||
674 | shouldsleep = 0; /* Command timed out. Recover */ | ||
673 | else if (!priv->fw_ready) | 675 | else if (!priv->fw_ready) |
674 | shouldsleep = 1; /* Firmware not ready. We're waiting for it */ | 676 | shouldsleep = 1; /* Firmware not ready. We're waiting for it */ |
675 | else if (priv->dnld_sent) | 677 | else if (priv->dnld_sent) |
@@ -740,6 +742,26 @@ static int lbs_thread(void *data) | |||
740 | spin_lock_irq(&priv->driver_lock); | 742 | spin_lock_irq(&priv->driver_lock); |
741 | } | 743 | } |
742 | 744 | ||
745 | if (priv->cmd_timed_out && priv->cur_cmd) { | ||
746 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | ||
747 | |||
748 | if (++priv->nr_retries > 10) { | ||
749 | lbs_pr_info("Excessive timeouts submitting command %x\n", | ||
750 | le16_to_cpu(cmdnode->cmdbuf->command)); | ||
751 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); | ||
752 | priv->nr_retries = 0; | ||
753 | } else { | ||
754 | priv->cur_cmd = NULL; | ||
755 | lbs_pr_info("requeueing command %x due to timeout (#%d)\n", | ||
756 | le16_to_cpu(cmdnode->cmdbuf->command), priv->nr_retries); | ||
757 | |||
758 | /* Stick it back at the _top_ of the pending queue | ||
759 | for immediate resubmission */ | ||
760 | list_add(&cmdnode->list, &priv->cmdpendingq); | ||
761 | } | ||
762 | } | ||
763 | priv->cmd_timed_out = 0; | ||
764 | |||
743 | /* Any Card Event */ | 765 | /* Any Card Event */ |
744 | if (priv->hisregcpy & MRVDRV_CARDEVENT) { | 766 | if (priv->hisregcpy & MRVDRV_CARDEVENT) { |
745 | lbs_deb_thread("main-thread: Card Event Activity\n"); | 767 | lbs_deb_thread("main-thread: Card Event Activity\n"); |
@@ -922,35 +944,21 @@ done: | |||
922 | static void command_timer_fn(unsigned long data) | 944 | static void command_timer_fn(unsigned long data) |
923 | { | 945 | { |
924 | struct lbs_private *priv = (struct lbs_private *)data; | 946 | struct lbs_private *priv = (struct lbs_private *)data; |
925 | struct cmd_ctrl_node *node; | ||
926 | unsigned long flags; | 947 | unsigned long flags; |
927 | 948 | ||
928 | node = priv->cur_cmd; | 949 | spin_lock_irqsave(&priv->driver_lock, flags); |
929 | if (node == NULL) { | ||
930 | lbs_deb_fw("ptempnode empty\n"); | ||
931 | return; | ||
932 | } | ||
933 | 950 | ||
934 | if (!node->cmdbuf) { | 951 | if (!priv->cur_cmd) { |
935 | lbs_deb_fw("cmd is NULL\n"); | 952 | lbs_pr_info("Command timer expired; no pending command\n"); |
936 | return; | 953 | goto out; |
937 | } | 954 | } |
938 | 955 | ||
939 | lbs_pr_info("command %x timed out\n", le16_to_cpu(node->cmdbuf->command)); | 956 | lbs_pr_info("Command %x timed out\n", le16_to_cpu(priv->cur_cmd->cmdbuf->command)); |
940 | |||
941 | if (!priv->fw_ready) | ||
942 | return; | ||
943 | |||
944 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
945 | priv->cur_cmd = NULL; | ||
946 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
947 | |||
948 | lbs_deb_fw("re-sending same command because of timeout\n"); | ||
949 | lbs_queue_cmd(priv, node, 0); | ||
950 | 957 | ||
958 | priv->cmd_timed_out = 1; | ||
951 | wake_up_interruptible(&priv->waitq); | 959 | wake_up_interruptible(&priv->waitq); |
952 | 960 | out: | |
953 | return; | 961 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
954 | } | 962 | } |
955 | 963 | ||
956 | static int lbs_init_adapter(struct lbs_private *priv) | 964 | static int lbs_init_adapter(struct lbs_private *priv) |