diff options
author | Dan Williams <dan.j.williams@intel.com> | 2009-09-08 20:42:29 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2009-09-08 20:42:29 -0400 |
commit | f9dd2134374c8de6b911e2b8652c6c9622eaa658 (patch) | |
tree | c1b8f8d622941606b9e7247ab31d811ba4295011 /drivers/dma | |
parent | 4b652f0db3be891c7b76b109c3b55003b920fc96 (diff) | |
parent | 07a3b417dc3d00802bd7b4874c3e811f0b015a7d (diff) |
Merge branch 'md-raid6-accel' into ioat3.2
Conflicts:
include/linux/dmaengine.h
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/Kconfig | 2 | ||||
-rw-r--r-- | drivers/dma/dmaengine.c | 53 | ||||
-rw-r--r-- | drivers/dma/dmatest.c | 26 | ||||
-rw-r--r-- | drivers/dma/iop-adma.c | 40 |
4 files changed, 63 insertions, 58 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 3b3c01b6f1ee..912a51b5cbd3 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | menuconfig DMADEVICES | 5 | menuconfig DMADEVICES |
6 | bool "DMA Engine support" | 6 | bool "DMA Engine support" |
7 | depends on !HIGHMEM64G && HAS_DMA | 7 | depends on HAS_DMA |
8 | help | 8 | help |
9 | DMA engines can do asynchronous data transfers without | 9 | DMA engines can do asynchronous data transfers without |
10 | involving the host CPU. Currently, this framework can be | 10 | involving the host CPU. Currently, this framework can be |
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 5a87384ea4ff..96598479eece 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -644,8 +644,12 @@ int dma_async_device_register(struct dma_device *device) | |||
644 | !device->device_prep_dma_memcpy); | 644 | !device->device_prep_dma_memcpy); |
645 | BUG_ON(dma_has_cap(DMA_XOR, device->cap_mask) && | 645 | BUG_ON(dma_has_cap(DMA_XOR, device->cap_mask) && |
646 | !device->device_prep_dma_xor); | 646 | !device->device_prep_dma_xor); |
647 | BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) && | 647 | BUG_ON(dma_has_cap(DMA_XOR_VAL, device->cap_mask) && |
648 | !device->device_prep_dma_zero_sum); | 648 | !device->device_prep_dma_xor_val); |
649 | BUG_ON(dma_has_cap(DMA_PQ, device->cap_mask) && | ||
650 | !device->device_prep_dma_pq); | ||
651 | BUG_ON(dma_has_cap(DMA_PQ_VAL, device->cap_mask) && | ||
652 | !device->device_prep_dma_pq_val); | ||
649 | BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) && | 653 | BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) && |
650 | !device->device_prep_dma_memset); | 654 | !device->device_prep_dma_memset); |
651 | BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) && | 655 | BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) && |
@@ -939,49 +943,24 @@ EXPORT_SYMBOL(dma_async_tx_descriptor_init); | |||
939 | 943 | ||
940 | /* dma_wait_for_async_tx - spin wait for a transaction to complete | 944 | /* dma_wait_for_async_tx - spin wait for a transaction to complete |
941 | * @tx: in-flight transaction to wait on | 945 | * @tx: in-flight transaction to wait on |
942 | * | ||
943 | * This routine assumes that tx was obtained from a call to async_memcpy, | ||
944 | * async_xor, async_memset, etc which ensures that tx is "in-flight" (prepped | ||
945 | * and submitted). Walking the parent chain is only meant to cover for DMA | ||
946 | * drivers that do not implement the DMA_INTERRUPT capability and may race with | ||
947 | * the driver's descriptor cleanup routine. | ||
948 | */ | 946 | */ |
949 | enum dma_status | 947 | enum dma_status |
950 | dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) | 948 | dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) |
951 | { | 949 | { |
952 | enum dma_status status; | 950 | unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000); |
953 | struct dma_async_tx_descriptor *iter; | ||
954 | struct dma_async_tx_descriptor *parent; | ||
955 | 951 | ||
956 | if (!tx) | 952 | if (!tx) |
957 | return DMA_SUCCESS; | 953 | return DMA_SUCCESS; |
958 | 954 | ||
959 | WARN_ONCE(tx->parent, "%s: speculatively walking dependency chain for" | 955 | while (tx->cookie == -EBUSY) { |
960 | " %s\n", __func__, dma_chan_name(tx->chan)); | 956 | if (time_after_eq(jiffies, dma_sync_wait_timeout)) { |
961 | 957 | pr_err("%s timeout waiting for descriptor submission\n", | |
962 | /* poll through the dependency chain, return when tx is complete */ | 958 | __func__); |
963 | do { | 959 | return DMA_ERROR; |
964 | iter = tx; | 960 | } |
965 | 961 | cpu_relax(); | |
966 | /* find the root of the unsubmitted dependency chain */ | 962 | } |
967 | do { | 963 | return dma_sync_wait(tx->chan, tx->cookie); |
968 | parent = iter->parent; | ||
969 | if (!parent) | ||
970 | break; | ||
971 | else | ||
972 | iter = parent; | ||
973 | } while (parent); | ||
974 | |||
975 | /* there is a small window for ->parent == NULL and | ||
976 | * ->cookie == -EBUSY | ||
977 | */ | ||
978 | while (iter->cookie == -EBUSY) | ||
979 | cpu_relax(); | ||
980 | |||
981 | status = dma_sync_wait(iter->chan, iter->cookie); | ||
982 | } while (status == DMA_IN_PROGRESS || (iter != tx)); | ||
983 | |||
984 | return status; | ||
985 | } | 964 | } |
986 | EXPORT_SYMBOL_GPL(dma_wait_for_async_tx); | 965 | EXPORT_SYMBOL_GPL(dma_wait_for_async_tx); |
987 | 966 | ||
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index fb7da5141e96..58e49e41c7a3 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c | |||
@@ -43,6 +43,11 @@ module_param(xor_sources, uint, S_IRUGO); | |||
43 | MODULE_PARM_DESC(xor_sources, | 43 | MODULE_PARM_DESC(xor_sources, |
44 | "Number of xor source buffers (default: 3)"); | 44 | "Number of xor source buffers (default: 3)"); |
45 | 45 | ||
46 | static unsigned int pq_sources = 3; | ||
47 | module_param(pq_sources, uint, S_IRUGO); | ||
48 | MODULE_PARM_DESC(pq_sources, | ||
49 | "Number of p+q source buffers (default: 3)"); | ||
50 | |||
46 | /* | 51 | /* |
47 | * Initialization patterns. All bytes in the source buffer has bit 7 | 52 | * Initialization patterns. All bytes in the source buffer has bit 7 |
48 | * set, all bytes in the destination buffer has bit 7 cleared. | 53 | * set, all bytes in the destination buffer has bit 7 cleared. |
@@ -227,6 +232,7 @@ static int dmatest_func(void *data) | |||
227 | dma_cookie_t cookie; | 232 | dma_cookie_t cookie; |
228 | enum dma_status status; | 233 | enum dma_status status; |
229 | enum dma_ctrl_flags flags; | 234 | enum dma_ctrl_flags flags; |
235 | u8 pq_coefs[pq_sources]; | ||
230 | int ret; | 236 | int ret; |
231 | int src_cnt; | 237 | int src_cnt; |
232 | int dst_cnt; | 238 | int dst_cnt; |
@@ -243,6 +249,11 @@ static int dmatest_func(void *data) | |||
243 | else if (thread->type == DMA_XOR) { | 249 | else if (thread->type == DMA_XOR) { |
244 | src_cnt = xor_sources | 1; /* force odd to ensure dst = src */ | 250 | src_cnt = xor_sources | 1; /* force odd to ensure dst = src */ |
245 | dst_cnt = 1; | 251 | dst_cnt = 1; |
252 | } else if (thread->type == DMA_PQ) { | ||
253 | src_cnt = pq_sources | 1; /* force odd to ensure dst = src */ | ||
254 | dst_cnt = 2; | ||
255 | for (i = 0; i < pq_sources; i++) | ||
256 | pq_coefs[i] = 1; | ||
246 | } else | 257 | } else |
247 | goto err_srcs; | 258 | goto err_srcs; |
248 | 259 | ||
@@ -310,6 +321,15 @@ static int dmatest_func(void *data) | |||
310 | dma_dsts[0] + dst_off, | 321 | dma_dsts[0] + dst_off, |
311 | dma_srcs, xor_sources, | 322 | dma_srcs, xor_sources, |
312 | len, flags); | 323 | len, flags); |
324 | else if (thread->type == DMA_PQ) { | ||
325 | dma_addr_t dma_pq[dst_cnt]; | ||
326 | |||
327 | for (i = 0; i < dst_cnt; i++) | ||
328 | dma_pq[i] = dma_dsts[i] + dst_off; | ||
329 | tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs, | ||
330 | pq_sources, pq_coefs, | ||
331 | len, flags); | ||
332 | } | ||
313 | 333 | ||
314 | if (!tx) { | 334 | if (!tx) { |
315 | for (i = 0; i < src_cnt; i++) | 335 | for (i = 0; i < src_cnt; i++) |
@@ -446,6 +466,8 @@ static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_ty | |||
446 | op = "copy"; | 466 | op = "copy"; |
447 | else if (type == DMA_XOR) | 467 | else if (type == DMA_XOR) |
448 | op = "xor"; | 468 | op = "xor"; |
469 | else if (type == DMA_PQ) | ||
470 | op = "pq"; | ||
449 | else | 471 | else |
450 | return -EINVAL; | 472 | return -EINVAL; |
451 | 473 | ||
@@ -501,6 +523,10 @@ static int dmatest_add_channel(struct dma_chan *chan) | |||
501 | cnt = dmatest_add_threads(dtc, DMA_XOR); | 523 | cnt = dmatest_add_threads(dtc, DMA_XOR); |
502 | thread_count += cnt > 0 ?: 0; | 524 | thread_count += cnt > 0 ?: 0; |
503 | } | 525 | } |
526 | if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { | ||
527 | cnt = dmatest_add_threads(dtc, DMA_PQ); | ||
528 | thread_count += cnt > 0 ?: 0; | ||
529 | } | ||
504 | 530 | ||
505 | pr_info("dmatest: Started %u threads using %s\n", | 531 | pr_info("dmatest: Started %u threads using %s\n", |
506 | thread_count, dma_chan_name(chan)); | 532 | thread_count, dma_chan_name(chan)); |
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 2f052265122f..4496bc606662 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
@@ -660,9 +660,9 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest, | |||
660 | } | 660 | } |
661 | 661 | ||
662 | static struct dma_async_tx_descriptor * | 662 | static struct dma_async_tx_descriptor * |
663 | iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src, | 663 | iop_adma_prep_dma_xor_val(struct dma_chan *chan, dma_addr_t *dma_src, |
664 | unsigned int src_cnt, size_t len, u32 *result, | 664 | unsigned int src_cnt, size_t len, u32 *result, |
665 | unsigned long flags) | 665 | unsigned long flags) |
666 | { | 666 | { |
667 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); | 667 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); |
668 | struct iop_adma_desc_slot *sw_desc, *grp_start; | 668 | struct iop_adma_desc_slot *sw_desc, *grp_start; |
@@ -906,7 +906,7 @@ out: | |||
906 | 906 | ||
907 | #define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */ | 907 | #define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */ |
908 | static int __devinit | 908 | static int __devinit |
909 | iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | 909 | iop_adma_xor_val_self_test(struct iop_adma_device *device) |
910 | { | 910 | { |
911 | int i, src_idx; | 911 | int i, src_idx; |
912 | struct page *dest; | 912 | struct page *dest; |
@@ -1002,7 +1002,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
1002 | PAGE_SIZE, DMA_TO_DEVICE); | 1002 | PAGE_SIZE, DMA_TO_DEVICE); |
1003 | 1003 | ||
1004 | /* skip zero sum if the capability is not present */ | 1004 | /* skip zero sum if the capability is not present */ |
1005 | if (!dma_has_cap(DMA_ZERO_SUM, dma_chan->device->cap_mask)) | 1005 | if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) |
1006 | goto free_resources; | 1006 | goto free_resources; |
1007 | 1007 | ||
1008 | /* zero sum the sources with the destintation page */ | 1008 | /* zero sum the sources with the destintation page */ |
@@ -1016,10 +1016,10 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
1016 | dma_srcs[i] = dma_map_page(dma_chan->device->dev, | 1016 | dma_srcs[i] = dma_map_page(dma_chan->device->dev, |
1017 | zero_sum_srcs[i], 0, PAGE_SIZE, | 1017 | zero_sum_srcs[i], 0, PAGE_SIZE, |
1018 | DMA_TO_DEVICE); | 1018 | DMA_TO_DEVICE); |
1019 | tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs, | 1019 | tx = iop_adma_prep_dma_xor_val(dma_chan, dma_srcs, |
1020 | IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE, | 1020 | IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE, |
1021 | &zero_sum_result, | 1021 | &zero_sum_result, |
1022 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 1022 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
1023 | 1023 | ||
1024 | cookie = iop_adma_tx_submit(tx); | 1024 | cookie = iop_adma_tx_submit(tx); |
1025 | iop_adma_issue_pending(dma_chan); | 1025 | iop_adma_issue_pending(dma_chan); |
@@ -1072,10 +1072,10 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
1072 | dma_srcs[i] = dma_map_page(dma_chan->device->dev, | 1072 | dma_srcs[i] = dma_map_page(dma_chan->device->dev, |
1073 | zero_sum_srcs[i], 0, PAGE_SIZE, | 1073 | zero_sum_srcs[i], 0, PAGE_SIZE, |
1074 | DMA_TO_DEVICE); | 1074 | DMA_TO_DEVICE); |
1075 | tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs, | 1075 | tx = iop_adma_prep_dma_xor_val(dma_chan, dma_srcs, |
1076 | IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE, | 1076 | IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE, |
1077 | &zero_sum_result, | 1077 | &zero_sum_result, |
1078 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 1078 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
1079 | 1079 | ||
1080 | cookie = iop_adma_tx_submit(tx); | 1080 | cookie = iop_adma_tx_submit(tx); |
1081 | iop_adma_issue_pending(dma_chan); | 1081 | iop_adma_issue_pending(dma_chan); |
@@ -1192,9 +1192,9 @@ static int __devinit iop_adma_probe(struct platform_device *pdev) | |||
1192 | dma_dev->max_xor = iop_adma_get_max_xor(); | 1192 | dma_dev->max_xor = iop_adma_get_max_xor(); |
1193 | dma_dev->device_prep_dma_xor = iop_adma_prep_dma_xor; | 1193 | dma_dev->device_prep_dma_xor = iop_adma_prep_dma_xor; |
1194 | } | 1194 | } |
1195 | if (dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask)) | 1195 | if (dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask)) |
1196 | dma_dev->device_prep_dma_zero_sum = | 1196 | dma_dev->device_prep_dma_xor_val = |
1197 | iop_adma_prep_dma_zero_sum; | 1197 | iop_adma_prep_dma_xor_val; |
1198 | if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask)) | 1198 | if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask)) |
1199 | dma_dev->device_prep_dma_interrupt = | 1199 | dma_dev->device_prep_dma_interrupt = |
1200 | iop_adma_prep_dma_interrupt; | 1200 | iop_adma_prep_dma_interrupt; |
@@ -1249,7 +1249,7 @@ static int __devinit iop_adma_probe(struct platform_device *pdev) | |||
1249 | 1249 | ||
1250 | if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) || | 1250 | if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) || |
1251 | dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) { | 1251 | dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) { |
1252 | ret = iop_adma_xor_zero_sum_self_test(adev); | 1252 | ret = iop_adma_xor_val_self_test(adev); |
1253 | dev_dbg(&pdev->dev, "xor self test returned %d\n", ret); | 1253 | dev_dbg(&pdev->dev, "xor self test returned %d\n", ret); |
1254 | if (ret) | 1254 | if (ret) |
1255 | goto err_free_iop_chan; | 1255 | goto err_free_iop_chan; |
@@ -1257,12 +1257,12 @@ static int __devinit iop_adma_probe(struct platform_device *pdev) | |||
1257 | 1257 | ||
1258 | dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: " | 1258 | dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: " |
1259 | "( %s%s%s%s%s%s%s%s%s%s)\n", | 1259 | "( %s%s%s%s%s%s%s%s%s%s)\n", |
1260 | dma_has_cap(DMA_PQ_XOR, dma_dev->cap_mask) ? "pq_xor " : "", | 1260 | dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "", |
1261 | dma_has_cap(DMA_PQ_UPDATE, dma_dev->cap_mask) ? "pq_update " : "", | 1261 | dma_has_cap(DMA_PQ_UPDATE, dma_dev->cap_mask) ? "pq_update " : "", |
1262 | dma_has_cap(DMA_PQ_ZERO_SUM, dma_dev->cap_mask) ? "pq_zero_sum " : "", | 1262 | dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask) ? "pq_val " : "", |
1263 | dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "", | 1263 | dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "", |
1264 | dma_has_cap(DMA_DUAL_XOR, dma_dev->cap_mask) ? "dual_xor " : "", | 1264 | dma_has_cap(DMA_DUAL_XOR, dma_dev->cap_mask) ? "dual_xor " : "", |
1265 | dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask) ? "xor_zero_sum " : "", | 1265 | dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask) ? "xor_val " : "", |
1266 | dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "", | 1266 | dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "", |
1267 | dma_has_cap(DMA_MEMCPY_CRC32C, dma_dev->cap_mask) ? "cpy+crc " : "", | 1267 | dma_has_cap(DMA_MEMCPY_CRC32C, dma_dev->cap_mask) ? "cpy+crc " : "", |
1268 | dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "", | 1268 | dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "", |