|
@@ -45,14 +45,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
|
|
|
|
|
|
static void if_usb_receive(struct urb *urb);
|
|
|
static void if_usb_receive_fwload(struct urb *urb);
|
|
|
-static int if_usb_register_dev(wlan_private * priv);
|
|
|
-static int if_usb_unregister_dev(wlan_private *);
|
|
|
-static int if_usb_prog_firmware(wlan_private *);
|
|
|
+static int if_usb_prog_firmware(struct usb_card_rec *cardp);
|
|
|
static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
|
|
|
static int if_usb_get_int_status(wlan_private * priv, u8 *);
|
|
|
static int if_usb_read_event_cause(wlan_private *);
|
|
|
-static int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb);
|
|
|
+static int usb_tx_block(struct usb_card_rec *cardp, u8 *payload, u16 nb);
|
|
|
static void if_usb_free(struct usb_card_rec *cardp);
|
|
|
+static int if_usb_submit_rx_urb(struct usb_card_rec *cardp);
|
|
|
+static int if_usb_reset_device(struct usb_card_rec *cardp);
|
|
|
|
|
|
/**
|
|
|
* @brief call back function to handle the status of the URB
|
|
@@ -61,29 +61,40 @@ static void if_usb_free(struct usb_card_rec *cardp);
|
|
|
*/
|
|
|
static void if_usb_write_bulk_callback(struct urb *urb)
|
|
|
{
|
|
|
- wlan_private *priv = (wlan_private *) (urb->context);
|
|
|
- wlan_adapter *adapter = priv->adapter;
|
|
|
- struct net_device *dev = priv->dev;
|
|
|
+ struct usb_card_rec *cardp = (struct usb_card_rec *) urb->context;
|
|
|
|
|
|
/* handle the transmission complete validations */
|
|
|
|
|
|
- if (urb->status != 0) {
|
|
|
- /* print the failure status number for debug */
|
|
|
- lbs_pr_info("URB in failure status: %d\n", urb->status);
|
|
|
- } else {
|
|
|
+ if (urb->status == 0) {
|
|
|
+ wlan_private *priv = cardp->priv;
|
|
|
+
|
|
|
/*
|
|
|
lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n");
|
|
|
lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n",
|
|
|
urb->actual_length);
|
|
|
*/
|
|
|
- priv->dnld_sent = DNLD_RES_RECEIVED;
|
|
|
- /* Wake main thread if commands are pending */
|
|
|
- if (!adapter->cur_cmd)
|
|
|
- wake_up_interruptible(&priv->waitq);
|
|
|
- if ((adapter->connect_status == LIBERTAS_CONNECTED)) {
|
|
|
- netif_wake_queue(dev);
|
|
|
- netif_wake_queue(priv->mesh_dev);
|
|
|
+
|
|
|
+ /* Used for both firmware TX and regular TX. priv isn't
|
|
|
+ * valid at firmware load time.
|
|
|
+ */
|
|
|
+ if (priv) {
|
|
|
+ wlan_adapter *adapter = priv->adapter;
|
|
|
+ struct net_device *dev = priv->dev;
|
|
|
+
|
|
|
+ priv->dnld_sent = DNLD_RES_RECEIVED;
|
|
|
+
|
|
|
+ /* Wake main thread if commands are pending */
|
|
|
+ if (!adapter->cur_cmd)
|
|
|
+ wake_up_interruptible(&priv->waitq);
|
|
|
+
|
|
|
+ if ((adapter->connect_status == LIBERTAS_CONNECTED)) {
|
|
|
+ netif_wake_queue(dev);
|
|
|
+ netif_wake_queue(priv->mesh_dev);
|
|
|
+ }
|
|
|
}
|
|
|
+ } else {
|
|
|
+ /* print the failure status number for debug */
|
|
|
+ lbs_pr_info("URB in failure status: %d\n", urb->status);
|
|
|
}
|
|
|
|
|
|
return;
|
|
@@ -205,24 +216,35 @@ static int if_usb_probe(struct usb_interface *intf,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* Upload firmware */
|
|
|
+ cardp->rinfo.cardp = cardp;
|
|
|
+ if (if_usb_prog_firmware(cardp)) {
|
|
|
+ lbs_deb_usbd(&udev->dev, "FW upload failed");
|
|
|
+ goto err_prog_firmware;
|
|
|
+ }
|
|
|
+
|
|
|
if (!(priv = libertas_add_card(cardp, &udev->dev)))
|
|
|
- goto dealloc;
|
|
|
+ goto err_prog_firmware;
|
|
|
|
|
|
- udev->dev.driver_data = priv;
|
|
|
+ cardp->priv = priv;
|
|
|
|
|
|
if (libertas_add_mesh(priv, &udev->dev))
|
|
|
goto err_add_mesh;
|
|
|
|
|
|
- priv->hw_register_dev = if_usb_register_dev;
|
|
|
- priv->hw_unregister_dev = if_usb_unregister_dev;
|
|
|
- priv->hw_prog_firmware = if_usb_prog_firmware;
|
|
|
+ cardp->eth_dev = priv->dev;
|
|
|
+
|
|
|
priv->hw_host_to_card = if_usb_host_to_card;
|
|
|
priv->hw_get_int_status = if_usb_get_int_status;
|
|
|
priv->hw_read_event_cause = if_usb_read_event_cause;
|
|
|
priv->boot2_version = udev->descriptor.bcdDevice;
|
|
|
|
|
|
- if (libertas_activate_card(priv))
|
|
|
- goto err_activate_card;
|
|
|
+ /* Delay 200 ms to waiting for the FW ready */
|
|
|
+ if_usb_submit_rx_urb(cardp);
|
|
|
+ msleep_interruptible(200);
|
|
|
+ priv->adapter->fw_ready = 1;
|
|
|
+
|
|
|
+ if (libertas_start_card(priv))
|
|
|
+ goto err_start_card;
|
|
|
|
|
|
list_add_tail(&cardp->list, &usb_devices);
|
|
|
|
|
@@ -231,11 +253,12 @@ static int if_usb_probe(struct usb_interface *intf,
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
-err_activate_card:
|
|
|
+err_start_card:
|
|
|
libertas_remove_mesh(priv);
|
|
|
err_add_mesh:
|
|
|
- free_netdev(priv->dev);
|
|
|
- kfree(priv->adapter);
|
|
|
+ libertas_remove_card(priv);
|
|
|
+err_prog_firmware:
|
|
|
+ if_usb_reset_device(cardp);
|
|
|
dealloc:
|
|
|
if_usb_free(cardp);
|
|
|
|
|
@@ -252,21 +275,22 @@ static void if_usb_disconnect(struct usb_interface *intf)
|
|
|
{
|
|
|
struct usb_card_rec *cardp = usb_get_intfdata(intf);
|
|
|
wlan_private *priv = (wlan_private *) cardp->priv;
|
|
|
- wlan_adapter *adapter = NULL;
|
|
|
|
|
|
- adapter = priv->adapter;
|
|
|
+ lbs_deb_enter(LBS_DEB_MAIN);
|
|
|
|
|
|
- /*
|
|
|
- * Update Surprise removed to TRUE
|
|
|
- */
|
|
|
- adapter->surpriseremoved = 1;
|
|
|
+ /* Update Surprise removed to TRUE */
|
|
|
+ cardp->surprise_removed = 1;
|
|
|
|
|
|
list_del(&cardp->list);
|
|
|
|
|
|
- /* card is removed and we can call wlan_remove_card */
|
|
|
- lbs_deb_usbd(&cardp->udev->dev, "call remove card\n");
|
|
|
- libertas_remove_mesh(priv);
|
|
|
- libertas_remove_card(priv);
|
|
|
+ if (priv) {
|
|
|
+ wlan_adapter *adapter = priv->adapter;
|
|
|
+
|
|
|
+ adapter->surpriseremoved = 1;
|
|
|
+ libertas_stop_card(priv);
|
|
|
+ libertas_remove_mesh(priv);
|
|
|
+ libertas_remove_card(priv);
|
|
|
+ }
|
|
|
|
|
|
/* Unlink and free urb */
|
|
|
if_usb_free(cardp);
|
|
@@ -274,7 +298,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
|
|
|
usb_set_intfdata(intf, NULL);
|
|
|
usb_put_dev(interface_to_usbdev(intf));
|
|
|
|
|
|
- return;
|
|
|
+ lbs_deb_leave(LBS_DEB_MAIN);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -282,12 +306,11 @@ static void if_usb_disconnect(struct usb_interface *intf)
|
|
|
* @param priv pointer to wlan_private
|
|
|
* @return 0
|
|
|
*/
|
|
|
-static int if_prog_firmware(wlan_private * priv)
|
|
|
+static int if_prog_firmware(struct usb_card_rec *cardp)
|
|
|
{
|
|
|
- struct usb_card_rec *cardp = priv->card;
|
|
|
struct FWData *fwdata;
|
|
|
struct fwheader *fwheader;
|
|
|
- u8 *firmware = priv->firmware->data;
|
|
|
+ u8 *firmware = cardp->fw->data;
|
|
|
|
|
|
fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);
|
|
|
|
|
@@ -335,7 +358,7 @@ static int if_prog_firmware(wlan_private * priv)
|
|
|
cardp->totalbytes);
|
|
|
*/
|
|
|
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
|
|
|
- usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
|
|
|
+ usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
|
|
|
|
|
|
} else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
|
|
|
/*
|
|
@@ -345,7 +368,7 @@ static int if_prog_firmware(wlan_private * priv)
|
|
|
"Donwloading FW JUMP BLOCK\n");
|
|
|
*/
|
|
|
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
|
|
|
- usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
|
|
|
+ usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
|
|
|
cardp->fwfinalblk = 1;
|
|
|
}
|
|
|
|
|
@@ -360,10 +383,10 @@ static int if_prog_firmware(wlan_private * priv)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int if_usb_reset_device(wlan_private *priv)
|
|
|
+static int if_usb_reset_device(struct usb_card_rec *cardp)
|
|
|
{
|
|
|
int ret;
|
|
|
- struct usb_card_rec *cardp = priv->card;
|
|
|
+ wlan_private * priv = cardp->priv;
|
|
|
|
|
|
lbs_deb_enter(LBS_DEB_USB);
|
|
|
|
|
@@ -371,7 +394,7 @@ static int if_usb_reset_device(wlan_private *priv)
|
|
|
* command to the firmware.
|
|
|
*/
|
|
|
ret = usb_reset_device(cardp->udev);
|
|
|
- if (!ret) {
|
|
|
+ if (!ret && priv) {
|
|
|
msleep(10);
|
|
|
ret = libertas_reset_device(priv);
|
|
|
msleep(10);
|
|
@@ -389,14 +412,12 @@ static int if_usb_reset_device(wlan_private *priv)
|
|
|
* @param nb data length
|
|
|
* @return 0 or -1
|
|
|
*/
|
|
|
-static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
|
|
|
+static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb)
|
|
|
{
|
|
|
- /* pointer to card structure */
|
|
|
- struct usb_card_rec *cardp = priv->card;
|
|
|
int ret = -1;
|
|
|
|
|
|
/* check if device is removed */
|
|
|
- if (priv->adapter->surpriseremoved) {
|
|
|
+ if (cardp->surprise_removed) {
|
|
|
lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
|
|
|
goto tx_ret;
|
|
|
}
|
|
@@ -404,7 +425,7 @@ static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
|
|
|
usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
|
|
|
usb_sndbulkpipe(cardp->udev,
|
|
|
cardp->bulk_out_endpointAddr),
|
|
|
- payload, nb, if_usb_write_bulk_callback, priv);
|
|
|
+ payload, nb, if_usb_write_bulk_callback, cardp);
|
|
|
|
|
|
cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
|
|
|
|
|
@@ -421,11 +442,9 @@ tx_ret:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int __if_usb_submit_rx_urb(wlan_private * priv,
|
|
|
- void (*callbackfn)
|
|
|
- (struct urb *urb))
|
|
|
+static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp,
|
|
|
+ void (*callbackfn)(struct urb *urb))
|
|
|
{
|
|
|
- struct usb_card_rec *cardp = priv->card;
|
|
|
struct sk_buff *skb;
|
|
|
struct read_cb_info *rinfo = &cardp->rinfo;
|
|
|
int ret = -1;
|
|
@@ -461,22 +480,21 @@ rx_ret:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static inline int if_usb_submit_rx_urb_fwload(wlan_private * priv)
|
|
|
+static int if_usb_submit_rx_urb_fwload(struct usb_card_rec *cardp)
|
|
|
{
|
|
|
- return __if_usb_submit_rx_urb(priv, &if_usb_receive_fwload);
|
|
|
+ return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
|
|
|
}
|
|
|
|
|
|
-static inline int if_usb_submit_rx_urb(wlan_private * priv)
|
|
|
+static int if_usb_submit_rx_urb(struct usb_card_rec *cardp)
|
|
|
{
|
|
|
- return __if_usb_submit_rx_urb(priv, &if_usb_receive);
|
|
|
+ return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
|
|
|
}
|
|
|
|
|
|
static void if_usb_receive_fwload(struct urb *urb)
|
|
|
{
|
|
|
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
|
|
|
- wlan_private *priv = rinfo->priv;
|
|
|
struct sk_buff *skb = rinfo->skb;
|
|
|
- struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
|
|
|
+ struct usb_card_rec *cardp = (struct usb_card_rec *)rinfo->cardp;
|
|
|
struct fwsyncheader *syncfwheader;
|
|
|
struct bootcmdrespStr bootcmdresp;
|
|
|
|
|
@@ -492,7 +510,7 @@ static void if_usb_receive_fwload(struct urb *urb)
|
|
|
sizeof(bootcmdresp));
|
|
|
if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
|
|
|
kfree_skb(skb);
|
|
|
- if_usb_submit_rx_urb_fwload(priv);
|
|
|
+ if_usb_submit_rx_urb_fwload(cardp);
|
|
|
cardp->bootcmdresp = 1;
|
|
|
lbs_deb_usbd(&cardp->udev->dev,
|
|
|
"Received valid boot command response\n");
|
|
@@ -516,7 +534,7 @@ static void if_usb_receive_fwload(struct urb *urb)
|
|
|
"Received valid boot command response\n");
|
|
|
}
|
|
|
kfree_skb(skb);
|
|
|
- if_usb_submit_rx_urb_fwload(priv);
|
|
|
+ if_usb_submit_rx_urb_fwload(cardp);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -552,9 +570,9 @@ static void if_usb_receive_fwload(struct urb *urb)
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- if_prog_firmware(priv);
|
|
|
+ if_prog_firmware(cardp);
|
|
|
|
|
|
- if_usb_submit_rx_urb_fwload(priv);
|
|
|
+ if_usb_submit_rx_urb_fwload(cardp);
|
|
|
exit:
|
|
|
kfree(syncfwheader);
|
|
|
|
|
@@ -633,9 +651,9 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
|
|
|
static void if_usb_receive(struct urb *urb)
|
|
|
{
|
|
|
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
|
|
|
- wlan_private *priv = rinfo->priv;
|
|
|
struct sk_buff *skb = rinfo->skb;
|
|
|
- struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
|
|
|
+ struct usb_card_rec *cardp = (struct usb_card_rec *) rinfo->cardp;
|
|
|
+ wlan_private * priv = cardp->priv;
|
|
|
|
|
|
int recvlength = urb->actual_length;
|
|
|
u8 *recvbuff = NULL;
|
|
@@ -696,7 +714,7 @@ static void if_usb_receive(struct urb *urb)
|
|
|
}
|
|
|
|
|
|
setup_for_next:
|
|
|
- if_usb_submit_rx_urb(priv);
|
|
|
+ if_usb_submit_rx_urb(cardp);
|
|
|
rx_exit:
|
|
|
lbs_deb_leave(LBS_DEB_USB);
|
|
|
}
|
|
@@ -731,7 +749,7 @@ static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 n
|
|
|
|
|
|
memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb);
|
|
|
|
|
|
- return usb_tx_block(priv, cardp->bulk_out_buffer,
|
|
|
+ return usb_tx_block(cardp, cardp->bulk_out_buffer,
|
|
|
nb + MESSAGE_HEADER_LEN);
|
|
|
}
|
|
|
|
|
@@ -751,46 +769,10 @@ static int if_usb_get_int_status(wlan_private * priv, u8 * ireg)
|
|
|
static int if_usb_read_event_cause(wlan_private * priv)
|
|
|
{
|
|
|
struct usb_card_rec *cardp = priv->card;
|
|
|
+
|
|
|
priv->adapter->eventcause = cardp->usb_event_cause;
|
|
|
/* Re-submit rx urb here to avoid event lost issue */
|
|
|
- if_usb_submit_rx_urb(priv);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int if_usb_unregister_dev(wlan_private * priv)
|
|
|
-{
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- /* Need to send a Reset command to device before USB resources freed
|
|
|
- * and wlan_remove_card() called, then device can handle FW download
|
|
|
- * again.
|
|
|
- */
|
|
|
- if (priv)
|
|
|
- libertas_reset_device(priv);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * @brief This function register usb device and initialize parameter
|
|
|
- * @param priv pointer to wlan_private
|
|
|
- * @return 0 or -1
|
|
|
- */
|
|
|
-static int if_usb_register_dev(wlan_private * priv)
|
|
|
-{
|
|
|
- struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
|
|
|
-
|
|
|
- lbs_deb_enter(LBS_DEB_USB);
|
|
|
-
|
|
|
- cardp->priv = priv;
|
|
|
- cardp->eth_dev = priv->dev;
|
|
|
- priv->hotplug_device = &(cardp->udev->dev);
|
|
|
-
|
|
|
- lbs_deb_usbd(&cardp->udev->dev, "udev pointer is at %p\n",
|
|
|
- cardp->udev);
|
|
|
-
|
|
|
- lbs_deb_leave(LBS_DEB_USB);
|
|
|
+ if_usb_submit_rx_urb(cardp);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -800,10 +782,9 @@ static int if_usb_register_dev(wlan_private * priv)
|
|
|
* 2:Boot from FW in EEPROM
|
|
|
* @return 0
|
|
|
*/
|
|
|
-static int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
|
|
|
+static int if_usb_issue_boot_command(struct usb_card_rec *cardp, int ivalue)
|
|
|
{
|
|
|
- struct usb_card_rec *cardp = priv->card;
|
|
|
- struct bootcmdstr sbootcmd;
|
|
|
+ struct bootcmdstr sbootcmd;
|
|
|
int i;
|
|
|
|
|
|
/* Prepare command */
|
|
@@ -814,28 +795,83 @@ static int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
|
|
|
memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr));
|
|
|
|
|
|
/* Issue command */
|
|
|
- usb_tx_block(priv, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
|
|
|
+ usb_tx_block(cardp, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
-static int if_usb_do_prog_firmware(wlan_private * priv)
|
|
|
+/**
|
|
|
+ * @brief This function checks the validity of Boot2/FW image.
|
|
|
+ *
|
|
|
+ * @param data pointer to image
|
|
|
+ * len image length
|
|
|
+ * @return 0 or -1
|
|
|
+ */
|
|
|
+static int check_fwfile_format(u8 *data, u32 totlen)
|
|
|
+{
|
|
|
+ u32 bincmd, exit;
|
|
|
+ u32 blksize, offset, len;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = 1;
|
|
|
+ exit = len = 0;
|
|
|
+
|
|
|
+ do {
|
|
|
+ struct fwheader *fwh = (void *)data;
|
|
|
+
|
|
|
+ bincmd = le32_to_cpu(fwh->dnldcmd);
|
|
|
+ blksize = le32_to_cpu(fwh->datalength);
|
|
|
+ switch (bincmd) {
|
|
|
+ case FW_HAS_DATA_TO_RECV:
|
|
|
+ offset = sizeof(struct fwheader) + blksize;
|
|
|
+ data += offset;
|
|
|
+ len += offset;
|
|
|
+ if (len >= totlen)
|
|
|
+ exit = 1;
|
|
|
+ break;
|
|
|
+ case FW_HAS_LAST_BLOCK:
|
|
|
+ exit = 1;
|
|
|
+ ret = 0;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ exit = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } while (!exit);
|
|
|
+
|
|
|
+ if (ret)
|
|
|
+ lbs_pr_err("firmware file format check FAIL\n");
|
|
|
+ else
|
|
|
+ lbs_deb_fw("firmware file format check PASS\n");
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int if_usb_prog_firmware(struct usb_card_rec *cardp)
|
|
|
{
|
|
|
- struct usb_card_rec *cardp = priv->card;
|
|
|
int i = 0;
|
|
|
static int reset_count = 10;
|
|
|
int ret = 0;
|
|
|
|
|
|
lbs_deb_enter(LBS_DEB_USB);
|
|
|
|
|
|
- cardp->rinfo.priv = priv;
|
|
|
+ if ((ret = request_firmware(&cardp->fw, libertas_fw_name,
|
|
|
+ &cardp->udev->dev)) < 0) {
|
|
|
+ lbs_pr_err("request_firmware() failed with %#x\n", ret);
|
|
|
+ lbs_pr_err("firmware %s not found\n", libertas_fw_name);
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
|
|
|
+ goto release_fw;
|
|
|
|
|
|
restart:
|
|
|
- if (if_usb_submit_rx_urb_fwload(priv) < 0) {
|
|
|
+ if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
|
|
|
lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
|
|
|
ret = -1;
|
|
|
- goto done;
|
|
|
+ goto release_fw;
|
|
|
}
|
|
|
|
|
|
cardp->bootcmdresp = 0;
|
|
@@ -843,7 +879,7 @@ restart:
|
|
|
int j = 0;
|
|
|
i++;
|
|
|
/* Issue Boot command = 1, Boot from Download-FW */
|
|
|
- if_usb_issue_boot_command(priv, BOOT_CMD_FW_BY_USB);
|
|
|
+ if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
|
|
|
/* wait for command response */
|
|
|
do {
|
|
|
j++;
|
|
@@ -853,14 +889,13 @@ restart:
|
|
|
|
|
|
if (cardp->bootcmdresp == 0) {
|
|
|
if (--reset_count >= 0) {
|
|
|
- if_usb_reset_device(priv);
|
|
|
+ if_usb_reset_device(cardp);
|
|
|
goto restart;
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
i = 0;
|
|
|
- priv->adapter->fw_ready = 0;
|
|
|
|
|
|
cardp->totalbytes = 0;
|
|
|
cardp->fwlastblksent = 0;
|
|
@@ -870,113 +905,37 @@ restart:
|
|
|
cardp->totalbytes = 0;
|
|
|
cardp->fwfinalblk = 0;
|
|
|
|
|
|
- if_prog_firmware(priv);
|
|
|
+ if_prog_firmware(cardp);
|
|
|
|
|
|
do {
|
|
|
lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n");
|
|
|
i++;
|
|
|
msleep_interruptible(100);
|
|
|
- if (priv->adapter->surpriseremoved || i >= 20)
|
|
|
+ if (cardp->surprise_removed || i >= 20)
|
|
|
break;
|
|
|
} while (!cardp->fwdnldover);
|
|
|
|
|
|
if (!cardp->fwdnldover) {
|
|
|
lbs_pr_info("failed to load fw, resetting device!\n");
|
|
|
if (--reset_count >= 0) {
|
|
|
- if_usb_reset_device(priv);
|
|
|
+ if_usb_reset_device(cardp);
|
|
|
goto restart;
|
|
|
}
|
|
|
|
|
|
lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
|
|
|
ret = -1;
|
|
|
- goto done;
|
|
|
+ goto release_fw;
|
|
|
}
|
|
|
|
|
|
- if_usb_submit_rx_urb(priv);
|
|
|
-
|
|
|
- /* Delay 200 ms to waiting for the FW ready */
|
|
|
- msleep_interruptible(200);
|
|
|
-
|
|
|
- priv->adapter->fw_ready = 1;
|
|
|
+release_fw:
|
|
|
+ release_firmware(cardp->fw);
|
|
|
+ cardp->fw = NULL;
|
|
|
|
|
|
done:
|
|
|
lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * @brief This function checks the validity of Boot2/FW image.
|
|
|
- *
|
|
|
- * @param data pointer to image
|
|
|
- * len image length
|
|
|
- * @return 0 or -1
|
|
|
- */
|
|
|
-static int check_fwfile_format(u8 *data, u32 totlen)
|
|
|
-{
|
|
|
- u32 bincmd, exit;
|
|
|
- u32 blksize, offset, len;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = 1;
|
|
|
- exit = len = 0;
|
|
|
-
|
|
|
- do {
|
|
|
- struct fwheader *fwh = (void *)data;
|
|
|
-
|
|
|
- bincmd = le32_to_cpu(fwh->dnldcmd);
|
|
|
- blksize = le32_to_cpu(fwh->datalength);
|
|
|
- switch (bincmd) {
|
|
|
- case FW_HAS_DATA_TO_RECV:
|
|
|
- offset = sizeof(struct fwheader) + blksize;
|
|
|
- data += offset;
|
|
|
- len += offset;
|
|
|
- if (len >= totlen)
|
|
|
- exit = 1;
|
|
|
- break;
|
|
|
- case FW_HAS_LAST_BLOCK:
|
|
|
- exit = 1;
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
- default:
|
|
|
- exit = 1;
|
|
|
- break;
|
|
|
- }
|
|
|
- } while (!exit);
|
|
|
-
|
|
|
- if (ret)
|
|
|
- lbs_pr_err("firmware file format check FAIL\n");
|
|
|
- else
|
|
|
- lbs_deb_fw("firmware file format check PASS\n");
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int if_usb_prog_firmware(wlan_private *priv)
|
|
|
-{
|
|
|
- int ret = -1;
|
|
|
-
|
|
|
- lbs_deb_enter(LBS_DEB_FW);
|
|
|
-
|
|
|
- if ((ret = request_firmware(&priv->firmware, libertas_fw_name,
|
|
|
- priv->hotplug_device)) < 0) {
|
|
|
- lbs_pr_err("request_firmware() failed with %#x\n", ret);
|
|
|
- lbs_pr_err("firmware %s not found\n", libertas_fw_name);
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- if (check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
|
|
|
- release_firmware(priv->firmware);
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- ret = if_usb_do_prog_firmware(priv);
|
|
|
-
|
|
|
- release_firmware(priv->firmware);
|
|
|
-done:
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
|
static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
|