ChangeSet 1.1243.50.5, 2003/06/06 15:03:07-07:00, [EMAIL PROTECTED]

[PATCH] USB: Don't allocate transfer buffers on the stack in hub.c

 Allocate hub status input buffers separately and not on the stack.


 drivers/usb/core/hub.c |  100 ++++++++++++++++++++++++++++++++-----------------
 drivers/usb/core/hub.h |    6 ++
 2 files changed, 72 insertions(+), 34 deletions(-)


diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c    Tue Jun 10 17:11:57 2003
+++ b/drivers/usb/core/hub.c    Tue Jun 10 17:11:57 2003
@@ -103,21 +103,23 @@
 /*
  * USB 2.0 spec Section 11.24.2.6
  */
-static int usb_get_hub_status(struct usb_device *dev, void *data)
+static int usb_get_hub_status(struct usb_device *dev,
+               struct usb_hub_status *data)
 {
        return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
-               data, sizeof(struct usb_hub_status), HZ);
+               data, sizeof(*data), HZ);
 }
 
 /*
  * USB 2.0 spec Section 11.24.2.7
  */
-static int usb_get_port_status(struct usb_device *dev, int port, void *data)
+static int usb_get_port_status(struct usb_device *dev, int port,
+               struct usb_port_status *data)
 {
        return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
-               data, sizeof(struct usb_hub_status), HZ);
+               data, sizeof(*data), HZ);
 }
 
 /* completion function, fires on port status changes and various faults */
@@ -272,16 +274,48 @@
        wait_ms(hub->descriptor->bPwrOn2PwrGood * 2);
 }
 
+static int usb_hub_hub_status(struct usb_hub *hub,
+               u16 *status, u16 *change)
+{
+       struct usb_device *dev = interface_to_usbdev (hub->intf);
+       int ret;
+
+       ret = usb_get_hub_status(dev, &hub->status->hub);
+       if (ret < 0)
+               dev_err (hubdev (dev),
+                       "%s failed (err = %d)\n", __FUNCTION__, ret);
+       else {
+               *status = le16_to_cpu(hub->status->hub.wHubStatus);
+               *change = le16_to_cpu(hub->status->hub.wHubChange); 
+               ret = 0;
+       }
+       return ret;
+}
+
 static int usb_hub_configure(struct usb_hub *hub,
        struct usb_endpoint_descriptor *endpoint)
 {
        struct usb_device *dev = interface_to_usbdev (hub->intf);
        struct device *hub_dev;
-       struct usb_hub_status hubstatus;
+       u16 hubstatus, hubchange;
        unsigned int pipe;
        int maxp, ret;
        char *message;
 
+       hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
+       if (!hub->buffer) {
+               message = "can't kmalloc hub irq buffer";
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL);
+       if (!hub->status) {
+               message = "can't kmalloc hub status buffer";
+               ret = -ENOMEM;
+               goto fail;
+       }
+
        hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
        if (!hub->descriptor) {
                message = "can't kmalloc hub descriptor";
@@ -396,27 +430,25 @@
        dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
                hub->descriptor->bHubContrCurrent);
 
-       ret = usb_get_hub_status(dev, &hubstatus);
+       ret = usb_hub_hub_status(hub, &hubstatus, &hubchange);
        if (ret < 0) {
                message = "can't get hub status";
                goto fail;
        }
 
-       le16_to_cpus(&hubstatus.wHubStatus);
-
        dev_dbg(hub_dev, "local power source is %s\n",
-               (hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER)
+               (hubstatus & HUB_STATUS_LOCAL_POWER)
                ? "lost (inactive)" : "good");
 
        dev_dbg(hub_dev, "%sover-current condition exists\n",
-               (hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
+               (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
 
        /* Start the interrupt endpoint */
        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
        maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
-       if (maxp > sizeof(hub->buffer))
-               maxp = sizeof(hub->buffer);
+       if (maxp > sizeof(*hub->buffer))
+               maxp = sizeof(*hub->buffer);
 
        hub->urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!hub->urb) {
@@ -425,7 +457,7 @@
                goto fail;
        }
 
-       usb_fill_int_urb(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
+       usb_fill_int_urb(hub->urb, dev, pipe, *hub->buffer, maxp, hub_irq,
                hub, endpoint->bInterval);
        ret = usb_submit_urb(hub->urb, GFP_KERNEL);
        if (ret) {
@@ -484,6 +516,16 @@
                hub->descriptor = NULL;
        }
 
+       if (hub->status) {
+               kfree(hub->status);
+               hub->status = NULL;
+       }
+
+       if (hub->buffer) {
+               kfree(hub->buffer);
+               hub->buffer = NULL;
+       }
+
        /* Free the memory */
        kfree(hub);
 }
@@ -641,25 +683,20 @@
        err("cannot disconnect hub %s", dev->devpath);
 }
 
-static int usb_hub_port_status(struct usb_device *hub, int port,
+static int usb_hub_port_status(struct usb_device *dev, int port,
                               u16 *status, u16 *change)
 {
-       struct usb_port_status *portsts;
-       int ret = -ENOMEM;
+       struct usb_hub *hub = usb_get_intfdata (dev->actconfig->interface);
+       int ret;
 
-       portsts = kmalloc(sizeof(*portsts), GFP_NOIO);
-       if (portsts) {
-               ret = usb_get_port_status(hub, port + 1, portsts);
-               if (ret < 0)
-                       dev_err (hubdev (hub),
-                               "%s failed (err = %d)\n", __FUNCTION__,
-                               ret);
-               else {
-                       *status = le16_to_cpu(portsts->wPortStatus);
-                       *change = le16_to_cpu(portsts->wPortChange); 
-                       ret = 0;
-               }
-               kfree(portsts);
+       ret = usb_get_port_status(dev, port + 1, &hub->status->port);
+       if (ret < 0)
+               dev_err (hubdev (dev),
+                       "%s failed (err = %d)\n", __FUNCTION__, ret);
+       else {
+               *status = le16_to_cpu(hub->status->port.wPortStatus);
+               *change = le16_to_cpu(hub->status->port.wPortChange); 
+               ret = 0;
        }
        return ret;
 }
@@ -955,7 +992,6 @@
        struct list_head *tmp;
        struct usb_device *dev;
        struct usb_hub *hub;
-       struct usb_hub_status hubsts;
        u16 hubstatus;
        u16 hubchange;
        u16 portstatus;
@@ -1064,11 +1100,9 @@
                } /* end for i */
 
                /* deal with hub status changes */
-               if (usb_get_hub_status(dev, &hubsts) < 0)
+               if (usb_hub_hub_status(hub, &hubstatus, &hubchange) < 0)
                        dev_err (&hub->intf->dev, "get_hub_status failed\n");
                else {
-                       hubstatus = le16_to_cpup(&hubsts.wHubStatus);
-                       hubchange = le16_to_cpup(&hubsts.wHubChange);
                        if (hubchange & HUB_CHANGE_LOCAL_POWER) {
                                dev_dbg (&hub->intf->dev, "power change\n");
                                usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h    Tue Jun 10 17:11:57 2003
+++ b/drivers/usb/core/hub.h    Tue Jun 10 17:11:57 2003
@@ -174,7 +174,11 @@
        struct urb              *urb;           /* for interrupt polling pipe */
 
        /* buffer for urb ... 1 bit each for hub and children, rounded up */
-       char                    buffer[(USB_MAXCHILDREN + 1 + 7) / 8];
+       char                    (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
+       union {
+               struct usb_hub_status   hub;
+               struct usb_port_status  port;
+       }                       *status;        /* buffer for status reports */
 
        int                     error;          /* last reported error */
        int                     nerrors;        /* track consecutive errors */



-------------------------------------------------------
This SF.net email is sponsored by:  Etnus, makers of TotalView, The best
thread debugger on the planet. Designed with thread debugging features
you've never dreamed of, try TotalView 6 free at www.etnus.com.
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to