summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2004-05-04 23:35:43 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2004-05-04 23:35:43 -0700
commit20cd671ac68dd7ad047fa81e65b5dde8827b40af (patch)
treedd98c5b9f443da3acc20b930aa36ce15f3c864d4
parentfa301125fe1d1355bd6cf245f49b3272748a14c0 (diff)
[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.
-rw-r--r--drivers/usb/core/message.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 1aa30005c4b7..3795c53e99d4 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1116,8 +1116,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
{
int i, ret;
struct usb_host_config *cp = NULL;
- struct usb_interface *new_interfaces[USB_MAXINTERFACES];
- int n;
+ struct usb_interface **new_interfaces = NULL;
+ int n, nintf;
/* dev->serialize guards all config changes */
@@ -1139,9 +1139,17 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
/* Allocate memory for new interfaces before doing anything else,
* so that if we run out then nothing will have changed. */
- n = 0;
+ n = nintf = 0;
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(
sizeof(struct usb_interface),
GFP_KERNEL);
@@ -1151,6 +1159,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
free_interfaces:
while (--n >= 0)
kfree(new_interfaces[n]);
+ kfree(new_interfaces);
return ret;
}
}
@@ -1173,11 +1182,10 @@ free_interfaces:
else {
dev->state = USB_STATE_CONFIGURED;
- /* re-initialize hc/hcd/usbcore interface/endpoint state.
- * this triggers binding of drivers to interfaces; and
- * maybe probe() calls will choose different altsettings.
+ /* Initialize the new interface structures and the
+ * hc/hcd/usbcore interface/endpoint state.
*/
- for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
+ for (i = 0; i < nintf; ++i) {
struct usb_interface_cache *intfc;
struct usb_interface *intf;
struct usb_host_interface *alt;
@@ -1212,12 +1220,15 @@ free_interfaces:
configuration,
alt->desc.bInterfaceNumber);
}
+ kfree(new_interfaces);
- /* Now that all interfaces are setup, probe() calls
- * may claim() any interface that's not yet bound.
- * Many class drivers need that: CDC, audio, video, etc.
+ /* Now that all the interfaces are set up, register them
+ * to trigger binding of drivers to interfaces. probe()
+ * 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_descriptor *desc;