ChangeSet 1.1587.3.36, 2004/05/05 13:35:43-07:00, stern@rowland.harvard.edu

[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.


 drivers/usb/core/message.c |   35 +++++++++++++++++++++++------------
 1 files changed, 23 insertions(+), 12 deletions(-)


diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	Fri May 14 15:29:51 2004
+++ b/drivers/usb/core/message.c	Fri May 14 15:29:51 2004
@@ -1116,8 +1116,8 @@
 {
 	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 @@
 
 	/* 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 @@
 free_interfaces:
 				while (--n >= 0)
 					kfree(new_interfaces[n]);
+				kfree(new_interfaces);
 				return ret;
 			}
 		}
@@ -1173,11 +1182,10 @@
 	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 @@
 				 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;
 
