forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
5.2 KiB
201 lines
5.2 KiB
/* SPDX-License-Identifier: GPL-2.0 */ |
|
/* |
|
* 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; |
|
state->in_flight_bytes = 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; |
|
} |
|
|
|
static inline void dma_set_in_flight_bytes(struct dma_tx_state *state, |
|
u32 in_flight_bytes) |
|
{ |
|
if (state) |
|
state->in_flight_bytes = in_flight_bytes; |
|
} |
|
|
|
struct dmaengine_desc_callback { |
|
dma_async_tx_callback callback; |
|
dma_async_tx_callback_result callback_result; |
|
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_result = tx->callback_result; |
|
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: transaction result |
|
* |
|
* 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 struct dmaengine_result *result) |
|
{ |
|
struct dmaengine_result dummy_result = { |
|
.result = DMA_TRANS_NOERROR, |
|
.residue = 0 |
|
}; |
|
|
|
if (cb->callback_result) { |
|
if (!result) |
|
result = &dummy_result; |
|
cb->callback_result(cb->callback_param, result); |
|
} else 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: transaction result |
|
* |
|
* 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 struct dmaengine_result *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; |
|
} |
|
|
|
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); |
|
struct dma_chan *dma_get_any_slave_channel(struct dma_device *device); |
|
|
|
#ifdef CONFIG_DEBUG_FS |
|
#include <linux/debugfs.h> |
|
|
|
static inline struct dentry * |
|
dmaengine_get_debugfs_root(struct dma_device *dma_dev) { |
|
return dma_dev->dbg_dev_root; |
|
} |
|
#else |
|
struct dentry; |
|
static inline struct dentry * |
|
dmaengine_get_debugfs_root(struct dma_device *dma_dev) |
|
{ |
|
return NULL; |
|
} |
|
#endif /* CONFIG_DEBUG_FS */ |
|
|
|
#endif
|
|
|