aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/if_usb.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2007-08-20 11:43:25 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:50:34 -0400
commit954ee164f4f4598afc172c0ec3865d0352e55a0b (patch)
tree51aae73210d22c0a91282a52b5198cfa1ad068b4 /drivers/net/wireless/libertas/if_usb.c
parentb1b1907dceadddc7d7317f8ae85a5efec44125d8 (diff)
[PATCH] libertas: reorganize and simplify init sequence
This patch moves all firmware load responsibility into the interface-specific code and gets rid of the firmware pointer in the generic card structure. It also removes 3 fairly unecessary callbacks: hw_register_dev, hw_unregister_dev, and hw_prog_firmware. It also makes the init sequence from interface probe functions more logical, as there are paired add/remove and start/stop calls into generic libertas code. Because the USB driver code uses the same TX URB callback for both firmware upload (where the generic libertas structure isn't initialized yet) and for normal operation (where it is), some bits of USB code have to deal with 'priv' being NULL. All USB firmware upload bits have been changed to not require 'priv' at all, but simply the USB card structure. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/if_usb.c')
-rw-r--r--drivers/net/wireless/libertas/if_usb.c365
1 files changed, 162 insertions, 203 deletions
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 364eae374b93..105a00a7025d 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -45,14 +45,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
45 45
46static void if_usb_receive(struct urb *urb); 46static void if_usb_receive(struct urb *urb);
47static void if_usb_receive_fwload(struct urb *urb); 47static void if_usb_receive_fwload(struct urb *urb);
48static int if_usb_register_dev(wlan_private * priv); 48static int if_usb_prog_firmware(struct usb_card_rec *cardp);
49static int if_usb_unregister_dev(wlan_private *);
50static int if_usb_prog_firmware(wlan_private *);
51static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb); 49static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
52static int if_usb_get_int_status(wlan_private * priv, u8 *); 50static int if_usb_get_int_status(wlan_private * priv, u8 *);
53static int if_usb_read_event_cause(wlan_private *); 51static int if_usb_read_event_cause(wlan_private *);
54static int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb); 52static int usb_tx_block(struct usb_card_rec *cardp, u8 *payload, u16 nb);
55static void if_usb_free(struct usb_card_rec *cardp); 53static void if_usb_free(struct usb_card_rec *cardp);
54static int if_usb_submit_rx_urb(struct usb_card_rec *cardp);
55static int if_usb_reset_device(struct usb_card_rec *cardp);
56 56
57/** 57/**
58 * @brief call back function to handle the status of the URB 58 * @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);
61 */ 61 */
62static void if_usb_write_bulk_callback(struct urb *urb) 62static void if_usb_write_bulk_callback(struct urb *urb)
63{ 63{
64 wlan_private *priv = (wlan_private *) (urb->context); 64 struct usb_card_rec *cardp = (struct usb_card_rec *) urb->context;
65 wlan_adapter *adapter = priv->adapter;
66 struct net_device *dev = priv->dev;
67 65
68 /* handle the transmission complete validations */ 66 /* handle the transmission complete validations */
69 67
70 if (urb->status != 0) { 68 if (urb->status == 0) {
71 /* print the failure status number for debug */ 69 wlan_private *priv = cardp->priv;
72 lbs_pr_info("URB in failure status: %d\n", urb->status); 70
73 } else {
74 /* 71 /*
75 lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n"); 72 lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n");
76 lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n", 73 lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n",
77 urb->actual_length); 74 urb->actual_length);
78 */ 75 */
79 priv->dnld_sent = DNLD_RES_RECEIVED; 76
80 /* Wake main thread if commands are pending */ 77 /* Used for both firmware TX and regular TX. priv isn't
81 if (!adapter->cur_cmd) 78 * valid at firmware load time.
82 wake_up_interruptible(&priv->waitq); 79 */
83 if ((adapter->connect_status == LIBERTAS_CONNECTED)) { 80 if (priv) {
84 netif_wake_queue(dev); 81 wlan_adapter *adapter = priv->adapter;
85 netif_wake_queue(priv->mesh_dev); 82 struct net_device *dev = priv->dev;
83
84 priv->dnld_sent = DNLD_RES_RECEIVED;
85
86 /* Wake main thread if commands are pending */
87 if (!adapter->cur_cmd)
88 wake_up_interruptible(&priv->waitq);
89
90 if ((adapter->connect_status == LIBERTAS_CONNECTED)) {
91 netif_wake_queue(dev);
92 netif_wake_queue(priv->mesh_dev);
93 }
86 } 94 }
95 } else {
96 /* print the failure status number for debug */
97 lbs_pr_info("URB in failure status: %d\n", urb->status);
87 } 98 }
88 99
89 return; 100 return;
@@ -205,24 +216,35 @@ static int if_usb_probe(struct usb_interface *intf,
205 } 216 }
206 } 217 }
207 218
219 /* Upload firmware */
220 cardp->rinfo.cardp = cardp;
221 if (if_usb_prog_firmware(cardp)) {
222 lbs_deb_usbd(&udev->dev, "FW upload failed");
223 goto err_prog_firmware;
224 }
225
208 if (!(priv = libertas_add_card(cardp, &udev->dev))) 226 if (!(priv = libertas_add_card(cardp, &udev->dev)))
209 goto dealloc; 227 goto err_prog_firmware;
210 228
211 udev->dev.driver_data = priv; 229 cardp->priv = priv;
212 230
213 if (libertas_add_mesh(priv, &udev->dev)) 231 if (libertas_add_mesh(priv, &udev->dev))
214 goto err_add_mesh; 232 goto err_add_mesh;
215 233
216 priv->hw_register_dev = if_usb_register_dev; 234 cardp->eth_dev = priv->dev;
217 priv->hw_unregister_dev = if_usb_unregister_dev; 235
218 priv->hw_prog_firmware = if_usb_prog_firmware;
219 priv->hw_host_to_card = if_usb_host_to_card; 236 priv->hw_host_to_card = if_usb_host_to_card;
220 priv->hw_get_int_status = if_usb_get_int_status; 237 priv->hw_get_int_status = if_usb_get_int_status;
221 priv->hw_read_event_cause = if_usb_read_event_cause; 238 priv->hw_read_event_cause = if_usb_read_event_cause;
222 priv->boot2_version = udev->descriptor.bcdDevice; 239 priv->boot2_version = udev->descriptor.bcdDevice;
223 240
224 if (libertas_activate_card(priv)) 241 /* Delay 200 ms to waiting for the FW ready */
225 goto err_activate_card; 242 if_usb_submit_rx_urb(cardp);
243 msleep_interruptible(200);
244 priv->adapter->fw_ready = 1;
245
246 if (libertas_start_card(priv))
247 goto err_start_card;
226 248
227 list_add_tail(&cardp->list, &usb_devices); 249 list_add_tail(&cardp->list, &usb_devices);
228 250
@@ -231,11 +253,12 @@ static int if_usb_probe(struct usb_interface *intf,
231 253
232 return 0; 254 return 0;
233 255
234err_activate_card: 256err_start_card:
235 libertas_remove_mesh(priv); 257 libertas_remove_mesh(priv);
236err_add_mesh: 258err_add_mesh:
237 free_netdev(priv->dev); 259 libertas_remove_card(priv);
238 kfree(priv->adapter); 260err_prog_firmware:
261 if_usb_reset_device(cardp);
239dealloc: 262dealloc:
240 if_usb_free(cardp); 263 if_usb_free(cardp);
241 264
@@ -252,21 +275,22 @@ static void if_usb_disconnect(struct usb_interface *intf)
252{ 275{
253 struct usb_card_rec *cardp = usb_get_intfdata(intf); 276 struct usb_card_rec *cardp = usb_get_intfdata(intf);
254 wlan_private *priv = (wlan_private *) cardp->priv; 277 wlan_private *priv = (wlan_private *) cardp->priv;
255 wlan_adapter *adapter = NULL;
256 278
257 adapter = priv->adapter; 279 lbs_deb_enter(LBS_DEB_MAIN);
258 280
259 /* 281 /* Update Surprise removed to TRUE */
260 * Update Surprise removed to TRUE 282 cardp->surprise_removed = 1;
261 */
262 adapter->surpriseremoved = 1;
263 283
264 list_del(&cardp->list); 284 list_del(&cardp->list);
265 285
266 /* card is removed and we can call wlan_remove_card */ 286 if (priv) {
267 lbs_deb_usbd(&cardp->udev->dev, "call remove card\n"); 287 wlan_adapter *adapter = priv->adapter;
268 libertas_remove_mesh(priv); 288
269 libertas_remove_card(priv); 289 adapter->surpriseremoved = 1;
290 libertas_stop_card(priv);
291 libertas_remove_mesh(priv);
292 libertas_remove_card(priv);
293 }
270 294
271 /* Unlink and free urb */ 295 /* Unlink and free urb */
272 if_usb_free(cardp); 296 if_usb_free(cardp);
@@ -274,7 +298,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
274 usb_set_intfdata(intf, NULL); 298 usb_set_intfdata(intf, NULL);
275 usb_put_dev(interface_to_usbdev(intf)); 299 usb_put_dev(interface_to_usbdev(intf));
276 300
277 return; 301 lbs_deb_leave(LBS_DEB_MAIN);
278} 302}
279 303
280/** 304/**
@@ -282,12 +306,11 @@ static void if_usb_disconnect(struct usb_interface *intf)
282 * @param priv pointer to wlan_private 306 * @param priv pointer to wlan_private
283 * @return 0 307 * @return 0
284 */ 308 */
285static int if_prog_firmware(wlan_private * priv) 309static int if_prog_firmware(struct usb_card_rec *cardp)
286{ 310{
287 struct usb_card_rec *cardp = priv->card;
288 struct FWData *fwdata; 311 struct FWData *fwdata;
289 struct fwheader *fwheader; 312 struct fwheader *fwheader;
290 u8 *firmware = priv->firmware->data; 313 u8 *firmware = cardp->fw->data;
291 314
292 fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC); 315 fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);
293 316
@@ -335,7 +358,7 @@ static int if_prog_firmware(wlan_private * priv)
335 cardp->totalbytes); 358 cardp->totalbytes);
336 */ 359 */
337 memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE); 360 memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
338 usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); 361 usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
339 362
340 } else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { 363 } else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
341 /* 364 /*
@@ -345,7 +368,7 @@ static int if_prog_firmware(wlan_private * priv)
345 "Donwloading FW JUMP BLOCK\n"); 368 "Donwloading FW JUMP BLOCK\n");
346 */ 369 */
347 memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE); 370 memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
348 usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); 371 usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
349 cardp->fwfinalblk = 1; 372 cardp->fwfinalblk = 1;
350 } 373 }
351 374
@@ -360,10 +383,10 @@ static int if_prog_firmware(wlan_private * priv)
360 return 0; 383 return 0;
361} 384}
362 385
363static int if_usb_reset_device(wlan_private *priv) 386static int if_usb_reset_device(struct usb_card_rec *cardp)
364{ 387{
365 int ret; 388 int ret;
366 struct usb_card_rec *cardp = priv->card; 389 wlan_private * priv = cardp->priv;
367 390
368 lbs_deb_enter(LBS_DEB_USB); 391 lbs_deb_enter(LBS_DEB_USB);
369 392
@@ -371,7 +394,7 @@ static int if_usb_reset_device(wlan_private *priv)
371 * command to the firmware. 394 * command to the firmware.
372 */ 395 */
373 ret = usb_reset_device(cardp->udev); 396 ret = usb_reset_device(cardp->udev);
374 if (!ret) { 397 if (!ret && priv) {
375 msleep(10); 398 msleep(10);
376 ret = libertas_reset_device(priv); 399 ret = libertas_reset_device(priv);
377 msleep(10); 400 msleep(10);
@@ -389,14 +412,12 @@ static int if_usb_reset_device(wlan_private *priv)
389 * @param nb data length 412 * @param nb data length
390 * @return 0 or -1 413 * @return 0 or -1
391 */ 414 */
392static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb) 415static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb)
393{ 416{
394 /* pointer to card structure */
395 struct usb_card_rec *cardp = priv->card;
396 int ret = -1; 417 int ret = -1;
397 418
398 /* check if device is removed */ 419 /* check if device is removed */
399 if (priv->adapter->surpriseremoved) { 420 if (cardp->surprise_removed) {
400 lbs_deb_usbd(&cardp->udev->dev, "Device removed\n"); 421 lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
401 goto tx_ret; 422 goto tx_ret;
402 } 423 }
@@ -404,7 +425,7 @@ static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
404 usb_fill_bulk_urb(cardp->tx_urb, cardp->udev, 425 usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
405 usb_sndbulkpipe(cardp->udev, 426 usb_sndbulkpipe(cardp->udev,
406 cardp->bulk_out_endpointAddr), 427 cardp->bulk_out_endpointAddr),
407 payload, nb, if_usb_write_bulk_callback, priv); 428 payload, nb, if_usb_write_bulk_callback, cardp);
408 429
409 cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET; 430 cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
410 431
@@ -421,11 +442,9 @@ tx_ret:
421 return ret; 442 return ret;
422} 443}
423 444
424static int __if_usb_submit_rx_urb(wlan_private * priv, 445static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp,
425 void (*callbackfn) 446 void (*callbackfn)(struct urb *urb))
426 (struct urb *urb))
427{ 447{
428 struct usb_card_rec *cardp = priv->card;
429 struct sk_buff *skb; 448 struct sk_buff *skb;
430 struct read_cb_info *rinfo = &cardp->rinfo; 449 struct read_cb_info *rinfo = &cardp->rinfo;
431 int ret = -1; 450 int ret = -1;
@@ -461,22 +480,21 @@ rx_ret:
461 return ret; 480 return ret;
462} 481}
463 482
464static inline int if_usb_submit_rx_urb_fwload(wlan_private * priv) 483static int if_usb_submit_rx_urb_fwload(struct usb_card_rec *cardp)
465{ 484{
466 return __if_usb_submit_rx_urb(priv, &if_usb_receive_fwload); 485 return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
467} 486}
468 487
469static inline int if_usb_submit_rx_urb(wlan_private * priv) 488static int if_usb_submit_rx_urb(struct usb_card_rec *cardp)
470{ 489{
471 return __if_usb_submit_rx_urb(priv, &if_usb_receive); 490 return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
472} 491}
473 492
474static void if_usb_receive_fwload(struct urb *urb) 493static void if_usb_receive_fwload(struct urb *urb)
475{ 494{
476 struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; 495 struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
477 wlan_private *priv = rinfo->priv;
478 struct sk_buff *skb = rinfo->skb; 496 struct sk_buff *skb = rinfo->skb;
479 struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; 497 struct usb_card_rec *cardp = (struct usb_card_rec *)rinfo->cardp;
480 struct fwsyncheader *syncfwheader; 498 struct fwsyncheader *syncfwheader;
481 struct bootcmdrespStr bootcmdresp; 499 struct bootcmdrespStr bootcmdresp;
482 500
@@ -492,7 +510,7 @@ static void if_usb_receive_fwload(struct urb *urb)
492 sizeof(bootcmdresp)); 510 sizeof(bootcmdresp));
493 if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) { 511 if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
494 kfree_skb(skb); 512 kfree_skb(skb);
495 if_usb_submit_rx_urb_fwload(priv); 513 if_usb_submit_rx_urb_fwload(cardp);
496 cardp->bootcmdresp = 1; 514 cardp->bootcmdresp = 1;
497 lbs_deb_usbd(&cardp->udev->dev, 515 lbs_deb_usbd(&cardp->udev->dev,
498 "Received valid boot command response\n"); 516 "Received valid boot command response\n");
@@ -516,7 +534,7 @@ static void if_usb_receive_fwload(struct urb *urb)
516 "Received valid boot command response\n"); 534 "Received valid boot command response\n");
517 } 535 }
518 kfree_skb(skb); 536 kfree_skb(skb);
519 if_usb_submit_rx_urb_fwload(priv); 537 if_usb_submit_rx_urb_fwload(cardp);
520 return; 538 return;
521 } 539 }
522 540
@@ -552,9 +570,9 @@ static void if_usb_receive_fwload(struct urb *urb)
552 goto exit; 570 goto exit;
553 } 571 }
554 572
555 if_prog_firmware(priv); 573 if_prog_firmware(cardp);
556 574
557 if_usb_submit_rx_urb_fwload(priv); 575 if_usb_submit_rx_urb_fwload(cardp);
558exit: 576exit:
559 kfree(syncfwheader); 577 kfree(syncfwheader);
560 578
@@ -633,9 +651,9 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
633static void if_usb_receive(struct urb *urb) 651static void if_usb_receive(struct urb *urb)
634{ 652{
635 struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; 653 struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
636 wlan_private *priv = rinfo->priv;
637 struct sk_buff *skb = rinfo->skb; 654 struct sk_buff *skb = rinfo->skb;
638 struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; 655 struct usb_card_rec *cardp = (struct usb_card_rec *) rinfo->cardp;
656 wlan_private * priv = cardp->priv;
639 657
640 int recvlength = urb->actual_length; 658 int recvlength = urb->actual_length;
641 u8 *recvbuff = NULL; 659 u8 *recvbuff = NULL;
@@ -696,7 +714,7 @@ static void if_usb_receive(struct urb *urb)
696 } 714 }
697 715
698setup_for_next: 716setup_for_next:
699 if_usb_submit_rx_urb(priv); 717 if_usb_submit_rx_urb(cardp);
700rx_exit: 718rx_exit:
701 lbs_deb_leave(LBS_DEB_USB); 719 lbs_deb_leave(LBS_DEB_USB);
702} 720}
@@ -731,7 +749,7 @@ static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 n
731 749
732 memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb); 750 memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb);
733 751
734 return usb_tx_block(priv, cardp->bulk_out_buffer, 752 return usb_tx_block(cardp, cardp->bulk_out_buffer,
735 nb + MESSAGE_HEADER_LEN); 753 nb + MESSAGE_HEADER_LEN);
736} 754}
737 755
@@ -751,46 +769,10 @@ static int if_usb_get_int_status(wlan_private * priv, u8 * ireg)
751static int if_usb_read_event_cause(wlan_private * priv) 769static int if_usb_read_event_cause(wlan_private * priv)
752{ 770{
753 struct usb_card_rec *cardp = priv->card; 771 struct usb_card_rec *cardp = priv->card;
772
754 priv->adapter->eventcause = cardp->usb_event_cause; 773 priv->adapter->eventcause = cardp->usb_event_cause;
755 /* Re-submit rx urb here to avoid event lost issue */ 774 /* Re-submit rx urb here to avoid event lost issue */
756 if_usb_submit_rx_urb(priv); 775 if_usb_submit_rx_urb(cardp);
757 return 0;
758}
759
760static int if_usb_unregister_dev(wlan_private * priv)
761{
762 int ret = 0;
763
764 /* Need to send a Reset command to device before USB resources freed
765 * and wlan_remove_card() called, then device can handle FW download
766 * again.
767 */
768 if (priv)
769 libertas_reset_device(priv);
770
771 return ret;
772}
773
774
775/**
776 * @brief This function register usb device and initialize parameter
777 * @param priv pointer to wlan_private
778 * @return 0 or -1
779 */
780static int if_usb_register_dev(wlan_private * priv)
781{
782 struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
783
784 lbs_deb_enter(LBS_DEB_USB);
785
786 cardp->priv = priv;
787 cardp->eth_dev = priv->dev;
788 priv->hotplug_device = &(cardp->udev->dev);
789
790 lbs_deb_usbd(&cardp->udev->dev, "udev pointer is at %p\n",
791 cardp->udev);
792
793 lbs_deb_leave(LBS_DEB_USB);
794 return 0; 776 return 0;
795} 777}
796 778
@@ -800,10 +782,9 @@ static int if_usb_register_dev(wlan_private * priv)
800 * 2:Boot from FW in EEPROM 782 * 2:Boot from FW in EEPROM
801 * @return 0 783 * @return 0
802 */ 784 */
803static int if_usb_issue_boot_command(wlan_private *priv, int ivalue) 785static int if_usb_issue_boot_command(struct usb_card_rec *cardp, int ivalue)
804{ 786{
805 struct usb_card_rec *cardp = priv->card; 787 struct bootcmdstr sbootcmd;
806 struct bootcmdstr sbootcmd;
807 int i; 788 int i;
808 789
809 /* Prepare command */ 790 /* Prepare command */
@@ -814,28 +795,83 @@ static int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
814 memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr)); 795 memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr));
815 796
816 /* Issue command */ 797 /* Issue command */
817 usb_tx_block(priv, cardp->bulk_out_buffer, sizeof(struct bootcmdstr)); 798 usb_tx_block(cardp, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
818 799
819 return 0; 800 return 0;
820} 801}
821 802
822 803
823static int if_usb_do_prog_firmware(wlan_private * priv) 804/**
805 * @brief This function checks the validity of Boot2/FW image.
806 *
807 * @param data pointer to image
808 * len image length
809 * @return 0 or -1
810 */
811static int check_fwfile_format(u8 *data, u32 totlen)
812{
813 u32 bincmd, exit;
814 u32 blksize, offset, len;
815 int ret;
816
817 ret = 1;
818 exit = len = 0;
819
820 do {
821 struct fwheader *fwh = (void *)data;
822
823 bincmd = le32_to_cpu(fwh->dnldcmd);
824 blksize = le32_to_cpu(fwh->datalength);
825 switch (bincmd) {
826 case FW_HAS_DATA_TO_RECV:
827 offset = sizeof(struct fwheader) + blksize;
828 data += offset;
829 len += offset;
830 if (len >= totlen)
831 exit = 1;
832 break;
833 case FW_HAS_LAST_BLOCK:
834 exit = 1;
835 ret = 0;
836 break;
837 default:
838 exit = 1;
839 break;
840 }
841 } while (!exit);
842
843 if (ret)
844 lbs_pr_err("firmware file format check FAIL\n");
845 else
846 lbs_deb_fw("firmware file format check PASS\n");
847
848 return ret;
849}
850
851
852static int if_usb_prog_firmware(struct usb_card_rec *cardp)
824{ 853{
825 struct usb_card_rec *cardp = priv->card;
826 int i = 0; 854 int i = 0;
827 static int reset_count = 10; 855 static int reset_count = 10;
828 int ret = 0; 856 int ret = 0;
829 857
830 lbs_deb_enter(LBS_DEB_USB); 858 lbs_deb_enter(LBS_DEB_USB);
831 859
832 cardp->rinfo.priv = priv; 860 if ((ret = request_firmware(&cardp->fw, libertas_fw_name,
861 &cardp->udev->dev)) < 0) {
862 lbs_pr_err("request_firmware() failed with %#x\n", ret);
863 lbs_pr_err("firmware %s not found\n", libertas_fw_name);
864 goto done;
865 }
866
867 if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
868 goto release_fw;
833 869
834restart: 870restart:
835 if (if_usb_submit_rx_urb_fwload(priv) < 0) { 871 if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
836 lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); 872 lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
837 ret = -1; 873 ret = -1;
838 goto done; 874 goto release_fw;
839 } 875 }
840 876
841 cardp->bootcmdresp = 0; 877 cardp->bootcmdresp = 0;
@@ -843,7 +879,7 @@ restart:
843 int j = 0; 879 int j = 0;
844 i++; 880 i++;
845 /* Issue Boot command = 1, Boot from Download-FW */ 881 /* Issue Boot command = 1, Boot from Download-FW */
846 if_usb_issue_boot_command(priv, BOOT_CMD_FW_BY_USB); 882 if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
847 /* wait for command response */ 883 /* wait for command response */
848 do { 884 do {
849 j++; 885 j++;
@@ -853,14 +889,13 @@ restart:
853 889
854 if (cardp->bootcmdresp == 0) { 890 if (cardp->bootcmdresp == 0) {
855 if (--reset_count >= 0) { 891 if (--reset_count >= 0) {
856 if_usb_reset_device(priv); 892 if_usb_reset_device(cardp);
857 goto restart; 893 goto restart;
858 } 894 }
859 return -1; 895 return -1;
860 } 896 }
861 897
862 i = 0; 898 i = 0;
863 priv->adapter->fw_ready = 0;
864 899
865 cardp->totalbytes = 0; 900 cardp->totalbytes = 0;
866 cardp->fwlastblksent = 0; 901 cardp->fwlastblksent = 0;
@@ -870,113 +905,37 @@ restart:
870 cardp->totalbytes = 0; 905 cardp->totalbytes = 0;
871 cardp->fwfinalblk = 0; 906 cardp->fwfinalblk = 0;
872 907
873 if_prog_firmware(priv); 908 if_prog_firmware(cardp);
874 909
875 do { 910 do {
876 lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n"); 911 lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n");
877 i++; 912 i++;
878 msleep_interruptible(100); 913 msleep_interruptible(100);
879 if (priv->adapter->surpriseremoved || i >= 20) 914 if (cardp->surprise_removed || i >= 20)
880 break; 915 break;
881 } while (!cardp->fwdnldover); 916 } while (!cardp->fwdnldover);
882 917
883 if (!cardp->fwdnldover) { 918 if (!cardp->fwdnldover) {
884 lbs_pr_info("failed to load fw, resetting device!\n"); 919 lbs_pr_info("failed to load fw, resetting device!\n");
885 if (--reset_count >= 0) { 920 if (--reset_count >= 0) {
886 if_usb_reset_device(priv); 921 if_usb_reset_device(cardp);
887 goto restart; 922 goto restart;
888 } 923 }
889 924
890 lbs_pr_info("FW download failure, time = %d ms\n", i * 100); 925 lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
891 ret = -1; 926 ret = -1;
892 goto done; 927 goto release_fw;
893 } 928 }
894 929
895 if_usb_submit_rx_urb(priv); 930release_fw:
896 931 release_firmware(cardp->fw);
897 /* Delay 200 ms to waiting for the FW ready */ 932 cardp->fw = NULL;
898 msleep_interruptible(200);
899
900 priv->adapter->fw_ready = 1;
901 933
902done: 934done:
903 lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); 935 lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
904 return ret; 936 return ret;
905} 937}
906 938
907/**
908 * @brief This function checks the validity of Boot2/FW image.
909 *
910 * @param data pointer to image
911 * len image length
912 * @return 0 or -1
913 */
914static int check_fwfile_format(u8 *data, u32 totlen)
915{
916 u32 bincmd, exit;
917 u32 blksize, offset, len;
918 int ret;
919
920 ret = 1;
921 exit = len = 0;
922
923 do {
924 struct fwheader *fwh = (void *)data;
925
926 bincmd = le32_to_cpu(fwh->dnldcmd);
927 blksize = le32_to_cpu(fwh->datalength);
928 switch (bincmd) {
929 case FW_HAS_DATA_TO_RECV:
930 offset = sizeof(struct fwheader) + blksize;
931 data += offset;
932 len += offset;
933 if (len >= totlen)
934 exit = 1;
935 break;
936 case FW_HAS_LAST_BLOCK:
937 exit = 1;
938 ret = 0;
939 break;
940 default:
941 exit = 1;
942 break;
943 }
944 } while (!exit);
945
946 if (ret)
947 lbs_pr_err("firmware file format check FAIL\n");
948 else
949 lbs_deb_fw("firmware file format check PASS\n");
950
951 return ret;
952}
953
954
955static int if_usb_prog_firmware(wlan_private *priv)
956{
957 int ret = -1;
958
959 lbs_deb_enter(LBS_DEB_FW);
960
961 if ((ret = request_firmware(&priv->firmware, libertas_fw_name,
962 priv->hotplug_device)) < 0) {
963 lbs_pr_err("request_firmware() failed with %#x\n", ret);
964 lbs_pr_err("firmware %s not found\n", libertas_fw_name);
965 goto done;
966 }
967
968 if (check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
969 release_firmware(priv->firmware);
970 goto done;
971 }
972
973 ret = if_usb_do_prog_firmware(priv);
974
975 release_firmware(priv->firmware);
976done:
977 return ret;
978}
979
980 939
981#ifdef CONFIG_PM 940#ifdef CONFIG_PM
982static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) 941static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)