202 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 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 || cb->callback_result;
 | |
| }
 | |
| 
 | |
| 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
 |