mirror of https://gitee.com/openkylin/linux.git
async_tx: fix kmap_atomic usage in async_memcpy
Andrew Morton: [async_memcpy] is very wrong if both ASYNC_TX_KMAP_DST and ASYNC_TX_KMAP_SRC can ever be set. We'll end up using the same kmap slot for both src add dest and we get either corrupted data or a BUG. Evgeniy Polyakov: Btw, shouldn't it always be kmap_atomic() even if flag is not set. That pages are usual one returned by alloc_page(). So fix the usage of kmap_atomic and kill the ASYNC_TX_KMAP_DST and ASYNC_TX_KMAP_SRC flags. Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
7c6129c68f
commit
eb0645a8b1
|
@ -36,7 +36,6 @@
|
|||
* @offset: offset in pages to start transaction
|
||||
* @len: length in bytes
|
||||
* @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
|
||||
* ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST
|
||||
* @depend_tx: memcpy depends on the result of this transaction
|
||||
* @cb_fn: function to call when the memcpy completes
|
||||
* @cb_param: parameter to pass to the callback routine
|
||||
|
@ -88,23 +87,13 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
|
|||
__FUNCTION__);
|
||||
}
|
||||
|
||||
if (flags & ASYNC_TX_KMAP_DST)
|
||||
dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
|
||||
else
|
||||
dest_buf = page_address(dest) + dest_offset;
|
||||
|
||||
if (flags & ASYNC_TX_KMAP_SRC)
|
||||
src_buf = kmap_atomic(src, KM_USER0) + src_offset;
|
||||
else
|
||||
src_buf = page_address(src) + src_offset;
|
||||
dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
|
||||
src_buf = kmap_atomic(src, KM_USER1) + src_offset;
|
||||
|
||||
memcpy(dest_buf, src_buf, len);
|
||||
|
||||
if (flags & ASYNC_TX_KMAP_DST)
|
||||
kunmap_atomic(dest_buf, KM_USER0);
|
||||
|
||||
if (flags & ASYNC_TX_KMAP_SRC)
|
||||
kunmap_atomic(src_buf, KM_USER0);
|
||||
kunmap_atomic(dest_buf, KM_USER0);
|
||||
kunmap_atomic(src_buf, KM_USER1);
|
||||
|
||||
async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
|
||||
}
|
||||
|
|
|
@ -493,12 +493,12 @@ async_copy_data(int frombio, struct bio *bio, struct page *page,
|
|||
if (frombio)
|
||||
tx = async_memcpy(page, bio_page, page_offset,
|
||||
b_offset, clen,
|
||||
ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_SRC,
|
||||
ASYNC_TX_DEP_ACK,
|
||||
tx, NULL, NULL);
|
||||
else
|
||||
tx = async_memcpy(bio_page, page, b_offset,
|
||||
page_offset, clen,
|
||||
ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_DST,
|
||||
ASYNC_TX_DEP_ACK,
|
||||
tx, NULL, NULL);
|
||||
}
|
||||
if (clen < len) /* hit end of page */
|
||||
|
|
|
@ -51,10 +51,6 @@ struct dma_chan_ref {
|
|||
* @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
|
||||
* dependency chain
|
||||
* @ASYNC_TX_DEP_ACK: ack the dependency descriptor. Useful for chaining.
|
||||
* @ASYNC_TX_KMAP_SRC: if the transaction is to be performed synchronously
|
||||
* take an atomic mapping (KM_USER0) on the source page(s)
|
||||
* @ASYNC_TX_KMAP_DST: if the transaction is to be performed synchronously
|
||||
* take an atomic mapping (KM_USER0) on the dest page(s)
|
||||
*/
|
||||
enum async_tx_flags {
|
||||
ASYNC_TX_XOR_ZERO_DST = (1 << 0),
|
||||
|
@ -62,8 +58,6 @@ enum async_tx_flags {
|
|||
ASYNC_TX_ASSUME_COHERENT = (1 << 2),
|
||||
ASYNC_TX_ACK = (1 << 3),
|
||||
ASYNC_TX_DEP_ACK = (1 << 4),
|
||||
ASYNC_TX_KMAP_SRC = (1 << 5),
|
||||
ASYNC_TX_KMAP_DST = (1 << 6),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DMA_ENGINE
|
||||
|
|
Loading…
Reference in New Issue