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