162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * The contents of this file are private to DMA engine drivers, and is not 462306a36Sopenharmony_ci * part of the API to be used by DMA engine users. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef DMAENGINE_H 762306a36Sopenharmony_ci#define DMAENGINE_H 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/bug.h> 1062306a36Sopenharmony_ci#include <linux/dmaengine.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/** 1362306a36Sopenharmony_ci * dma_cookie_init - initialize the cookies for a DMA channel 1462306a36Sopenharmony_ci * @chan: dma channel to initialize 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_cistatic inline void dma_cookie_init(struct dma_chan *chan) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci chan->cookie = DMA_MIN_COOKIE; 1962306a36Sopenharmony_ci chan->completed_cookie = DMA_MIN_COOKIE; 2062306a36Sopenharmony_ci} 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/** 2362306a36Sopenharmony_ci * dma_cookie_assign - assign a DMA engine cookie to the descriptor 2462306a36Sopenharmony_ci * @tx: descriptor needing cookie 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * Assign a unique non-zero per-channel cookie to the descriptor. 2762306a36Sopenharmony_ci * Note: caller is expected to hold a lock to prevent concurrency. 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_cistatic inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci struct dma_chan *chan = tx->chan; 3262306a36Sopenharmony_ci dma_cookie_t cookie; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci cookie = chan->cookie + 1; 3562306a36Sopenharmony_ci if (cookie < DMA_MIN_COOKIE) 3662306a36Sopenharmony_ci cookie = DMA_MIN_COOKIE; 3762306a36Sopenharmony_ci tx->cookie = chan->cookie = cookie; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci return cookie; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/** 4362306a36Sopenharmony_ci * dma_cookie_complete - complete a descriptor 4462306a36Sopenharmony_ci * @tx: descriptor to complete 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * Mark this descriptor complete by updating the channels completed 4762306a36Sopenharmony_ci * cookie marker. Zero the descriptors cookie to prevent accidental 4862306a36Sopenharmony_ci * repeated completions. 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * Note: caller is expected to hold a lock to prevent concurrency. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_cistatic inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci BUG_ON(tx->cookie < DMA_MIN_COOKIE); 5562306a36Sopenharmony_ci tx->chan->completed_cookie = tx->cookie; 5662306a36Sopenharmony_ci tx->cookie = 0; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/** 6062306a36Sopenharmony_ci * dma_cookie_status - report cookie status 6162306a36Sopenharmony_ci * @chan: dma channel 6262306a36Sopenharmony_ci * @cookie: cookie we are interested in 6362306a36Sopenharmony_ci * @state: dma_tx_state structure to return last/used cookies 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * Report the status of the cookie, filling in the state structure if 6662306a36Sopenharmony_ci * non-NULL. No locking is required. 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_cistatic inline enum dma_status dma_cookie_status(struct dma_chan *chan, 6962306a36Sopenharmony_ci dma_cookie_t cookie, struct dma_tx_state *state) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci dma_cookie_t used, complete; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci used = chan->cookie; 7462306a36Sopenharmony_ci complete = chan->completed_cookie; 7562306a36Sopenharmony_ci barrier(); 7662306a36Sopenharmony_ci if (state) { 7762306a36Sopenharmony_ci state->last = complete; 7862306a36Sopenharmony_ci state->used = used; 7962306a36Sopenharmony_ci state->residue = 0; 8062306a36Sopenharmony_ci state->in_flight_bytes = 0; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci return dma_async_is_complete(cookie, complete, used); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic inline void dma_set_residue(struct dma_tx_state *state, u32 residue) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci if (state) 8862306a36Sopenharmony_ci state->residue = residue; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic inline void dma_set_in_flight_bytes(struct dma_tx_state *state, 9262306a36Sopenharmony_ci u32 in_flight_bytes) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci if (state) 9562306a36Sopenharmony_ci state->in_flight_bytes = in_flight_bytes; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistruct dmaengine_desc_callback { 9962306a36Sopenharmony_ci dma_async_tx_callback callback; 10062306a36Sopenharmony_ci dma_async_tx_callback_result callback_result; 10162306a36Sopenharmony_ci void *callback_param; 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/** 10562306a36Sopenharmony_ci * dmaengine_desc_get_callback - get the passed in callback function 10662306a36Sopenharmony_ci * @tx: tx descriptor 10762306a36Sopenharmony_ci * @cb: temp struct to hold the callback info 10862306a36Sopenharmony_ci * 10962306a36Sopenharmony_ci * Fill the passed in cb struct with what's available in the passed in 11062306a36Sopenharmony_ci * tx descriptor struct 11162306a36Sopenharmony_ci * No locking is required. 11262306a36Sopenharmony_ci */ 11362306a36Sopenharmony_cistatic inline void 11462306a36Sopenharmony_cidmaengine_desc_get_callback(struct dma_async_tx_descriptor *tx, 11562306a36Sopenharmony_ci struct dmaengine_desc_callback *cb) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci cb->callback = tx->callback; 11862306a36Sopenharmony_ci cb->callback_result = tx->callback_result; 11962306a36Sopenharmony_ci cb->callback_param = tx->callback_param; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/** 12362306a36Sopenharmony_ci * dmaengine_desc_callback_invoke - call the callback function in cb struct 12462306a36Sopenharmony_ci * @cb: temp struct that is holding the callback info 12562306a36Sopenharmony_ci * @result: transaction result 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * Call the callback function provided in the cb struct with the parameter 12862306a36Sopenharmony_ci * in the cb struct. 12962306a36Sopenharmony_ci * Locking is dependent on the driver. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_cistatic inline void 13262306a36Sopenharmony_cidmaengine_desc_callback_invoke(struct dmaengine_desc_callback *cb, 13362306a36Sopenharmony_ci const struct dmaengine_result *result) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct dmaengine_result dummy_result = { 13662306a36Sopenharmony_ci .result = DMA_TRANS_NOERROR, 13762306a36Sopenharmony_ci .residue = 0 13862306a36Sopenharmony_ci }; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (cb->callback_result) { 14162306a36Sopenharmony_ci if (!result) 14262306a36Sopenharmony_ci result = &dummy_result; 14362306a36Sopenharmony_ci cb->callback_result(cb->callback_param, result); 14462306a36Sopenharmony_ci } else if (cb->callback) { 14562306a36Sopenharmony_ci cb->callback(cb->callback_param); 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/** 15062306a36Sopenharmony_ci * dmaengine_desc_get_callback_invoke - get the callback in tx descriptor and 15162306a36Sopenharmony_ci * then immediately call the callback. 15262306a36Sopenharmony_ci * @tx: dma async tx descriptor 15362306a36Sopenharmony_ci * @result: transaction result 15462306a36Sopenharmony_ci * 15562306a36Sopenharmony_ci * Call dmaengine_desc_get_callback() and dmaengine_desc_callback_invoke() 15662306a36Sopenharmony_ci * in a single function since no work is necessary in between for the driver. 15762306a36Sopenharmony_ci * Locking is dependent on the driver. 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_cistatic inline void 16062306a36Sopenharmony_cidmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx, 16162306a36Sopenharmony_ci const struct dmaengine_result *result) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci struct dmaengine_desc_callback cb; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci dmaengine_desc_get_callback(tx, &cb); 16662306a36Sopenharmony_ci dmaengine_desc_callback_invoke(&cb, result); 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/** 17062306a36Sopenharmony_ci * dmaengine_desc_callback_valid - verify the callback is valid in cb 17162306a36Sopenharmony_ci * @cb: callback info struct 17262306a36Sopenharmony_ci * 17362306a36Sopenharmony_ci * Return a bool that verifies whether callback in cb is valid or not. 17462306a36Sopenharmony_ci * No locking is required. 17562306a36Sopenharmony_ci */ 17662306a36Sopenharmony_cistatic inline bool 17762306a36Sopenharmony_cidmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci return cb->callback || cb->callback_result; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistruct dma_chan *dma_get_slave_channel(struct dma_chan *chan); 18362306a36Sopenharmony_cistruct dma_chan *dma_get_any_slave_channel(struct dma_device *device); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 18662306a36Sopenharmony_ci#include <linux/debugfs.h> 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic inline struct dentry * 18962306a36Sopenharmony_cidmaengine_get_debugfs_root(struct dma_device *dma_dev) { 19062306a36Sopenharmony_ci return dma_dev->dbg_dev_root; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci#else 19362306a36Sopenharmony_cistruct dentry; 19462306a36Sopenharmony_cistatic inline struct dentry * 19562306a36Sopenharmony_cidmaengine_get_debugfs_root(struct dma_device *dma_dev) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci return NULL; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */ 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#endif 202