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