Re: Unable to read memory mapped PCI memory the second time == freezeup..

Gerard Roudier (groudier@club-internet.fr)
Sat, 10 Jul 1999 21:51:40 +0200 (MET DST)


The first thing you want to do when playing with MMIO is to prevent the
compiler from optimizing accesses to MMIO regions.
Using 'volatile' for each MMIO access is required, otherwise the actual
asm code may just do a job that is different from the one you want to
perform (btw, the readX/writeX stuff add the 'volatile' stuff for you).

If you are running your code on x86 machine, memory barriers should not be
needed since the CPU mostly enforces strong ordering for access to MMIO
regions. On other architectures, memory barriers may have to be used in
order to enforce proper ordering.

I donnot have any idea on the cause of the lock-up. But you must keep in
mind that the actual machine code is very probably different from what the
C code is intended to do due to compiler optimizations.
So, it would be a lot more helpful to look into the generated asm code if
you want to have a chance to understand what actually happens.

Gérard.

On Sat, 10 Jul 1999, Klaus Nielsen wrote:

> Aloha guys
>
> I am writing an Ethernet driver for a Internal PCI cable modem with
> some onboard memory that I have mapped using ioremap.
>
> But I have problem reading the memory, more accurately, I can read it
> once, write it many, but not read it a second time.
>
> It is mapped using:
>
> // Remap physical PCI controller LCR memory to virtual memory
> if(((char*)(global_lcr_vmemaddr = (u32) ioremap(global_pci_lcr_memaddr, LCR_MEMORY_RANGE)))==NULL)
> return -EAGAIN;
>
> // Remap physical PCI memory to virtual memory
> if((((char*)global_vmemaddr = (u32) ioremap(global_pci_memaddr,MODEM_MEMORY_RANGE))) == NULL) {
> iounmap((char*)global_lcr_vmemaddr); return -EAGAIN;
> }
>
> The following silly code then works fine:
>
> Byte byArgh;
>
> byArgh = *((Byte*)global_vmemaddr);
> if(byArgh==0) printk(KERN_DEBUG "byArgh\n");
> *((Byte*)global_vmemaddr) = 0x5a;
> byArgh = *((Byte*)global_vmemaddr);
>
> While the PC freezes completely at the last conditional statement
> at the following, almost identical, code fragment:
>
> Byte byArgh;
>
> byArgh = *((Byte*)global_vmemaddr);
> if(byArgh==0) printk(KERN_DEBUG "byArgh\n");
> *((Byte*)global_vmemaddr) = 0x5a;
> byArgh = *((Byte*)global_vmemaddr);
> if(byArgh==0) printk(KERN_DEBUG "byArgh\n"); // DEATH HERE
>
> - as if the bus had not finished the transfer the second time I read.
>
> I have in a similar way mapped PCI LCR memory in the PLX9052 PCI
> controller (that by the way does not support master mode). And I can
> read and write that LCR memory as much as I want.
>
> I have tried changing compiler (to gcc 2.7.2.3), changing the
> modem board with one that works with my WinNT driver, adding
> udelay(60) between accesses, using readb() instead of direct access -
> no change.
>
> If I do _extensive_ memory testing, writing all the memory twice, then
> reading all, writing all again, reading all, writing all again -
> there is no problem reading, but later in the driver when just
> accessing a single byte like in the second example I freeze again.
>
> A small sample code is available at http://www.zorland.dk/jimbo/hw.c
>
> This is my first SW project of any kind on linux, so please be gentle
> with me :-) Maybe I am mapping the memory in a wrong way ?
>
> I am using kernel 2.2.9.
>
> PS: I am in no way acting on behalf of COCOM A/S, this is purely a
> spare time project.
>
> --
> Best regards, Klaus.
> ----------------------------------------------------
> Klaus J. O. Nielsen
> System Engineer, COCOM A/S, www.cocom.dk
> Personal web: http://www.zorland.dk/jimbo
> PGP public key: http://www.zorland.dk/jimbo/kjn.asc
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.rutgers.edu
> Please read the FAQ at http://www.tux.org/lkml/
>
>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/