On Tue, 16 May 2006, Ezequiel Valenzuela wrote:
> The question I have for the nice people here is: how do I force the
> kernel to use the uhci-hcd module instead of ehci-hcd *just for this
> device*, considering that I want to plug other USB 2.0 devices to the
> same machine? Is there any solution involving hotplug? (I think it's
> probably "too late" for hotplug to determine which host controller
> device to use). Can I edit some kernel source file (I haven't looked
> into that yet) to force the other host controller driver (uhci-hcd)
> instead of the automatically chosen one (ehci-hcd)?
Here's a patch for 2.6.17-rc4 (it also applies to 2.6.16) that does what
you want.
Let's suppose you have a high-speed USB device, something like 1-4 (i.e.,
controller 1 port 4). You can force it to run at full speed by doing:
echo 1-4 >/sys/class/usb/usb_host/usb_host1/companion
(the "1" in "usb_host1" is also the controller number, the same as the "1"
in "1-4").
Issuing the command a second time will switch the device back to high
speed.
Alan Stern
P.S.: Dave, what do you think? I'm not sure why the retry loop was
necessary; perhaps the port has to be disabled first before PORT_OWNER can
take effect. Also, there ought to be a way to do this when there's an
integrated TT, but I don't know how that would work.
Index: usb-2.6/drivers/usb/host/ehci-hub.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ehci-hub.c
+++ usb-2.6/drivers/usb/host/ehci-hub.c
@@ -173,6 +173,76 @@ static int ehci_bus_resume (struct usb_h
/*-------------------------------------------------------------------------*/
+/* Toggle the state of the OWNER bit for the requested port */
+static ssize_t
+store_companion (struct class_device *class_dev, const char *buf, size_t count)
+{
+ struct usb_bus *bus;
+ struct usb_hcd *hcd;
+ struct ehci_hcd *ehci;
+ int busnum, index, illegal;
+ int port_status, old_owner, try;
+
+ bus = class_get_devdata(class_dev);
+ hcd = bus->hcpriv;
+ ehci = hcd_to_ehci (hcd);
+
+ switch (sscanf (buf, "%d-%d.%d", &busnum, &index, &illegal)) {
+ case 1:
+ index = busnum;
+ break;
+ case 2:
+ if (busnum != bus->busnum)
+ return -ENODEV;
+ break;
+ default:
+ return -EINVAL;
+ }
+ --index;
+ if (index < 0 || index >= HCS_N_PORTS (ehci->hcs_params))
+ return -ENOENT;
+
+ old_owner = readl (&ehci->regs->port_status [index]) & PORT_OWNER;
+ for (try = 5; try > 0; --try) {
+ spin_lock_irq (&ehci->lock);
+ port_status = readl (&ehci->regs->port_status [index]);
+ if ((port_status & PORT_OWNER) == old_owner) {
+ port_status ^= PORT_OWNER;
+ port_status &= ~(PORT_PE | PORT_RWC_BITS);
+ writel (port_status, &ehci->regs->port_status [index]);
+ } else
+ try = 0;
+ spin_unlock_irq (&ehci->lock);
+ if (try > 1)
+ msleep(5);
+ }
+ return count;
+}
+static CLASS_DEVICE_ATTR (companion, S_IWUSR, NULL, store_companion);
+
+static inline void create_companion_file (struct ehci_hcd *ehci)
+{
+ struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
+
+ /* with integrated TT there is no companion! */
+ if (ehci_is_TDI(ehci))
+ return;
+ class_device_create_file(cldev, &class_device_attr_companion);
+}
+
+static inline void remove_companion_file (struct ehci_hcd *ehci)
+{
+ struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
+
+ /* with integrated TT there is no companion! */
+ if (ehci_is_TDI(ehci))
+ return;
+ class_device_create_file(cldev, &class_device_attr_companion);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
static int check_reset_complete (
struct ehci_hcd *ehci,
int index,
Index: usb-2.6/drivers/usb/host/ehci-hcd.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ehci-hcd.c
+++ usb-2.6/drivers/usb/host/ehci-hcd.c
@@ -384,6 +384,7 @@ static void ehci_stop (struct usb_hcd *h
writel (0, &ehci->regs->configured_flag);
unregister_reboot_notifier (&ehci->reboot_notifier);
+ remove_companion_file(ehci);
remove_debug_files (ehci);
/* root hub is shut down separately (first, when possible) */
@@ -560,6 +561,7 @@ static int ehci_run (struct usb_hcd *hcd
* since the class device isn't created that early.
*/
create_debug_files(ehci);
+ create_companion_file(ehci);
return 0;
}
-------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-users