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