Re: [RFC PATCH 2/5] usb: add usb port auto power off mechanism

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

 



On Fri, 9 Nov 2012, Lan Tianyu wrote:

> This patch is to add usb port auto power off mechanism.
> When usb device is suspending, usb core will send clear usb port's
> POWER feature requst to power off port if all conditions were met.
> These conditions are remote wakeup enable, pm qos NO_POWER_OFF flags
> and persist feature. When device is suspended and power off, usb core

You got the conditions wrong.  You need remote wakeup to be
disabled, NO_POWER_OFF clear, and persist enabled.

> will ignore port's connect and enable change event to keep the device
> not being disconnected. When it resumes, power on port again.

> @@ -47,6 +48,7 @@ struct usb_port {
>  	struct device dev;
>  	struct dev_state *port_owner;
>  	enum usb_port_connect_type connect_type;
> +	unsigned		power_state:1;

What's with the peculiar spacing?

>  };
>  
>  struct usb_hub {
> @@ -166,6 +168,11 @@ MODULE_PARM_DESC(use_both_schemes,
>  DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
>  EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
>  
> +#define USB_PORT_POWER_STATE_ON		0
> +#define USB_PORT_POWER_STATE_OFF	1

Just call the new field power_on (and make it bool rather than
unsigned).  Then these symbols won't be needed.

> @@ -2970,6 +2984,23 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
>  		udev->port_is_suspended = 1;
>  		msleep(10);
>  	}
> +
> +	/*
> +	 * Check whether current status is meeting requirement of
> +	 * usb port power off mechanism
> +	 */
> +	if (!udev->do_remote_wakeup
> +			&& !(dev_pm_qos_flags(&port_dev->dev,
> +			PM_QOS_FLAG_NO_POWER_OFF) == PM_QOS_FLAGS_ALL)

Why write it this complicated way?  Just use !=.

> +			&& udev->persist_enabled
> +			&& !status) {
> +		port_dev->power_state = USB_PORT_POWER_STATE_OFF;
> +		if (clear_port_feature(udev->parent, port1,
> +				USB_PORT_FEAT_POWER)) {
> +			port_dev->power_state = USB_PORT_POWER_STATE_ON;

Do this the other way around: If clear_port_feature() succeeds, clear 
port_dev->power_on.

> @@ -3094,6 +3144,25 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
>  	int		status;
>  	u16		portchange, portstatus;
>  
> +
> +	set_bit(port1, hub->busy_bits);
> +
> +	if (hub->ports[port1 - 1]->power_state == USB_PORT_POWER_STATE_OFF) {
> +		set_port_feature(udev->parent, port1, USB_PORT_FEAT_POWER);

At this point you should set the port's power_on flag.

> +
> +		/*
> +		 * Wait for usb hub port to be reconnected in order to make
> +		 * the resume procedure successful.
> +		 */
> +		status = usb_port_wait_for_connected(hub, port1);
> +		if (status < 0) {
> +			dev_dbg(&udev->dev, "can't get reconnection after setting port  power on, status %d\n",
> +					status);
> +			return status;
> +		}
> +		hub->ports[port1 - 1]->power_state = USB_PORT_POWER_STATE_ON;

Not here.  The way you've got it, the power_on flag will be wrong if 
usb_port_wait_for_connected fails.

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