aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54usb.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2009-04-25 15:12:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-06 15:14:41 -0400
commit1ca5f2e94c40b04d5dec437cd41fd5ba12aaac31 (patch)
tree7aff5fa8798e8d4e4cb90ba2e516ad01e4575167 /drivers/net/wireless/p54/p54usb.c
parenta406ac0dc15b22807b65f5a6590b9cb34d99d4ab (diff)
p54usb: rework driver for resume
This patch redo the driver code so that p54usb no longer hangs the kernel on resume. Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/p54usb.c')
-rw-r--r--drivers/net/wireless/p54/p54usb.c256
1 files changed, 165 insertions, 91 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 44ab3ccac910..ec6c95474f1a 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -81,6 +81,29 @@ static struct usb_device_id p54u_table[] __devinitdata = {
81 81
82MODULE_DEVICE_TABLE(usb, p54u_table); 82MODULE_DEVICE_TABLE(usb, p54u_table);
83 83
84static const struct {
85 u32 intf;
86 enum p54u_hw_type type;
87 char fw[FIRMWARE_NAME_MAX];
88 char fw_legacy[FIRMWARE_NAME_MAX];
89 char hw[20];
90} p54u_fwlist[__NUM_P54U_HWTYPES] = {
91 {
92 .type = P54U_NET2280,
93 .intf = FW_LM86,
94 .fw = "isl3886usb",
95 .fw_legacy = "isl3890usb",
96 .hw = "ISL3886 + net2280",
97 },
98 {
99 .type = P54U_3887,
100 .intf = FW_LM87,
101 .fw = "isl3887usb",
102 .fw_legacy = "isl3887usb_bare",
103 .hw = "ISL3887",
104 },
105};
106
84static void p54u_rx_cb(struct urb *urb) 107static void p54u_rx_cb(struct urb *urb)
85{ 108{
86 struct sk_buff *skb = (struct sk_buff *) urb->context; 109 struct sk_buff *skb = (struct sk_buff *) urb->context;
@@ -125,11 +148,7 @@ static void p54u_rx_cb(struct urb *urb)
125 } 148 }
126 skb_reset_tail_pointer(skb); 149 skb_reset_tail_pointer(skb);
127 skb_trim(skb, 0); 150 skb_trim(skb, 0);
128 if (urb->transfer_buffer != skb_tail_pointer(skb)) { 151 urb->transfer_buffer = skb_tail_pointer(skb);
129 /* this should not happen */
130 WARN_ON(1);
131 urb->transfer_buffer = skb_tail_pointer(skb);
132 }
133 } 152 }
134 skb_queue_tail(&priv->rx_queue, skb); 153 skb_queue_tail(&priv->rx_queue, skb);
135 usb_anchor_urb(urb, &priv->submitted); 154 usb_anchor_urb(urb, &priv->submitted);
@@ -378,20 +397,16 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
378 data, len, &alen, 2000); 397 data, len, &alen, 2000);
379} 398}
380 399
381static const char p54u_romboot_3887[] = "~~~~"; 400static int p54u_device_reset(struct ieee80211_hw *dev)
382static const char p54u_firmware_upload_3887[] = "<\r";
383
384static int p54u_device_reset_3887(struct ieee80211_hw *dev)
385{ 401{
386 struct p54u_priv *priv = dev->priv; 402 struct p54u_priv *priv = dev->priv;
387 int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING); 403 int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);
388 u8 buf[4];
389 404
390 if (lock) { 405 if (lock) {
391 ret = usb_lock_device_for_reset(priv->udev, priv->intf); 406 ret = usb_lock_device_for_reset(priv->udev, priv->intf);
392 if (ret < 0) { 407 if (ret < 0) {
393 dev_err(&priv->udev->dev, "(p54usb) unable to lock " 408 dev_err(&priv->udev->dev, "(p54usb) unable to lock "
394 " device for reset: %d\n", ret); 409 "device for reset (%d)!\n", ret);
395 return ret; 410 return ret;
396 } 411 }
397 } 412 }
@@ -400,26 +415,34 @@ static int p54u_device_reset_3887(struct ieee80211_hw *dev)
400 if (lock) 415 if (lock)
401 usb_unlock_device(priv->udev); 416 usb_unlock_device(priv->udev);
402 417
403 if (ret) { 418 if (ret)
404 dev_err(&priv->udev->dev, "(p54usb) unable to reset " 419 dev_err(&priv->udev->dev, "(p54usb) unable to reset "
405 "device: %d\n", ret); 420 "device (%d)!\n", ret);
406 return ret; 421
407 } 422 return ret;
423}
424
425static const char p54u_romboot_3887[] = "~~~~";
426static int p54u_firmware_reset_3887(struct ieee80211_hw *dev)
427{
428 struct p54u_priv *priv = dev->priv;
429 u8 buf[4];
430 int ret;
408 431
409 memcpy(&buf, p54u_romboot_3887, sizeof(buf)); 432 memcpy(&buf, p54u_romboot_3887, sizeof(buf));
410 ret = p54u_bulk_msg(priv, P54U_PIPE_DATA, 433 ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
411 buf, sizeof(buf)); 434 buf, sizeof(buf));
412 if (ret) 435 if (ret)
413 dev_err(&priv->udev->dev, "(p54usb) unable to jump to " 436 dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
414 "boot ROM: %d\n", ret); 437 "boot ROM (%d)!\n", ret);
415 438
416 return ret; 439 return ret;
417} 440}
418 441
442static const char p54u_firmware_upload_3887[] = "<\r";
419static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) 443static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
420{ 444{
421 struct p54u_priv *priv = dev->priv; 445 struct p54u_priv *priv = dev->priv;
422 const struct firmware *fw_entry = NULL;
423 int err, alen; 446 int err, alen;
424 u8 carry = 0; 447 u8 carry = 0;
425 u8 *buf, *tmp; 448 u8 *buf, *tmp;
@@ -428,51 +451,29 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
428 struct x2_header *hdr; 451 struct x2_header *hdr;
429 unsigned long timeout; 452 unsigned long timeout;
430 453
454 err = p54u_firmware_reset_3887(dev);
455 if (err)
456 return err;
457
431 tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL); 458 tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
432 if (!buf) { 459 if (!buf) {
433 dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware" 460 dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
434 "upload buffer!\n"); 461 "upload buffer!\n");
435 err = -ENOMEM; 462 return -ENOMEM;
436 goto err_bufalloc;
437 }
438
439 err = p54u_device_reset_3887(dev);
440 if (err)
441 goto err_reset;
442
443 err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
444 if (err) {
445 dev_err(&priv->udev->dev, "p54usb: cannot find firmware "
446 "(isl3887usb)\n");
447 err = request_firmware(&fw_entry, "isl3887usb_bare",
448 &priv->udev->dev);
449 if (err)
450 goto err_req_fw_failed;
451 }
452
453 err = p54_parse_firmware(dev, fw_entry);
454 if (err)
455 goto err_upload_failed;
456
457 if (priv->common.fw_interface != FW_LM87) {
458 dev_err(&priv->udev->dev, "wrong firmware, "
459 "please get a LM87 firmware and try again.\n");
460 err = -EINVAL;
461 goto err_upload_failed;
462 } 463 }
463 464
464 left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size); 465 left = block_size = min((size_t)P54U_FW_BLOCK, priv->fw->size);
465 strcpy(buf, p54u_firmware_upload_3887); 466 strcpy(buf, p54u_firmware_upload_3887);
466 left -= strlen(p54u_firmware_upload_3887); 467 left -= strlen(p54u_firmware_upload_3887);
467 tmp += strlen(p54u_firmware_upload_3887); 468 tmp += strlen(p54u_firmware_upload_3887);
468 469
469 data = fw_entry->data; 470 data = priv->fw->data;
470 remains = fw_entry->size; 471 remains = priv->fw->size;
471 472
472 hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887)); 473 hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
473 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE); 474 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
474 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR); 475 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
475 hdr->fw_length = cpu_to_le32(fw_entry->size); 476 hdr->fw_length = cpu_to_le32(priv->fw->size);
476 hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr, 477 hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
477 sizeof(u32)*2)); 478 sizeof(u32)*2));
478 left -= sizeof(*hdr); 479 left -= sizeof(*hdr);
@@ -514,7 +515,8 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
514 left = block_size = min((unsigned int)P54U_FW_BLOCK, remains); 515 left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
515 } 516 }
516 517
517 *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size)); 518 *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data,
519 priv->fw->size));
518 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32)); 520 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
519 if (err) { 521 if (err) {
520 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n"); 522 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
@@ -565,19 +567,14 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
565 if (err) 567 if (err)
566 goto err_upload_failed; 568 goto err_upload_failed;
567 569
568 err_upload_failed: 570err_upload_failed:
569 release_firmware(fw_entry);
570 err_req_fw_failed:
571 err_reset:
572 kfree(buf); 571 kfree(buf);
573 err_bufalloc:
574 return err; 572 return err;
575} 573}
576 574
577static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) 575static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
578{ 576{
579 struct p54u_priv *priv = dev->priv; 577 struct p54u_priv *priv = dev->priv;
580 const struct firmware *fw_entry = NULL;
581 const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE; 578 const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
582 int err, alen; 579 int err, alen;
583 void *buf; 580 void *buf;
@@ -592,33 +589,6 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
592 return -ENOMEM; 589 return -ENOMEM;
593 } 590 }
594 591
595 err = request_firmware(&fw_entry, "isl3886usb", &priv->udev->dev);
596 if (err) {
597 dev_err(&priv->udev->dev, "(p54usb) cannot find firmware "
598 "(isl3886usb)\n");
599 err = request_firmware(&fw_entry, "isl3890usb",
600 &priv->udev->dev);
601 if (err) {
602 kfree(buf);
603 return err;
604 }
605 }
606
607 err = p54_parse_firmware(dev, fw_entry);
608 if (err) {
609 kfree(buf);
610 release_firmware(fw_entry);
611 return err;
612 }
613
614 if (priv->common.fw_interface != FW_LM86) {
615 dev_err(&priv->udev->dev, "wrong firmware, "
616 "please get a LM86(USB) firmware and try again.\n");
617 kfree(buf);
618 release_firmware(fw_entry);
619 return -EINVAL;
620 }
621
622#define P54U_WRITE(type, addr, data) \ 592#define P54U_WRITE(type, addr, data) \
623 do {\ 593 do {\
624 err = p54u_write(priv, buf, type,\ 594 err = p54u_write(priv, buf, type,\
@@ -718,8 +688,8 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
718 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); 688 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
719 689
720 /* finally, we can upload firmware now! */ 690 /* finally, we can upload firmware now! */
721 remains = fw_entry->size; 691 remains = priv->fw->size;
722 data = fw_entry->data; 692 data = priv->fw->data;
723 offset = ISL38XX_DEV_FIRMWARE_ADDR; 693 offset = ISL38XX_DEV_FIRMWARE_ADDR;
724 694
725 while (remains) { 695 while (remains) {
@@ -828,12 +798,54 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
828#undef P54U_WRITE 798#undef P54U_WRITE
829#undef P54U_READ 799#undef P54U_READ
830 800
831 fail: 801fail:
832 release_firmware(fw_entry);
833 kfree(buf); 802 kfree(buf);
834 return err; 803 return err;
835} 804}
836 805
806static int p54u_load_firmware(struct ieee80211_hw *dev)
807{
808 struct p54u_priv *priv = dev->priv;
809 int err, i;
810
811 BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES);
812
813 for (i = 0; i < __NUM_P54U_HWTYPES; i++)
814 if (p54u_fwlist[i].type == priv->hw_type)
815 break;
816
817 if (i == __NUM_P54U_HWTYPES)
818 return -EOPNOTSUPP;
819
820 err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev);
821 if (err) {
822 dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
823 "(%d)!\n", p54u_fwlist[i].fw, err);
824
825 err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy,
826 &priv->udev->dev);
827 if (err)
828 return err;
829 }
830
831 err = p54_parse_firmware(dev, priv->fw);
832 if (err)
833 goto out;
834
835 if (priv->common.fw_interface != p54u_fwlist[i].intf) {
836 dev_err(&priv->udev->dev, "wrong firmware, please get "
837 "a firmware for \"%s\" and try again.\n",
838 p54u_fwlist[i].hw);
839 err = -EINVAL;
840 }
841
842out:
843 if (err)
844 release_firmware(priv->fw);
845
846 return err;
847}
848
837static int p54u_open(struct ieee80211_hw *dev) 849static int p54u_open(struct ieee80211_hw *dev)
838{ 850{
839 struct p54u_priv *priv = dev->priv; 851 struct p54u_priv *priv = dev->priv;
@@ -875,6 +887,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
875 } 887 }
876 888
877 priv = dev->priv; 889 priv = dev->priv;
890 priv->hw_type = P54U_INVALID_HW;
878 891
879 SET_IEEE80211_DEV(dev, &intf->dev); 892 SET_IEEE80211_DEV(dev, &intf->dev);
880 usb_set_intfdata(intf, dev); 893 usb_set_intfdata(intf, dev);
@@ -906,34 +919,46 @@ static int __devinit p54u_probe(struct usb_interface *intf,
906 priv->common.open = p54u_open; 919 priv->common.open = p54u_open;
907 priv->common.stop = p54u_stop; 920 priv->common.stop = p54u_stop;
908 if (recognized_pipes < P54U_PIPE_NUMBER) { 921 if (recognized_pipes < P54U_PIPE_NUMBER) {
922 /* ISL3887 needs a full reset on resume */
923 udev->reset_resume = 1;
924 err = p54u_device_reset(dev);
925
909 priv->hw_type = P54U_3887; 926 priv->hw_type = P54U_3887;
910 dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); 927 dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
911 priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); 928 priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
912 priv->common.tx = p54u_tx_lm87; 929 priv->common.tx = p54u_tx_lm87;
913 err = p54u_upload_firmware_3887(dev); 930 priv->upload_fw = p54u_upload_firmware_3887;
914 } else { 931 } else {
915 priv->hw_type = P54U_NET2280; 932 priv->hw_type = P54U_NET2280;
916 dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); 933 dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
917 priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); 934 priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
918 priv->common.tx = p54u_tx_net2280; 935 priv->common.tx = p54u_tx_net2280;
919 err = p54u_upload_firmware_net2280(dev); 936 priv->upload_fw = p54u_upload_firmware_net2280;
920 } 937 }
938 err = p54u_load_firmware(dev);
921 if (err) 939 if (err)
922 goto err_free_dev; 940 goto err_free_dev;
923 941
942 err = priv->upload_fw(dev);
943 if (err)
944 goto err_free_fw;
945
924 p54u_open(dev); 946 p54u_open(dev);
925 err = p54_read_eeprom(dev); 947 err = p54_read_eeprom(dev);
926 p54u_stop(dev); 948 p54u_stop(dev);
927 if (err) 949 if (err)
928 goto err_free_dev; 950 goto err_free_fw;
929 951
930 err = p54_register_common(dev, &udev->dev); 952 err = p54_register_common(dev, &udev->dev);
931 if (err) 953 if (err)
932 goto err_free_dev; 954 goto err_free_fw;
933 955
934 return 0; 956 return 0;
935 957
936 err_free_dev: 958err_free_fw:
959 release_firmware(priv->fw);
960
961err_free_dev:
937 ieee80211_free_hw(dev); 962 ieee80211_free_hw(dev);
938 usb_set_intfdata(intf, NULL); 963 usb_set_intfdata(intf, NULL);
939 usb_put_dev(udev); 964 usb_put_dev(udev);
@@ -952,20 +977,64 @@ static void __devexit p54u_disconnect(struct usb_interface *intf)
952 977
953 priv = dev->priv; 978 priv = dev->priv;
954 usb_put_dev(interface_to_usbdev(intf)); 979 usb_put_dev(interface_to_usbdev(intf));
980 release_firmware(priv->fw);
955 p54_free_common(dev); 981 p54_free_common(dev);
956 ieee80211_free_hw(dev); 982 ieee80211_free_hw(dev);
957} 983}
958 984
959static int p54u_pre_reset(struct usb_interface *intf) 985static int p54u_pre_reset(struct usb_interface *intf)
960{ 986{
987 struct ieee80211_hw *dev = usb_get_intfdata(intf);
988
989 if (!dev)
990 return -ENODEV;
991
992 p54u_stop(dev);
961 return 0; 993 return 0;
962} 994}
963 995
996static int p54u_resume(struct usb_interface *intf)
997{
998 struct ieee80211_hw *dev = usb_get_intfdata(intf);
999 struct p54u_priv *priv;
1000
1001 if (!dev)
1002 return -ENODEV;
1003
1004 priv = dev->priv;
1005 if (unlikely(!(priv->upload_fw && priv->fw)))
1006 return 0;
1007
1008 return priv->upload_fw(dev);
1009}
1010
964static int p54u_post_reset(struct usb_interface *intf) 1011static int p54u_post_reset(struct usb_interface *intf)
965{ 1012{
1013 struct ieee80211_hw *dev = usb_get_intfdata(intf);
1014 struct p54u_priv *priv;
1015 int err;
1016
1017 err = p54u_resume(intf);
1018 if (err)
1019 return err;
1020
1021 /* reinitialize old device state */
1022 priv = dev->priv;
1023 if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED)
1024 ieee80211_restart_hw(dev);
1025
966 return 0; 1026 return 0;
967} 1027}
968 1028
1029#ifdef CONFIG_PM
1030
1031static int p54u_suspend(struct usb_interface *intf, pm_message_t message)
1032{
1033 return p54u_pre_reset(intf);
1034}
1035
1036#endif /* CONFIG_PM */
1037
969static struct usb_driver p54u_driver = { 1038static struct usb_driver p54u_driver = {
970 .name = "p54usb", 1039 .name = "p54usb",
971 .id_table = p54u_table, 1040 .id_table = p54u_table,
@@ -973,6 +1042,11 @@ static struct usb_driver p54u_driver = {
973 .disconnect = p54u_disconnect, 1042 .disconnect = p54u_disconnect,
974 .pre_reset = p54u_pre_reset, 1043 .pre_reset = p54u_pre_reset,
975 .post_reset = p54u_post_reset, 1044 .post_reset = p54u_post_reset,
1045#ifdef CONFIG_PM
1046 .suspend = p54u_suspend,
1047 .resume = p54u_resume,
1048 .reset_resume = p54u_resume,
1049#endif /* CONFIG_PM */
976 .soft_unbind = 1, 1050 .soft_unbind = 1,
977}; 1051};
978 1052