On Thu, Oct 24, 2013 at 12:35:35AM -0700, Dan Williams wrote:
> Platform firmware identifies ports that share a connector.  This
> information is relevant for port power control since we do not want a
> device to reconnect on its peer port in a connector when pm has decided
> to power-off its currently connected port.

I think I know what you mean by the above paragraph, but I'm not quite
sure.  Do you mean that if you power off a SuperSpeed port, the USB 3.0
device will attempt to reconnect to its shared USB 2.0 port?  Or do you
mean something different?

Sarah Sharp

> In the case of xhci, peer ports are attached through separate root hubs
> (and zero or more integrated hubs).  'struct usb_domain' is introduced
> so that each root hub 'hcd' can register its ports to a unified
> 'platform' domain where connector relationships can be evaluated.  A
> connector is formed when two ports are registered with identical 'match
> data'.  ACPI defines connectors by specifying a common 'group token' and
> 'group position' property for the port [1].  Outside of this match data
> there is nothing firmware specific about this implementation, hence the
> creation of the common rountines in usb-platform.c.
> 
> [1] ACPI 5.0 Section 6.1.8 _PLD (Physical Device Location)
> 
> Signed-off-by: Dan Williams <[email protected]>
> ---
>  drivers/usb/core/Kconfig        |    4 +
>  drivers/usb/core/Makefile       |    1 
>  drivers/usb/core/hcd-pci.c      |   17 +++-
>  drivers/usb/core/hcd.c          |    2 
>  drivers/usb/core/hub.h          |    8 ++
>  drivers/usb/core/usb-acpi.c     |   69 +++++++++++++++--
>  drivers/usb/core/usb-platform.c |  162 
> +++++++++++++++++++++++++++++++++++++++
>  drivers/usb/core/usb-platform.h |   44 +++++++++++
>  drivers/usb/host/xhci-pci.c     |   16 +++-
>  include/linux/usb/hcd.h         |    9 ++
>  10 files changed, 320 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/usb/core/usb-platform.c
>  create mode 100644 drivers/usb/core/usb-platform.h
> 
> diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
> index db535b0aa172..e439a14b0210 100644
> --- a/drivers/usb/core/Kconfig
> +++ b/drivers/usb/core/Kconfig
> @@ -89,3 +89,7 @@ config USB_OTG_BLACKLIST_HUB
>         and software costs by not supporting external hubs.  So
>         are "Embedded Hosts" that don't offer OTG support.
>  
> +config USB_PLATFORM
> +     bool
> +     default y if ACPI
> +
> diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
> index 5e847ad2f58a..b534b9b28c69 100644
> --- a/drivers/usb/core/Makefile
> +++ b/drivers/usb/core/Makefile
> @@ -11,5 +11,6 @@ usbcore-y += port.o
>  
>  usbcore-$(CONFIG_PCI)                += hcd-pci.o
>  usbcore-$(CONFIG_ACPI)               += usb-acpi.o
> +usbcore-$(CONFIG_USB_PLATFORM)  += usb-platform.o
>  
>  obj-$(CONFIG_USB)            += usbcore.o
> diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
> index dfe9d0f22978..542dc0f6ef74 100644
> --- a/drivers/usb/core/hcd-pci.c
> +++ b/drivers/usb/core/hcd-pci.c
> @@ -161,20 +161,23 @@ static void ehci_wait_for_companions(struct pci_dev 
> *pdev, struct usb_hcd *hcd,
>  /* always called with process context; sleeping is OK */
>  
>  /**
> - * usb_hcd_pci_probe - initialize PCI-based HCDs
> + * usb_hcd_pci_probe_domain - initialize PCI-based HCDs
>   * @dev: USB Host Controller being probed
>   * @id: pci hotplug id connecting controller to HCD framework
> + * @domain: if this hcd coordinates port activity with another hcd from pdev
>   * Context: !in_interrupt()
>   *
>   * Allocates basic PCI resources for this USB host controller, and
>   * then invokes the start() method for the HCD associated with it
>   * through the hotplug entry's driver_data.
>   *
> - * Store this function in the HCD's struct pci_driver as probe().
> + * Note the usb_domain is not to be confused with companion controllers which
> + * multiplex the same phy with multiple controllers.
>   *
>   * Return: 0 if successful.
>   */
> -int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
> +int usb_hcd_pci_probe_domain(struct pci_dev *dev, struct usb_domain *udom,
> +                          const struct pci_device_id *id)
>  {
>       struct hc_driver        *driver;
>       struct usb_hcd          *hcd;
> @@ -215,6 +218,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct 
> pci_device_id *id)
>               goto disable_pci;
>       }
>  
> +     hcd->domain = usb_get_domain(udom);
>       hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) &&
>                       driver->flags & (HCD_USB11 | HCD_USB3)) ? 1 : 0;
>  
> @@ -301,6 +305,13 @@ disable_pci:
>       dev_err(&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
>       return retval;
>  }
> +EXPORT_SYMBOL_GPL(usb_hcd_pci_probe_domain);
> +
> +
> +int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
> +{
> +     return usb_hcd_pci_probe_domain(dev, NULL, id);
> +}
>  EXPORT_SYMBOL_GPL(usb_hcd_pci_probe);
>  
>  
> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
> index 6bffb8c87bc9..892574f439a4 100644
> --- a/drivers/usb/core/hcd.c
> +++ b/drivers/usb/core/hcd.c
> @@ -2505,6 +2505,8 @@ static void hcd_release (struct kref *kref)
>               kfree(hcd->bandwidth_mutex);
>       else
>               hcd->shared_hcd->shared_hcd = NULL;
> +
> +     usb_put_domain(hcd->domain);
>       kfree(hcd);
>  }
>  
> diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
> index 4e4790dea343..9ea075d1b7a3 100644
> --- a/drivers/usb/core/hub.h
> +++ b/drivers/usb/core/hub.h
> @@ -19,6 +19,9 @@
>   * for more details.
>   */
>  
> +#ifndef __USB_HUB_H__
> +#define __USB_HUB_H__
> +
>  #include <linux/usb.h>
>  #include <linux/usb/ch11.h>
>  #include <linux/usb/hcd.h>
> @@ -80,6 +83,8 @@ struct usb_hub {
>   * struct usb port - kernel's representation of a usb port
>   * @child: usb device attatched to the port
>   * @dev: generic device interface
> + * @node: peer ports in a given connector
> + * @connector: parent connector for this port
>   * @port_owner: port's owner
>   * @connect_type: port's connect type
>   * @portnum: port index num based one
> @@ -88,6 +93,8 @@ struct usb_hub {
>   */
>  struct usb_port {
>       struct usb_device *child;
> +     struct list_head node;
> +     struct usb_connector *connector;
>       struct device dev;
>       struct dev_state *port_owner;
>       enum usb_port_connect_type connect_type;
> @@ -123,3 +130,4 @@ static inline int hub_port_debounce_be_stable(struct 
> usb_hub *hub,
>       return hub_port_debounce(hub, port1, false);
>  }
>  
> +#endif /* __USB_HUB_H__ */
> diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
> index 255c14464bf2..fab4a8288803 100644
> --- a/drivers/usb/core/usb-acpi.c
> +++ b/drivers/usb/core/usb-acpi.c
> @@ -18,7 +18,8 @@
>  #include <linux/usb/hcd.h>
>  #include <acpi/acpi_bus.h>
>  
> -#include "usb.h"
> +#include "hub.h"
> +#include "usb-platform.h"
>  
>  /**
>   * usb_acpi_power_manageable - check whether usb port has
> @@ -42,6 +43,51 @@ bool usb_acpi_power_manageable(struct usb_device *hdev, 
> int index)
>  }
>  EXPORT_SYMBOL_GPL(usb_acpi_power_manageable);
>  
> +struct usb_acpi_pair_data {
> +     u8 group_token;
> +     u8 group_position;
> +};
> +
> +static void usb_acpi_pair_port(struct usb_device *hdev, acpi_handle *handle,
> +                            int port1, struct acpi_pld_info *pld)
> +{
> +     struct usb_acpi_pair_data data;
> +     struct usb_port *port_dev;
> +     struct usb_hcd *hcd;
> +     struct usb_hub *hub;
> +
> +     if (!pld)
> +             return;
> +
> +     hub = usb_hub_to_struct_hub(hdev);
> +     if (!hub)
> +             return;
> +
> +     port_dev = hub->ports[port1 - 1];
> +     hcd = bus_to_hcd(hdev->bus);
> +
> +     memset(&data, 0, sizeof(data));
> +     data.group_token = pld->group_token;
> +     data.group_position = pld->group_position;
> +     usb_domain_pair_port(hcd->domain, port_dev, &data, sizeof(data));
> +}
> +
> +static void usb_acpi_cleanup(struct device *dev)
> +{
> +     struct usb_port *port_dev;
> +     struct usb_device *hdev;
> +     struct usb_hcd *hcd;
> +
> +     if (!is_usb_port(dev))
> +             return;
> +
> +     hdev = to_usb_device(dev->parent->parent);
> +     port_dev = to_usb_port(dev);
> +     hcd = bus_to_hcd(hdev->bus);
> +
> +     usb_domain_remove_port(hcd->domain, port_dev);
> +}
> +
>  /**
>   * usb_acpi_set_power_state - control usb port's power via acpi power
>   * resource
> @@ -83,12 +129,11 @@ int usb_acpi_set_power_state(struct usb_device *hdev, 
> int index, bool enable)
>  EXPORT_SYMBOL_GPL(usb_acpi_set_power_state);
>  
>  static int usb_acpi_check_port_connect_type(struct usb_device *hdev,
> -     acpi_handle handle, int port1)
> +     acpi_handle handle, int port1, struct acpi_pld_info *pld)
>  {
>       acpi_status status;
>       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>       union acpi_object *upc;
> -     struct acpi_pld_info *pld;
>       int ret = 0;
>  
>       /*
> @@ -99,8 +144,7 @@ static int usb_acpi_check_port_connect_type(struct 
> usb_device *hdev,
>        * a usb device is directly hard-wired to the port. If no visible and
>        * no connectable, the port would be not used.
>        */
> -     status = acpi_get_physical_device_location(handle, &pld);
> -     if (ACPI_FAILURE(status))
> +     if (!pld)
>               return -ENODEV;
>  
>       status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer);
> @@ -122,7 +166,6 @@ static int usb_acpi_check_port_connect_type(struct 
> usb_device *hdev,
>               usb_set_hub_port_connect_type(hdev, port1, USB_PORT_NOT_USED);
>  
>  out:
> -     ACPI_FREE(pld);
>       kfree(upc);
>       return ret;
>  }
> @@ -179,6 +222,9 @@ static int usb_acpi_find_device(struct device *dev, 
> acpi_handle *handle)
>                       return -ENODEV;
>               return 0;
>       } else if (is_usb_port(dev)) {
> +             struct acpi_pld_info *pld;
> +             acpi_status status;
> +
>               sscanf(dev_name(dev), "port%d", &port_num);
>               /* Get the struct usb_device point of port's hub */
>               udev = to_usb_device(dev->parent->parent);
> @@ -209,7 +255,15 @@ static int usb_acpi_find_device(struct device *dev, 
> acpi_handle *handle)
>                       if (!*handle)
>                               return -ENODEV;
>               }
> -             usb_acpi_check_port_connect_type(udev, *handle, port_num);
> +
> +             status = acpi_get_physical_device_location(*handle, &pld);
> +             if (ACPI_FAILURE(status))
> +                     pld = NULL;
> +
> +             usb_acpi_check_port_connect_type(udev, *handle, port_num, pld);
> +             usb_acpi_pair_port(udev, *handle, port_num, pld);
> +
> +             ACPI_FREE(pld);
>       } else
>               return -ENODEV;
>  
> @@ -225,6 +279,7 @@ static struct acpi_bus_type usb_acpi_bus = {
>       .name = "USB",
>       .match = usb_acpi_bus_match,
>       .find_device = usb_acpi_find_device,
> +     .cleanup = usb_acpi_cleanup,
>  };
>  
>  int usb_acpi_register(void)
> diff --git a/drivers/usb/core/usb-platform.c b/drivers/usb/core/usb-platform.c
> new file mode 100644
> index 000000000000..476ac3fa47c2
> --- /dev/null
> +++ b/drivers/usb/core/usb-platform.c
> @@ -0,0 +1,162 @@
> +/*
> + * USB support for platform defined connectors / port-pairings
> + *
> + * Copyright 2013 Intel Corporation <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation, version 2.
> + *
> + */
> +#include <linux/device.h>
> +#include "usb-platform.h"
> +
> +static void domain_release(struct kref *kref)
> +{
> +     struct usb_domain *udom = container_of(kref, struct usb_domain, kref);
> +
> +     WARN(!list_empty(&udom->connectors), "connectors list not empty\n");
> +
> +     kfree(udom);
> +}
> +
> +void usb_put_domain(struct usb_domain *udom)
> +{
> +     if (udom)
> +             kref_put(&udom->kref, domain_release);
> +}
> +EXPORT_SYMBOL_GPL(usb_put_domain);
> +
> +struct usb_domain *usb_get_domain(struct usb_domain *udom)
> +{
> +     if (udom)
> +             kref_get(&udom->kref);
> +     return udom;
> +}
> +EXPORT_SYMBOL_GPL(usb_get_domain);
> +
> +struct usb_domain *usb_create_domain(void)
> +{
> +     struct usb_domain *udom = kmalloc(sizeof(*udom), GFP_KERNEL);
> +
> +     if (!udom)
> +             return NULL;
> +
> +     INIT_LIST_HEAD(&udom->connectors);
> +     mutex_init(&udom->lock);
> +     kref_init(&udom->kref);
> +     return udom;
> +}
> +EXPORT_SYMBOL_GPL(usb_create_domain);
> +
> +static struct usb_connector *create_connector(struct usb_domain *udom,
> +                                           struct usb_port *port_dev,
> +                                           size_t pair_data)
> +{
> +     struct usb_connector *uconn;
> +
> +     uconn = kzalloc(sizeof(*uconn) + pair_data, GFP_KERNEL);
> +     if (!uconn)
> +             return NULL;
> +
> +     uconn->connect_type = port_dev->connect_type;
> +     INIT_LIST_HEAD(&uconn->ports);
> +     INIT_LIST_HEAD(&uconn->node);
> +     uconn->domain = udom;
> +
> +     return uconn;
> +}
> +
> +static void check_connector(struct usb_connector *uconn,
> +                         struct usb_port *port_dev)
> +{
> +     if (uconn->connect_type != port_dev->connect_type) {
> +             struct device *intf_dev = port_dev->dev.parent;
> +
> +             dev_info(intf_dev, "port%d inconsistent connect types %d:%d",
> +                      port_dev->portnum, port_dev->connect_type,
> +                      uconn->connect_type);
> +             list_for_each_entry(port_dev, &uconn->ports, node)
> +                     port_dev->connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
> +             uconn->connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
> +     }
> +}
> +
> +static void add_port_connector(struct usb_port *port_dev,
> +                            struct usb_connector *uconn)
> +{
> +     list_add(&port_dev->node, &uconn->ports);
> +     port_dev->connector = uconn;
> +     check_connector(uconn, port_dev);
> +}
> +
> +static void remove_port_connector(struct usb_port *port_dev)
> +{
> +     list_del_init(&port_dev->node);
> +     port_dev->connector = NULL;
> +}
> +
> +int usb_domain_pair_port(struct usb_domain *udom, struct usb_port *port_dev,
> +                      void *data, size_t size)
> +{
> +     struct usb_connector *uconn;
> +     int rc = -ENODEV;
> +
> +     if (!udom)
> +             return 0;
> +
> +     mutex_lock(&udom->lock);
> +     list_for_each_entry(uconn, &udom->connectors, node) {
> +             if (memcmp(data, uconn->pair_data, size) != 0)
> +                     continue;
> +             add_port_connector(port_dev, uconn);
> +             port_dev = NULL;
> +             break;
> +     }
> +     while (port_dev) {
> +             uconn = create_connector(udom, port_dev, size);
> +             if (!uconn) {
> +                     rc = -ENOMEM;
> +                     break;
> +             }
> +             usb_get_domain(udom);
> +             memcpy(uconn->pair_data, data, size);
> +             list_add(&uconn->node, &udom->connectors);
> +             add_port_connector(port_dev, uconn);
> +             break;
> +     }
> +     mutex_unlock(&udom->lock);
> +
> +     return rc;
> +}
> +
> +void usb_domain_remove_port(struct usb_domain *udom, struct usb_port 
> *port_dev)
> +{
> +     struct usb_connector *uconn;
> +
> +     if (!udom)
> +             return;
> +
> +     usb_get_domain(udom);
> +     mutex_lock(&udom->lock);
> +     list_for_each_entry(uconn, &udom->connectors, node) {
> +             struct usb_port *p;
> +
> +             list_for_each_entry(p, &uconn->ports, node)
> +                     if (p == port_dev) {
> +                             remove_port_connector(port_dev);
> +                             break;
> +                     }
> +
> +             if (!list_empty(&uconn->ports))
> +                     continue;
> +
> +             /* connector is empty, drop it from the domain */
> +             list_del(&uconn->node);
> +             usb_put_domain(udom);
> +             kfree(uconn);
> +             break;
> +     }
> +     mutex_unlock(&udom->lock);
> +     usb_put_domain(udom);
> +}
> diff --git a/drivers/usb/core/usb-platform.h b/drivers/usb/core/usb-platform.h
> new file mode 100644
> index 000000000000..768bc1d4c831
> --- /dev/null
> +++ b/drivers/usb/core/usb-platform.h
> @@ -0,0 +1,44 @@
> +#include <linux/mutex.h>
> +#include <linux/list.h>
> +#include <linux/kref.h>
> +#include <linux/usb.h>
> +
> +#include "hub.h"
> +
> +/**
> + * struct usb_domain - track pair ports by connector in this domain
> + * @connectors: list of struct usb_connector instances
> + * @lock: lock manipulation of 'connectors'
> + * @kref: ref count domain users
> + *
> + * Platform data describes the topology of the domain.  For example,
> + * ACPI may specify that port1 on hcd1 is a peer with port1 on hcd2
> + * where hcd1,2 share a common controller (as is the case with XHCI).
> + * Firmware stashes port to 'connector' relationships in this structure
> + * when it binds to the port devices.  (See: struct usb_connector)
> + */
> +struct usb_domain {
> +     struct list_head connectors;
> +     struct mutex lock;
> +     struct kref kref;
> +};
> +
> +/**
> + * struct usb_connector - platform defined container of one or more ports
> + * @ports: platform defined ports that share this same connector
> + * @node: sibling connectors in the struct usb_domain
> + * @connect_type: unified connection type defined by the platform
> + * @domain: parent domain for these connectors
> + * @pair_data: opaque buffer for storing platform-specific port-pairing data
> + */
> +struct usb_connector {
> +     struct list_head ports;
> +     struct list_head node;
> +     enum usb_port_connect_type connect_type;
> +     struct usb_domain *domain;
> +     u8 pair_data[0];
> +};
> +
> +int usb_domain_pair_port(struct usb_domain *udom, struct usb_port *port_dev,
> +                      void *data, size_t size);
> +void usb_domain_remove_port(struct usb_domain *udom, struct usb_port 
> *port_dev);
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index b8dffd59eb25..eb8991ec1316 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -178,6 +178,11 @@ static int xhci_pci_probe(struct pci_dev *dev, const 
> struct pci_device_id *id)
>       struct xhci_hcd *xhci;
>       struct hc_driver *driver;
>       struct usb_hcd *hcd;
> +     struct usb_domain *udom;
> +
> +     udom = usb_create_domain();
> +     if (!udom)
> +             return -ENOMEM;
>  
>       driver = (struct hc_driver *)id->driver_data;
>       /* Register the USB 2.0 roothub.
> @@ -186,10 +191,10 @@ static int xhci_pci_probe(struct pci_dev *dev, const 
> struct pci_device_id *id)
>        * to say USB 2.0, but I'm not sure what the implications would be in
>        * the other parts of the HCD code.
>        */
> -     retval = usb_hcd_pci_probe(dev, id);
> +     retval = usb_hcd_pci_probe_domain(dev, udom, id);
>  
>       if (retval)
> -             return retval;
> +             goto put_domain;
>  
>       /* USB 2.0 roothub is stored in the PCI device now. */
>       hcd = dev_get_drvdata(&dev->dev);
> @@ -200,6 +205,7 @@ static int xhci_pci_probe(struct pci_dev *dev, const 
> struct pci_device_id *id)
>               retval = -ENOMEM;
>               goto dealloc_usb2_hcd;
>       }
> +     xhci->shared_hcd->domain = usb_get_domain(udom);
>  
>       /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset)
>        * is called by usb_add_hcd().
> @@ -218,12 +224,18 @@ static int xhci_pci_probe(struct pci_dev *dev, const 
> struct pci_device_id *id)
>       if (xhci->quirks & XHCI_LPM_SUPPORT)
>               hcd_to_bus(xhci->shared_hcd)->root_hub->lpm_capable = 1;
>  
> +     /* now only the hcd(s) pin the domain */
> +     usb_put_domain(udom);
> +
>       return 0;
>  
>  put_usb3_hcd:
>       usb_put_hcd(xhci->shared_hcd);
>  dealloc_usb2_hcd:
>       usb_hcd_pci_remove(dev);
> +put_domain:
> +     usb_put_domain(udom);
> +
>       return retval;
>  }
>  
> diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
> index b8aba196f7f1..33e45e9ec81b 100644
> --- a/include/linux/usb/hcd.h
> +++ b/include/linux/usb/hcd.h
> @@ -76,6 +76,7 @@ struct giveback_urb_bh {
>       struct usb_host_endpoint *completing_ep;
>  };
>  
> +struct usb_domain;
>  struct usb_hcd {
>  
>       /*
> @@ -83,6 +84,7 @@ struct usb_hcd {
>        */
>       struct usb_bus          self;           /* hcd is-a bus */
>       struct kref             kref;           /* reference counter */
> +     struct usb_domain       *domain;        /* platform port assocs */
>  
>       const char              *product_desc;  /* product/vendor string */
>       int                     speed;          /* Speed for this roothub.
> @@ -412,6 +414,10 @@ extern int usb_hcd_alloc_bandwidth(struct usb_device 
> *udev,
>               struct usb_host_interface *new_alt);
>  extern int usb_hcd_get_frame_number(struct usb_device *udev);
>  
> +extern struct usb_domain *usb_create_domain(void);
> +extern struct usb_domain *usb_get_domain(struct usb_domain *udom);
> +extern void usb_put_domain(struct usb_domain *udom);
> +
>  extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
>               struct device *dev, const char *bus_name);
>  extern struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
> @@ -433,6 +439,9 @@ struct pci_dev;
>  struct pci_device_id;
>  extern int usb_hcd_pci_probe(struct pci_dev *dev,
>                               const struct pci_device_id *id);
> +extern int usb_hcd_pci_probe_domain(struct pci_dev *dev,
> +                                 struct usb_domain *udom,
> +                                 const struct pci_device_id *id);
>  extern void usb_hcd_pci_remove(struct pci_dev *dev);
>  extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
>  
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to