184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman/*
284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman * drivers/usb/core/endpoint.c
384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman *
484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman
584412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman * (C) Copyright 2002,2004 IBM Corp.
684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman * (C) Copyright 2006 Novell Inc.
784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman *
884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman * Endpoint sysfs stuff
984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman *
1084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman */
1184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
1284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman#include <linux/kernel.h>
137e27780ffdf5fcf8675dfb278ca316a1f2b7e179Sarah Bailey#include <linux/spinlock.h>
145a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
157e27780ffdf5fcf8675dfb278ca316a1f2b7e179Sarah Bailey#include <linux/idr.h>
1684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman#include <linux/usb.h>
1784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman#include "usb.h"
1884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
199bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstruct ep_device {
2084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	struct usb_endpoint_descriptor *desc;
2184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	struct usb_device *udev;
229bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	struct device dev;
2384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman};
249bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman#define to_ep_device(_dev) \
259bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	container_of(_dev, struct ep_device, dev)
2684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
275512966643adb17483efc5f61481a38fc33088bbKay Sieversstruct device_type usb_ep_device_type = {
285512966643adb17483efc5f61481a38fc33088bbKay Sievers	.name =		"usb_endpoint",
295512966643adb17483efc5f61481a38fc33088bbKay Sievers};
305512966643adb17483efc5f61481a38fc33088bbKay Sievers
3184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartmanstruct ep_attribute {
3284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	struct attribute attr;
3384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	ssize_t (*show)(struct usb_device *,
3484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman			struct usb_endpoint_descriptor *, char *);
3584412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman};
3684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman#define to_ep_attribute(_attr) \
3784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	container_of(_attr, struct ep_attribute, attr)
3884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
3984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman#define usb_ep_attr(field, format_string)			\
409bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic ssize_t show_ep_##field(struct device *dev,		\
419bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman			       struct device_attribute *attr,	\
429bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman			       char *buf)			\
4384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman{								\
449bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	struct ep_device *ep = to_ep_device(dev);		\
459bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	return sprintf(buf, format_string, ep->desc->field);	\
4684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman}								\
479bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic DEVICE_ATTR(field, S_IRUGO, show_ep_##field, NULL);
4884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
4984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartmanusb_ep_attr(bLength, "%02x\n")
5084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartmanusb_ep_attr(bEndpointAddress, "%02x\n")
5184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartmanusb_ep_attr(bmAttributes, "%02x\n")
5284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartmanusb_ep_attr(bInterval, "%02x\n")
5384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
549bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic ssize_t show_ep_wMaxPacketSize(struct device *dev,
559bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman				      struct device_attribute *attr, char *buf)
5684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman{
579bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	struct ep_device *ep = to_ep_device(dev);
5884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	return sprintf(buf, "%04x\n",
5929cc88979a8818cd8c5019426e945aed118b400eKuninori Morimoto		        usb_endpoint_maxp(ep->desc) & 0x07ff);
6084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman}
619bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL);
6284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
639bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic ssize_t show_ep_type(struct device *dev, struct device_attribute *attr,
649bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman			    char *buf)
6584412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman{
669bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	struct ep_device *ep = to_ep_device(dev);
6784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	char *type = "unknown";
6884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
692e0fe709687470637a0709b930ccc9e993d2dad5Julia Lawall	switch (usb_endpoint_type(ep->desc)) {
7084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	case USB_ENDPOINT_XFER_CONTROL:
7184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		type = "Control";
7284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		break;
7384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	case USB_ENDPOINT_XFER_ISOC:
7484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		type = "Isoc";
7584412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		break;
7684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	case USB_ENDPOINT_XFER_BULK:
7784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		type = "Bulk";
7884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		break;
7984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	case USB_ENDPOINT_XFER_INT:
8084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		type = "Interrupt";
8184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		break;
8284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	}
8384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	return sprintf(buf, "%s\n", type);
8484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman}
859bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic DEVICE_ATTR(type, S_IRUGO, show_ep_type, NULL);
8684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
879bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic ssize_t show_ep_interval(struct device *dev,
889bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman				struct device_attribute *attr, char *buf)
8984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman{
909bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	struct ep_device *ep = to_ep_device(dev);
9184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	char unit;
9284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	unsigned interval = 0;
9384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	unsigned in;
9484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
959bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	in = (ep->desc->bEndpointAddress & USB_DIR_IN);
9684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
972e0fe709687470637a0709b930ccc9e993d2dad5Julia Lawall	switch (usb_endpoint_type(ep->desc)) {
9884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	case USB_ENDPOINT_XFER_CONTROL:
99cd62aced31dee9a9a8e63da7bd564911891b3665csanchez@neurowork.net		if (ep->udev->speed == USB_SPEED_HIGH)
100cd62aced31dee9a9a8e63da7bd564911891b3665csanchez@neurowork.net			/* uframes per NAK */
1019bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman			interval = ep->desc->bInterval;
10284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		break;
103cd62aced31dee9a9a8e63da7bd564911891b3665csanchez@neurowork.net
10484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	case USB_ENDPOINT_XFER_ISOC:
1059bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman		interval = 1 << (ep->desc->bInterval - 1);
10684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		break;
107cd62aced31dee9a9a8e63da7bd564911891b3665csanchez@neurowork.net
10884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	case USB_ENDPOINT_XFER_BULK:
109cd62aced31dee9a9a8e63da7bd564911891b3665csanchez@neurowork.net		if (ep->udev->speed == USB_SPEED_HIGH && !in)
110cd62aced31dee9a9a8e63da7bd564911891b3665csanchez@neurowork.net			/* uframes per NAK */
1119bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman			interval = ep->desc->bInterval;
11284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		break;
113cd62aced31dee9a9a8e63da7bd564911891b3665csanchez@neurowork.net
11484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	case USB_ENDPOINT_XFER_INT:
1159bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman		if (ep->udev->speed == USB_SPEED_HIGH)
1169bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman			interval = 1 << (ep->desc->bInterval - 1);
11784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		else
1189bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman			interval = ep->desc->bInterval;
11984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		break;
12084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	}
1219bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
12284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	if (interval % 1000)
12384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		unit = 'u';
12484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	else {
12584412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		unit = 'm';
12684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		interval /= 1000;
12784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	}
12884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
12984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	return sprintf(buf, "%d%cs\n", interval, unit);
13084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman}
1319bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic DEVICE_ATTR(interval, S_IRUGO, show_ep_interval, NULL);
13284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
1339bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic ssize_t show_ep_direction(struct device *dev,
1349bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman				 struct device_attribute *attr, char *buf)
13584412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman{
1369bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	struct ep_device *ep = to_ep_device(dev);
13784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	char *direction;
13884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
1392e0fe709687470637a0709b930ccc9e993d2dad5Julia Lawall	if (usb_endpoint_xfer_control(ep->desc))
14084412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		direction = "both";
1412e0fe709687470637a0709b930ccc9e993d2dad5Julia Lawall	else if (usb_endpoint_dir_in(ep->desc))
14284412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		direction = "in";
14384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	else
14484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman		direction = "out";
14584412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	return sprintf(buf, "%s\n", direction);
14684412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman}
1479bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic DEVICE_ATTR(direction, S_IRUGO, show_ep_direction, NULL);
1489bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman
1499bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic struct attribute *ep_dev_attrs[] = {
1509bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	&dev_attr_bLength.attr,
1519bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	&dev_attr_bEndpointAddress.attr,
1529bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	&dev_attr_bmAttributes.attr,
1539bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	&dev_attr_bInterval.attr,
1549bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	&dev_attr_wMaxPacketSize.attr,
1559bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	&dev_attr_interval.attr,
1569bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	&dev_attr_type.attr,
1579bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	&dev_attr_direction.attr,
15884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	NULL,
15984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman};
1609bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic struct attribute_group ep_dev_attr_grp = {
1619bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	.attrs = ep_dev_attrs,
1629bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman};
163a4dbd6740df0872cdf0a86841f75beec8381964dDavid Brownellstatic const struct attribute_group *ep_dev_groups[] = {
1642e5f10e4f0a9649186d8a8c793822b2e0dae8373Alan Stern	&ep_dev_attr_grp,
1652e5f10e4f0a9649186d8a8c793822b2e0dae8373Alan Stern	NULL
1662e5f10e4f0a9649186d8a8c793822b2e0dae8373Alan Stern};
16784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
1689bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartmanstatic void ep_device_release(struct device *dev)
1699bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman{
1709bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	struct ep_device *ep_dev = to_ep_device(dev);
17184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
1729bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	kfree(ep_dev);
1739bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman}
17484412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
1753b23dd6f8a718e5339de4f7d86ce76a078b5f771Alan Sternint usb_create_ep_devs(struct device *parent,
1761b21d5e166e104f8914441ef52e2cd50ce65b479Greg Kroah-Hartman			struct usb_host_endpoint *endpoint,
1771b21d5e166e104f8914441ef52e2cd50ce65b479Greg Kroah-Hartman			struct usb_device *udev)
17884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman{
1799bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	struct ep_device *ep_dev;
1809bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	int retval;
1819bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman
1829bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
1839bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	if (!ep_dev) {
1849bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman		retval = -ENOMEM;
1855512966643adb17483efc5f61481a38fc33088bbKay Sievers		goto exit;
1867e27780ffdf5fcf8675dfb278ca316a1f2b7e179Sarah Bailey	}
18784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
1889bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	ep_dev->desc = &endpoint->desc;
1899bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	ep_dev->udev = udev;
1902e5f10e4f0a9649186d8a8c793822b2e0dae8373Alan Stern	ep_dev->dev.groups = ep_dev_groups;
1915512966643adb17483efc5f61481a38fc33088bbKay Sievers	ep_dev->dev.type = &usb_ep_device_type;
1929bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	ep_dev->dev.parent = parent;
1939bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	ep_dev->dev.release = ep_device_release;
1945512966643adb17483efc5f61481a38fc33088bbKay Sievers	dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
19584412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
1969bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	retval = device_register(&ep_dev->dev);
1979bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman	if (retval)
1985512966643adb17483efc5f61481a38fc33088bbKay Sievers		goto error_register;
1999bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman
200956227120f2e8eed8ca459879d7eafee78591cc1Peter Chen	device_enable_async_suspend(&ep_dev->dev);
201d5477c11111467e19787f00d3cab20fb48c2699eAlan Stern	endpoint->ep_dev = ep_dev;
2021b21d5e166e104f8914441ef52e2cd50ce65b479Greg Kroah-Hartman	return retval;
2031b21d5e166e104f8914441ef52e2cd50ce65b479Greg Kroah-Hartman
204d5477c11111467e19787f00d3cab20fb48c2699eAlan Sternerror_register:
2057b3a766c7b9bce07875098cb68642df2b8f0b152Rahul Ruikar	put_device(&ep_dev->dev);
206d5477c11111467e19787f00d3cab20fb48c2699eAlan Sternexit:
2071b21d5e166e104f8914441ef52e2cd50ce65b479Greg Kroah-Hartman	return retval;
20884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman}
20984412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
2103b23dd6f8a718e5339de4f7d86ce76a078b5f771Alan Sternvoid usb_remove_ep_devs(struct usb_host_endpoint *endpoint)
21184412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman{
2127e27780ffdf5fcf8675dfb278ca316a1f2b7e179Sarah Bailey	struct ep_device *ep_dev = endpoint->ep_dev;
21384412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman
2147e27780ffdf5fcf8675dfb278ca316a1f2b7e179Sarah Bailey	if (ep_dev) {
2157e27780ffdf5fcf8675dfb278ca316a1f2b7e179Sarah Bailey		device_unregister(&ep_dev->dev);
2169bde7497e0b54178c317fac47a18be7f948dd471Greg Kroah-Hartman		endpoint->ep_dev = NULL;
21784412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman	}
21884412f6291b50690febd81899e46f0f0ef7a13e0Greg Kroah-Hartman}
219