Hi Greg,
Below is a fix for a bounce-buffer handling problem in 2.4. The problem
is where no actual DMA by the card occurs, and the result of the
operation is inserted straight into the original buffer by software.
When bounce-buffers are being used, the memcpy inside pci_unmap_single
copies the uninitialized junk from the DMA buffer over the original
buffer, destroying the result that had been set up there.
(The problem showed up on an sh prototyping/development board where the
PCI controller (V320USC) doesn't have any access to the CPU main memory,
only to a small separate shared block of RAM that's there specifically
to provide DMA bounce buffers.)
The patch has been tested by me on sh64 and on that sh platform, and by
David on x86.
Can you consider including it please?
BTW, there's been a fix in 2.6 for this for quite some time, IIRC
courtesy of Russell King (I think as a result of finding the same
problem on an ARM platform with bounce-buffers).
===== drivers/usb/hcd.c 1.10 vs edited =====
--- 1.10/drivers/usb/hcd.c Mon Mar 31 14:22:42 2003
+++ edited/drivers/usb/hcd.c Mon Jan 5 15:55:30 2004
@@ -1201,25 +1201,27 @@
return status;
// NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag
- if (usb_pipecontrol (urb->pipe))
- urb->setup_dma = pci_map_single (
- hcd->pdev,
- urb->setup_packet,
- sizeof (struct usb_ctrlrequest),
- PCI_DMA_TODEVICE);
- if (urb->transfer_buffer_length != 0)
- urb->transfer_dma = pci_map_single (
- hcd->pdev,
- urb->transfer_buffer,
- urb->transfer_buffer_length,
- usb_pipein (urb->pipe)
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE);
-
- if (urb->dev == hcd->bus->root_hub)
+
+ /* For 2.4, don't map bounce buffer if it's a root hub operation. */
+ if (urb->dev == hcd->bus->root_hub) {
status = rh_urb_enqueue (hcd, urb);
- else
+ } else {
+ if (usb_pipecontrol (urb->pipe))
+ urb->setup_dma = pci_map_single (
+ hcd->pdev,
+ urb->setup_packet,
+ sizeof (struct usb_ctrlrequest),
+ PCI_DMA_TODEVICE);
+ if (urb->transfer_buffer_length != 0)
+ urb->transfer_dma = pci_map_single (
+ hcd->pdev,
+ urb->transfer_buffer,
+ urb->transfer_buffer_length,
+ usb_pipein (urb->pipe)
+ ? PCI_DMA_FROMDEVICE
+ : PCI_DMA_TODEVICE);
status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+ }
return status;
}
@@ -1471,6 +1473,11 @@
*/
void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
{
+ int is_root_hub_operation;
+
+ /* Work this out here as urb_unlink clears urb->dev */
+ is_root_hub_operation = (urb->dev == hcd->bus->root_hub);
+
urb_unlink (urb);
// NOTE: a generic device/urb monitoring hook would go here.
@@ -1480,11 +1487,14 @@
// hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
// NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag
- if (usb_pipecontrol (urb->pipe))
+
+ /* For 2.4, don't unmap bounce buffer if it's a root hub operation. */
+ if (usb_pipecontrol (urb->pipe) && !is_root_hub_operation)
pci_unmap_single (hcd->pdev, urb->setup_dma,
sizeof (struct usb_ctrlrequest),
PCI_DMA_TODEVICE);
- if (urb->transfer_buffer_length != 0)
+
+ if ((urb->transfer_buffer_length != 0) && !is_root_hub_operation)
pci_unmap_single (hcd->pdev, urb->transfer_dma,
urb->transfer_buffer_length,
usb_pipein (urb->pipe)
--
Richard \\\ SH-4/SH-5 Core & Debug Architect
Curnow \\\ SuperH (UK) Ltd, Bristol
-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel