aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-12-11 23:42:49 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:06:59 -0500
commite1258177e437cb8b892622f2b7beedd4701540ac (patch)
tree35addee654285e88ec1b49526cf3473427500f1e /drivers
parent06113c1c70349f5f888436ac2af28c707f4602ef (diff)
libertas: be more careful about command responses matching cur_cmd
Especially in the light of OLPC trac #5461, in which the firmware starts sending us seemingly random command responses which bear little relation to the command we sent it. Signed-off-by: David Woodhouse <dwmw2@infradead.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/libertas/cmd.c4
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c36
-rw-r--r--drivers/net/wireless/libertas/if_usb.c1
-rw-r--r--drivers/net/wireless/libertas/main.c2
4 files changed, 26 insertions, 17 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 1cb42dc90010..5ddb46a477a4 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -1216,8 +1216,8 @@ static int DownloadcommandToStation(struct lbs_private *priv,
1216 cmdsize = le16_to_cpu(cmd->size); 1216 cmdsize = le16_to_cpu(cmd->size);
1217 command = le16_to_cpu(cmd->command); 1217 command = le16_to_cpu(cmd->command);
1218 1218
1219 lbs_deb_host("DNLD_CMD: command 0x%04x, size %d, jiffies %lu\n", 1219 lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n",
1220 command, cmdsize, jiffies); 1220 command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies);
1221 lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); 1221 lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
1222 1222
1223 cmdnode->cmdwaitqwoken = 0; 1223 cmdnode->cmdwaitqwoken = 0;
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index bf9941ecc239..53f73c4abdd0 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -611,7 +611,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
611 611
612 default: 612 default:
613 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n", 613 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
614 resp->command); 614 le16_to_cpu(resp->command));
615 break; 615 break;
616 } 616 }
617 lbs_deb_leave(LBS_DEB_HOST); 617 lbs_deb_leave(LBS_DEB_HOST);
@@ -620,17 +620,14 @@ static inline int handle_cmd_response(struct lbs_private *priv,
620 620
621int lbs_process_rx_command(struct lbs_private *priv) 621int lbs_process_rx_command(struct lbs_private *priv)
622{ 622{
623 u16 respcmd; 623 uint16_t respcmd, curcmd;
624 struct cmd_header *resp; 624 struct cmd_header *resp;
625 int ret = 0; 625 int ret = 0;
626 ulong flags; 626 unsigned long flags;
627 u16 result; 627 uint16_t result;
628 628
629 lbs_deb_enter(LBS_DEB_HOST); 629 lbs_deb_enter(LBS_DEB_HOST);
630 630
631 /* Now we got response from FW, cancel the command timer */
632 del_timer(&priv->command_timer);
633
634 mutex_lock(&priv->lock); 631 mutex_lock(&priv->lock);
635 spin_lock_irqsave(&priv->driver_lock, flags); 632 spin_lock_irqsave(&priv->driver_lock, flags);
636 633
@@ -640,24 +637,35 @@ int lbs_process_rx_command(struct lbs_private *priv)
640 spin_unlock_irqrestore(&priv->driver_lock, flags); 637 spin_unlock_irqrestore(&priv->driver_lock, flags);
641 goto done; 638 goto done;
642 } 639 }
640
641 curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
642
643 resp = priv->cur_cmd->cmdbuf; 643 resp = priv->cur_cmd->cmdbuf;
644 644
645 respcmd = le16_to_cpu(resp->command); 645 respcmd = le16_to_cpu(resp->command);
646 result = le16_to_cpu(resp->result); 646 result = le16_to_cpu(resp->result);
647 647
648 lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n", 648 lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
649 respcmd, priv->upld_len, jiffies); 649 respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
650 lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len); 650 lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
651 651
652 if (!(respcmd & 0x8000)) { 652 if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
653 lbs_deb_host("invalid response!\n"); 653 lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
654 priv->cur_cmd_retcode = -1; 654 le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum));
655 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
656 priv->cur_cmd = NULL;
657 spin_unlock_irqrestore(&priv->driver_lock, flags); 655 spin_unlock_irqrestore(&priv->driver_lock, flags);
658 ret = -1; 656 ret = -1;
659 goto done; 657 goto done;
660 } 658 }
659 if (respcmd != CMD_RET(curcmd) &&
660 respcmd != CMD_802_11_ASSOCIATE && curcmd != CMD_RET_802_11_ASSOCIATE) {
661 lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
662 spin_unlock_irqrestore(&priv->driver_lock, flags);
663 ret = -1;
664 goto done;
665 }
666
667 /* Now we got response from FW, cancel the command timer */
668 del_timer(&priv->command_timer);
661 669
662 /* Store the response code to cur_cmd_retcode. */ 670 /* Store the response code to cur_cmd_retcode. */
663 priv->cur_cmd_retcode = result; 671 priv->cur_cmd_retcode = result;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 02192e8a15ea..6b8ac62e6f9a 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -643,6 +643,7 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
643 /* take care of cur_cmd = NULL case by reading the 643 /* take care of cur_cmd = NULL case by reading the
644 * data to clear the interrupt */ 644 * data to clear the interrupt */
645 if (!priv->cur_cmd) { 645 if (!priv->cur_cmd) {
646 lbs_deb_hex(LBS_DEB_HOST, "Unsolicited CMD_RESP", (void *) recvbuff + MESSAGE_HEADER_LEN, priv->upld_len);
646 cmdbuf = priv->upld_buf; 647 cmdbuf = priv->upld_buf;
647 priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY; 648 priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
648 } else 649 } else
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index bb685ac8e15e..cdf5934aaf8b 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -893,7 +893,7 @@ static void command_timer_fn(unsigned long data)
893 return; 893 return;
894 } 894 }
895 895
896 lbs_deb_fw("command_timer_fn fired, cmd %x\n", node->cmdbuf->command); 896 lbs_pr_info("command %x timed out\n", le16_to_cpu(node->cmdbuf->command));
897 897
898 if (!priv->fw_ready) 898 if (!priv->fw_ready)
899 return; 899 return;