usb: convert endpoint devices to bus-less childs of the usb interface

The endpoint devices look like simple attribute groups now, and no longer
like devices with a specific subsystem. They will also no longer emit uevents.

It also removes the device node requests for endpoint devices, which are not
implemented for now.

Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index c115eed..77de8d6 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -154,16 +154,11 @@
 static int usb_probe_device(struct device *dev)
 {
 	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
-	struct usb_device *udev;
+	struct usb_device *udev = to_usb_device(dev);
 	int error = -ENODEV;
 
 	dev_dbg(dev, "%s\n", __func__);
 
-	if (!is_usb_device(dev))	/* Sanity check */
-		return error;
-
-	udev = to_usb_device(dev);
-
 	/* TODO: Add real matching code */
 
 	/* The device should always appear to be in use
@@ -203,18 +198,13 @@
 static int usb_probe_interface(struct device *dev)
 {
 	struct usb_driver *driver = to_usb_driver(dev->driver);
-	struct usb_interface *intf;
-	struct usb_device *udev;
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_device *udev = interface_to_usbdev(intf);
 	const struct usb_device_id *id;
 	int error = -ENODEV;
 
 	dev_dbg(dev, "%s\n", __func__);
 
-	if (is_usb_device(dev))		/* Sanity check */
-		return error;
-
-	intf = to_usb_interface(dev);
-	udev = interface_to_usbdev(intf);
 	intf->needs_binding = 0;
 
 	if (udev->authorized == 0) {
@@ -593,7 +583,7 @@
 		/* TODO: Add real matching code */
 		return 1;
 
-	} else {
+	} else if (is_usb_interface(dev)) {
 		struct usb_interface *intf;
 		struct usb_driver *usb_drv;
 		const struct usb_device_id *id;
@@ -625,11 +615,14 @@
 	/* driver is often null here; dev_dbg() would oops */
 	pr_debug("usb %s: uevent\n", dev_name(dev));
 
-	if (is_usb_device(dev))
+	if (is_usb_device(dev)) {
 		usb_dev = to_usb_device(dev);
-	else {
+	} else if (is_usb_interface(dev)) {
 		struct usb_interface *intf = to_usb_interface(dev);
+
 		usb_dev = interface_to_usbdev(intf);
+	} else {
+		return 0;
 	}
 
 	if (usb_dev->devnum < 0) {
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 40dee2a..bc39fc4 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -15,19 +15,18 @@
 #include <linux/usb.h>
 #include "usb.h"
 
-#define MAX_ENDPOINT_MINORS (64*128*32)
-static int usb_endpoint_major;
-static DEFINE_IDR(endpoint_idr);
-
 struct ep_device {
 	struct usb_endpoint_descriptor *desc;
 	struct usb_device *udev;
 	struct device dev;
-	int minor;
 };
 #define to_ep_device(_dev) \
 	container_of(_dev, struct ep_device, dev)
 
+struct device_type usb_ep_device_type = {
+	.name =		"usb_endpoint",
+};
+
 struct ep_attribute {
 	struct attribute attr;
 	ssize_t (*show)(struct usb_device *,
@@ -160,118 +159,10 @@
 	NULL
 };
 
-static int usb_endpoint_major_init(void)
-{
-	dev_t dev;
-	int error;
-
-	error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS,
-				    "usb_endpoint");
-	if (error) {
-		printk(KERN_ERR "Unable to get a dynamic major for "
-		       "usb endpoints.\n");
-		return error;
-	}
-	usb_endpoint_major = MAJOR(dev);
-
-	return error;
-}
-
-static void usb_endpoint_major_cleanup(void)
-{
-	unregister_chrdev_region(MKDEV(usb_endpoint_major, 0),
-				 MAX_ENDPOINT_MINORS);
-}
-
-static int endpoint_get_minor(struct ep_device *ep_dev)
-{
-	static DEFINE_MUTEX(minor_lock);
-	int retval = -ENOMEM;
-	int id;
-
-	mutex_lock(&minor_lock);
-	if (idr_pre_get(&endpoint_idr, GFP_KERNEL) == 0)
-		goto exit;
-
-	retval = idr_get_new(&endpoint_idr, ep_dev, &id);
-	if (retval < 0) {
-		if (retval == -EAGAIN)
-			retval = -ENOMEM;
-		goto exit;
-	}
-	ep_dev->minor = id & MAX_ID_MASK;
-exit:
-	mutex_unlock(&minor_lock);
-	return retval;
-}
-
-static void endpoint_free_minor(struct ep_device *ep_dev)
-{
-	idr_remove(&endpoint_idr, ep_dev->minor);
-}
-
-static struct endpoint_class {
-	struct kref kref;
-	struct class *class;
-} *ep_class;
-
-static int init_endpoint_class(void)
-{
-	int result = 0;
-
-	if (ep_class != NULL) {
-		kref_get(&ep_class->kref);
-		goto exit;
-	}
-
-	ep_class = kmalloc(sizeof(*ep_class), GFP_KERNEL);
-	if (!ep_class) {
-		result = -ENOMEM;
-		goto exit;
-	}
-
-	kref_init(&ep_class->kref);
-	ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
-	if (IS_ERR(ep_class->class)) {
-		result = PTR_ERR(ep_class->class);
-		goto class_create_error;
-	}
-
-	result = usb_endpoint_major_init();
-	if (result)
-		goto endpoint_major_error;
-
-	goto exit;
-
-endpoint_major_error:
-	class_destroy(ep_class->class);
-class_create_error:
-	kfree(ep_class);
-	ep_class = NULL;
-exit:
-	return result;
-}
-
-static void release_endpoint_class(struct kref *kref)
-{
-	/* Ok, we cheat as we know we only have one ep_class */
-	class_destroy(ep_class->class);
-	kfree(ep_class);
-	ep_class = NULL;
-	usb_endpoint_major_cleanup();
-}
-
-static void destroy_endpoint_class(void)
-{
-	if (ep_class)
-		kref_put(&ep_class->kref, release_endpoint_class);
-}
-
 static void ep_device_release(struct device *dev)
 {
 	struct ep_device *ep_dev = to_ep_device(dev);
 
-	endpoint_free_minor(ep_dev);
 	kfree(ep_dev);
 }
 
@@ -279,62 +170,32 @@
 			struct usb_host_endpoint *endpoint,
 			struct usb_device *udev)
 {
-	char name[8];
 	struct ep_device *ep_dev;
 	int retval;
 
-	retval = init_endpoint_class();
-	if (retval)
-		goto exit;
-
 	ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
 	if (!ep_dev) {
 		retval = -ENOMEM;
-		goto error_alloc;
-	}
-
-	retval = endpoint_get_minor(ep_dev);
-	if (retval) {
-		dev_err(parent, "can not allocate minor number for %s\n",
-			dev_name(&ep_dev->dev));
-		goto error_register;
+		goto exit;
 	}
 
 	ep_dev->desc = &endpoint->desc;
 	ep_dev->udev = udev;
 	ep_dev->dev.groups = ep_dev_groups;
-	ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor);
-	ep_dev->dev.class = ep_class->class;
+	ep_dev->dev.type = &usb_ep_device_type;
 	ep_dev->dev.parent = parent;
 	ep_dev->dev.release = ep_device_release;
-	dev_set_name(&ep_dev->dev, "usbdev%d.%d_ep%02x",
-		 udev->bus->busnum, udev->devnum,
-		 endpoint->desc.bEndpointAddress);
+	dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
 
 	retval = device_register(&ep_dev->dev);
 	if (retval)
-		goto error_chrdev;
+		goto error_register;
 
-	/* create the symlink to the old-style "ep_XX" directory */
-	sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
-	retval = sysfs_create_link(&parent->kobj, &ep_dev->dev.kobj, name);
-	if (retval)
-		goto error_link;
 	endpoint->ep_dev = ep_dev;
 	return retval;
 
-error_link:
-	device_unregister(&ep_dev->dev);
-	destroy_endpoint_class();
-	return retval;
-
-error_chrdev:
-	endpoint_free_minor(ep_dev);
-
 error_register:
 	kfree(ep_dev);
-error_alloc:
-	destroy_endpoint_class();
 exit:
 	return retval;
 }
@@ -344,12 +205,7 @@
 	struct ep_device *ep_dev = endpoint->ep_dev;
 
 	if (ep_dev) {
-		char name[8];
-
-		sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
-		sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
 		device_unregister(&ep_dev->dev);
 		endpoint->ep_dev = NULL;
-		destroy_endpoint_class();
 	}
 }
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index eb810bb..c32811a 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -140,8 +140,7 @@
 	struct find_interface_arg *arg = data;
 	struct usb_interface *intf;
 
-	/* can't look at usb devices, only interfaces */
-	if (is_usb_device(dev))
+	if (!is_usb_interface(dev))
 		return 0;
 
 	intf = to_usb_interface(dev);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index dabf925..e2a8cfa 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -104,6 +104,7 @@
 extern struct bus_type usb_bus_type;
 extern struct device_type usb_device_type;
 extern struct device_type usb_if_device_type;
+extern struct device_type usb_ep_device_type;
 extern struct usb_device_driver usb_generic_driver;
 
 static inline int is_usb_device(const struct device *dev)
@@ -111,6 +112,16 @@
 	return dev->type == &usb_device_type;
 }
 
+static inline int is_usb_interface(const struct device *dev)
+{
+	return dev->type == &usb_if_device_type;
+}
+
+static inline int is_usb_endpoint(const struct device *dev)
+{
+	return dev->type == &usb_ep_device_type;
+}
+
 /* Do the same for device drivers and interface drivers. */
 
 static inline int is_usb_device_driver(struct device_driver *drv)