From cc2552df704f68fd49086c0b18eb12cf8298d131 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 17 Mar 2003 23:12:07 -0800 Subject: [PATCH] ia64: remove stale mmiob function The consensus on lkml was that devices should do reads from safe registers to ensure PIO write ordering, which means we no longer need mmiob. This patch removes the mmiob entries from the machine vector headers and io.h and updates the documentation about PIO ordering. --- Documentation/io_ordering.txt | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/io_ordering.txt (limited to 'Documentation') diff --git a/Documentation/io_ordering.txt b/Documentation/io_ordering.txt new file mode 100644 index 000000000000..9faae6f26d32 --- /dev/null +++ b/Documentation/io_ordering.txt @@ -0,0 +1,47 @@ +On some platforms, so-called memory-mapped I/O is weakly ordered. On such +platforms, driver writers are responsible for ensuring that I/O writes to +memory-mapped addresses on their device arrive in the order intended. This is +typically done by reading a 'safe' device or bridge register, causing the I/O +chipset to flush pending writes to the device before any reads are posted. A +driver would usually use this technique immediately prior to the exit of a +critical section of code protected by spinlocks. This would ensure that +subsequent writes to I/O space arrived only after all prior writes (much like a +memory barrier op, mb(), only with respect to I/O). + +A more concrete example from a hypothetical device driver: + + ... +CPU A: spin_lock_irqsave(&dev_lock, flags) +CPU A: val = readl(my_status); +CPU A: ... +CPU A: writel(newval, ring_ptr); +CPU A: spin_unlock_irqrestore(&dev_lock, flags) + ... +CPU B: spin_lock_irqsave(&dev_lock, flags) +CPU B: val = readl(my_status); +CPU B: ... +CPU B: writel(newval2, ring_ptr); +CPU B: spin_unlock_irqrestore(&dev_lock, flags) + ... + +In the case above, the device may receive newval2 before it receives newval, +which could cause problems. Fixing it is easy enough though: + + ... +CPU A: spin_lock_irqsave(&dev_lock, flags) +CPU A: val = readl(my_status); +CPU A: ... +CPU A: writel(newval, ring_ptr); +CPU A: (void)readl(safe_register); /* maybe a config register? */ +CPU A: spin_unlock_irqrestore(&dev_lock, flags) + ... +CPU B: spin_lock_irqsave(&dev_lock, flags) +CPU B: val = readl(my_status); +CPU B: ... +CPU B: writel(newval2, ring_ptr); +CPU B: (void)readl(safe_register); /* maybe a config register? */ +CPU B: spin_unlock_irqrestore(&dev_lock, flags) + +Here, the reads from safe_register will cause the I/O chipset to flush any +pending writes before actually posting the read to the chipset, preventing +possible data corruption. -- cgit v1.2.3