diff mbox

Fix for soc-dma type code

Message ID 20110802173020.GA26833@davesworkthinkpad
State New
Headers show

Commit Message

Dr. David Alan Gilbert Aug. 2, 2011, 5:30 p.m. UTC
Hi,
  I was looking at trying to get soc_dma to call a fifo routine using 
soc_dma_port_add_fifo_in and hit a few problems that are fixed by the following
patch.

1) Where there are two entries matching an address (i.e. a fifo registered for 
both input and output) soc_dma_lookup finds the last one in the list
however soc_dma_ch_update_type then searches forward missing any other cases.
(It would be good for someone to cast another eye over soc_dma_lookup to check
it always gets the last one in the list)

2) soc_dma_ch_update_type in the memory case was marking the area as 'other'
when it wasn't a constant address - I believe this is actually intended to
be if it isn't linearly addressed.

3) I'm suspicious of the address check around line 147:
        if (entry->addr > ch->vaddr[port] ||
                        entry->addr + entry->u.mem.size <= ch->vaddr[port])

  won't that break if the entry describes a block of RAM at the top of the
address space and the address space is as large as the type of entry->addr
such that entry->addr+entry->u.mem.size wraps?  (I'm not sure what the clean
fix for that is, so I left that alone).

Note: Users of soc_dma might find that fix (2) might now
cause the soc_dma internal memory->memory case to correctly trigger
if they try and dma from memory->memory where it might not have done
before.

Dave
diff mbox

Patch

diff --git a/hw/soc_dma.c b/hw/soc_dma.c
index 3f0f414..4ef5316 100644
--- a/hw/soc_dma.c
+++ b/hw/soc_dma.c
@@ -129,9 +129,10 @@  static inline enum soc_dma_port_type soc_dma_ch_update_type(
     struct memmap_entry_s *entry = soc_dma_lookup(dma, ch->vaddr[port]);
 
     if (entry->type == soc_dma_port_fifo) {
-        while (entry < dma->memmap + dma->memmap_size &&
+        while (entry > dma->memmap &&
                         entry->u.fifo.out != port)
-            entry ++;
+            entry --;
+
         if (entry->addr != ch->vaddr[port] || entry->u.fifo.out != port)
             return soc_dma_port_other;
 
@@ -148,11 +149,12 @@  static inline enum soc_dma_port_type soc_dma_ch_update_type(
 
         /* TODO: support constant memory address for source port as used for
          * drawing solid rectangles by PalmOS(R).  */
-        if (ch->type[port] != soc_dma_access_const)
+        if (ch->type[port] != soc_dma_access_linear)
             return soc_dma_port_other;
 
         ch->paddr[port] = (uint8_t *) entry->u.mem.base +
                 (ch->vaddr[port] - entry->addr);
+
         /* TODO: save bytes left to the end of the mapping somewhere so we
          * can check we're not reading beyond it.  */
         return soc_dma_port_mem;