Commit 3668d7cd authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB physical paths id

This provides something that gets discussed regularly: stable
device IDs.  Straightforward; most of it was already present:

    - Moves "bus_name" out of HCD framework into usb_bus.
      This accounts for _by far the bulk_ of this patch, since
      every use of that original field needed to change.

    - Make Vojtech's usb_make_path() use bus_name instead
      of unstable bus numbers ... and usb_device->devpath
      instead of recomputing that same info.  Combine two
      stable IDs, and the result is still stable.  And since both
      are precomputed, usb_make_path() turns into only an
      error check wrapped around snprintf() ... so I inlined it.

    - Minor tweak to usb_device->devpath construction.  It
      still uses "/" for the root hub (better suggestions?) but
      Vojtech wanted "." for separators, so I changed that.

    - The older HCDs (uhci.c etc) initialize usb_bus.bus_name,
      as well as the sharable HCD framework

    - HCD framework no longer uses "bus" member.

These IDs are currently exposed in "input" hotplugging, and
my next patch addresses that for USB network devices.
parent c060c5c9
...@@ -310,7 +310,7 @@ static int rh_string ( ...@@ -310,7 +310,7 @@ static int rh_string (
// serial number // serial number
} else if (id == 1) { } else if (id == 1) {
strcpy (buf, hcd->bus_name); strcpy (buf, hcd->self.bus_name);
// product description // product description
} else if (id == 2) { } else if (id == 2) {
...@@ -406,7 +406,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) ...@@ -406,7 +406,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
case DeviceOutRequest | USB_REQ_SET_ADDRESS: case DeviceOutRequest | USB_REQ_SET_ADDRESS:
// wValue == urb->dev->devaddr // wValue == urb->dev->devaddr
dbg ("%s root hub device address %d", dbg ("%s root hub device address %d",
hcd->bus_name, wValue); hcd->self.bus_name, wValue);
break; break;
/* INTERFACE REQUESTS (no defined feature/status flags) */ /* INTERFACE REQUESTS (no defined feature/status flags) */
...@@ -520,7 +520,7 @@ static void rh_report_status (unsigned long ptr) ...@@ -520,7 +520,7 @@ static void rh_report_status (unsigned long ptr)
&& rh_status_urb (hcd, urb) != 0) { && rh_status_urb (hcd, urb) != 0) {
/* another driver snuck in? */ /* another driver snuck in? */
dbg ("%s, can't resubmit roothub status urb?", dbg ("%s, can't resubmit roothub status urb?",
hcd->bus_name); hcd->self.bus_name);
spin_unlock_irqrestore (&hcd_data_lock, flags); spin_unlock_irqrestore (&hcd_data_lock, flags);
BUG (); BUG ();
} }
...@@ -1051,8 +1051,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1051,8 +1051,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
usb_init_bus (&hcd->self); usb_init_bus (&hcd->self);
hcd->self.op = &hcd_operations; hcd->self.op = &hcd_operations;
hcd->self.hcpriv = (void *) hcd; hcd->self.hcpriv = (void *) hcd;
hcd->bus = &hcd->self; hcd->self.bus_name = dev->slot_name;
hcd->bus_name = dev->slot_name;
hcd->product_desc = dev->name; hcd->product_desc = dev->name;
INIT_LIST_HEAD (&hcd->dev_list); INIT_LIST_HEAD (&hcd->dev_list);
...@@ -1089,16 +1088,15 @@ void usb_hcd_pci_remove (struct pci_dev *dev) ...@@ -1089,16 +1088,15 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
hcd = pci_get_drvdata(dev); hcd = pci_get_drvdata(dev);
if (!hcd) if (!hcd)
return; return;
info ("remove: %s, state %x", hcd->bus_name, hcd->state); info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
if (in_interrupt ()) BUG (); if (in_interrupt ()) BUG ();
hub = hcd->bus->root_hub; hub = hcd->self.root_hub;
hcd->state = USB_STATE_QUIESCING; hcd->state = USB_STATE_QUIESCING;
dbg ("%s: roothub graceful disconnect", hcd->bus_name); dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
usb_disconnect (&hub); usb_disconnect (&hub);
// usb_disconnect (&hcd->bus->root_hub);
hcd->driver->stop (hcd); hcd->driver->stop (hcd);
hcd->state = USB_STATE_HALT; hcd->state = USB_STATE_HALT;
...@@ -1113,10 +1111,9 @@ void usb_hcd_pci_remove (struct pci_dev *dev) ...@@ -1113,10 +1111,9 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
pci_resource_len (dev, hcd->region)); pci_resource_len (dev, hcd->region));
} }
usb_deregister_bus (hcd->bus); usb_deregister_bus (&hcd->self);
if (atomic_read (&hcd->self.refcnt) != 1) if (atomic_read (&hcd->self.refcnt) != 1)
err ("usb_hcd_pci_remove %s, count != 1", hcd->bus_name); err ("usb_hcd_pci_remove %s, count != 1", hcd->self.bus_name);
hcd->bus = NULL;
hcd->driver->hcd_free (hcd); hcd->driver->hcd_free (hcd);
} }
...@@ -1164,7 +1161,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state) ...@@ -1164,7 +1161,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
int retval; int retval;
hcd = pci_get_drvdata(dev); hcd = pci_get_drvdata(dev);
info ("suspend %s to state %d", hcd->bus_name, state); info ("suspend %s to state %d", hcd->self.bus_name, state);
pci_save_state (dev, hcd->pci_state); pci_save_state (dev, hcd->pci_state);
...@@ -1193,12 +1190,12 @@ int usb_hcd_pci_resume (struct pci_dev *dev) ...@@ -1193,12 +1190,12 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
int retval; int retval;
hcd = pci_get_drvdata(dev); hcd = pci_get_drvdata(dev);
info ("resume %s", hcd->bus_name); info ("resume %s", hcd->self.bus_name);
/* guard against multiple resumes (APM bug?) */ /* guard against multiple resumes (APM bug?) */
atomic_inc (&hcd->resume_count); atomic_inc (&hcd->resume_count);
if (atomic_read (&hcd->resume_count) != 1) { if (atomic_read (&hcd->resume_count) != 1) {
err ("concurrent PCI resumes for %s", hcd->bus_name); err ("concurrent PCI resumes for %s", hcd->self.bus_name);
retval = 0; retval = 0;
goto done; goto done;
} }
...@@ -1215,7 +1212,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) ...@@ -1215,7 +1212,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
retval = hcd->driver->resume (hcd); retval = hcd->driver->resume (hcd);
if (!HCD_IS_RUNNING (hcd->state)) { if (!HCD_IS_RUNNING (hcd->state)) {
dbg ("resume %s failure, retval %d", hcd->bus_name, retval); dbg ("resume %s failure, retval %d", hcd->self.bus_name, retval);
hc_died (hcd); hc_died (hcd);
// FIXME: recover, reset etc. // FIXME: recover, reset etc.
} else { } else {
...@@ -1290,7 +1287,7 @@ static void hc_died (struct usb_hcd *hcd) ...@@ -1290,7 +1287,7 @@ static void hc_died (struct usb_hcd *hcd)
list_for_each (urblist, &dev->urb_list) { list_for_each (urblist, &dev->urb_list) {
urb = list_entry (urblist, struct urb, urb_list); urb = list_entry (urblist, struct urb, urb_list);
dbg ("shutdown %s urb %p pipe %x, current status %d", dbg ("shutdown %s urb %p pipe %x, current status %d",
hcd->bus_name, urb, urb->pipe, urb->status); hcd->self.bus_name, urb, urb->pipe, urb->status);
if (urb->status == -EINPROGRESS) if (urb->status == -EINPROGRESS)
urb->status = -ESHUTDOWN; urb->status = -ESHUTDOWN;
} }
...@@ -1534,7 +1531,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) ...@@ -1534,7 +1531,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
* since we report some queuing/setup errors ourselves * since we report some queuing/setup errors ourselves
*/ */
urb = usb_get_urb (urb); urb = usb_get_urb (urb);
if (urb->dev == hcd->bus->root_hub) if (urb->dev == hcd->self.root_hub)
status = rh_urb_enqueue (hcd, urb); status = rh_urb_enqueue (hcd, urb);
else else
status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
...@@ -1686,7 +1683,7 @@ if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval); ...@@ -1686,7 +1683,7 @@ if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
&& HCD_IS_RUNNING (hcd->state) && HCD_IS_RUNNING (hcd->state)
&& !retval) { && !retval) {
dbg ("%s: wait for giveback urb %p", dbg ("%s: wait for giveback urb %p",
hcd->bus_name, urb); hcd->self.bus_name, urb);
wait_for_completion (&splice.done); wait_for_completion (&splice.done);
} else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) { } else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) {
return -EINPROGRESS; return -EINPROGRESS;
...@@ -1698,7 +1695,7 @@ if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval); ...@@ -1698,7 +1695,7 @@ if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
bye: bye:
if (retval) if (retval)
dbg ("%s: hcd_unlink_urb fail %d", dbg ("%s: hcd_unlink_urb fail %d",
hcd ? hcd->bus_name : "(no bus?)", hcd ? hcd->self.bus_name : "(no bus?)",
retval); retval);
return retval; return retval;
} }
...@@ -1731,7 +1728,7 @@ static int hcd_free_dev (struct usb_device *udev) ...@@ -1731,7 +1728,7 @@ static int hcd_free_dev (struct usb_device *udev)
/* device driver problem with refcounts? */ /* device driver problem with refcounts? */
if (!list_empty (&dev->urb_list)) { if (!list_empty (&dev->urb_list)) {
dbg ("free busy dev, %s devnum %d (bug!)", dbg ("free busy dev, %s devnum %d (bug!)",
hcd->bus_name, udev->devnum); hcd->self.bus_name, udev->devnum);
return -EINVAL; return -EINVAL;
} }
......
...@@ -35,10 +35,8 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ ...@@ -35,10 +35,8 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
/* /*
* housekeeping * housekeeping
*/ */
struct usb_bus *bus; /* FIXME only use "self" */
struct usb_bus self; /* hcd is-a bus */ struct usb_bus self; /* hcd is-a bus */
const char *bus_name;
const char *product_desc; /* product/vendor string */ const char *product_desc; /* product/vendor string */
const char *description; /* "ehci-hcd" etc */ const char *description; /* "ehci-hcd" etc */
......
...@@ -765,23 +765,23 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port, ...@@ -765,23 +765,23 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
* devices by location for diagnostics, tools, etc. The * devices by location for diagnostics, tools, etc. The
* string is a path along hub ports, from the root. Each * string is a path along hub ports, from the root. Each
* device's id will be stable until USB is re-cabled, and * device's id will be stable until USB is re-cabled, and
* hubs are often labled with these port numbers. * hubs are often labeled with these port numbers.
* *
* Initial size: "/NN" times five hubs + NUL = 16 bytes max * Initial size: ".NN" times five hubs + NUL = 16 bytes max
* (quite rare, since most hubs have 4-6 ports). * (quite rare, since most hubs have 4-6 ports).
*/ */
pdev = dev->parent; pdev = dev->parent;
if (pdev->devpath [1] != '\0') /* parent not root */ if (pdev->devpath [0] != '/') /* parent not root */
len = snprintf (dev->devpath, sizeof dev->devpath, len = snprintf (dev->devpath, sizeof dev->devpath,
"%s/%d", pdev->devpath, port + 1); "%s.%d", pdev->devpath, port + 1);
else /* root == "/", root port 2 == "/2" */ else /* root == "/", root port 2 == "2", port 3 that hub "/2.3" */
len = snprintf (dev->devpath, sizeof dev->devpath, len = snprintf (dev->devpath, sizeof dev->devpath,
"/%d", port + 1); "%d", port + 1);
if (len == sizeof dev->devpath) if (len == sizeof dev->devpath)
warn ("devpath size! usb/%03d/%03d path %s", warn ("devpath size! usb/%03d/%03d path %s",
dev->bus->busnum, dev->devnum, dev->devpath); dev->bus->busnum, dev->devnum, dev->devpath);
info("new USB device on bus %d path %s, assigned address %d", info("new USB device %s-%s, assigned address %d",
dev->bus->busnum, dev->devpath, dev->devnum); dev->bus->bus_name, dev->devpath, dev->devnum);
/* put the device in the global device tree */ /* put the device in the global device tree */
dev->dev.parent = &dev->parent->dev; dev->dev.parent = &dev->parent->dev;
......
...@@ -2407,56 +2407,6 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) ...@@ -2407,56 +2407,6 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
return err; return err;
} }
/**
* usb_make_path - returns device path in the hub tree
* @dev: the device whose path is being constructed
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* Returns length of the string (>= 0) or out of memory status (< 0).
*
* NOTE: prefer to use use dev->devpath directly.
*/
int usb_make_path(struct usb_device *dev, char *buf, size_t size)
{
struct usb_device *pdev = dev->parent;
char *tmp;
char *port;
int i;
if (!(port = kmalloc(size, GFP_KERNEL)))
return -ENOMEM;
if (!(tmp = kmalloc(size, GFP_KERNEL))) {
kfree(port);
return -ENOMEM;
}
*port = 0;
while (pdev) {
for (i = 0; i < pdev->maxchild; i++)
if (pdev->children[i] == dev)
break;
if (pdev->children[i] != dev) {
kfree(port);
kfree(tmp);
return -ENODEV;
}
strcpy(tmp, port);
snprintf(port, size, strlen(port) ? "%d.%s" : "%d", i + 1, tmp);
dev = pdev;
pdev = dev->parent;
}
snprintf(buf, size, "usb%d:%s", dev->bus->busnum, port);
kfree(port);
kfree(tmp);
return strlen(buf);
}
/* /*
* By the time we get here, the device has gotten a new device ID * By the time we get here, the device has gotten a new device ID
* and is in the default state. We need to identify the thing and * and is in the default state. We need to identify the thing and
......
...@@ -55,7 +55,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) ...@@ -55,7 +55,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
strcat(buf, tmp); strcat(buf, tmp);
} }
dbg ("%s: %s portroute %s", dbg ("%s: %s portroute %s",
ehci->hcd.bus_name, label, ehci->hcd.self.bus_name, label,
buf); buf);
} }
} }
......
...@@ -248,7 +248,7 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -248,7 +248,7 @@ static int ehci_start (struct usb_hcd *hcd)
ehci->tasklet.data = (unsigned long) ehci; ehci->tasklet.data = (unsigned long) ehci;
/* wire up the root hub */ /* wire up the root hub */
hcd->bus->root_hub = udev = usb_alloc_dev (NULL, hcd->bus); hcd->self.root_hub = udev = usb_alloc_dev (NULL, &hcd->self);
if (!udev) { if (!udev) {
done2: done2:
ehci_mem_cleanup (ehci); ehci_mem_cleanup (ehci);
...@@ -288,8 +288,7 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -288,8 +288,7 @@ static int ehci_start (struct usb_hcd *hcd)
while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS)) while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
udelay (100); udelay (100);
ehci_reset (ehci); ehci_reset (ehci);
// usb_disconnect (udev); hcd->self.root_hub = 0;
hcd->bus->root_hub = 0;
usb_free_dev (udev); usb_free_dev (udev);
retval = -ENODEV; retval = -ENODEV;
goto done2; goto done2;
...@@ -304,7 +303,7 @@ static void ehci_stop (struct usb_hcd *hcd) ...@@ -304,7 +303,7 @@ static void ehci_stop (struct usb_hcd *hcd)
{ {
struct ehci_hcd *ehci = hcd_to_ehci (hcd); struct ehci_hcd *ehci = hcd_to_ehci (hcd);
dbg ("%s: stop", hcd->bus_name); dbg ("%s: stop", hcd->self.bus_name);
if (hcd->state == USB_STATE_RUNNING) if (hcd->state == USB_STATE_RUNNING)
ehci_ready (ehci); ehci_ready (ehci);
...@@ -339,7 +338,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state) ...@@ -339,7 +338,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
int ports; int ports;
int i; int i;
dbg ("%s: suspend to %d", hcd->bus_name, state); dbg ("%s: suspend to %d", hcd->self.bus_name, state);
ports = HCS_N_PORTS (ehci->hcs_params); ports = HCS_N_PORTS (ehci->hcs_params);
...@@ -356,7 +355,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state) ...@@ -356,7 +355,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
if ((temp & PORT_PE) == 0 if ((temp & PORT_PE) == 0
|| (temp & PORT_OWNER) != 0) || (temp & PORT_OWNER) != 0)
continue; continue;
dbg ("%s: suspend port %d", hcd->bus_name, i); dbg ("%s: suspend port %d", hcd->self.bus_name, i);
temp |= PORT_SUSPEND; temp |= PORT_SUSPEND;
writel (temp, &ehci->regs->port_status [i]); writel (temp, &ehci->regs->port_status [i]);
} }
...@@ -380,7 +379,7 @@ static int ehci_resume (struct usb_hcd *hcd) ...@@ -380,7 +379,7 @@ static int ehci_resume (struct usb_hcd *hcd)
int ports; int ports;
int i; int i;
dbg ("%s: resume", hcd->bus_name); dbg ("%s: resume", hcd->self.bus_name);
ports = HCS_N_PORTS (ehci->hcs_params); ports = HCS_N_PORTS (ehci->hcs_params);
...@@ -400,7 +399,7 @@ static int ehci_resume (struct usb_hcd *hcd) ...@@ -400,7 +399,7 @@ static int ehci_resume (struct usb_hcd *hcd)
if ((temp & PORT_PE) == 0 if ((temp & PORT_PE) == 0
|| (temp & PORT_SUSPEND) != 0) || (temp & PORT_SUSPEND) != 0)
continue; continue;
dbg ("%s: resume port %d", hcd->bus_name, i); dbg ("%s: resume port %d", hcd->self.bus_name, i);
temp |= PORT_RESUME; temp |= PORT_RESUME;
writel (temp, &ehci->regs->port_status [i]); writel (temp, &ehci->regs->port_status [i]);
readl (&ehci->regs->command); /* unblock posted writes */ readl (&ehci->regs->command); /* unblock posted writes */
...@@ -472,7 +471,7 @@ static void ehci_irq (struct usb_hcd *hcd) ...@@ -472,7 +471,7 @@ static void ehci_irq (struct usb_hcd *hcd)
/* PCI errors [4.15.2.4] */ /* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) { if (unlikely ((status & STS_FATAL) != 0)) {
err ("%s: fatal error, state %x", hcd->bus_name, hcd->state); err ("%s: fatal error, state %x", hcd->self.bus_name, hcd->state);
ehci_reset (ehci); ehci_reset (ehci);
// generic layer kills/unlinks all urbs // generic layer kills/unlinks all urbs
// then tasklet cleans up the rest // then tasklet cleans up the rest
...@@ -547,7 +546,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -547,7 +546,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
unsigned long flags; unsigned long flags;
dbg ("%s urb_dequeue %p qh state %d", dbg ("%s urb_dequeue %p qh state %d",
hcd->bus_name, urb, qh->qh_state); hcd->self.bus_name, urb, qh->qh_state);
switch (usb_pipetype (urb->pipe)) { switch (usb_pipetype (urb->pipe)) {
case PIPE_CONTROL: case PIPE_CONTROL:
...@@ -608,7 +607,7 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev) ...@@ -608,7 +607,7 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
/* ASSERT: nobody can be submitting urbs for this any more */ /* ASSERT: nobody can be submitting urbs for this any more */
dbg ("%s: free_config devnum %d", hcd->bus_name, udev->devnum); dbg ("%s: free_config devnum %d", hcd->self.bus_name, udev->devnum);
spin_lock_irqsave (&ehci->lock, flags); spin_lock_irqsave (&ehci->lock, flags);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
......
...@@ -41,14 +41,14 @@ static int check_reset_complete ( ...@@ -41,14 +41,14 @@ static int check_reset_complete (
/* if reset finished and it's still not enabled -- handoff */ /* if reset finished and it's still not enabled -- handoff */
if (!(port_status & PORT_PE)) { if (!(port_status & PORT_PE)) {
dbg ("%s port %d full speed, give to companion, 0x%x", dbg ("%s port %d full speed, give to companion, 0x%x",
ehci->hcd.bus_name, index + 1, port_status); ehci->hcd.self.bus_name, index + 1, port_status);
// what happens if HCS_N_CC(params) == 0 ? // what happens if HCS_N_CC(params) == 0 ?
port_status |= PORT_OWNER; port_status |= PORT_OWNER;
writel (port_status, &ehci->regs->port_status [index]); writel (port_status, &ehci->regs->port_status [index]);
} else } else
dbg ("%s port %d high speed", ehci->hcd.bus_name, index + 1); dbg ("%s port %d high speed", ehci->hcd.self.bus_name, index + 1);
return port_status; return port_status;
} }
...@@ -306,11 +306,11 @@ static int ehci_hub_control ( ...@@ -306,11 +306,11 @@ static int ehci_hub_control (
if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
&& PORT_USB11 (temp)) { && PORT_USB11 (temp)) {
dbg ("%s port %d low speed, give to companion", dbg ("%s port %d low speed, give to companion",
hcd->bus_name, wIndex + 1); hcd->self.bus_name, wIndex + 1);
temp |= PORT_OWNER; temp |= PORT_OWNER;
} else { } else {
vdbg ("%s port %d reset", vdbg ("%s port %d reset",
hcd->bus_name, wIndex + 1); hcd->self.bus_name, wIndex + 1);
temp |= PORT_RESET; temp |= PORT_RESET;
temp &= ~PORT_PE; temp &= ~PORT_PE;
......
...@@ -733,7 +733,7 @@ submit_async ( ...@@ -733,7 +733,7 @@ submit_async (
epnum |= 0x10; epnum |= 0x10;
vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]", vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]",
ehci->hcd.bus_name, urb, urb->transfer_buffer_length, ehci->hcd.self.bus_name, urb, urb->transfer_buffer_length,
epnum & 0x0f, (epnum & 0x10) ? "in" : "out", epnum & 0x0f, (epnum & 0x10) ? "in" : "out",
qtd, dev ? dev->ep [epnum] : (void *)~0); qtd, dev ? dev->ep [epnum] : (void *)~0);
......
...@@ -89,7 +89,7 @@ void ohci_dump_periodic (struct ohci_hcd *ohci, char *label) ...@@ -89,7 +89,7 @@ void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
continue; continue;
printed = 1; printed = 1;
printk (KERN_DEBUG "%s, ohci %s frame %2d:", printk (KERN_DEBUG "%s, ohci %s frame %2d:",
label, ohci->hcd.bus_name, i); label, ohci->hcd.self.bus_name, i);
while (*ed_p != 0 && j--) { while (*ed_p != 0 && j--) {
struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p)); struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p));
printk (" %p/%08x;", ed, ed->hwINFO); printk (" %p/%08x;", ed, ed->hwINFO);
...@@ -99,7 +99,7 @@ void ohci_dump_periodic (struct ohci_hcd *ohci, char *label) ...@@ -99,7 +99,7 @@ void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
} }
if (!printed) if (!printed)
printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n", printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n",
label, ohci->hcd.bus_name); label, ohci->hcd.self.bus_name);
} }
#endif #endif
...@@ -229,7 +229,7 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) ...@@ -229,7 +229,7 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
static void ohci_dump (struct ohci_hcd *controller, int verbose) static void ohci_dump (struct ohci_hcd *controller, int verbose)
{ {
dbg ("OHCI controller %s state", controller->hcd.bus_name); dbg ("OHCI controller %s state", controller->hcd.self.bus_name);
// dumps some of the state we know about // dumps some of the state we know about
ohci_dump_status (controller); ohci_dump_status (controller);
......
...@@ -379,7 +379,7 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -379,7 +379,7 @@ static int hc_reset (struct ohci_hcd *ohci)
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
dbg ("USB HC reset_hc %s: ctrl = 0x%x ;", dbg ("USB HC reset_hc %s: ctrl = 0x%x ;",
ohci->hcd.bus_name, ohci->hcd.self.bus_name,
readl (&ohci->regs->control)); readl (&ohci->regs->control));
/* Reset USB (needed by some controllers) */ /* Reset USB (needed by some controllers) */
...@@ -449,7 +449,7 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -449,7 +449,7 @@ static int hc_start (struct ohci_hcd *ohci)
mdelay ((roothub_a (ohci) >> 23) & 0x1fe); mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
/* connect the virtual root hub */ /* connect the virtual root hub */
ohci->hcd.bus->root_hub = udev = usb_alloc_dev (NULL, ohci->hcd.bus); ohci->hcd.self.root_hub = udev = usb_alloc_dev (NULL, &ohci->hcd.self);
ohci->hcd.state = USB_STATE_READY; ohci->hcd.state = USB_STATE_READY;
if (!udev) { if (!udev) {
ohci->disabled = 1; ohci->disabled = 1;
...@@ -491,7 +491,7 @@ static void ohci_irq (struct usb_hcd *hcd) ...@@ -491,7 +491,7 @@ static void ohci_irq (struct usb_hcd *hcd)
if (ints & OHCI_INTR_UE) { if (ints & OHCI_INTR_UE) {
ohci->disabled++; ohci->disabled++;
err ("OHCI Unrecoverable Error, %s disabled", hcd->bus_name); err ("OHCI Unrecoverable Error, %s disabled", hcd->self.bus_name);
// e.g. due to PCI Master/Target Abort // e.g. due to PCI Master/Target Abort
#ifdef DEBUG #ifdef DEBUG
...@@ -530,7 +530,7 @@ static void ohci_stop (struct usb_hcd *hcd) ...@@ -530,7 +530,7 @@ static void ohci_stop (struct usb_hcd *hcd)
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
dbg ("%s: stop %s controller%s", dbg ("%s: stop %s controller%s",
hcd->bus_name, hcd->self.bus_name,
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
ohci->disabled ? " (disabled)" : "" ohci->disabled ? " (disabled)" : ""
); );
...@@ -571,7 +571,7 @@ ohci_start (struct usb_hcd *hcd) ...@@ -571,7 +571,7 @@ ohci_start (struct usb_hcd *hcd)
&& hcd->pdev->device == 0x740c) { && hcd->pdev->device == 0x740c) {
ohci->flags = OHCI_QUIRK_AMD756; ohci->flags = OHCI_QUIRK_AMD756;
info ("%s: AMD756 erratum 4 workaround", info ("%s: AMD756 erratum 4 workaround",
hcd->bus_name); hcd->self.bus_name);
} }
/* Apple's OHCI driver has a lot of bizarre workarounds /* Apple's OHCI driver has a lot of bizarre workarounds
...@@ -581,7 +581,7 @@ ohci_start (struct usb_hcd *hcd) ...@@ -581,7 +581,7 @@ ohci_start (struct usb_hcd *hcd)
else if (hcd->pdev->vendor == 0x1045 else if (hcd->pdev->vendor == 0x1045
&& hcd->pdev->device == 0xc861) { && hcd->pdev->device == 0xc861) {
info ("%s: WARNING: OPTi workarounds unavailable", info ("%s: WARNING: OPTi workarounds unavailable",
hcd->bus_name); hcd->self.bus_name);
} }
} }
#else #else
...@@ -601,7 +601,7 @@ ohci_start (struct usb_hcd *hcd) ...@@ -601,7 +601,7 @@ ohci_start (struct usb_hcd *hcd)
} }
if (hc_start (ohci) < 0) { if (hc_start (ohci) < 0) {
err ("can't start %s", ohci->hcd.bus_name); err ("can't start %s", ohci->hcd.self.bus_name);
ohci_stop (hcd); ohci_stop (hcd);
return -EBUSY; return -EBUSY;
} }
...@@ -623,13 +623,13 @@ static int ohci_suspend (struct usb_hcd *hcd, u32 state) ...@@ -623,13 +623,13 @@ static int ohci_suspend (struct usb_hcd *hcd, u32 state)
u16 cmd; u16 cmd;
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
dbg ("can't suspend %s (state is %s)", hcd->bus_name, dbg ("can't suspend %s (state is %s)", hcd->self.bus_name,
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
return -EIO; return -EIO;
} }
/* act as if usb suspend can always be used */ /* act as if usb suspend can always be used */
dbg ("%s: suspend to %d", hcd->bus_name, state); dbg ("%s: suspend to %d", hcd->self.bus_name, state);
ohci->sleeping = 1; ohci->sleeping = 1;
/* First stop processing */ /* First stop processing */
...@@ -664,16 +664,16 @@ static int ohci_suspend (struct usb_hcd *hcd, u32 state) ...@@ -664,16 +664,16 @@ static int ohci_suspend (struct usb_hcd *hcd, u32 state)
switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
case OHCI_USB_RESET: case OHCI_USB_RESET:
dbg ("%s suspend->reset ?", hcd->bus_name); dbg ("%s suspend->reset ?", hcd->self.bus_name);
break; break;
case OHCI_USB_RESUME: case OHCI_USB_RESUME:
dbg ("%s suspend->resume ?", hcd->bus_name); dbg ("%s suspend->resume ?", hcd->self.bus_name);
break; break;
case OHCI_USB_OPER: case OHCI_USB_OPER:
dbg ("%s suspend->operational ?", hcd->bus_name); dbg ("%s suspend->operational ?", hcd->self.bus_name);
break; break;
case OHCI_USB_SUSPEND: case OHCI_USB_SUSPEND:
dbg ("%s suspended", hcd->bus_name); dbg ("%s suspended", hcd->self.bus_name);
break; break;
} }
...@@ -711,8 +711,8 @@ static int hc_restart (struct ohci_hcd *ohci) ...@@ -711,8 +711,8 @@ static int hc_restart (struct ohci_hcd *ohci)
ohci->disabled = 1; ohci->disabled = 1;
ohci->sleeping = 0; ohci->sleeping = 0;
if (ohci->hcd.bus->root_hub) if (ohci->hcd.self.root_hub)
usb_disconnect (&ohci->hcd.bus->root_hub); usb_disconnect (&ohci->hcd.self.root_hub);
/* empty the interrupt branches */ /* empty the interrupt branches */
for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load [i] = 0; for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load [i] = 0;
...@@ -728,10 +728,10 @@ static int hc_restart (struct ohci_hcd *ohci) ...@@ -728,10 +728,10 @@ static int hc_restart (struct ohci_hcd *ohci)
ohci->ed_bulktail = NULL; ohci->ed_bulktail = NULL;
if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
err ("can't restart %s, %d", ohci->hcd.bus_name, temp); err ("can't restart %s, %d", ohci->hcd.self.bus_name, temp);
return temp; return temp;
} else } else
dbg ("restart %s completed", ohci->hcd.bus_name); dbg ("restart %s completed", ohci->hcd.self.bus_name);
return 0; return 0;
} }
...@@ -767,13 +767,13 @@ static int ohci_resume (struct usb_hcd *hcd) ...@@ -767,13 +767,13 @@ static int ohci_resume (struct usb_hcd *hcd)
switch (temp) { switch (temp) {
case OHCI_USB_RESET: // lost power case OHCI_USB_RESET: // lost power
info ("USB restart: %s", hcd->bus_name); info ("USB restart: %s", hcd->self.bus_name);
retval = hc_restart (ohci); retval = hc_restart (ohci);
break; break;
case OHCI_USB_SUSPEND: // host wakeup case OHCI_USB_SUSPEND: // host wakeup
case OHCI_USB_RESUME: // remote wakeup case OHCI_USB_RESUME: // remote wakeup
info ("USB continue: %s from %s wakeup", hcd->bus_name, info ("USB continue: %s from %s wakeup", hcd->self.bus_name,
(temp == OHCI_USB_SUSPEND) (temp == OHCI_USB_SUSPEND)
? "host" : "remote"); ? "host" : "remote");
ohci->hc_control = OHCI_USB_RESUME; ohci->hc_control = OHCI_USB_RESUME;
...@@ -786,7 +786,7 @@ static int ohci_resume (struct usb_hcd *hcd) ...@@ -786,7 +786,7 @@ static int ohci_resume (struct usb_hcd *hcd)
temp = readl (&ohci->regs->control); temp = readl (&ohci->regs->control);
temp = ohci->hc_control & OHCI_CTRL_HCFS; temp = ohci->hc_control & OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) { if (temp != OHCI_USB_RESUME) {
err ("controller %s won't resume", hcd->bus_name); err ("controller %s won't resume", hcd->self.bus_name);
ohci->disabled = 1; ohci->disabled = 1;
retval = -EIO; retval = -EIO;
break; break;
...@@ -836,7 +836,7 @@ dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled); ...@@ -836,7 +836,7 @@ dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled);
break; break;
default: default:
warn ("odd PCI resume for %s", hcd->bus_name); warn ("odd PCI resume for %s", hcd->self.bus_name);
} }
return retval; return retval;
} }
......
...@@ -41,7 +41,7 @@ static u32 roothub_portstatus (struct ohci_hcd *hc, int i) ...@@ -41,7 +41,7 @@ static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
#define dbg_port(hc,label,num,value) \ #define dbg_port(hc,label,num,value) \
dbg ("%s: %s roothub.portstatus [%d] " \ dbg ("%s: %s roothub.portstatus [%d] " \
"= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", \ "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", \
hc->hcd.bus_name, label, num, temp, \ hc->hcd.self.bus_name, label, num, temp, \
(temp & RH_PS_PRSC) ? " PRSC" : "", \ (temp & RH_PS_PRSC) ? " PRSC" : "", \
(temp & RH_PS_OCIC) ? " OCIC" : "", \ (temp & RH_PS_OCIC) ? " OCIC" : "", \
(temp & RH_PS_PSSC) ? " PSSC" : "", \ (temp & RH_PS_PSSC) ? " PSSC" : "", \
...@@ -71,7 +71,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) ...@@ -71,7 +71,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
ports = roothub_a (ohci) & RH_A_NDP; ports = roothub_a (ohci) & RH_A_NDP;
if (ports > MAX_ROOT_PORTS) { if (ports > MAX_ROOT_PORTS) {
err ("%s: bogus NDP=%d", hcd->bus_name, ports); err ("%s: bogus NDP=%d", hcd->self.bus_name, ports);
err ("rereads as NDP=%d", err ("rereads as NDP=%d",
readl (&ohci->regs->roothub.a) & RH_A_NDP); readl (&ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */ /* retry later; "should not happen" */
......
...@@ -2799,6 +2799,7 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io ...@@ -2799,6 +2799,7 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io
uhci->bus = bus; uhci->bus = bus;
bus->hcpriv = uhci; bus->hcpriv = uhci;
bus->bus_name = dev->slot_name;
usb_register_bus(uhci->bus); usb_register_bus(uhci->bus);
......
...@@ -2400,6 +2400,7 @@ static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base) ...@@ -2400,6 +2400,7 @@ static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base)
return NULL; return NULL;
} }
ohci->bus->hcpriv = (void *) ohci; ohci->bus->hcpriv = (void *) ohci;
ohci->bus->bus_name = dev->slot_name;
return ohci; return ohci;
} }
......
...@@ -2977,6 +2977,7 @@ _static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_ ...@@ -2977,6 +2977,7 @@ _static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_
s->bus = bus; s->bus = bus;
bus->hcpriv = s; bus->hcpriv = s;
bus->bus_name = dev->slot_name;
/* UHCI specs says devices must have 2 ports, but goes on to say */ /* UHCI specs says devices must have 2 ports, but goes on to say */
/* they may have more but give no way to determine how many they */ /* they may have more but give no way to determine how many they */
......
...@@ -890,7 +890,6 @@ extern int usb_string(struct usb_device *dev, int index, ...@@ -890,7 +890,6 @@ extern int usb_string(struct usb_device *dev, int index,
char *buf, size_t size); char *buf, size_t size);
extern int usb_set_configuration(struct usb_device *dev, int configuration); extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
extern int usb_make_path(struct usb_device *dev, char *buf, size_t size);
/* /*
* timeouts, in seconds, used for sending/receiving control messages * timeouts, in seconds, used for sending/receiving control messages
...@@ -917,6 +916,7 @@ struct usb_operations; ...@@ -917,6 +916,7 @@ struct usb_operations;
*/ */
struct usb_bus { struct usb_bus {
int busnum; /* Bus number (in order of reg) */ int busnum; /* Bus number (in order of reg) */
char *bus_name; /* stable id (PCI slot_name etc) */
#ifdef DEVNUM_ROUND_ROBIN #ifdef DEVNUM_ROUND_ROBIN
int devnum_next; /* Next open device number in round-robin allocation */ int devnum_next; /* Next open device number in round-robin allocation */
...@@ -1087,6 +1087,37 @@ const struct usb_device_id *usb_match_id(struct usb_device *dev, ...@@ -1087,6 +1087,37 @@ const struct usb_device_id *usb_match_id(struct usb_device *dev,
struct usb_interface *interface, struct usb_interface *interface,
const struct usb_device_id *id); const struct usb_device_id *id);
/**
* usb_make_path - returns stable device path in the usb tree
* @dev: the device whose path is being constructed
* @buf: where to put the string
* @size: how big is "buf"?
*
* Returns length of the string (> 0) or negative if size was too small.
*
* This identifier is intended to be "stable", reflecting physical paths in
* hardware such as physical bus addresses for host controllers or ports on
* USB hubs. That makes it stay the same until systems are physically
* reconfigured, by re-cabling a tree of USB devices or by moving USB host
* controllers. Adding and removing devices, including virtual root hubs
* in host controller driver modules, does not change these path identifers;
* neither does rebooting or re-enumerating. These are more useful identifiers
* than changeable ("unstable") ones like bus numbers or device addresses.
*
* With a partial exception for devices connected to USB 2.0 root hubs, these
* identifiers are also predictable: so long as the device tree isn't changed,
* plugging any USB device into a given hub port always gives it the same path.
* Because of the use of "companion" controllers, devices connected to ports on
* USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are
* high speed, and a different one if they are full or low speed.
*/
static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
{
int actual;
actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name, dev->devpath);
return (actual >= size) ? -1 : actual;
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment