diff options
author | David Brownell <david-b@pacbell.net> | 2008-05-07 17:25:24 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-05-14 13:00:28 -0400 |
commit | 734d37c654569f03156f8603a9761c402a73aa20 (patch) | |
tree | 880694ade8bc79bd45425ec108e002776cea1628 /drivers/usb/gadget | |
parent | 2c2d28a015f0dd36c5d1a06e16923e3142574066 (diff) |
USB: serial gadget: simplify endpoint handling
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>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/serial.c | 146 |
1 files changed, 57 insertions, 89 deletions
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b0c32c73aeb6..0829027d9296 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -198,10 +198,6 @@ static unsigned int gs_buf_get(struct gs_buf *gb, char *buf, | |||
198 | 198 | ||
199 | static struct gs_dev *gs_device; | 199 | static struct gs_dev *gs_device; |
200 | 200 | ||
201 | static const char *EP_IN_NAME; | ||
202 | static const char *EP_OUT_NAME; | ||
203 | static const char *EP_NOTIFY_NAME; | ||
204 | |||
205 | static struct mutex gs_open_close_lock[GS_NUM_PORTS]; | 201 | static struct mutex gs_open_close_lock[GS_NUM_PORTS]; |
206 | 202 | ||
207 | 203 | ||
@@ -1217,13 +1213,8 @@ static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget) | |||
1217 | gs_free_req(gadget->ep0, dev->dev_ctrl_req); | 1213 | gs_free_req(gadget->ep0, dev->dev_ctrl_req); |
1218 | dev->dev_ctrl_req = NULL; | 1214 | dev->dev_ctrl_req = NULL; |
1219 | } | 1215 | } |
1216 | gs_reset_config(dev); | ||
1220 | gs_free_ports(dev); | 1217 | gs_free_ports(dev); |
1221 | if (dev->dev_notify_ep) | ||
1222 | usb_ep_disable(dev->dev_notify_ep); | ||
1223 | if (dev->dev_in_ep) | ||
1224 | usb_ep_disable(dev->dev_in_ep); | ||
1225 | if (dev->dev_out_ep) | ||
1226 | usb_ep_disable(dev->dev_out_ep); | ||
1227 | kfree(dev); | 1218 | kfree(dev); |
1228 | set_gadget_data(gadget, NULL); | 1219 | set_gadget_data(gadget, NULL); |
1229 | } | 1220 | } |
@@ -1264,19 +1255,23 @@ static int __init gs_bind(struct usb_gadget *gadget) | |||
1264 | __constant_cpu_to_le16(GS_VERSION_NUM|0x0099); | 1255 | __constant_cpu_to_le16(GS_VERSION_NUM|0x0099); |
1265 | } | 1256 | } |
1266 | 1257 | ||
1258 | dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL); | ||
1259 | if (dev == NULL) | ||
1260 | return -ENOMEM; | ||
1261 | |||
1267 | usb_ep_autoconfig_reset(gadget); | 1262 | usb_ep_autoconfig_reset(gadget); |
1268 | 1263 | ||
1269 | ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc); | 1264 | ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc); |
1270 | if (!ep) | 1265 | if (!ep) |
1271 | goto autoconf_fail; | 1266 | goto autoconf_fail; |
1272 | EP_IN_NAME = ep->name; | 1267 | dev->dev_in_ep = ep; |
1273 | ep->driver_data = ep; /* claim the endpoint */ | 1268 | ep->driver_data = dev; /* claim the endpoint */ |
1274 | 1269 | ||
1275 | ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc); | 1270 | ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc); |
1276 | if (!ep) | 1271 | if (!ep) |
1277 | goto autoconf_fail; | 1272 | goto autoconf_fail; |
1278 | EP_OUT_NAME = ep->name; | 1273 | dev->dev_out_ep = ep; |
1279 | ep->driver_data = ep; /* claim the endpoint */ | 1274 | ep->driver_data = dev; /* claim the endpoint */ |
1280 | 1275 | ||
1281 | if (use_acm) { | 1276 | if (use_acm) { |
1282 | ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc); | 1277 | ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc); |
@@ -1286,8 +1281,8 @@ static int __init gs_bind(struct usb_gadget *gadget) | |||
1286 | } | 1281 | } |
1287 | gs_device_desc.idProduct = __constant_cpu_to_le16( | 1282 | gs_device_desc.idProduct = __constant_cpu_to_le16( |
1288 | GS_CDC_PRODUCT_ID), | 1283 | GS_CDC_PRODUCT_ID), |
1289 | EP_NOTIFY_NAME = ep->name; | 1284 | dev->dev_notify_ep = ep; |
1290 | ep->driver_data = ep; /* claim the endpoint */ | 1285 | ep->driver_data = dev; /* claim the endpoint */ |
1291 | } | 1286 | } |
1292 | 1287 | ||
1293 | gs_device_desc.bDeviceClass = use_acm | 1288 | gs_device_desc.bDeviceClass = use_acm |
@@ -1317,9 +1312,7 @@ static int __init gs_bind(struct usb_gadget *gadget) | |||
1317 | gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 1312 | gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
1318 | } | 1313 | } |
1319 | 1314 | ||
1320 | gs_device = dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL); | 1315 | gs_device = dev; |
1321 | if (dev == NULL) | ||
1322 | return -ENOMEM; | ||
1323 | 1316 | ||
1324 | snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", | 1317 | snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", |
1325 | init_utsname()->sysname, init_utsname()->release, | 1318 | init_utsname()->sysname, init_utsname()->release, |
@@ -1351,6 +1344,7 @@ static int __init gs_bind(struct usb_gadget *gadget) | |||
1351 | return 0; | 1344 | return 0; |
1352 | 1345 | ||
1353 | autoconf_fail: | 1346 | autoconf_fail: |
1347 | kfree(dev); | ||
1354 | pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name); | 1348 | pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name); |
1355 | return -ENODEV; | 1349 | return -ENODEV; |
1356 | } | 1350 | } |
@@ -1710,7 +1704,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) | |||
1710 | int ret = 0; | 1704 | int ret = 0; |
1711 | struct usb_gadget *gadget = dev->dev_gadget; | 1705 | struct usb_gadget *gadget = dev->dev_gadget; |
1712 | struct usb_ep *ep; | 1706 | struct usb_ep *ep; |
1713 | struct usb_endpoint_descriptor *ep_desc; | 1707 | struct usb_endpoint_descriptor *out, *in, *notify; |
1714 | struct usb_request *req; | 1708 | struct usb_request *req; |
1715 | 1709 | ||
1716 | if (dev == NULL) { | 1710 | if (dev == NULL) { |
@@ -1738,71 +1732,53 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) | |||
1738 | return -EINVAL; | 1732 | return -EINVAL; |
1739 | } | 1733 | } |
1740 | 1734 | ||
1741 | dev->dev_config = config; | 1735 | in = choose_ep_desc(gadget, |
1742 | 1736 | &gs_highspeed_in_desc, | |
1743 | gadget_for_each_ep(ep, gadget) { | 1737 | &gs_fullspeed_in_desc); |
1744 | 1738 | out = choose_ep_desc(gadget, | |
1745 | if (EP_NOTIFY_NAME | 1739 | &gs_highspeed_out_desc, |
1746 | && strcmp(ep->name, EP_NOTIFY_NAME) == 0) { | 1740 | &gs_fullspeed_out_desc); |
1747 | ep_desc = choose_ep_desc(gadget, | 1741 | notify = dev->dev_notify_ep |
1742 | ? choose_ep_desc(gadget, | ||
1748 | &gs_highspeed_notify_desc, | 1743 | &gs_highspeed_notify_desc, |
1749 | &gs_fullspeed_notify_desc); | 1744 | &gs_fullspeed_notify_desc) |
1750 | ret = usb_ep_enable(ep,ep_desc); | 1745 | : NULL; |
1751 | if (ret == 0) { | ||
1752 | ep->driver_data = dev; | ||
1753 | dev->dev_notify_ep = ep; | ||
1754 | dev->dev_notify_ep_desc = ep_desc; | ||
1755 | } else { | ||
1756 | pr_err("gs_set_config: cannot enable NOTIFY " | ||
1757 | "endpoint %s, ret=%d\n", | ||
1758 | ep->name, ret); | ||
1759 | goto exit_reset_config; | ||
1760 | } | ||
1761 | } | ||
1762 | 1746 | ||
1763 | else if (strcmp(ep->name, EP_IN_NAME) == 0) { | 1747 | ret = usb_ep_enable(dev->dev_in_ep, in); |
1764 | ep_desc = choose_ep_desc(gadget, | 1748 | if (ret == 0) { |
1765 | &gs_highspeed_in_desc, | 1749 | dev->dev_in_ep_desc = in; |
1766 | &gs_fullspeed_in_desc); | 1750 | } else { |
1767 | ret = usb_ep_enable(ep,ep_desc); | 1751 | pr_debug("%s: cannot enable %s %s, ret=%d\n", |
1768 | if (ret == 0) { | 1752 | __func__, "IN", dev->dev_in_ep->name, ret); |
1769 | ep->driver_data = dev; | 1753 | return ret; |
1770 | dev->dev_in_ep = ep; | 1754 | } |
1771 | dev->dev_in_ep_desc = ep_desc; | ||
1772 | } else { | ||
1773 | pr_err("gs_set_config: cannot enable IN " | ||
1774 | "endpoint %s, ret=%d\n", | ||
1775 | ep->name, ret); | ||
1776 | goto exit_reset_config; | ||
1777 | } | ||
1778 | } | ||
1779 | |||
1780 | else if (strcmp(ep->name, EP_OUT_NAME) == 0) { | ||
1781 | ep_desc = choose_ep_desc(gadget, | ||
1782 | &gs_highspeed_out_desc, | ||
1783 | &gs_fullspeed_out_desc); | ||
1784 | ret = usb_ep_enable(ep,ep_desc); | ||
1785 | if (ret == 0) { | ||
1786 | ep->driver_data = dev; | ||
1787 | dev->dev_out_ep = ep; | ||
1788 | dev->dev_out_ep_desc = ep_desc; | ||
1789 | } else { | ||
1790 | pr_err("gs_set_config: cannot enable OUT " | ||
1791 | "endpoint %s, ret=%d\n", | ||
1792 | ep->name, ret); | ||
1793 | goto exit_reset_config; | ||
1794 | } | ||
1795 | } | ||
1796 | 1755 | ||
1756 | ret = usb_ep_enable(dev->dev_out_ep, out); | ||
1757 | if (ret == 0) { | ||
1758 | dev->dev_out_ep_desc = out; | ||
1759 | } else { | ||
1760 | pr_debug("%s: cannot enable %s %s, ret=%d\n", | ||
1761 | __func__, "OUT", dev->dev_out_ep->name, ret); | ||
1762 | fail0: | ||
1763 | usb_ep_disable(dev->dev_in_ep); | ||
1764 | return ret; | ||
1797 | } | 1765 | } |
1798 | 1766 | ||
1799 | if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL | 1767 | if (notify) { |
1800 | || (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) { | 1768 | ret = usb_ep_enable(dev->dev_notify_ep, notify); |
1801 | pr_err("gs_set_config: cannot find endpoints\n"); | 1769 | if (ret == 0) { |
1802 | ret = -ENODEV; | 1770 | dev->dev_notify_ep_desc = notify; |
1803 | goto exit_reset_config; | 1771 | } else { |
1772 | pr_debug("%s: cannot enable %s %s, ret=%d\n", | ||
1773 | __func__, "NOTIFY", | ||
1774 | dev->dev_notify_ep->name, ret); | ||
1775 | usb_ep_disable(dev->dev_out_ep); | ||
1776 | goto fail0; | ||
1777 | } | ||
1804 | } | 1778 | } |
1805 | 1779 | ||
1780 | dev->dev_config = config; | ||
1781 | |||
1806 | /* allocate and queue read requests */ | 1782 | /* allocate and queue read requests */ |
1807 | ep = dev->dev_out_ep; | 1783 | ep = dev->dev_out_ep; |
1808 | for (i=0; i<read_q_size && ret == 0; i++) { | 1784 | for (i=0; i<read_q_size && ret == 0; i++) { |
@@ -1886,18 +1862,10 @@ static void gs_reset_config(struct gs_dev *dev) | |||
1886 | 1862 | ||
1887 | /* disable endpoints, forcing completion of pending i/o; */ | 1863 | /* disable endpoints, forcing completion of pending i/o; */ |
1888 | /* completion handlers free their requests in this case */ | 1864 | /* completion handlers free their requests in this case */ |
1889 | if (dev->dev_notify_ep) { | 1865 | if (dev->dev_notify_ep) |
1890 | usb_ep_disable(dev->dev_notify_ep); | 1866 | usb_ep_disable(dev->dev_notify_ep); |
1891 | dev->dev_notify_ep = NULL; | 1867 | usb_ep_disable(dev->dev_in_ep); |
1892 | } | 1868 | usb_ep_disable(dev->dev_out_ep); |
1893 | if (dev->dev_in_ep) { | ||
1894 | usb_ep_disable(dev->dev_in_ep); | ||
1895 | dev->dev_in_ep = NULL; | ||
1896 | } | ||
1897 | if (dev->dev_out_ep) { | ||
1898 | usb_ep_disable(dev->dev_out_ep); | ||
1899 | dev->dev_out_ep = NULL; | ||
1900 | } | ||
1901 | } | 1869 | } |
1902 | 1870 | ||
1903 | /* | 1871 | /* |