Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] ppc32 CPM_UART: Fixed odd address translations

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>

authored by

Vitaly Bordug and committed by
Paul Mackerras
09b03b6c 4427d6bf

+50 -26
+33
drivers/serial/cpm_uart/cpm_uart.h
··· 66 uint dp_addr; 67 void *mem_addr; 68 dma_addr_t dma_addr; 69 /* helpers */ 70 int baud; 71 int bits; ··· 92 void scc2_lineif(struct uart_cpm_port *pinfo); 93 void scc3_lineif(struct uart_cpm_port *pinfo); 94 void scc4_lineif(struct uart_cpm_port *pinfo); 95 96 #endif /* CPM_UART_H */
··· 66 uint dp_addr; 67 void *mem_addr; 68 dma_addr_t dma_addr; 69 + u32 mem_size; 70 /* helpers */ 71 int baud; 72 int bits; ··· 91 void scc2_lineif(struct uart_cpm_port *pinfo); 92 void scc3_lineif(struct uart_cpm_port *pinfo); 93 void scc4_lineif(struct uart_cpm_port *pinfo); 94 + 95 + /* 96 + virtual to phys transtalion 97 + */ 98 + static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo) 99 + { 100 + int offset; 101 + u32 val = (u32)addr; 102 + /* sane check */ 103 + if ((val >= (u32)pinfo->mem_addr) && 104 + (val<((u32)pinfo->mem_addr + pinfo->mem_size))) { 105 + offset = val - (u32)pinfo->mem_addr; 106 + return pinfo->dma_addr+offset; 107 + } 108 + printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val); 109 + return 0; 110 + } 111 + 112 + static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo) 113 + { 114 + int offset; 115 + u32 val = addr; 116 + /* sane check */ 117 + if ((val >= pinfo->dma_addr) && 118 + (val<(pinfo->dma_addr + pinfo->mem_size))) { 119 + offset = val - (u32)pinfo->dma_addr; 120 + return (void*)(pinfo->mem_addr+offset); 121 + } 122 + printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val); 123 + return 0; 124 + } 125 + 126 127 #endif /* CPM_UART_H */
+9 -22
drivers/serial/cpm_uart/cpm_uart_core.c
··· 72 73 /**************************************************************/ 74 75 - static inline unsigned long cpu2cpm_addr(void *addr) 76 - { 77 - if ((unsigned long)addr >= CPM_ADDR) 78 - return (unsigned long)addr; 79 - return virt_to_bus(addr); 80 - } 81 - 82 - static inline void *cpm2cpu_addr(unsigned long addr) 83 - { 84 - if (addr >= CPM_ADDR) 85 - return (void *)addr; 86 - return bus_to_virt(addr); 87 - } 88 89 /* Place-holder for board-specific stuff */ 90 struct platform_device* __attribute__ ((weak)) __init ··· 277 } 278 279 /* get pointer */ 280 - cp = cpm2cpu_addr(bdp->cbd_bufaddr); 281 282 /* loop through the buffer */ 283 while (i-- > 0) { ··· 620 /* Pick next descriptor and fill from buffer */ 621 bdp = pinfo->tx_cur; 622 623 - p = cpm2cpu_addr(bdp->cbd_bufaddr); 624 625 *p++ = port->x_char; 626 bdp->cbd_datlen = 1; ··· 647 648 while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { 649 count = 0; 650 - p = cpm2cpu_addr(bdp->cbd_bufaddr); 651 while (count < pinfo->tx_fifosize) { 652 *p++ = xmit->buf[xmit->tail]; 653 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); ··· 696 mem_addr = pinfo->mem_addr; 697 bdp = pinfo->rx_cur = pinfo->rx_bd_base; 698 for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { 699 - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); 700 bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; 701 mem_addr += pinfo->rx_fifosize; 702 } 703 704 - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); 705 bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; 706 707 /* Set the physical address of the host memory ··· 711 mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); 712 bdp = pinfo->tx_cur = pinfo->tx_bd_base; 713 for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { 714 - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); 715 bdp->cbd_sc = BD_SC_INTRPT; 716 mem_addr += pinfo->tx_fifosize; 717 } 718 719 - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); 720 bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; 721 } 722 ··· 1086 * If the buffer address is in the CPM DPRAM, don't 1087 * convert it. 1088 */ 1089 - cp = cpm2cpu_addr(bdp->cbd_bufaddr); 1090 1091 *cp = *s; 1092 ··· 1103 while ((bdp->cbd_sc & BD_SC_READY) != 0) 1104 ; 1105 1106 - cp = cpm2cpu_addr(bdp->cbd_bufaddr); 1107 1108 *cp = 13; 1109 bdp->cbd_datlen = 1;
··· 72 73 /**************************************************************/ 74 75 76 /* Place-holder for board-specific stuff */ 77 struct platform_device* __attribute__ ((weak)) __init ··· 290 } 291 292 /* get pointer */ 293 + cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); 294 295 /* loop through the buffer */ 296 while (i-- > 0) { ··· 633 /* Pick next descriptor and fill from buffer */ 634 bdp = pinfo->tx_cur; 635 636 + p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); 637 638 *p++ = port->x_char; 639 bdp->cbd_datlen = 1; ··· 660 661 while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { 662 count = 0; 663 + p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); 664 while (count < pinfo->tx_fifosize) { 665 *p++ = xmit->buf[xmit->tail]; 666 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); ··· 709 mem_addr = pinfo->mem_addr; 710 bdp = pinfo->rx_cur = pinfo->rx_bd_base; 711 for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { 712 + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); 713 bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; 714 mem_addr += pinfo->rx_fifosize; 715 } 716 717 + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); 718 bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; 719 720 /* Set the physical address of the host memory ··· 724 mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); 725 bdp = pinfo->tx_cur = pinfo->tx_bd_base; 726 for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { 727 + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); 728 bdp->cbd_sc = BD_SC_INTRPT; 729 mem_addr += pinfo->tx_fifosize; 730 } 731 732 + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); 733 bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; 734 } 735 ··· 1099 * If the buffer address is in the CPM DPRAM, don't 1100 * convert it. 1101 */ 1102 + cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); 1103 1104 *cp = *s; 1105 ··· 1116 while ((bdp->cbd_sc & BD_SC_READY) != 0) 1117 ; 1118 1119 + cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); 1120 1121 *cp = 13; 1122 bdp->cbd_datlen = 1;
+4 -3
drivers/serial/cpm_uart/cpm_uart_cpm1.c
··· 144 /* was hostalloc but changed cause it blows away the */ 145 /* large tlb mapping when pinning the kernel area */ 146 mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); 147 - dma_addr = 0; 148 } else 149 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, 150 GFP_KERNEL); ··· 157 } 158 159 pinfo->dp_addr = dp_offset; 160 - pinfo->mem_addr = mem_addr; 161 - pinfo->dma_addr = dma_addr; 162 163 pinfo->rx_buf = mem_addr; 164 pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
··· 144 /* was hostalloc but changed cause it blows away the */ 145 /* large tlb mapping when pinning the kernel area */ 146 mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); 147 + dma_addr = (u32)mem_addr; 148 } else 149 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, 150 GFP_KERNEL); ··· 157 } 158 159 pinfo->dp_addr = dp_offset; 160 + pinfo->mem_addr = mem_addr; /* virtual address*/ 161 + pinfo->dma_addr = dma_addr; /* physical address*/ 162 + pinfo->mem_size = memsz; 163 164 pinfo->rx_buf = mem_addr; 165 pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
+4 -1
drivers/serial/cpm_uart/cpm_uart_cpm2.c
··· 209 210 memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + 211 L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); 212 - if (is_con) 213 mem_addr = alloc_bootmem(memsz); 214 else 215 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, 216 GFP_KERNEL); ··· 227 pinfo->dp_addr = dp_offset; 228 pinfo->mem_addr = mem_addr; 229 pinfo->dma_addr = dma_addr; 230 231 pinfo->rx_buf = mem_addr; 232 pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
··· 209 210 memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + 211 L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); 212 + if (is_con) { 213 mem_addr = alloc_bootmem(memsz); 214 + dma_addr = mem_addr; 215 + } 216 else 217 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, 218 GFP_KERNEL); ··· 225 pinfo->dp_addr = dp_offset; 226 pinfo->mem_addr = mem_addr; 227 pinfo->dma_addr = dma_addr; 228 + pinfo->mem_size = memsz; 229 230 pinfo->rx_buf = mem_addr; 231 pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos