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;