diff options
| author | Jesse Barnes <jbarnes@engr.sgi.com> | 2004-11-01 23:13:42 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-11-01 23:13:42 -0800 |
| commit | e2e9cdaa1bebf6799c4d4816a852c8b9e78065a2 (patch) | |
| tree | 939cd3b09de7d82bb259b3841db92c0da9cc7b4c /Documentation | |
| parent | 3d620a491aa10eefb1bbb808a20b47bbdcd758f1 (diff) | |
[PATCH] document mmiowb and readX_relaxed a bit more in deviceiobook.tmpl
This is a small patch to deviceiobook.tmpl to describe the new mmiowb
routine a bit more completely. I've also updated it to provide pointers to
drivers that do write flushing, use mmiowb, and use the readX_relaxed
routines.
Acked-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Jesse Barnes <jbarnes@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'Documentation')
| -rw-r--r-- | Documentation/DocBook/deviceiobook.tmpl | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/Documentation/DocBook/deviceiobook.tmpl b/Documentation/DocBook/deviceiobook.tmpl index cfce4e6de50d..0d1da8cbd752 100644 --- a/Documentation/DocBook/deviceiobook.tmpl +++ b/Documentation/DocBook/deviceiobook.tmpl @@ -195,7 +195,12 @@ qla1280_disable_intrs(struct scsi_qla_host *ha) be strongly ordered coming from different CPUs. Thus it's important to properly protect parts of your driver that do memory-mapped writes with locks and use the <function>mmiowb</function> to make sure they - arrive in the order intended. + arrive in the order intended. Issuing a regular <function>readX + </function> will also ensure write ordering, but should only be used + when the driver has to be sure that the write has actually arrived + at the device (not that it's simply ordered with respect to other + writes), since a full <function>readX</function> is a relatively + expensive operation. </para> <para> @@ -203,29 +208,50 @@ qla1280_disable_intrs(struct scsi_qla_host *ha) releasing a spinlock that protects regions using <function>writeb </function> or similar functions that aren't surrounded by <function> readb</function> calls, which will ensure ordering and flushing. The - following example (again from qla1280.c) illustrates its use. + following pseudocode illustrates what might occur if write ordering + isn't guaranteed via <function>mmiowb</function> or one of the + <function>readX</function> functions. </para> <programlisting> - sp->flags |= SRB_SENT; - ha->actthreads++; - WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index); - - /* - * A Memory Mapped I/O Write Barrier is needed to ensure that this write - * of the request queue in register is ordered ahead of writes issued - * after this one by other CPUs. Access to the register is protected - * by the host_lock. Without the mmiowb, however, it is possible for - * this CPU to release the host lock, another CPU acquire the host lock, - * and write to the request queue in, and have the second write make it - * to the chip first. - */ - mmiowb(); /* posted write ordering */ +CPU A: spin_lock_irqsave(&dev_lock, flags) +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: writel(newval2, ring_ptr); +CPU B: ... +CPU B: spin_unlock_irqrestore(&dev_lock, flags) </programlisting> <para> + In the case above, newval2 could be written to ring_ptr before + newval. Fixing it is easy though: + </para> + +<programlisting> +CPU A: spin_lock_irqsave(&dev_lock, flags) +CPU A: ... +CPU A: writel(newval, ring_ptr); +CPU A: mmiowb(); /* ensure no other writes beat us to the device */ +CPU A: spin_unlock_irqrestore(&dev_lock, flags) + ... +CPU B: spin_lock_irqsave(&dev_lock, flags) +CPU B: writel(newval2, ring_ptr); +CPU B: ... +CPU B: mmiowb(); +CPU B: spin_unlock_irqrestore(&dev_lock, flags) +</programlisting> + + <para> + See tg3.c for a real world example of how to use <function>mmiowb + </function> + </para> + + <para> PCI ordering rules also guarantee that PIO read responses arrive - after any outstanding DMA writes on that bus, since for some devices + after any outstanding DMA writes from that bus, since for some devices the result of a <function>readb</function> call may signal to the driver that a DMA transaction is complete. In many cases, however, the driver may want to indicate that the next @@ -234,7 +260,11 @@ qla1280_disable_intrs(struct scsi_qla_host *ha) <function>readb_relaxed</function> for these cases, although only some platforms will honor the relaxed semantics. Using the relaxed read functions will provide significant performance benefits on - platforms that support it. + platforms that support it. The qla2xxx driver provides examples + of how to use <function>readX_relaxed</function>. In many cases, + a majority of the driver's <function>readX</function> calls can + safely be converted to <function>readX_relaxed</function> calls, since + only a few will indicate or depend on DMA completion. </para> </sect1> |
