Re: [RFC PATCH 02/15] usbcore: introduce usb_domain for tracking port-connector relationships

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <dan.j.williams@xxxxxxxxx>
> ---
>  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 <dan.j.williams@xxxxxxxxx>
> + *
> + * 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux