lib/scatterlist: add a flags to signalize mapping direction

sg_miter_start() is currently unaware of the direction of the copy
process (to or from the scatter list). It is important to know the
direction because the page has to be flushed in case the data written
is seen on a different mapping in user land on cache incoherent
architectures.

Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Pierre Ossman <pierre@ossman.eu>

authored by Sebastian Andrzej Siewior and committed by Pierre Ossman 6de7e356 b5929724

+14 -4
+2
include/linux/scatterlist.h
··· 242 */ 243 244 #define SG_MITER_ATOMIC (1 << 0) /* use kmap_atomic */ 245 246 struct sg_mapping_iter { 247 /* the following three fields can be accessed directly */
··· 242 */ 243 244 #define SG_MITER_ATOMIC (1 << 0) /* use kmap_atomic */ 245 + #define SG_MITER_TO_SG (1 << 1) /* flush back to phys on unmap */ 246 + #define SG_MITER_FROM_SG (1 << 2) /* nop */ 247 248 struct sg_mapping_iter { 249 /* the following three fields can be accessed directly */
+12 -4
lib/scatterlist.c
··· 314 miter->__sg = sgl; 315 miter->__nents = nents; 316 miter->__offset = 0; 317 miter->__flags = flags; 318 } 319 EXPORT_SYMBOL(sg_miter_start); ··· 395 if (miter->addr) { 396 miter->__offset += miter->consumed; 397 398 if (miter->__flags & SG_MITER_ATOMIC) { 399 WARN_ON(!irqs_disabled()); 400 kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ); ··· 430 unsigned int offset = 0; 431 struct sg_mapping_iter miter; 432 unsigned long flags; 433 434 - sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC); 435 436 local_irq_save(flags); 437 ··· 448 449 if (to_buffer) 450 memcpy(buf + offset, miter.addr, len); 451 - else { 452 memcpy(miter.addr, buf + offset, len); 453 - flush_kernel_dcache_page(miter.page); 454 - } 455 456 offset += len; 457 }
··· 314 miter->__sg = sgl; 315 miter->__nents = nents; 316 miter->__offset = 0; 317 + WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG))); 318 miter->__flags = flags; 319 } 320 EXPORT_SYMBOL(sg_miter_start); ··· 394 if (miter->addr) { 395 miter->__offset += miter->consumed; 396 397 + if (miter->__flags & SG_MITER_TO_SG) 398 + flush_kernel_dcache_page(miter->page); 399 + 400 if (miter->__flags & SG_MITER_ATOMIC) { 401 WARN_ON(!irqs_disabled()); 402 kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ); ··· 426 unsigned int offset = 0; 427 struct sg_mapping_iter miter; 428 unsigned long flags; 429 + unsigned int sg_flags = SG_MITER_ATOMIC; 430 431 + if (to_buffer) 432 + sg_flags |= SG_MITER_FROM_SG; 433 + else 434 + sg_flags |= SG_MITER_TO_SG; 435 + 436 + sg_miter_start(&miter, sgl, nents, sg_flags); 437 438 local_irq_save(flags); 439 ··· 438 439 if (to_buffer) 440 memcpy(buf + offset, miter.addr, len); 441 + else 442 memcpy(miter.addr, buf + offset, len); 443 444 offset += len; 445 }