All of lore.kernel.org
 help / color / mirror / Atom feed
* Strange transmit corruption in jsm driver on geode sc1200 system
@ 2006-08-25 20:30 Lennart Sorensen
  2006-08-25 21:20 ` Alan Cox
  0 siblings, 1 reply; 9+ messages in thread
From: Lennart Sorensen @ 2006-08-25 20:30 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Len Sorensen

I am seeing a very strange problem with the jsm driver.

I am using a Digi Neo 2 DB9 card on a system with a Geode SC1200 cpu.
This is essentially an EXAR XC17D152 chip rebranded for Digi.

Kernel is based on debian's 2.6.16-17 which is 2.6.16.25 with a few
patches.

When I use minicom to transmit a chunk of text by sending a text file,
the data is transmitted in the wrong order.

testfile:
0123456789ABCDEF

Received text:
123056749AB8DEFC

If I use the same driver and the same card on a P4 system, everything
works fine.

The driver is doing memcpy_toio to tranfer data to the transmit FIFO
(which is a 64byte memory mapped block of memory on the PCI bus as far
as I can tell).  The data in the transmit queue is in the right order
being passed to memcpy_toio, but somehow by the time it is in the uart
and goes out the transmiter, every 4th byte is moved 3 bytes back.
Transmitting a single character at a time works fine of course since
there is nothing to swap it around with, and it is only copying a single
byte to the UART rather than a block of bytes.

I read something about the geodes doing memory write reordering, but
that it is supposed to magically not screw up PCI writes.  I have no
idea if it is or not though.

I have no problem with pcnet32 or any of the other PCI devices I use.

Does anyone have any suggestions for something to try?

The cpu in question has this information:
processor       : 0
vendor_id       : CyrixInstead
cpu family      : 5
model           : 9
model name      : Unknown
stepping        : 1
cpu MHz         : 266.760
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 2
wp              : yes
flags           : fpu tsc msr cx8 cmov mmx cxmmx
bogomips        : 535.33

I noticed that cyrix.c has some code for controlling reordering and
such, although it doesn't seem to match this particular cpu's ID, so it
isn't called.  I have no idea if it should have.

--
Len Sorensen

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

* Re: Strange transmit corruption in jsm driver on geode sc1200 system
  2006-08-25 21:20 ` Alan Cox
@ 2006-08-25 21:03   ` Lennart Sorensen
  2006-08-25 21:24     ` Alexey Dobriyan
  0 siblings, 1 reply; 9+ messages in thread
From: Lennart Sorensen @ 2006-08-25 21:03 UTC (permalink / raw)
  To: Alan Cox; +Cc: Linux Kernel Mailing List

On Fri, Aug 25, 2006 at 10:20:17PM +0100, Alan Cox wrote:
> That should be staying in order unless the device memory is mislabelled
> and prefetchable etc.

Hmm, no according to lspci the memory is labeled non-prefetachble, and
the pci bridge agrees with that setting too.

> What happens if you swap the memcpy_toio with while() writeb() ?

I tried changing it to a for loop that calles memcpy_toio with one byte
at a time, and it works fine that way (although probably less
efficient).  I expect the writeb one at a time will work too.

> They do a lot of stuff but it should not affect the PCI side and I'd
> expect it to do other things than byte lane re-ordering.

Yeah no kidding.

> Is the buffer 32bit aligned ?

I honestly don't know.  I am just trying to figure out why the jsm
driver isn't working on this system while it works on other types of
hardware, and so far it seems to come down to the __memcpy assembly not
being happy on the SC1200 doing more than one byte at a time.  it is
very consistently making the same mistake all the time.

--
Len Sorensen

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

* Re: Strange transmit corruption in jsm driver on geode sc1200 system
  2006-08-25 20:30 Strange transmit corruption in jsm driver on geode sc1200 system Lennart Sorensen
@ 2006-08-25 21:20 ` Alan Cox
  2006-08-25 21:03   ` Lennart Sorensen
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Cox @ 2006-08-25 21:20 UTC (permalink / raw)
  To: Lennart Sorensen; +Cc: Linux Kernel Mailing List

Ar Gwe, 2006-08-25 am 16:30 -0400, ysgrifennodd Lennart Sorensen:
> The driver is doing memcpy_toio to tranfer data to the transmit FIFO
> (which is a 64byte memory mapped block of memory on the PCI bus as far
> as I can tell).  The data in the transmit queue is in the right order

That should be staying in order unless the device memory is mislabelled
and prefetchable etc.

> being passed to memcpy_toio, but somehow by the time it is in the uart
> and goes out the transmiter, every 4th byte is moved 3 bytes back.

What happens if you swap the memcpy_toio with while() writeb() ?

> I read something about the geodes doing memory write reordering, but
> that it is supposed to magically not screw up PCI writes.  I have no
> idea if it is or not though.

They do a lot of stuff but it should not affect the PCI side and I'd
expect it to do other things than byte lane re-ordering.

> Does anyone have any suggestions for something to try?

Is the buffer 32bit aligned ?



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

* Re: Strange transmit corruption in jsm driver on geode sc1200 system
  2006-08-25 21:03   ` Lennart Sorensen
@ 2006-08-25 21:24     ` Alexey Dobriyan
  2006-08-25 21:57       ` Lennart Sorensen
  0 siblings, 1 reply; 9+ messages in thread
From: Alexey Dobriyan @ 2006-08-25 21:24 UTC (permalink / raw)
  To: Lennart Sorensen; +Cc: Alan Cox, linux-kernel

On Fri, Aug 25, 2006 at 05:03:05PM -0400, Lennart Sorensen wrote:
> > Is the buffer 32bit aligned ?
>
> I honestly don't know.

But you can check. Insert something like this in right place:

	printk("%p\n", buffer);

> I am just trying to figure out why the jsm
> driver isn't working on this system while it works on other types of
> hardware, and so far it seems to come down to the __memcpy assembly not
> being happy on the SC1200 doing more than one byte at a time.  it is
> very consistently making the same mistake all the time.


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

* Re: Strange transmit corruption in jsm driver on geode sc1200 system
  2006-08-25 21:24     ` Alexey Dobriyan
@ 2006-08-25 21:57       ` Lennart Sorensen
  2006-08-28 17:30         ` Lennart Sorensen
  2006-08-28 18:11         ` Lennart Sorensen
  0 siblings, 2 replies; 9+ messages in thread
From: Lennart Sorensen @ 2006-08-25 21:57 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Alan Cox, linux-kernel

On Sat, Aug 26, 2006 at 01:24:41AM +0400, Alexey Dobriyan wrote:
> But you can check. Insert something like this in right place:
> 
> 	printk("%p\n", buffer);

It would be 1/4 of the time given the code is this:

memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);

tail is the offset in the write queue in the jsm driver, which can be
any offset whatsoever.  So sometimes it is 32bit aligned, but often it
isn't.

The txrxburst of course is 32bit alligned.  Receiving works fine when
copying from the alligned buffer in hardware to wherever in the receiver
queue.

Of course given the __memcpy assembly seems to work fine unalligned on a
pentium4, and probably most othe systems, what could make it not work
correctly on a geode SC1200?

This is the chunk of assembly in use:

static __always_inline void * __memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
        "rep ; movsl\n\t"
        "movl %4,%%ecx\n\t"
        "andl $3,%%ecx\n\t"
#if 1   /* want to pay 2 byte penalty for a chance to skip microcoded rep? */
        "jz 1f\n\t"
#endif
        "rep ; movsb\n\t"
        "1:"
        : "=&c" (d0), "=&D" (d1), "=&S" (d2)
        : "0" (n/4), "g" (n), "1" ((long) to), "2" ((long) from)
        : "memory");
return (to);
}

I am affraid I don't know the rep instruction on x86, so it really
doesn't make sense to me.

I suppose if nothing else works, I can do one byte at a time until the
tail is 32bit alligned, and then do the rest of the transfer as a block
and see if that makes it work, or whether it is broken no matter what
the allignement of the buffer is.

--
Len Sorensen

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

* Re: Strange transmit corruption in jsm driver on geode sc1200 system
  2006-08-25 21:57       ` Lennart Sorensen
@ 2006-08-28 17:30         ` Lennart Sorensen
  2006-08-28 18:11         ` Lennart Sorensen
  1 sibling, 0 replies; 9+ messages in thread
From: Lennart Sorensen @ 2006-08-28 17:30 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Alan Cox, linux-kernel

On Fri, Aug 25, 2006 at 05:57:24PM -0400, Lennart Sorensen wrote:
> It would be 1/4 of the time given the code is this:
> 
> memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);
> 
> tail is the offset in the write queue in the jsm driver, which can be
> any offset whatsoever.  So sometimes it is 32bit aligned, but often it
> isn't.
> 
> The txrxburst of course is 32bit alligned.  Receiving works fine when
> copying from the alligned buffer in hardware to wherever in the receiver
> queue.
> 
> Of course given the __memcpy assembly seems to work fine unalligned on a
> pentium4, and probably most othe systems, what could make it not work
> correctly on a geode SC1200?
> 
> This is the chunk of assembly in use:
> 
> static __always_inline void * __memcpy(void * to, const void * from, size_t n)
> {
> int d0, d1, d2;
> __asm__ __volatile__(
>         "rep ; movsl\n\t"
>         "movl %4,%%ecx\n\t"
>         "andl $3,%%ecx\n\t"
> #if 1   /* want to pay 2 byte penalty for a chance to skip microcoded rep? */
>         "jz 1f\n\t"
> #endif
>         "rep ; movsb\n\t"
>         "1:"
>         : "=&c" (d0), "=&D" (d1), "=&S" (d2)
>         : "0" (n/4), "g" (n), "1" ((long) to), "2" ((long) from)
>         : "memory");
> return (to);
> }
> 
> I am affraid I don't know the rep instruction on x86, so it really
> doesn't make sense to me.
> 
> I suppose if nothing else works, I can do one byte at a time until the
> tail is 32bit alligned, and then do the rest of the transfer as a block
> and see if that makes it work, or whether it is broken no matter what
> the allignement of the buffer is.

I tried to do a check on the alignment, and only do the whole transfer
as a block with memcpy_toio if it was 32bit aligned.  It breaks the same
way no matter how it is aligned.  It really seems that somehow using
this __memcpy assembly block on the geode sc1200 doesn't work correctly.
Doing the call using a loop with d2=1 works fine, but anything bigger
seems broken.

--
Len Sorensen

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

* Re: Strange transmit corruption in jsm driver on geode sc1200 system
  2006-08-25 21:57       ` Lennart Sorensen
  2006-08-28 17:30         ` Lennart Sorensen
@ 2006-08-28 18:11         ` Lennart Sorensen
  2006-08-28 19:09           ` Alan Cox
  1 sibling, 1 reply; 9+ messages in thread
From: Lennart Sorensen @ 2006-08-28 18:11 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Alan Cox, linux-kernel

On Fri, Aug 25, 2006 at 05:57:24PM -0400, Lennart Sorensen wrote:
> Of course given the __memcpy assembly seems to work fine unalligned on a
> pentium4, and probably most othe systems, what could make it not work
> correctly on a geode SC1200?

Related to the SC1200, I notied cyrix.c doesn't actually know about the
SC1200 that we are using.  This one returs dir0_msn = 11, while cyrix.c
only knows about 0 through 5.  If I add 11 to the block handling geode
GX1, then I get this cpuinfo:

processor       : 0
vendor_id       : CyrixInstead
cpu family      : 5
model           : 9
model name      : Geode(TM) Integrated Processor by National Semi
stepping        : 1
cpu MHz         : 266.729
cache size      : 16 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 2
wp              : yes
flags           : fpu tsc msr cx8 cmov mmx cxmmx
bogomips        : 535.35

So the get_model_name function seems to do something on it.  Otherwise I
get "model name" of Unknown, since there is no entry for it in cyrix.c

Since it is unknown, no setup calls are being done, although it seems a
number of features exist that could be enabled on the geode gx1, which I
believe is what a geode sc1200 really is.  The full label of the CPU is:

(national semi conductors logo)
Geode(tm)
SC1200
SC1200UL-266
(C)(M)NSC1999 D3
VS424AB

Does anyone know what should be called on this CPU type, and how to fix
cyrix.c to handle it correcly rather than ignoring it?

Forcing it to be treated like a GX1 and calling the geode_configure
function call, does not make my memcpy_toio problem go away.  On the
other hand I have a small optimistic hope that if it actually turns on
power saving on HLT, and some cache and memory optimizations, that it
might actually make the system run slightly faster and use slightly less
power.  If someone knows that part for sure I would love to know.

--
Len Sorensen

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

* Re: Strange transmit corruption in jsm driver on geode sc1200 system
  2006-08-28 18:11         ` Lennart Sorensen
@ 2006-08-28 19:09           ` Alan Cox
  2006-08-28 19:18             ` Lennart Sorensen
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Cox @ 2006-08-28 19:09 UTC (permalink / raw)
  To: Lennart Sorensen; +Cc: Alexey Dobriyan, linux-kernel

Ar Llu, 2006-08-28 am 14:11 -0400, ysgrifennodd Lennart Sorensen:
> Related to the SC1200, I notied cyrix.c doesn't actually know about the
> SC1200 that we are using.  This one returs dir0_msn = 11, while cyrix.c
> only knows about 0 through 5.  If I add 11 to the block handling geode

That is worth fixing.

> Does anyone know what should be called on this CPU type, and how to fix
> cyrix.c to handle it correcly rather than ignoring it?

The databook is available from www.amd.com I believe. You'd need to look
at that and see what needs setting. It is quite similar so it probably
will benefit a little - but that also depends what the BIOS does for you
and with ACPI that should be handled by the ACPI.

Alan

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

* Re: Strange transmit corruption in jsm driver on geode sc1200 system
  2006-08-28 19:09           ` Alan Cox
@ 2006-08-28 19:18             ` Lennart Sorensen
  0 siblings, 0 replies; 9+ messages in thread
From: Lennart Sorensen @ 2006-08-28 19:18 UTC (permalink / raw)
  To: Alan Cox; +Cc: Alexey Dobriyan, linux-kernel

On Mon, Aug 28, 2006 at 08:09:38PM +0100, Alan Cox wrote:
> That is worth fixing.

Well changing

case 4:

to

case 4:
case 11:
	dir0_msn = 4;

Makes the geode code appear to be called, and nothing is broken so
far.  Minimal testing so far actually seems to indicate a slight
performance improvement.  And /proc/cpuinfo no longer shows Unknown
model.  I am pretty sure in the past I have seen the model name show
MediaGX, so I suspect sometime in the last year there was a revision
change or something in the cpu modules we are using, since it now shows
Unknown.

> The databook is available from www.amd.com I believe. You'd need to look
> at that and see what needs setting. It is quite similar so it probably
> will benefit a little - but that also depends what the BIOS does for you
> and with ACPI that should be handled by the ACPI.

This BIOS has no ACPI.  At best it could do APM.

Seems the amd site requires an NDA to get at anything useful.  Maybe I
looked in the wrong place.

--
Len Sorensen

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

end of thread, other threads:[~2006-08-28 19:18 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-08-25 20:30 Strange transmit corruption in jsm driver on geode sc1200 system Lennart Sorensen
2006-08-25 21:20 ` Alan Cox
2006-08-25 21:03   ` Lennart Sorensen
2006-08-25 21:24     ` Alexey Dobriyan
2006-08-25 21:57       ` Lennart Sorensen
2006-08-28 17:30         ` Lennart Sorensen
2006-08-28 18:11         ` Lennart Sorensen
2006-08-28 19:09           ` Alan Cox
2006-08-28 19:18             ` Lennart Sorensen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.