ioatdma: fix "ioatdma frees DMA memory with wrong function"
as reported by Alexander Beregalov <a.beregalov@gmail.com> ioatdma 0000:00:08.0: DMA-API: device driver frees DMA memory with wrong function [device address=0x000000007f76f800] [size=2000 bytes] [map ped as single] [unmapped as page] The ioatdma driver was unmapping all regions (either allocated as page or single) using unmap_page. This patch lets dma driver recognize if unmap_single or unmap_page should be used. It introduces two new dma control flags: DMA_COMPL_SRC_UNMAP_SINGLE and DMA_COMPL_DEST_UNMAP_SINGLE. They should be set to indicate dma driver to do dma-unmapping as single (first one for the source, tha latter for the destination). If respective flag is not set, the driver assumes dma-unmapping as page. Signed-off-by: Maciej Sosnowski <maciej.sosnowski@intel.com> Reported-by: Alexander Beregalov <a.beregalov@gmail.com> Tested-by: Alexander Beregalov <a.beregalov@gmail.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
committed by
Dan Williams
parent
ca50a51e89
commit
4f005dbe55
@@ -804,11 +804,14 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
|
||||
dma_addr_t dma_dest, dma_src;
|
||||
dma_cookie_t cookie;
|
||||
int cpu;
|
||||
unsigned long flags;
|
||||
|
||||
dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
|
||||
dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
|
||||
tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
|
||||
DMA_CTRL_ACK);
|
||||
flags = DMA_CTRL_ACK |
|
||||
DMA_COMPL_SRC_UNMAP_SINGLE |
|
||||
DMA_COMPL_DEST_UNMAP_SINGLE;
|
||||
tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
|
||||
|
||||
if (!tx) {
|
||||
dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
|
||||
@@ -850,11 +853,12 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
|
||||
dma_addr_t dma_dest, dma_src;
|
||||
dma_cookie_t cookie;
|
||||
int cpu;
|
||||
unsigned long flags;
|
||||
|
||||
dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
|
||||
dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
|
||||
tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
|
||||
DMA_CTRL_ACK);
|
||||
flags = DMA_CTRL_ACK | DMA_COMPL_SRC_UNMAP_SINGLE;
|
||||
tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
|
||||
|
||||
if (!tx) {
|
||||
dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
|
||||
@@ -898,12 +902,13 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
|
||||
dma_addr_t dma_dest, dma_src;
|
||||
dma_cookie_t cookie;
|
||||
int cpu;
|
||||
unsigned long flags;
|
||||
|
||||
dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
|
||||
dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len,
|
||||
DMA_FROM_DEVICE);
|
||||
tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
|
||||
DMA_CTRL_ACK);
|
||||
flags = DMA_CTRL_ACK;
|
||||
tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
|
||||
|
||||
if (!tx) {
|
||||
dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE);
|
||||
|
Reference in New Issue
Block a user