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