Re: [PATCH 0/3] ACPI / bind: Use struct acpi_device pointers instead of ACPI handles
On 2013年11月29日 08:36, Rafael J. Wysocki wrote: Hi, Now that we store a pointer to struct acpi_device as the ACPI companion in struct device, the code making associations between physical devices and ACPI device objects can be modified to work with struct acpi_device pointers instead of ACPI handles too. The first two of the following patches make these changes and the third one is just a related cleanup. [1/3] ACPI / bind: Replace .find_device in struct acpi_bus_type with .find_companion [2/3] ACPI / bind: Modify acpi_bind_one() to take a struct acpi_device pointer as the second argument. [3/3] ACPI / bind: Move acpi_get_child() to ide-acpi.c which is the only remaining user of that function. Test usb/ACPI bind part, it works normally. Tested-by: Lan Tianyu tianyu@intel.com The patches are on top of linux-pm.git/linux-next. Please let me know if you see any problems in them. Thanks! -- Best regards Tianyu Lan -- 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: [RFC Patch] USB: Add check for portnum in the usb_acpi_find_device()
On 2013/5/31 19:18 Greg KH wrote the following: On Fri, May 31, 2013 at 02:18:06PM +0800, Lan Tianyu wrote: This patch is to add a check of portnum which from the usb port dev's name. Why do we need this now? The portnum will be used as array index for struct usb_hub-ports in the usb_set_hub_port_connect_type(). Is something failing today without this check? We don't add code to the kernel until we need it... No, actually current code will not fail. The patch is the result of analysis tools Klockwork which is pushed by some QAs. I just notice you have said to be over-eager in checking parameters that we have full control of is not needed at all. So please ignore this. Sorry for noise. http://marc.info/?l=linux-usbm=136984950910015w=2 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
[RFC Patch] USB: Add check for portnum in the usb_acpi_find_device()
This patch is to add a check of portnum which from the usb port dev's name. The portnum will be used as array index for struct usb_hub-ports in the usb_set_hub_port_connect_type(). Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/usb-acpi.c |3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 255c144..ec0e7cf 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -183,6 +183,9 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) /* Get the struct usb_device point of port's hub */ udev = to_usb_device(dev-parent-parent); + if (port_num == 0 || port_num udev-maxchild) + return -EINVAL; + /* * The root hub ports' parent is the root hub. The non-root-hub * ports' parent is the parent hub port which the hub is -- 1.7.10.4 -- 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 2/4] usb: introduce usb force power off mechanism
On 2013/3/30 4:24, Alan Stern wrote: On Fri, 29 Mar 2013, Sarah Sharp wrote: Also, bear in mind that the proposed patch does not give userspace a way to power off ports via usbfs. What the new code does is a power-off reset -- it turns off power to the port, waits a short time, and then turns power back on. I think we need two separate IOCTLs: turn off the port power and turn it on. Then we get the manual port power off for our QA testing, distros can make interesting policies about manually powering off ports, and userspace can choose how long they want the port to be off. After all, different devices may need a longer powered-off period than others. Or one port-power IOCTL that takes the setting as an argument. Yes, this would be more flexible than a power-off reset. Hi Alan Sarah: I just recall why I put power off and power on in one ioctl. At first, I also tried to make power on and power off into two ioctls. But I found after powering off a device, the usbfs device node will be removed and so can't power on the port via the same usbfs node. For this point, we should add usbfs node for usb port? Alan Stern -- 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 2/4] usb: introduce usb force power off mechanism
On 2013/4/1 23:12, Alan Stern wrote: On Mon, 1 Apr 2013, Lan Tianyu wrote: On 2013年03月30日 01:23, Alan Stern wrote: On Fri, 29 Mar 2013, Sarah Sharp wrote: However, what happens if you echo 0 to pm_qos_no_power_off, the power/control is set to auto, and there's a suspended USB device attached to the port with remote wakeup enabled? Will the port be powered off? I don't think it will with the current patchset, but I will have to double check. It shouldn't be, because remote wakeup is enabled. But what about the case where remote wakeup is disabled? Will writing a 0 to pm_qos_no_power_off cause the power to be turned off? Or what about the case where there's no device attached to the port? I guess both questions amount to the same thing: When the user writes to a pm_qos_* file, does the code call pm_runtime_idle? Usb port's initial usage count is 0. For port attached with usb port, when usb device is connected, the usb port's usage count is increased by one. During device's suspend, its usage count would be decreased to 0 and powered of only when remote wakeup disable, persist enable and PM Qos NO_POWER_OFF unsetting. I already know all this. During pm_qos_* file changing, pm_runtime_get_sync/put(port_dev) will be done in the dev_pm_qos_update_flags(). The port's usage count would be increased and decreased by 1. Whether the port's pm_runtime_idle would be called depends on port's usage count to be set to 0. That answers my question. If the usb port has already been powered off(port usage count is already set to 0), it would be powered on first and powered off depending the PM Qos NO_POWER_OFF flag value. Obviously. If the usb port wasn't powered off, this mean the usb port didn't meet power off condition() and its usage count was still greater than 0 So during changing flag, only usage count was changed and no actual operation. No, because one of the power off conditions is that the NO_POWER_OFF flag must be clear. If that flag was set, the port won't be powered off even though the usage count is equal to 0. If the write to the pm_qos_* file then clears the flag, the port _will_ get powered off. Hi Alan: I think current code can't achieve that power off port(whose child device was already suspended but it was not powered off due to NO_POWER_OFF flag setting.) via clearing NO_POWER_OFF flag. Because at that moment, its usage count can't be 0. At last, it should be 1 or large. port's pm_runtime_idle will not be called. Further thinking, now we call pm_runtime_put_sync() in the usb_port_suspend() when persist enable, do_remote_wakeup disable and PM Qos NO_POWER_OFF flag cleared. But PM Qos NO_POWER_OFF flag will also will be checked in the usb_port_runtime_suspend(). This seems redundant. From my opinion, the PM Qos check in the usb_port_suspend() should be removed and port usage count will reach 0 when persist enable and remote_wakeup disable. Whether power off or not totally depends on the PM Qos flag in the usb_port_runtime_suspend(). For NO_POWER_OFF flag setting case during usb device being suspend, the port's usage count will be 0 but its runtime status is still active due to flag being set and usb_port_runtime_suspend() returns -EAGAIN. At this time, clearing the flag and the port can be powered off. Does this make sense? For empty port, Only when PM Qos NO_POWER_OFF flag value is set to 0, the port will be power off. Alan Stern -- 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 2/4] usb: introduce usb force power off mechanism
On 2013年03月29日 22:11, Alan Stern wrote: On Fri, 29 Mar 2013, Lan Tianyu wrote: Actually, I exposed pm qos flags for usb port via dev_pm_qos_expose_flags(). It creates power/pm_qos_no_power_off under usb port sysfs directory. User can echo 0 pm_qos_no_power_off to power off the empty port. Before it's too late, we should consider changing the flag's name. Writing 0 to a file named pm_qos_no_power_off is a double negative, which is always awkward to think about. Instead, how about calling the file pm_qos_allow_power_off? Will the PM-QOS system allow something like that, i.e., something that is the opposite of a constraint? If not, how about naming it pm_qos_keep_power_on? This is PM core sysfs attribute and I am not sure that this can be changed. CC: Rafael. Alan Stern -- Best regards Tianyu Lan -- 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 2/4] usb: introduce usb force power off mechanism
On 2013年03月30日 01:23, Alan Stern wrote: On Fri, 29 Mar 2013, Sarah Sharp wrote: However, what happens if you echo 0 to pm_qos_no_power_off, the power/control is set to auto, and there's a suspended USB device attached to the port with remote wakeup enabled? Will the port be powered off? I don't think it will with the current patchset, but I will have to double check. It shouldn't be, because remote wakeup is enabled. But what about the case where remote wakeup is disabled? Will writing a 0 to pm_qos_no_power_off cause the power to be turned off? Or what about the case where there's no device attached to the port? I guess both questions amount to the same thing: When the user writes to a pm_qos_* file, does the code call pm_runtime_idle? Usb port's initial usage count is 0. For port attached with usb port, when usb device is connected, the usb port's usage count is increased by one. During device's suspend, its usage count would be decreased to 0 and powered of only when remote wakeup disable, persist enable and PM Qos NO_POWER_OFF unsetting. During pm_qos_* file changing, pm_runtime_get_sync/put(port_dev) will be done in the dev_pm_qos_update_flags(). The port's usage count would be increased and decreased by 1. Whether the port's pm_runtime_idle would be called depends on port's usage count to be set to 0. If the usb port has already been powered off(port usage count is already set to 0), it would be powered on first and powered off depending the PM Qos NO_POWER_OFF flag value. If the usb port wasn't powered off, this mean the usb port didn't meet power off condition() and its usage count was still greater than 0 So during changing flag, only usage count was changed and no actual operation. For empty port, Only when PM Qos NO_POWER_OFF flag value is set to 0, the port will be power off. Alan Stern -- Best regards Tianyu Lan -- 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 2/4] usb: introduce usb force power off mechanism
On 2013/3/29 6:43, Sarah Sharp wrote: On Thu, Mar 28, 2013 at 05:00:23PM -0400, Alan Stern wrote: On Thu, 28 Mar 2013, Sarah Sharp wrote: On Thu, Mar 28, 2013 at 01:11:02AM +0800, Lan Tianyu wrote: Some devices' firmware will be broken at some points. Power down and power on device can help device to rework in this case. This patch is to add ioctl cmd USBDEVFS_POWER_RESET for usbfs node to repower usb device. First, call hub_port_logical_disconnect() to disconnect device. Second, Power down and up usb port. I don't think this is the right approach. We want to be able to power off a port, even if no devices are attached. One of the use case scenarios we discussed was allowing distros to turn off empty USB ports according to some policy (e.g. screen blank, lost bluetooth connection to their phone that indicates the user walked away from the computer, server admin wants to save power, etc). With the current patches in 3.9, I don't see a way we can do that. The ports have power/control, which can only be set to 'on' or 'auto'. You should add an 'off' option to that file. Won't empty ports naturally be powered off by runtime PM, so long as there isn't a PM_QOS constraint to prevent it? The user (or system software) may need to write auto to the port's power/control file, which may require us to put the ports on the usb_bus_type or to make them class devices. But however we do it, this should work automatically. Now I'm a bit confused and I'll have to look at the code again. I can't remember if Tianyu made the kernel add a PM_QOS constraint to set the no power off flag for hot pluggable ports, or if we expect userspace to use the connect type sysfs file to figure out it shouldn't write auto to the file. Actually, I exposed pm qos flags for usb port via dev_pm_qos_expose_flags(). It creates power/pm_qos_no_power_off under usb port sysfs directory. User can echo 0 pm_qos_no_power_off to power off the empty port. If the kernel isn't adding that constraint, then Tianyu *really* needs to document that. power/pm_qos_no_power_off is device's power attribute and it has been described in the sysfs-devices-power. I think I should mention in the usb/power-management.text. Sarah Sharp -- 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 2/4] usb: introduce usb force power off mechanism
On 2013/3/28 2:45, Alan Stern wrote: +int usb_hub_port_power_reset(struct usb_device *hdev, int port1) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + struct usb_interface *intf = to_usb_interface(hub-intfdev); + int ret; + + usb_autopm_get_interface(intf); What happens if hdev is NULL? Yes, This will be a problem. The repower cmd to root hub should be ignored. + hub_port_logical_disconnect(hub, port1); + ret = usb_hub_set_port_power(hdev, port1, false); How long do you think the power should remain turned off? This code will leave it off for only a few milliseconds at most. That may not even be long enough for the voltage to drop all the way to 0. The delay probably should be at least 100 ms. Maybe more, I don't know. I think this depends on the device. I don't find the answer on spec. I find the cool down delay of over-current for port is 100ms and one for hub is 500ms. Could we reference these delay? 500ms would be safe. + ret |= usb_hub_set_port_power(hdev, port1, true); Don't use |=. Skip the second call if the first one fails. OK. + usb_autopm_put_interface(intf); + + return ret; +} If you placed this function later on in the source file, you wouldn't need the forward declaration of hub_port_logical_disconnect(). Yes, I will do this. Alan Stern -- 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 2/4] usb: introduce usb force power off mechanism
On 2013/3/28 22:46, Alan Stern wrote: On Thu, 28 Mar 2013, Lan Tianyu wrote: How long do you think the power should remain turned off? This code will leave it off for only a few milliseconds at most. That may not even be long enough for the voltage to drop all the way to 0. The delay probably should be at least 100 ms. Maybe more, I don't know. I think this depends on the device. I don't find the answer on spec. I find the cool down delay of over-current for port is 100ms and one for hub is 500ms. Could we reference these delay? 500ms would be safe. Okay, then use 500 ms. Alan Stern Ok. About the path usb: Add usb port system pm support, do you think it's ok? On 2013/3/28 2:47, Alan Stern wrote: What happens if there's no device plugged in to the port, but the hub is enabled for remote wakeup? How will the hub be able to detect a plug-in event if the port isn't powered? Alan Stern Hi Alan: Great thanks for your review. The hub will not detect the new devices. From my opinion, this depends on the user space since the port only will be powered off when pm qos NO_POWER_OFF flag is unset(it is default to be set). If unset the flag, losing plug-in event should have been took into account. -- 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 2/4] usb: introduce usb force power off mechanism
On 2013/3/29 0:50, Alan Stern wrote: On Fri, 29 Mar 2013, Lan Tianyu wrote: About the path usb: Add usb port system pm support, do you think it's ok? Generally yes. But why doesn't usb_port_system_suspend check for any PM_QOS constraints? Either on the port itself or on the child device. Because usb_port_runtime_suspend() will PM Qos flags. If add check in usb_port_system_suspend(), PM Qos flags would be checked twice and this seems redundant. Alan Stern -- 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 2/4] usb: introduce usb force power off mechanism
On 2013/3/29 1:49, Alan Stern wrote: On Fri, 29 Mar 2013, Lan Tianyu wrote: On 2013/3/29 0:50, Alan Stern wrote: On Fri, 29 Mar 2013, Lan Tianyu wrote: About the path usb: Add usb port system pm support, do you think it's ok? Generally yes. But why doesn't usb_port_system_suspend check for any PM_QOS constraints? Either on the port itself or on the child device. Because usb_port_runtime_suspend() will PM Qos flags. If add check in usb_port_system_suspend(), PM Qos flags would be checked twice and this seems redundant. Yes, that's right -- I noticed this the first time I read the patch and then forgot it again. I don't see any other problems with that patch. Alan Stern Ok. I just refresh patch usb: introduce usb force power off mechanism Please have a look. From 16f5c7c6dd00830530a9ac758af25b575e0b8731 Mon Sep 17 00:00:00 2001 From: Lan Tianyu tianyu@intel.com Date: Tue, 26 Feb 2013 11:12:09 +0800 Subject: [PATCH] usb: introduce usb force power off mechanism Some devices' firmware will be broken at some points. Power down and power on device can help device to rework in this case. This patch is to add ioctl cmd USBDEVFS_POWER_RESET for usbfs node to repower usb device. First, call hub_port_logical_disconnect() to disconnect device. Second, Power down and up usb port. This patch is also helpful fo some QAs who want to do hcd's memleak test(Plug and unplug device thousand times.) Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/devio.c | 16 drivers/usb/core/hub.c| 27 +++ drivers/usb/core/usb.h|2 ++ include/uapi/linux/usbdevice_fs.h |1 + 4 files changed, 46 insertions(+) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8823e98..951e904 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1102,6 +1102,17 @@ static int proc_resetdevice(struct dev_state *ps) return usb_reset_device(ps-dev); } +static int proc_resetdevicepower(struct dev_state *ps) +{ + struct usb_device *udev = ps-dev; + struct usb_device *hdev = udev-parent; + + if (!hdev) + return -EINVAL; + + return usb_hub_port_power_reset(hdev, udev-portnum); +} + static int proc_setintf(struct dev_state *ps, void __user *arg) { struct usbdevfs_setinterface setintf; @@ -2011,6 +2022,11 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, ret = proc_resetdevice(ps); break; + case USBDEVFS_POWER_RESET: + snoop(dev-dev, %s: RESET POWER\n, __func__); + ret = proc_resetdevicepower(ps); + break; + case USBDEVFS_CLEAR_HALT: snoop(dev-dev, %s: CLEAR_HALT\n, __func__); ret = proc_clearhalt(ps, p); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6b7f5b9..9729e36 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -948,6 +948,33 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) } /** + * usb_hub_port_power_reset - repower hub port + * @hdev: USB device belonging to the usb hub + * @port1: port num to be repowered. + * + * This routine will try to disconnect the device on + * the port and then repower the port. + */ +int usb_hub_port_power_reset(struct usb_device *hdev, int port1) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + struct usb_interface *intf = to_usb_interface(hub-intfdev); + int ret; + + usb_autopm_get_interface(intf); + hub_port_logical_disconnect(hub, port1); + ret = usb_hub_set_port_power(hdev, port1, false); + if (!ret) { + /* Wait for power down device */ + msleep(500); + ret = usb_hub_set_port_power(hdev, port1, true); + } + usb_autopm_put_interface(intf); + + return ret; +} + +/** * usb_remove_device - disable a device's port on its parent hub * @udev: device to be disabled and removed * Context: @udev locked, must be able to sleep. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index a7f20bd..4e7785c 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -185,6 +185,8 @@ extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, enum usb_port_connect_type type); extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, struct usb_hub_descriptor *desc); +extern int usb_hub_port_power_reset(struct usb_device *hdev, + int port1); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h index 0c65e4b..b6e0d17 100644 --- a/include/uapi/linux/usbdevice_fs.h +++ b/include/uapi/linux/usbdevice_fs.h @@ -176,5 +176,6 @@ struct usbdevfs_disconnect_claim { #define USBDEVFS_RELEASE_PORT _IOR('U', 25, unsigned int) #define
Re: [PATCH 4/4] usb: register usb port to usb_bus_type
On 2013/3/29 2:21, Greg KH wrote: What does it look like if you reverse the naming scheme (hub dev name + port)? Doesn't that show the devices in a bit more logical way? Hi Greg: Do you mean e.g port1.2-1, originally it's port2-1.1. 2-1 is hub dev name? No, I mean 2-1.port1 as these are the ports on the device, the device prefix should go first, right? If right, how about root hub port and it should be port2.usb1? usb1.port2 Ok. I get it. Yes, this looks more logical. Thanks. Will refresh soon. -- 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 4/4] usb: register usb port to usb_bus_type
On 2013/3/29 2:44, Alan Stern wrote: On Thu, 28 Mar 2013, Greg KH wrote: ls /sys/bus/usb/devices 1-0:1.02-0:1.0 port1-1 port1-1.3 port2-1.2 port2-2 port4-3 1-12-1 port1-1.1port1-1.4 port2-1.3 port3-1 port4-4 1-1.1 2-1:1.0 port1-1.2port1-1.5 port2-1.4 port3-2 usb1 1-1:1.03-0:1.0 port1-1.2.1 port1-1.6 port2-1.5 port3-3 usb2 1-1.1:1.0 3-1 port1-1.2.2 port1-2port2-1.6 port3-4 usb3 1-1.2 3-1:1.0 port1-1.2.3 port2-1port2-1.7 port4-1 usb4 1-1.2:1.0 4-0:1.0 port1-1.2.4 port2-1.1 port2-1.8 port4-2 What does it look like if you reverse the naming scheme (hub dev name + port)? Doesn't that show the devices in a bit more logical way? Hi Greg: Do you mean e.g port1.2-1, originally it's port2-1.1. 2-1 is hub dev name? No, I mean 2-1.port1 as these are the ports on the device, the device prefix should go first, right? If right, how about root hub port and it should be port2.usb1? usb1.port2 Is this a good idea? There are userspace programs that look through the list of files in /sys/bus/usb/devices, and they probably expect filenames beginning with a number or with 'usb' to be USB devices and After updating ls /sys/bus/usb/devices 1-0:1.0 1-1.1:1.0 1-1.4 1-1.port3 2-1:1.02-1.6 2-1.port2 2-1.port6 usb1.port1 usb2.port1 usb3.port1 usb4 usb4.port4 1-1 1-1.1:1.1 1-1.4:1.0 1-1.port4 2-1.5 2-1.6:1.0 2-1.port3 3-0:1.0usb1.port2 usb2.port2 usb3.port2 usb4.port1 1-1.11-1.2 1-1.port1 2-0:1.02-1.5:1.0 2-1.6:1.1 2-1.port4 4-0:1.0usb1.port3 usb2.port3 usb3.port3 usb4.port2 1-1:1.0 1-1.2:1.0 1-1.port2 2-12-1.5:1.1 2-1.port1 2-1.port5 usb1 usb2usb3usb3.port4 usb4.port3 interfaces. Alan Stern -- 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 4/4] usb: register usb port to usb_bus_type
On 2013/3/29 2:53, Greg KH wrote: On Thu, Mar 28, 2013 at 02:44:01PM -0400, Alan Stern wrote: On Thu, 28 Mar 2013, Greg KH wrote: ls /sys/bus/usb/devices 1-0:1.02-0:1.0 port1-1 port1-1.3 port2-1.2 port2-2 port4-3 1-12-1 port1-1.1port1-1.4 port2-1.3 port3-1 port4-4 1-1.1 2-1:1.0 port1-1.2port1-1.5 port2-1.4 port3-2 usb1 1-1:1.03-0:1.0 port1-1.2.1 port1-1.6 port2-1.5 port3-3 usb2 1-1.1:1.0 3-1 port1-1.2.2 port1-2port2-1.6 port3-4 usb3 1-1.2 3-1:1.0 port1-1.2.3 port2-1port2-1.7 port4-1 usb4 1-1.2:1.0 4-0:1.0 port1-1.2.4 port2-1.1 port2-1.8 port4-2 What does it look like if you reverse the naming scheme (hub dev name + port)? Doesn't that show the devices in a bit more logical way? Hi Greg: Do you mean e.g port1.2-1, originally it's port2-1.1. 2-1 is hub dev name? No, I mean 2-1.port1 as these are the ports on the device, the device prefix should go first, right? If right, how about root hub port and it should be port2.usb1? usb1.port2 Is this a good idea? There are userspace programs that look through the list of files in /sys/bus/usb/devices, and they probably expect filenames beginning with a number or with 'usb' to be USB devices and interfaces. What userspace programs? And if they do that, then we shouldn't put the ports in here at all. This means usb port should be assigned to usb_bus_type. How about creating a usb_port class and assign usb port devices to it? ATA layer does something like this. 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 2/4] usb: introduce usb force power off mechanism
On 2013/3/29 3:38, Alan Stern wrote: On Fri, 29 Mar 2013, Lan Tianyu wrote: Ok. I just refresh patch usb: introduce usb force power off mechanism Please have a look. From 16f5c7c6dd00830530a9ac758af25b575e0b8731 Mon Sep 17 00:00:00 2001 From: Lan Tianyu tianyu@intel.com Date: Tue, 26 Feb 2013 11:12:09 +0800 Subject: [PATCH] usb: introduce usb force power off mechanism Some devices' firmware will be broken at some points. Power down and power on device can help device to rework in this case. This patch is to add ioctl cmd USBDEVFS_POWER_RESET for usbfs node to repower usb device. First, call hub_port_logical_disconnect() to disconnect device. Second, Power down and up usb port. This patch is also helpful fo some QAs who want to do hcd's memleak test(Plug and unplug device thousand times.) Signed-off-by: Lan Tianyu tianyu@intel.com ... --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -185,6 +185,8 @@ extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, enum usb_port_connect_type type); extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, struct usb_hub_descriptor *desc); +extern int usb_hub_port_power_reset(struct usb_device *hdev, + int port1); This can all go on one line. It looks okay. When you test it, does the attached device get detected and initialized properly? I test usb2.0 key on my machine. It works. Alan Stern -- 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 3/4] usb: Add usb port system pm support
On 2013/3/29 4:47, Sarah Sharp wrote: On Thu, Mar 28, 2013 at 07:58:47AM +0800, Lan Tianyu wrote: On 2013/3/28 2:47, Alan Stern wrote: On Thu, 28 Mar 2013, Lan Tianyu wrote What happens if there's no device plugged in to the port, but the hub is enabled for remote wakeup? How will the hub be able to detect a plug-in event if the port isn't powered? Alan Stern Hi Alan: Great thanks for your review. The hub will not detect the new devices. From my opinion, this depends on the user space since the port only will be powered off when pm qos NO_POWER_OFF flag is unset(it is default to be set). If unset the flag, losing plug-in event should have been took into account. So basically, you're saying that any new distro policy that turns off port power will need to re-enable it if the user wants hotplug events from a hub? I think that's a very important thing to document. I really think we need to add more description about the port power off mechanisms to Documentation/usb/power-management.txt. There's a little bit in Documentation/ABI/testing/sysfs-bus-usb, but since this mechanism is so new, I think we need to educate distro users on its effects and suggestions on how to use it. Can you take a first stab at an overview, and I'll let you know what's missing? That's good idea. Ok. I will do that. Sarah Sharp -- 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
[PATCH 0/4] usb: remote_wakeup code clean up and usb port related feature
PATCH 1 is for code clean up. PATCH 2~3 is to introduce usb port power off new feature PATCH 4 is to fix usb port doesn't register to any bus_type usb: add usb_enable/disable_remote_wakeup() usb: introduce usb force power off mechanism usb: Add usb port system pm support usb: register usb port to usb_bus_type -- 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
[PATCH 1/4] usb: add usb_enable/disable_remote_wakeup()
usb2.0 and usb3.0 devices have different ways to enalbe/disable remote wakeup. This patch is to put both their operations into the seperate functions. Otherwise, usb_control_msg() has some long arguments and are usually nested some indentations. So encapsulating it into seperate functions would be convienient to use and more readable. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 136 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7815462..6b7f5b9 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2826,22 +2826,72 @@ void usb_enable_ltm(struct usb_device *udev) EXPORT_SYMBOL_GPL(usb_enable_ltm); #ifdef CONFIG_USB_SUSPEND -/* - * usb_disable_function_remotewakeup - disable usb3.0 - * device's function remote wakeup - * @udev: target device - * - * Assume there's only one function on the USB 3.0 - * device and disable remote wake for the first - * interface. FIXME if the interface association - * descriptor shows there's more than one function. - */ -static int usb_disable_function_remotewakeup(struct usb_device *udev) +static int usb_disable_remote_wakeup(struct usb_device *udev) { - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, - USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + int status = 0; + u16 devstatus; + + if (udev-speed != USB_SPEED_SUPER) { + status = usb_get_status(udev, USB_RECIP_DEVICE, 0, devstatus); + le16_to_cpus(devstatus); + if (!status devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* +* Assume there's only one function on the USB 3.0 +* device and disable remote wake for the first +* interface. FIXME if the interface association +* descriptor shows there's more than one function. +*/ + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + devstatus); + le16_to_cpus(devstatus); + if (!status devstatus + (USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW)) + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } + + return status; +} + +static int usb_enable_remote_wakeup(struct usb_device *udev) +{ + int status; + + if (udev-speed != USB_SPEED_SUPER) { + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* Assume there's only one function on the USB 3.0 +* device and enable remote wake for the first +* interface. FIXME if the interface association +* descriptor shows there's more than one function. +*/ + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, + USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, + USB_INTRF_FUNC_SUSPEND_RW | + USB_INTRF_FUNC_SUSPEND_LP, + NULL, 0, USB_CTRL_SET_TIMEOUT); + } + + return status; } /* @@ -2905,27 +2955,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) * we don't explicitly enable it here. */ if (udev-do_remote_wakeup) { - if (!hub_is_superspeed(hub-hdev)) { - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0
[PATCH 3/4] usb: Add usb port system pm support
This patch is to add usb port system pm support. Add usb port's system suspend/resume callbacks and call usb_port_runtime_resume/suspend() to power off these ports whose pm qos NO_POWER_OFF flag is not set, system wakeup is disabled and persist is enalbed. During system pm, usb port should be powered off after dev being suspended and powered on before dev being resumed. Since usb ports and devs enable async suspend, call device_pm_wait_for_dev() in the usb_port_system_suspend() and usb_port_resume() to keeping the order. If usb port was already powered off by runtime pm with port_dev-power_is_on being false, usb_port_system_suspend() returns directly. If usb port was not powered off during system suspend with port_dev-power_is_on being true, usb_port_system_resume() returns directly. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c |4 drivers/usb/core/port.c | 49 --- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c228e69..8c2562e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3166,6 +3166,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) int status; u16 portchange, portstatus; + /* Wait for usb port system resume finishing */ + if (!PMSG_IS_AUTO(msg)) + device_pm_wait_for_dev(udev-dev, port_dev-dev); + if (port_dev-did_runtime_put) { status = pm_runtime_get_sync(port_dev-dev); port_dev-did_runtime_put = false; diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 797f9d5..f14fc72 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -71,7 +71,7 @@ static void usb_port_device_release(struct device *dev) kfree(port_dev); } -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM static int usb_port_runtime_resume(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); @@ -131,25 +131,68 @@ static int usb_port_runtime_suspend(struct device *dev) set_bit(port1, hub-busy_bits); retval = usb_hub_set_port_power(hdev, port1, false); usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); - usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); + usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); clear_bit(port1, hub-busy_bits); usb_autopm_put_interface(intf); return retval; } -#endif + +static int usb_port_system_suspend(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + + if (!port_dev-power_is_on) + return 0; + + if (port_dev-child) { + struct usb_device *udev = port_dev-child; + + /* +* usb port can't be powered off when dev's system +* wakeup is enabled or persist is disabled. +*/ + if (device_may_wakeup(udev-dev) + || !udev-persist_enabled) + return 0; + + /* +* usb port should be powered off after usb dev +* being suspended. +*/ + device_pm_wait_for_dev(dev, port_dev-child-dev); + } + + usb_port_runtime_suspend(dev); + return 0; +} + +static int usb_port_system_resume(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + + if (port_dev-power_is_on) + return 0; + + return usb_port_runtime_resume(dev); +} static const struct dev_pm_ops usb_port_pm_ops = { + .suspend = usb_port_system_suspend, + .resume = usb_port_system_resume, #ifdef CONFIG_USB_SUSPEND .runtime_suspend = usb_port_runtime_suspend, .runtime_resume = usb_port_runtime_resume, .runtime_idle = pm_generic_runtime_idle, #endif }; +#endif struct device_type usb_port_device_type = { .name = usb_port, .release = usb_port_device_release, +#if CONFIG_PM .pm = usb_port_pm_ops, +#endif }; int usb_hub_create_port_device(struct usb_hub *hub, int port1) -- 1.7.9.5 -- 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
[PATCH 4/4] usb: register usb port to usb_bus_type
Usb port isn't assigned to any bus_type. This seems not good from Greg's comments. http://marc.info/?l=linux-usbm=136200364929942w=2 This patch is to register usb port to usb_bus_type. The usb port's original name is portX. This will cause name confilct after adding usb port to usb_bus_type since the usb ports with same port num under different hub have the same name. So change the usb port's name format to port + (hub dev name) + '.' + (port num) for non-root hub and port + (usb bus num) + '-' + (port num) for root hub. ls /sys/bus/usb/devices 1-0:1.02-0:1.0 port1-1 port1-1.3 port2-1.2 port2-2 port4-3 1-12-1 port1-1.1port1-1.4 port2-1.3 port3-1 port4-4 1-1.1 2-1:1.0 port1-1.2port1-1.5 port2-1.4 port3-2 usb1 1-1:1.03-0:1.0 port1-1.2.1 port1-1.6 port2-1.5 port3-3 usb2 1-1.1:1.0 3-1 port1-1.2.2 port1-2port2-1.6 port3-4 usb3 1-1.2 3-1:1.0 port1-1.2.3 port2-1port2-1.7 port4-1 usb4 1-1.2:1.0 4-0:1.0 port1-1.2.4 port2-1.1 port2-1.8 port4-2 Signed-off-by: Lan Tianyu tianyu@intel.com --- Documentation/ABI/testing/sysfs-bus-usb |6 +++--- drivers/usb/core/port.c | 10 +- drivers/usb/core/usb-acpi.c |7 +-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index c8baaf5..842e8b8 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -221,14 +221,14 @@ Description: The file will be present for all speeds of USB devices, and will always read no for USB 1.1 and USB 2.0 devices. -What: /sys/bus/usb/devices/.../(hub interface)/portX +What: /sys/bus/usb/devices/.../(hub interface)/portX-X Date: August 2012 Contact: Lan Tianyu tianyu@intel.com Description: - The /sys/bus/usb/devices/.../(hub interface)/portX + The /sys/bus/usb/devices/.../(hub interface)/portX-X is usb port device's sysfs directory. -What: /sys/bus/usb/devices/.../(hub interface)/portX/connect_type +What: /sys/bus/usb/devices/.../(hub interface)/portX-X/connect_type Date: January 2013 Contact: Lan Tianyu tianyu@intel.com Description: diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index f14fc72..2c086dc 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -198,6 +198,7 @@ struct device_type usb_port_device_type = { int usb_hub_create_port_device(struct usb_hub *hub, int port1) { struct usb_port *port_dev = NULL; + struct usb_device *hdev = hub-hdev; int retval; port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); @@ -212,7 +213,14 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) port_dev-dev.parent = hub-intfdev; port_dev-dev.groups = port_dev_group; port_dev-dev.type = usb_port_device_type; - dev_set_name(port_dev-dev, port%d, port1); + port_dev-dev.bus = usb_bus_type; + + if (!hdev-parent) + dev_set_name(port_dev-dev, port%d-%d, + hdev-bus-busnum, port1); + else + dev_set_name(port_dev-dev, port%s.%d, + dev_name(hdev-dev), port1); retval = device_register(port_dev-dev); if (retval) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index b6f4bad..1cc55c9 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -17,7 +17,7 @@ #include linux/pci.h #include acpi/acpi_bus.h -#include usb.h +#include hub.h /** * usb_acpi_power_manageable - check whether usb port has @@ -178,7 +178,10 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) return -ENODEV; return 0; } else if (is_usb_port(dev)) { - sscanf(dev_name(dev), port%d, port_num); + struct usb_port *port_dev = to_usb_port(dev); + + port_num = port_dev-portnum; + /* Get the struct usb_device point of port's hub */ udev = to_usb_device(dev-parent-parent); -- 1.7.9.5 -- 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
[PATCH 2/4] usb: introduce usb force power off mechanism
Some devices' firmware will be broken at some points. Power down and power on device can help device to rework in this case. This patch is to add ioctl cmd USBDEVFS_POWER_RESET for usbfs node to repower usb device. First, call hub_port_logical_disconnect() to disconnect device. Second, Power down and up usb port. This patch is also helpful fo some QAs who want to do hcd's memleak test(Plug and unplug device thousand times.) Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/devio.c | 13 + drivers/usb/core/hub.c| 16 drivers/usb/core/usb.h|2 ++ include/uapi/linux/usbdevice_fs.h |1 + 4 files changed, 32 insertions(+) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8823e98..a76b326 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1102,6 +1102,14 @@ static int proc_resetdevice(struct dev_state *ps) return usb_reset_device(ps-dev); } +static int proc_resetdevicepower(struct dev_state *ps) +{ + struct usb_device *udev = ps-dev; + struct usb_device *hdev = udev-parent; + + return usb_hub_port_power_reset(hdev, udev-portnum); +} + static int proc_setintf(struct dev_state *ps, void __user *arg) { struct usbdevfs_setinterface setintf; @@ -2011,6 +2019,11 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, ret = proc_resetdevice(ps); break; + case USBDEVFS_POWER_RESET: + snoop(dev-dev, %s: RESET POWER\n, __func__); + ret = proc_resetdevicepower(ps); + break; + case USBDEVFS_CLEAR_HALT: snoop(dev-dev, %s: CLEAR_HALT\n, __func__); ret = proc_clearhalt(ps, p); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6b7f5b9..c228e69 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -114,6 +114,7 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); #define HUB_DEBOUNCE_STABLE 100 static int usb_reset_and_verify_device(struct usb_device *udev); +static void hub_port_logical_disconnect(struct usb_hub *hub, int port1); static inline char *portspeed(struct usb_hub *hub, int portstatus) { @@ -741,6 +742,21 @@ int usb_hub_set_port_power(struct usb_device *hdev, int port1, return ret; } +int usb_hub_port_power_reset(struct usb_device *hdev, int port1) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + struct usb_interface *intf = to_usb_interface(hub-intfdev); + int ret; + + usb_autopm_get_interface(intf); + hub_port_logical_disconnect(hub, port1); + ret = usb_hub_set_port_power(hdev, port1, false); + ret |= usb_hub_set_port_power(hdev, port1, true); + usb_autopm_put_interface(intf); + + return ret; +} + /** * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub * @urb: an URB associated with the failed or incomplete split transaction diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index a7f20bd..4e7785c 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -185,6 +185,8 @@ extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, enum usb_port_connect_type type); extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, struct usb_hub_descriptor *desc); +extern int usb_hub_port_power_reset(struct usb_device *hdev, + int port1); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h index 0c65e4b..b6e0d17 100644 --- a/include/uapi/linux/usbdevice_fs.h +++ b/include/uapi/linux/usbdevice_fs.h @@ -176,5 +176,6 @@ struct usbdevfs_disconnect_claim { #define USBDEVFS_RELEASE_PORT _IOR('U', 25, unsigned int) #define USBDEVFS_GET_CAPABILITIES _IOR('U', 26, __u32) #define USBDEVFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbdevfs_disconnect_claim) +#define USBDEVFS_POWER_RESET _IO('U', 28) #endif /* _UAPI_LINUX_USBDEVICE_FS_H */ -- 1.7.9.5 -- 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 2/4] usb: introduce usb force power off mechanism
A small tool to test this patch. #include stdio.h #include unistd.h #include fcntl.h #include errno.h #include sys/ioctl.h #include linux/usbdevice_fs.h #define USBDEVFS_POWER_RESET _IO('U', 28) int main(int argc, char **argv) { const char *filename; int fd; int rc; if (argc != 2) { fprintf(stderr, Usage: usbreset device-filename\n); return 1; } filename = argv[1]; fd = open(filename, O_WRONLY); if (fd 0) { perror(Error opening output file); return 1; } printf(Repowering USB device %s\n, filename); rc = ioctl(fd, USBDEVFS_POWER_RESET, 0); if (rc 0) { perror(Error in ioctl); return 1; } printf(Repower successful\n); close(fd); return 0; } Best Regards Tianyu Lan -Original Message- From: Lan, Tianyu Sent: Thursday, March 28, 2013 1:11 AM To: gre...@linuxfoundation.org; sarah.a.sh...@linux.intel.com; st...@rowland.harvard.edu Cc: linux-usb@vger.kernel.org; Lan, Tianyu Subject: [PATCH 2/4] usb: introduce usb force power off mechanism Some devices' firmware will be broken at some points. Power down and power on device can help device to rework in this case. This patch is to add ioctl cmd USBDEVFS_POWER_RESET for usbfs node to repower usb device. First, call hub_port_logical_disconnect() to disconnect device. Second, Power down and up usb port. This patch is also helpful fo some QAs who want to do hcd's memleak test(Plug and unplug device thousand times.) Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/devio.c | 13 + drivers/usb/core/hub.c| 16 drivers/usb/core/usb.h|2 ++ include/uapi/linux/usbdevice_fs.h |1 + 4 files changed, 32 insertions(+) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8823e98..a76b326 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1102,6 +1102,14 @@ static int proc_resetdevice(struct dev_state *ps) return usb_reset_device(ps-dev); } +static int proc_resetdevicepower(struct dev_state *ps) { + struct usb_device *udev = ps-dev; + struct usb_device *hdev = udev-parent; + + return usb_hub_port_power_reset(hdev, udev-portnum); } + static int proc_setintf(struct dev_state *ps, void __user *arg) { struct usbdevfs_setinterface setintf; @@ -2011,6 +2019,11 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, ret = proc_resetdevice(ps); break; + case USBDEVFS_POWER_RESET: + snoop(dev-dev, %s: RESET POWER\n, __func__); + ret = proc_resetdevicepower(ps); + break; + case USBDEVFS_CLEAR_HALT: snoop(dev-dev, %s: CLEAR_HALT\n, __func__); ret = proc_clearhalt(ps, p); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6b7f5b9..c228e69 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -114,6 +114,7 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); #define HUB_DEBOUNCE_STABLE 100 static int usb_reset_and_verify_device(struct usb_device *udev); +static void hub_port_logical_disconnect(struct usb_hub *hub, int +port1); static inline char *portspeed(struct usb_hub *hub, int portstatus) { @@ -741,6 +742,21 @@ int usb_hub_set_port_power(struct usb_device *hdev, int port1, return ret; } +int usb_hub_port_power_reset(struct usb_device *hdev, int port1) { + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + struct usb_interface *intf = to_usb_interface(hub-intfdev); + int ret; + + usb_autopm_get_interface(intf); + hub_port_logical_disconnect(hub, port1); + ret = usb_hub_set_port_power(hdev, port1, false); + ret |= usb_hub_set_port_power(hdev, port1, true); + usb_autopm_put_interface(intf); + + return ret; +} + /** * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub * @urb: an URB associated with the failed or incomplete split transaction diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index a7f20bd..4e7785c 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -185,6 +185,8 @@ extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, enum usb_port_connect_type type); extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, struct usb_hub_descriptor *desc); +extern int usb_hub_port_power_reset(struct usb_device *hdev, + int port1); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h index 0c65e4b..b6e0d17 100644 --- a/include/uapi/linux/usbdevice_fs.h +++ b/include/uapi/linux/usbdevice_fs.h @@ -176,5 +176,6
Re: [PATCH 3/4] usb: Add usb port system pm support
On 2013/3/28 2:47, Alan Stern wrote: On Thu, 28 Mar 2013, Lan Tianyu wrote What happens if there's no device plugged in to the port, but the hub is enabled for remote wakeup? How will the hub be able to detect a plug-in event if the port isn't powered? Alan Stern Hi Alan: Great thanks for your review. The hub will not detect the new devices. From my opinion, this depends on the user space since the port only will be powered off when pm qos NO_POWER_OFF flag is unset(it is default to be set). If unset the flag, losing plug-in event should have been took into account. -- 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: USB port power-off and system suspend
On 2013/3/23 1:35, Alan Stern wrote: Tianyu: Did you ever test the port power-off mechanism with system suspend? Right now it doesn't seem like it would work, because it relies on runtime PM to turn off the port power, and runtime PM doesn't operate normally during a system suspend. Alan Stern Hi Alan: You are right. Current the port power-off can't work during system suspend. I have already worked on a patch of adding usb port system pm support. But there is a still problem that how to control power off mechanism from kernel side. Before, we have a solution for runtime pm that increase/decrease port dev's usage count. http://marc.info/?l=linux-usbm=135772122031446w=2 But now, we have another user, System pm. So I think we should find a solution to cover these two cases. Maybe add a new pm qos request for NO_POWER_OFF flag? I'd like to see your opinion. I have a patch that can work and it still needs to add some condition checks in the usb_port_system_suspend(). Dev's system wakeup disable and persist enable. From c3abd373707910672d6fd2e96da78879b3e22417 Mon Sep 17 00:00:00 2001 From: Lan Tianyu tianyu@intel.com Date: Tue, 26 Feb 2013 11:12:09 +0800 Subject: [PATCH] usb: Add usb port system pm support This patch is to add usb port system pm support. Add usb port's system suspend/resume callbacks and call usb_port_runtime_resume/suspend() to power off these ports without pm qos NO_POWER_OFF flag setting. During system pm, usb port should be powered off after dev being suspended and powered on before dev being resumed. Usb ports and devs enable async suspend. In order to keeping the order, call device_pm_wait_for_dev() in the usb_port_system_suspend() and usb_port_resume(). Usb_port_system_suspend() ignores EAGAIN from usb_port_runtime_suspend(). EAGAIN is caused by pm qos NO_POWER_OFF setting. This is not an error for usb port system pm. --- drivers/usb/core/hub.c |4 drivers/usb/core/port.c | 31 +++ 2 files changed, 35 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 53c1555..8868f15 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3162,6 +3162,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) int status; u16 portchange, portstatus; + /* Wait for usb port system resume finishing */ + if (!PMSG_IS_AUTO(msg)) + device_pm_wait_for_dev(udev-dev, port_dev-dev); + if (port_dev-did_runtime_put) { status = pm_runtime_get_sync(port_dev-dev); port_dev-did_runtime_put = false; diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 797f9d5..e5c6ec5 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -84,6 +84,9 @@ static int usb_port_runtime_resume(struct device *dev) if (!hub) return -EINVAL; + if (port_dev-power_is_on) + return 0; + usb_autopm_get_interface(intf); set_bit(port1, hub-busy_bits); @@ -127,6 +130,9 @@ static int usb_port_runtime_suspend(struct device *dev) == PM_QOS_FLAGS_ALL) return -EAGAIN; + if (!port_dev-power_is_on) + return 0; + usb_autopm_get_interface(intf); set_bit(port1, hub-busy_bits); retval = usb_hub_set_port_power(hdev, port1, false); @@ -136,9 +142,34 @@ static int usb_port_runtime_suspend(struct device *dev) usb_autopm_put_interface(intf); return retval; } +#else +static int usb_port_runtime_suspend(struct device *dev) { return 0; } +static int usb_port_runtime_resume(struct device *dev) { return 0; } #endif +static int usb_port_system_suspend(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + int retval; + + if (port_dev-child) + device_pm_wait_for_dev(dev, port_dev-child-dev); + + retval = usb_port_runtime_suspend(dev); + if (retval 0 retval != -EAGAIN) + return retval; + + return 0; +} + +static int usb_port_system_resume(struct device *dev) +{ + return usb_port_runtime_resume(dev); +} + static const struct dev_pm_ops usb_port_pm_ops = { + .suspend = usb_port_system_suspend, + .resume = usb_port_system_resume, #ifdef CONFIG_USB_SUSPEND .runtime_suspend = usb_port_runtime_suspend, .runtime_resume = usb_port_runtime_resume, -- 1.7.10.4 -- 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
[RFC PATCH] usb: register usb port to usb_bus_type
Usb port isn't assigned to any bus_type. This seems not good from Greg's comments. http://marc.info/?l=linux-usbm=136200364929942w=2 This patch is to register usb port to usb_bus_type. The usb port's original name is portX. This will cause name confilct after adding usb port to usb_bus_type since the usb ports with same port num under different hub have the same name. So change the usb port's name format to port + (hub dev name) + '.' + (port num) for non-root hub and port + (usb bus num) + '-' + (port num) for root hub. ls /sys/bus/usb/devices 1-0:1.02-0:1.0 port1-1 port1-1.3 port2-1.2 port2-2 port4-3 1-12-1 port1-1.1port1-1.4 port2-1.3 port3-1 port4-4 1-1.1 2-1:1.0 port1-1.2port1-1.5 port2-1.4 port3-2 usb1 1-1:1.03-0:1.0 port1-1.2.1 port1-1.6 port2-1.5 port3-3 usb2 1-1.1:1.0 3-1 port1-1.2.2 port1-2port2-1.6 port3-4 usb3 1-1.2 3-1:1.0 port1-1.2.3 port2-1port2-1.7 port4-1 usb4 1-1.2:1.0 4-0:1.0 port1-1.2.4 port2-1.1 port2-1.8 port4-2 Signed-off-by: Lan Tianyu tianyu@intel.com --- Documentation/ABI/testing/sysfs-bus-usb |6 +++--- drivers/usb/core/port.c | 10 +- drivers/usb/core/usb-acpi.c |7 +-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index c8baaf5..842e8b8 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -221,14 +221,14 @@ Description: The file will be present for all speeds of USB devices, and will always read no for USB 1.1 and USB 2.0 devices. -What: /sys/bus/usb/devices/.../(hub interface)/portX +What: /sys/bus/usb/devices/.../(hub interface)/portX-X Date: August 2012 Contact: Lan Tianyu tianyu@intel.com Description: - The /sys/bus/usb/devices/.../(hub interface)/portX + The /sys/bus/usb/devices/.../(hub interface)/portX-X is usb port device's sysfs directory. -What: /sys/bus/usb/devices/.../(hub interface)/portX/connect_type +What: /sys/bus/usb/devices/.../(hub interface)/portX-X/connect_type Date: January 2013 Contact: Lan Tianyu tianyu@intel.com Description: diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 797f9d5..4d37984 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -155,6 +155,7 @@ struct device_type usb_port_device_type = { int usb_hub_create_port_device(struct usb_hub *hub, int port1) { struct usb_port *port_dev = NULL; + struct usb_device *hdev = hub-hdev; int retval; port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); @@ -169,7 +170,14 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) port_dev-dev.parent = hub-intfdev; port_dev-dev.groups = port_dev_group; port_dev-dev.type = usb_port_device_type; - dev_set_name(port_dev-dev, port%d, port1); + port_dev-dev.bus = usb_bus_type; + + if (!hdev-parent) + dev_set_name(port_dev-dev, port%d-%d, + hdev-bus-busnum, port1); + else + dev_set_name(port_dev-dev, port%s.%d, + dev_name(hdev-dev), port1); retval = device_register(port_dev-dev); if (retval) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index b6f4bad..1cc55c9 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -17,7 +17,7 @@ #include linux/pci.h #include acpi/acpi_bus.h -#include usb.h +#include hub.h /** * usb_acpi_power_manageable - check whether usb port has @@ -178,7 +178,10 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) return -ENODEV; return 0; } else if (is_usb_port(dev)) { - sscanf(dev_name(dev), port%d, port_num); + struct usb_port *port_dev = to_usb_port(dev); + + port_num = port_dev-portnum; + /* Get the struct usb_device point of port's hub */ udev = to_usb_device(dev-parent-parent); -- 1.7.9.5 -- 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 V4 2/2] usb/acpi: binding xhci root hub usb port with ACPI
On 2013年03月21日 02:28, Sarah Sharp wrote: On Wed, Mar 20, 2013 at 10:18:03AM +0800, Lan Tianyu wrote: On 2013年03月20日 03:06, Sarah Sharp wrote: Ok, this looks sane, and our Intel testers report it doesn't oops like v2. The patch description on the first patch is better as well. Tianyu, I know this introduces a new API to the host controller driver structure, and we would normally queue these two patches for 3.10. However, I know a lot of the port power off code went into 3.9. If we don't have these patches in 3.9, what will be the impact? Will we say, misassign a power resource from a particular port, or mismark a USB port connection type? Is there any user-level impact if we don't have these in 3.9? If these patches should go into 3.9, should they also be backported to 3.8 and 3.7? Commit d557542421da643358201664903e67fd01dfca1a usb/acpi: Bind ACPI node to USB port, not usb_device. was first introduced in 3.7, and it looks like the sysfs files to turn on and off ports were added in 3.7 as well. Without these two patches, will that sysfs interface work correctly? I think there is an impact for usb3.0 paired ports. So it's better to backport these patchs to 3.7, 3.8, 3.9 if possible. These patches also depend on the commit 1033f9041d ACPI: Allow ACPI binding with USB-3.0 hub. I'd like to take the job if I could do. I'm not sure what you mean by I'd like to take the job if I could do. If you are talking about backporting patches to stable, I'll just mark your two patches to Cc the stable mailing list, and Greg will automatically backport this when it hits Linus' tree. There's no work for you or I to do, unless the patches don't apply. Sorry. I didn't say clearly. My concern is that these patches may not be applied on the v3.7, v3.8 or v3.9. If that case, we would need to rework these patches. BTW, the sysfs files to turn on and off ports has been reverted by Greg in v3.7. If the sysfs files were reverted for 3.7, and there was no policy for how to use the port connection information, is there any point in fixing this in 3.7? Yes, the connection info might be wrong, but if no one can use it, why should we go to the trouble of backporting it? There is also no policy for how to use the port connection information in v3.8. If ignore wrong connect info, this seems also not to be needed in v3.8. I do agree this should be in 3.8 and 3.9, I'm just not sure about 3.7. Sarah Sharp -- Best regards Tianyu Lan -- 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
[Resend PATCH V2] usb: add usb_enable/disable_remote_wakeup()
usb2.0 and usb3.0 devices have different ways to enalbe/disable remote wakeup. This patch is to put both their operations into the seperate functions. Otherwise, usb_control_msg() has some long arguments and are usually nested some indentations. So encapsulating it into seperate functions would be convienient to use and more readable. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 136 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5480352..56eea28 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2822,22 +2822,72 @@ void usb_enable_ltm(struct usb_device *udev) EXPORT_SYMBOL_GPL(usb_enable_ltm); #ifdef CONFIG_USB_SUSPEND -/* - * usb_disable_function_remotewakeup - disable usb3.0 - * device's function remote wakeup - * @udev: target device - * - * Assume there's only one function on the USB 3.0 - * device and disable remote wake for the first - * interface. FIXME if the interface association - * descriptor shows there's more than one function. - */ -static int usb_disable_function_remotewakeup(struct usb_device *udev) +static int usb_disable_remote_wakeup(struct usb_device *udev) { - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, - USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + int status = 0; + u16 devstatus; + + if (udev-speed != USB_SPEED_SUPER) { + status = usb_get_status(udev, USB_RECIP_DEVICE, 0, devstatus); + le16_to_cpus(devstatus); + if (!status devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* +* Assume there's only one function on the USB 3.0 +* device and disable remote wake for the first +* interface. FIXME if the interface association +* descriptor shows there's more than one function. +*/ + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + devstatus); + le16_to_cpus(devstatus); + if (!status devstatus + (USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW)) + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } + + return status; +} + +static int usb_enable_remote_wakeup(struct usb_device *udev) +{ + int status; + + if (udev-speed != USB_SPEED_SUPER) { + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* Assume there's only one function on the USB 3.0 +* device and enable remote wake for the first +* interface. FIXME if the interface association +* descriptor shows there's more than one function. +*/ + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, + USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, + USB_INTRF_FUNC_SUSPEND_RW | + USB_INTRF_FUNC_SUSPEND_LP, + NULL, 0, USB_CTRL_SET_TIMEOUT); + } + + return status; } /* @@ -2901,27 +2951,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) * we don't explicitly enable it here. */ if (udev-do_remote_wakeup) { - if (!hub_is_superspeed(hub-hdev)) { - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0
[PATCH V4 1/2] usb: add find_raw_port_number callback to struct hc_driver()
xhci driver divides the root hub into two logical hubs which work respectively for usb 2.0 and usb 3.0 devices. They are independent devices in the usb core. But in the ACPI table, it's one device node and all usb2.0 and usb3.0 ports are under it. Binding usb port with its acpi node needs the raw port number which is reflected in the xhci extended capabilities table. This patch is to add find_raw_port_number callback to struct hc_driver(), fill it with xhci_find_raw_port_number() which will return raw port number and add a wrap usb_hcd_find_raw_port_number(). Otherwise, refactor xhci_find_real_port_number(). Using xhci_find_raw_port_number() to get real index in the HW port status registers instead of scanning through the xHCI roothub port array. This can help to speed up. All addresses in xhci-usb2_ports and xhci-usb3_ports array are kown good ports and don't include following bad ports in the extended capabilities talbe. (1) root port that doesn't have an entry (2) root port with unknown speed (3) root port that is listed twice and with different speeds. So xhci_find_raw_port_number() will only return port num of good ones and never touch bad ports above. Signed-off-by: Lan Tianyu tianyu@intel.com --- This patchset is based on usb-next tree commit 3f3b55bf usb: ehci-s5p: Use devm for requesting ehci_vbus_gpio. Change since v1: Don't export usb_hcd_find_raw_port_number() symbol since there is no its user outside of usb core. Change since v2: combine patch usb: add find_raw_port_number callback to struct hc_driver() with this patch. Change since v3: add more changlog to prove this patch will not break previous function drivers/usb/core/hcd.c |8 drivers/usb/host/xhci-mem.c | 36 drivers/usb/host/xhci-pci.c |1 + drivers/usb/host/xhci.c | 22 ++ drivers/usb/host/xhci.h |1 + include/linux/usb/hcd.h |2 ++ 6 files changed, 42 insertions(+), 28 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 99b34a3..f9ec44c 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2412,6 +2412,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd) } EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd); +int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ + if (!hcd-driver-find_raw_port_number) + return port1; + + return hcd-driver-find_raw_port_number(hcd, port1); +} + static int usb_hcd_request_irqs(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags) { diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 35616ff..6dc238c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, * is attached to (or the roothub port its ancestor hub is attached to). All we * know is the index of that port under either the USB 2.0 or the USB 3.0 * roothub, but that doesn't give us the real index into the HW port status - * registers. Scan through the xHCI roothub port array, looking for the Nth - * entry of the correct port speed. Return the port number of that entry. + * registers. Call xhci_find_raw_port_number() to get real index. */ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, struct usb_device *udev) { struct usb_device *top_dev; - unsigned int num_similar_speed_ports; - unsigned int faked_port_num; - int i; + struct usb_hcd *hcd; + + if (udev-speed == USB_SPEED_SUPER) + hcd = xhci-shared_hcd; + else + hcd = xhci-main_hcd; for (top_dev = udev; top_dev-parent top_dev-parent-parent; top_dev = top_dev-parent) /* Found device below root hub */; - faked_port_num = top_dev-portnum; - for (i = 0, num_similar_speed_ports = 0; - i HCS_MAX_PORTS(xhci-hcs_params1); i++) { - u8 port_speed = xhci-port_array[i]; - - /* -* Skip ports that don't have known speeds, or have duplicate -* Extended Capabilities port speed entries. -*/ - if (port_speed == 0 || port_speed == DUPLICATE_ENTRY) - continue; - /* -* USB 3.0 ports are always under a USB 3.0 hub. USB 2.0 and -* 1.1 ports are under the USB 2.0 hub. If the port speed -* matches the device speed, it's a similar speed port. -*/ - if ((port_speed == 0x03) == (udev-speed == USB_SPEED_SUPER)) - num_similar_speed_ports++; - if (num_similar_speed_ports == faked_port_num) - /* Roothub ports are numbered from 1 to N */ - return i+1
[PATCH V4 2/2] usb/acpi: binding xhci root hub usb port with ACPI
This patch is to bind xhci root hub usb port with its acpi node. The port num in the acpi table matches with the sequence in the xhci extended capabilities table. So call usb_hcd_find_raw_port_number() to transfer hub port num into raw port number which associates with the sequence in the xhci extended capabilities table before binding. Signed-off-by: Lan Tianyu tianyu@intel.com --- Change since v3: add a temprorary variable to recard raw port num and get ACPI handle rahter than overwrite port num with raw port num. This is to avoid passing raw port num as port num to usb_acpi_check_port_connect_type(). drivers/usb/core/usb-acpi.c |8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index b6f4bad..255c144 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -15,6 +15,7 @@ #include linux/kernel.h #include linux/acpi.h #include linux/pci.h +#include linux/usb/hcd.h #include acpi/acpi_bus.h #include usb.h @@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) * connected to. */ if (!udev-parent) { - *handle = acpi_get_child(DEVICE_ACPI_HANDLE(udev-dev), + struct usb_hcd *hcd = bus_to_hcd(udev-bus); + int raw_port_num; + + raw_port_num = usb_hcd_find_raw_port_number(hcd, port_num); + *handle = acpi_get_child(DEVICE_ACPI_HANDLE(udev-dev), + raw_port_num); if (!*handle) return -ENODEV; } else { -- 1.7.9.5 -- 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 V4 2/2] usb/acpi: binding xhci root hub usb port with ACPI
On 2013年03月20日 03:06, Sarah Sharp wrote: Ok, this looks sane, and our Intel testers report it doesn't oops like v2. The patch description on the first patch is better as well. Tianyu, I know this introduces a new API to the host controller driver structure, and we would normally queue these two patches for 3.10. However, I know a lot of the port power off code went into 3.9. If we don't have these patches in 3.9, what will be the impact? Will we say, misassign a power resource from a particular port, or mismark a USB port connection type? Is there any user-level impact if we don't have these in 3.9? If these patches should go into 3.9, should they also be backported to 3.8 and 3.7? Commit d557542421da643358201664903e67fd01dfca1a usb/acpi: Bind ACPI node to USB port, not usb_device. was first introduced in 3.7, and it looks like the sysfs files to turn on and off ports were added in 3.7 as well. Without these two patches, will that sysfs interface work correctly? I think there is an impact for usb3.0 paired ports. So it's better to backport these patchs to 3.7, 3.8, 3.9 if possible. These patches also depend on the commit 1033f9041d ACPI: Allow ACPI binding with USB-3.0 hub. I'd like to take the job if I could do. BTW, the sysfs files to turn on and off ports has been reverted by Greg in v3.7. Sarah Sharp On Tue, Mar 19, 2013 at 04:48:13PM +0800, Lan Tianyu wrote: This patch is to bind xhci root hub usb port with its acpi node. The port num in the acpi table matches with the sequence in the xhci extended capabilities table. So call usb_hcd_find_raw_port_number() to transfer hub port num into raw port number which associates with the sequence in the xhci extended capabilities table before binding. Signed-off-by: Lan Tianyu tianyu@intel.com --- Change since v3: add a temprorary variable to recard raw port num and get ACPI handle rahter than overwrite port num with raw port num. This is to avoid passing raw port num as port num to usb_acpi_check_port_connect_type(). drivers/usb/core/usb-acpi.c |8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index b6f4bad..255c144 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -15,6 +15,7 @@ #include linux/kernel.h #include linux/acpi.h #include linux/pci.h +#include linux/usb/hcd.h #include acpi/acpi_bus.h #include usb.h @@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) * connected to. */ if (!udev-parent) { -*handle = acpi_get_child(DEVICE_ACPI_HANDLE(udev-dev), +struct usb_hcd *hcd = bus_to_hcd(udev-bus); +int raw_port_num; + +raw_port_num = usb_hcd_find_raw_port_number(hcd, port_num); +*handle = acpi_get_child(DEVICE_ACPI_HANDLE(udev-dev), +raw_port_num); if (!*handle) return -ENODEV; } else { -- 1.7.9.5 -- Best regards Tianyu Lan -- 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: Testing for hardware bug in EHCI controllers
2013/2/26 Alan Stern st...@rowland.harvard.edu: Sarah (and anyone else who's interested): A while ago I wrote about a hardware bug in my Intel ICH5 and ICH8 EHCI controllers. You pointed out that these are rather old components, not being used in current systems, which is quite true. Now I have figured out a simple way for anyone to test for this bug in any EHCI controller, without the need for a g-zero gadget. It's a two-part procedure: Apply the patch below (which is written for vanilla 3.8) and load the resulting driver. The patch adds an explicit test to ehci-hcd for detecting the bug. Then plug in an ordinary USB flash drive and run the attached program (as root), giving it the device path for the flash drive as the single command-line argument. For example: sudo ./ehci-test /dev/bus/usb/002/003 The program won't do anything bad to the flash drive; it just reads the first 256 KB of data over and over again, now and then unlinking an URB to try and trigger the bug. If the program works right, it will print out a loop counter every hundred iterations. If it runs for 1000 iterations with no error messages in the kernel log, you may consider that the controller has passed the test. This should take under a minute, depending on the hardware speed. The program won't stop by itself unless something goes wrong. You can kill it with ^C or more simply by unplugging the flash drive. (If you want to be safe, make sure there are no mounted filesystems on the drive before running the test program.) If the hardware bug is detected, the kernel patch will print error messages to the system log. For example, when I run the test on the Intel controller in this computer, I get: [ 150.019441] usb-storage 3-8:1.0: disconnect by usbfs [ 150.271190] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 150.591089] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 151.538560] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 151.857569] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 152.018886] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 152.179810] ehci-pci :00:1d.7: EHCI hardware bug detected: 80008d00 8d00 [ 153.211804] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 153.374497] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 153.770443] ehci-pci :00:1d.7: EHCI hardware bug detected: 80008d00 8d00 [ 154.247861] ehci-pci :00:1d.7: EHCI hardware bug detected: 82008d80 8d00 [ 154.566912] ehci-pci :00:1d.7: EHCI hardware bug detected: 82008d80 8d00 [ 155.359101] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 155.838132] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 156.791107] ehci-pci :00:1d.7: EHCI hardware bug detected: 80008d00 8d00 [ 157.267620] ehci-pci :00:1d.7: EHCI hardware bug detected: 8d00 80008d00 [ 159.252057] ehci-pci :00:1d.7: EHCI hardware bug detected: 80008d00 8d00 [ 159.886048] ehci-pci :00:1d.7: EHCI hardware bug detected: 80008d00 8d00 [ 160.206625] ehci-pci :00:1d.7: EHCI hardware bug detected: 02008d80 80008d00 ... You get the idea. The values in the two columns on the right are always supposed to be equal; when they aren't it indicates that the controller has done a DMA write at a time when ehci-hcd isn't expecting one to happen. I'd be interested to hear the results of testing on a variety of controllers. (This computer also has an NEC EHCI controller, and that one does not have the bug.) Do the EHCI controllers on current Intel chipsets pass the test? What about other vendors? Thanks to all who try it out and report their results. Test on the Sandybridge platform. At the first time, I get following output. But after that, I was hard to get any output. And test on the v3.8. sudo ./ehci-test /dev/bus/usb/001/003 [ 140.855342] usb-storage 1-1.2:1.0: disconnect by usbfs Invalid URB stat[ 140.863000] ehci-pci :00:1a.0: shutdown urb 88014545f300 ep1in-bulk [ 140.871303] ehci-pci :00:1a.0: shutdown urb 88014545f0c0 ep1in-bulk [ 140.878231] ehci-pci :00:1a.0: shutdown urb 88014545fcc0 ep1in-bulk [ 140.885158] ehci-pci :00:1a.0: shutdown urb 88014545fb40 ep1in-bulk [ 140.892088] ehci-pci :00:1a.0: shutdown urb 88014545f9c0 ep1in-bulk [ 140.899015] ehci-pci :00:1a.0: shutdown urb 88014545f780 ep1in-bulk [ 140.905941] ehci-pci :00:1a.0: shutdown urb 88014545f240 ep1in-bulk [ 140.912870] ehci-pci :00:1a.0: shutdown urb 88014545f900 ep1in-bulk [ 140.919799] ehci-pci :00:1a.0: shutdown urb 88014545fc00 ep1in-bulk [ 140.926725] ehci-pci :00:1a.0: shutdown urb
Re: [PATCH 4/5] usb: call pm_runtime_put_sync in pm_runtime_get_sync failed case
On 2013年02月28日 15:57, Li Fei wrote: Even in failed case of pm_runtime_get_sync, the usage_count is incremented. In order to keep the usage_count with correct value and runtime power management to behave correctly, call pm_runtime_put(_sync) in such case. Hi Fei: It's not necessary. Because the did_runtime_put == true means the port's usage count has already been decreased during usb_port_suspend().So to keep usage count balance, we should increase the usage count in the usb_port_resume() whatever. Signed-off-by Liu Chuansheng chuansheng@intel.com Signed-off-by: Li Fei fei...@intel.com --- drivers/usb/core/hub.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5480352..b68493b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3152,6 +3152,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) if (status 0) { dev_dbg(udev-dev, can't resume usb port, status %d\n, status); + pm_runtime_put_sync(port_dev-dev); return status; } } Hi Alan: Further thinking, the device should be disconnected since the port can't be resumed and the device will not work normally. Something like following. Does this make sense? --- diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d5d3de4..cf36b11 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3170,6 +3170,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) if (status 0) { dev_dbg(udev-dev, can't resume usb port, status %d\n, status); + hub_port_logical_disconnect(hub, port1); return status; } } -- Best regards Tianyu Lan -- 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: [Resend][PATCH] ACPI / glue: Drop .find_bridge() callback from struct acpi_bus_type
On 2013年02月28日 07:31, Yinghai Lu wrote: On Wed, Feb 27, 2013 at 2:20 PM, Greg Kroah-Hartman gre...@linuxfoundation.org wrote: On Wed, Feb 27, 2013 at 11:06:52PM +0100, Rafael J. Wysocki wrote: From: Rafael J. Wysocki rafael.j.wyso...@intel.com After PCI has stopped using the .find_bridge() callback in struct acpi_bus_type, the only remaining users of it are SATA and USB. However, SATA only pretends to be a user, because it points that callback to a stub always returning -ENODEV, and USB uses it incorrectly, because as a result of the way it is used by USB every device in the system that doesn't have a bus type or parent is passed to usb_acpi_find_device() for inspection. What USB actually needs, though, is to call usb_acpi_find_device() for USB ports that don't have a bus type defined, but have usb_port_device_type as their device type. Ick, that's not good. Can you have the original creator of that code (someone else from Intel, I can't remember at the moment), fix that up properly and send me patches? [Add To: Lan Tianyu tianyu@intel.com] Ok. I will fix it later. Please let me know if there are any objections. I still prefer to ask USB to add bus_type instead at first. Thanks Yinghai -- Best regards Tianyu Lan -- 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: [GIT PATCH] USB patches for 3.9-rc1
On 2013/2/22 16:59, Dave Jones wrote: On Thu, Feb 21, 2013 at 10:40:10AM -0800, Greg KH wrote: USB patches for 3.9-rc1 Here's the big USB merge for 3.9-rc1 Nothing major, lots of gadget fixes, and of course, xhci stuff. I get no USB devices recognised when I insert them any more, which I think is pretty major. I suspect it has something to do with this ? Lan Tianyu (12): usb: add runtime pm support for usb port device usb: add usb port auto power off mechanism It looks like every port on my laptop is powered down, as I can't even charge devices with it. Hi Dave: Do you disable usb port's pm_qos_no_power_off? cat /sys/bus/usb/devices/(dev)/port/power/pm_qos_no_power_off I tried running powertop, which noted autosuspend for the usb controllers was 'good'. I flipped them to 'bad', but it made no difference. What can I do to debug this ? Can you attach the output of dmesg with CONFIG_USB_DEBUG? $ lspci | grep USB 00:14.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller (rev 04) 00:1a.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (rev 04) 00:1d.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (rev 04) $ lsusb Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 003: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad] Bus 001 Device 004: ID 5986:02d5 Acer, Inc (inserted USB devices don't show up in this list) $ dmesg | grep -i usb [0.996096] ACPI: bus type usb registered [0.996428] usbcore: registered new interface driver usbfs [0.996638] usbcore: registered new interface driver hub [0.996875] usbcore: registered new device driver usb [1.874896] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver [1.876103] ehci-pci :00:1a.0: new USB bus registered, assigned bus number 1 [1.886220] ehci-pci :00:1a.0: USB 2.0 started, EHCI 1.00 [1.886781] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002 [1.886878] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [1.887017] usb usb1: Product: EHCI Host Controller [1.887111] usb usb1: Manufacturer: Linux 3.8.0+ ehci_hcd [1.887220] usb usb1: SerialNumber: :00:1a.0 [1.888942] hub 1-0:1.0: USB hub found [1.892347] ehci-pci :00:1d.0: new USB bus registered, assigned bus number 2 [1.902216] ehci-pci :00:1d.0: USB 2.0 started, EHCI 1.00 [1.902674] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002 [1.902770] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [1.902910] usb usb2: Product: EHCI Host Controller [1.903004] usb usb2: Manufacturer: Linux 3.8.0+ ehci_hcd [1.903098] usb usb2: SerialNumber: :00:1d.0 [1.90] hub 2-0:1.0: USB hub found [1.906795] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver [1.906970] uhci_hcd: USB Universal Host Controller Interface driver [1.908243] xhci_hcd :00:14.0: new USB bus registered, assigned bus number 3 [1.909823] usb usb3: New USB device found, idVendor=1d6b, idProduct=0002 [1.909920] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [1.910060] usb usb3: Product: xHCI Host Controller [1.910153] usb usb3: Manufacturer: Linux 3.8.0+ xhci_hcd [1.910260] usb usb3: SerialNumber: :00:14.0 [1.911644] hub 3-0:1.0: USB hub found [1.930176] xhci_hcd :00:14.0: new USB bus registered, assigned bus number 4 [1.930802] usb usb4: New USB device found, idVendor=1d6b, idProduct=0003 [1.930899] usb usb4: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [1.931039] usb usb4: Product: xHCI Host Controller [1.931131] usb usb4: Manufacturer: Linux 3.8.0+ xhci_hcd [1.931239] usb usb4: SerialNumber: :00:14.0 [1.932568] hub 4-0:1.0: USB hub found [1.950215] usbcore: registered new interface driver usbserial [1.950388] usbcore: registered new interface driver usbserial_generic [1.950612] usbserial: USB Serial support registered for generic [1.950781] usbcore: registered new interface driver usb_debug [1.950959] usbserial: USB Serial support registered for debug [1.972227] usbcore: registered new interface driver usbhid [1.972322] usbhid: USB HID core driver [2.193584] usb 1-1: new high-speed USB device number 2 using ehci-pci [2.309836] usb 1-1: New USB device found, idVendor=8087, idProduct=0024 [2.309965] usb 1-1: New USB device strings: Mfr=0
Re: [GIT PATCH] USB patches for 3.9-rc1
On 2013/2/23 0:43, Dave Jones wrote: On Fri, Feb 22, 2013 at 05:51:10PM +0800, Lan Tianyu wrote: Nothing major, lots of gadget fixes, and of course, xhci stuff. I get no USB devices recognised when I insert them any more, which I think is pretty major. I suspect it has something to do with this ? Lan Tianyu (12): usb: add runtime pm support for usb port device usb: add usb port auto power off mechanism It looks like every port on my laptop is powered down, as I can't even charge devices with it. Do you enable the port/power/pm_qos_no_power_off? cat /sys/bus/usb/devices/(dev)/port/power/pm_qos_no_power_off to show. /sys/bus/usb/devices/1-1.4/port/power/pm_qos_no_power_off:1 /sys/bus/usb/devices/1-1.6/port/power/pm_qos_no_power_off:1 /sys/bus/usb/devices/1-1/port/power/pm_qos_no_power_off:1 /sys/bus/usb/devices/2-1/port/power/pm_qos_no_power_off:1 At last, this mean usb port power off mechanism should not work. I changed them to 0, made no difference. What can I do to debug this ? Can you attach the output of dmesg with CONFIG_USB_DEBUG? http://paste.fedoraproject.org/3620 How aboutsudo lsusb -s 1:1 -v or 2:1? Dave -- 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: [GIT PATCH] USB patches for 3.9-rc1
On 2013/2/23 1:14, Dave Jones wrote: On Sat, Feb 23, 2013 at 01:02:11AM +0800, Lan Tianyu wrote: What can I do to debug this ? Can you attach the output of dmesg with CONFIG_USB_DEBUG? http://paste.fedoraproject.org/3620 How aboutsudo lsusb -s 1:1 -v or 2:1? (12:13:51:davej@t430s:~)$ sudo lsusb -s 1:1 Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub (12:13:53:davej@t430s:~)$ sudo lsusb -s 2:1 Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Oh. Sorry, I didn't say clearly. Please run sudo lsusb -s 1:1 -v sudo lsusb -s 2:1 -v -- 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: Not enough resource for old configuration after USB bus reset
2013/2/19 Soar Hung soarh...@realtek.com: Hi all, I checkout the usb-next branch (on 2/18) and following the https://wiki.ubuntu.com/KernelTeam/GitKernelBuild to build the kernel. After reboot, the new kernel version is Linux dev 3.8.0-rc5-usbnext #1 SMP Mon Feb 18 18:04:02 CST 2013 i686 i686 i386 GNU/Linux. I try the same operation to produce the issue, and it also fails. Please attach the output of dmesg with CONFIG_USB_DEBUG and XHCI_DEBUG. Thanks, Soar -Original Message- From: Lan Tianyu [mailto:lantianyu1...@gmail.com] Sent: Friday, February 08, 2013 12:57 AM To: Soar Hung Cc: Alan Stern; Sarah Sharp; linux-usb@vger.kernel.org Subject: Re: Not enough resource for old configuration after USB bus reset 于 2013/2/7 16:59, Soar Hung 写道: Hi Tianyu, I can produce the issue on the Ubuntu 12.10 (linux 3.5), too. However, could you tell me more detail about what to do or give me some hint for google? Do you mean replacing the usb related source with source from 'usb next', rebuild the kernel, and test again? I think you can git clone git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git and git checkout usb-next. Compile kernel and test it. Best regards, Soar -Original Message- From: Lan Tianyu [mailto:lantianyu1...@gmail.com] Sent: Thursday, February 07, 2013 4:18 PM To: Soar Hung Cc: Alan Stern; Sarah Sharp; linux-usb@vger.kernel.org Subject: Re: Not enough resource for old configuration after USB bus reset 2013/2/4 Soar Hung soarh...@realtek.com: Hi Alan, Sarah, Thank you for your kindly help. Can I do something to provide some help? You found the issue on the 3.0.30+ kernel. Can you test it on the usb-next branch of usb tree? Sarah has fixed a lot of bugs since v3.0. Best regards, Soar -Original Message- From: Alan Stern [mailto:st...@rowland.harvard.edu] Sent: Friday, February 01, 2013 11:36 PM To: Soar Hung Cc: Sarah Sharp; linux-usb@vger.kernel.org Subject: RE: Not enough resource for old configuration after USB bus reset On Fri, 1 Feb 2013, [big5] x R wrote: Hi, According to xHCI spec Rev1 page 125, Endpoint context state diagram. When reset device, the endpoint state transit to disabled state. Do I make some mistake? I'll try to figure out the endopint state transitions during the reset flow, and update information later. Thanks for the direction. Ah, now I understand the problem. The device reset automatically disables the endpoints, so when usb_reset_and_verify_device calls usb_hcd_alloc_bandwidth, and that routine tries to drop the endpoints, it fails because the endpoints are already disabled. Sarah is going to to have to figure out the right way to fix this. She's the maintainer for xhci-hcd. Alan Stern -- Best regards Tianyu Lan --Please consider the environment before printing this e-mail. -- Best regards Tianyu Lan -- Best regards Tianyu Lan -- 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: Not enough resource for old configuration after USB bus reset
2013/2/4 Soar Hung soarh...@realtek.com: Hi Alan, Sarah, Thank you for your kindly help. Can I do something to provide some help? You found the issue on the 3.0.30+ kernel. Can you test it on the usb-next branch of usb tree? Sarah has fixed a lot of bugs since v3.0. Best regards, Soar -Original Message- From: Alan Stern [mailto:st...@rowland.harvard.edu] Sent: Friday, February 01, 2013 11:36 PM To: Soar Hung Cc: Sarah Sharp; linux-usb@vger.kernel.org Subject: RE: Not enough resource for old configuration after USB bus reset On Fri, 1 Feb 2013, [big5] x R wrote: Hi, According to xHCI spec Rev1 page 125, Endpoint context state diagram. When reset device, the endpoint state transit to disabled state. Do I make some mistake? I'll try to figure out the endopint state transitions during the reset flow, and update information later. Thanks for the direction. Ah, now I understand the problem. The device reset automatically disables the endpoints, so when usb_reset_and_verify_device calls usb_hcd_alloc_bandwidth, and that routine tries to drop the endpoints, it fails because the endpoints are already disabled. Sarah is going to to have to figure out the right way to fix this. She's the maintainer for xhci-hcd. Alan Stern -- Best regards Tianyu Lan -- 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: Not enough resource for old configuration after USB bus reset
于 2013/2/7 16:59, Soar Hung 写道: Hi Tianyu, I can produce the issue on the Ubuntu 12.10 (linux 3.5), too. However, could you tell me more detail about what to do or give me some hint for google? Do you mean replacing the usb related source with source from 'usb next', rebuild the kernel, and test again? I think you can git clone git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git and git checkout usb-next. Compile kernel and test it. Best regards, Soar -Original Message- From: Lan Tianyu [mailto:lantianyu1...@gmail.com] Sent: Thursday, February 07, 2013 4:18 PM To: Soar Hung Cc: Alan Stern; Sarah Sharp; linux-usb@vger.kernel.org Subject: Re: Not enough resource for old configuration after USB bus reset 2013/2/4 Soar Hung soarh...@realtek.com: Hi Alan, Sarah, Thank you for your kindly help. Can I do something to provide some help? You found the issue on the 3.0.30+ kernel. Can you test it on the usb-next branch of usb tree? Sarah has fixed a lot of bugs since v3.0. Best regards, Soar -Original Message- From: Alan Stern [mailto:st...@rowland.harvard.edu] Sent: Friday, February 01, 2013 11:36 PM To: Soar Hung Cc: Sarah Sharp; linux-usb@vger.kernel.org Subject: RE: Not enough resource for old configuration after USB bus reset On Fri, 1 Feb 2013, [big5] x R wrote: Hi, According to xHCI spec Rev1 page 125, Endpoint context state diagram. When reset device, the endpoint state transit to disabled state. Do I make some mistake? I'll try to figure out the endopint state transitions during the reset flow, and update information later. Thanks for the direction. Ah, now I understand the problem. The device reset automatically disables the endpoints, so when usb_reset_and_verify_device calls usb_hcd_alloc_bandwidth, and that routine tries to drop the endpoints, it fails because the endpoints are already disabled. Sarah is going to to have to figure out the right way to fix this. She's the maintainer for xhci-hcd. Alan Stern -- Best regards Tianyu Lan --Please consider the environment before printing this e-mail. -- Best regards Tianyu Lan -- 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
[PATCH] Revert usb: Register usb port's acpi power resources
This reverts commit 88bb965ed711e8a5984e70208ebc901a6ff4141f. The linux-next branch of linux-pm tree has replaced acpi_power_resource_(un)register_device() with new routines. Commit 88bb965 will cause conflict in the linux-next tree. So revert it and this will not affect other functions. Will send a new patch with new routines after 3.9 merge window. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |6 -- drivers/usb/core/usb-acpi.c | 18 -- drivers/usb/core/usb.h |6 -- 3 files changed, 30 deletions(-) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 5df143d..797f9d5 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -68,7 +68,6 @@ static void usb_port_device_release(struct device *dev) struct usb_port *port_dev = to_usb_port(dev); dev_pm_qos_hide_flags(dev); - usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -187,11 +186,6 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) pm_runtime_enable(port_dev-dev); device_enable_async_suspend(port_dev-dev); - - retval = usb_acpi_register_power_resources(port_dev-dev); - if (retval retval != -ENODEV) - dev_warn(port_dev-dev, the port can't register its ACPI power resource.\n); - return 0; error_register: diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 8d304b0..cef4252 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -216,24 +216,6 @@ static struct acpi_bus_type usb_acpi_bus = { .find_device = usb_acpi_find_device, }; -int usb_acpi_register_power_resources(struct device *dev) -{ - acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); - - if (!port_handle) - return -ENODEV; - - return acpi_power_resource_register_device(dev, port_handle); -} - -void usb_acpi_unregister_power_resources(struct device *dev) -{ - acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); - - if (port_handle) - acpi_power_resource_unregister_device(dev, port_handle); -} - int usb_acpi_register(void) { return register_acpi_bus_type(usb_acpi_bus); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 601b044..a7f20bd 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -191,13 +191,7 @@ extern int usb_acpi_register(void); extern void usb_acpi_unregister(void); extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, int port1); -extern int usb_acpi_register_power_resources(struct device *dev); -extern void usb_acpi_unregister_power_resources(struct device *dev); #else static inline int usb_acpi_register(void) { return 0; }; static inline void usb_acpi_unregister(void) { }; -static inline int usb_acpi_register_power_resources(struct device *dev) - { return 0; }; -static inline void usb_acpi_unregister_power_resources(struct device *dev) - { }; #endif -- 1.7.9.5 -- 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 v2 1/3] usb: add find_raw_port_number callback to struct hc_driver()
On 2013年01月25日 08:52, Sarah Sharp wrote: Please combine this patch with patch three, so that I can clearly see what is being replaced in xhci-mem.c:xhci_find_real_port_number. Ok, I will refresh it soon. Sarah Sharp On Sat, Jan 19, 2013 at 12:43:32AM +0800, Lan Tianyu wrote: xhci driver divides the root hub into two logical hubs which work respectively for usb 2.0 and usb 3.0 devices. They are independent devices in the usb core. But in the ACPI table, it's one device node and all usb2.0 and usb3.0 ports are under it. Binding usb port with its acpi node needs the raw port number which is reflected in the xhci extended capabilities table. This patch is to add find_raw_port_number callback to struct hc_driver() and fill it with xhci_find_raw_port_number(). Signed-off-by: Lan Tianyu tianyu@intel.com --- Change since v1: Don't export usb_hcd_find_raw_port_number() symbol since there is no its user outside of usb core. This patchset is rebased on the usb-next tree commit 74ff31b81d9 usb: misc: usb3503_probe() can be static --- drivers/usb/core/hcd.c |8 drivers/usb/host/xhci-pci.c |1 + drivers/usb/host/xhci.c | 22 ++ drivers/usb/host/xhci.h |1 + include/linux/usb/hcd.h |2 ++ 5 files changed, 34 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5f6da8b..0277bd2 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2364,6 +2364,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd) } EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd); +int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ +if (!hcd-driver-find_raw_port_number) +return port1; + +return hcd-driver-find_raw_port_number(hcd, port1); +} + static int usb_hcd_request_irqs(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags) { diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index af259e0..1a30c38 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = { .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, +.find_raw_port_number = xhci_find_raw_port_number, }; /*-*/ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f1f01a8..0780d8f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3778,6 +3778,28 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) return 0; } +/* + * Transfer the port index into real index in the HW port status + * registers. Caculate offset between the port's PORTSC register + * and port status base. Divide the number of per port register + * to get the real index. The raw port number bases 1. + */ +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ +struct xhci_hcd *xhci = hcd_to_xhci(hcd); +__le32 __iomem *base_addr = xhci-op_regs-port_status_base; +__le32 __iomem *addr; +int raw_port; + +if (hcd-speed != HCD_USB3) +addr = xhci-usb2_ports[port1 - 1]; +else +addr = xhci-usb3_ports[port1 - 1]; + +raw_port = (addr - base_addr)/NUM_PORT_REGS + 1; +return raw_port; +} + #ifdef CONFIG_USB_SUSPEND /* BESL to HIRD Encoding array for USB2 LPM */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f791bd0..55345d9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1829,6 +1829,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); #ifdef CONFIG_PM int xhci_bus_suspend(struct usb_hcd *hcd); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 608050b..61b88b5 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -357,6 +357,7 @@ struct hc_driver { */ int (*disable_usb3_lpm_timeout)(struct usb_hcd *, struct usb_device *, enum usb3_link_state state); +int (*find_raw_port_number)(struct usb_hcd *, int); }; extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); @@ -396,6 +397,7 @@ extern int usb_hcd_is_primary_hcd(struct usb_hcd *hcd); extern int usb_add_hcd(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags); extern void usb_remove_hcd(struct usb_hcd *hcd); +extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1
[PATCH v3 1/2] usb: add find_raw_port_number callback to struct hc_driver()
xhci driver divides the root hub into two logical hubs which work respectively for usb 2.0 and usb 3.0 devices. They are independent devices in the usb core. But in the ACPI table, it's one device node and all usb2.0 and usb3.0 ports are under it. Binding usb port with its acpi node needs the raw port number which is reflected in the xhci extended capabilities table. This patch is to add find_raw_port_number callback to struct hc_driver() and fill it with xhci_find_raw_port_number(). Otherwise, call xhci_find_raw_port_number() to get real index in the HW port status registers instead of scanning through the xHCI roothub port array in the xhci_find_real_port_number(). Signed-off-by: Lan Tianyu tianyu@intel.com --- Change since v1: Don't export usb_hcd_find_raw_port_number() symbol since there is no its user outside of usb core. Change since v2: combine patch usb: add find_raw_port_number callback to struct hc_driver() with this patch. This patchset is rebased on the usb-next tree commit 6e24777 usb: ehci-s5p/ohci-exynos: Fix compatible strings for the device drivers/usb/core/hcd.c |9 + drivers/usb/host/xhci-mem.c | 36 drivers/usb/host/xhci-pci.c |1 + drivers/usb/host/xhci.c | 22 ++ drivers/usb/host/xhci.h |1 + include/linux/usb/hcd.h |2 ++ 6 files changed, 43 insertions(+), 28 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 2459896..774ac61 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2368,6 +2368,15 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd) } EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd); +int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ + if (!hcd-driver-find_raw_port_number) + return port1; + + return hcd-driver-find_raw_port_number(hcd, port1); +} +EXPORT_SYMBOL_GPL(usb_hcd_find_raw_port_number); + static int usb_hcd_request_irqs(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags) { diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 35616ff..6dc238c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, * is attached to (or the roothub port its ancestor hub is attached to). All we * know is the index of that port under either the USB 2.0 or the USB 3.0 * roothub, but that doesn't give us the real index into the HW port status - * registers. Scan through the xHCI roothub port array, looking for the Nth - * entry of the correct port speed. Return the port number of that entry. + * registers. Call xhci_find_raw_port_number() to get real index. */ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, struct usb_device *udev) { struct usb_device *top_dev; - unsigned int num_similar_speed_ports; - unsigned int faked_port_num; - int i; + struct usb_hcd *hcd; + + if (udev-speed == USB_SPEED_SUPER) + hcd = xhci-shared_hcd; + else + hcd = xhci-main_hcd; for (top_dev = udev; top_dev-parent top_dev-parent-parent; top_dev = top_dev-parent) /* Found device below root hub */; - faked_port_num = top_dev-portnum; - for (i = 0, num_similar_speed_ports = 0; - i HCS_MAX_PORTS(xhci-hcs_params1); i++) { - u8 port_speed = xhci-port_array[i]; - - /* -* Skip ports that don't have known speeds, or have duplicate -* Extended Capabilities port speed entries. -*/ - if (port_speed == 0 || port_speed == DUPLICATE_ENTRY) - continue; - /* -* USB 3.0 ports are always under a USB 3.0 hub. USB 2.0 and -* 1.1 ports are under the USB 2.0 hub. If the port speed -* matches the device speed, it's a similar speed port. -*/ - if ((port_speed == 0x03) == (udev-speed == USB_SPEED_SUPER)) - num_similar_speed_ports++; - if (num_similar_speed_ports == faked_port_num) - /* Roothub ports are numbered from 1 to N */ - return i+1; - } - return 0; + return xhci_find_raw_port_number(hcd, top_dev-portnum); } /* Setup an xHCI virtual device for a Set Address command */ diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index af259e0..1a30c38 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = { .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout
[PATCH v3 2/2] usb/acpi: binding xhci root hub usb port with ACPI
This patch is to bind xhci root hub usb port with its acpi node. The port num in the acpi table matches with the sequence in the xhci extended capabilities table. So call usb_hcd_find_raw_port_number() to transfer hub port num into raw port number which associates with the sequence in the xhci extended capabilities table before binding. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/usb-acpi.c |4 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252..40f5a6a 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -15,6 +15,7 @@ #include linux/kernel.h #include linux/acpi.h #include linux/pci.h +#include linux/usb/hcd.h #include acpi/acpi_bus.h #include usb.h @@ -188,6 +189,9 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) * connected to. */ if (!udev-parent) { + struct usb_hcd *hcd = bus_to_hcd(udev-bus); + + port_num = usb_hcd_find_raw_port_number(hcd, port_num); *handle = acpi_get_child(DEVICE_ACPI_HANDLE(udev-dev), port_num); if (!*handle) -- 1.7.9.5 -- 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
[PATCH v2 1/2] usb: Using correct way to clear usb3.0 device's remote wakeup feature.
Usb3.0 device defines function remote wakeup which is only for interface recipient rather than device recipient. This is different with usb2.0 device's remote wakeup feature which is defined for device recipient. According usb3.0 spec 9.4.5, the function remote wakeup can be modified by the SetFeature() requests using the FUNCTION_SUSPEND feature selector. This patch is to use correct way to disable usb3.0 device's function remote wakeup after suspend error and resuming. Signed-off-by: Lan Tianyu tianyu@intel.com --- This patchset is based on the usb-next tree commit d2123fd: USB: Set usb port's DeviceRemovable according acpi information drivers/usb/core/hub.c | 70 +++--- include/uapi/linux/usb/ch9.h |6 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 29ca6ed..29791a6 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2776,6 +2776,23 @@ void usb_enable_ltm(struct usb_device *udev) EXPORT_SYMBOL_GPL(usb_enable_ltm); #ifdef CONFIG_USB_SUSPEND +/* + * usb_disable_function_remotewakeup - disable usb3.0 + * device's function remote wakeup + * @udev: target device + * + * Assume there's only one function on the USB 3.0 + * device and disable remote wake for the first + * interface. FIXME if the interface association + * descriptor shows there's more than one function. + */ +static int usb_disable_function_remotewakeup(struct usb_device *udev) +{ + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} /* * usb_port_suspend - suspend a usb device's upstream port @@ -2891,12 +2908,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) dev_dbg(hub-intfdev, can't suspend port %d, status %d\n, port1, status); /* paranoia: should not happen */ - if (udev-do_remote_wakeup) - (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + if (udev-do_remote_wakeup) { + if (!hub_is_superspeed(hub-hdev)) { + (void) usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else + (void) usb_disable_function_remotewakeup(udev); + + } /* Try to enable USB2 hardware LPM again */ if (udev-usb2_hw_lpm_capable == 1) @@ -2988,20 +3012,30 @@ static int finish_port_resume(struct usb_device *udev) * udev-reset_resume */ } else if (udev-actconfig !udev-reset_resume) { - le16_to_cpus(devstatus); - if (devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) { - status = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, + if (!hub_is_superspeed(udev-parent)) { + le16_to_cpus(devstatus); + if (devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - if (status) - dev_dbg(udev-dev, - disable remote wakeup, status %d\n, - status); + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + devstatus); + le16_to_cpus(devstatus
[PATCH v2 2/2] usb: add usb_enable/disable_remote_wakeup()
usb2.0 and usb3.0 devices have different ways to enalbe/disable remote wakeup. This patch is to put both their operations into the seperate functions. Otherwise, usb_control_msg() has some long arguments and are usually nested some indentations. So encapsulating it into seperate functions would be convienient to use and more readable. Signed-off-by: Lan Tianyu tianyu@intel.com --- Change since v1: remove usb_disable_function_remotewakeup() and call usb_control_msg() directly in the usb_disable_remote_wakeup() drivers/usb/core/hub.c | 136 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 29791a6..4c14b04 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2776,22 +2776,72 @@ void usb_enable_ltm(struct usb_device *udev) EXPORT_SYMBOL_GPL(usb_enable_ltm); #ifdef CONFIG_USB_SUSPEND -/* - * usb_disable_function_remotewakeup - disable usb3.0 - * device's function remote wakeup - * @udev: target device - * - * Assume there's only one function on the USB 3.0 - * device and disable remote wake for the first - * interface. FIXME if the interface association - * descriptor shows there's more than one function. - */ -static int usb_disable_function_remotewakeup(struct usb_device *udev) +static int usb_disable_remote_wakeup(struct usb_device *udev) { - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, - USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + int status = 0; + u16 devstatus; + + if (udev-speed != USB_SPEED_SUPER) { + status = usb_get_status(udev, USB_RECIP_DEVICE, 0, devstatus); + le16_to_cpus(devstatus); + if (!status devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* +* Assume there's only one function on the USB 3.0 +* device and disable remote wake for the first +* interface. FIXME if the interface association +* descriptor shows there's more than one function. +*/ + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + devstatus); + le16_to_cpus(devstatus); + if (!status devstatus + (USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW)) + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } + + return status; +} + +static int usb_enable_remote_wakeup(struct usb_device *udev) +{ + int status; + + if (udev-speed != USB_SPEED_SUPER) { + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* Assume there's only one function on the USB 3.0 +* device and enable remote wake for the first +* interface. FIXME if the interface association +* descriptor shows there's more than one function. +*/ + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, + USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, + USB_INTRF_FUNC_SUSPEND_RW | + USB_INTRF_FUNC_SUSPEND_LP, + NULL, 0, USB_CTRL_SET_TIMEOUT); + } + + return status; } /* @@ -2853,27 +2903,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) * we don't explicitly enable it here. */ if (udev-do_remote_wakeup) { - if (!hub_is_superspeed(hub-hdev)) { - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE
Re: [PATCH v6 6/8] usb: expose usb port's pm qos flags to user space
On 2013/1/22 5:31, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:05PM +0800, Lan Tianyu wrote: This patch is to expose usb port's pm qos flags(pm_qos_no_power_off, pm_qos_remote_wakeup) to user space. User can set pm_qos_no_power_off flag to prohibit the port from being powered off. How are they now seen by userspace? Should a new Documentation/ABI entry be created somewhere describing this? There are already some descriptors in the Documentation/ABI/testing/sysfs-devices-power(line 208, lin223). 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 7/8] usb: add usb_device_allow_power_off() and usb_device_prevent_power_off() function.
On 2013/1/22 5:33, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:06PM +0800, Lan Tianyu wrote: Some usb devices can't be resumed correctly after power off. This patch is to add usb_device_allow_power_off() and usb_device_prevent_power_off() for device's driver. Call pm_runtime_get_sync(portdev) to increase port's usage count and then port will not be suspended. The device will not be powered off. Please linewrap comments at the proper level (git likes 72). Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 0c51d24..0334d91 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -18,11 +18,39 @@ #include linux/slab.h #include linux/pm_qos.h +#include linux/module.h #include hub.h static const struct attribute_group *port_dev_group[]; +/** + * usb_device_control_power_off - Allow or prohibit power off device. + * @udev: target usb device + * @allow: choice of allow or prohibit + * + * Call pm_runtime_get/put_sync(portdev) to allow or prohibit target + * usb device to be powered off in the kernel. The operations of setting + * true and false should be couple. The default status is allowed. + */ +int usb_device_control_power_off(struct usb_device *udev, bool allow) Ick, again with the boolean variables. Please don't do this, just make two different functions: usb_device_allow_power_off() usb_device_forbid_power_off() that makes it much easier to understand when you see the function being called, right? Ok. I will do 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 7/8] usb: add usb_device_allow_power_off() and usb_device_prevent_power_off() function.
On 2013/1/22 5:33, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:06PM +0800, Lan Tianyu wrote: Some usb devices can't be resumed correctly after power off. This patch is to add usb_device_allow_power_off() and usb_device_prevent_power_off() for device's driver. Call pm_runtime_get_sync(portdev) to increase port's usage count and then port will not be suspended. The device will not be powered off. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 0c51d24..0334d91 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -18,11 +18,39 @@ #include linux/slab.h #include linux/pm_qos.h +#include linux/module.h #include hub.h static const struct attribute_group *port_dev_group[]; +/** + * usb_device_control_power_off - Allow or prohibit power off device. + * @udev: target usb device + * @allow: choice of allow or prohibit + * + * Call pm_runtime_get/put_sync(portdev) to allow or prohibit target + * usb device to be powered off in the kernel. The operations of setting + * true and false should be couple. The default status is allowed. + */ +int usb_device_control_power_off(struct usb_device *udev, bool allow) +{ + struct usb_port *port_dev; + + if (!udev-parent) + return -EINVAL; + + port_dev = hdev_to_hub(udev-parent)-ports[udev-portnum - 1]; + + if (allow) + pm_runtime_put_sync(port_dev-dev); + else + pm_runtime_get_sync(port_dev-dev); + + return 0; +} +EXPORT_SYMBOL_GPL(usb_device_control_power_off); Oh, I don't see any code calling this function, so why did you add it? Who needs it? Where is that code? This is provided for device driver. Some device may not be compatible with the power off mechanism and driver can use these function to forbid/allow it. But currently, we are not sure which kinds of device they are. So just provide new interfaces. 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 8/8] usb: enable usb port device's async suspend.
On 2013/1/22 5:34, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:07PM +0800, Lan Tianyu wrote: Signed-off-by: Lan Tianyu tianyu@intel.com Why are you doing this? Why is it now ok? We need a much better changelog entry here. Ok. I will add later. 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 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 7/8] usb: add usb_device_allow_power_off() and usb_device_prevent_power_off() function.
On 2013/1/22 23:05, Greg KH wrote: On Tue, Jan 22, 2013 at 10:23:12PM +0800, Lan Tianyu wrote: On 2013/1/22 5:33, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:06PM +0800, Lan Tianyu wrote: Some usb devices can't be resumed correctly after power off. This patch is to add usb_device_allow_power_off() and usb_device_prevent_power_off() for device's driver. Call pm_runtime_get_sync(portdev) to increase port's usage count and then port will not be suspended. The device will not be powered off. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 0c51d24..0334d91 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -18,11 +18,39 @@ #include linux/slab.h #include linux/pm_qos.h +#include linux/module.h #include hub.h static const struct attribute_group *port_dev_group[]; +/** + * usb_device_control_power_off - Allow or prohibit power off device. + * @udev: target usb device + * @allow: choice of allow or prohibit + * + * Call pm_runtime_get/put_sync(portdev) to allow or prohibit target + * usb device to be powered off in the kernel. The operations of setting + * true and false should be couple. The default status is allowed. + */ +int usb_device_control_power_off(struct usb_device *udev, bool allow) +{ + struct usb_port *port_dev; + + if (!udev-parent) + return -EINVAL; + + port_dev = hdev_to_hub(udev-parent)-ports[udev-portnum - 1]; + + if (allow) + pm_runtime_put_sync(port_dev-dev); + else + pm_runtime_get_sync(port_dev-dev); + + return 0; +} +EXPORT_SYMBOL_GPL(usb_device_control_power_off); Oh, I don't see any code calling this function, so why did you add it? Who needs it? Where is that code? This is provided for device driver. Some device may not be compatible with the power off mechanism and driver can use these function to forbid/allow it. But currently, we are not sure which kinds of device they are. So just provide new interfaces. We don't add new interfaces to the kernel unless they have a user. If I were to see this in the tree, I would expect it to be removed because of that. So don't add it at all, only add it when it is needed. Ok. I will add it later when I find such device. 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 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 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
[PATCH V7 0/6] usb: usb port power off mechanism
Change since v1: optimize the export connect type patch and adjust the DeviceRemovalbe flag in the rh_call_control() after GetHubDescriptor request being processed. move all debounce operation to usb port's runtime resume callback(). Add did_runtime_put in the struct usb_port to call pm_runtime_get/put(portdev) paired. using pm_runtime_get/put(portdev) to allow or prohibit device to be power off inside of pm qos request in the kernel side. Change since v2: Correct some link breaks. Add did_runtime_put in the usb_disconnect() before calling pm_runtime_put(portdev). Provide two seperate functions usb_device_allow_power_off() and usb_device_prevent_power_off() instead of just one. Change since v3: Set did_runtime_put to false in usb_disconnect() when its value is true Add comment about not enable port runtime pm if fail to expose port's pm qos. and call pm_runtime_set_active(portdev) unconditionally. rename usb_device_allow_prevent_power_off with usb_device_control_power_off Modify be power off to be powered off Expose dev_pm_qos_flags() symbol in order to ensure usb core can compile as module. Resend v4: make patch PM/Qos: Expose dev_pm_qos_flags symbol as first patch to avoid compilation error during git bisect correct some comments. Change since v4: use EXPORT_SYMBOL_GPL to export dev_pm_qos_flags(). correct some unnecessary link breaks. Add CONFIG_USB_SUSPEND check around usb_port_runtime_resume() and usb_port_runtime_suspend() Change since v5: predefine struct usb_hub_descriptor in the /driver/usb/core/usb.h instead of including linux/usb/ch11.h move patch PM/Qos: Expose dev_pm_qos_flags symbol before patch usb: add runtime pm support for usb port device where dev_pm_qos_flags() fistly is called. Change since v6: Patch 1: add usb_acpi_register_power_resources() error handle. If there was acpi power resource for usb port and register failed, produce a warning. Patch 3: add kerneldoc for usb_hub_set_port_power() Patch 4: add more detail change logs. Make clear_port_feature() and hdev_to_hub() as global symbol. Extend hub_port_debounce() and add two wraps to call it. Change soeme indention. Patch 6: add changelog This patchset is based on usb-next tree commit d2123fd USB: Set usb port's DeviceRemovable according acpi information This patchset is to add usb port power off mechanism and merge with patchset usb: expose DeviceRemovable to user space via sysfs attribute. Patchset usb: expose DeviceRemovable to user space via sysfs attribute. http://marc.info/?l=linux-usbm=135279430410171w=2 with some link break corrects The main discussion about usb port power off mechanism is in the following link: http://marc.info/?l=linux-usbm=134818340017208w=2 usb: Register usb port's acpi power resources PM/Qos: Expose dev_pm_qos_flags symbol usb: add runtime pm support for usb port device usb: add usb port auto power off mechanism usb: expose usb port's pm qos flags to user space usb: enable usb port device's async suspend. -- 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
[PATCH v7 1/6] usb: Register usb port's acpi power resources
This patch is to register usb port's acpi power resources. Create link between usb port device and its acpi power resource. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |5 + drivers/usb/core/usb-acpi.c | 18 ++ drivers/usb/core/usb.h |6 ++ 3 files changed, 29 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index fe5959f..153e799 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -66,6 +66,7 @@ static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); + usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -95,6 +96,10 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) if (retval) goto error_register; + retval = usb_acpi_register_power_resources(port_dev-dev); + if (retval retval != -ENODEV) + dev_warn(port_dev-dev, the port can't register its ACPI power resource.\n); + return 0; error_register: diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252..8d304b0 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -216,6 +216,24 @@ static struct acpi_bus_type usb_acpi_bus = { .find_device = usb_acpi_find_device, }; +int usb_acpi_register_power_resources(struct device *dev) +{ + acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + + if (!port_handle) + return -ENODEV; + + return acpi_power_resource_register_device(dev, port_handle); +} + +void usb_acpi_unregister_power_resources(struct device *dev) +{ + acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + + if (port_handle) + acpi_power_resource_unregister_device(dev, port_handle); +} + int usb_acpi_register(void) { return register_acpi_bus_type(usb_acpi_bus); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index a7f20bd..601b044 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -191,7 +191,13 @@ extern int usb_acpi_register(void); extern void usb_acpi_unregister(void); extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, int port1); +extern int usb_acpi_register_power_resources(struct device *dev); +extern void usb_acpi_unregister_power_resources(struct device *dev); #else static inline int usb_acpi_register(void) { return 0; }; static inline void usb_acpi_unregister(void) { }; +static inline int usb_acpi_register_power_resources(struct device *dev) + { return 0; }; +static inline void usb_acpi_unregister_power_resources(struct device *dev) + { }; #endif -- 1.7.9.5 -- 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
[PATCH v7 2/6] PM/Qos: Expose dev_pm_qos_flags symbol
The dev_pm_qos_flags() will be used in the usb core which could be compiled as a module. This patch is to export it. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/base/power/qos.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index d213495..3d4d1f8 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -91,6 +91,7 @@ enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask) return ret; } +EXPORT_SYMBOL_GPL(dev_pm_qos_flags); /** * __dev_pm_qos_read_value - Get PM QoS constraint for a given device. -- 1.7.9.5 -- 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
[PATCH v7 3/6] usb: add runtime pm support for usb port device
This patch is to add runtime pm callback for usb port device. Set/clear PORT_POWER feature in the resume/suspend callback. Add portnum for struct usb_port to record port number. Do pm_rumtime_get_sync/put(portdev) when a device is plugged/unplugged to prevent it from being powered off when it is active. 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 | 27 +++ drivers/usb/core/hub.h |4 drivers/usb/core/port.c | 46 ++ 3 files changed, 77 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 29ca6ed..7fb1633 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -715,6 +715,27 @@ static void hub_tt_work(struct work_struct *work) } /** + * usb_hub_set_port_power - control hub port's power state + * @hdev: target hub + * @port1: port index + * @set: expected status + * + * call this function to control port's power via setting or + * clearing the port's PORT_POWER feature. + */ +int usb_hub_set_port_power(struct usb_device *hdev, int port1, + bool set) +{ + int ret; + + if (set) + ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + else + ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + return ret; +} + +/** * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub * @urb: an URB associated with the failed or incomplete split transaction * @@ -1569,6 +1590,7 @@ static void hub_disconnect(struct usb_interface *intf) kfree(hub-status); kfree(hub-buffer); + pm_suspend_ignore_children(intf-dev, false); kref_put(hub-kref, hub_release); } @@ -1671,6 +1693,7 @@ descriptor_error: usb_set_intfdata (intf, hub); intf-needs_remote_wakeup = 1; + pm_suspend_ignore_children(intf-dev, true); if (hdev-speed == USB_SPEED_HIGH) highspeed_hubs++; @@ -1997,6 +2020,8 @@ 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); } usb_remove_ep_devs(udev-ep0); @@ -2307,6 +2332,8 @@ int usb_new_device(struct usb_device *udev) sysfs_remove_link(udev-dev.kobj, port); goto fail; } + + pm_runtime_get_sync(port_dev-dev); } (void) usb_create_ep_devs(udev-dev, udev-ep0, udev); diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index d16a7c9..8ea6bc8 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -79,12 +79,14 @@ struct usb_hub { * @dev: generic device interface * @port_owner: port's owner * @connect_type: port's connect type + * @portnum: port index num based one */ struct usb_port { struct usb_device *child; struct device dev; struct dev_state *port_owner; enum usb_port_connect_type connect_type; + u8 portnum; }; #define to_usb_port(_dev) \ @@ -94,4 +96,6 @@ extern int usb_hub_create_port_device(struct usb_hub *hub, int port1); extern void usb_hub_remove_port_device(struct usb_hub *hub, int port1); +extern int usb_hub_set_port_power(struct usb_device *hdev, + int port1, bool set); diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 153e799..169c89e 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -17,6 +17,7 @@ */ #include linux/slab.h +#include linux/pm_qos.h #include hub.h @@ -70,9 +71,50 @@ static void usb_port_device_release(struct device *dev) kfree(port_dev); } +#ifdef CONFIG_USB_SUSPEND +static int usb_port_runtime_resume(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + struct usb_device *hdev = to_usb_device(dev-parent-parent); + struct usb_interface *intf = to_usb_interface(dev-parent); + int retval; + + usb_autopm_get_interface(intf); + retval = usb_hub_set_port_power(hdev, port_dev-portnum, true); + usb_autopm_put_interface(intf); + return retval; +} + +static int usb_port_runtime_suspend(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + struct usb_device *hdev = to_usb_device(dev-parent-parent); + struct usb_interface *intf = to_usb_interface(dev-parent); + int retval; + + if (dev_pm_qos_flags(port_dev-dev, PM_QOS_FLAG_NO_POWER_OFF) + == PM_QOS_FLAGS_ALL) + return -EAGAIN; + + usb_autopm_get_interface(intf); + retval = usb_hub_set_port_power(hdev, port_dev-portnum, false); + usb_autopm_put_interface(intf); + return retval; +} +#endif + +static const
[PATCH v7 5/6] usb: expose usb port's pm qos flags to user space
This patch is to expose usb port's pm qos flags(pm_qos_no_power_off, pm_qos_remote_wakeup) to user space. User can set pm_qos_no_power_off flag to prohibit the port from being powered off. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 36003e0..968dd41 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -67,6 +67,7 @@ static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); + dev_pm_qos_hide_flags(dev); usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -176,7 +177,15 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) goto error_register; pm_runtime_set_active(port_dev-dev); - pm_runtime_enable(port_dev-dev); + + /* It would be dangerous if user space couldn't +* prevent usb device from being powered off. So don't +* enable port runtime pm if failed to expose port's pm qos. +*/ + if (!dev_pm_qos_expose_flags(port_dev-dev, + PM_QOS_FLAG_NO_POWER_OFF)) + pm_runtime_enable(port_dev-dev); + retval = usb_acpi_register_power_resources(port_dev-dev); if (retval retval != -ENODEV) -- 1.7.9.5 -- 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
[PATCH v7 6/6] usb: enable usb port device's async suspend.
This patch is to set power.async_suspend for usb port in order to allow it to be suspended and resumed asynchronously during system sleep transitions. The power.async_suspend flag is also set for devices that don't have suspend or resume callbacks, because otherwise they would make the main suspend/resume thread wait for their asynchronous children (during suspend) or parents (during resume), effectively negating the possible gains from executing these devices' suspend and resume callbacks asynchronously. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 968dd41..0248b88 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -186,6 +186,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) PM_QOS_FLAG_NO_POWER_OFF)) pm_runtime_enable(port_dev-dev); + device_enable_async_suspend(port_dev-dev); retval = usb_acpi_register_power_resources(port_dev-dev); if (retval retval != -ENODEV) -- 1.7.9.5 -- 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
[PATCH v7 4/6] usb: add usb port auto power off mechanism
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 to ensure pm_runtime_get/put(portdev) to be called pairedly. Set did_runtime_put to true when call pm_runtime_put(portdev) during suspending. The pm_runtime_get(portdev) only will be called when did_runtime_put is set to true during resuming. Set did_runtime_put to false after calling pm_runtime_get(portdev). Make clear_port_feature() and hdev_to_hub() as global symbol. Rename clear_port_feature() to usb_clear_port_feature() and hdev_to_hub() to usb_hub_to_struct_hub(). Extend hub_port_debounce() with the fuction of debouncing to be connected. Add two wraps: hub_port_debounce_be_connected() and hub_port_debouce_be_stable(). Increase HUB_DEBOUNCE_TIMEOUT to 2000 because some usb ssds needs around 1.5 or more to make the hub port status to be connected steadily after being powered off and powered on. 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 | 161 ++- drivers/usb/core/hub.h | 21 +++ drivers/usb/core/port.c | 40 +++- 3 files changed, 164 insertions(+), 58 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7fb1633..0883364 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 #define HUB_DEBOUNCE_STEP25 #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 *usb_hub_to_struct_hub(struct usb_device *hdev) { if (!hdev || !hdev-actconfig || !hdev-maxchild) return NULL; @@ -301,7 +302,7 @@ static void usb_set_lpm_parameters(struct usb_device *udev) if (!udev-lpm_capable || udev-speed != USB_SPEED_SUPER) return; - hub = hdev_to_hub(udev-parent); + hub = usb_hub_to_struct_hub(udev-parent); /* It doesn't take time to transition the roothub into U0, since it * doesn't have an upstream link. */ @@ -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 usb_clear_port_feature(struct usb_device *hdev, int port1, int feature) { return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1, @@ -586,7 +587,7 @@ static void kick_khubd(struct usb_hub *hub) void usb_kick_khubd(struct usb_device *hdev) { - struct usb_hub *hub = hdev_to_hub(hdev); + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); if (hub) kick_khubd(hub); @@ -608,7 +609,7 @@ void usb_wakeup_notification(struct usb_device *hdev, if (!hdev) return; - hub = hdev_to_hub(hdev); + hub = usb_hub_to_struct_hub(hdev); if (hub) { set_bit(portnum, hub-wakeup_bits); kick_khubd(hub); @@ -727,11 +728,16 @@ int usb_hub_set_port_power(struct usb_device *hdev, int port1, bool set) { int ret; + struct usb_hub *hub = usb_hub_to_struct_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); + ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + + if (!ret) + port_dev-power_is_on = set; return ret; } @@ -811,7 +817,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
[PATCH V6 0/8] usb: usb port power off mechanism and expose usb port connect type
Change since v1: optimize the export connect type patch and adjust the DeviceRemovalbe flag in the rh_call_control() after GetHubDescriptor request being processed. move all debounce operation to usb port's runtime resume callback(). Add did_runtime_put in the struct usb_port to call pm_runtime_get/put(portdev) paired. using pm_runtime_get/put(portdev) to allow or prohibit device to be power off inside of pm qos request in the kernel side. Change since v2: Correct some link breaks. Add did_runtime_put in the usb_disconnect() before calling pm_runtime_put(portdev). Provide two seperate functions usb_device_allow_power_off() and usb_device_prevent_power_off() instead of just one. Change since v3: Set did_runtime_put to false in usb_disconnect() when its value is true Add comment about not enable port runtime pm if fail to expose port's pm qos. and call pm_runtime_set_active(portdev) unconditionally. rename usb_device_allow_prevent_power_off with usb_device_control_power_off Modify be power off to be powered off Expose dev_pm_qos_flags() symbol in order to ensure usb core can compile as module. Resend v4: make patch PM/Qos: Expose dev_pm_qos_flags symbol as first patch to avoid compilation error during git bisect correct some comments. Change since v4: use EXPORT_SYMBOL_GPL to export dev_pm_qos_flags(). correct some unnecessary link breaks. Add CONFIG_USB_SUSPEND check around usb_port_runtime_resume() and usb_port_runtime_suspend() Change since v5: predefine struct usb_hub_descriptor in the /driver/usb/core/usb.h instead of including linux/usb/ch11.h move patch PM/Qos: Expose dev_pm_qos_flags symbol before patch usb: add runtime pm support for usb port device where dev_pm_qos_flags() fistly is called. This patchset is based on usb-next tree commit f4cc1834 USB: storage: avoid scanning other targets for single target device This patchset is to add usb port power off mechanism and merge with patchset usb: expose DeviceRemovable to user space via sysfs attribute. Patchset usb: expose DeviceRemovable to user space via sysfs attribute. http://marc.info/?l=linux-usbm=135279430410171w=2 with some link break corrects The main discussion about usb port power off mechanism is in the following link: http://marc.info/?l=linux-usbm=134818340017208w=2 USB: Set usb port's DeviceRemovable according acpi information usb: Register usb port's acpi power resources PM/Qos: Expose dev_pm_qos_flags symbol usb: add runtime pm support for usb port device usb: add usb port auto power off mechanism usb: expose usb port's pm qos flags to user space usb: add usb_device_allow_power_off() and usb_device_prevent_power_off() function. usb: enable usb port device's async suspend. -- 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
[PATCH v6 1/8] USB: Set usb port's DeviceRemovable according acpi information
ACPI provide _PLD and _UPC aml methods to describe usb port visibility and connectability. This patch is to add usb_hub_adjust_DeviceRemovable() to adjust usb hub port's DeviceRemovable according ACPI information and invoke it in the rh_call_control(). When hub descriptor request is issued at first time, usb port device isn't created and usb port is not bound with acpi. So first hub descriptor request is not changed based on ACPI information. After usb port devices being created, call usb_hub_adjust_DeviceRemovable in the hub_configure() and then set hub port's DeviceRemovable according ACPI information and this also works for non-root hub. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hcd.c |4 drivers/usb/core/hub.c | 43 +++ drivers/usb/core/usb.h |3 +++ 3 files changed, 50 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5f6da8b..2459896 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -619,6 +619,10 @@ nongeneric: status = hcd-driver-hub_control (hcd, typeReq, wValue, wIndex, tbuf, wLength); + + if (typeReq == GetHubDescriptor) + usb_hub_adjust_deviceremovable(hcd-self.root_hub, + (struct usb_hub_descriptor *)tbuf); break; error: /* protocol stall on error */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cfdd4ee..29ca6ed 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1513,6 +1513,8 @@ static int hub_configure(struct usb_hub *hub, dev_err(hub-intfdev, couldn't create port%d device.\n, i + 1); + usb_hub_adjust_deviceremovable(hdev, hub-descriptor); + hub_activate(hub, HUB_INIT); return 0; @@ -5219,6 +5221,47 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) return hub-ports[port1 - 1]-connect_type; } +void usb_hub_adjust_deviceremovable(struct usb_device *hdev, + struct usb_hub_descriptor *desc) +{ + enum usb_port_connect_type connect_type; + int i; + + if (!hub_is_superspeed(hdev)) { + for (i = 1; i = hdev-maxchild; i++) { + connect_type = usb_get_hub_port_connect_type(hdev, i); + + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u8 mask = 1 (i%8); + + if (!(desc-u.hs.DeviceRemovable[i/8] mask)) { + dev_dbg(hdev-dev, usb port%d's DeviceRemovable is changed to 1 according to platform information.\n, + i); + desc-u.hs.DeviceRemovable[i/8] |= mask; + } + } + } + } else { + u16 port_removable = le16_to_cpu(desc-u.ss.DeviceRemovable); + + for (i = 1; i = hdev-maxchild; i++) { + connect_type = usb_get_hub_port_connect_type(hdev, i); + + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u16 mask = 1 i; + + if (!(port_removable mask)) { + dev_dbg(hdev-dev, usb port%d's DeviceRemovable is changed to 1 according to platform information.\n, + i); + port_removable |= mask; + } + } + } + + desc-u.ss.DeviceRemovable = cpu_to_le16(port_removable); + } +} + #ifdef CONFIG_ACPI /** * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index fb7d8fc..a7f20bd 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -1,6 +1,7 @@ #include linux/pm.h #include linux/acpi.h +struct usb_hub_descriptor; struct dev_state; /* Functions local to drivers/usb/core/ */ @@ -182,6 +183,8 @@ extern enum usb_port_connect_type usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, enum usb_port_connect_type type); +extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, + struct usb_hub_descriptor *desc); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); -- 1.7.9.5 -- 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
[PATCH v6 2/8] usb: Register usb port's acpi power resources
This patch is to register usb port's acpi power resources. Create link between usb port device and its acpi power resource. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |3 +++ drivers/usb/core/usb-acpi.c | 20 drivers/usb/core/usb.h |6 ++ 3 files changed, 29 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index fe5959f..4dfa254 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -66,6 +66,7 @@ static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); + usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -95,6 +96,8 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) if (retval) goto error_register; + usb_acpi_register_power_resources(port_dev-dev); + return 0; error_register: diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252..558ab01 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -216,6 +216,26 @@ static struct acpi_bus_type usb_acpi_bus = { .find_device = usb_acpi_find_device, }; +int usb_acpi_register_power_resources(struct device *dev) +{ + acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + + if (!port_handle) + return -ENODEV; + + if (acpi_power_resource_register_device(dev, port_handle) 0) + return -ENODEV; + return 0; +} + +void usb_acpi_unregister_power_resources(struct device *dev) +{ + acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + + if (port_handle) + acpi_power_resource_unregister_device(dev, port_handle); +} + int usb_acpi_register(void) { return register_acpi_bus_type(usb_acpi_bus); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index a7f20bd..601b044 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -191,7 +191,13 @@ extern int usb_acpi_register(void); extern void usb_acpi_unregister(void); extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, int port1); +extern int usb_acpi_register_power_resources(struct device *dev); +extern void usb_acpi_unregister_power_resources(struct device *dev); #else static inline int usb_acpi_register(void) { return 0; }; static inline void usb_acpi_unregister(void) { }; +static inline int usb_acpi_register_power_resources(struct device *dev) + { return 0; }; +static inline void usb_acpi_unregister_power_resources(struct device *dev) + { }; #endif -- 1.7.9.5 -- 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
[PATCH v6 3/8] PM/Qos: Expose dev_pm_qos_flags symbol
The dev_pm_qos_flags() will be used in the usb core which could be compiled as a module. This patch is to export it. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/base/power/qos.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index d213495..3d4d1f8 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -91,6 +91,7 @@ enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask) return ret; } +EXPORT_SYMBOL_GPL(dev_pm_qos_flags); /** * __dev_pm_qos_read_value - Get PM QoS constraint for a given device. -- 1.7.9.5 -- 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
[PATCH v6 4/8] usb: add runtime pm support for usb port device
This patch is to add runtime pm callback for usb port device. Set/clear PORT_POWER feature in the resume/suspend callbak. Add portnum for struct usb_port to record port number. Do pm_rumtime_get_sync/put(portdev) when a device is plugged/unplugged to prevent it from being powered off when it is active. 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 | 18 ++ drivers/usb/core/hub.h |4 drivers/usb/core/port.c | 45 + 3 files changed, 67 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 29ca6ed..8c1f9a5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -714,6 +714,18 @@ static void hub_tt_work(struct work_struct *work) spin_unlock_irqrestore (hub-tt.lock, flags); } +int usb_hub_set_port_power(struct usb_device *hdev, int port1, + bool set) +{ + int ret; + + if (set) + ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + else + ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + return ret; +} + /** * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub * @urb: an URB associated with the failed or incomplete split transaction @@ -1569,6 +1581,7 @@ static void hub_disconnect(struct usb_interface *intf) kfree(hub-status); kfree(hub-buffer); + pm_suspend_ignore_children(intf-dev, false); kref_put(hub-kref, hub_release); } @@ -1671,6 +1684,7 @@ descriptor_error: usb_set_intfdata (intf, hub); intf-needs_remote_wakeup = 1; + pm_suspend_ignore_children(intf-dev, true); if (hdev-speed == USB_SPEED_HIGH) highspeed_hubs++; @@ -1997,6 +2011,8 @@ 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); } usb_remove_ep_devs(udev-ep0); @@ -2307,6 +2323,8 @@ int usb_new_device(struct usb_device *udev) sysfs_remove_link(udev-dev.kobj, port); goto fail; } + + pm_runtime_get_sync(port_dev-dev); } (void) usb_create_ep_devs(udev-dev, udev-ep0, udev); diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index d16a7c9..8ea6bc8 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -79,12 +79,14 @@ struct usb_hub { * @dev: generic device interface * @port_owner: port's owner * @connect_type: port's connect type + * @portnum: port index num based one */ struct usb_port { struct usb_device *child; struct device dev; struct dev_state *port_owner; enum usb_port_connect_type connect_type; + u8 portnum; }; #define to_usb_port(_dev) \ @@ -94,4 +96,6 @@ extern int usb_hub_create_port_device(struct usb_hub *hub, int port1); extern void usb_hub_remove_port_device(struct usb_hub *hub, int port1); +extern int usb_hub_set_port_power(struct usb_device *hdev, + int port1, bool set); diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 4dfa254..bd08f7e 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -17,6 +17,7 @@ */ #include linux/slab.h +#include linux/pm_qos.h #include hub.h @@ -70,9 +71,50 @@ static void usb_port_device_release(struct device *dev) kfree(port_dev); } +#ifdef CONFIG_USB_SUSPEND +static int usb_port_runtime_resume(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + struct usb_device *hdev = to_usb_device(dev-parent-parent); + struct usb_interface *intf = to_usb_interface(dev-parent); + int retval; + + usb_autopm_get_interface(intf); + retval = usb_hub_set_port_power(hdev, port_dev-portnum, true); + usb_autopm_put_interface(intf); + return retval; +} + +static int usb_port_runtime_suspend(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + struct usb_device *hdev = to_usb_device(dev-parent-parent); + struct usb_interface *intf = to_usb_interface(dev-parent); + int retval; + + if (dev_pm_qos_flags(port_dev-dev, PM_QOS_FLAG_NO_POWER_OFF) + == PM_QOS_FLAGS_ALL) + return -EAGAIN; + + usb_autopm_get_interface(intf); + retval = usb_hub_set_port_power(hdev, port_dev-portnum, false); + usb_autopm_put_interface(intf); + return retval; +} +#endif + +static const struct dev_pm_ops usb_port_pm_ops = { +#ifdef CONFIG_USB_SUSPEND + .runtime_suspend = usb_port_runtime_suspend, + .runtime_resume = usb_port_runtime_resume, + .runtime_idle
[PATCH v6 6/8] usb: expose usb port's pm qos flags to user space
This patch is to expose usb port's pm qos flags(pm_qos_no_power_off, pm_qos_remote_wakeup) to user space. User can set pm_qos_no_power_off flag to prohibit the port from being powered off. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index dc1aaec..0c51d24 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -67,6 +67,7 @@ static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); + dev_pm_qos_hide_flags(dev); usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -176,7 +177,15 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) goto error_register; pm_runtime_set_active(port_dev-dev); - pm_runtime_enable(port_dev-dev); + + /* It would be dangerous if user space couldn't +* prevent usb device from being powered off. So don't +* enable port runtime pm if failed to expose port's pm qos. +*/ + if (!dev_pm_qos_expose_flags(port_dev-dev, + PM_QOS_FLAG_NO_POWER_OFF)) + pm_runtime_enable(port_dev-dev); + usb_acpi_register_power_resources(port_dev-dev); return 0; -- 1.7.9.5 -- 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
[PATCH v6 8/8] usb: enable usb port device's async suspend.
Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 0334d91..50b646e 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -215,7 +215,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) pm_runtime_enable(port_dev-dev); usb_acpi_register_power_resources(port_dev-dev); - + device_enable_async_suspend(port_dev-dev); return 0; error_register: -- 1.7.9.5 -- 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 2/8] usb: Register usb port's acpi power resources
Hi Greg: Great thanks for your review. I learn a lot from your comments which I have not noticed before. On 2013年01月22日 05:20, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:01PM +0800, Lan Tianyu wrote: This patch is to register usb port's acpi power resources. Create link between usb port device and its acpi power resource. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |3 +++ drivers/usb/core/usb-acpi.c | 20 drivers/usb/core/usb.h |6 ++ 3 files changed, 29 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index fe5959f..4dfa254 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -66,6 +66,7 @@ static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); +usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -95,6 +96,8 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) if (retval) goto error_register; +usb_acpi_register_power_resources(port_dev-dev); + return 0; error_register: diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252..558ab01 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -216,6 +216,26 @@ static struct acpi_bus_type usb_acpi_bus = { .find_device = usb_acpi_find_device, }; +int usb_acpi_register_power_resources(struct device *dev) +{ +acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + +if (!port_handle) +return -ENODEV; + +if (acpi_power_resource_register_device(dev, port_handle) 0) +return -ENODEV; +return 0; +} Why return a value if you never check it? Either properly handle the error in the place you call this function, or don't have a return value. I'd prefer you to handle the error properly. Not all system will provide acpi power resouces for usb port and this will not damage usb device function. So I think I should produce some warning if the return value is not ENODEV. thanks, greg k-h -- Best regards Tianyu Lan -- 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 4/8] usb: add runtime pm support for usb port device
On 2013年01月22日 05:24, Greg KH wrote: On Mon, Jan 21, 2013 at 10:18:03PM +0800, Lan Tianyu wrote: This patch is to add runtime pm callback for usb port device. Set/clear PORT_POWER feature in the resume/suspend callbak. Add portnum for struct usb_port to record port number. Do pm_rumtime_get_sync/put(portdev) when a device is plugged/unplugged to prevent it from being powered off when it is active. 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 | 18 ++ drivers/usb/core/hub.h |4 drivers/usb/core/port.c | 45 + 3 files changed, 67 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 29ca6ed..8c1f9a5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -714,6 +714,18 @@ static void hub_tt_work(struct work_struct *work) spin_unlock_irqrestore (hub-tt.lock, flags); } +int usb_hub_set_port_power(struct usb_device *hdev, int port1, +bool set) As this is a new global USB function, please provide the proper kerneldoc comments describing what it does. OK. I will add later and actually the function will be only used in the driver/usb/core/hub.c and port.c. thanks, greg k-h -- Best regards Tianyu Lan -- 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 V5 0/10] usb: usb port power off mechanism and expose usb port connect type
2013/1/21 Greg KH gre...@linuxfoundation.org On Sun, Jan 20, 2013 at 01:53:29AM +0800, Lan Tianyu wrote: Change since v5: use EXPORT_SYMBOL_GPL to export dev_pm_qos_flags(). correct some unnecessary link breaks. Add CONFIG_USB_SUSPEND check around usb_port_runtime_resume() and usb_port_runtime_suspend() I've applied a few of these, care to redo the series based on the feedback for the .h file issue? Ok. I wll update soon. 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 -- Best regards Tianyu Lan -- 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
[PATCH] usb: fix compilation error and warning of driver/usb/core/port.c on arm and blackfin
This patch is to fix compilation error and warning on the arm and blackfin. Add linux/slab.h head file to driver/usb/core/port.c. These are reported from 0-DAY kernel build testing backend. head: 6e30d7cba992d626c9d16b3873a7b90c700d0e95 commit: 6e30d7cba992d626c9d16b3873a7b90c700d0e95 [26/26] usb: Add driver/usb/core/(port.c,hub.h) files config: make ARCH=arm at91_dt_defconfig All error/warnings: drivers/usb/core/port.c: In function 'usb_port_device_release': drivers/usb/core/port.c:25:2: error: implicit declaration of function 'kfree' [-Werror=implicit-function-declaration] drivers/usb/core/port.c: In function 'usb_hub_create_port_device': drivers/usb/core/port.c:38:2: error: implicit declaration of function 'kzalloc' [-Werror=implicit-function-declaration] drivers/usb/core/port.c:38:40: error: 'GFP_KERNEL' undeclared (first use in this function) drivers/usb/core/port.c:38:40: note: each undeclared identifier is reported only once for each function it appears in cc1: some warnings being treated as errors head: 6e30d7cba992d626c9d16b3873a7b90c700d0e95 commit: 6e30d7cba992d626c9d16b3873a7b90c700d0e95 [26/26] usb: Add driver/usb/core/(port.c,hub.h) files config: make ARCH=blackfin BF526-EZBRD_defconfig All warnings: drivers/usb/core/port.c: In function 'usb_port_device_release': drivers/usb/core/port.c:25:2: error: implicit declaration of function 'kfree' [-Werror=implicit-function-declaration] drivers/usb/core/port.c: In function 'usb_hub_create_port_device': drivers/usb/core/port.c:38:2: error: implicit declaration of function 'kzalloc' [-Werror=implicit-function-declaration] drivers/usb/core/port.c:38:11: warning: assignment makes pointer from integer without a cast [enabled by default] cc1: some warnings being treated as errors Reported-by: Fengguang Wu w...@linux.intel.com Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 2bc1cef..3734850 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -16,6 +16,8 @@ * */ +#include linux/slab.h + #include hub.h static void usb_port_device_release(struct device *dev) -- 1.7.9.5 -- 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
[PATCH V5 0/10] usb: usb port power off mechanism and expose usb port connect type
Change since v1: optimize the export connect type patch and adjust the DeviceRemovalbe flag in the rh_call_control() after GetHubDescriptor request being processed. move all debounce operation to usb port's runtime resume callback(). Add did_runtime_put in the struct usb_port to call pm_runtime_get/put(portdev) paired. using pm_runtime_get/put(portdev) to allow or prohibit device to be power off inside of pm qos request in the kernel side. Change since v2: Correct some link breaks. Add did_runtime_put in the usb_disconnect() before calling pm_runtime_put(portdev). Provide two seperate functions usb_device_allow_power_off() and usb_device_prevent_power_off() instead of just one. Change since v3: Set did_runtime_put to false in usb_disconnect() when its value is true Add comment about not enable port runtime pm if fail to expose port's pm qos. and call pm_runtime_set_active(portdev) unconditionally. rename usb_device_allow_prevent_power_off with usb_device_control_power_off Modify be power off to be powered off Expose dev_pm_qos_flags() symbol in order to ensure usb core can compile as module. Resend v4: make patch PM/Qos: Expose dev_pm_qos_flags symbol as first patch to avoid compilation error during git bisect correct some comments. Change since v5: use EXPORT_SYMBOL_GPL to export dev_pm_qos_flags(). correct some unnecessary link breaks. Add CONFIG_USB_SUSPEND check around usb_port_runtime_resume() and usb_port_runtime_suspend() This patchset is based on usb-next tree commit 6e30d7cba usb: Add driver/usb/core/(port.c,hub.h) files and the patch usb: fix compilation error and warning of driver/usb/core/port.c on arm and blackfin http://marc.info/?l=linux-usbm=135860593115173w=2 This patchset is to add usb port power off mechanism and merge with patchset usb: expose DeviceRemovable to user space via sysfs attribute. Patchset usb: expose DeviceRemovable to user space via sysfs attribute. http://marc.info/?l=linux-usbm=135279430410171w=2 with some link break corrects The main discussion about usb port power off mechanism is in the following link: http://marc.info/?l=linux-usbm=134818340017208w=2 PM/Qos: Expose dev_pm_qos_flags symbol USB: Set usb port's DeviceRemovable according acpi information usb: Add portX/connect_type attribute to expose usb port's connect type usb: Create link files between child device and usb port device. usb: Register usb port's acpi power resources usb: add runtime pm support for usb port device usb: add usb port auto power off mechanism usb: expose usb port's pm qos flags to user space usb: add usb_device_allow_power_off() and usb_device_prevent_power_off() function. usb: enable usb port device's async suspend. -- 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
[PATCH v5 01/10] PM/Qos: Expose dev_pm_qos_flags symbol
The dev_pm_qos_flags() will be used in the usb core which could be compiled as a module. This patch is to export it. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/base/power/qos.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index d213495..3d4d1f8 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -91,6 +91,7 @@ enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask) return ret; } +EXPORT_SYMBOL_GPL(dev_pm_qos_flags); /** * __dev_pm_qos_read_value - Get PM QoS constraint for a given device. -- 1.7.9.5 -- 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
[PATCH v5 02/10] USB: Set usb port's DeviceRemovable according acpi information
ACPI provide _PLD and _UPC aml methods to describe usb port visibility and connectability. This patch is to add usb_hub_adjust_DeviceRemovable() to adjust usb hub port's DeviceRemovable according ACPI information and invoke it in the rh_call_control(). When hub descriptor request is issued at first time, usb port device isn't created and usb port is not bound with acpi. So first hub descriptor request is not changed based on ACPI information. After usb port devices being created, call usb_hub_adjust_DeviceRemovable in the hub_configure() and then set hub port's DeviceRemovable according ACPI information and this also works for non-root hub. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hcd.c |4 drivers/usb/core/hub.c | 43 +++ drivers/usb/core/usb.h |3 +++ 3 files changed, 50 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5f6da8b..2459896 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -619,6 +619,10 @@ nongeneric: status = hcd-driver-hub_control (hcd, typeReq, wValue, wIndex, tbuf, wLength); + + if (typeReq == GetHubDescriptor) + usb_hub_adjust_deviceremovable(hcd-self.root_hub, + (struct usb_hub_descriptor *)tbuf); break; error: /* protocol stall on error */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f6ff130..f7e1402 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1513,6 +1513,8 @@ static int hub_configure(struct usb_hub *hub, dev_err(hub-intfdev, couldn't create port%d device.\n, i + 1); + usb_hub_adjust_deviceremovable(hdev, hub-descriptor); + hub_activate(hub, HUB_INIT); return 0; @@ -5193,6 +5195,47 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) return hub-ports[port1 - 1]-connect_type; } +void usb_hub_adjust_deviceremovable(struct usb_device *hdev, + struct usb_hub_descriptor *desc) +{ + enum usb_port_connect_type connect_type; + int i; + + if (!hub_is_superspeed(hdev)) { + for (i = 1; i = hdev-maxchild; i++) { + connect_type = usb_get_hub_port_connect_type(hdev, i); + + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u8 mask = 1 (i%8); + + if (!(desc-u.hs.DeviceRemovable[i/8] mask)) { + dev_dbg(hdev-dev, usb port%d's DeviceRemovable is changed to 1 according to platform information.\n, + i); + desc-u.hs.DeviceRemovable[i/8] |= mask; + } + } + } + } else { + u16 port_removable = le16_to_cpu(desc-u.ss.DeviceRemovable); + + for (i = 1; i = hdev-maxchild; i++) { + connect_type = usb_get_hub_port_connect_type(hdev, i); + + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u16 mask = 1 i; + + if (!(port_removable mask)) { + dev_dbg(hdev-dev, usb port%d's DeviceRemovable is changed to 1 according to platform information.\n, + i); + port_removable |= mask; + } + } + } + + desc-u.ss.DeviceRemovable = cpu_to_le16(port_removable); + } +} + #ifdef CONFIG_ACPI /** * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index fb7d8fc..31f32cd 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -1,5 +1,6 @@ #include linux/pm.h #include linux/acpi.h +#include linux/usb/ch11.h struct dev_state; @@ -182,6 +183,8 @@ extern enum usb_port_connect_type usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, enum usb_port_connect_type type); +extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, + struct usb_hub_descriptor *desc); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); -- 1.7.9.5 -- 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
[PATCH v5 03/10] usb: Add portX/connect_type attribute to expose usb port's connect type
Some platforms provide usb port connect types through ACPI. This patch is to add this new attribute to expose these information to user space. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- Documentation/ABI/testing/sysfs-bus-usb |9 +++ drivers/usb/core/port.c | 43 +++ 2 files changed, 52 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index b6fbe51..c8baaf5 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -227,3 +227,12 @@ Contact: Lan Tianyu tianyu@intel.com Description: The /sys/bus/usb/devices/.../(hub interface)/portX is usb port device's sysfs directory. + +What: /sys/bus/usb/devices/.../(hub interface)/portX/connect_type +Date: January 2013 +Contact: Lan Tianyu tianyu@intel.com +Description: + Some platforms provide usb port connect types through ACPI. + This attribute is to expose these information to user space. + The file will read hotplug, wired and not used if the + information is available, and unknown otherwise. diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 3734850..fe5959f 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -20,6 +20,48 @@ #include hub.h +static const struct attribute_group *port_dev_group[]; + +static ssize_t show_port_connect_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_port *port_dev = to_usb_port(dev); + char *result; + + switch (port_dev-connect_type) { + case USB_PORT_CONNECT_TYPE_HOT_PLUG: + result = hotplug; + break; + case USB_PORT_CONNECT_TYPE_HARD_WIRED: + result = hardwired; + break; + case USB_PORT_NOT_USED: + result = not used; + break; + default: + result = unknown; + break; + } + + return sprintf(buf, %s\n, result); +} +static DEVICE_ATTR(connect_type, S_IRUGO, show_port_connect_type, + NULL); + +static struct attribute *port_dev_attrs[] = { + dev_attr_connect_type.attr, + NULL, +}; + +static struct attribute_group port_dev_attr_grp = { + .attrs = port_dev_attrs, +}; + +static const struct attribute_group *port_dev_group[] = { + port_dev_attr_grp, + NULL, +}; + static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); @@ -45,6 +87,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) hub-ports[port1 - 1] = port_dev; port_dev-dev.parent = hub-intfdev; + port_dev-dev.groups = port_dev_group; port_dev-dev.type = usb_port_device_type; dev_set_name(port_dev-dev, port%d, port1); -- 1.7.9.5 -- 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
[PATCH v5 04/10] usb: Create link files between child device and usb port device.
To show the relationship between usb port and child device, add link file port under usb device's sysfs directoy and device under usb port device's sysfs directory. They are linked to each other. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f7e1402..29ca6ed 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1991,6 +1991,14 @@ void usb_disconnect(struct usb_device **pdev) usb_disable_device(udev, 0); usb_hcd_synchronize_unlinks(udev); + if (udev-parent) { + struct usb_port *port_dev = + hdev_to_hub(udev-parent)-ports[udev-portnum - 1]; + + sysfs_remove_link(udev-dev.kobj, port); + sysfs_remove_link(port_dev-dev.kobj, device); + } + usb_remove_ep_devs(udev-ep0); usb_unlock_device(udev); @@ -2283,6 +2291,24 @@ int usb_new_device(struct usb_device *udev) goto fail; } + /* Create link files between child device and usb port device. */ + if (udev-parent) { + struct usb_port *port_dev = + hdev_to_hub(udev-parent)-ports[udev-portnum - 1]; + + err = sysfs_create_link(udev-dev.kobj, + port_dev-dev.kobj, port); + if (err) + goto fail; + + err = sysfs_create_link(port_dev-dev.kobj, + udev-dev.kobj, device); + if (err) { + sysfs_remove_link(udev-dev.kobj, port); + goto fail; + } + } + (void) usb_create_ep_devs(udev-dev, udev-ep0, udev); usb_mark_last_busy(udev); pm_runtime_put_sync_autosuspend(udev-dev); -- 1.7.9.5 -- 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
[PATCH v5 05/10] usb: Register usb port's acpi power resources
This patch is to register usb port's acpi power resources. Create link between usb port device and its acpi power resource. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |3 +++ drivers/usb/core/usb-acpi.c | 20 drivers/usb/core/usb.h |6 ++ 3 files changed, 29 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index fe5959f..4dfa254 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -66,6 +66,7 @@ static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); + usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -95,6 +96,8 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) if (retval) goto error_register; + usb_acpi_register_power_resources(port_dev-dev); + return 0; error_register: diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252..558ab01 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -216,6 +216,26 @@ static struct acpi_bus_type usb_acpi_bus = { .find_device = usb_acpi_find_device, }; +int usb_acpi_register_power_resources(struct device *dev) +{ + acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + + if (!port_handle) + return -ENODEV; + + if (acpi_power_resource_register_device(dev, port_handle) 0) + return -ENODEV; + return 0; +} + +void usb_acpi_unregister_power_resources(struct device *dev) +{ + acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + + if (port_handle) + acpi_power_resource_unregister_device(dev, port_handle); +} + int usb_acpi_register(void) { return register_acpi_bus_type(usb_acpi_bus); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 31f32cd..bf524e4 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -191,7 +191,13 @@ extern int usb_acpi_register(void); extern void usb_acpi_unregister(void); extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, int port1); +extern int usb_acpi_register_power_resources(struct device *dev); +extern void usb_acpi_unregister_power_resources(struct device *dev); #else static inline int usb_acpi_register(void) { return 0; }; static inline void usb_acpi_unregister(void) { }; +static inline int usb_acpi_register_power_resources(struct device *udev) + { return 0; }; +static inline void usb_acpi_unregister_power_resources(struct device *udev) + { }; #endif -- 1.7.9.5 -- 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
[PATCH v5 07/10] usb: add usb port auto power off mechanism
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. 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 #define HUB_DEBOUNCE_STEP25 #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) { 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) { 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 (!port_dev-did_runtime_put) + pm_runtime_put(port_dev-dev); + else + port_dev-did_runtime_put = false; } usb_remove_ep_devs(udev-ep0); @@ -2844,6 +2863,8 @@ EXPORT_SYMBOL_GPL(usb_enable_ltm); int usb_port_suspend(struct usb_device *udev, pm_message_t msg) { struct usb_hub *hub = hdev_to_hub(udev-parent); + struct usb_port *port_dev = hub-ports
[PATCH v5 08/10] usb: expose usb port's pm qos flags to user space
This patch is to expose usb port's pm qos flags(pm_qos_no_power_off, pm_qos_remote_wakeup) to user space. User can set pm_qos_no_power_off flag to prohibit the port from being powered off. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index dc1aaec..0c51d24 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -67,6 +67,7 @@ static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); + dev_pm_qos_hide_flags(dev); usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -176,7 +177,15 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) goto error_register; pm_runtime_set_active(port_dev-dev); - pm_runtime_enable(port_dev-dev); + + /* It would be dangerous if user space couldn't +* prevent usb device from being powered off. So don't +* enable port runtime pm if failed to expose port's pm qos. +*/ + if (!dev_pm_qos_expose_flags(port_dev-dev, + PM_QOS_FLAG_NO_POWER_OFF)) + pm_runtime_enable(port_dev-dev); + usb_acpi_register_power_resources(port_dev-dev); return 0; -- 1.7.9.5 -- 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
[PATCH v5 09/10] usb: add usb_device_allow_power_off() and usb_device_prevent_power_off() function.
Some usb devices can't be resumed correctly after power off. This patch is to add usb_device_allow_power_off() and usb_device_prevent_power_off() for device's driver. Call pm_runtime_get_sync(portdev) to increase port's usage count and then port will not be suspended. The device will not be powered off. Acked-by: Alan Stern st...@rowland.harvard.edu Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 0c51d24..0334d91 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -18,11 +18,39 @@ #include linux/slab.h #include linux/pm_qos.h +#include linux/module.h #include hub.h static const struct attribute_group *port_dev_group[]; +/** + * usb_device_control_power_off - Allow or prohibit power off device. + * @udev: target usb device + * @allow: choice of allow or prohibit + * + * Call pm_runtime_get/put_sync(portdev) to allow or prohibit target + * usb device to be powered off in the kernel. The operations of setting + * true and false should be couple. The default status is allowed. + */ +int usb_device_control_power_off(struct usb_device *udev, bool allow) +{ + struct usb_port *port_dev; + + if (!udev-parent) + return -EINVAL; + + port_dev = hdev_to_hub(udev-parent)-ports[udev-portnum - 1]; + + if (allow) + pm_runtime_put_sync(port_dev-dev); + else + pm_runtime_get_sync(port_dev-dev); + + return 0; +} +EXPORT_SYMBOL_GPL(usb_device_control_power_off); + static ssize_t show_port_connect_type(struct device *dev, struct device_attribute *attr, char *buf) { -- 1.7.9.5 -- 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
[PATCH v5 10/10] usb: enable usb port device's async suspend.
Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 0334d91..50b646e 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -215,7 +215,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) pm_runtime_enable(port_dev-dev); usb_acpi_register_power_resources(port_dev-dev); - + device_enable_async_suspend(port_dev-dev); return 0; error_register: -- 1.7.9.5 -- 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: [Resend PATCH V4 0/10] usb: usb port power off mechanism anc expose usb port connect type
On 2013年01月16日 23:45, Alan Stern wrote: On Tue, 15 Jan 2013, Lan Tianyu wrote: Hi GregAlan: Do you have some more comments about this patchset? Thanks. I don't have any more comments at this point. It looks okay to me. Acked-by: Alan Stern st...@rowland.harvard.edu By the way, have you checked whether the auto-power-off mechanism works correctly when you do a system suspend? Thanks for reminder. I test this today and find an issue. If usb device was powered off during runtime, pm_runtime_get_sync() in the usb_port_resume() will return -EACCES when do system resume. This is because port's runtime pm was disabled during system suspend. Following are some log. The device's runtime pm will be enabled after system suspend. The port device is advance to be inserted in the dpm_list than usb device(port device is created before creating usb device). So the resume sequence is that resume usb device firstly and then usb port. In the result, pm_runtime_get_sync() doesn't work. [ 70.448028] power LNXPOWER:03: driver resume [ 70.448029] usb usb4: runtime enable [ 70.448031] usb 3-1: can't resume usb port, status -13 [ 70.448032] usb usb4: type resume [ 70.448039] dpm_run_callback(): usb_dev_resume+0x0/0x15 returns -13 [ 70.448040] usb usb4: usb resume [ 70.448041] usb 3-2: can't resume usb port, status -13 [ 70.448043] PM: Device 3-1 failed to resume async: error -13 [ 70.448047] dpm_run_callback(): usb_dev_resume+0x0/0x15 returns -13 [ 70.448048] PM: Device 3-2 failed to resume async: error -13 [ 70.448056] hub 4-0:1.0: hub_resume [ 70.448088] acpi device:49: runtime enable I found one solution of adding pm_runtime_enable/disable() in the usb_port_resume(). This is simple sovlution. if (port_dev-did_runtime_put) { if (!PMSG_IS_AUTO(msg)) { pm_runtime_enable(port_dev-dev); status = pm_runtime_get_sync(port_dev-dev); pm_runtime_disable(port_dev-dev); } else status = pm_runtime_get_sync(port_dev-dev); port_dev-did_runtime_put = false; if (status 0) { dev_dbg(udev-dev, can't resume usb port, status %d\n, status); return status; } } This can work but I am not sure that it is safe to do system resume() in the system resume(). Another proposal is to export usb_port_runtime_resume() or do a wrapper. Call it in the usb_port_resume() with pm_runtime_get_noresume() and pm_runtime_set_active(). This also work. if (port_dev-did_runtime_put) { if (!PMSG_IS_AUTO(msg)) { status = usb_port_runtime_resume(port_dev-dev); pm_runtime_get_noresume(port_dev-dev); pm_runtime_set_active(udev-dev); } else status = pm_runtime_get_sync(port_dev-dev); port_dev-did_runtime_put = false; if (status 0) { dev_dbg(udev-dev, can't resume usb port, status %d\n, status); return status; } } Alan Stern -- Best regards Tianyu Lan -- 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
[Rebase PATCH] usb: Using correct way to clear usb3.0 device's remote wakeup feature.
Usb3.0 device defines function remote wakeup which is only for interface recipient rather than device recipient. This is different with usb2.0 device's remote wakeup feature which is defined for device recipient. According usb3.0 spec 9.4.5, the function remote wakeup can be modified by the SetFeature() requests using the FUNCTION_SUSPEND feature selector. This patch is to use correct way to disable usb3.0 device's function remote wakeup after suspend error and resuming. Signed-off-by: Lan Tianyu tianyu@intel.com --- This patch is rebased on the usb-linus branch commit 1ee0a224bc9aa USB: io_ti: Fix NULL dereference in chase_port() --- drivers/usb/core/hub.c | 71 +++--- include/uapi/linux/usb/ch9.h |6 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 957ed2c..d1753d6 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2837,6 +2837,24 @@ void usb_enable_ltm(struct usb_device *udev) } EXPORT_SYMBOL_GPL(usb_enable_ltm); +/* + * usb_disable_function_remotewakeup - disable usb3.0 + * device's function remote wakeup + * @udev: target device + * + * Assume there's only one function on the USB 3.0 + * device and disable remote wake for the first + * interface. FIXME if the interface association + * descriptor shows there's more than one function. + */ +static int usb_disable_function_remotewakeup(struct usb_device *udev) +{ + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} + #ifdef CONFIG_USB_SUSPEND /* @@ -2955,12 +2973,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) dev_dbg(hub-intfdev, can't suspend port %d, status %d\n, port1, status); /* paranoia: should not happen */ - if (udev-do_remote_wakeup) - (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + if (udev-do_remote_wakeup) { + if (!hub_is_superspeed(hub-hdev)) { + (void) usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else + (void) usb_disable_function_remotewakeup(udev); + + } /* Try to enable USB2 hardware LPM again */ if (udev-usb2_hw_lpm_capable == 1) @@ -3052,20 +3077,30 @@ static int finish_port_resume(struct usb_device *udev) * udev-reset_resume */ } else if (udev-actconfig !udev-reset_resume) { - le16_to_cpus(devstatus); - if (devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) { - status = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, + if (!hub_is_superspeed(udev-parent)) { + le16_to_cpus(devstatus); + if (devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - if (status) - dev_dbg(udev-dev, - disable remote wakeup, status %d\n, - status); + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + devstatus); + le16_to_cpus(devstatus); + if (!status devstatus
[PATCH v2 1/3] usb: add find_raw_port_number callback to struct hc_driver()
xhci driver divides the root hub into two logical hubs which work respectively for usb 2.0 and usb 3.0 devices. They are independent devices in the usb core. But in the ACPI table, it's one device node and all usb2.0 and usb3.0 ports are under it. Binding usb port with its acpi node needs the raw port number which is reflected in the xhci extended capabilities table. This patch is to add find_raw_port_number callback to struct hc_driver() and fill it with xhci_find_raw_port_number(). Signed-off-by: Lan Tianyu tianyu@intel.com --- Change since v1: Don't export usb_hcd_find_raw_port_number() symbol since there is no its user outside of usb core. This patchset is rebased on the usb-next tree commit 74ff31b81d9 usb: misc: usb3503_probe() can be static --- drivers/usb/core/hcd.c |8 drivers/usb/host/xhci-pci.c |1 + drivers/usb/host/xhci.c | 22 ++ drivers/usb/host/xhci.h |1 + include/linux/usb/hcd.h |2 ++ 5 files changed, 34 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5f6da8b..0277bd2 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2364,6 +2364,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd) } EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd); +int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ + if (!hcd-driver-find_raw_port_number) + return port1; + + return hcd-driver-find_raw_port_number(hcd, port1); +} + static int usb_hcd_request_irqs(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags) { diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index af259e0..1a30c38 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = { .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, + .find_raw_port_number = xhci_find_raw_port_number, }; /*-*/ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f1f01a8..0780d8f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3778,6 +3778,28 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) return 0; } +/* + * Transfer the port index into real index in the HW port status + * registers. Caculate offset between the port's PORTSC register + * and port status base. Divide the number of per port register + * to get the real index. The raw port number bases 1. + */ +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + __le32 __iomem *base_addr = xhci-op_regs-port_status_base; + __le32 __iomem *addr; + int raw_port; + + if (hcd-speed != HCD_USB3) + addr = xhci-usb2_ports[port1 - 1]; + else + addr = xhci-usb3_ports[port1 - 1]; + + raw_port = (addr - base_addr)/NUM_PORT_REGS + 1; + return raw_port; +} + #ifdef CONFIG_USB_SUSPEND /* BESL to HIRD Encoding array for USB2 LPM */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f791bd0..55345d9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1829,6 +1829,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); #ifdef CONFIG_PM int xhci_bus_suspend(struct usb_hcd *hcd); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 608050b..61b88b5 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -357,6 +357,7 @@ struct hc_driver { */ int (*disable_usb3_lpm_timeout)(struct usb_hcd *, struct usb_device *, enum usb3_link_state state); + int (*find_raw_port_number)(struct usb_hcd *, int); }; extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); @@ -396,6 +397,7 @@ extern int usb_hcd_is_primary_hcd(struct usb_hcd *hcd); extern int usb_add_hcd(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags); extern void usb_remove_hcd(struct usb_hcd *hcd); +extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1); struct platform_device; extern void usb_hcd_platform_shutdown(struct platform_device *dev); -- 1.7.10.4 -- 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
[PATCH v2 2/3] usb/acpi: binding xhci root hub usb port with ACPI
This patch is to bind xhci root hub usb port with its acpi node. The port num in the acpi table matches with the sequence in the xhci extended capabilities table. So call usb_hcd_find_raw_port_number() to transfer hub port num into raw port number which associates with the sequence in the xhci extended capabilities table before binding. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/usb-acpi.c |4 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252..40f5a6a 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -15,6 +15,7 @@ #include linux/kernel.h #include linux/acpi.h #include linux/pci.h +#include linux/usb/hcd.h #include acpi/acpi_bus.h #include usb.h @@ -188,6 +189,9 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) * connected to. */ if (!udev-parent) { + struct usb_hcd *hcd = bus_to_hcd(udev-bus); + + port_num = usb_hcd_find_raw_port_number(hcd, port_num); *handle = acpi_get_child(DEVICE_ACPI_HANDLE(udev-dev), port_num); if (!*handle) -- 1.7.10.4 -- 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
[PATCH v2 3/3] usb/xhci: refactor xhci_find_real_port_number()
This patch is to optimize xhci_find_realport_number(). Call xhci_find_raw_port_number() to get real index in the HW port status registers instead of scanning through the xHCI roothub port array. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/host/xhci-mem.c | 36 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 35616ff..6dc238c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, * is attached to (or the roothub port its ancestor hub is attached to). All we * know is the index of that port under either the USB 2.0 or the USB 3.0 * roothub, but that doesn't give us the real index into the HW port status - * registers. Scan through the xHCI roothub port array, looking for the Nth - * entry of the correct port speed. Return the port number of that entry. + * registers. Call xhci_find_raw_port_number() to get real index. */ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, struct usb_device *udev) { struct usb_device *top_dev; - unsigned int num_similar_speed_ports; - unsigned int faked_port_num; - int i; + struct usb_hcd *hcd; + + if (udev-speed == USB_SPEED_SUPER) + hcd = xhci-shared_hcd; + else + hcd = xhci-main_hcd; for (top_dev = udev; top_dev-parent top_dev-parent-parent; top_dev = top_dev-parent) /* Found device below root hub */; - faked_port_num = top_dev-portnum; - for (i = 0, num_similar_speed_ports = 0; - i HCS_MAX_PORTS(xhci-hcs_params1); i++) { - u8 port_speed = xhci-port_array[i]; - - /* -* Skip ports that don't have known speeds, or have duplicate -* Extended Capabilities port speed entries. -*/ - if (port_speed == 0 || port_speed == DUPLICATE_ENTRY) - continue; - /* -* USB 3.0 ports are always under a USB 3.0 hub. USB 2.0 and -* 1.1 ports are under the USB 2.0 hub. If the port speed -* matches the device speed, it's a similar speed port. -*/ - if ((port_speed == 0x03) == (udev-speed == USB_SPEED_SUPER)) - num_similar_speed_ports++; - if (num_similar_speed_ports == faked_port_num) - /* Roothub ports are numbered from 1 to N */ - return i+1; - } - return 0; + return xhci_find_raw_port_number(hcd, top_dev-portnum); } /* Setup an xHCI virtual device for a Set Address command */ -- 1.7.10.4 -- 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: [Resend PATCH V4 0/10] usb: usb port power off mechanism anc expose usb port connect type
HI Alan: I just find Rafael's patch has resolved this issue. In this patch, enable runtime PM right after executing subsystem/driver .resume_early() callbacks. When do resume(), the device's runtime pm has been enabled. This patch now is already in the v3.8-rc4. So this patchset will not cause problem with Rafael patch and I have tested. About the port system suspend/resume() callback, Could I do this in the next step? commit a8d3848dadc2fd41a9117cb08dc04fe6d7c551f9 Author: Rafael J. Wysocki rafael.j.wyso...@intel.com Date: Sat Dec 22 23:59:01 2012 +0100 PM: Move disabling/enabling runtime PM to late suspend/early resume Currently, the PM core disables runtime PM for all devices right after executing subsystem/driver .suspend() callbacks for them and re-enables it right before executing subsystem/driver .resume() callbacks for them. This may lead to problems when there are two devices such that the .suspend() callback executed for one of them depends on runtime PM working for the other. In that case, if runtime PM has already been disabled for the second device, the first one's .suspend() won't work correctly (and analogously for resume). To make those issues go away, make the PM core disable runtime PM for devices right before executing subsystem/driver .suspend_late() callbacks for them and enable runtime PM for them right after executing subsystem/driver .resume_early() callbacks for them. This way the potential conflitcs between .suspend_late()/.resume_early() and their runtime PM counterparts are still prevented from happening, but the subtle ordering issues related to disabling/enabling runtime PM for devices during system suspend/resume are much easier to avoid. Best Regards Tianyu Lan -Original Message- From: Alan Stern [mailto:st...@rowland.harvard.edu] Sent: Saturday, January 19, 2013 12:21 AM To: Lan, Tianyu Cc: r...@sisk.pl; gre...@linuxfoundation.org; sarah.a.sh...@linux.intel.com; oneu...@suse.de; linux-usb@vger.kernel.org Subject: Re: [Resend PATCH V4 0/10] usb: usb port power off mechanism anc expose usb port connect type On Fri, 18 Jan 2013, Lan Tianyu wrote: By the way, have you checked whether the auto-power-off mechanism works correctly when you do a system suspend? Thanks for reminder. I test this today and find an issue. If usb device was powered off during runtime, pm_runtime_get_sync() in the usb_port_resume() will return -EACCES when do system resume. This is because port's runtime pm was disabled during system suspend. Actually it's worse than that. The PM layer assumes that devices are brought back to full power during system resume. But that's not true for your usb_port devices, because they don't have a resume callback. In addition, we need to enable async PM for the usb_ports, just like everything else in the USB stack. This means you have to call device_enable_async_suspend before the port is registered. Following are some log. The device's runtime pm will be enabled after system suspend. The port device is advance to be inserted in the dpm_list than usb device(port device is created before creating usb device). So the resume sequence is that resume usb device firstly and then usb port. In the result, pm_runtime_get_sync() doesn't work. When async is enabled, there won't be any defined ordering. We will have to enforce the proper ordering by hand. This means usb_resume_device will have to call device_pm_wait_for_dev for the port device (it already does this for the companion root hub). In fact, the code to do this waiting probably should be moved to usb_resume, because it applies only to system resume, not to runtime resume. [ 70.448028] power LNXPOWER:03: driver resume [ 70.448029] usb usb4: runtime enable [ 70.448031] usb 3-1: can't resume usb port, status -13 [ 70.448032] usb usb4: type resume [ 70.448039] dpm_run_callback(): usb_dev_resume+0x0/0x15 returns -13 [ 70.448040] usb usb4: usb resume [ 70.448041] usb 3-2: can't resume usb port, status -13 [ 70.448043] PM: Device 3-1 failed to resume async: error -13 [ 70.448047] dpm_run_callback(): usb_dev_resume+0x0/0x15 returns -13 [ 70.448048] PM: Device 3-2 failed to resume async: error -13 [ 70.448056] hub 4-0:1.0: hub_resume [ 70.448088] acpi device:49: runtime enable I found one solution of adding pm_runtime_enable/disable() in the usb_port_resume(). This is simple sovlution. if (port_dev-did_runtime_put) { if (!PMSG_IS_AUTO(msg)) { pm_runtime_enable(port_dev-dev); status = pm_runtime_get_sync(port_dev-dev); pm_runtime_disable(port_dev-dev); } else status = pm_runtime_get_sync(port_dev-dev); port_dev-did_runtime_put = false; if (status 0) { dev_dbg(udev-dev, can't resume usb port, status %d\n
[PATCH] usb: Using correct way to clear usb3.0 device's remote wakeup feature.
Usb3.0 device defines function remote wakeup which is only for interface recipient rather than device recipient. This is different with usb2.0 device's remote wakeup feature which is defined for device recipient. According usb3.0 spec 9.4.5, the function remote wakeup can be modified by the SetFeature() requests using the FUNCTION_SUSPEND feature selector. This patch is to use correct way to disable usb3.0 device's function remote wakeup after suspend error and resuming. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 71 +++--- include/uapi/linux/usb/ch9.h |6 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0ef512a..08c9c04 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2852,6 +2852,24 @@ void usb_enable_ltm(struct usb_device *udev) } EXPORT_SYMBOL_GPL(usb_enable_ltm); +/* + * usb_disable_function_remotewakeup - disable usb3.0 + * device's function remote wakeup + * @udev: target device + * + * Assume there's only one function on the USB 3.0 + * device and disable remote wake for the first + * interface. FIXME if the interface association + * descriptor shows there's more than one function. + */ +static int usb_disable_function_remotewakeup(struct usb_device *udev) +{ + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} + #ifdef CONFIG_USB_SUSPEND /* @@ -2968,12 +2986,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) dev_dbg(hub-intfdev, can't suspend port %d, status %d\n, port1, status); /* paranoia: should not happen */ - if (udev-do_remote_wakeup) - (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + if (udev-do_remote_wakeup) { + if (!hub_is_superspeed(hub-hdev)) { + (void) usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else + (void) usb_disable_function_remotewakeup(udev); + + } /* Try to enable USB2 hardware LPM again */ if (udev-usb2_hw_lpm_capable == 1) @@ -3059,20 +3084,30 @@ static int finish_port_resume(struct usb_device *udev) dev_dbg(udev-dev, gone after usb resume? status %d\n, status); } else if (udev-actconfig) { - le16_to_cpus(devstatus); - if (devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) { - status = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, + if (!hub_is_superspeed(udev-parent)) { + le16_to_cpus(devstatus); + if (devstatus (1 USB_DEVICE_REMOTE_WAKEUP)) + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - if (status) - dev_dbg(udev-dev, - disable remote wakeup, status %d\n, - status); + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + devstatus); + le16_to_cpus(devstatus); + if (!status devstatus (USB_INTRF_STAT_FUNC_RW_CAP
Re: [Resend PATCH V4 0/10] usb: usb port power off mechanism anc expose usb port connect type
On 2013年01月11日 20:10, Lan Tianyu wrote: Change since v1: optimize the export connect type patch and adjust the DeviceRemovalbe flag in the rh_call_control() after GetHubDescriptor request being processed. move all debounce operation to usb port's runtime resume callback(). Add did_runtime_put in the struct usb_port to call pm_runtime_get/put(portdev) paired. using pm_runtime_get/put(portdev) to allow or prohibit device to be power off inside of pm qos request in the kernel side. Change since v2: Correct some link breaks. Add did_runtime_put in the usb_disconnect() before calling pm_runtime_put(portdev). Provide two seperate functions usb_device_allow_power_off() and usb_device_prevent_power_off() instead of just one. Change since v3: Set did_runtime_put to false in usb_disconnect() when its value is true Add comment about not enable port runtime pm if fail to expose port's pm qos. and call pm_runtime_set_active(portdev) unconditionally. rename usb_device_allow_prevent_power_off with usb_device_control_power_off Modify be power off to be powered off Expose dev_pm_qos_flags() symbol in order to ensure usb core can compile as module. Resend v4: make patch PM/Qos: Expose dev_pm_qos_flags symbol as first patch to avoid compilation error during git bisect correct some comments. This Patchset is based on usb-next tree commit 102ee001912 Merge tag 'for-usb-next-2013-01-03' This patchset is to add usb port power off mechanism and merge with patchset usb: expose DeviceRemovable to user space via sysfs attribute. Patchset usb: expose DeviceRemovable to user space via sysfs attribute. http://marc.info/?l=linux-usbm=135279430410171w=2 with some link break corrects The main discussion about usb port power off mechanism is in the following link: http://marc.info/?l=linux-usbm=134818340017208w=2 PM/Qos: Expose dev_pm_qos_flags symbol usb: Add driver/usb/core/(port.c,hub.h) files USB: Set usb port's DeviceRemovable according acpi information usb: Add portX/connect_type attribute to expose usb port's connect type usb: Create link files between child device and usb port device. usb: Register usb port's acpi power resources usb: add runtime pm support for usb port device usb: add usb port auto power off mechanism usb: expose usb port's pm qos flags to user space usb: add usb_device_allow_power_off() and usb_device_prevent_power_off() function. Hi GregAlan: Do you have some more comments about this patchset? Thanks. -- Best regards Tianyu Lan -- 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: USB device cannot be reconnected and khubd blocked for more than 120 seconds
On 2013年1月12日 15:48:59, Alex Riesen wrote: On Fri, Jan 11, 2013 at 10:04 PM, Alex Riesen raa.l...@gmail.com wrote: Hi, the USB stick (an Cruzer Titanium 2GB) was not recognized at any of the USB ports of this system (an System76 lemu4 laptop, XHCI device) after it was removed. If I attempt to insert it again in any of the ports (one of the two USB3, or the USB2) the led on the stick lights up shortly and if off again. There is no media detection messages in the dmesg output, only that from the first time: usb 1-1.2: new high-speed USB device number 3 using ehci-pci usb 1-1.2: New USB device found, idVendor=0781, idProduct=5408 usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 1-1.2: Product: U3 Titanium usb 1-1.2: Manufacturer: SanDisk Corporation usb 1-1.2: SerialNumber: 187A3A60F1E9 scsi6 : usb-storage 1-1.2:1.0 io scheduler deadline registered (default) usb 1-1.2: USB disconnect, device number 3 The kernel is v3.8-rc3. I never had this problem in 3.7. I could almost reproduce the problem later in a simplified setup (init=/bin/bash) on USB3 ports by inserting and removing the stick quickly. Almost - because the USB3 ports recovered after some time, while the USB2 port never experienced the problem. One more detail: I usually use the noop elevator. That time it was the deadline. And I just reproduced it easily with deadline. Can you provide the output of dmesg with CONFIG_USB_DEBUG? This will be helpful. -- 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 -- Best regards Tianyu Lan -- 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
[Resend PATCH V4 0/10] usb: usb port power off mechanism anc expose usb port connect type
Change since v1: optimize the export connect type patch and adjust the DeviceRemovalbe flag in the rh_call_control() after GetHubDescriptor request being processed. move all debounce operation to usb port's runtime resume callback(). Add did_runtime_put in the struct usb_port to call pm_runtime_get/put(portdev) paired. using pm_runtime_get/put(portdev) to allow or prohibit device to be power off inside of pm qos request in the kernel side. Change since v2: Correct some link breaks. Add did_runtime_put in the usb_disconnect() before calling pm_runtime_put(portdev). Provide two seperate functions usb_device_allow_power_off() and usb_device_prevent_power_off() instead of just one. Change since v3: Set did_runtime_put to false in usb_disconnect() when its value is true Add comment about not enable port runtime pm if fail to expose port's pm qos. and call pm_runtime_set_active(portdev) unconditionally. rename usb_device_allow_prevent_power_off with usb_device_control_power_off Modify be power off to be powered off Expose dev_pm_qos_flags() symbol in order to ensure usb core can compile as module. Resend v4: make patch PM/Qos: Expose dev_pm_qos_flags symbol as first patch to avoid compilation error during git bisect correct some comments. This Patchset is based on usb-next tree commit 102ee001912 Merge tag 'for-usb-next-2013-01-03' This patchset is to add usb port power off mechanism and merge with patchset usb: expose DeviceRemovable to user space via sysfs attribute. Patchset usb: expose DeviceRemovable to user space via sysfs attribute. http://marc.info/?l=linux-usbm=135279430410171w=2 with some link break corrects The main discussion about usb port power off mechanism is in the following link: http://marc.info/?l=linux-usbm=134818340017208w=2 PM/Qos: Expose dev_pm_qos_flags symbol usb: Add driver/usb/core/(port.c,hub.h) files USB: Set usb port's DeviceRemovable according acpi information usb: Add portX/connect_type attribute to expose usb port's connect type usb: Create link files between child device and usb port device. usb: Register usb port's acpi power resources usb: add runtime pm support for usb port device usb: add usb port auto power off mechanism usb: expose usb port's pm qos flags to user space usb: add usb_device_allow_power_off() and usb_device_prevent_power_off() function. -- 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
[Resend PATCH v4 01/10] PM/Qos: Expose dev_pm_qos_flags symbol
The dev_pm_qos_flags() will be used in the usb core which could be compiled as a module. This patch is to export it. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/base/power/qos.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index ff46387..e26b380 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -91,6 +91,7 @@ enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask) return ret; } +EXPORT_SYMBOL(dev_pm_qos_flags); /** * __dev_pm_qos_read_value - Get PM QoS constraint for a given device. -- 1.7.9.5 -- 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
[Resend PATCH v4 02/10] usb: Add driver/usb/core/(port.c,hub.h) files
This patch is to create driver/usb/core/(port.c,hub.h) files and move usb port related code into port.c. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/Makefile |1 + drivers/usb/core/hub.c| 107 + drivers/usb/core/hub.h| 97 drivers/usb/core/port.c | 66 4 files changed, 165 insertions(+), 106 deletions(-) create mode 100644 drivers/usb/core/hub.h create mode 100644 drivers/usb/core/port.c diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 26059b9..5e847ad 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -7,6 +7,7 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o usbcore-y += devio.o notify.o generic.o quirks.o devices.o +usbcore-y += port.o usbcore-$(CONFIG_PCI) += hcd-pci.o usbcore-$(CONFIG_ACPI) += usb-acpi.o diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ae10862..f5caf72 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -30,7 +30,7 @@ #include asm/uaccess.h #include asm/byteorder.h -#include usb.h +#include hub.h /* if we are in debug mode, always announce new devices */ #ifdef DEBUG @@ -42,62 +42,6 @@ #define USB_VENDOR_GENESYS_LOGIC 0x05e3 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 -struct usb_port { - struct usb_device *child; - struct device dev; - struct dev_state *port_owner; - enum usb_port_connect_type connect_type; -}; - -struct usb_hub { - struct device *intfdev; /* the interface device */ - struct usb_device *hdev; - struct kref kref; - struct urb *urb; /* for interrupt polling pipe */ - - /* buffer for urb ... with extra space in case of babble */ - char(*buffer)[8]; - union { - struct usb_hub_status hub; - struct usb_port_status port; - } *status;/* buffer for status reports */ - struct mutexstatus_mutex; /* for the status buffer */ - - int error; /* last reported error */ - int nerrors;/* track consecutive errors */ - - struct list_headevent_list; /* hubs w/data or errs ready */ - unsigned long event_bits[1]; /* status change bitmask */ - unsigned long change_bits[1]; /* ports with logical connect - status change */ - unsigned long busy_bits[1]; /* ports being reset or - resumed */ - unsigned long removed_bits[1]; /* ports with a removed - device present */ - unsigned long wakeup_bits[1]; /* ports that have signaled - remote wakeup */ -#if USB_MAXCHILDREN 31 /* 8*sizeof(unsigned long) - 1 */ -#error event_bits[] is too short! -#endif - - struct usb_hub_descriptor *descriptor; /* class descriptor */ - struct usb_tt tt; /* Transaction Translator */ - - unsignedmA_per_port;/* current for each child */ - - unsignedlimited_power:1; - unsignedquiescing:1; - unsigneddisconnected:1; - - unsignedquirk_check_port_auto_suspend:1; - - unsignedhas_indicators:1; - u8 indicator[USB_MAXCHILDREN]; - struct delayed_work leds; - struct delayed_work init_work; - struct usb_port **ports; -}; - static inline int hub_is_superspeed(struct usb_device *hdev) { return (hdev-descriptor.bDeviceProtocol == USB_HUB_PR_SS); @@ -168,9 +112,6 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); #define HUB_DEBOUNCE_STEP25 #define HUB_DEBOUNCE_STABLE 100 -#define to_usb_port(_dev) \ - container_of(_dev, struct usb_port, dev) - static int usb_reset_and_verify_device(struct usb_device *udev); static inline char *portspeed(struct usb_hub *hub, int portstatus) @@ -1294,52 +1235,6 @@ static int hub_post_reset(struct usb_interface *intf) return 0; } -static void usb_port_device_release(struct device *dev) -{ - struct usb_port *port_dev = to_usb_port(dev); - - kfree(port_dev); -} - -static void usb_hub_remove_port_device(struct usb_hub *hub, - int port1) -{ - device_unregister(hub-ports[port1 - 1]-dev); -} - -struct device_type usb_port_device_type = { - .name = usb_port
[Resend PATCH v4 04/10] usb: Add portX/connect_type attribute to expose usb port's connect type
Some platforms provide usb port connect types through ACPI. This patch is to add this new attribute to expose these information to user space. Signed-off-by: Lan Tianyu tianyu@intel.com --- Documentation/ABI/testing/sysfs-bus-usb |9 +++ drivers/usb/core/port.c | 43 +++ 2 files changed, 52 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index b6fbe51..c8baaf5 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -227,3 +227,12 @@ Contact: Lan Tianyu tianyu@intel.com Description: The /sys/bus/usb/devices/.../(hub interface)/portX is usb port device's sysfs directory. + +What: /sys/bus/usb/devices/.../(hub interface)/portX/connect_type +Date: January 2013 +Contact: Lan Tianyu tianyu@intel.com +Description: + Some platforms provide usb port connect types through ACPI. + This attribute is to expose these information to user space. + The file will read hotplug, wired and not used if the + information is available, and unknown otherwise. diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 2bc1cef..824e90b 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -18,6 +18,48 @@ #include hub.h +static const struct attribute_group *port_dev_group[]; + +static ssize_t show_port_connect_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_port *port_dev = to_usb_port(dev); + char *result; + + switch (port_dev-connect_type) { + case USB_PORT_CONNECT_TYPE_HOT_PLUG: + result = hotplug; + break; + case USB_PORT_CONNECT_TYPE_HARD_WIRED: + result = hardwired; + break; + case USB_PORT_NOT_USED: + result = not used; + break; + default: + result = unknown; + break; + } + + return sprintf(buf, %s\n, result); +} +static DEVICE_ATTR(connect_type, S_IRUGO, show_port_connect_type, + NULL); + +static struct attribute *port_dev_attrs[] = { + dev_attr_connect_type.attr, + NULL, +}; + +static struct attribute_group port_dev_attr_grp = { + .attrs = port_dev_attrs, +}; + +static const struct attribute_group *port_dev_group[] = { + port_dev_attr_grp, + NULL, +}; + static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); @@ -43,6 +85,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) hub-ports[port1 - 1] = port_dev; port_dev-dev.parent = hub-intfdev; + port_dev-dev.groups = port_dev_group; port_dev-dev.type = usb_port_device_type; dev_set_name(port_dev-dev, port%d, port1); -- 1.7.9.5 -- 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
[Resend PATCH v4 05/10] usb: Create link files between child device and usb port device.
To show the relationship between usb port and child device, add link file port under usb device's sysfs directoy and device under usb port device's sysfs directory. They are linked to each other. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7a893b0..05bdb04 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1978,6 +1978,14 @@ void usb_disconnect(struct usb_device **pdev) usb_disable_device(udev, 0); usb_hcd_synchronize_unlinks(udev); + if (udev-parent) { + struct usb_port *port_dev = + hdev_to_hub(udev-parent)-ports[udev-portnum - 1]; + + sysfs_remove_link(udev-dev.kobj, port); + sysfs_remove_link(port_dev-dev.kobj, device); + } + usb_remove_ep_devs(udev-ep0); usb_unlock_device(udev); @@ -2270,6 +2278,24 @@ int usb_new_device(struct usb_device *udev) goto fail; } + /* Create link files between child device and usb port device. */ + if (udev-parent) { + struct usb_port *port_dev = + hdev_to_hub(udev-parent)-ports[udev-portnum - 1]; + + err = sysfs_create_link(udev-dev.kobj, + port_dev-dev.kobj, port); + if (err) + goto fail; + + err = sysfs_create_link(port_dev-dev.kobj, + udev-dev.kobj, device); + if (err) { + sysfs_remove_link(udev-dev.kobj, port); + goto fail; + } + } + (void) usb_create_ep_devs(udev-dev, udev-ep0, udev); usb_mark_last_busy(udev); pm_runtime_put_sync_autosuspend(udev-dev); -- 1.7.9.5 -- 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
[Resend PATCH v4 03/10] USB: Set usb port's DeviceRemovable according acpi information
ACPI provide _PLD and _UPC aml methods to describe usb port visibility and connectability. This patch is to add usb_hub_adjust_DeviceRemovable() to adjust usb hub port's DeviceRemovable according ACPI information and invoke it in the rh_call_control(). When hub descriptor request is issued at first time, usb port device isn't created and usb port is not bound with acpi. So first hub descriptor request is not changed based on ACPI information. After usb port devices being created, call usb_hub_adjust_DeviceRemovable in the hub_configure() and then set hub port's DeviceRemovable according ACPI information and this also works for non-root hub. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hcd.c |4 drivers/usb/core/hub.c | 48 drivers/usb/core/usb.h |3 +++ 3 files changed, 55 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 4225d5e..6687302 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -619,6 +619,10 @@ nongeneric: status = hcd-driver-hub_control (hcd, typeReq, wValue, wIndex, tbuf, wLength); + + if (typeReq == GetHubDescriptor) + usb_hub_adjust_deviceremovable(hcd-self.root_hub, + (struct usb_hub_descriptor *)tbuf); break; error: /* protocol stall on error */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f5caf72..7a893b0 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1500,6 +1500,8 @@ static int hub_configure(struct usb_hub *hub, dev_err(hub-intfdev, couldn't create port%d device.\n, i + 1); + usb_hub_adjust_deviceremovable(hdev, hub-descriptor); + hub_activate(hub, HUB_INIT); return 0; @@ -5162,6 +5164,52 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) return hub-ports[port1 - 1]-connect_type; } +void usb_hub_adjust_deviceremovable(struct usb_device *hdev, + struct usb_hub_descriptor *desc) +{ + enum usb_port_connect_type connect_type; + int i; + + if (!hub_is_superspeed(hdev)) { + for (i = 1; i = hdev-maxchild; i++) { + connect_type = + usb_get_hub_port_connect_type(hdev, i); + + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u8 mask = 1 (i%8); + + if (!(desc-u.hs.DeviceRemovable[i/8] mask)) { + dev_dbg(hdev-dev, usb port%d's DeviceRemovable is changed to 1 according to platform information.\n, + i); + desc-u.hs.DeviceRemovable[i/8] + |= mask; + } + } + } + } else { + u16 port_removable = + le16_to_cpu(desc-u.ss.DeviceRemovable); + + for (i = 1; i = hdev-maxchild; i++) { + connect_type = + usb_get_hub_port_connect_type(hdev, i); + + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u16 mask = 1 i; + + if (!(port_removable mask)) { + dev_dbg(hdev-dev, usb port%d's DeviceRemovable is changed to 1 according to platform information.\n, + i); + port_removable |= mask; + } + } + } + + desc-u.ss.DeviceRemovable = + cpu_to_le16(port_removable); + } +} + #ifdef CONFIG_ACPI /** * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 1c528c1..3f18f2d 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -1,5 +1,6 @@ #include linux/pm.h #include linux/acpi.h +#include linux/usb/ch11.h struct dev_state; @@ -173,6 +174,8 @@ extern enum usb_port_connect_type usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, enum usb_port_connect_type type); +extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, + struct usb_hub_descriptor *desc); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); -- 1.7.9.5 -- 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
[Resend PATCH v4 06/10] usb: Register usb port's acpi power resources
This patch is to register usb port's acpi power resources. Create link between usb port device and its acpi power resource. Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/port.c |3 +++ drivers/usb/core/usb-acpi.c | 20 drivers/usb/core/usb.h |6 ++ 3 files changed, 29 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 824e90b..2365d5e 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -64,6 +64,7 @@ static void usb_port_device_release(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); + usb_acpi_unregister_power_resources(dev); kfree(port_dev); } @@ -93,6 +94,8 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) if (retval) goto error_register; + usb_acpi_register_power_resources(port_dev-dev); + return 0; error_register: diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252..558ab01 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -216,6 +216,26 @@ static struct acpi_bus_type usb_acpi_bus = { .find_device = usb_acpi_find_device, }; +int usb_acpi_register_power_resources(struct device *dev) +{ + acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + + if (!port_handle) + return -ENODEV; + + if (acpi_power_resource_register_device(dev, port_handle) 0) + return -ENODEV; + return 0; +} + +void usb_acpi_unregister_power_resources(struct device *dev) +{ + acpi_handle port_handle = DEVICE_ACPI_HANDLE(dev); + + if (port_handle) + acpi_power_resource_unregister_device(dev, port_handle); +} + int usb_acpi_register(void) { return register_acpi_bus_type(usb_acpi_bus); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 3f18f2d..386f562 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -182,7 +182,13 @@ extern int usb_acpi_register(void); extern void usb_acpi_unregister(void); extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, int port1); +extern int usb_acpi_register_power_resources(struct device *dev); +extern void usb_acpi_unregister_power_resources(struct device *dev); #else static inline int usb_acpi_register(void) { return 0; }; static inline void usb_acpi_unregister(void) { }; +static inline int usb_acpi_register_power_resources(struct usb_device *udev) + { return 0; }; +static inline int usb_acpi_unregister_power_resources(struct usb_device *udev) + { }; #endif -- 1.7.9.5 -- 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
[Resend PATCH v4 07/10] usb: add runtime pm support for usb port device
This patch is to add runtime pm callback for usb port device. Set/clear PORT_POWER feature in the resume/suspend callbak. Add portnum for struct usb_port to record port number. Do pm_rumtime_get_sync/put(portdev) when a device is plugged/unplugged to prevent it from being powered off when it is active. Acked-by: Rafael J. Wysocki rafael.j.wyso...@intel.com Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 18 ++ drivers/usb/core/hub.h |4 drivers/usb/core/port.c | 43 +++ 3 files changed, 65 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 05bdb04..a0dfdc5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -714,6 +714,18 @@ static void hub_tt_work(struct work_struct *work) spin_unlock_irqrestore (hub-tt.lock, flags); } +int usb_hub_set_port_power(struct usb_device *hdev, int port1, + bool set) +{ + int ret; + + if (set) + ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + else + ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + return ret; +} + /** * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub * @urb: an URB associated with the failed or incomplete split transaction @@ -1556,6 +1568,7 @@ static void hub_disconnect(struct usb_interface *intf) kfree(hub-status); kfree(hub-buffer); + pm_suspend_ignore_children(intf-dev, false); kref_put(hub-kref, hub_release); } @@ -1658,6 +1671,7 @@ descriptor_error: usb_set_intfdata (intf, hub); intf-needs_remote_wakeup = 1; + pm_suspend_ignore_children(intf-dev, true); if (hdev-speed == USB_SPEED_HIGH) highspeed_hubs++; @@ -1984,6 +1998,8 @@ 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); } usb_remove_ep_devs(udev-ep0); @@ -2294,6 +2310,8 @@ int usb_new_device(struct usb_device *udev) sysfs_remove_link(udev-dev.kobj, port); goto fail; } + + pm_runtime_get_sync(port_dev-dev); } (void) usb_create_ep_devs(udev-dev, udev-ep0, udev); diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index d16a7c9..8ea6bc8 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -79,12 +79,14 @@ struct usb_hub { * @dev: generic device interface * @port_owner: port's owner * @connect_type: port's connect type + * @portnum: port index num based one */ struct usb_port { struct usb_device *child; struct device dev; struct dev_state *port_owner; enum usb_port_connect_type connect_type; + u8 portnum; }; #define to_usb_port(_dev) \ @@ -94,4 +96,6 @@ extern int usb_hub_create_port_device(struct usb_hub *hub, int port1); extern void usb_hub_remove_port_device(struct usb_hub *hub, int port1); +extern int usb_hub_set_port_power(struct usb_device *hdev, + int port1, bool set); diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 2365d5e..a966596 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -17,6 +17,7 @@ */ #include hub.h +#include linux/pm_qos.h static const struct attribute_group *port_dev_group[]; @@ -68,9 +69,48 @@ static void usb_port_device_release(struct device *dev) kfree(port_dev); } +static int usb_port_runtime_resume(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + struct usb_device *hdev = to_usb_device(dev-parent-parent); + struct usb_interface *intf = to_usb_interface(dev-parent); + int retval; + + usb_autopm_get_interface(intf); + retval = usb_hub_set_port_power(hdev, port_dev-portnum, true); + usb_autopm_put_interface(intf); + return retval; +} + +static int usb_port_runtime_suspend(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + struct usb_device *hdev = to_usb_device(dev-parent-parent); + struct usb_interface *intf = to_usb_interface(dev-parent); + int retval; + + if (dev_pm_qos_flags(port_dev-dev, PM_QOS_FLAG_NO_POWER_OFF) + == PM_QOS_FLAGS_ALL) + return -EAGAIN; + + usb_autopm_get_interface(intf); + retval = usb_hub_set_port_power(hdev, port_dev-portnum, false); + usb_autopm_put_interface(intf); + return retval; +} + +static const struct dev_pm_ops usb_port_pm_ops = { +#ifdef CONFIG_USB_SUSPEND + .runtime_suspend = usb_port_runtime_suspend, + .runtime_resume = usb_port_runtime_resume, + .runtime_idle = pm_generic_runtime_idle, +#endif +}; + struct
[Resend PATCH v4 08/10] usb: add usb port auto power off mechanism
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. Acked-by: Rafael J. Wysocki rafael.j.wyso...@intel.com Signed-off-by: Lan Tianyu tianyu@intel.com --- drivers/usb/core/hub.c | 65 --- drivers/usb/core/hub.h |9 +++ drivers/usb/core/port.c | 40 +++-- 3 files changed, 103 insertions(+), 11 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a0dfdc5..c81d374 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 #define HUB_DEBOUNCE_STEP25 #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) { 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) { 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 */ @@ -1999,7 +2015,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 (!port_dev-did_runtime_put) + pm_runtime_put(port_dev-dev); + else + port_dev-did_runtime_put = false; } usb_remove_ep_devs(udev-ep0); @@ -2831,6 +2850,7 @@ EXPORT_SYMBOL_GPL(usb_enable_ltm); int usb_port_suspend(struct usb_device *udev, pm_message_t msg) { struct usb_hub *hub = hdev_to_hub(udev-parent); + struct usb_port *port_dev = hub-ports[udev-portnum - 1]; int