linux/drivers/dma/dmaengine.h
Dave Jiang f083f55718 dmaengine: Add helper function to prep for error reporting
Dmaengine does not provide a way to pass back the result from a DMA
transaction through the callback function. We are adding dmaengine
helper function in order to prep for a mechanism that allow result
status and other information through the callback. The initial conversion
will make the existing driver use these new helper functions but retain
the original behavior of the code. However, the helper functions paves
a way towards adding the result parameter through callback.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
2016-08-08 08:11:37 +05:30

162 lines
4.2 KiB
C

/*
* The contents of this file are private to DMA engine drivers, and is not
* part of the API to be used by DMA engine users.
*/
#ifndef DMAENGINE_H
#define DMAENGINE_H
#include <linux/bug.h>
#include <linux/dmaengine.h>
/**
* dma_cookie_init - initialize the cookies for a DMA channel
* @chan: dma channel to initialize
*/
static inline void dma_cookie_init(struct dma_chan *chan)
{
chan->cookie = DMA_MIN_COOKIE;
chan->completed_cookie = DMA_MIN_COOKIE;
}
/**
* dma_cookie_assign - assign a DMA engine cookie to the descriptor
* @tx: descriptor needing cookie
*
* Assign a unique non-zero per-channel cookie to the descriptor.
* Note: caller is expected to hold a lock to prevent concurrency.
*/
static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx)
{
struct dma_chan *chan = tx->chan;
dma_cookie_t cookie;
cookie = chan->cookie + 1;
if (cookie < DMA_MIN_COOKIE)
cookie = DMA_MIN_COOKIE;
tx->cookie = chan->cookie = cookie;
return cookie;
}
/**
* dma_cookie_complete - complete a descriptor
* @tx: descriptor to complete
*
* Mark this descriptor complete by updating the channels completed
* cookie marker. Zero the descriptors cookie to prevent accidental
* repeated completions.
*
* Note: caller is expected to hold a lock to prevent concurrency.
*/
static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx)
{
BUG_ON(tx->cookie < DMA_MIN_COOKIE);
tx->chan->completed_cookie = tx->cookie;
tx->cookie = 0;
}
/**
* dma_cookie_status - report cookie status
* @chan: dma channel
* @cookie: cookie we are interested in
* @state: dma_tx_state structure to return last/used cookies
*
* Report the status of the cookie, filling in the state structure if
* non-NULL. No locking is required.
*/
static inline enum dma_status dma_cookie_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *state)
{
dma_cookie_t used, complete;
used = chan->cookie;
complete = chan->completed_cookie;
barrier();
if (state) {
state->last = complete;
state->used = used;
state->residue = 0;
}
return dma_async_is_complete(cookie, complete, used);
}
static inline void dma_set_residue(struct dma_tx_state *state, u32 residue)
{
if (state)
state->residue = residue;
}
struct dmaengine_desc_callback {
dma_async_tx_callback callback;
void *callback_param;
};
/**
* dmaengine_desc_get_callback - get the passed in callback function
* @tx: tx descriptor
* @cb: temp struct to hold the callback info
*
* Fill the passed in cb struct with what's available in the passed in
* tx descriptor struct
* No locking is required.
*/
static inline void
dmaengine_desc_get_callback(struct dma_async_tx_descriptor *tx,
struct dmaengine_desc_callback *cb)
{
cb->callback = tx->callback;
cb->callback_param = tx->callback_param;
}
/**
* dmaengine_desc_callback_invoke - call the callback function in cb struct
* @cb: temp struct that is holding the callback info
* @result: dummy pointer for now
*
* Call the callback function provided in the cb struct with the parameter
* in the cb struct.
* Locking is dependent on the driver.
*/
static inline void
dmaengine_desc_callback_invoke(struct dmaengine_desc_callback *cb,
const void *result)
{
if (cb->callback)
cb->callback(cb->callback_param);
}
/**
* dmaengine_desc_get_callback_invoke - get the callback in tx descriptor and
* then immediately call the callback.
* @tx: dma async tx descriptor
* @result: dummy pointer for now
*
* Call dmaengine_desc_get_callback() and dmaengine_desc_callback_invoke()
* in a single function since no work is necessary in between for the driver.
* Locking is dependent on the driver.
*/
static inline void
dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx,
const void *result)
{
struct dmaengine_desc_callback cb;
dmaengine_desc_get_callback(tx, &cb);
dmaengine_desc_callback_invoke(&cb, result);
}
/**
* dmaengine_desc_callback_valid - verify the callback is valid in cb
* @cb: callback info struct
*
* Return a bool that verifies whether callback in cb is valid or not.
* No locking is required.
*/
static inline bool
dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb)
{
return (cb->callback) ? true : false;
}
#endif