Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: ack to flags: make use of the unused bits in the 'ack' field

'ack' is currently a simple integer that flags whether or not a client is done
touching fields in the given descriptor. It is effectively just a single bit
of information. Converting this to a flags parameter allows the other bits to
be put to use to control completion actions, like dma-unmap, and capture
results, like xor-zero-sum == 0.

Changes are one of:
1/ convert all open-coded ->ack manipulations to use async_tx_ack
and async_tx_test_ack.
2/ set the ack bit at prep time where possible
3/ make drivers store the flags at prep time
4/ add flags to the device_prep_dma_interrupt prototype

Acked-by: Maciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+69 -54
+1 -1
crypto/async_tx/async_memcpy.c
··· 77 77 /* if ack is already set then we cannot be sure 78 78 * we are referring to the correct operation 79 79 */ 80 - BUG_ON(depend_tx->ack); 80 + BUG_ON(async_tx_test_ack(depend_tx)); 81 81 if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR) 82 82 panic("%s: DMA_ERROR waiting for depend_tx\n", 83 83 __func__);
+5 -4
crypto/async_tx/async_tx.c
··· 446 446 * otherwise poll for completion 447 447 */ 448 448 if (dma_has_cap(DMA_INTERRUPT, device->cap_mask)) 449 - intr_tx = device->device_prep_dma_interrupt(chan); 449 + intr_tx = device->device_prep_dma_interrupt(chan, 0); 450 450 else 451 451 intr_tx = NULL; 452 452 ··· 515 515 * 2/ dependencies are 1:1 i.e. two transactions can 516 516 * not depend on the same parent 517 517 */ 518 - BUG_ON(depend_tx->ack || depend_tx->next || tx->parent); 518 + BUG_ON(async_tx_test_ack(depend_tx) || depend_tx->next || 519 + tx->parent); 519 520 520 521 /* the lock prevents async_tx_run_dependencies from missing 521 522 * the setting of ->next when ->parent != NULL ··· 595 594 if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask)) 596 595 device = NULL; 597 596 598 - tx = device ? device->device_prep_dma_interrupt(chan) : NULL; 597 + tx = device ? device->device_prep_dma_interrupt(chan, 0) : NULL; 599 598 } else 600 599 tx = NULL; 601 600 ··· 611 610 /* if ack is already set then we cannot be sure 612 611 * we are referring to the correct operation 613 612 */ 614 - BUG_ON(depend_tx->ack); 613 + BUG_ON(async_tx_test_ack(depend_tx)); 615 614 if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR) 616 615 panic("%s: DMA_ERROR waiting for depend_tx\n", 617 616 __func__);
+1 -1
crypto/async_tx/async_xor.c
··· 191 191 /* if ack is already set then we cannot be sure 192 192 * we are referring to the correct operation 193 193 */ 194 - BUG_ON(depend_tx->ack); 194 + BUG_ON(async_tx_test_ack(depend_tx)); 195 195 if (dma_wait_for_async_tx(depend_tx) == 196 196 DMA_ERROR) 197 197 panic("%s: DMA_ERROR waiting for "
+6 -6
drivers/dma/dmaengine.c
··· 478 478 479 479 dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE); 480 480 dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE); 481 - tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0); 481 + tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 482 + DMA_CTRL_ACK); 482 483 483 484 if (!tx) { 484 485 dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE); ··· 487 486 return -ENOMEM; 488 487 } 489 488 490 - tx->ack = 1; 491 489 tx->callback = NULL; 492 490 cookie = tx->tx_submit(tx); 493 491 ··· 524 524 525 525 dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE); 526 526 dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE); 527 - tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0); 527 + tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 528 + DMA_CTRL_ACK); 528 529 529 530 if (!tx) { 530 531 dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE); ··· 533 532 return -ENOMEM; 534 533 } 535 534 536 - tx->ack = 1; 537 535 tx->callback = NULL; 538 536 cookie = tx->tx_submit(tx); 539 537 ··· 573 573 dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE); 574 574 dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len, 575 575 DMA_FROM_DEVICE); 576 - tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0); 576 + tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 577 + DMA_CTRL_ACK); 577 578 578 579 if (!tx) { 579 580 dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE); ··· 582 581 return -ENOMEM; 583 582 } 584 583 585 - tx->ack = 1; 586 584 tx->callback = NULL; 587 585 cookie = tx->tx_submit(tx); 588 586
+5 -5
drivers/dma/fsldma.c
··· 412 412 } 413 413 414 414 static struct dma_async_tx_descriptor * 415 - fsl_dma_prep_interrupt(struct dma_chan *chan) 415 + fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags) 416 416 { 417 417 struct fsl_dma_chan *fsl_chan; 418 418 struct fsl_desc_sw *new; ··· 429 429 } 430 430 431 431 new->async_tx.cookie = -EBUSY; 432 - new->async_tx.ack = 0; 432 + new->async_tx.flags = flags; 433 433 434 434 /* Insert the link descriptor to the LD ring */ 435 435 list_add_tail(&new->node, &new->async_tx.tx_list); ··· 482 482 set_desc_next(fsl_chan, &prev->hw, new->async_tx.phys); 483 483 484 484 new->async_tx.cookie = 0; 485 - new->async_tx.ack = 1; 485 + async_tx_ack(&new->async_tx); 486 486 487 487 prev = new; 488 488 len -= copy; ··· 493 493 list_add_tail(&new->node, &first->async_tx.tx_list); 494 494 } while (len); 495 495 496 - new->async_tx.ack = 0; /* client is in control of this ack */ 496 + new->async_tx.flags = flags; /* client is in control of this ack */ 497 497 new->async_tx.cookie = -EBUSY; 498 498 499 499 /* Set End-of-link to the last link descriptor of new list*/ ··· 874 874 async_tx_ack(tx3); 875 875 876 876 /* Interrupt tx test */ 877 - tx1 = fsl_dma_prep_interrupt(chan); 877 + tx1 = fsl_dma_prep_interrupt(chan, 0); 878 878 async_tx_ack(tx1); 879 879 cookie = fsl_dma_tx_submit(tx1); 880 880
+12 -12
drivers/dma/ioat_dma.c
··· 212 212 u32 copy; 213 213 size_t len; 214 214 dma_addr_t src, dst; 215 - int orig_ack; 215 + unsigned long orig_flags; 216 216 unsigned int desc_count = 0; 217 217 218 218 /* src and dest and len are stored in the initial descriptor */ 219 219 len = first->len; 220 220 src = first->src; 221 221 dst = first->dst; 222 - orig_ack = first->async_tx.ack; 222 + orig_flags = first->async_tx.flags; 223 223 new = first; 224 224 225 225 spin_lock_bh(&ioat_chan->desc_lock); ··· 228 228 do { 229 229 copy = min_t(size_t, len, ioat_chan->xfercap); 230 230 231 - new->async_tx.ack = 1; 231 + async_tx_ack(&new->async_tx); 232 232 233 233 hw = new->hw; 234 234 hw->size = copy; ··· 264 264 } 265 265 266 266 new->tx_cnt = desc_count; 267 - new->async_tx.ack = orig_ack; /* client is in control of this ack */ 267 + new->async_tx.flags = orig_flags; /* client is in control of this ack */ 268 268 269 269 /* store the original values for use in later cleanup */ 270 270 if (new != first) { ··· 304 304 u32 copy; 305 305 size_t len; 306 306 dma_addr_t src, dst; 307 - int orig_ack; 307 + unsigned long orig_flags; 308 308 unsigned int desc_count = 0; 309 309 310 310 /* src and dest and len are stored in the initial descriptor */ 311 311 len = first->len; 312 312 src = first->src; 313 313 dst = first->dst; 314 - orig_ack = first->async_tx.ack; 314 + orig_flags = first->async_tx.flags; 315 315 new = first; 316 316 317 317 /* ··· 321 321 do { 322 322 copy = min_t(size_t, len, ioat_chan->xfercap); 323 323 324 - new->async_tx.ack = 1; 324 + async_tx_ack(&new->async_tx); 325 325 326 326 hw = new->hw; 327 327 hw->size = copy; ··· 349 349 } 350 350 351 351 new->tx_cnt = desc_count; 352 - new->async_tx.ack = orig_ack; /* client is in control of this ack */ 352 + new->async_tx.flags = orig_flags; /* client is in control of this ack */ 353 353 354 354 /* store the original values for use in later cleanup */ 355 355 if (new != first) { ··· 714 714 new->len = len; 715 715 new->dst = dma_dest; 716 716 new->src = dma_src; 717 - new->async_tx.ack = 0; 717 + new->async_tx.flags = flags; 718 718 return &new->async_tx; 719 719 } else 720 720 return NULL; ··· 742 742 new->len = len; 743 743 new->dst = dma_dest; 744 744 new->src = dma_src; 745 - new->async_tx.ack = 0; 745 + new->async_tx.flags = flags; 746 746 return &new->async_tx; 747 747 } else 748 748 return NULL; ··· 842 842 * a completed entry, but not the last, so clean 843 843 * up if the client is done with the descriptor 844 844 */ 845 - if (desc->async_tx.ack) { 845 + if (async_tx_test_ack(&desc->async_tx)) { 846 846 list_del(&desc->node); 847 847 list_add_tail(&desc->node, 848 848 &ioat_chan->free_desc); ··· 979 979 desc->hw->size = 0; 980 980 desc->hw->src_addr = 0; 981 981 desc->hw->dst_addr = 0; 982 - desc->async_tx.ack = 1; 982 + async_tx_ack(&desc->async_tx); 983 983 switch (ioat_chan->device->version) { 984 984 case IOAT_VER_1_2: 985 985 desc->hw->next = 0;
+21 -18
drivers/dma/iop-adma.c
··· 111 111 /* the client is allowed to attach dependent operations 112 112 * until 'ack' is set 113 113 */ 114 - if (!desc->async_tx.ack) 114 + if (!async_tx_test_ack(&desc->async_tx)) 115 115 return 0; 116 116 117 117 /* leave the last descriptor in the chain ··· 148 148 "this_desc: %#x next_desc: %#x ack: %d\n", 149 149 iter->async_tx.cookie, iter->idx, busy, 150 150 iter->async_tx.phys, iop_desc_get_next_desc(iter), 151 - iter->async_tx.ack); 151 + async_tx_test_ack(&iter->async_tx)); 152 152 prefetch(_iter); 153 153 prefetch(&_iter->async_tx); 154 154 ··· 338 338 339 339 /* pre-ack all but the last descriptor */ 340 340 if (num_slots != slots_per_op) 341 - iter->async_tx.ack = 1; 342 - else 343 - iter->async_tx.ack = 0; 341 + async_tx_ack(&iter->async_tx); 344 342 345 343 list_add_tail(&iter->chain_node, &chain); 346 344 alloc_tail = iter; ··· 511 513 } 512 514 513 515 static struct dma_async_tx_descriptor * 514 - iop_adma_prep_dma_interrupt(struct dma_chan *chan) 516 + iop_adma_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags) 515 517 { 516 518 struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); 517 519 struct iop_adma_desc_slot *sw_desc, *grp_start; ··· 526 528 grp_start = sw_desc->group_head; 527 529 iop_desc_init_interrupt(grp_start, iop_chan); 528 530 grp_start->unmap_len = 0; 531 + sw_desc->async_tx.flags = flags; 529 532 } 530 533 spin_unlock_bh(&iop_chan->lock); 531 534 ··· 559 560 iop_desc_set_memcpy_src_addr(grp_start, dma_src); 560 561 sw_desc->unmap_src_cnt = 1; 561 562 sw_desc->unmap_len = len; 563 + sw_desc->async_tx.flags = flags; 562 564 } 563 565 spin_unlock_bh(&iop_chan->lock); 564 566 ··· 592 592 iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest); 593 593 sw_desc->unmap_src_cnt = 1; 594 594 sw_desc->unmap_len = len; 595 + sw_desc->async_tx.flags = flags; 595 596 } 596 597 spin_unlock_bh(&iop_chan->lock); 597 598 ··· 626 625 iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest); 627 626 sw_desc->unmap_src_cnt = src_cnt; 628 627 sw_desc->unmap_len = len; 628 + sw_desc->async_tx.flags = flags; 629 629 while (src_cnt--) 630 630 iop_desc_set_xor_src_addr(grp_start, src_cnt, 631 631 dma_src[src_cnt]); ··· 663 661 __func__, grp_start->xor_check_result); 664 662 sw_desc->unmap_src_cnt = src_cnt; 665 663 sw_desc->unmap_len = len; 664 + sw_desc->async_tx.flags = flags; 666 665 while (src_cnt--) 667 666 iop_desc_set_zero_sum_src_addr(grp_start, src_cnt, 668 667 dma_src[src_cnt]); ··· 850 847 src_dma = dma_map_single(dma_chan->device->dev, src, 851 848 IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE); 852 849 tx = iop_adma_prep_dma_memcpy(dma_chan, dest_dma, src_dma, 853 - IOP_ADMA_TEST_SIZE, 1); 850 + IOP_ADMA_TEST_SIZE, 851 + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 854 852 855 853 cookie = iop_adma_tx_submit(tx); 856 854 iop_adma_issue_pending(dma_chan); 857 - async_tx_ack(tx); 858 855 msleep(1); 859 856 860 857 if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != ··· 950 947 dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i], 951 948 0, PAGE_SIZE, DMA_TO_DEVICE); 952 949 tx = iop_adma_prep_dma_xor(dma_chan, dest_dma, dma_srcs, 953 - IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE, 1); 950 + IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE, 951 + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 954 952 955 953 cookie = iop_adma_tx_submit(tx); 956 954 iop_adma_issue_pending(dma_chan); 957 - async_tx_ack(tx); 958 955 msleep(8); 959 956 960 957 if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != ··· 997 994 DMA_TO_DEVICE); 998 995 tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs, 999 996 IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE, 1000 - &zero_sum_result, 1); 997 + &zero_sum_result, 998 + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 1001 999 1002 1000 cookie = iop_adma_tx_submit(tx); 1003 1001 iop_adma_issue_pending(dma_chan); 1004 - async_tx_ack(tx); 1005 1002 msleep(8); 1006 1003 1007 1004 if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { ··· 1021 1018 /* test memset */ 1022 1019 dma_addr = dma_map_page(dma_chan->device->dev, dest, 0, 1023 1020 PAGE_SIZE, DMA_FROM_DEVICE); 1024 - tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, 1); 1021 + tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, 1022 + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 1025 1023 1026 1024 cookie = iop_adma_tx_submit(tx); 1027 1025 iop_adma_issue_pending(dma_chan); 1028 - async_tx_ack(tx); 1029 1026 msleep(8); 1030 1027 1031 1028 if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { ··· 1053 1050 DMA_TO_DEVICE); 1054 1051 tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs, 1055 1052 IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE, 1056 - &zero_sum_result, 1); 1053 + &zero_sum_result, 1054 + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 1057 1055 1058 1056 cookie = iop_adma_tx_submit(tx); 1059 1057 iop_adma_issue_pending(dma_chan); 1060 - async_tx_ack(tx); 1061 1058 msleep(8); 1062 1059 1063 1060 if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { ··· 1290 1287 grp_start = sw_desc->group_head; 1291 1288 1292 1289 list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain); 1293 - sw_desc->async_tx.ack = 1; 1290 + async_tx_ack(&sw_desc->async_tx); 1294 1291 iop_desc_init_memcpy(grp_start, 0); 1295 1292 iop_desc_set_byte_count(grp_start, iop_chan, 0); 1296 1293 iop_desc_set_dest_addr(grp_start, iop_chan, 0); ··· 1346 1343 if (sw_desc) { 1347 1344 grp_start = sw_desc->group_head; 1348 1345 list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain); 1349 - sw_desc->async_tx.ack = 1; 1346 + async_tx_ack(&sw_desc->async_tx); 1350 1347 iop_desc_init_null_xor(grp_start, 2, 0); 1351 1348 iop_desc_set_byte_count(grp_start, iop_chan, 0); 1352 1349 iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+18 -7
include/linux/dmaengine.h
··· 95 95 #define DMA_TX_TYPE_END (DMA_INTERRUPT + 1) 96 96 97 97 /** 98 - * enum dma_prep_flags - DMA flags to augment operation preparation 98 + * enum dma_ctrl_flags - DMA flags to augment operation preparation, 99 + * control completion, and communicate status. 99 100 * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of 100 101 * this transaction 102 + * @DMA_CTRL_ACK - the descriptor cannot be reused until the client 103 + * acknowledges receipt, i.e. has has a chance to establish any 104 + * dependency chains 101 105 */ 102 - enum dma_prep_flags { 106 + enum dma_ctrl_flags { 103 107 DMA_PREP_INTERRUPT = (1 << 0), 108 + DMA_CTRL_ACK = (1 << 1), 104 109 }; 105 110 106 111 /** ··· 216 211 * ---dma generic offload fields--- 217 212 * @cookie: tracking cookie for this transaction, set to -EBUSY if 218 213 * this tx is sitting on a dependency list 219 - * @ack: the descriptor can not be reused until the client acknowledges 220 - * receipt, i.e. has has a chance to establish any dependency chains 214 + * @flags: flags to augment operation preparation, control completion, and 215 + * communicate status 221 216 * @phys: physical address of the descriptor 222 217 * @tx_list: driver common field for operations that require multiple 223 218 * descriptors ··· 232 227 */ 233 228 struct dma_async_tx_descriptor { 234 229 dma_cookie_t cookie; 235 - int ack; 230 + enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */ 236 231 dma_addr_t phys; 237 232 struct list_head tx_list; 238 233 struct dma_chan *chan; ··· 295 290 struct dma_chan *chan, dma_addr_t dest, int value, size_t len, 296 291 unsigned long flags); 297 292 struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)( 298 - struct dma_chan *chan); 293 + struct dma_chan *chan, unsigned long flags); 299 294 300 295 enum dma_status (*device_is_tx_complete)(struct dma_chan *chan, 301 296 dma_cookie_t cookie, dma_cookie_t *last, ··· 321 316 static inline void 322 317 async_tx_ack(struct dma_async_tx_descriptor *tx) 323 318 { 324 - tx->ack = 1; 319 + tx->flags |= DMA_CTRL_ACK; 320 + } 321 + 322 + static inline int 323 + async_tx_test_ack(struct dma_async_tx_descriptor *tx) 324 + { 325 + return tx->flags & DMA_CTRL_ACK; 325 326 } 326 327 327 328 #define first_dma_cap(mask) __first_dma_cap(&(mask))