From ca078bae813dd46c0f9b102fdfb4a3384641ff48 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sat, 3 Sep 2005 15:56:57 -0700 Subject: [PATCH] swsusp: switch pm_message_t to struct This adds type-checking to pm_message_t, so that people can't confuse it with int or u32. It also allows us to fix "disk yoyo" during suspend (disk spinning down/up/down). [We've tried that before; since that cpufreq problems were fixed and I've tried make allyes config and fixed resulting damage.] Signed-off-by: Pavel Machek Signed-off-by: Alexander Nyberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/core/hub.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/usb/core/hub.c') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c3e46d24a37..c9412daff68 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1570,7 +1570,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, struct usb_driver *driver; intf = udev->actconfig->interface[i]; - if (state <= intf->dev.power.power_state) + if (state.event <= intf->dev.power.power_state.event) continue; if (!intf->dev.driver) continue; @@ -1578,11 +1578,11 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, if (driver->suspend) { status = driver->suspend(intf, state); - if (intf->dev.power.power_state != state + if (intf->dev.power.power_state.event != state.event || status) dev_err(&intf->dev, "suspend %d fail, code %d\n", - state, status); + state.event, status); } /* only drivers with suspend() can ever resume(); @@ -1595,7 +1595,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, * since we know every driver's probe/disconnect works * even for drivers that can't suspend. */ - if (!driver->suspend || state > PM_SUSPEND_MEM) { + if (!driver->suspend || state.event > PM_EVENT_FREEZE) { #if 1 dev_warn(&intf->dev, "resume is unsafe!\n"); #else @@ -1616,7 +1616,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, * policies (when HNP doesn't apply) once we have mechanisms to * turn power back on! (Likely not before 2.7...) */ - if (state > PM_SUSPEND_MEM) { + if (state.event > PM_EVENT_FREEZE) { dev_warn(&udev->dev, "no poweroff yet, suspending instead\n"); } @@ -1733,7 +1733,7 @@ static int finish_port_resume(struct usb_device *udev) struct usb_driver *driver; intf = udev->actconfig->interface[i]; - if (intf->dev.power.power_state == PMSG_ON) + if (intf->dev.power.power_state.event == PM_EVENT_ON) continue; if (!intf->dev.driver) { /* FIXME maybe force to alt 0 */ @@ -1747,11 +1747,11 @@ static int finish_port_resume(struct usb_device *udev) /* can we do better than just logging errors? */ status = driver->resume(intf); - if (intf->dev.power.power_state != PMSG_ON + if (intf->dev.power.power_state.event != PM_EVENT_ON || status) dev_dbg(&intf->dev, "resume fail, state %d code %d\n", - intf->dev.power.power_state, status); + intf->dev.power.power_state.event, status); } status = 0; @@ -1934,7 +1934,7 @@ static int hub_resume(struct usb_interface *intf) unsigned port1; int status; - if (intf->dev.power.power_state == PM_SUSPEND_ON) + if (intf->dev.power.power_state.event == PM_EVENT_ON) return 0; for (port1 = 1; port1 <= hdev->maxchild; port1++) { -- cgit v1.2.3 From fbf82fd2e1f4e679c60516d772d1862c941ca845 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 31 Jul 2005 01:05:53 +0200 Subject: [PATCH] USB: real nodes instead of usbfs This patch introduces a /sys/class/usb_device/ class where every connected usb-device will show up: tree /sys/class/usb_device/ /sys/class/usb_device/ |-- usb1.1 | |-- dev | `-- device -> ../../../devices/pci0000:00/0000:00:1d.0/usb1 |-- usb2.1 | |-- dev | `-- device -> ../../../devices/pci0000:00/0000:00:1d.1/usb2 ... The presence of the "dev" file lets udev create real device nodes. kay@pim:~/src/linux-2.6> tree /dev/bus/usb/ /dev/bus/usb/ |-- 1 | `-- 1 |-- 2 | `-- 1 ... udev rule: SUBSYSTEM="usb_device", PROGRAM="/sbin/usb_device %k", NAME="%c" (echo $1 | /bin/sed 's/usb\([0-9]*\)\.\([0-9]*\)/bus\/usb\/\1\/\2/') This makes libusb pick up the real nodes instead of the mounted usbfs: export USB_DEVFS_PATH=/dev/bus/usb Background: All this makes it possible to manage usb devices with udev instead of the devfs solution. We are currently working on a pam_console/resmgr replacement driven by udev and a pam-helper. It applies ACL's to device nodes, which is required for modern desktop functionalty like "Fast User Switching" or multiple local login support. New patch with its own major. I've succesfully disabled usbfs and use real nodes only on my box. With: "export USB_DEVFS_PATH=/dev/bus/usb" libusb picks up the udev managed nodes instead of reading usbfs files. This makes udev to provide symlinks for libusb to pick up: SUBSYSTEM="usb_device", PROGRAM="/sbin/usbdevice %k", SYMLINK="%c" /sbin/usbdevice: #!/bin/sh echo $1 | /bin/sed 's/usbdev\([0-9]*\)\.\([0-9]*\)/bus\/usb\/\1\/\2/' Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb/core/hub.c') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c9412daff68..a220a5e7f4a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1051,6 +1051,7 @@ void usb_disconnect(struct usb_device **pdev) dev_dbg (&udev->dev, "unregistering device\n"); release_address(udev); usbfs_remove_device(udev); + usbdev_remove(udev); usb_remove_sysfs_dev_files(udev); /* Avoid races with recursively_mark_NOTATTACHED() */ @@ -1290,6 +1291,7 @@ int usb_new_device(struct usb_device *udev) /* USB device state == configured ... usable */ /* add a /proc/bus/usb entry */ + usbdev_add(udev); usbfs_add_device(udev); return 0; -- cgit v1.2.3 From 8b28c7526a302bbfa618f7eab4ef961edd68c9a0 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 10 Aug 2005 17:04:13 -0400 Subject: [PATCH] USB: Code motion in the hub driver This patch (as553) merely moves some code and deletes an unneeded test in the hub driver. This is in preparation for the patch that follows. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'drivers/usb/core/hub.c') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a220a5e7f4a..4a4b41f2665 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -492,6 +492,23 @@ static int hub_hub_status(struct usb_hub *hub, return ret; } +static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) +{ + struct usb_device *hdev = hub->hdev; + int ret; + + if (hdev->children[port1-1] && set_state) { + usb_set_device_state(hdev->children[port1-1], + USB_STATE_NOTATTACHED); + } + ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); + if (ret) + dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", + port1, ret); + + return ret; +} + static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { @@ -717,15 +734,12 @@ static void hub_disconnect(struct usb_interface *intf) struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev; - if (!hub) - return; + usb_set_intfdata (intf, NULL); hdev = hub->hdev; if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs--; - usb_set_intfdata (intf, NULL); - hub_quiesce(hub); usb_free_urb(hub->urb); hub->urb = NULL; @@ -1430,23 +1444,6 @@ static int hub_port_reset(struct usb_hub *hub, int port1, return status; } -static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) -{ - struct usb_device *hdev = hub->hdev; - int ret; - - if (hdev->children[port1-1] && set_state) { - usb_set_device_state(hdev->children[port1-1], - USB_STATE_NOTATTACHED); - } - ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); - if (ret) - dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", - port1, ret); - - return ret; -} - /* * Disable a port and mark a logical connnect-change event, so that some * time later khubd will disconnect() any existing usb_device on the port -- cgit v1.2.3 From bf193d3cd2a3b73f2df74f57106114867946c09c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 10 Aug 2005 17:12:31 -0400 Subject: [PATCH] USB: Disconnect children when unbinding the hub driver This patch (as554) makes the hub driver disconnect any child USB devices when it is unbound from a hub. Normally this will never happen, but there are a few oddball ways to unbind the hub driver while leaving the children intact. For example, the new "unbind" sysfs attribute can be used for this purpose. Given that unbinding hubs with children is now safe, the patch also removes the code that prevented people from doing so using usbfs. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'drivers/usb/core/hub.c') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4a4b41f2665..9f54e8330f7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -729,10 +729,29 @@ fail: static unsigned highspeed_hubs; +/* Called after the hub driver is unbound from a hub with children */ +static void hub_remove_children_work(void *__hub) +{ + struct usb_hub *hub = __hub; + struct usb_device *hdev = hub->hdev; + int i; + + kfree(hub); + + usb_lock_device(hdev); + for (i = 0; i < hdev->maxchild; ++i) { + if (hdev->children[i]) + usb_disconnect(&hdev->children[i]); + } + usb_unlock_device(hdev); + usb_put_dev(hdev); +} + static void hub_disconnect(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev; + int n, port1; usb_set_intfdata (intf, NULL); hdev = hub->hdev; @@ -760,8 +779,27 @@ static void hub_disconnect(struct usb_interface *intf) hub->buffer = NULL; } - /* Free the memory */ - kfree(hub); + /* If there are any children then this is an unbind only, not a + * physical disconnection. The active ports must be disabled + * and later on we must call usb_disconnect(). We can't call + * it now because we may not hold the hub's device lock. + */ + n = 0; + for (port1 = 1; port1 <= hdev->maxchild; ++port1) { + if (hdev->children[port1 - 1]) { + ++n; + hub_port_disable(hub, port1, 1); + } + } + + if (n == 0) + kfree(hub); + else { + /* Reuse the hub->leds work_struct for our own purposes */ + INIT_WORK(&hub->leds, hub_remove_children_work, hub); + schedule_work(&hub->leds); + usb_get_dev(hdev); + } } static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) -- cgit v1.2.3 From e09711aef4180002241c7f2eab37390ddf40d6a0 Mon Sep 17 00:00:00 2001 From: "david-b@pacbell.net" Date: Sat, 13 Aug 2005 18:41:04 -0700 Subject: [PATCH] ehci: add think_time This adds think_time to the usb_tt struct and sets it appropriately (measured in ns); this can help us implement better split transaction scheduling. Signed-off-by: Dan Streetman Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers/usb/core/hub.c') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 9f54e8330f7..758c7f0ed15 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -627,19 +627,33 @@ static int hub_configure(struct usb_hub *hub, break; } + /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */ switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { - case 0x00: - if (hdev->descriptor.bDeviceProtocol != 0) - dev_dbg(hub_dev, "TT requires at most 8 FS bit times\n"); + case HUB_TTTT_8_BITS: + if (hdev->descriptor.bDeviceProtocol != 0) { + hub->tt.think_time = 666; + dev_dbg(hub_dev, "TT requires at most %d " + "FS bit times (%d ns)\n", + 8, hub->tt.think_time); + } break; - case 0x20: - dev_dbg(hub_dev, "TT requires at most 16 FS bit times\n"); + case HUB_TTTT_16_BITS: + hub->tt.think_time = 666 * 2; + dev_dbg(hub_dev, "TT requires at most %d " + "FS bit times (%d ns)\n", + 16, hub->tt.think_time); break; - case 0x40: - dev_dbg(hub_dev, "TT requires at most 24 FS bit times\n"); + case HUB_TTTT_24_BITS: + hub->tt.think_time = 666 * 3; + dev_dbg(hub_dev, "TT requires at most %d " + "FS bit times (%d ns)\n", + 24, hub->tt.think_time); break; - case 0x60: - dev_dbg(hub_dev, "TT requires at most 32 FS bit times\n"); + case HUB_TTTT_32_BITS: + hub->tt.think_time = 666 * 4; + dev_dbg(hub_dev, "TT requires at most %d " + "FS bit times (%d ns)\n", + 32, hub->tt.think_time); break; } -- cgit v1.2.3