* [PATCH 1/2] dma: mv_xor: use proper dma memory management functions
@ 2012-12-27 19:23 Lubomir Rintel
2012-12-27 19:23 ` [PATCH 2/2] dma: mv_xor: do not sync the DMA buffer after being deallocated Lubomir Rintel
0 siblings, 1 reply; 8+ messages in thread
From: Lubomir Rintel @ 2012-12-27 19:23 UTC (permalink / raw)
To: linux-arm-kernel
Caught by self-check with DMA_API_DEBUG:
WARNING: at lib/dma-debug.c:878 check_unmap+0x37c/0x748()
mv_xor mv_xor.0: DMA-API: device driver frees DMA memory with wrong function [device address=0x000000001f3a1a40] [size=2000 bytes] [mapped as single] [unmapped as page]
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/dma/mv_xor.c | 22 +++++++++++++++-------
1 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index ac71f55..39387df 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -306,9 +306,7 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
desc->async_tx.callback(
desc->async_tx.callback_param);
- /* unmap dma addresses
- * (unmap_single vs unmap_page?)
- */
+ /* unmap dma addresses */
if (desc->group_head && desc->unmap_len) {
struct mv_xor_desc_slot *unmap = desc->group_head;
struct device *dev = mv_chan_to_devp(mv_chan);
@@ -327,7 +325,11 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
dir = DMA_BIDIRECTIONAL;
else
dir = DMA_FROM_DEVICE;
- dma_unmap_page(dev, dest, len, dir);
+
+ if (flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+ dma_unmap_single(dev, dest, len, dir);
+ else
+ dma_unmap_page(dev, dest, len, dir);
}
if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
@@ -336,8 +338,12 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
src_cnt);
if (addr == dest)
continue;
- dma_unmap_page(dev, addr, len,
- DMA_TO_DEVICE);
+ if (flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+ dma_unmap_single(dev, addr, len,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(dev, addr, len,
+ DMA_TO_DEVICE);
}
}
desc->group_head = NULL;
@@ -938,7 +944,9 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
- MV_XOR_TEST_SIZE, 0);
+ MV_XOR_TEST_SIZE,
+ DMA_COMPL_SRC_UNMAP_SINGLE |
+ DMA_COMPL_DEST_UNMAP_SINGLE);
cookie = mv_xor_tx_submit(tx);
mv_xor_issue_pending(dma_chan);
async_tx_ack(tx);
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] dma: mv_xor: do not sync the DMA buffer after being deallocated
2012-12-27 19:23 [PATCH 1/2] dma: mv_xor: use proper dma memory management functions Lubomir Rintel
@ 2012-12-27 19:23 ` Lubomir Rintel
2013-01-04 16:10 ` Thomas Petazzoni
0 siblings, 1 reply; 8+ messages in thread
From: Lubomir Rintel @ 2012-12-27 19:23 UTC (permalink / raw)
To: linux-arm-kernel
DMA_CHECK was unhappy:
mv_xor mv_xor.0: DMA-API: device driver tries to sync DMA memory it has not
Also, the xor test was causing the mv_xor_slot_cleanup() to incorrectly
dealocate the destination buffer. This is fixed as well, since the deallocation
is done in mv_xor_probe() (with correct flags) now:
mv_xor mv_xor.0: DMA-API: device driver frees DMA memory with different direction [device address=0x000000001dea4000] [size=4096 bytes] [mapped with DMA_FROM_DEVICE] [unmapped with DMA_BIDIRECTIONAL]
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/dma/mv_xor.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 39387df..f642d8b 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -946,7 +946,7 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
MV_XOR_TEST_SIZE,
DMA_COMPL_SRC_UNMAP_SINGLE |
- DMA_COMPL_DEST_UNMAP_SINGLE);
+ DMA_COMPL_SKIP_DEST_UNMAP);
cookie = mv_xor_tx_submit(tx);
mv_xor_issue_pending(dma_chan);
async_tx_ack(tx);
@@ -962,6 +962,8 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+ dma_unmap_single(dma_chan->device->dev, dest_dma, MV_XOR_TEST_SIZE,
+ DMA_FROM_DEVICE);
if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
dev_err(dma_chan->device->dev,
"Self-test copy failed compare, disabling\n");
@@ -1039,7 +1041,8 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
0, PAGE_SIZE, DMA_TO_DEVICE);
tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
- MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
+ MV_XOR_NUM_SRC_TEST, PAGE_SIZE,
+ DMA_COMPL_SKIP_DEST_UNMAP);
cookie = mv_xor_tx_submit(tx);
mv_xor_issue_pending(dma_chan);
@@ -1056,6 +1059,8 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
PAGE_SIZE, DMA_FROM_DEVICE);
+ dma_unmap_page(dma_chan->device->dev, dest_dma, PAGE_SIZE,
+ DMA_FROM_DEVICE);
for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
u32 *ptr = page_address(dest);
if (ptr[i] != cmp_word) {
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] dma: mv_xor: do not sync the DMA buffer after being deallocated
2012-12-27 19:23 ` [PATCH 2/2] dma: mv_xor: do not sync the DMA buffer after being deallocated Lubomir Rintel
@ 2013-01-04 16:10 ` Thomas Petazzoni
2013-01-13 13:18 ` Lubomir Rintel
0 siblings, 1 reply; 8+ messages in thread
From: Thomas Petazzoni @ 2013-01-04 16:10 UTC (permalink / raw)
To: linux-arm-kernel
Dear Lubomir Rintel,
On Thu, 27 Dec 2012 20:23:48 +0100, Lubomir Rintel wrote:
> dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
> MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
> + dma_unmap_single(dma_chan->device->dev, dest_dma, MV_XOR_TEST_SIZE,
> + DMA_FROM_DEVICE);
I would assume that dma_unmap_single() implies a
dma_sync_single_for_cpu() since you're unmapping the DMA buffer. So if
you use dma_unmap_single(), I think you can remove the call to
dma_sync_single_for_cpu().
> dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
> PAGE_SIZE, DMA_FROM_DEVICE);
> + dma_unmap_page(dma_chan->device->dev, dest_dma, PAGE_SIZE,
> + DMA_FROM_DEVICE);
Ditto.
Also, the mv_xor_memcpy_self_test() function not only dma_map_single()
the destination buffer, but also the source buffer. So presumably, the
source buffer should also be dma_unmap_single()'d.
And for the mv_xor_xor_self_test() function, multiple source buffers
are dma_map_page()'d, so they should all be dma_unmap_page()'d I guess,
not only the destination buffer.
Does that make sense?
Thanks,
Thomas
--
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] dma: mv_xor: do not sync the DMA buffer after being deallocated
2013-01-04 16:10 ` Thomas Petazzoni
@ 2013-01-13 13:18 ` Lubomir Rintel
2013-01-18 7:45 ` Lubomir Rintel
0 siblings, 1 reply; 8+ messages in thread
From: Lubomir Rintel @ 2013-01-13 13:18 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-01-04 at 17:10 +0100, Thomas Petazzoni wrote:
> Dear Lubomir Rintel,
>
> On Thu, 27 Dec 2012 20:23:48 +0100, Lubomir Rintel wrote:
>
> > dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
> > MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
> > + dma_unmap_single(dma_chan->device->dev, dest_dma, MV_XOR_TEST_SIZE,
> > + DMA_FROM_DEVICE);
>
> I would assume that dma_unmap_single() implies a
> dma_sync_single_for_cpu() since you're unmapping the DMA buffer. So if
> you use dma_unmap_single(), I think you can remove the call to
> dma_sync_single_for_cpu().
Yes, it indeed seems to be the case (comment for arm_dma_unmap_page():
"After this call, reads by the CPU to the buffer are guaranteed to see
whatever the device wrote there.".
> > dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
> > PAGE_SIZE, DMA_FROM_DEVICE);
> > + dma_unmap_page(dma_chan->device->dev, dest_dma, PAGE_SIZE,
> > + DMA_FROM_DEVICE);
>
> Ditto.
>
> Also, the mv_xor_memcpy_self_test() function not only dma_map_single()
> the destination buffer, but also the source buffer. So presumably, the
> source buffer should also be dma_unmap_single()'d.
>
> And for the mv_xor_xor_self_test() function, multiple source buffers
> are dma_map_page()'d, so they should all be dma_unmap_page()'d I guess,
> not only the destination buffer.
Those get released by the mv_xor_run_tx_complete_actions() callback.
I will follow up with an updated patch.
Regards,
Lubo
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] dma: mv_xor: do not sync the DMA buffer after being deallocated
2013-01-13 13:18 ` Lubomir Rintel
@ 2013-01-18 7:45 ` Lubomir Rintel
2013-01-18 7:46 ` [PATCH 1/3] " Lubomir Rintel
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Lubomir Rintel @ 2013-01-18 7:45 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 2013-01-13 at 14:18 +0100, Lubomir Rintel wrote:
> On Fri, 2013-01-04 at 17:10 +0100, Thomas Petazzoni wrote:
> > Dear Lubomir Rintel,
> >
> > On Thu, 27 Dec 2012 20:23:48 +0100, Lubomir Rintel wrote:
> >
> > > dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
> > > MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
> > > + dma_unmap_single(dma_chan->device->dev, dest_dma, MV_XOR_TEST_SIZE,
> > > + DMA_FROM_DEVICE);
> >
> > I would assume that dma_unmap_single() implies a
> > dma_sync_single_for_cpu() since you're unmapping the DMA buffer. So if
> > you use dma_unmap_single(), I think you can remove the call to
> > dma_sync_single_for_cpu().
>
> Yes, it indeed seems to be the case (comment for arm_dma_unmap_page():
> "After this call, reads by the CPU to the buffer are guaranteed to see
> whatever the device wrote there.".
>
> > > dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
> > > PAGE_SIZE, DMA_FROM_DEVICE);
> > > + dma_unmap_page(dma_chan->device->dev, dest_dma, PAGE_SIZE,
> > > + DMA_FROM_DEVICE);
> >
> > Ditto.
> >
> > Also, the mv_xor_memcpy_self_test() function not only dma_map_single()
> > the destination buffer, but also the source buffer. So presumably, the
> > source buffer should also be dma_unmap_single()'d.
> >
> > And for the mv_xor_xor_self_test() function, multiple source buffers
> > are dma_map_page()'d, so they should all be dma_unmap_page()'d I guess,
> > not only the destination buffer.
>
> Those get released by the mv_xor_run_tx_complete_actions() callback.
>
> I will follow up with an updated patch.
Actually, after cleaning up the sync a couple more selfcheck warnings
popped up. I'd be very thankful if you could take a look (patches
chained to this message).
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] dma: mv_xor: do not sync the DMA buffer after being deallocated
2013-01-18 7:45 ` Lubomir Rintel
@ 2013-01-18 7:46 ` Lubomir Rintel
2013-01-18 7:46 ` [PATCH 2/3] dma: mv_xor: fix DMA-API error handling sanity check Lubomir Rintel
2013-01-18 7:46 ` [PATCH 3/3] dma: mv_xor: get rid of a DMA-API sanity check warning Lubomir Rintel
2 siblings, 0 replies; 8+ messages in thread
From: Lubomir Rintel @ 2013-01-18 7:46 UTC (permalink / raw)
To: linux-arm-kernel
DMA_CHECK was unhappy:
mv_xor mv_xor.0: DMA-API: device driver tries to sync DMA memory it has not allocated [device address=0x000000001f3a1a40] [size=2000 bytes]
Deallocation, which involves a sync, happens automatically by
mv_xor_slot_cleanup() once the transfer is finished.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/dma/mv_xor.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index e666983..8b81a04 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -960,8 +960,6 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
goto free_resources;
}
- dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
- MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
dev_err(dma_chan->device->dev,
"Self-test copy failed compare, disabling\n");
@@ -1054,8 +1052,6 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
goto free_resources;
}
- dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
- PAGE_SIZE, DMA_FROM_DEVICE);
for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
u32 *ptr = page_address(dest);
if (ptr[i] != cmp_word) {
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/3] dma: mv_xor: fix DMA-API error handling sanity check
2013-01-18 7:45 ` Lubomir Rintel
2013-01-18 7:46 ` [PATCH 1/3] " Lubomir Rintel
@ 2013-01-18 7:46 ` Lubomir Rintel
2013-01-18 7:46 ` [PATCH 3/3] dma: mv_xor: get rid of a DMA-API sanity check warning Lubomir Rintel
2 siblings, 0 replies; 8+ messages in thread
From: Lubomir Rintel @ 2013-01-18 7:46 UTC (permalink / raw)
To: linux-arm-kernel
Add error checking.
---
drivers/dma/mv_xor.c | 27 ++++++++++++++++++++++++++-
1 files changed, 26 insertions(+), 1 deletions(-)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 8b81a04..d00a834 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -939,9 +939,21 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
dest_dma = dma_map_single(dma_chan->device->dev, dest,
MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dma_chan->device->dev, dest_dma)) {
+ dev_err(dma_chan->device->dev,
+ "Could not map destination buffer, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
src_dma = dma_map_single(dma_chan->device->dev, src,
MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
+ if (dma_mapping_error(dma_chan->device->dev, src_dma)) {
+ dev_err(dma_chan->device->dev,
+ "Could not map source buffer, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
MV_XOR_TEST_SIZE,
@@ -1031,10 +1043,23 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
/* test xor */
dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(dma_chan->device->dev, dest_dma)) {
+ dev_err(dma_chan->device->dev,
+ "Could not map destination page, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
- for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++)
+ for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++) {
dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
0, PAGE_SIZE, DMA_TO_DEVICE);
+ if (dma_mapping_error(dma_chan->device->dev, dma_srcs[i])) {
+ dev_err(dma_chan->device->dev,
+ "Could not map source page, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+ }
tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] dma: mv_xor: get rid of a DMA-API sanity check warning
2013-01-18 7:45 ` Lubomir Rintel
2013-01-18 7:46 ` [PATCH 1/3] " Lubomir Rintel
2013-01-18 7:46 ` [PATCH 2/3] dma: mv_xor: fix DMA-API error handling sanity check Lubomir Rintel
@ 2013-01-18 7:46 ` Lubomir Rintel
2 siblings, 0 replies; 8+ messages in thread
From: Lubomir Rintel @ 2013-01-18 7:46 UTC (permalink / raw)
To: linux-arm-kernel
mv_xor mv_xor.0: DMA-API: device driver frees DMA memory with different direction [device address=0x000000001dea4000] [size=4096 bytes] [mapped with DMA_FROM_DEVICE] [unmapped with DMA_BIDIRECTIONAL]
Change xor self test destination buffer allocation direction to bidirectional,
as it's what mv_xor_run_tx_complete_actions() frees for multiple sources.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/dma/mv_xor.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index d00a834..1e90f5d 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1042,7 +1042,7 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
/* test xor */
dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
- DMA_FROM_DEVICE);
+ DMA_BIDIRECTIONAL);
if (dma_mapping_error(dma_chan->device->dev, dest_dma)) {
dev_err(dma_chan->device->dev,
"Could not map destination page, disabling\n");
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-01-18 7:46 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-27 19:23 [PATCH 1/2] dma: mv_xor: use proper dma memory management functions Lubomir Rintel
2012-12-27 19:23 ` [PATCH 2/2] dma: mv_xor: do not sync the DMA buffer after being deallocated Lubomir Rintel
2013-01-04 16:10 ` Thomas Petazzoni
2013-01-13 13:18 ` Lubomir Rintel
2013-01-18 7:45 ` Lubomir Rintel
2013-01-18 7:46 ` [PATCH 1/3] " Lubomir Rintel
2013-01-18 7:46 ` [PATCH 2/3] dma: mv_xor: fix DMA-API error handling sanity check Lubomir Rintel
2013-01-18 7:46 ` [PATCH 3/3] dma: mv_xor: get rid of a DMA-API sanity check warning Lubomir Rintel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).