aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2008-12-26 13:08:31 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 15:59:39 -0500
commit6982869d993009c02cefcca98a67b212d0e61c5f (patch)
treebda0dbb4dfe78aa7ddfaa1f221b9c0ef1b4ac789
parent6b1c7c67603efdf0b39f6056989b0f8194cdc1f3 (diff)
p54usb: utilize usb_reset_device for 3887
Sometimes on unload or reboot the 3887 USB devices become stuck. <usual log entry> kernel: usbcore: registered new interface driver p54usb kernel: usb 2-10: (p54usb) reset failed! (-110) kernel: p54usb: probe of 2-10:1.0 failed with error -110 [...] and a physical unplug and replug was necessary. However we should be able to do this in software as well, without any user interaction. Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/p54/p54usb.c70
-rw-r--r--drivers/net/wireless/p54/p54usb.h1
2 files changed, 58 insertions, 13 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 5de2ebfb28c7..3c31c15267b5 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -424,9 +424,44 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
424 data, len, &alen, 2000); 424 data, len, &alen, 2000);
425} 425}
426 426
427static const char p54u_romboot_3887[] = "~~~~";
428static const char p54u_firmware_upload_3887[] = "<\r";
429
430static int p54u_device_reset_3887(struct ieee80211_hw *dev)
431{
432 struct p54u_priv *priv = dev->priv;
433 int ret, lock;
434 u8 buf[4];
435
436 ret = lock = usb_lock_device_for_reset(priv->udev, priv->intf);
437 if (ret < 0) {
438 dev_err(&priv->udev->dev, "(p54usb) unable to lock device for "
439 "reset: %d\n", ret);
440 return ret;
441 }
442
443 ret = usb_reset_device(priv->udev);
444 if (lock)
445 usb_unlock_device(priv->udev);
446
447 if (ret) {
448 dev_err(&priv->udev->dev, "(p54usb) unable to reset "
449 "device: %d\n", ret);
450 return ret;
451 }
452
453 memcpy(&buf, p54u_romboot_3887, sizeof(buf));
454 ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
455 buf, sizeof(buf));
456 if (ret)
457 dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
458 "boot ROM: %d\n", ret);
459
460 return ret;
461}
462
427static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) 463static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
428{ 464{
429 static char start_string[] = "~~~~<\r";
430 struct p54u_priv *priv = dev->priv; 465 struct p54u_priv *priv = dev->priv;
431 const struct firmware *fw_entry = NULL; 466 const struct firmware *fw_entry = NULL;
432 int err, alen; 467 int err, alen;
@@ -445,12 +480,9 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
445 goto err_bufalloc; 480 goto err_bufalloc;
446 } 481 }
447 482
448 memcpy(buf, start_string, 4); 483 err = p54u_device_reset_3887(dev);
449 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4); 484 if (err)
450 if (err) {
451 dev_err(&priv->udev->dev, "(p54usb) reset failed! (%d)\n", err);
452 goto err_reset; 485 goto err_reset;
453 }
454 486
455 err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev); 487 err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
456 if (err) { 488 if (err) {
@@ -467,14 +499,14 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
467 goto err_upload_failed; 499 goto err_upload_failed;
468 500
469 left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size); 501 left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
470 strcpy(buf, start_string); 502 strcpy(buf, p54u_firmware_upload_3887);
471 left -= strlen(start_string); 503 left -= strlen(p54u_firmware_upload_3887);
472 tmp += strlen(start_string); 504 tmp += strlen(p54u_firmware_upload_3887);
473 505
474 data = fw_entry->data; 506 data = fw_entry->data;
475 remains = fw_entry->size; 507 remains = fw_entry->size;
476 508
477 hdr = (struct x2_header *)(buf + strlen(start_string)); 509 hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
478 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE); 510 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
479 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR); 511 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
480 hdr->fw_length = cpu_to_le32(fw_entry->size); 512 hdr->fw_length = cpu_to_le32(fw_entry->size);
@@ -876,6 +908,9 @@ static int __devinit p54u_probe(struct usb_interface *intf,
876 SET_IEEE80211_DEV(dev, &intf->dev); 908 SET_IEEE80211_DEV(dev, &intf->dev);
877 usb_set_intfdata(intf, dev); 909 usb_set_intfdata(intf, dev);
878 priv->udev = udev; 910 priv->udev = udev;
911 priv->intf = intf;
912 skb_queue_head_init(&priv->rx_queue);
913 init_usb_anchor(&priv->submitted);
879 914
880 usb_get_dev(udev); 915 usb_get_dev(udev);
881 916
@@ -918,9 +953,6 @@ static int __devinit p54u_probe(struct usb_interface *intf,
918 if (err) 953 if (err)
919 goto err_free_dev; 954 goto err_free_dev;
920 955
921 skb_queue_head_init(&priv->rx_queue);
922 init_usb_anchor(&priv->submitted);
923
924 p54u_open(dev); 956 p54u_open(dev);
925 err = p54_read_eeprom(dev); 957 err = p54_read_eeprom(dev);
926 p54u_stop(dev); 958 p54u_stop(dev);
@@ -958,11 +990,23 @@ static void __devexit p54u_disconnect(struct usb_interface *intf)
958 ieee80211_free_hw(dev); 990 ieee80211_free_hw(dev);
959} 991}
960 992
993static int p54u_pre_reset(struct usb_interface *intf)
994{
995 return 0;
996}
997
998static int p54u_post_reset(struct usb_interface *intf)
999{
1000 return 0;
1001}
1002
961static struct usb_driver p54u_driver = { 1003static struct usb_driver p54u_driver = {
962 .name = "p54usb", 1004 .name = "p54usb",
963 .id_table = p54u_table, 1005 .id_table = p54u_table,
964 .probe = p54u_probe, 1006 .probe = p54u_probe,
965 .disconnect = p54u_disconnect, 1007 .disconnect = p54u_disconnect,
1008 .pre_reset = p54u_pre_reset,
1009 .post_reset = p54u_post_reset,
966}; 1010};
967 1011
968static int __init p54u_init(void) 1012static int __init p54u_init(void)
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
index 54ee738bf2af..8bc58982d8dd 100644
--- a/drivers/net/wireless/p54/p54usb.h
+++ b/drivers/net/wireless/p54/p54usb.h
@@ -126,6 +126,7 @@ struct p54u_rx_info {
126struct p54u_priv { 126struct p54u_priv {
127 struct p54_common common; 127 struct p54_common common;
128 struct usb_device *udev; 128 struct usb_device *udev;
129 struct usb_interface *intf;
129 enum { 130 enum {
130 P54U_NET2280 = 0, 131 P54U_NET2280 = 0,
131 P54U_3887 132 P54U_3887