On Tue, 3 Jun 2003, Greg KH wrote:

> On Tue, Jun 03, 2003 at 04:59:31PM -0400, Alan Stern wrote:
> > I've been told it's not a good idea to put transfer buffers on the stack,
> > as that's not DMA-able on some architectures.  Nevertheless, it's done in
> > the USB core (well, I found one place in hub.c that does it -- but that's
> > after only 1 minute of looking).
> > 
> > Does this need to be cleaned up?
> 
> Yes.  I thought we had fixed all of this in the past, did we miss
> something?

This should fix things.  I added buffer space (4 bytes) in struct usb_hub
to store the status reports.

Alan Stern


===== hub.c 1.105 vs edited =====
--- 1.105/drivers/usb/core/hub.c        Sat May 24 18:40:11 2003
+++ edited/drivers/usb/core/hub.c       Wed Jun  4 11:32:10 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,12 +274,30 @@
        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;
@@ -396,20 +416,18 @@
        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);
@@ -641,25 +659,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 +968,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 +1076,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);
===== hub.h 1.17 vs edited =====
--- 1.17/drivers/usb/core/hub.h Mon Oct  7 16:26:34 2002
+++ edited/drivers/usb/core/hub.h       Wed Jun  4 10:37:30 2003
@@ -175,6 +175,10 @@
 
        /* buffer for urb ... 1 bit each for hub and children, rounded up */
        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