Re: Autosuspending devices that seem to need reset_resume

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 8 Jun 2009, Matthew Garrett wrote:

> If I turn on autosuspend on qcserial (which claims to support it), the 
> card fails to resume. The following bodge makes it work:
> 
> diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
> index 7528b8d..f8c02ba 100644
> --- a/drivers/usb/serial/qcserial.c
> +++ b/drivers/usb/serial/qcserial.c
> @@ -15,6 +15,7 @@
>  #include <linux/tty_flip.h>
>  #include <linux/usb.h>
>  #include <linux/usb/serial.h>
> +#include <linux/usb/quirks.h>
>  
>  #define DRIVER_AUTHOR "Qualcomm Inc"
>  #define DRIVER_DESC "Qualcomm USB Serial driver"
> @@ -51,6 +52,14 @@ static struct usb_device_id id_table[] = {
>  };
>  MODULE_DEVICE_TABLE(usb, id_table);
>  
> +static int qc_reset_resume(struct usb_interface *intf) {
> +	struct usb_device *udev = interface_to_usbdev(intf);
> +
> +	intf->needs_binding = 1;
> +	udev->quirks &= USB_QUIRK_RESET_RESUME;
> +	return 0;
> +}

This looks rather strange.  Are you sure you don't mean "|=" instead of 
"&="?  Anyway, this code doesn't belong here.  The reset_resume routine 
is supposed to do whatever is necessary to restore any device state 
that was lost when the device was reset.

> +
>  static struct usb_driver qcdriver = {
>  	.name			= "qcserial",
>  	.probe			= usb_serial_probe,
> @@ -58,6 +67,7 @@ static struct usb_driver qcdriver = {
>  	.id_table		= id_table,
>  	.suspend		= usb_serial_suspend,
>  	.resume			= usb_serial_resume,
> +	.reset_resume		= qc_reset_resume,
>  	.supports_autosuspend	= true,
>  };
>  
> @@ -66,6 +76,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
>  	int retval = -ENODEV;
>  	__u8 nintf;
>  	__u8 ifnum;
> +        struct usb_device       *udev = interface_to_usbdev(serial->interface);
>  
>  	dbg("%s", __func__);
>  
> @@ -74,6 +85,9 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
>  	ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
>  	dbg("This Interface = %d", ifnum);
>  
> +	udev->quirks &= USB_QUIRK_RESET_RESUME;
> +	udev->reset_resume = 1;
> +
>  	switch (nintf) {
>  	case 1:
>  		/* QDL mode */

This is peculiar and roundabout.

> but I'm left with a few questions. Firstly, is there a better way for a 
> driver to indicate that it wants reset_resume? I'd rather not add it to 
> the quirks list since that means duplicating all the IDs in the driver 
> and there's a risk of them getting out of sync.

You don't have to add all the IDs to the quirks list; all you need to 
do is put

	udev->quirks |= USB_QUIRK_RESET_RESUME;

in the driver's probe routine.  The result will be the same.

> Secondly, is there a 
> better way to do this in the first place?

Better way to do what?  Indicate that the device should always get a 
reset-resume?  No; see above.

>  I've got no documentation for 
> the card, but there's no relevant state kept when there isn't an open 
> interface.

But what about when there _is_ an open interface?  The reset_resume 
method has to handle all cases.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux