Re: question on memory barrier

From: Alan Cox
Date: Wed Aug 24 2005 - 16:29:38 EST


On Mer, 2005-08-24 at 14:43 +0200, moreau francis wrote:
> I'm currently trying to write a USB driver for Linux. The device must be
> configured by writing some values into the same register but I want to be
> sure that the writing order is respected by either the compiler and the cpu.

The Linux kernel defines writel() in such a way that for each platform a
series of writel() calls are ordered with respect to the processor. In
other words if on one processor you issue

writel(0, foo);
writel(1, foo);
writel(2, foo);

the hardware will see 0, 1, 2. writel does not guarantee that the write
occurs immediately so while you know the writes are ordered you don't
know the write has "arrived" at the device when the writel() call
returns. That isn't usually a problem except when delays are required.
Then you need to avoid PCI posting and do

writel(0, foo);
readl(foo);
udelay(50);
writel(1, foo);

The only other complication is multiprocessor systems - if you have
multiple places that may issue these I/O's you may need a lock to
protect them from both processors configuring at the same time, and in
theory an mmiowb() call to ensure the first processor has finished its
I/O before the second starts - ie

spin_lock(&conf_lock);
writel(0, foo);
writel(1, foo);
mmiowb();
spin_unlock(&conf_lock);


The "wmb/rmb" are barriers to memory not to device I/O. The locking
functions (spin_unlock etc) are implicit memory barriers, but atomic
operations are not.

Generally speaking if you use writel the right semantics just happen,
and that is why the writel definition is the way it is.

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