ChangeSet 1.971, 2003/01/27 23:12:19+11:00, [EMAIL PROTECTED]
[PATCH] USB: usbcore misc cleanup (notably for non-dma hcds)
The support for non-dma HCDs is likely the most interesting bit here.
- makes dma calls behave sensibly when used with host controllers
that don't use dma (including sl811). usb_buffer_map() is a nop
while scatterlist dma mappings fail (as they must).
- make usb_sg_init() behave sensibly when used with non-dma hcs.
the urbs are initted with transfer_buffer, not transfer_dma.
this is the higher level analogue to usb_buffer_map(), so it
needs to succeed unless there's a Real Error (tm).
- moves two compatibility inlines from ehci.h into hcd.h so
it'll be more practical to have the other hcds work in other
environments (notably lk 2.4) too
- remove URB_TIMEOUT_KILLED flag ... no device driver tests it;
hcds don't really (uhci sets it, never reads it; sl811 doesn't
enable the path that might set it), and it's not well defined.
if any hcd needs such state, keep it in hc-private storage.
- in usb_sg_wait(), use yield() instead of schedule() to let
other activities free resources needed to continue. (This
was noted recently by Oliver.)
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c Tue Feb 4 15:17:46 2003
+++ b/drivers/usb/core/hcd.c Tue Feb 4 15:17:46 2003
@@ -1029,8 +1029,11 @@
return status;
}
- /* lower level hcd code should use *_dma exclusively */
- if (!(urb->transfer_flags & URB_NO_DMA_MAP)) {
+ /* lower level hcd code should use *_dma exclusively,
+ * unless it uses pio or talks to another transport.
+ */
+ if (!(urb->transfer_flags & URB_NO_DMA_MAP)
+ && hcd->controller->dma_mask) {
if (usb_pipecontrol (urb->pipe))
urb->setup_dma = dma_map_single (
hcd->controller,
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h Tue Feb 4 15:17:45 2003
+++ b/drivers/usb/core/hcd.h Tue Feb 4 15:17:45 2003
@@ -111,6 +111,13 @@
*/
};
+/* 2.4 does this a bit differently ... */
+static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
+{
+ return &hcd->self;
+}
+
+
struct hcd_dev { /* usb_device.hcpriv points to this */
struct list_head dev_list; /* on this hcd */
struct list_head urb_list; /* pending on this dev */
@@ -342,6 +349,13 @@
extern int usb_register_root_hub (struct usb_device *usb_dev,
struct device *parent_dev);
+
+/* for portability to 2.4, hcds should call this */
+static inline int hcd_register_root (struct usb_hcd *hcd)
+{
+ return usb_register_root_hub (
+ hcd_to_bus (hcd)->root_hub, hcd->controller);
+}
/*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c Tue Feb 4 15:17:45 2003
+++ b/drivers/usb/core/message.c Tue Feb 4 15:17:45 2003
@@ -206,7 +206,8 @@
kfree (io->urbs);
io->urbs = 0;
}
- usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
+ if (io->dev->dev.dma_mask != 0)
+ usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
io->dev = 0;
}
@@ -301,6 +302,7 @@
{
int i;
int urb_flags;
+ int dma;
if (!io || !dev || !sg
|| usb_pipecontrol (pipe)
@@ -314,8 +316,16 @@
io->sg = sg;
io->nents = nents;
+ /* not all host controllers use DMA (like the mainstream pci ones);
+ * they can use PIO (sl811) or be software over another transport.
+ */
+ dma = (dev->dev.dma_mask == 0);
+ if (dma)
+ io->entries = usb_buffer_map_sg (dev, pipe, sg, nents);
+ else
+ io->entries = nents;
+
/* initialize all the urbs we'll use */
- io->entries = usb_buffer_map_sg (dev, pipe, sg, nents);
if (io->entries <= 0)
return io->entries;
@@ -347,8 +357,17 @@
io->urbs [i]->status = -EINPROGRESS;
io->urbs [i]->actual_length = 0;
- io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
- len = sg_dma_len (sg + i);
+ if (dma) {
+ /* hc may use _only_ transfer_dma */
+ io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
+ len = sg_dma_len (sg + i);
+ } else {
+ /* hc may use _only_ transfer_buffer */
+ io->urbs [i]->transfer_buffer =
+ page_address (sg [i].page) + sg [i].offset;
+ len = sg [i].length;
+ }
+
if (length) {
len = min_t (unsigned, len, length);
length -= len;
@@ -434,9 +453,7 @@
retval = 0;
i--;
// FIXME: should it usb_sg_cancel() on INTERRUPT?
- // how about imposing a backoff?
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule ();
+ yield ();
break;
/* no error? continue immediately.
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c Tue Feb 4 15:17:45 2003
+++ b/drivers/usb/core/usb.c Tue Feb 4 15:17:45 2003
@@ -1224,7 +1224,8 @@
*
* Return value is either null (indicating no buffer could be mapped), or
* the parameter. URB_NO_DMA_MAP is added to urb->transfer_flags if the
- * operation succeeds.
+ * operation succeeds. If the device is connected to this system through
+ * a non-DMA controller, this operation always succeeds.
*
* This call would normally be used for an urb which is reused, perhaps
* as the target of a large periodic transfer, with usb_buffer_dmasync()
@@ -1245,12 +1246,15 @@
|| !(controller = bus->controller))
return 0;
- urb->transfer_dma = dma_map_single (controller,
+ if (controller->dma_mask) {
+ urb->transfer_dma = dma_map_single (controller,
urb->transfer_buffer, urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? DMA_FROM_DEVICE : DMA_TO_DEVICE);
// FIXME generic api broken like pci, can't report errors
// if (urb->transfer_dma == DMA_ADDR_INVALID) return 0;
+ } else
+ urb->transfer_dma = ~0;
urb->transfer_flags |= URB_NO_DMA_MAP;
return urb;
}
@@ -1271,7 +1275,8 @@
|| !(controller = bus->controller))
return;
- dma_sync_single (controller,
+ if (controller->dma_mask)
+ dma_sync_single (controller,
urb->transfer_dma, urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? DMA_FROM_DEVICE : DMA_TO_DEVICE);
@@ -1295,10 +1300,12 @@
|| !(controller = bus->controller))
return;
- dma_unmap_single (controller,
+ if (controller->dma_mask)
+ dma_unmap_single (controller,
urb->transfer_dma, urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ urb->transfer_flags &= ~URB_NO_DMA_MAP;
}
/**
@@ -1336,7 +1343,8 @@
if (!dev
|| usb_pipecontrol (pipe)
|| !(bus = dev->bus)
- || !(controller = bus->controller))
+ || !(controller = bus->controller)
+ || !controller->dma_mask)
return -1;
// FIXME generic api broken like pci, can't report errors
@@ -1362,7 +1370,8 @@
if (!dev
|| !(bus = dev->bus)
- || !(controller = bus->controller))
+ || !(controller = bus->controller)
+ || !controller->dma_mask)
return;
dma_sync_sg (controller, sg, n_hw_ents,
@@ -1386,7 +1395,8 @@
if (!dev
|| !(bus = dev->bus)
- || !(controller = bus->controller))
+ || !(controller = bus->controller)
+ || !controller->dma_mask)
return;
dma_unmap_sg (controller, sg, n_hw_ents,
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h Tue Feb 4 15:17:46 2003
+++ b/drivers/usb/host/ehci.h Tue Feb 4 15:17:46 2003
@@ -426,16 +426,6 @@
#else /* LINUX_VERSION_CODE */
-// hcd_to_bus() eventually moves to hcd.h on 2.5 too
-static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
- { return &hcd->self; }
-// ... as does hcd_register_root()
-static inline int hcd_register_root (struct usb_hcd *hcd)
-{
- return usb_register_root_hub (
- hcd_to_bus (hcd)->root_hub, &hcd->pdev->dev);
-}
-
#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags)
#ifndef DEBUG
diff -Nru a/drivers/usb/host/hc_simple.c b/drivers/usb/host/hc_simple.c
--- a/drivers/usb/host/hc_simple.c Tue Feb 4 15:17:46 2003
+++ b/drivers/usb/host/hc_simple.c Tue Feb 4 15:17:46 2003
@@ -219,7 +219,7 @@
if (!list_empty (&urb->urb_list) && urb->status == -EINPROGRESS) {
/* URB active? */
- if (urb->transfer_flags & (URB_ASYNC_UNLINK | URB_TIMEOUT_KILLED)) {
+ if (urb->transfer_flags & URB_ASYNC_UNLINK) {
/* asynchronous with callback */
/* relink the urb to the del list */
list_move (&urb->urb_list, &hci->del_list);
@@ -388,7 +388,6 @@
struct urb *urb = (struct urb *) lurb;
DBGFUNC ("enter qu_urb_timeout\n");
- urb->transfer_flags |= URB_TIMEOUT_KILLED;
hci_unlink_urb (urb);
}
#endif
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c Tue Feb 4 15:17:46 2003
+++ b/drivers/usb/host/uhci-hcd.c Tue Feb 4 15:17:46 2003
@@ -1747,7 +1747,6 @@
tmp = tmp->next;
- u->transfer_flags |= URB_TIMEOUT_KILLED;
uhci_urb_dequeue(hcd, u);
}
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h Tue Feb 4 15:17:45 2003
+++ b/include/linux/usb.h Tue Feb 4 15:17:45 2003
@@ -554,7 +554,6 @@
#define URB_NO_FSBR 0x0020 /* UHCI-specific */
#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet
*/
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
-#define URB_TIMEOUT_KILLED 0x1000 /* only set by HCD! */
struct usb_iso_packet_descriptor {
unsigned int offset;
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel