*/
 
 #define SG_MITER_ATOMIC                (1 << 0)         /* use kmap_atomic */
+#define SG_MITER_TO_SG         (1 << 1)        /* flush back to phys on unmap */
+#define SG_MITER_FROM_SG       (1 << 2)        /* nop */
 
 struct sg_mapping_iter {
        /* the following three fields can be accessed directly */
 
        miter->__sg = sgl;
        miter->__nents = nents;
        miter->__offset = 0;
+       WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
        miter->__flags = flags;
 }
 EXPORT_SYMBOL(sg_miter_start);
        if (miter->addr) {
                miter->__offset += miter->consumed;
 
+               if (miter->__flags & SG_MITER_TO_SG)
+                       flush_kernel_dcache_page(miter->page);
+
                if (miter->__flags & SG_MITER_ATOMIC) {
                        WARN_ON(!irqs_disabled());
                        kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
        unsigned int offset = 0;
        struct sg_mapping_iter miter;
        unsigned long flags;
+       unsigned int sg_flags = SG_MITER_ATOMIC;
+
+       if (to_buffer)
+               sg_flags |= SG_MITER_FROM_SG;
+       else
+               sg_flags |= SG_MITER_TO_SG;
 
-       sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC);
+       sg_miter_start(&miter, sgl, nents, sg_flags);
 
        local_irq_save(flags);
 
 
                if (to_buffer)
                        memcpy(buf + offset, miter.addr, len);
-               else {
+               else
                        memcpy(miter.addr, buf + offset, len);
-                       flush_kernel_dcache_page(miter.page);
-               }
 
                offset += len;
        }