Re: [PATCH v6 5/8] usb: add usb port auto power off mechanism
On 2013/1/22 5:30, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:04PM +0800, Lan Tianyu wrote: This patch is to add usb port auto power off mechanism. When usb device is suspending, usb core will suspend usb port and usb port runtime pm callback will clear PORT_POWER feature to power off port if all conditions were met. These conditions are remote wakeup disable, pm qos NO_POWER_OFF flag clear and persist enable. When it resumes, power on port again. Add did_runtime_put in the struct usb_port in order to call pm_runtime_get/put(portdev) paired during suspending and resuming. I don't understand what did_runtime_put is supposed to mean. Care to explain this better? Ok. Acked-by: Alan Stern st...@rowland.harvard.edu Acked-by: Rafael J. Wysocki rafael.j.wyso...@intel.com Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 67 --- drivers/usb/core/hub.h |9 +++ drivers/usb/core/port.c | 40 ++-- 3 files changed, 105 insertions(+), 11 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8c1f9a5..786db99 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -26,6 +26,7 @@ #include linux/mutex.h #include linux/freezer.h #include linux/random.h +#include linux/pm_qos.h #include asm/uaccess.h #include asm/byteorder.h @@ -108,7 +109,7 @@ MODULE_PARM_DESC(use_both_schemes, DECLARE_RWSEM(ehci_cf_port_reset_rwsem); EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); -#define HUB_DEBOUNCE_TIMEOUT 1500 +#define HUB_DEBOUNCE_TIMEOUT 2000 Why did you increase this timeout? You don't mention that above in the changelog entry. I will add this into change log. #define HUB_DEBOUNCE_STEP 25 #define HUB_DEBOUNCE_STABLE100 @@ -127,7 +128,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus) } /* Note that hdev or one of its children must be locked! */ -static struct usb_hub *hdev_to_hub(struct usb_device *hdev) +struct usb_hub *hdev_to_hub(struct usb_device *hdev) This needs a better name now that this is a global function. No one knows what a hdev is. Actually the routine will only be used in the driver/usb/core/(hub.c, port.c). Port also should be the part of hub, right? Moving port related code to port.c is to make code more clear. I am not sure whether we should rename it. If we renamed it, how about usb_hub_to_struct_hub? \ Should we do rename operation in a separate patch since hdev_to_hub() is called many places in the hub.c? { if (!hdev || !hdev-actconfig || !hdev-maxchild) return NULL; @@ -393,7 +394,7 @@ static int clear_hub_feature(struct usb_device *hdev, int feature) /* * USB 2.0 spec Section 11.24.2.2 */ -static int clear_port_feature(struct usb_device *hdev, int port1, int feature) +int clear_port_feature(struct usb_device *hdev, int port1, int feature) This is now a global function, please put usb_ infront of it. Same above? { return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1, @@ -718,11 +719,16 @@ int usb_hub_set_port_power(struct usb_device *hdev, int port1, bool set) { int ret; + struct usb_hub *hub = hdev_to_hub(hdev); + struct usb_port *port_dev = hub-ports[port1 - 1]; if (set) ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); else ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + + if (!ret) + port_dev-power_is_on = set; return ret; } @@ -802,7 +808,11 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay) dev_dbg(hub-intfdev, trying to enable port power on non-switchable hub\n); for (port1 = 1; port1 = hub-descriptor-bNbrPorts; port1++) - set_port_feature(hub-hdev, port1, USB_PORT_FEAT_POWER); + if (hub-ports[port1 - 1]-power_is_on) + set_port_feature(hub-hdev, port1, USB_PORT_FEAT_POWER); + else + clear_port_feature(hub-hdev, port1, + USB_PORT_FEAT_POWER); /* Wait at least 100 msec for power to become stable */ delay = max(pgood_delay, (unsigned) 100); @@ -1134,10 +1144,16 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) set_bit(port1, hub-change_bits); } else if (udev-persist_enabled) { + struct usb_port *port_dev = hub-ports[port1 - 1]; + #ifdef CONFIG_PM udev-reset_resume = 1; #endif - set_bit(port1, hub-change_bits); + /* Don't set the change_bits when the device +* was powered off. +
Re: [PATCH v6 5/8] usb: add usb port auto power off mechanism
On Tue, Jan 22, 2013 at 11:32:13PM +0800, Lan Tianyu wrote: On 2013/1/22 5:30, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:04PM +0800, Lan Tianyu wrote: @@ -127,7 +128,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus) } /* Note that hdev or one of its children must be locked! */ -static struct usb_hub *hdev_to_hub(struct usb_device *hdev) +struct usb_hub *hdev_to_hub(struct usb_device *hdev) This needs a better name now that this is a global function. No one knows what a hdev is. Actually the routine will only be used in the driver/usb/core/(hub.c, port.c). Port also should be the part of hub, right? Moving port related code to port.c is to make code more clear. I am not sure whether we should rename it. It is now a global symbol in the kernel name space, so yes, it should be renamed. If we renamed it, how about usb_hub_to_struct_hub? \ Should we do rename operation in a separate patch since hdev_to_hub() is called many places in the hub.c? That's fine with me. { if (!hdev || !hdev-actconfig || !hdev-maxchild) return NULL; @@ -393,7 +394,7 @@ static int clear_hub_feature(struct usb_device *hdev, int feature) /* * USB 2.0 spec Section 11.24.2.2 */ -static int clear_port_feature(struct usb_device *hdev, int port1, int feature) +int clear_port_feature(struct usb_device *hdev, int port1, int feature) This is now a global function, please put usb_ infront of it. Same above? Yes. -static int hub_port_debounce(struct usb_hub *hub, int port1) +int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected) I hate boolean flags in functions that do different things depending on the value. Can you just make two different functions here, and have them call this private one with the proper flag set? Sorry. I am not very sure I understand correctly. Do you mean to create two wraps which call hub_port_debounce()? Just like hub_port_debounce_be_counted() { hub_port_debounce(...,..., true); } hub_port_debounce_be_counted() { hub_port_debounce(...,..., false); } If you name the functions differently, yes :) @@ -3758,7 +3805,9 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) if (!(portchange USB_PORT_STAT_C_CONNECTION) (portstatus USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || (connection + == USB_PORT_STAT_CONNECTION)) Please do: if (!must_be_connected || (connection == USB_PORT_STAT_CONNECTION)) instead, that makes it much more readable. Oh. I originally do the same thing. But there is following code which requires this line to be more indention. This will cause this line over 80 characters. So I had to break this line. The above line, as written is under 80 characters, so I don't understand the issue. I finally find that if I just do following, it also can work. if (!must_be_connected || connection) stable_time += HUB_DEBOUNCE_STEP; Does this make sense? Since connection only will be assigned to the result of portstatus USB_PORT_STAT_CONNECTION. Connection is an enumerated type, please be explicit when testing it. thanks, greg k-h -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 5/8] usb: add usb port auto power off mechanism
On 2013/1/23 0:02, Greg KH wrote: On Tue, Jan 22, 2013 at 11:32:13PM +0800, Lan Tianyu wrote: On 2013/1/22 5:30, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:04PM +0800, Lan Tianyu wrote: @@ -127,7 +128,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus) } /* Note that hdev or one of its children must be locked! */ -static struct usb_hub *hdev_to_hub(struct usb_device *hdev) +struct usb_hub *hdev_to_hub(struct usb_device *hdev) This needs a better name now that this is a global function. No one knows what a hdev is. Actually the routine will only be used in the driver/usb/core/(hub.c, port.c). Port also should be the part of hub, right? Moving port related code to port.c is to make code more clear. I am not sure whether we should rename it. It is now a global symbol in the kernel name space, so yes, it should be renamed. If we renamed it, how about usb_hub_to_struct_hub? \ Should we do rename operation in a separate patch since hdev_to_hub() is called many places in the hub.c? That's fine with me. { if (!hdev || !hdev-actconfig || !hdev-maxchild) return NULL; @@ -393,7 +394,7 @@ static int clear_hub_feature(struct usb_device *hdev, int feature) /* * USB 2.0 spec Section 11.24.2.2 */ -static int clear_port_feature(struct usb_device *hdev, int port1, int feature) +int clear_port_feature(struct usb_device *hdev, int port1, int feature) This is now a global function, please put usb_ infront of it. Same above? Yes. -static int hub_port_debounce(struct usb_hub *hub, int port1) +int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected) I hate boolean flags in functions that do different things depending on the value. Can you just make two different functions here, and have them call this private one with the proper flag set? Sorry. I am not very sure I understand correctly. Do you mean to create two wraps which call hub_port_debounce()? Just like hub_port_debounce_be_counted() { hub_port_debounce(...,..., true); } hub_port_debounce_be_counted() { hub_port_debounce(...,..., false); } If you name the functions differently, yes :) @@ -3758,7 +3805,9 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) if (!(portchange USB_PORT_STAT_C_CONNECTION) (portstatus USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || (connection + == USB_PORT_STAT_CONNECTION)) Please do: if (!must_be_connected || (connection == USB_PORT_STAT_CONNECTION)) instead, that makes it much more readable. Oh. I originally do the same thing. But there is following code which requires this line to be more indention. This will cause this line over 80 characters. So I had to break this line. The above line, as written is under 80 characters, so I don't understand the issue. If I do following, scripts/checkpatch.pl will complain over 80 characters. @@ -3767,7 +3814,9 @@ if (!(portchange USB_PORT_STAT_C_CONNECTION) (portstatus USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || + (connection == USB_PORT_STAT_CONNECTION)) + stable_time += HUB_DEBOUNCE_STEP; if (stable_time = HUB_DEBOUNCE_STABLE) break; } else { WARNING: line over 80 characters #203: FILE: drivers/usb/core/hub.c:3818: + (connection == USB_PORT_STAT_CONNECTION)) If I use (connection USB_PORT_STAT_CONNECTION)), that will be ok. I am curious about that checkpatch.pl considers a space or tab as a character? I finally find that if I just do following, it also can work. if (!must_be_connected || connection) stable_time += HUB_DEBOUNCE_STEP; Does this make sense? Since connection only will be assigned to the result of portstatus USB_PORT_STAT_CONNECTION. Connection is an enumerated type, please be explicit when testing it. thanks, greg k-h -- Best Regards Tianyu Lan linux kernel enabling team -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 5/8] usb: add usb port auto power off mechanism
On Wed, Jan 23, 2013 at 12:58:09AM +0800, Lan Tianyu wrote: On 2013/1/23 0:02, Greg KH wrote: On Tue, Jan 22, 2013 at 11:32:13PM +0800, Lan Tianyu wrote: On 2013/1/22 5:30, Greg KH wrote: @@ -3758,7 +3805,9 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) if (!(portchange USB_PORT_STAT_C_CONNECTION) (portstatus USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || (connection + == USB_PORT_STAT_CONNECTION)) Please do: if (!must_be_connected || (connection == USB_PORT_STAT_CONNECTION)) instead, that makes it much more readable. Oh. I originally do the same thing. But there is following code which requires this line to be more indention. This will cause this line over 80 characters. So I had to break this line. The above line, as written is under 80 characters, so I don't understand the issue. If I do following, scripts/checkpatch.pl will complain over 80 characters. @@ -3767,7 +3814,9 @@ if (!(portchange USB_PORT_STAT_C_CONNECTION) (portstatus USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || + (connection == USB_PORT_STAT_CONNECTION)) + stable_time += HUB_DEBOUNCE_STEP; if (stable_time = HUB_DEBOUNCE_STABLE) break; } else { WARNING: line over 80 characters #203: FILE: drivers/usb/core/hub.c:3818: + (connection == USB_PORT_STAT_CONNECTION)) Of course, which is why I didn't say to do that :) See above for where to line up the line with the previous one, showing that it all can fit just fine within 80 characters. If I use (connection USB_PORT_STAT_CONNECTION)), that will be ok. I am curious about that checkpatch.pl considers a space or tab as a character? It understands the difference between tabs and spaces properly. thanks, greg k-h -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 5/8] usb: add usb port auto power off mechanism
On 2013/1/23 1:18, Greg KH wrote: On Wed, Jan 23, 2013 at 12:58:09AM +0800, Lan Tianyu wrote The above line, as written is under 80 characters, so I don't understand the issue. If I do following, scripts/checkpatch.pl will complain over 80 characters. @@ -3767,7 +3814,9 @@ if (!(portchange USB_PORT_STAT_C_CONNECTION) (portstatus USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || + (connection == USB_PORT_STAT_CONNECTION)) + stable_time += HUB_DEBOUNCE_STEP; if (stable_time = HUB_DEBOUNCE_STABLE) break; } else { WARNING: line over 80 characters #203: FILE: drivers/usb/core/hub.c:3818: + (connection == USB_PORT_STAT_CONNECTION)) Of course, which is why I didn't say to do that :) See above for where to line up the line with the previous one, showing that it all can fit just fine within 80 characters. Ok. I get it. learn one more trick. :) Now I have two solutions. Which one do you think more readable? @@ -3740,7 +3814,9 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) if (!(portchange USB_PORT_STAT_C_CONNECTION) (portstatus USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || + (connection USB_PORT_STAT_CONNECTION)) + stable_time += HUB_DEBOUNCE_STEP; if (stable_time = HUB_DEBOUNCE_STABLE) break; @@ -3740,7 +3814,9 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) if (!(portchange USB_PORT_STAT_C_CONNECTION) (portstatus USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || +(connection == USB_PORT_STAT_CONNECTION)) + stable_time += HUB_DEBOUNCE_STEP; if (stable_time = HUB_DEBOUNCE_STABLE) If I use (connection USB_PORT_STAT_CONNECTION)), that will be ok. I am curious about that checkpatch.pl considers a space or tab as a character? It understands the difference between tabs and spaces properly. thanks, greg k-h -- Best Regards Tianyu Lan linux kernel enabling team -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 5/8] usb: add usb port auto power off mechanism
On Mon, Jan 21, 2013 at 10:18:04PM +0800, Lan Tianyu wrote: This patch is to add usb port auto power off mechanism. When usb device is suspending, usb core will suspend usb port and usb port runtime pm callback will clear PORT_POWER feature to power off port if all conditions were met. These conditions are remote wakeup disable, pm qos NO_POWER_OFF flag clear and persist enable. When it resumes, power on port again. Add did_runtime_put in the struct usb_port in order to call pm_runtime_get/put(portdev) paired during suspending and resuming. I don't understand what did_runtime_put is supposed to mean. Care to explain this better? Acked-by: Alan Stern st...@rowland.harvard.edu Acked-by: Rafael J. Wysocki rafael.j.wyso...@intel.com Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 67 --- drivers/usb/core/hub.h |9 +++ drivers/usb/core/port.c | 40 ++-- 3 files changed, 105 insertions(+), 11 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8c1f9a5..786db99 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -26,6 +26,7 @@ #include linux/mutex.h #include linux/freezer.h #include linux/random.h +#include linux/pm_qos.h #include asm/uaccess.h #include asm/byteorder.h @@ -108,7 +109,7 @@ MODULE_PARM_DESC(use_both_schemes, DECLARE_RWSEM(ehci_cf_port_reset_rwsem); EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); -#define HUB_DEBOUNCE_TIMEOUT 1500 +#define HUB_DEBOUNCE_TIMEOUT 2000 Why did you increase this timeout? You don't mention that above in the changelog entry. #define HUB_DEBOUNCE_STEP 25 #define HUB_DEBOUNCE_STABLE 100 @@ -127,7 +128,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus) } /* Note that hdev or one of its children must be locked! */ -static struct usb_hub *hdev_to_hub(struct usb_device *hdev) +struct usb_hub *hdev_to_hub(struct usb_device *hdev) This needs a better name now that this is a global function. No one knows what a hdev is. { if (!hdev || !hdev-actconfig || !hdev-maxchild) return NULL; @@ -393,7 +394,7 @@ static int clear_hub_feature(struct usb_device *hdev, int feature) /* * USB 2.0 spec Section 11.24.2.2 */ -static int clear_port_feature(struct usb_device *hdev, int port1, int feature) +int clear_port_feature(struct usb_device *hdev, int port1, int feature) This is now a global function, please put usb_ infront of it. { return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1, @@ -718,11 +719,16 @@ int usb_hub_set_port_power(struct usb_device *hdev, int port1, bool set) { int ret; + struct usb_hub *hub = hdev_to_hub(hdev); + struct usb_port *port_dev = hub-ports[port1 - 1]; if (set) ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); else ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + + if (!ret) + port_dev-power_is_on = set; return ret; } @@ -802,7 +808,11 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay) dev_dbg(hub-intfdev, trying to enable port power on non-switchable hub\n); for (port1 = 1; port1 = hub-descriptor-bNbrPorts; port1++) - set_port_feature(hub-hdev, port1, USB_PORT_FEAT_POWER); + if (hub-ports[port1 - 1]-power_is_on) + set_port_feature(hub-hdev, port1, USB_PORT_FEAT_POWER); + else + clear_port_feature(hub-hdev, port1, + USB_PORT_FEAT_POWER); /* Wait at least 100 msec for power to become stable */ delay = max(pgood_delay, (unsigned) 100); @@ -1134,10 +1144,16 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) set_bit(port1, hub-change_bits); } else if (udev-persist_enabled) { + struct usb_port *port_dev = hub-ports[port1 - 1]; + #ifdef CONFIG_PM udev-reset_resume = 1; #endif - set_bit(port1, hub-change_bits); + /* Don't set the change_bits when the device + * was powered off. + */ + if (port_dev-power_is_on) + set_bit(port1, hub-change_bits); } else { /* The power session is gone; tell khubd */ @@ -2012,7 +2028,10 @@ void usb_disconnect(struct usb_device **pdev) sysfs_remove_link(udev-dev.kobj, port); sysfs_remove_link(port_dev-dev.kobj, device); - pm_runtime_put(port_dev-dev); + if