summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-12-11 00:07:58 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 15:06:39 -0800
commit4f82f5c853e314dfe877b87b4c1e4b127ee9a34b (patch)
tree71f48875b74f1a0a0c010bb9b9cd37cb31d72f69 /drivers/net
parentc8ba39d0605200c81f43c59418871e036d973685 (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/net')
-rw-r--r--drivers/net/wireless/libertas/if_usb.c38
-rw-r--r--drivers/net/wireless/libertas/if_usb.h5
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)
lbs_deb_usb("Setting boot2 version failed\n");
}
+void if_usb_fw_timeo(unsigned long priv)
+{
+ struct usb_card_rec *cardp = (void *)priv;
+ if (cardp->fwdnldover) {
+ lbs_deb_usb("Download complete, no event. Assuming success\n");
+ } else {
+ lbs_pr_err("Download timed out\n");
+ cardp->surprise_removed = 1;
+ }
+ wake_up(&cardp->fw_wq);
+}
/**
* @brief sets the configuration values
* @param ifnum interface number
@@ -138,6 +149,9 @@ static int if_usb_probe(struct usb_interface *intf,
goto error;
}
+ setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
+ init_waitqueue_head(&cardp->fw_wq);
+
cardp->udev = udev;
iface_desc = intf->cur_altsetting;
@@ -296,7 +310,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
* @param priv pointer to struct lbs_private
* @return 0
*/
-static int if_prog_firmware(struct usb_card_rec *cardp)
+static int if_usb_send_fw_pkt(struct usb_card_rec *cardp)
{
struct FWData *fwdata;
struct fwheader *fwheader;
@@ -566,19 +580,21 @@ static void if_usb_receive_fwload(struct urb *urb)
kfree_skb(skb);
+ /* reschedule timer for 200ms hence */
+ mod_timer(&cardp->fw_timeout, jiffies + (HZ/5));
+
if (cardp->fwfinalblk) {
cardp->fwdnldover = 1;
goto exit;
}
- if_prog_firmware(cardp);
+ if_usb_send_fw_pkt(cardp);
if_usb_submit_rx_urb_fwload(cardp);
-exit:
+ exit:
kfree(syncfwheader);
return;
-
}
#define MRVDRV_MIN_PKT_LEN 30
@@ -911,15 +927,13 @@ restart:
cardp->totalbytes = 0;
cardp->fwfinalblk = 0;
- if_prog_firmware(cardp);
+ /* Send the first firmware packet... */
+ if_usb_send_fw_pkt(cardp);
- do {
- lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n");
- i++;
- msleep_interruptible(100);
- if (cardp->surprise_removed || i >= 20)
- break;
- } while (!cardp->fwdnldover);
+ /* ... and wait for the process to complete */
+ wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover);
+
+ del_timer_sync(&cardp->fw_timeout);
if (!cardp->fwdnldover) {
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 @@
#ifndef _LBS_IF_USB_H
#define _LBS_IF_USB_H
+#include <linux/wait.h>
+#include <linux/timer.h>
+
/**
* This file contains definition for USB interface.
*/
@@ -56,6 +59,8 @@ struct usb_card_rec {
u8 bulk_out_endpointAddr;
const struct firmware *fw;
+ struct timer_list fw_timeout;
+ wait_queue_head_t fw_wq;
u8 CRC_OK;
u32 fwseqnum;
u32 lastseqnum;