| Submitter | Qiang Liu |
|---|---|
| Date | July 27, 2012, 9:16 a.m. |
| Message ID | <1343380616-12126-1-git-send-email-qiang.liu@freescale.com> |
| Download | mbox | patch |
| Permalink | /patch/173608/ |
| State | Superseded |
| Headers | show |
Comments
qiang.liu@freescale.com wrote: > > Add memory copy self test when probe device, fsl-dma will be disabled > if self test failed. Is this a real problem that can occur? The DMA driver used to have a self-test, but I removed it a long time ago because it was pointless. I don't see why we need to add another one back in.
On Mon, Jul 30, 2012 at 12:48:41PM -0500, Timur Tabi wrote: > qiang.liu@freescale.com wrote: > > > > Add memory copy self test when probe device, fsl-dma will be disabled > > if self test failed. > > Is this a real problem that can occur? The DMA driver used to have a > self-test, but I removed it a long time ago because it was pointless. I > don't see why we need to add another one back in. > > -- > Timur Tabi > Linux kernel developer at Freescale > I made a comment that a test suite for the async_tx API would be very helpful in diagnosing similar problems in this and other DMA drivers. Something standalone, similar to the drivers/dma/dmatest.c driver, using the async_tx API. I think this was misinterpreted into me asking that the driver have a built-in self test. Ira
> -----Original Message----- > From: linux-crypto-owner@vger.kernel.org [mailto:linux-crypto- > owner@vger.kernel.org] On Behalf Of Ira W. Snyder > Sent: Tuesday, July 31, 2012 2:33 AM > To: Tabi Timur-B04825 > Cc: Liu Qiang-B32616; linux-crypto@vger.kernel.org; linuxppc- > dev@lists.ozlabs.org; Vinod Koul; herbert@gondor.hengli.com.au; Dan > Williams; Li Yang-R58472; davem@davemloft.net > Subject: Re: [linuxppc-release] [PATCH v4 7/7] fsl-dma: add memcpy self > test interface > > On Mon, Jul 30, 2012 at 12:48:41PM -0500, Timur Tabi wrote: > > qiang.liu@freescale.com wrote: > > > > > > Add memory copy self test when probe device, fsl-dma will be disabled > > > if self test failed. > > > > Is this a real problem that can occur? The DMA driver used to have a > > self-test, but I removed it a long time ago because it was pointless. > I > > don't see why we need to add another one back in. > > > > -- > > Timur Tabi > > Linux kernel developer at Freescale > > > > I made a comment that a test suite for the async_tx API would be very > helpful in diagnosing similar problems in this and other DMA drivers. > Something standalone, similar to the drivers/dma/dmatest.c driver, using > the async_tx API. > > I think this was misinterpreted into me asking that the driver have a > built-in self test. I will drop it in next version. Thanks. > > Ira > -- > To unsubscribe from this list: send the line "unsubscribe linux-crypto" > in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
Patch
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 6fc22eb..5e0b162 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1277,6 +1277,82 @@ out_unwind: return ret; } +/* + * Perform a transaction to verify the HW works. + */ +#define FSL_DMA_TEST_SIZE 2000 + +static int __devinit fsl_dma_memcpy_self_test(struct fsldma_device *device) +{ + int i; + void *src, *dest; + dma_addr_t src_dma, dest_dma; + struct dma_chan *dma_chan; + dma_cookie_t cookie; + struct dma_async_tx_descriptor *tx; + int err = 0; + struct fsldma_chan *chan; + + src = kmalloc(sizeof(u8) * FSL_DMA_TEST_SIZE, GFP_KERNEL); + if (!src) + return -ENOMEM; + + dest = kzalloc(sizeof(u8) * FSL_DMA_TEST_SIZE, GFP_KERNEL); + if (!dest) { + kfree(src); + return -ENOMEM; + } + + /* Fill in src buffer */ + for (i = 0; i < FSL_DMA_TEST_SIZE; i++) + ((u8 *) src)[i] = (u8)i; + + /* Start copy, using first DMA channel */ + dma_chan = container_of(device->common.channels.next, + struct dma_chan, device_node); + if (fsl_dma_alloc_chan_resources(dma_chan) < 1) { + err = -ENODEV; + goto out; + } + + chan = to_fsl_chan(dma_chan); + dest_dma = dma_map_single(chan->common.device->dev, dest, + FSL_DMA_TEST_SIZE, DMA_FROM_DEVICE); + + src_dma = dma_map_single(chan->common.device->dev, src, + FSL_DMA_TEST_SIZE, DMA_TO_DEVICE); + + tx = fsl_dma_prep_memcpy(dma_chan, dest_dma, src_dma, FSL_DMA_TEST_SIZE, + DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE); + cookie = fsl_dma_tx_submit(tx); + fsl_dma_memcpy_issue_pending(dma_chan); + async_tx_ack(tx); + msleep(1); + + if (fsl_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { + dev_printk(KERN_ERR, dma_chan->device->dev, + "Self-test copy timed out, disabling\n"); + err = -ENODEV; + goto free_resources; + } + + dma_sync_single_for_cpu(device->dev, dest_dma, + FSL_DMA_TEST_SIZE, DMA_FROM_DEVICE); + if (memcmp(src, dest, FSL_DMA_TEST_SIZE)) { + dev_printk(KERN_ERR, dma_chan->device->dev, + "Self-test copy failed compare, disabling\n"); + err = -ENODEV; + goto free_resources; + } + +free_resources: + fsl_dma_free_chan_resources(dma_chan); +out: + kfree(src); + kfree(dest); + return err; +} + /*----------------------------------------------------------------------------*/ /* OpenFirmware Subsystem */ /*----------------------------------------------------------------------------*/ @@ -1461,6 +1537,13 @@ static int __devinit fsldma_of_probe(struct platform_device *op) goto out_free_fdev; } + if (dma_has_cap(DMA_MEMCPY, fdev->common.cap_mask)) { + err = fsl_dma_memcpy_self_test(fdev); + printk(KERN_INFO "FSL-DMA Channel memcpy self test returned %d\n", err); + if (err) + goto out_free_fdev; + } + dma_async_device_register(&fdev->common); return 0;