I/O read, write implementation questions

From: Zoltan Menyhart <Zoltan.Menyhart_at_bull.net>
Date: 2006-04-26 00:13:58
The SDM shows on pages 2:585-586 how the I/O space reads and
writes have to be iplemented, e.g.:

outb:	...
	mf
	st1.rel [port_addr] = in1
	mf.a
	mf

inb:	...
	mf
	ld1.acq r8 = [port_addr]
	mf.a
	mf

The actual implementation does not include the pairs of "mf"-s.
Can someone, please, explain me why they are left off?

The following code sequence:

	outb(data, port_addr);
	flag = 1;

may be compiled as:

	add	r8 = 1, r0
	add	r2 = flag_offs, r1
	;;
	st1.rel [port_addr] = data
	mf.a
	st1	[r2] = r8

What prevents "st1 [r2] = r8" from being seen before
"st1.rel [port_addr] = data" is seen?
("mf.a" is unordered, see Table 4-14, SDM vol2.)
Similar hazardous code can be constructed with "inb()".

Why do not "readb()" ... "writeb()" include "mf.a"-s?

Let's take an example from the "ia-64 Linux Kernel" book, chapter 7.2.1:

	dmabuf[0] = 5;
	memcpy(dmabuf + 1, "hello", 5);
	mb();
	readl(dmactl);	// Memory mapped I/O
// And let's add:
	flag = 1;

What prevents "flag = 1" from being seen before the DMA is actually
kicked off?

The ".acq" generated by "readl()" - because "dmactl" is a volatile
pointer - plays with the OzQ only.
As "dmactl" is an uncached address, the read request goes into the
In-Order Output Queue.
Nothing remains in the OzQ ahead of "flag = 1", it gets committed
happily against the L2 cache, i.e. it becomes globally visible.
Our uncached read request is still sitting in the In-Order Output Queue...
It would not help if I added an "mb()" before "flag = 1".

Thanks,

Zoltan
-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Received on Wed Apr 26 00:14:40 2006

This archive was generated by hypermail 2.1.8 : 2006-04-26 00:15:00 EST