From 7369f56e3e7193583576ec705d95647b04838b05 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 5 Nov 2012 10:00:19 +0000 Subject: [PATCH] ioat3: add missing DMA unmap to ioat_xor_val_self_test() Make ioat_xor_val_self_test() do DMA unmapping itself and fix handling of failure cases. Cc: Dan Williams Cc: Tomasz Figa Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Signed-off-by: Dan Williams --- drivers/dma/ioat/dma_v3.c | 76 ++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index f7f1dc62c15c..6456f7d38e13 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -863,6 +863,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) unsigned long tmo; struct device *dev = &device->pdev->dev; struct dma_device *dma = &device->common; + u8 op = 0; dev_dbg(dev, "%s\n", __func__); @@ -908,18 +909,22 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) } /* test xor */ + op = IOAT_OP_XOR; + dest_dma = dma_map_page(dev, dest, 0, PAGE_SIZE, DMA_FROM_DEVICE); for (i = 0; i < IOAT_NUM_SRC_TEST; i++) dma_srcs[i] = dma_map_page(dev, xor_srcs[i], 0, PAGE_SIZE, DMA_TO_DEVICE); tx = dma->device_prep_dma_xor(dma_chan, dest_dma, dma_srcs, IOAT_NUM_SRC_TEST, PAGE_SIZE, - DMA_PREP_INTERRUPT); + DMA_PREP_INTERRUPT | + DMA_COMPL_SKIP_SRC_UNMAP | + DMA_COMPL_SKIP_DEST_UNMAP); if (!tx) { dev_err(dev, "Self-test xor prep failed\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } async_tx_ack(tx); @@ -930,7 +935,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test xor setup failed\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } dma->device_issue_pending(dma_chan); @@ -939,9 +944,13 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { dev_err(dev, "Self-test xor timed out\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } + dma_unmap_page(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); + for (i = 0; i < IOAT_NUM_SRC_TEST; i++) + dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, DMA_TO_DEVICE); + dma_sync_single_for_cpu(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) { u32 *ptr = page_address(dest); @@ -957,6 +966,8 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) goto free_resources; + op = IOAT_OP_XOR_VAL; + /* validate the sources with the destintation page */ for (i = 0; i < IOAT_NUM_SRC_TEST; i++) xor_val_srcs[i] = xor_srcs[i]; @@ -969,11 +980,13 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) DMA_TO_DEVICE); tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs, IOAT_NUM_SRC_TEST + 1, PAGE_SIZE, - &xor_val_result, DMA_PREP_INTERRUPT); + &xor_val_result, DMA_PREP_INTERRUPT | + DMA_COMPL_SKIP_SRC_UNMAP | + DMA_COMPL_SKIP_DEST_UNMAP); if (!tx) { dev_err(dev, "Self-test zero prep failed\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } async_tx_ack(tx); @@ -984,7 +997,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test zero setup failed\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } dma->device_issue_pending(dma_chan); @@ -993,9 +1006,12 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { dev_err(dev, "Self-test validate timed out\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } + for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) + dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, DMA_TO_DEVICE); + if (xor_val_result != 0) { dev_err(dev, "Self-test validate failed compare\n"); err = -ENODEV; @@ -1007,14 +1023,18 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) goto free_resources; /* test memset */ + op = IOAT_OP_FILL; + dma_addr = dma_map_page(dev, dest, 0, PAGE_SIZE, DMA_FROM_DEVICE); tx = dma->device_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, - DMA_PREP_INTERRUPT); + DMA_PREP_INTERRUPT | + DMA_COMPL_SKIP_SRC_UNMAP | + DMA_COMPL_SKIP_DEST_UNMAP); if (!tx) { dev_err(dev, "Self-test memset prep failed\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } async_tx_ack(tx); @@ -1025,7 +1045,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test memset setup failed\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } dma->device_issue_pending(dma_chan); @@ -1034,9 +1054,11 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { dev_err(dev, "Self-test memset timed out\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } + dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); + for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) { u32 *ptr = page_address(dest); if (ptr[i]) { @@ -1047,17 +1069,21 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) } /* test for non-zero parity sum */ + op = IOAT_OP_XOR_VAL; + xor_val_result = 0; for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) dma_srcs[i] = dma_map_page(dev, xor_val_srcs[i], 0, PAGE_SIZE, DMA_TO_DEVICE); tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs, IOAT_NUM_SRC_TEST + 1, PAGE_SIZE, - &xor_val_result, DMA_PREP_INTERRUPT); + &xor_val_result, DMA_PREP_INTERRUPT | + DMA_COMPL_SKIP_SRC_UNMAP | + DMA_COMPL_SKIP_DEST_UNMAP); if (!tx) { dev_err(dev, "Self-test 2nd zero prep failed\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } async_tx_ack(tx); @@ -1068,7 +1094,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (cookie < 0) { dev_err(dev, "Self-test 2nd zero setup failed\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } dma->device_issue_pending(dma_chan); @@ -1077,15 +1103,31 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) { dev_err(dev, "Self-test 2nd validate timed out\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } if (xor_val_result != SUM_CHECK_P_RESULT) { dev_err(dev, "Self-test validate failed compare\n"); err = -ENODEV; - goto free_resources; + goto dma_unmap; } + for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) + dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, DMA_TO_DEVICE); + + goto free_resources; +dma_unmap: + if (op == IOAT_OP_XOR) { + dma_unmap_page(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); + for (i = 0; i < IOAT_NUM_SRC_TEST; i++) + dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, + DMA_TO_DEVICE); + } else if (op == IOAT_OP_XOR_VAL) { + for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) + dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, + DMA_TO_DEVICE); + } else if (op == IOAT_OP_FILL) + dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); free_resources: dma->device_free_chan_resources(dma_chan); out: