linux-raid.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dan Williams <dan.j.williams@intel.com>
To: linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: neilb@suse.de, maciej.sosnowski@intel.com
Subject: [PATCH 09/13] iop-adma: P+Q self test
Date: Wed, 18 Mar 2009 12:21:02 -0700	[thread overview]
Message-ID: <20090318192102.20375.36540.stgit@dwillia2-linux.ch.intel.com> (raw)
In-Reply-To: <20090318191248.20375.40560.stgit@dwillia2-linux.ch.intel.com>

Even though the intent is to extend dmatest with P+Q tests there is
still value in having an always-on sanity check to prevent an
unintentionally broken driver from registering.

This depends on raid6_pq.ko for verification, the side effect being that
PQ capable channels will fail to register when raid6 is disabled.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/dma/iop-adma.c |  182 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 181 insertions(+), 1 deletions(-)

diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 0cdb333..2b014b6 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -31,6 +31,7 @@
 #include <linux/platform_device.h>
 #include <linux/memory.h>
 #include <linux/ioport.h>
+#include <linux/raid/raid6.h>
 
 #include <mach/adma.h>
 
@@ -1200,6 +1201,177 @@ out:
 	return err;
 }
 
+static int __devinit
+iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
+{
+	#ifdef CONFIG_MD_RAID6_PQ
+	/* combined sources, software pq results, and extra hw pq results */
+	struct page *pq[IOP_ADMA_NUM_SRC_TEST+2+2];
+	/* ptr to the extra hw pq buffers defined above */
+	struct page **pq_hw = &pq[IOP_ADMA_NUM_SRC_TEST+2];
+	/* address conversion buffers (dma_map / page_address) */
+	void *pq_sw[IOP_ADMA_NUM_SRC_TEST+2];
+	dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST];
+	dma_addr_t pq_dest[2];
+
+	int i;
+	struct dma_async_tx_descriptor *tx;
+	struct dma_chan *dma_chan;
+	dma_cookie_t cookie;
+	u32 zero_sum_result;
+	int err = 0;
+	struct device *dev;
+
+	dev_dbg(device->common.dev, "%s\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(pq); i++) {
+		pq[i] = alloc_page(GFP_KERNEL);
+		if (!pq[i]) {
+			while (i--)
+				__free_page(pq[i]);
+			return -ENOMEM;
+		}
+	}
+
+	/* Fill in src buffers */
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) {
+		pq_sw[i] = page_address(pq[i]);
+		memset(pq_sw[i], 0x11111111 * (1<<i), PAGE_SIZE);
+	}
+	pq_sw[i] = page_address(pq[i]);
+	pq_sw[i+1] = page_address(pq[i+1]);
+
+	dma_chan = container_of(device->common.channels.next,
+				struct dma_chan,
+				device_node);
+	if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	dev = dma_chan->device->dev;
+
+	/* initialize the dests */
+	memset(page_address(pq_hw[0]), 0 , PAGE_SIZE);
+	memset(page_address(pq_hw[1]), 0 , PAGE_SIZE);
+
+	/* test pq */
+	pq_dest[0] = dma_map_page(dev, pq_hw[0], 0, PAGE_SIZE, DMA_FROM_DEVICE);
+	pq_dest[1] = dma_map_page(dev, pq_hw[1], 0, PAGE_SIZE, DMA_FROM_DEVICE);
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
+		pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE,
+					 DMA_TO_DEVICE);
+
+	tx = iop_adma_prep_dma_pq(dma_chan, pq_dest, pq_src,
+				  IOP_ADMA_NUM_SRC_TEST, (u8 *)raid6_gfexp,
+				  PAGE_SIZE,
+				  DMA_PREP_INTERRUPT |
+				  DMA_CTRL_ACK);
+
+	cookie = iop_adma_tx_submit(tx);
+	iop_adma_issue_pending(dma_chan);
+	msleep(8);
+
+	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+		DMA_SUCCESS) {
+		dev_err(dev, "Self-test pq timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	raid6_call.gen_syndrome(IOP_ADMA_NUM_SRC_TEST+2, PAGE_SIZE, pq_sw);
+
+	if (memcmp(pq_sw[IOP_ADMA_NUM_SRC_TEST],
+		   page_address(pq_hw[0]), PAGE_SIZE) != 0) {
+		dev_err(dev, "Self-test p failed compare, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+	if (memcmp(pq_sw[IOP_ADMA_NUM_SRC_TEST+1],
+		   page_address(pq_hw[1]), PAGE_SIZE) != 0) {
+		dev_err(dev, "Self-test q failed compare, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	/* test correct zero sum using the software generated pq values */
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 2; i++)
+		pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE,
+					 DMA_TO_DEVICE);
+
+	zero_sum_result = ~0;
+	tx = iop_adma_prep_dma_pq_zero_sum(dma_chan, pq_src,
+					   IOP_ADMA_NUM_SRC_TEST + 2,
+					   (u8 *) raid6_gfexp, PAGE_SIZE,
+					   &zero_sum_result,
+					   DMA_PREP_INTERRUPT |
+					   DMA_CTRL_ACK);
+
+	cookie = iop_adma_tx_submit(tx);
+	iop_adma_issue_pending(dma_chan);
+	msleep(8);
+
+	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+		DMA_SUCCESS) {
+		dev_err(dev, "Self-test pq-zero-sum timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	if (zero_sum_result != 0) {
+		dev_err(dev, "Self-test pq-zero-sum failed to validate: %x\n",
+			zero_sum_result);
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	/* test incorrect zero sum */
+	i = IOP_ADMA_NUM_SRC_TEST;
+	memset(pq_sw[i] + 100, 0, 100);
+	memset(pq_sw[i+1] + 200, 0, 200);
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 2; i++)
+		pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE,
+					 DMA_TO_DEVICE);
+
+	zero_sum_result = 0;
+	tx = iop_adma_prep_dma_pq_zero_sum(dma_chan, pq_src,
+					   IOP_ADMA_NUM_SRC_TEST + 2,
+					   (u8 *) raid6_gfexp, PAGE_SIZE,
+					   &zero_sum_result,
+					   DMA_PREP_INTERRUPT |
+					   DMA_CTRL_ACK);
+
+	cookie = iop_adma_tx_submit(tx);
+	iop_adma_issue_pending(dma_chan);
+	msleep(8);
+
+	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+		DMA_SUCCESS) {
+		dev_err(dev, "Self-test !pq-zero-sum timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	if (zero_sum_result != (SUM_CHECK_P_RESULT | SUM_CHECK_Q_RESULT)) {
+		dev_err(dev, "Self-test !pq-zero-sum failed to validate: %x\n",
+			zero_sum_result);
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+free_resources:
+	iop_adma_free_chan_resources(dma_chan);
+out:
+	i = ARRAY_SIZE(pq);
+	while (i--)
+		__free_page(pq[i]);
+	return err;
+	#else
+	return -ENODEV; /* no raid6 support */
+	#endif
+}
+
+
 static int __devexit iop_adma_remove(struct platform_device *dev)
 {
 	struct iop_adma_device *device = platform_get_drvdata(dev);
@@ -1350,13 +1522,21 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
 	}
 
 	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) ||
-		dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) {
+	    dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) {
 		ret = iop_adma_xor_zero_sum_self_test(adev);
 		dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
 		if (ret)
 			goto err_free_iop_chan;
 	}
 
+	if (dma_has_cap(DMA_PQ, dma_dev->cap_mask) &&
+	    dma_has_cap(DMA_PQ_ZERO_SUM, dma_dev->cap_mask)) {
+		ret = iop_adma_pq_zero_sum_self_test(adev);
+		dev_dbg(&pdev->dev, "pq self test returned %d\n", ret);
+		if (ret)
+			goto err_free_iop_chan;
+	}
+
 	dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: "
 	  "( %s%s%s%s%s%s%s%s%s%s)\n",
 	  dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "",


  parent reply	other threads:[~2009-03-18 19:21 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-18 19:20 [PATCH 00/13] Asynchronous raid6 acceleration (part 1 of 2) Dan Williams
2009-03-18 19:20 ` [PATCH 01/13] md/raid6: move raid6 data processing to raid6_pq.ko Dan Williams
2009-03-19 20:09   ` Andre Noll
2009-03-22 17:22     ` Dan Williams
2009-03-18 19:20 ` [PATCH 02/13] async_tx: don't use src_list argument of async_xor() for dma addresses Dan Williams
2009-03-19 20:10   ` Andre Noll
2009-03-25 17:11     ` Dan Williams
2009-03-26 10:39       ` Andre Noll
2009-03-18 19:20 ` [PATCH 03/13] async_tx: provide __async_inline for HAS_DMA=n archs Dan Williams
2009-03-18 19:20 ` [PATCH 04/13] async_tx: kill needless module_{init|exit} Dan Williams
2009-03-18 19:20 ` [PATCH 05/13] async_tx: add sum check flags Dan Williams
2009-03-18 19:20 ` [PATCH 06/13] async_tx: add support for asynchronous GF multiplication Dan Williams
2009-03-19 16:06   ` H. Peter Anvin
2009-03-19 17:20     ` Dan Williams
2009-03-20 22:43       ` H. Peter Anvin
2009-03-20 23:00         ` Ilya Yanok
2009-03-20 23:25           ` H. Peter Anvin
2009-03-21  0:06             ` Ilya Yanok
2009-03-21  2:30               ` H. Peter Anvin
2009-03-21 10:19                 ` Ilya Yanok
2009-03-21 19:16                   ` H. Peter Anvin
2009-03-21 15:19                 ` Dan Williams
2009-03-21 19:15                   ` H. Peter Anvin
2009-03-21 22:14                     ` Dan Williams
2009-03-21 22:26                       ` Ilya Yanok
2009-03-21 22:46                         ` Dan Williams
2009-03-21 20:05     ` Ilya Yanok
2009-03-21 22:00       ` Dan Williams
2009-03-21 22:43         ` Ilya Yanok
2009-03-21 22:53           ` Dan Williams
2009-03-22 21:37             ` Ilya Yanok
2009-03-19 20:09   ` Andre Noll
2009-03-30 14:30   ` Sosnowski, Maciej
2009-03-18 19:20 ` [PATCH 07/13] async_tx: add support for asynchronous RAID6 recovery operations Dan Williams
2009-03-23 10:11   ` Andre Noll
2009-03-30 14:30   ` Sosnowski, Maciej
2009-03-18 19:20 ` [PATCH 08/13] iop-adma: P+Q support for iop13xx adma engines Dan Williams
2009-03-18 19:21 ` Dan Williams [this message]
2009-03-20  0:14   ` [PATCH 09/13] iop-adma: P+Q self test Neil Brown
2009-03-20  0:19     ` Dan Williams
2009-03-30 14:30   ` Sosnowski, Maciej
2009-03-18 19:21 ` [PATCH 10/13] dmaengine: allow dma support for async_tx to be toggled Dan Williams
2009-03-18 19:21 ` [PATCH 11/13] dmatest: add xor test Dan Williams
2009-03-18 19:21 ` [PATCH 12/13] dmatest: add dma interrupts and callbacks Dan Williams
2009-03-18 19:21 ` [PATCH 13/13] dmatest: add pq support Dan Williams
2009-03-18 23:43 ` [PATCH 00/13] Asynchronous raid6 acceleration (part 1 of 2) Andi Kleen
2009-03-19 17:08   ` Dan Williams
2009-03-20  0:30 ` Neil Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090318192102.20375.36540.stgit@dwillia2-linux.ch.intel.com \
    --to=dan.j.williams@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-raid@vger.kernel.org \
    --cc=maciej.sosnowski@intel.com \
    --cc=neilb@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).