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 (
// serial number
} else if (id == 1) {
strcpy (buf, hcd->bus_name);
strcpy (buf, hcd->self.bus_name);
// product description
} else if (id == 2) {
......@@ -406,7 +406,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
// wValue == urb->dev->devaddr
dbg ("%s root hub device address %d",
hcd->bus_name, wValue);
hcd->self.bus_name, wValue);
break;
/* INTERFACE REQUESTS (no defined feature/status flags) */
......@@ -520,7 +520,7 @@ static void rh_report_status (unsigned long ptr)
&& rh_status_urb (hcd, urb) != 0) {
/* another driver snuck in? */
dbg ("%s, can't resubmit roothub status urb?",
hcd->bus_name);
hcd->self.bus_name);
spin_unlock_irqrestore (&hcd_data_lock, flags);
BUG ();
}
......@@ -1051,8 +1051,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
usb_init_bus (&hcd->self);
hcd->self.op = &hcd_operations;
hcd->self.hcpriv = (void *) hcd;
hcd->bus = &hcd->self;
hcd->bus_name = dev->slot_name;
hcd->self.bus_name = dev->slot_name;
hcd->product_desc = dev->name;
INIT_LIST_HEAD (&hcd->dev_list);
......@@ -1089,16 +1088,15 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
hcd = pci_get_drvdata(dev);
if (!hcd)
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 ();
hub = hcd->bus->root_hub;
hub = hcd->self.root_hub;
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 (&hcd->bus->root_hub);
hcd->driver->stop (hcd);
hcd->state = USB_STATE_HALT;
......@@ -1113,10 +1111,9 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
pci_resource_len (dev, hcd->region));
}
usb_deregister_bus (hcd->bus);
usb_deregister_bus (&hcd->self);
if (atomic_read (&hcd->self.refcnt) != 1)
err ("usb_hcd_pci_remove %s, count != 1", hcd->bus_name);
hcd->bus = NULL;
err ("usb_hcd_pci_remove %s, count != 1", hcd->self.bus_name);
hcd->driver->hcd_free (hcd);
}
......@@ -1164,7 +1161,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
int retval;
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);
......@@ -1193,12 +1190,12 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
int retval;
hcd = pci_get_drvdata(dev);
info ("resume %s", hcd->bus_name);
info ("resume %s", hcd->self.bus_name);
/* guard against multiple resumes (APM bug?) */
atomic_inc (&hcd->resume_count);
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;
goto done;
}
......@@ -1215,7 +1212,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
retval = hcd->driver->resume (hcd);
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);
// FIXME: recover, reset etc.
} else {
......@@ -1290,7 +1287,7 @@ static void hc_died (struct usb_hcd *hcd)
list_for_each (urblist, &dev->urb_list) {
urb = list_entry (urblist, struct urb, urb_list);
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)
urb->status = -ESHUTDOWN;
}
......@@ -1534,7 +1531,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
* since we report some queuing/setup errors ourselves
*/
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);
else
status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
......@@ -1686,7 +1683,7 @@ if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
&& HCD_IS_RUNNING (hcd->state)
&& !retval) {
dbg ("%s: wait for giveback urb %p",
hcd->bus_name, urb);
hcd->self.bus_name, urb);
wait_for_completion (&splice.done);
} else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) {
return -EINPROGRESS;
......@@ -1698,7 +1695,7 @@ if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
bye:
if (retval)
dbg ("%s: hcd_unlink_urb fail %d",
hcd ? hcd->bus_name : "(no bus?)",
hcd ? hcd->self.bus_name : "(no bus?)",
retval);
return retval;
}
......@@ -1731,7 +1728,7 @@ static int hcd_free_dev (struct usb_device *udev)
/* device driver problem with refcounts? */
if (!list_empty (&dev->urb_list)) {
dbg ("free busy dev, %s devnum %d (bug!)",
hcd->bus_name, udev->devnum);
hcd->self.bus_name, udev->devnum);
return -EINVAL;
}
......
......@@ -35,10 +35,8 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
/*
* housekeeping
*/
struct usb_bus *bus; /* FIXME only use "self" */
struct usb_bus self; /* hcd is-a bus */
const char *bus_name;
const char *product_desc; /* product/vendor string */
const char *description; /* "ehci-hcd" etc */
......
......@@ -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
* string is a path along hub ports, from the root. Each
* 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).
*/
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,
"%s/%d", pdev->devpath, port + 1);
else /* root == "/", root port 2 == "/2" */
"%s.%d", pdev->devpath, port + 1);
else /* root == "/", root port 2 == "2", port 3 that hub "/2.3" */
len = snprintf (dev->devpath, sizeof dev->devpath,
"/%d", port + 1);
"%d", port + 1);
if (len == sizeof dev->devpath)
warn ("devpath size! usb/%03d/%03d path %s",
dev->bus->busnum, dev->devnum, dev->devpath);
info("new USB device on bus %d path %s, assigned address %d",
dev->bus->busnum, dev->devpath, dev->devnum);
info("new USB device %s-%s, assigned address %d",
dev->bus->bus_name, dev->devpath, dev->devnum);
/* put the device in the global device tree */
dev->dev.parent = &dev->parent->dev;
......
......@@ -2407,56 +2407,6 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
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
* 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)
strcat(buf, tmp);
}
dbg ("%s: %s portroute %s",
ehci->hcd.bus_name, label,
ehci->hcd.self.bus_name, label,
buf);
}
}
......
......@@ -248,7 +248,7 @@ static int ehci_start (struct usb_hcd *hcd)
ehci->tasklet.data = (unsigned long) ehci;
/* 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) {
done2:
ehci_mem_cleanup (ehci);
......@@ -288,8 +288,7 @@ static int ehci_start (struct usb_hcd *hcd)
while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
udelay (100);
ehci_reset (ehci);
// usb_disconnect (udev);
hcd->bus->root_hub = 0;
hcd->self.root_hub = 0;
usb_free_dev (udev);
retval = -ENODEV;
goto done2;
......@@ -304,7 +303,7 @@ static void ehci_stop (struct usb_hcd *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)
ehci_ready (ehci);
......@@ -339,7 +338,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
int ports;
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);
......@@ -356,7 +355,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
if ((temp & PORT_PE) == 0
|| (temp & PORT_OWNER) != 0)
continue;
dbg ("%s: suspend port %d", hcd->bus_name, i);
dbg ("%s: suspend port %d", hcd->self.bus_name, i);
temp |= PORT_SUSPEND;
writel (temp, &ehci->regs->port_status [i]);
}
......@@ -380,7 +379,7 @@ static int ehci_resume (struct usb_hcd *hcd)
int ports;
int i;
dbg ("%s: resume", hcd->bus_name);
dbg ("%s: resume", hcd->self.bus_name);
ports = HCS_N_PORTS (ehci->hcs_params);
......@@ -400,7 +399,7 @@ static int ehci_resume (struct usb_hcd *hcd)
if ((temp & PORT_PE) == 0
|| (temp & PORT_SUSPEND) != 0)
continue;
dbg ("%s: resume port %d", hcd->bus_name, i);
dbg ("%s: resume port %d", hcd->self.bus_name, i);
temp |= PORT_RESUME;
writel (temp, &ehci->regs->port_status [i]);
readl (&ehci->regs->command); /* unblock posted writes */
......@@ -472,7 +471,7 @@ static void ehci_irq (struct usb_hcd *hcd)
/* PCI errors [4.15.2.4] */
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);
// generic layer kills/unlinks all urbs
// then tasklet cleans up the rest
......@@ -547,7 +546,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
unsigned long flags;
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)) {
case PIPE_CONTROL:
......@@ -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 */
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);
for (i = 0; i < 32; i++) {
......
......@@ -41,14 +41,14 @@ static int check_reset_complete (
/* if reset finished and it's still not enabled -- handoff */
if (!(port_status & PORT_PE)) {
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 ?
port_status |= PORT_OWNER;
writel (port_status, &ehci->regs->port_status [index]);
} 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;
}
......@@ -306,11 +306,11 @@ static int ehci_hub_control (
if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
&& PORT_USB11 (temp)) {
dbg ("%s port %d low speed, give to companion",
hcd->bus_name, wIndex + 1);
hcd->self.bus_name, wIndex + 1);
temp |= PORT_OWNER;
} else {
vdbg ("%s port %d reset",
hcd->bus_name, wIndex + 1);
hcd->self.bus_name, wIndex + 1);
temp |= PORT_RESET;
temp &= ~PORT_PE;
......
......@@ -733,7 +733,7 @@ submit_async (
epnum |= 0x10;
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",
qtd, dev ? dev->ep [epnum] : (void *)~0);
......
......@@ -89,7 +89,7 @@ void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
continue;
printed = 1;
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--) {
struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p));
printk (" %p/%08x;", ed, ed->hwINFO);
......@@ -99,7 +99,7 @@ void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
}
if (!printed)
printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n",
label, ohci->hcd.bus_name);
label, ohci->hcd.self.bus_name);
}
#endif
......@@ -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)
{
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
ohci_dump_status (controller);
......
......@@ -379,7 +379,7 @@ static int hc_reset (struct ohci_hcd *ohci)
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
dbg ("USB HC reset_hc %s: ctrl = 0x%x ;",
ohci->hcd.bus_name,
ohci->hcd.self.bus_name,
readl (&ohci->regs->control));
/* Reset USB (needed by some controllers) */
......@@ -449,7 +449,7 @@ static int hc_start (struct ohci_hcd *ohci)
mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
/* 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;
if (!udev) {
ohci->disabled = 1;
......@@ -491,7 +491,7 @@ static void ohci_irq (struct usb_hcd *hcd)
if (ints & OHCI_INTR_UE) {
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
#ifdef DEBUG
......@@ -530,7 +530,7 @@ static void ohci_stop (struct usb_hcd *hcd)
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
dbg ("%s: stop %s controller%s",
hcd->bus_name,
hcd->self.bus_name,
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
ohci->disabled ? " (disabled)" : ""
);
......@@ -571,7 +571,7 @@ ohci_start (struct usb_hcd *hcd)
&& hcd->pdev->device == 0x740c) {
ohci->flags = OHCI_QUIRK_AMD756;
info ("%s: AMD756 erratum 4 workaround",
hcd->bus_name);
hcd->self.bus_name);
}
/* Apple's OHCI driver has a lot of bizarre workarounds
......@@ -581,7 +581,7 @@ ohci_start (struct usb_hcd *hcd)
else if (hcd->pdev->vendor == 0x1045
&& hcd->pdev->device == 0xc861) {
info ("%s: WARNING: OPTi workarounds unavailable",
hcd->bus_name);
hcd->self.bus_name);
}
}
#else
......@@ -601,7 +601,7 @@ ohci_start (struct usb_hcd *hcd)
}
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);
return -EBUSY;
}
......@@ -623,13 +623,13 @@ static int ohci_suspend (struct usb_hcd *hcd, u32 state)
u16 cmd;
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));
return -EIO;
}
/* 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;
/* First stop processing */
......@@ -664,16 +664,16 @@ static int ohci_suspend (struct usb_hcd *hcd, u32 state)
switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
case OHCI_USB_RESET:
dbg ("%s suspend->reset ?", hcd->bus_name);
dbg ("%s suspend->reset ?", hcd->self.bus_name);
break;
case OHCI_USB_RESUME:
dbg ("%s suspend->resume ?", hcd->bus_name);
dbg ("%s suspend->resume ?", hcd->self.bus_name);
break;
case OHCI_USB_OPER:
dbg ("%s suspend->operational ?", hcd->bus_name);
dbg ("%s suspend->operational ?", hcd->self.bus_name);
break;
case OHCI_USB_SUSPEND:
dbg ("%s suspended", hcd->bus_name);
dbg ("%s suspended", hcd->self.bus_name);
break;
}
......@@ -711,8 +711,8 @@ static int hc_restart (struct ohci_hcd *ohci)
ohci->disabled = 1;
ohci->sleeping = 0;
if (ohci->hcd.bus->root_hub)
usb_disconnect (&ohci->hcd.bus->root_hub);
if (ohci->hcd.self.root_hub)
usb_disconnect (&ohci->hcd.self.root_hub);
/* empty the interrupt branches */
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)
ohci->ed_bulktail = NULL;
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;
} else
dbg ("restart %s completed", ohci->hcd.bus_name);
dbg ("restart %s completed", ohci->hcd.self.bus_name);
return 0;
}
......@@ -767,13 +767,13 @@ static int ohci_resume (struct usb_hcd *hcd)
switch (temp) {
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);
break;
case OHCI_USB_SUSPEND: // host 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)
? "host" : "remote");
ohci->hc_control = OHCI_USB_RESUME;
......@@ -786,7 +786,7 @@ static int ohci_resume (struct usb_hcd *hcd)
temp = readl (&ohci->regs->control);
temp = ohci->hc_control & OHCI_CTRL_HCFS;
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;
retval = -EIO;
break;
......@@ -836,7 +836,7 @@ dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled);
break;
default:
warn ("odd PCI resume for %s", hcd->bus_name);
warn ("odd PCI resume for %s", hcd->self.bus_name);
}
return retval;
}
......
......@@ -41,7 +41,7 @@ static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
#define dbg_port(hc,label,num,value) \
dbg ("%s: %s roothub.portstatus [%d] " \
"= 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_OCIC) ? " OCIC" : "", \
(temp & RH_PS_PSSC) ? " PSSC" : "", \
......@@ -71,7 +71,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
ports = roothub_a (ohci) & RH_A_NDP;
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",
readl (&ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */
......
......@@ -2799,6 +2799,7 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io
uhci->bus = bus;
bus->hcpriv = uhci;
bus->bus_name = dev->slot_name;
usb_register_bus(uhci->bus);
......
......@@ -2400,6 +2400,7 @@ static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base)
return NULL;
}
ohci->bus->hcpriv = (void *) ohci;
ohci->bus->bus_name = dev->slot_name;
return ohci;
}
......
......@@ -2977,6 +2977,7 @@ _static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_
s->bus = bus;
bus->hcpriv = s;
bus->bus_name = dev->slot_name;
/* 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 */
......
......@@ -890,7 +890,6 @@ extern int usb_string(struct usb_device *dev, int index,
char *buf, size_t size);
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_make_path(struct usb_device *dev, char *buf, size_t size);
/*
* timeouts, in seconds, used for sending/receiving control messages
......@@ -917,6 +916,7 @@ struct usb_operations;
*/
struct usb_bus {
int busnum; /* Bus number (in order of reg) */
char *bus_name; /* stable id (PCI slot_name etc) */
#ifdef DEVNUM_ROUND_ROBIN
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,
struct usb_interface *interface,
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