p54usb: utilize usb_reset_device for 3887
PATCH 1/3 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 <[email protected]>
---
drivers/net/wireless/p54/p54usb.c +57 -13
@@ -428,9 +428,44 @@ static int p54u_bulk_msg(struct p54u_pri data, len, &alen, 2000); } +static const char p54u_romboot_3887[] ="~~~~" ; +static const char p54u_firmware_upload_3887[] ="<\r" ; + +static int p54u_device_reset_3887 (struct ieee80211_hw *dev) +{ +struct p54u_priv *priv = dev->priv; +int ret, lock; +u8 buf[4 ]; + + ret = lock =usb_lock_device_for_reset (priv->udev, priv->intf); +if (ret <0 ) { +dev_err (&priv->udev->dev,"(p54usb) unable to lock device for " +"reset: %d\n" , ret); +return ret; + } + + ret =usb_reset_device (priv->udev); +if (lock) +usb_unlock_device (priv->udev); + +if (ret) { +dev_err (&priv->udev->dev,"(p54usb) unable to reset " +"device: %d\n" , ret); +return ret; + } + +memcpy (&buf, p54u_romboot_3887,sizeof (buf)); + ret =p54u_bulk_msg (priv,P54U_PIPE_DATA , + buf,sizeof (buf)); +if (ret) +dev_err (&priv->udev->dev,"(p54usb) unable to jump to " +"boot ROM: %d\n" , ret); + +return ret; +} +static int p54u_upload_firmware_3887 (struct ieee80211_hw *dev) { -static char start_string[] ="~~~~<\r" ;struct p54u_priv *priv = dev->priv;const struct firmware *fw_entry =NULL ;int err, alen;
@@ -449,12 +484,9 @@ static int p54u_upload_firmware_3887(str goto err_bufalloc; } -memcpy (buf, start_string,4 ); - err =p54u_bulk_msg (priv,P54U_PIPE_DATA , buf,4 ); -if (err) { -dev_err (&priv->udev->dev,"(p54usb) reset failed! (%d)\n" , err); + err =p54u_device_reset_3887 (dev); +if (err) goto err_reset; - } err =request_firmware (&fw_entry,"isl3887usb" , &priv->udev->dev);if (err) {
@@ -471,14 +503,14 @@ static int p54u_upload_firmware_3887(str goto err_upload_failed; left = block_size =min ((size_t )P54U_FW_BLOCK , fw_entry->size); -strcpy (buf, start_string); - left -=strlen (start_string); - tmp +=strlen (start_string); +strcpy (buf, p54u_firmware_upload_3887); + left -=strlen (p54u_firmware_upload_3887); + tmp +=strlen (p54u_firmware_upload_3887); data = fw_entry->data; remains = fw_entry->size; - hdr = (struct x2_header *)(buf +strlen (start_string)); + hdr = (struct x2_header *)(buf +strlen (p54u_firmware_upload_3887));memcpy (hdr->signature,X2_SIGNATURE ,X2_SIGNATURE_SIZE ); hdr->fw_load_addr =cpu_to_le32 (ISL38XX_DEV_FIRMWARE_ADDR ); hdr->fw_length =cpu_to_le32 (fw_entry->size);
@@ -881,6 +913,9 @@ static int __devinit p54u_probe(struct uSET_IEEE80211_DEV (dev, &intf->dev);usb_set_intfdata (intf, dev); priv->udev = udev; + priv->intf = intf; +skb_queue_head_init (&priv->rx_queue); +init_usb_anchor (&priv->submitted);usb_get_dev (udev);
@@ -923,9 +958,6 @@ static int __devinit p54u_probe(struct uif (err) goto err_free_dev; -skb_queue_head_init (&priv->rx_queue); -init_usb_anchor (&priv->submitted); -p54u_open (dev); err =p54_read_eeprom (dev);p54u_stop (dev);
@@ -963,11 +995,23 @@ static void __devexit p54u_disconnect(stieee80211_free_hw (dev); } +static int p54u_pre_reset (struct usb_interface *intf) +{ +return 0 ; +} + +static int p54u_post_reset (struct usb_interface *intf) +{ +return 0 ; +} +static struct usb_driver p54u_driver = { .name ="p54usb" , .id_table = p54u_table, .probe = p54u_probe, .disconnect = p54u_disconnect, + .pre_reset = p54u_pre_reset, + .post_reset = p54u_post_reset, };static int __init p54u_init (void )
drivers/net/wireless/p54/p54usb.h +1 -0
@@ -126,6 +126,7 @@ struct p54u_rx_info {struct p54u_priv {struct p54_common common;struct usb_device *udev; +struct usb_interface *intf;enum {P54U_NET2280 =0 ,P54U_3887