Commit 1cdfd319 authored by Russell King's avatar Russell King

[PATCH] 2.5.32-usb

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.
parent 5d96e6b7
...@@ -1020,6 +1020,16 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) ...@@ -1020,6 +1020,16 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
if (status) if (status)
return 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 */ /* lower level hcd code should use *_dma exclusively */
if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { if (!(urb->transfer_flags & URB_NO_DMA_MAP)) {
if (usb_pipecontrol (urb->pipe)) if (usb_pipecontrol (urb->pipe))
...@@ -1038,16 +1048,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) ...@@ -1038,16 +1048,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
: PCI_DMA_TODEVICE); : PCI_DMA_TODEVICE);
} }
/* increment urb's reference count as part of giving it to the HCD return hcd->driver->urb_enqueue (hcd, urb, mem_flags);
* (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;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -208,7 +208,8 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose) ...@@ -208,7 +208,8 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose)
if (verbose) if (verbose)
ohci_dump_periodic (controller, "hcca"); ohci_dump_periodic (controller, "hcca");
#endif #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); ohci_dump_roothub (controller, 1);
} }
......
...@@ -519,7 +519,8 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -519,7 +519,8 @@ static int hc_start (struct ohci_hcd *ohci)
usb_connect (udev); usb_connect (udev);
udev->speed = USB_SPEED_FULL; udev->speed = USB_SPEED_FULL;
if (usb_register_root_hub (udev, ohci->parent_dev) != 0) { 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); disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
......
...@@ -2329,6 +2329,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd) ...@@ -2329,6 +2329,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
err_alloc_skeltd: err_alloc_skeltd:
usb_free_dev(udev); usb_free_dev(udev);
hcd->self.root_hub = NULL;
err_alloc_root_hub: err_alloc_root_hub:
pci_pool_destroy(uhci->qh_pool); pci_pool_destroy(uhci->qh_pool);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment