Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 165823
b: refs/heads/master
c: f6dbf65
h: refs/heads/master
i:
  165821: 6cfaa3e
  165819: d7c173f
  165815: ed481b1
  165807: 0b78e3b
  165791: a7c24a9
  165759: 6116f09
v: v3
  • Loading branch information
Dan Williams committed Aug 30, 2009
1 parent 0be7439 commit 04c5343
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7bf649aee8ac93ecc280f8745dcf8ec19d7b9fb1
refs/heads/master: f6dbf651615900646fe0ba1ef5ce1027e5b4748d
182 changes: 181 additions & 1 deletion trunk/drivers/dma/iop-adma.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/memory.h>
#include <linux/ioport.h>
#include <linux/raid/pq.h>

#include <mach/adma.h>

Expand Down Expand Up @@ -1267,6 +1268,170 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
return err;
}

#ifdef CONFIG_MD_RAID6_PQ
static int __devinit
iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
{
/* 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_val(dma_chan, &pq_src[IOP_ADMA_NUM_SRC_TEST],
pq_src, IOP_ADMA_NUM_SRC_TEST,
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_val(dma_chan, &pq_src[IOP_ADMA_NUM_SRC_TEST],
pq_src, IOP_ADMA_NUM_SRC_TEST,
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;
}
#endif

static int __devexit iop_adma_remove(struct platform_device *dev)
{
struct iop_adma_device *device = platform_get_drvdata(dev);
Expand Down Expand Up @@ -1417,13 +1582,28 @@ 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_val_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_VAL, dma_dev->cap_mask)) {
#ifdef CONFIG_MD_RAID6_PQ
ret = iop_adma_pq_zero_sum_self_test(adev);
dev_dbg(&pdev->dev, "pq self test returned %d\n", ret);
#else
/* can not test raid6, so do not publish capability */
dma_cap_clear(DMA_PQ, dma_dev->cap_mask);
dma_cap_clear(DMA_PQ_VAL, dma_dev->cap_mask);
ret = 0;
#endif
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 " : "",
Expand Down

0 comments on commit 04c5343

Please sign in to comment.