USB: serial gadget: simplify endpoint handling
authorDavid Brownell <david-b@pacbell.net>
Wed, 7 May 2008 21:25:24 +0000 (14:25 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 14 May 2008 17:00:28 +0000 (10:00 -0700)
Switch serial gadget away from a *very* old idiom:  just remember
the endpoints we'll be using, instead of looking them up by name
each time.  This is a net code and data (globals) shrink.

Also fix a small memory leak in the rmmod path, by working the
same as the disconnect code.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Al Borchers <alborchers@steinerpoint.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/serial.c

index b0c32c73aeb6ce88497e2da767a80cf414b792d8..0829027d929693d46f69a230e6f12a74385eb69b 100644 (file)
@@ -198,10 +198,6 @@ static unsigned int gs_buf_get(struct gs_buf *gb, char *buf,
 
 static struct gs_dev *gs_device;
 
-static const char *EP_IN_NAME;
-static const char *EP_OUT_NAME;
-static const char *EP_NOTIFY_NAME;
-
 static struct mutex gs_open_close_lock[GS_NUM_PORTS];
 
 
@@ -1217,13 +1213,8 @@ static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
                        gs_free_req(gadget->ep0, dev->dev_ctrl_req);
                        dev->dev_ctrl_req = NULL;
                }
+               gs_reset_config(dev);
                gs_free_ports(dev);
-               if (dev->dev_notify_ep)
-                       usb_ep_disable(dev->dev_notify_ep);
-               if (dev->dev_in_ep)
-                       usb_ep_disable(dev->dev_in_ep);
-               if (dev->dev_out_ep)
-                       usb_ep_disable(dev->dev_out_ep);
                kfree(dev);
                set_gadget_data(gadget, NULL);
        }
@@ -1264,19 +1255,23 @@ static int __init gs_bind(struct usb_gadget *gadget)
                        __constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
        }
 
+       dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL);
+       if (dev == NULL)
+               return -ENOMEM;
+
        usb_ep_autoconfig_reset(gadget);
 
        ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
        if (!ep)
                goto autoconf_fail;
-       EP_IN_NAME = ep->name;
-       ep->driver_data = ep;   /* claim the endpoint */
+       dev->dev_in_ep = ep;
+       ep->driver_data = dev;  /* claim the endpoint */
 
        ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
        if (!ep)
                goto autoconf_fail;
-       EP_OUT_NAME = ep->name;
-       ep->driver_data = ep;   /* claim the endpoint */
+       dev->dev_out_ep = ep;
+       ep->driver_data = dev;  /* claim the endpoint */
 
        if (use_acm) {
                ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
@@ -1286,8 +1281,8 @@ static int __init gs_bind(struct usb_gadget *gadget)
                }
                gs_device_desc.idProduct = __constant_cpu_to_le16(
                                                GS_CDC_PRODUCT_ID),
-               EP_NOTIFY_NAME = ep->name;
-               ep->driver_data = ep;   /* claim the endpoint */
+               dev->dev_notify_ep = ep;
+               ep->driver_data = dev;  /* claim the endpoint */
        }
 
        gs_device_desc.bDeviceClass = use_acm
@@ -1317,9 +1312,7 @@ static int __init gs_bind(struct usb_gadget *gadget)
                gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       gs_device = dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL);
-       if (dev == NULL)
-               return -ENOMEM;
+       gs_device = dev;
 
        snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
                init_utsname()->sysname, init_utsname()->release,
@@ -1351,6 +1344,7 @@ static int __init gs_bind(struct usb_gadget *gadget)
        return 0;
 
 autoconf_fail:
+       kfree(dev);
        pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name);
        return -ENODEV;
 }
@@ -1710,7 +1704,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
        int ret = 0;
        struct usb_gadget *gadget = dev->dev_gadget;
        struct usb_ep *ep;
-       struct usb_endpoint_descriptor *ep_desc;
+       struct usb_endpoint_descriptor *out, *in, *notify;
        struct usb_request *req;
 
        if (dev == NULL) {
@@ -1738,71 +1732,53 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
                return -EINVAL;
        }
 
-       dev->dev_config = config;
-
-       gadget_for_each_ep(ep, gadget) {
-
-               if (EP_NOTIFY_NAME
-               && strcmp(ep->name, EP_NOTIFY_NAME) == 0) {
-                       ep_desc = choose_ep_desc(gadget,
+       in = choose_ep_desc(gadget,
+                       &gs_highspeed_in_desc,
+                       &gs_fullspeed_in_desc);
+       out = choose_ep_desc(gadget,
+                       &gs_highspeed_out_desc,
+                       &gs_fullspeed_out_desc);
+       notify = dev->dev_notify_ep
+               ? choose_ep_desc(gadget,
                                &gs_highspeed_notify_desc,
-                               &gs_fullspeed_notify_desc);
-                       ret = usb_ep_enable(ep,ep_desc);
-                       if (ret == 0) {
-                               ep->driver_data = dev;
-                               dev->dev_notify_ep = ep;
-                               dev->dev_notify_ep_desc = ep_desc;
-                       } else {
-                               pr_err("gs_set_config: cannot enable NOTIFY "
-                                       "endpoint %s, ret=%d\n",
-                                       ep->name, ret);
-                               goto exit_reset_config;
-                       }
-               }
+                               &gs_fullspeed_notify_desc)
+               : NULL;
 
-               else if (strcmp(ep->name, EP_IN_NAME) == 0) {
-                       ep_desc = choose_ep_desc(gadget,
-                               &gs_highspeed_in_desc,
-                               &gs_fullspeed_in_desc);
-                       ret = usb_ep_enable(ep,ep_desc);
-                       if (ret == 0) {
-                               ep->driver_data = dev;
-                               dev->dev_in_ep = ep;
-                               dev->dev_in_ep_desc = ep_desc;
-                       } else {
-                               pr_err("gs_set_config: cannot enable IN "
-                                       "endpoint %s, ret=%d\n",
-                                       ep->name, ret);
-                               goto exit_reset_config;
-                       }
-               }
-
-               else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
-                       ep_desc = choose_ep_desc(gadget,
-                               &gs_highspeed_out_desc,
-                               &gs_fullspeed_out_desc);
-                       ret = usb_ep_enable(ep,ep_desc);
-                       if (ret == 0) {
-                               ep->driver_data = dev;
-                               dev->dev_out_ep = ep;
-                               dev->dev_out_ep_desc = ep_desc;
-                       } else {
-                               pr_err("gs_set_config: cannot enable OUT "
-                                       "endpoint %s, ret=%d\n",
-                                       ep->name, ret);
-                               goto exit_reset_config;
-                       }
-               }
+       ret = usb_ep_enable(dev->dev_in_ep, in);
+       if (ret == 0) {
+               dev->dev_in_ep_desc = in;
+       } else {
+               pr_debug("%s: cannot enable %s %s, ret=%d\n",
+                       __func__, "IN", dev->dev_in_ep->name, ret);
+               return ret;
+       }
 
+       ret = usb_ep_enable(dev->dev_out_ep, out);
+       if (ret == 0) {
+               dev->dev_out_ep_desc = out;
+       } else {
+               pr_debug("%s: cannot enable %s %s, ret=%d\n",
+                       __func__, "OUT", dev->dev_out_ep->name, ret);
+fail0:
+               usb_ep_disable(dev->dev_in_ep);
+               return ret;
        }
 
-       if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL
-       || (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) {
-               pr_err("gs_set_config: cannot find endpoints\n");
-               ret = -ENODEV;
-               goto exit_reset_config;
+       if (notify) {
+               ret = usb_ep_enable(dev->dev_notify_ep, notify);
+               if (ret == 0) {
+                       dev->dev_notify_ep_desc = notify;
+               } else {
+                       pr_debug("%s: cannot enable %s %s, ret=%d\n",
+                               __func__, "NOTIFY",
+                               dev->dev_notify_ep->name, ret);
+                       usb_ep_disable(dev->dev_out_ep);
+                       goto fail0;
+               }
        }
 
+       dev->dev_config = config;
+
        /* allocate and queue read requests */
        ep = dev->dev_out_ep;
        for (i=0; i<read_q_size && ret == 0; i++) {
@@ -1886,18 +1862,10 @@ static void gs_reset_config(struct gs_dev *dev)
 
        /* disable endpoints, forcing completion of pending i/o; */
        /* completion handlers free their requests in this case */
-       if (dev->dev_notify_ep) {
+       if (dev->dev_notify_ep)
                usb_ep_disable(dev->dev_notify_ep);
-               dev->dev_notify_ep = NULL;
-       }
-       if (dev->dev_in_ep) {
-               usb_ep_disable(dev->dev_in_ep);
-               dev->dev_in_ep = NULL;
-       }
-       if (dev->dev_out_ep) {
-               usb_ep_disable(dev->dev_out_ep);
-               dev->dev_out_ep = NULL;
-       }
+       usb_ep_disable(dev->dev_in_ep);
+       usb_ep_disable(dev->dev_out_ep);
 }
 
 /*