xref: /openbmc/linux/include/linux/async_tx.h (revision 4f86ff55)
1a61127c2SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
29bc89cd8SDan Williams /*
39bc89cd8SDan Williams  * Copyright © 2006, Intel Corporation.
49bc89cd8SDan Williams  */
59bc89cd8SDan Williams #ifndef _ASYNC_TX_H_
69bc89cd8SDan Williams #define _ASYNC_TX_H_
79bc89cd8SDan Williams #include <linux/dmaengine.h>
89bc89cd8SDan Williams #include <linux/spinlock.h>
99bc89cd8SDan Williams #include <linux/interrupt.h>
109bc89cd8SDan Williams 
1106164f31SDan Williams /* on architectures without dma-mapping capabilities we need to ensure
1206164f31SDan Williams  * that the asynchronous path compiles away
1306164f31SDan Williams  */
1406164f31SDan Williams #ifdef CONFIG_HAS_DMA
1506164f31SDan Williams #define __async_inline
1606164f31SDan Williams #else
1706164f31SDan Williams #define __async_inline __always_inline
1806164f31SDan Williams #endif
1906164f31SDan Williams 
209bc89cd8SDan Williams /**
219bc89cd8SDan Williams  * dma_chan_ref - object used to manage dma channels received from the
229bc89cd8SDan Williams  *   dmaengine core.
239bc89cd8SDan Williams  * @chan - the channel being tracked
249bc89cd8SDan Williams  * @node - node for the channel to be placed on async_tx_master_list
259bc89cd8SDan Williams  * @rcu - for list_del_rcu
269bc89cd8SDan Williams  * @count - number of times this channel is listed in the pool
279bc89cd8SDan Williams  *	(for channels with multiple capabiities)
289bc89cd8SDan Williams  */
299bc89cd8SDan Williams struct dma_chan_ref {
309bc89cd8SDan Williams 	struct dma_chan *chan;
319bc89cd8SDan Williams 	struct list_head node;
329bc89cd8SDan Williams 	struct rcu_head rcu;
339bc89cd8SDan Williams 	atomic_t count;
349bc89cd8SDan Williams };
359bc89cd8SDan Williams 
369bc89cd8SDan Williams /**
379bc89cd8SDan Williams  * async_tx_flags - modifiers for the async_* calls
389bc89cd8SDan Williams  * @ASYNC_TX_XOR_ZERO_DST: this flag must be used for xor operations where the
39121ae8daSRandy Dunlap  * destination address is not a source.  The asynchronous case handles this
409bc89cd8SDan Williams  * implicitly, the synchronous case needs to zero the destination block.
419bc89cd8SDan Williams  * @ASYNC_TX_XOR_DROP_DST: this flag must be used if the destination address is
429bc89cd8SDan Williams  * also one of the source addresses.  In the synchronous case the destination
439bc89cd8SDan Williams  * address is an implied source, whereas the asynchronous case it must be listed
449bc89cd8SDan Williams  * as a source.  The destination address must be the first address in the source
459bc89cd8SDan Williams  * array.
469bc89cd8SDan Williams  * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
479bc89cd8SDan Williams  * dependency chain
480403e382SDan Williams  * @ASYNC_TX_FENCE: specify that the next operation in the dependency
490403e382SDan Williams  * chain uses this operation's result as an input
50584acdd4SMarkus Stockhausen  * @ASYNC_TX_PQ_XOR_DST: do not overwrite the syndrome but XOR it with the
51584acdd4SMarkus Stockhausen  * input data. Required for rmw case.
529bc89cd8SDan Williams  */
539bc89cd8SDan Williams enum async_tx_flags {
549bc89cd8SDan Williams 	ASYNC_TX_XOR_ZERO_DST	 = (1 << 0),
559bc89cd8SDan Williams 	ASYNC_TX_XOR_DROP_DST	 = (1 << 1),
5688ba2aa5SDan Williams 	ASYNC_TX_ACK		 = (1 << 2),
570403e382SDan Williams 	ASYNC_TX_FENCE		 = (1 << 3),
58584acdd4SMarkus Stockhausen 	ASYNC_TX_PQ_XOR_DST	 = (1 << 4),
599bc89cd8SDan Williams };
609bc89cd8SDan Williams 
61a08abd8cSDan Williams /**
62a08abd8cSDan Williams  * struct async_submit_ctl - async_tx submission/completion modifiers
63a08abd8cSDan Williams  * @flags: submission modifiers
64a08abd8cSDan Williams  * @depend_tx: parent dependency of the current operation being submitted
65a08abd8cSDan Williams  * @cb_fn: callback routine to run at operation completion
66a08abd8cSDan Williams  * @cb_param: parameter for the callback routine
67a08abd8cSDan Williams  * @scribble: caller provided space for dma/page address conversions
68a08abd8cSDan Williams  */
69a08abd8cSDan Williams struct async_submit_ctl {
70a08abd8cSDan Williams 	enum async_tx_flags flags;
71a08abd8cSDan Williams 	struct dma_async_tx_descriptor *depend_tx;
72a08abd8cSDan Williams 	dma_async_tx_callback cb_fn;
73a08abd8cSDan Williams 	void *cb_param;
74a08abd8cSDan Williams 	void *scribble;
75a08abd8cSDan Williams };
76a08abd8cSDan Williams 
77b802c841SDan Williams #if defined(CONFIG_DMA_ENGINE) && !defined(CONFIG_ASYNC_TX_CHANNEL_SWITCH)
782ba05622SDan Williams #define async_tx_issue_pending_all dma_issue_pending_all
7995475e57SDan Williams 
8095475e57SDan Williams /**
8195475e57SDan Williams  * async_tx_issue_pending - send pending descriptor to the hardware channel
8295475e57SDan Williams  * @tx: descriptor handle to retrieve hardware context
8395475e57SDan Williams  *
8495475e57SDan Williams  * Note: any dependent operations will have already been issued by
8595475e57SDan Williams  * async_tx_channel_switch, or (in the case of no channel switch) will
8695475e57SDan Williams  * be already pending on this channel.
8795475e57SDan Williams  */
async_tx_issue_pending(struct dma_async_tx_descriptor * tx)8895475e57SDan Williams static inline void async_tx_issue_pending(struct dma_async_tx_descriptor *tx)
8995475e57SDan Williams {
9095475e57SDan Williams 	if (likely(tx)) {
9195475e57SDan Williams 		struct dma_chan *chan = tx->chan;
9295475e57SDan Williams 		struct dma_device *dma = chan->device;
9395475e57SDan Williams 
9495475e57SDan Williams 		dma->device_issue_pending(chan);
9595475e57SDan Williams 	}
9695475e57SDan Williams }
9747437b2cSDan Williams #ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL
9847437b2cSDan Williams #include <asm/async_tx.h>
9947437b2cSDan Williams #else
10047437b2cSDan Williams #define async_tx_find_channel(dep, type, dst, dst_count, src, src_count, len) \
10147437b2cSDan Williams 	 __async_tx_find_channel(dep, type)
1029bc89cd8SDan Williams struct dma_chan *
103a08abd8cSDan Williams __async_tx_find_channel(struct async_submit_ctl *submit,
1049bc89cd8SDan Williams 			enum dma_transaction_type tx_type);
10547437b2cSDan Williams #endif /* CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL */
1069bc89cd8SDan Williams #else
async_tx_issue_pending_all(void)1079bc89cd8SDan Williams static inline void async_tx_issue_pending_all(void)
1089bc89cd8SDan Williams {
1099bc89cd8SDan Williams 	do { } while (0);
1109bc89cd8SDan Williams }
1119bc89cd8SDan Williams 
async_tx_issue_pending(struct dma_async_tx_descriptor * tx)11295475e57SDan Williams static inline void async_tx_issue_pending(struct dma_async_tx_descriptor *tx)
11395475e57SDan Williams {
11495475e57SDan Williams 	do { } while (0);
11595475e57SDan Williams }
11695475e57SDan Williams 
1179bc89cd8SDan Williams static inline struct dma_chan *
async_tx_find_channel(struct async_submit_ctl * submit,enum dma_transaction_type tx_type,struct page ** dst,int dst_count,struct page ** src,int src_count,size_t len)118a08abd8cSDan Williams async_tx_find_channel(struct async_submit_ctl *submit,
119a08abd8cSDan Williams 		      enum dma_transaction_type tx_type, struct page **dst,
120a08abd8cSDan Williams 		      int dst_count, struct page **src, int src_count,
121a08abd8cSDan Williams 		      size_t len)
1229bc89cd8SDan Williams {
1239bc89cd8SDan Williams 	return NULL;
1249bc89cd8SDan Williams }
1259bc89cd8SDan Williams #endif
1269bc89cd8SDan Williams 
1279bc89cd8SDan Williams /**
1289bc89cd8SDan Williams  * async_tx_sync_epilog - actions to take if an operation is run synchronously
1299bc89cd8SDan Williams  * @cb_fn: function to call when the transaction completes
1309bc89cd8SDan Williams  * @cb_fn_param: parameter to pass to the callback routine
1319bc89cd8SDan Williams  */
1329bc89cd8SDan Williams static inline void
async_tx_sync_epilog(struct async_submit_ctl * submit)133a08abd8cSDan Williams async_tx_sync_epilog(struct async_submit_ctl *submit)
1349bc89cd8SDan Williams {
135a08abd8cSDan Williams 	if (submit->cb_fn)
136a08abd8cSDan Williams 		submit->cb_fn(submit->cb_param);
1379bc89cd8SDan Williams }
1389bc89cd8SDan Williams 
139a08abd8cSDan Williams typedef union {
140a08abd8cSDan Williams 	unsigned long addr;
141a08abd8cSDan Williams 	struct page *page;
142a08abd8cSDan Williams 	dma_addr_t dma;
143a08abd8cSDan Williams } addr_conv_t;
144a08abd8cSDan Williams 
145a08abd8cSDan Williams static inline void
init_async_submit(struct async_submit_ctl * args,enum async_tx_flags flags,struct dma_async_tx_descriptor * tx,dma_async_tx_callback cb_fn,void * cb_param,addr_conv_t * scribble)146a08abd8cSDan Williams init_async_submit(struct async_submit_ctl *args, enum async_tx_flags flags,
147a08abd8cSDan Williams 		  struct dma_async_tx_descriptor *tx,
148a08abd8cSDan Williams 		  dma_async_tx_callback cb_fn, void *cb_param,
149a08abd8cSDan Williams 		  addr_conv_t *scribble)
150a08abd8cSDan Williams {
151a08abd8cSDan Williams 	args->flags = flags;
152a08abd8cSDan Williams 	args->depend_tx = tx;
153a08abd8cSDan Williams 	args->cb_fn = cb_fn;
154a08abd8cSDan Williams 	args->cb_param = cb_param;
155a08abd8cSDan Williams 	args->scribble = scribble;
156a08abd8cSDan Williams }
157a08abd8cSDan Williams 
158a08abd8cSDan Williams void async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
159a08abd8cSDan Williams 		     struct async_submit_ctl *submit);
1609bc89cd8SDan Williams 
1619bc89cd8SDan Williams struct dma_async_tx_descriptor *
1629bc89cd8SDan Williams async_xor(struct page *dest, struct page **src_list, unsigned int offset,
163a08abd8cSDan Williams 	  int src_cnt, size_t len, struct async_submit_ctl *submit);
1649bc89cd8SDan Williams 
1659bc89cd8SDan Williams struct dma_async_tx_descriptor *
16629bcff78SYufen Yu async_xor_offs(struct page *dest, unsigned int offset,
16729bcff78SYufen Yu 		struct page **src_list, unsigned int *src_offset,
16829bcff78SYufen Yu 		int src_cnt, size_t len, struct async_submit_ctl *submit);
16929bcff78SYufen Yu 
17029bcff78SYufen Yu struct dma_async_tx_descriptor *
171a08abd8cSDan Williams async_xor_val(struct page *dest, struct page **src_list, unsigned int offset,
172ad283ea4SDan Williams 	      int src_cnt, size_t len, enum sum_check_flags *result,
173a08abd8cSDan Williams 	      struct async_submit_ctl *submit);
1749bc89cd8SDan Williams 
1759bc89cd8SDan Williams struct dma_async_tx_descriptor *
17629bcff78SYufen Yu async_xor_val_offs(struct page *dest, unsigned int offset,
17729bcff78SYufen Yu 		struct page **src_list, unsigned int *src_offset,
17829bcff78SYufen Yu 		int src_cnt, size_t len, enum sum_check_flags *result,
17929bcff78SYufen Yu 		struct async_submit_ctl *submit);
18029bcff78SYufen Yu 
18129bcff78SYufen Yu struct dma_async_tx_descriptor *
1829bc89cd8SDan Williams async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
183a08abd8cSDan Williams 	     unsigned int src_offset, size_t len,
184a08abd8cSDan Williams 	     struct async_submit_ctl *submit);
1859bc89cd8SDan Williams 
186a08abd8cSDan Williams struct dma_async_tx_descriptor *async_trigger_callback(struct async_submit_ctl *submit);
187d2c52b79SDan Williams 
188b2f46fd8SDan Williams struct dma_async_tx_descriptor *
189d69454bcSYufen Yu async_gen_syndrome(struct page **blocks, unsigned int *offsets, int src_cnt,
190b2f46fd8SDan Williams 		   size_t len, struct async_submit_ctl *submit);
191b2f46fd8SDan Williams 
192b2f46fd8SDan Williams struct dma_async_tx_descriptor *
193d69454bcSYufen Yu async_syndrome_val(struct page **blocks, unsigned int *offsets, int src_cnt,
194b2f46fd8SDan Williams 		   size_t len, enum sum_check_flags *pqres, struct page *spare,
195d69454bcSYufen Yu 		   unsigned int s_off, struct async_submit_ctl *submit);
196b2f46fd8SDan Williams 
1970a82a623SDan Williams struct dma_async_tx_descriptor *
1980a82a623SDan Williams async_raid6_2data_recov(int src_num, size_t bytes, int faila, int failb,
1994f86ff55SYufen Yu 			struct page **ptrs, unsigned int *offs,
2004f86ff55SYufen Yu 			struct async_submit_ctl *submit);
2010a82a623SDan Williams 
2020a82a623SDan Williams struct dma_async_tx_descriptor *
2030a82a623SDan Williams async_raid6_datap_recov(int src_num, size_t bytes, int faila,
2044f86ff55SYufen Yu 			struct page **ptrs, unsigned int *offs,
2054f86ff55SYufen Yu 			struct async_submit_ctl *submit);
2060a82a623SDan Williams 
207d2c52b79SDan Williams void async_tx_quiesce(struct dma_async_tx_descriptor **tx);
2089bc89cd8SDan Williams #endif /* _ASYNC_TX_H_ */
209