diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-12-11 00:07:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:06:39 -0500 |
commit | 4f82f5c853e314dfe877b87b4c1e4b127ee9a34b (patch) | |
tree | 71f48875b74f1a0a0c010bb9b9cd37cb31d72f69 /drivers | |
parent | c8ba39d0605200c81f43c59418871e036d973685 (diff) |
libertas: switch to a waitqueue and timer for handling USB firmware load
No need to busy-wait, even if we did have a 100ms delay in the loop.
This makes it easier to support the new 'firmware ready' event which is
in the new firmware, too.
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/if_usb.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.h | 5 |
2 files changed, 31 insertions, 12 deletions
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 0a3795048c2c..a086653803fe 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -113,7 +113,18 @@ static void if_usb_set_boot2_ver(struct lbs_private *priv) | |||
113 | lbs_deb_usb("Setting boot2 version failed\n"); | 113 | lbs_deb_usb("Setting boot2 version failed\n"); |
114 | } | 114 | } |
115 | 115 | ||
116 | void if_usb_fw_timeo(unsigned long priv) | ||
117 | { | ||
118 | struct usb_card_rec *cardp = (void *)priv; | ||
116 | 119 | ||
120 | if (cardp->fwdnldover) { | ||
121 | lbs_deb_usb("Download complete, no event. Assuming success\n"); | ||
122 | } else { | ||
123 | lbs_pr_err("Download timed out\n"); | ||
124 | cardp->surprise_removed = 1; | ||
125 | } | ||
126 | wake_up(&cardp->fw_wq); | ||
127 | } | ||
117 | /** | 128 | /** |
118 | * @brief sets the configuration values | 129 | * @brief sets the configuration values |
119 | * @param ifnum interface number | 130 | * @param ifnum interface number |
@@ -138,6 +149,9 @@ static int if_usb_probe(struct usb_interface *intf, | |||
138 | goto error; | 149 | goto error; |
139 | } | 150 | } |
140 | 151 | ||
152 | setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp); | ||
153 | init_waitqueue_head(&cardp->fw_wq); | ||
154 | |||
141 | cardp->udev = udev; | 155 | cardp->udev = udev; |
142 | iface_desc = intf->cur_altsetting; | 156 | iface_desc = intf->cur_altsetting; |
143 | 157 | ||
@@ -296,7 +310,7 @@ static void if_usb_disconnect(struct usb_interface *intf) | |||
296 | * @param priv pointer to struct lbs_private | 310 | * @param priv pointer to struct lbs_private |
297 | * @return 0 | 311 | * @return 0 |
298 | */ | 312 | */ |
299 | static int if_prog_firmware(struct usb_card_rec *cardp) | 313 | static int if_usb_send_fw_pkt(struct usb_card_rec *cardp) |
300 | { | 314 | { |
301 | struct FWData *fwdata; | 315 | struct FWData *fwdata; |
302 | struct fwheader *fwheader; | 316 | struct fwheader *fwheader; |
@@ -566,19 +580,21 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
566 | 580 | ||
567 | kfree_skb(skb); | 581 | kfree_skb(skb); |
568 | 582 | ||
583 | /* reschedule timer for 200ms hence */ | ||
584 | mod_timer(&cardp->fw_timeout, jiffies + (HZ/5)); | ||
585 | |||
569 | if (cardp->fwfinalblk) { | 586 | if (cardp->fwfinalblk) { |
570 | cardp->fwdnldover = 1; | 587 | cardp->fwdnldover = 1; |
571 | goto exit; | 588 | goto exit; |
572 | } | 589 | } |
573 | 590 | ||
574 | if_prog_firmware(cardp); | 591 | if_usb_send_fw_pkt(cardp); |
575 | 592 | ||
576 | if_usb_submit_rx_urb_fwload(cardp); | 593 | if_usb_submit_rx_urb_fwload(cardp); |
577 | exit: | 594 | exit: |
578 | kfree(syncfwheader); | 595 | kfree(syncfwheader); |
579 | 596 | ||
580 | return; | 597 | return; |
581 | |||
582 | } | 598 | } |
583 | 599 | ||
584 | #define MRVDRV_MIN_PKT_LEN 30 | 600 | #define MRVDRV_MIN_PKT_LEN 30 |
@@ -911,15 +927,13 @@ restart: | |||
911 | cardp->totalbytes = 0; | 927 | cardp->totalbytes = 0; |
912 | cardp->fwfinalblk = 0; | 928 | cardp->fwfinalblk = 0; |
913 | 929 | ||
914 | if_prog_firmware(cardp); | 930 | /* Send the first firmware packet... */ |
931 | if_usb_send_fw_pkt(cardp); | ||
915 | 932 | ||
916 | do { | 933 | /* ... and wait for the process to complete */ |
917 | lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n"); | 934 | wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover); |
918 | i++; | 935 | |
919 | msleep_interruptible(100); | 936 | del_timer_sync(&cardp->fw_timeout); |
920 | if (cardp->surprise_removed || i >= 20) | ||
921 | break; | ||
922 | } while (!cardp->fwdnldover); | ||
923 | 937 | ||
924 | if (!cardp->fwdnldover) { | 938 | if (!cardp->fwdnldover) { |
925 | lbs_pr_info("failed to load fw, resetting device!\n"); | 939 | lbs_pr_info("failed to load fw, resetting device!\n"); |
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index 940a369f1fe7..224c957e292d 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h | |||
@@ -1,6 +1,9 @@ | |||
1 | #ifndef _LBS_IF_USB_H | 1 | #ifndef _LBS_IF_USB_H |
2 | #define _LBS_IF_USB_H | 2 | #define _LBS_IF_USB_H |
3 | 3 | ||
4 | #include <linux/wait.h> | ||
5 | #include <linux/timer.h> | ||
6 | |||
4 | /** | 7 | /** |
5 | * This file contains definition for USB interface. | 8 | * This file contains definition for USB interface. |
6 | */ | 9 | */ |
@@ -56,6 +59,8 @@ struct usb_card_rec { | |||
56 | u8 bulk_out_endpointAddr; | 59 | u8 bulk_out_endpointAddr; |
57 | 60 | ||
58 | const struct firmware *fw; | 61 | const struct firmware *fw; |
62 | struct timer_list fw_timeout; | ||
63 | wait_queue_head_t fw_wq; | ||
59 | u8 CRC_OK; | 64 | u8 CRC_OK; |
60 | u32 fwseqnum; | 65 | u32 fwseqnum; |
61 | u32 lastseqnum; | 66 | u32 lastseqnum; |