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