[PATCH] ppc32 CPM_UART: Fixed odd address translations
authorVitaly Bordug <vbordug@ru.mvista.com>
Tue, 25 Apr 2006 16:26:46 +0000 (20:26 +0400)
committerPaul Mackerras <paulus@samba.org>
Fri, 28 Apr 2006 11:11:33 +0000 (21:11 +1000)
Current address translation methods can produce wrong results, because
virt_to_bus and vice versa may not produce correct offsets on dma-allocated
memory. The right way is, while tracking both phys and virt address of the
window that has been allocated for boffer descriptors, and use those
numbers to compute the offset and make translation properly.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
drivers/serial/cpm_uart/cpm_uart.h
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/cpm_uart/cpm_uart_cpm1.c
drivers/serial/cpm_uart/cpm_uart_cpm2.c

index 17f2c7aa45033f92bfdf129586f28e5cddc9bf71..aa5eb7ddeda9adf3b41a61ecbc716502fb2392c0 100644 (file)
@@ -66,6 +66,7 @@ struct uart_cpm_port {
        uint                     dp_addr;
        void                    *mem_addr;
        dma_addr_t               dma_addr;
+       u32                     mem_size;
        /* helpers */
        int                      baud;
        int                      bits;
@@ -92,4 +93,36 @@ void scc2_lineif(struct uart_cpm_port *pinfo);
 void scc3_lineif(struct uart_cpm_port *pinfo);
 void scc4_lineif(struct uart_cpm_port *pinfo);
 
+/*
+   virtual to phys transtalion
+*/
+static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo)
+{
+       int offset;
+       u32 val = (u32)addr;
+       /* sane check */
+       if ((val >= (u32)pinfo->mem_addr) &&
+                       (val<((u32)pinfo->mem_addr + pinfo->mem_size))) {
+               offset = val - (u32)pinfo->mem_addr;
+               return pinfo->dma_addr+offset;
+       }
+       printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val);
+       return 0;
+}
+
+static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo)
+{
+       int offset;
+       u32 val = addr;
+       /* sane check */
+       if ((val >= pinfo->dma_addr) &&
+                       (val<(pinfo->dma_addr + pinfo->mem_size))) {
+               offset = val - (u32)pinfo->dma_addr;
+               return (void*)(pinfo->mem_addr+offset);
+       }
+       printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val);
+       return 0;
+}
+
+
 #endif /* CPM_UART_H */
index 9a5b044ce06864ec56903e9920408a3a843b6055..ced193bf9e1ebbcec6df30924f8c8285cc079970 100644 (file)
@@ -72,19 +72,6 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
 
 /**************************************************************/
 
-static inline unsigned long cpu2cpm_addr(void *addr)
-{
-       if ((unsigned long)addr >= CPM_ADDR)
-               return (unsigned long)addr;
-       return virt_to_bus(addr);
-}
-
-static inline void *cpm2cpu_addr(unsigned long addr)
-{
-       if (addr >= CPM_ADDR)
-               return (void *)addr;
-       return bus_to_virt(addr);
-}
 
 /* Place-holder for board-specific stuff */
 struct platform_device* __attribute__ ((weak)) __init
@@ -290,7 +277,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
                }
 
                /* get pointer */
-               cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+               cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
 
                /* loop through the buffer */
                while (i-- > 0) {
@@ -633,7 +620,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
                /* Pick next descriptor and fill from buffer */
                bdp = pinfo->tx_cur;
 
-               p = cpm2cpu_addr(bdp->cbd_bufaddr);
+               p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
 
                *p++ = port->x_char;
                bdp->cbd_datlen = 1;
@@ -660,7 +647,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
 
        while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
                count = 0;
-               p = cpm2cpu_addr(bdp->cbd_bufaddr);
+               p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
                while (count < pinfo->tx_fifosize) {
                        *p++ = xmit->buf[xmit->tail];
                        xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -709,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
        mem_addr = pinfo->mem_addr;
        bdp = pinfo->rx_cur = pinfo->rx_bd_base;
        for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
-               bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+               bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
                bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
                mem_addr += pinfo->rx_fifosize;
        }
 
-       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
        bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
 
        /* Set the physical address of the host memory
@@ -724,12 +711,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
        mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
        bdp = pinfo->tx_cur = pinfo->tx_bd_base;
        for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
-               bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+               bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
                bdp->cbd_sc = BD_SC_INTRPT;
                mem_addr += pinfo->tx_fifosize;
        }
 
-       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
        bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
 }
 
@@ -1099,7 +1086,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                 * If the buffer address is in the CPM DPRAM, don't
                 * convert it.
                 */
-               cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+               cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
 
                *cp = *s;
 
@@ -1116,7 +1103,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                        while ((bdp->cbd_sc & BD_SC_READY) != 0)
                                ;
 
-                       cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+                       cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
 
                        *cp = 13;
                        bdp->cbd_datlen = 1;
index 31223aa862f54be2961de4142dcf4f2fc5ad9d16..a5a30622637a33d1ed80dbacbbdd41b33b1d0d37 100644 (file)
@@ -144,7 +144,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
                /* was hostalloc but changed cause it blows away the */
                /* large tlb mapping when pinning the kernel area    */
                mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
-               dma_addr = 0;
+               dma_addr = (u32)mem_addr;
        } else
                mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
                                              GFP_KERNEL);
@@ -157,8 +157,9 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
        }
 
        pinfo->dp_addr = dp_offset;
-       pinfo->mem_addr = mem_addr;
-       pinfo->dma_addr = dma_addr;
+       pinfo->mem_addr = mem_addr;             /*  virtual address*/
+       pinfo->dma_addr = dma_addr;             /*  physical address*/
+       pinfo->mem_size = memsz;
 
        pinfo->rx_buf = mem_addr;
        pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
index c9c3b1d8810b0b4295d9bdacbf5ad73aefcd0156..7c6b07aeea9254cf2ca2f214e372af9615ab1a35 100644 (file)
@@ -209,8 +209,10 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
 
        memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
            L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
-       if (is_con)
+       if (is_con) {
                mem_addr = alloc_bootmem(memsz);
+               dma_addr = mem_addr;
+       }
        else
                mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
                                              GFP_KERNEL);
@@ -225,6 +227,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
        pinfo->dp_addr = dp_offset;
        pinfo->mem_addr = mem_addr;
        pinfo->dma_addr = dma_addr;
+       pinfo->mem_size = memsz;
 
        pinfo->rx_buf = mem_addr;
        pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos