diff --git a/Documentation/driver-api/dmaengine/client.rst b/Documentation/driver-api/dmaengine/client.rst index ba913c2dd12729347af20bc630f368d81b3abee1..09a3f66dcd263e4e366eb49cb489b6d7455ec648 100644 --- a/Documentation/driver-api/dmaengine/client.rst +++ b/Documentation/driver-api/dmaengine/client.rst @@ -344,8 +344,9 @@ Further APIs the documentation in include/linux/dmaengine.h for a more complete description of this API. - This can be used with the cookie returned from dmaengine_submit() - to check for completion of a specific DMA transaction. + This can be used in conjunction with dma_async_is_complete() and + the cookie returned from dmaengine_submit() to check for + completion of a specific DMA transaction. .. note:: diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index fd52556c3edb416efee06ce659eb9685bebd9111..a24882ba37643db58ba982a53e1da00d6873ffbb 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -1544,6 +1544,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_interrupt( } /* + * Code accessing dma_async_is_complete() in a tight loop may give problems. * If slaves are relying on interrupts to signal completion this function * must not be called with interrupts disabled. */ diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 90f9fc4c36dc2917591585621c5911c0070e7a74..7eaee5b705b1bf47bb7c78301550cd5751720ee2 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1464,7 +1464,8 @@ static int atc_terminate_all(struct dma_chan *chan) * @txstate: if not %NULL updated with transaction state * * If @txstate is passed in, upon return it reflect the driver - * internal state. + * internal state and can be used with dma_async_is_complete() to check + * the status of multiple cookies without re-checking hardware state. */ static enum dma_status atc_tx_status(struct dma_chan *chan, diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h index e72876a512a39684479b6efd6dd2bcd2df26c0ea..86e505fafcb0880efa0a30703e2ad52df7125d96 100644 --- a/drivers/dma/dmaengine.h +++ b/drivers/dma/dmaengine.h @@ -79,15 +79,7 @@ static inline enum dma_status dma_cookie_status(struct dma_chan *chan, state->residue = 0; state->in_flight_bytes = 0; } - - if (complete <= used) { - if ((cookie <= complete) || (cookie > used)) - return DMA_COMPLETE; - } else { - if ((cookie <= complete) && (cookie > used)) - return DMA_COMPLETE; - } - return DMA_IN_PROGRESS; + return dma_async_is_complete(cookie, complete, used); } static inline void dma_set_tx_state(struct dma_tx_state *st, diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 8d63e30c79f87f2ffc0e8401bd8b020fdfafadf4..beb2559be91c95b78cf6d5625176c45260098859 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1434,9 +1434,9 @@ static inline void dma_async_issue_pending(struct dma_chan *chan) * @last: returns last completed cookie, can be NULL * @used: returns last issued cookie, can be NULL * - * If @last and @used are passed in, upon return they reflect the most - * recently submitted (used) cookie and the most recently completed - * cookie. + * If @last and @used are passed in, upon return they reflect the driver + * internal state and can be used with dma_async_is_complete() to check + * the status of multiple cookies without re-checking hardware state. */ static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) @@ -1452,6 +1452,28 @@ static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, return status; } +/** + * dma_async_is_complete - test a cookie against chan state + * @cookie: transaction identifier to test status of + * @last_complete: last know completed transaction + * @last_used: last cookie value handed out + * + * dma_async_is_complete() is used in dma_async_is_tx_complete() + * the test logic is separated for lightweight testing of multiple cookies + */ +static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, + dma_cookie_t last_complete, dma_cookie_t last_used) +{ + if (last_complete <= last_used) { + if ((cookie <= last_complete) || (cookie > last_used)) + return DMA_COMPLETE; + } else { + if ((cookie <= last_complete) && (cookie > last_used)) + return DMA_COMPLETE; + } + return DMA_IN_PROGRESS; +} + #ifdef CONFIG_DMA_ENGINE struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type); enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);