Messages in this thread Patch in this message |  | | From | Russell King <> | Subject | [PATCH] 2.5.32-usb | Date | Sun, 01 Sep 2002 20:01:06 +0100 |
| |
This patch appears not to be in 2.5.32, but applies cleanly.
The following patch fixes 3 problems in USB:
1. Don't pci_map buffers when we know we're not going to pass them to a device.
This was first noticed on ARM (no surprises here); the root hub code, rh_call_control(), placed data into the buffer and then called usb_hcd_giveback_urb(). This function called pci_unmap_single() on this region which promptly destroyed the data that rh_call_control() had placed there. This lead to a corrupted device descriptor and the "too many configurations" message.
2. If controller->hcca is NULL, don't try to dereference it.
3. If we free the root hub (in ohci-hcd.c or uhci-hcd.c), don't leave a dangling pointer around to trip us up in usb_disconnect(). EHCI appears to get this right.
drivers/usb/core/hcd.c | 21 +++++++++++---------- drivers/usb/host/ohci-dbg.c | 3 ++- drivers/usb/host/ohci-hcd.c | 3 ++- drivers/usb/host/uhci-hcd.c | 1 + 4 files changed, 16 insertions, 12 deletions
diff -ur orig/drivers/usb/core/hcd.c linux/drivers/usb/core/hcd.c --- orig/drivers/usb/core/hcd.c Fri Aug 30 14:53:19 2002 +++ linux/drivers/usb/core/hcd.c Sun Sep 1 19:51:46 2002 @@ -1020,6 +1020,16 @@ if (status) return status; + /* increment urb's reference count as part of giving it to the HCD + * (which now controls it). HCD guarantees that it either returns + * an error or calls giveback(), but not both. + */ + urb = usb_get_urb (urb); + if (urb->dev == hcd->self.root_hub) { + urb->transfer_flags |= URB_NO_DMA_MAP; + return rh_urb_enqueue (hcd, urb); + } + /* lower level hcd code should use *_dma exclusively */ if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { if (usb_pipecontrol (urb->pipe)) @@ -1038,16 +1048,7 @@ : PCI_DMA_TODEVICE); } - /* increment urb's reference count as part of giving it to the HCD - * (which now controls it). HCD guarantees that it either returns - * an error or calls giveback(), but not both. - */ - urb = usb_get_urb (urb); - if (urb->dev == hcd->self.root_hub) - status = rh_urb_enqueue (hcd, urb); - else - status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); - return status; + return hcd->driver->urb_enqueue (hcd, urb, mem_flags); } /*-------------------------------------------------------------------------*/ diff -ur orig/drivers/usb/host/ohci-dbg.c linux/drivers/usb/host/ohci-dbg.c --- orig/drivers/usb/host/ohci-dbg.c Sat Jul 27 13:55:21 2002 +++ linux/drivers/usb/host/ohci-dbg.c Sun Sep 1 17:14:27 2002 @@ -239,7 +239,8 @@ if (verbose) ohci_dump_periodic (controller, "hcca"); #endif - dbg ("hcca frame #%04x", controller->hcca->frame_no); + if (controller->hcca) + dbg ("hcca frame #%04x", controller->hcca->frame_no); ohci_dump_roothub (controller, 1); } diff -ur orig/drivers/usb/host/ohci-hcd.c linux/drivers/usb/host/ohci-hcd.c --- orig/drivers/usb/host/ohci-hcd.c Sat Jul 27 13:55:21 2002 +++ linux/drivers/usb/host/ohci-hcd.c Sun Sep 1 17:26:11 2002 @@ -530,7 +530,8 @@ usb_connect (udev); udev->speed = USB_SPEED_FULL; if (usb_register_root_hub (udev, ohci->parent_dev) != 0) { - usb_free_dev (udev); + usb_free_dev (udev); + ohci->hcd.self.root_hub = NULL; disable (ohci); ohci->hc_control &= ~OHCI_CTRL_HCFS; writel (ohci->hc_control, &ohci->regs->control); --- orig/drivers/usb/host/uhci-hcd.c Fri Aug 30 14:53:21 2002 +++ linux/drivers/usb/host/uhci-hcd.c Sun Sep 1 19:58:51 2002 @@ -2340,6 +2340,7 @@ err_alloc_skeltd: usb_free_dev(uhci->rh_dev); uhci->rh_dev = NULL; + hcd->self.root_hub = NULL; err_alloc_root_hub: pci_pool_destroy(uhci->qh_pool); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|  |