linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* kernel 2.6.15: cpm_uart driver broken?
@ 2006-04-18 19:19 Kenneth Poole
  2006-04-19  9:28 ` David Jander
  0 siblings, 1 reply; 13+ messages in thread
From: Kenneth Poole @ 2006-04-18 19:19 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 1055 bytes --]

For David Jander and Vitaly Bordug:

Regarding DMA allocation for CPM uarts, we had a similar issue with our
MPC857T and MPC885 boards. I think the real problem is that
bus_to_virt() and virt_to_bus() don't work on 8xx platforms for
addresses allocated using dma_alloc_coherent(). We had a previous
discussion Pantelis Antoniou and he agreed that the use of bus_to_virt()
and virt_to_bus() should be deprecated. This is also recommended in the
whitepaper series that discussed porting device drivers from 2.4 to 2.6.

What we did was use dma_alloc_coherent() in cpm_uart_cpm1.c, saving
dma_addr in the pinfo structure. The in cpm_uart_core.c, we use dma_addr
as the base address for the cbd_bufaddr values in each of the
descriptors. The software, when accessing the DMA buffers, uses mem_addr
as the base, applying the same offset computed previously for the dma
addresses. This technique is used in other drivers all over 2.6.

This avoids the configuration dependencies on the conversion functions.

Ken Poole
kpoole@bos.mrv.com


[-- Attachment #2: Type: text/html, Size: 5214 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread
* Re: kernel 2.6.15: cpm_uart driver broken?
@ 2007-10-25 13:54 raul.moreno
  0 siblings, 0 replies; 13+ messages in thread
From: raul.moreno @ 2007-10-25 13:54 UTC (permalink / raw)
  To: linuxppc-embedded



Hi,

I've found this thread, but I haven't seen the end of the discussion. I=
 am
using this kernel version, and I am also having problems with the cpm_u=
art.
Only the console (SMC1) is working, the other devices working as uart f=
ail.
I've realised that the problem is in the DMA. The system crash when the=
 Rx
and Tx buffers are allocated in external memory (in case of allocating =
in
the DPRAM of my mpc866, it works properly) and I don't know why. It is
supposed other devices (as fec) use the same functions
("dma_alloc_coherent") and they work.

Moreover I don't find any documentation about the parameters
"CONFIG_CONSISTENT_START" and "CONFIG_CONSISTENT_SIZE". Does these
parameters affect to the driver behaviour?

Could anyone help me?

Kind regards,

Ra=FAl Moreno
***********Internet Email Confidentiality Footer*************
This email and any files transmitted with it are confidential and inten=
ded
solely for the use of the organization or individual to whom they are
addressed.  It is expressly forbidden to retransmit or copy email and/o=
r
this  attached files without our permission .  If you are not the
addressee indicated in this message (or responsible for delivery of the=

message to such person), you may not copy or deliver this message
to anyone. In such case, you should destroy this message and kindly
notify the sender by reply email. Please advise immediately if you or
your employer does not consent to Internet email for messages of this
kind.  Opinions, conclusions and other information in this message that=

do not relate to the official business of my firm shall be understood a=
s
neither given nor endorsed by it.=

^ permalink raw reply	[flat|nested] 13+ messages in thread
* RE: kernel 2.6.15: cpm_uart driver broken?
@ 2006-04-19 20:40 Kenneth Poole
  2006-04-19 21:14 ` Dan Malek
  0 siblings, 1 reply; 13+ messages in thread
From: Kenneth Poole @ 2006-04-19 20:40 UTC (permalink / raw)
  To: Dan Malek; +Cc: David Jander, linuxppc-embedded

Hello Dan:

>
>From: Dan Malek [mailto:dan@embeddedalley.com]=20
>Sent: Wednesday, April 19, 2006 3:42 PM
>To: Kenneth Poole
>Cc: Vitaly Bordug; David Jander; linuxppc-embedded@ozlabs.org
>Subject: Re: kernel 2.6.15: cpm_uart driver broken?


>On Apr 19, 2006, at 3:24 PM, Kenneth Poole wrote:

>>
>>  		/* get pointer */
>> -		cp =3D cpm2cpu_addr(bdp->cbd_bufaddr);
>> +		cp =3D (unsigned char *)pinfo->mem_addr +
>> (bdp->cbd_bufaddr - pinfo->dma_addr);


>Ummm, no.  Keep the cpm2cpu_addr() and pass it
>some driver data structure pointer so it does the computes,
>

We did this to solve the problem mentioned earlier in this thread which
is that bus_to_virt() and virt_to_bus() don't work for memory allocated
with dma_alloc_coherent(). By saving the return value from
dma_alloc_coherent() in dma_addr, we avoid having to do those
conversions all of the time.

>or better, keep the phys/virt addresses in a handy data
>structure you can easily access and work with offsets within
>the different address spaces.

That's what we're doing by using dma_addr. We just compute the offset in
the physical address space and apply that offset in the virtual address
space. Some drivers keep both sets of pointers around for each buffer
allocated, and that would work as well.

>  The test of addr >=3D CPM_ADDR
>is critically important to early boot and kgdb support
>and can't be removed.

I assumed that this test was simply to exclude console ports from
conversion. But in cpm_uart_allocbuf() there already is a test (is_con).
For the console, we simply save the unconverted dma_addr in the port
structure once and use it normally. Our console port works just fine.
Testing addr >=3D CPM_ADDR forces very specific ordering onto the IMMR =
and
DMA address spaces, and I thought our approach was more general.=20

>> -		bdp->cbd_bufaddr =3D cpu2cpm_addr(mem_addr);
>> +		bdp->cbd_bufaddr =3D dma_addr;

>This kind of initialization is broken, too.  You have to test
>that memory address and return the proper space.

>Thanks.

>	-- Dan

^ permalink raw reply	[flat|nested] 13+ messages in thread
* RE: kernel 2.6.15: cpm_uart driver broken?
@ 2006-04-19 19:24 Kenneth Poole
  2006-04-19 19:42 ` Dan Malek
  0 siblings, 1 reply; 13+ messages in thread
From: Kenneth Poole @ 2006-04-19 19:24 UTC (permalink / raw)
  To: Vitaly Bordug, David Jander; +Cc: linuxppc-embedded




>If there is any code to reference, I'd appreciate it (and merge to the
>driver).=20

Ok, here's a patch, below. It includes changes for DMA buffer allocation
as discussed. This is untested, because the CPM uart driver for our
platforms has many other modifications that don't apply.

It also includes a fix for sending x_char in cpm_uart_tx_pump(). This
allows the actual x_char to be sent, instead of the next regular
character.

-------------------------------------------------------------
--- cpm_uart_core.c.orig	2006-04-19 10:24:47.000000000 -0400
+++ cpm_uart_core.c	2006-04-19 10:51:43.000000000 -0400
@@ -71,20 +71,6 @@
=20
 /**************************************************************/
=20
-static inline unsigned long cpu2cpm_addr(void *addr)
-{
-	if ((unsigned long)addr >=3D CPM_ADDR)
-		return (unsigned long)addr;
-	return virt_to_bus(addr);
-}
-
-static inline void *cpm2cpu_addr(unsigned long addr)
-{
-	if (addr >=3D CPM_ADDR)
-		return (void *)addr;
-	return bus_to_virt(addr);
-}
-
 /*
  * Check, if transmit buffers are processed
 */
@@ -261,7 +247,7 @@
 		}
=20
 		/* get pointer */
-		cp =3D cpm2cpu_addr(bdp->cbd_bufaddr);
+		cp =3D (unsigned char *)pinfo->mem_addr +
(bdp->cbd_bufaddr - pinfo->dma_addr);
=20
 		/* loop through the buffer */
 		while (i-- > 0) {
@@ -606,11 +592,12 @@
 		/* Pick next descriptor and fill from buffer */
 		bdp =3D pinfo->tx_cur;
=20
-		p =3D cpm2cpu_addr(bdp->cbd_bufaddr);
+		p =3D (unsigned char *)pinfo->mem_addr + (bdp->cbd_bufaddr
- pinfo->dma_addr);
=20
-		*p++ =3D xmit->buf[xmit->tail];
+		*p =3D port->x_char;
 		bdp->cbd_datlen =3D 1;
 		bdp->cbd_sc |=3D BD_SC_READY;
+		__asm__("eieio");
 		/* Get next BD. */
 		if (bdp->cbd_sc & BD_SC_WRAP)
 			bdp =3D pinfo->tx_bd_base;
@@ -633,7 +620,7 @@
=20
 	while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail !=3D
xmit->head)) {
 		count =3D 0;
-		p =3D cpm2cpu_addr(bdp->cbd_bufaddr);
+		p =3D (unsigned char *)pinfo->mem_addr + (bdp->cbd_bufaddr
- pinfo->dma_addr);
 		while (count < pinfo->tx_fifosize) {
 			*p++ =3D xmit->buf[xmit->tail];
 			xmit->tail =3D (xmit->tail + 1) & (UART_XMIT_SIZE
- 1);
@@ -670,39 +657,37 @@
 static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
 {
 	int i;
-	u8 *mem_addr;
+	dma_addr_t dma_addr;
 	volatile cbd_t *bdp;
=20
 	pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line);
=20
 	/* Set the physical address of the host memory
-	 * buffers in the buffer descriptors, and the
-	 * virtual address for us to work with.
+	 * buffers in the buffer descriptors.
 	 */
-	mem_addr =3D pinfo->mem_addr;
+	dma_addr =3D pinfo->dma_addr;
 	bdp =3D pinfo->rx_cur =3D pinfo->rx_bd_base;
 	for (i =3D 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
-		bdp->cbd_bufaddr =3D cpu2cpm_addr(mem_addr);
+		bdp->cbd_bufaddr =3D dma_addr;
 		bdp->cbd_sc =3D BD_SC_EMPTY | BD_SC_INTRPT;
-		mem_addr +=3D pinfo->rx_fifosize;
+		dma_addr +=3D pinfo->rx_fifosize;
 	}
-
-	bdp->cbd_bufaddr =3D cpu2cpm_addr(mem_addr);
+=09
+	bdp->cbd_bufaddr =3D dma_addr;
 	bdp->cbd_sc =3D BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
=20
 	/* Set the physical address of the host memory
-	 * buffers in the buffer descriptors, and the
-	 * virtual address for us to work with.
+	 * buffers in the buffer descriptors.
 	 */
-	mem_addr =3D pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos *
pinfo->rx_fifosize);
+	dma_addr =3D pinfo->dma_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos *
pinfo->rx_fifosize);
 	bdp =3D pinfo->tx_cur =3D pinfo->tx_bd_base;
 	for (i =3D 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
-		bdp->cbd_bufaddr =3D cpu2cpm_addr(mem_addr);
+		bdp->cbd_bufaddr =3D dma_addr;
 		bdp->cbd_sc =3D BD_SC_INTRPT;
-		mem_addr +=3D pinfo->tx_fifosize;
+		dma_addr +=3D pinfo->tx_fifosize;
 	}
-
-	bdp->cbd_bufaddr =3D cpu2cpm_addr(mem_addr);
+=09
+	bdp->cbd_bufaddr =3D dma_addr;
 	bdp->cbd_sc =3D BD_SC_WRAP | BD_SC_INTRPT;
 }
=20
@@ -1032,7 +1017,7 @@
 		 * If the buffer address is in the CPM DPRAM, don't
 		 * convert it.
 		 */
-		cp =3D cpm2cpu_addr(bdp->cbd_bufaddr);
+		cp =3D (unsigned char *)pinfo->mem_addr +
(bdp->cbd_bufaddr - pinfo->dma_addr);
=20
 		*cp =3D *s;
=20
@@ -1049,7 +1034,7 @@
 			while ((bdp->cbd_sc & BD_SC_READY) !=3D 0)
 				;
=20
-			cp =3D cpm2cpu_addr(bdp->cbd_bufaddr);
+			cp =3D (unsigned char *)pinfo->mem_addr +
(bdp->cbd_bufaddr - pinfo->dma_addr);
=20
 			*cp =3D 13;
 			bdp->cbd_datlen =3D 1;
--- cpm_uart_cpm1.c.orig	2006-04-19 10:26:46.000000000 -0400
+++ cpm_uart_cpm1.c	2006-04-19 10:32:05.000000000 -0400
@@ -191,7 +191,7 @@
 		/* was hostalloc but changed cause it blows away the */
 		/* large tlb mapping when pinning the kernel area    */
 		mem_addr =3D (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
-		dma_addr =3D 0;
+		dma_addr =3D (dma_addr_t)mem_addr;
 	} else
 		mem_addr =3D dma_alloc_coherent(NULL, memsz, &dma_addr,
 					      GFP_KERNEL);

----------------------------------------------------------

Ken Poole
kpoole@bos.mrv.com
=20

^ permalink raw reply	[flat|nested] 13+ messages in thread
* kernel 2.6.15: cpm_uart driver broken?
@ 2006-04-18 12:46 David Jander
  2006-04-18 13:22 ` Vitaly Bordug
  0 siblings, 1 reply; 13+ messages in thread
From: David Jander @ 2006-04-18 12:46 UTC (permalink / raw)
  To: linuxppc-embedded


Hi all,

Situation 1: MPC852T with SMC1 as uart/console, and SCC3/SCC4 as additional 
uarts. SMC1 works fine, but SCC3/4 don't. On transmission attempt, both UARTS 
transmit a byte 0x00 instead of what was intended to be transmitted.\

Situation 2: The same as above, but console on either SCC3 or SCC4. The uart 
being initialized as console works ok, the other two don't.

I'm pretty sure the following is wrong, but I can't seem to fix it either. 
This seems to apply for both PQ and PQ2 type uarts:
from drivers/serial/cpm_uart/cpm_uart_cpm1.c (line 190):

....
	if (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;
	} else
		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
					      GFP_KERNEL);

....
	pinfo->dp_addr = dp_offset;
	pinfo->mem_addr = mem_addr;
	pinfo->dma_addr = dma_addr;

	pinfo->rx_buf = mem_addr;
....

AFAICS pinfo->rx_buf is the pointer to a buffer as seen from the CPM's point 
of view, so it should hold a physical adress, not a virtual address. It seems 
to me that it should be more like this (lines marked with ** are changed):

....
	if (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 = mem_addr;
	} else
		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
					      GFP_KERNEL);

....
	pinfo->dp_addr = dp_offset;
	pinfo->mem_addr = mem_addr;
	pinfo->dma_addr = dma_addr;

**	pinfo->rx_buf = dma_addr;
....

This does not work either, but I suspect this is a different problem, because 
if I change dma_alloc_coherent() for something using kmalloc() and then 
dma_addr=virt_to_phys(mem_addr), uarts begin to work, but trasmit mixed old 
and new data from the buffers due to the cache getting in the way. At least 
reception seems to work ok then. 
So, why doesn't dma_alloc_coherent() work the way one would expect?
Obviously, changing "if (is_con)" into "if (1)" all three uarts work 
correctly, but I guess we want to save on DP_RAM usage if ever possible.

What else is wrong here?

Greetings,

-- 
David Jander

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2007-10-25 13:53 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-18 19:19 kernel 2.6.15: cpm_uart driver broken? Kenneth Poole
2006-04-19  9:28 ` David Jander
2006-04-19 10:21   ` Vitaly Bordug
  -- strict thread matches above, loose matches on Subject: below --
2007-10-25 13:54 raul.moreno
2006-04-19 20:40 Kenneth Poole
2006-04-19 21:14 ` Dan Malek
2006-04-20  7:41   ` David Jander
2006-04-19 19:24 Kenneth Poole
2006-04-19 19:42 ` Dan Malek
2006-04-18 12:46 David Jander
2006-04-18 13:22 ` Vitaly Bordug
2006-04-18 14:05   ` David Jander
2006-04-18 14:21     ` Vitaly Bordug

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).