Commit 20cd671a authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: Reduce kernel stack usage

This patch allocates a temporary array from the heap instead of from the
kernel's stack in usb_set_configuration().  It also updates a few
comments.  Please apply.
parent fa301125
...@@ -1116,8 +1116,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1116,8 +1116,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
{ {
int i, ret; int i, ret;
struct usb_host_config *cp = NULL; struct usb_host_config *cp = NULL;
struct usb_interface *new_interfaces[USB_MAXINTERFACES]; struct usb_interface **new_interfaces = NULL;
int n; int n, nintf;
/* dev->serialize guards all config changes */ /* dev->serialize guards all config changes */
...@@ -1139,9 +1139,17 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1139,9 +1139,17 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
/* Allocate memory for new interfaces before doing anything else, /* Allocate memory for new interfaces before doing anything else,
* so that if we run out then nothing will have changed. */ * so that if we run out then nothing will have changed. */
n = 0; n = nintf = 0;
if (cp) { if (cp) {
for (; n < cp->desc.bNumInterfaces; ++n) { nintf = cp->desc.bNumInterfaces;
new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
GFP_KERNEL);
if (!new_interfaces) {
dev_err(&dev->dev, "Out of memory");
return -ENOMEM;
}
for (; n < nintf; ++n) {
new_interfaces[n] = kmalloc( new_interfaces[n] = kmalloc(
sizeof(struct usb_interface), sizeof(struct usb_interface),
GFP_KERNEL); GFP_KERNEL);
...@@ -1151,6 +1159,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1151,6 +1159,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
free_interfaces: free_interfaces:
while (--n >= 0) while (--n >= 0)
kfree(new_interfaces[n]); kfree(new_interfaces[n]);
kfree(new_interfaces);
return ret; return ret;
} }
} }
...@@ -1173,11 +1182,10 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1173,11 +1182,10 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
else { else {
dev->state = USB_STATE_CONFIGURED; dev->state = USB_STATE_CONFIGURED;
/* re-initialize hc/hcd/usbcore interface/endpoint state. /* Initialize the new interface structures and the
* this triggers binding of drivers to interfaces; and * hc/hcd/usbcore interface/endpoint state.
* maybe probe() calls will choose different altsettings.
*/ */
for (i = 0; i < cp->desc.bNumInterfaces; ++i) { for (i = 0; i < nintf; ++i) {
struct usb_interface_cache *intfc; struct usb_interface_cache *intfc;
struct usb_interface *intf; struct usb_interface *intf;
struct usb_host_interface *alt; struct usb_host_interface *alt;
...@@ -1212,12 +1220,15 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1212,12 +1220,15 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
configuration, configuration,
alt->desc.bInterfaceNumber); alt->desc.bInterfaceNumber);
} }
kfree(new_interfaces);
/* Now that all interfaces are setup, probe() calls /* Now that all the interfaces are set up, register them
* may claim() any interface that's not yet bound. * to trigger binding of drivers to interfaces. probe()
* Many class drivers need that: CDC, audio, video, etc. * routines may install different altsettings and may
* claim() any interfaces not yet bound. Many class drivers
* need that: CDC, audio, video, etc.
*/ */
for (i = 0; i < cp->desc.bNumInterfaces; ++i) { for (i = 0; i < nintf; ++i) {
struct usb_interface *intf = cp->interface[i]; struct usb_interface *intf = cp->interface[i];
struct usb_interface_descriptor *desc; struct usb_interface_descriptor *desc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment