aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorVitaly Bordug <vbordug@ru.mvista.com>2006-04-25 12:26:46 -0400
committerPaul Mackerras <paulus@samba.org>2006-04-28 07:11:33 -0400
commit09b03b6c29638eb5c79b02e585cb1b20d91a8ea0 (patch)
treec6348427c9b785a90db7f87d55903c6b75804170 /drivers/serial
parent4427d6bf966379304f77b7cc8c92421e6bb95483 (diff)
[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>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/cpm_uart/cpm_uart.h33
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c31
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c7
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c5
4 files changed, 50 insertions, 26 deletions
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 17f2c7aa4503..aa5eb7ddeda9 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -66,6 +66,7 @@ struct uart_cpm_port {
66 uint dp_addr; 66 uint dp_addr;
67 void *mem_addr; 67 void *mem_addr;
68 dma_addr_t dma_addr; 68 dma_addr_t dma_addr;
69 u32 mem_size;
69 /* helpers */ 70 /* helpers */
70 int baud; 71 int baud;
71 int bits; 72 int bits;
@@ -92,4 +93,36 @@ void scc2_lineif(struct uart_cpm_port *pinfo);
92void scc3_lineif(struct uart_cpm_port *pinfo); 93void scc3_lineif(struct uart_cpm_port *pinfo);
93void scc4_lineif(struct uart_cpm_port *pinfo); 94void scc4_lineif(struct uart_cpm_port *pinfo);
94 95
96/*
97 virtual to phys transtalion
98*/
99static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo)
100{
101 int offset;
102 u32 val = (u32)addr;
103 /* sane check */
104 if ((val >= (u32)pinfo->mem_addr) &&
105 (val<((u32)pinfo->mem_addr + pinfo->mem_size))) {
106 offset = val - (u32)pinfo->mem_addr;
107 return pinfo->dma_addr+offset;
108 }
109 printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val);
110 return 0;
111}
112
113static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo)
114{
115 int offset;
116 u32 val = addr;
117 /* sane check */
118 if ((val >= pinfo->dma_addr) &&
119 (val<(pinfo->dma_addr + pinfo->mem_size))) {
120 offset = val - (u32)pinfo->dma_addr;
121 return (void*)(pinfo->mem_addr+offset);
122 }
123 printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val);
124 return 0;
125}
126
127
95#endif /* CPM_UART_H */ 128#endif /* CPM_UART_H */
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 9a5b044ce068..ced193bf9e1e 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -72,19 +72,6 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
72 72
73/**************************************************************/ 73/**************************************************************/
74 74
75static 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
82static 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 75
89/* Place-holder for board-specific stuff */ 76/* Place-holder for board-specific stuff */
90struct platform_device* __attribute__ ((weak)) __init 77struct platform_device* __attribute__ ((weak)) __init
@@ -290,7 +277,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
290 } 277 }
291 278
292 /* get pointer */ 279 /* get pointer */
293 cp = cpm2cpu_addr(bdp->cbd_bufaddr); 280 cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
294 281
295 /* loop through the buffer */ 282 /* loop through the buffer */
296 while (i-- > 0) { 283 while (i-- > 0) {
@@ -633,7 +620,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
633 /* Pick next descriptor and fill from buffer */ 620 /* Pick next descriptor and fill from buffer */
634 bdp = pinfo->tx_cur; 621 bdp = pinfo->tx_cur;
635 622
636 p = cpm2cpu_addr(bdp->cbd_bufaddr); 623 p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
637 624
638 *p++ = port->x_char; 625 *p++ = port->x_char;
639 bdp->cbd_datlen = 1; 626 bdp->cbd_datlen = 1;
@@ -660,7 +647,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
660 647
661 while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { 648 while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
662 count = 0; 649 count = 0;
663 p = cpm2cpu_addr(bdp->cbd_bufaddr); 650 p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
664 while (count < pinfo->tx_fifosize) { 651 while (count < pinfo->tx_fifosize) {
665 *p++ = xmit->buf[xmit->tail]; 652 *p++ = xmit->buf[xmit->tail];
666 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 653 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -709,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
709 mem_addr = pinfo->mem_addr; 696 mem_addr = pinfo->mem_addr;
710 bdp = pinfo->rx_cur = pinfo->rx_bd_base; 697 bdp = pinfo->rx_cur = pinfo->rx_bd_base;
711 for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { 698 for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
712 bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); 699 bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
713 bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; 700 bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
714 mem_addr += pinfo->rx_fifosize; 701 mem_addr += pinfo->rx_fifosize;
715 } 702 }
716 703
717 bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); 704 bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
718 bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; 705 bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
719 706
720 /* Set the physical address of the host memory 707 /* Set the physical address of the host memory
@@ -724,12 +711,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
724 mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); 711 mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
725 bdp = pinfo->tx_cur = pinfo->tx_bd_base; 712 bdp = pinfo->tx_cur = pinfo->tx_bd_base;
726 for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { 713 for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
727 bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); 714 bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
728 bdp->cbd_sc = BD_SC_INTRPT; 715 bdp->cbd_sc = BD_SC_INTRPT;
729 mem_addr += pinfo->tx_fifosize; 716 mem_addr += pinfo->tx_fifosize;
730 } 717 }
731 718
732 bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); 719 bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
733 bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; 720 bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
734} 721}
735 722
@@ -1099,7 +1086,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
1099 * If the buffer address is in the CPM DPRAM, don't 1086 * If the buffer address is in the CPM DPRAM, don't
1100 * convert it. 1087 * convert it.
1101 */ 1088 */
1102 cp = cpm2cpu_addr(bdp->cbd_bufaddr); 1089 cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
1103 1090
1104 *cp = *s; 1091 *cp = *s;
1105 1092
@@ -1116,7 +1103,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
1116 while ((bdp->cbd_sc & BD_SC_READY) != 0) 1103 while ((bdp->cbd_sc & BD_SC_READY) != 0)
1117 ; 1104 ;
1118 1105
1119 cp = cpm2cpu_addr(bdp->cbd_bufaddr); 1106 cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
1120 1107
1121 *cp = 13; 1108 *cp = 13;
1122 bdp->cbd_datlen = 1; 1109 bdp->cbd_datlen = 1;
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 31223aa862f5..a5a30622637a 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -144,7 +144,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
144 /* was hostalloc but changed cause it blows away the */ 144 /* was hostalloc but changed cause it blows away the */
145 /* large tlb mapping when pinning the kernel area */ 145 /* large tlb mapping when pinning the kernel area */
146 mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); 146 mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
147 dma_addr = 0; 147 dma_addr = (u32)mem_addr;
148 } else 148 } else
149 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, 149 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
150 GFP_KERNEL); 150 GFP_KERNEL);
@@ -157,8 +157,9 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
157 } 157 }
158 158
159 pinfo->dp_addr = dp_offset; 159 pinfo->dp_addr = dp_offset;
160 pinfo->mem_addr = mem_addr; 160 pinfo->mem_addr = mem_addr; /* virtual address*/
161 pinfo->dma_addr = dma_addr; 161 pinfo->dma_addr = dma_addr; /* physical address*/
162 pinfo->mem_size = memsz;
162 163
163 pinfo->rx_buf = mem_addr; 164 pinfo->rx_buf = mem_addr;
164 pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos 165 pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index c9c3b1d8810b..7c6b07aeea92 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -209,8 +209,10 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
209 209
210 memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + 210 memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
211 L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); 211 L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
212 if (is_con) 212 if (is_con) {
213 mem_addr = alloc_bootmem(memsz); 213 mem_addr = alloc_bootmem(memsz);
214 dma_addr = mem_addr;
215 }
214 else 216 else
215 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, 217 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
216 GFP_KERNEL); 218 GFP_KERNEL);
@@ -225,6 +227,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
225 pinfo->dp_addr = dp_offset; 227 pinfo->dp_addr = dp_offset;
226 pinfo->mem_addr = mem_addr; 228 pinfo->mem_addr = mem_addr;
227 pinfo->dma_addr = dma_addr; 229 pinfo->dma_addr = dma_addr;
230 pinfo->mem_size = memsz;
228 231
229 pinfo->rx_buf = mem_addr; 232 pinfo->rx_buf = mem_addr;
230 pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos 233 pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos