Merge branch 'md-raid6-accel' into ioat3.2
Conflicts: include/linux/dmaengine.h
This commit is contained in:
+94
-32
@@ -58,25 +58,57 @@ struct dma_chan_ref {
|
||||
* array.
|
||||
* @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
|
||||
* dependency chain
|
||||
* @ASYNC_TX_DEP_ACK: ack the dependency descriptor. Useful for chaining.
|
||||
*/
|
||||
enum async_tx_flags {
|
||||
ASYNC_TX_XOR_ZERO_DST = (1 << 0),
|
||||
ASYNC_TX_XOR_DROP_DST = (1 << 1),
|
||||
ASYNC_TX_ACK = (1 << 3),
|
||||
ASYNC_TX_DEP_ACK = (1 << 4),
|
||||
ASYNC_TX_ACK = (1 << 2),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct async_submit_ctl - async_tx submission/completion modifiers
|
||||
* @flags: submission modifiers
|
||||
* @depend_tx: parent dependency of the current operation being submitted
|
||||
* @cb_fn: callback routine to run at operation completion
|
||||
* @cb_param: parameter for the callback routine
|
||||
* @scribble: caller provided space for dma/page address conversions
|
||||
*/
|
||||
struct async_submit_ctl {
|
||||
enum async_tx_flags flags;
|
||||
struct dma_async_tx_descriptor *depend_tx;
|
||||
dma_async_tx_callback cb_fn;
|
||||
void *cb_param;
|
||||
void *scribble;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DMA_ENGINE
|
||||
#define async_tx_issue_pending_all dma_issue_pending_all
|
||||
|
||||
/**
|
||||
* async_tx_issue_pending - send pending descriptor to the hardware channel
|
||||
* @tx: descriptor handle to retrieve hardware context
|
||||
*
|
||||
* Note: any dependent operations will have already been issued by
|
||||
* async_tx_channel_switch, or (in the case of no channel switch) will
|
||||
* be already pending on this channel.
|
||||
*/
|
||||
static inline void async_tx_issue_pending(struct dma_async_tx_descriptor *tx)
|
||||
{
|
||||
if (likely(tx)) {
|
||||
struct dma_chan *chan = tx->chan;
|
||||
struct dma_device *dma = chan->device;
|
||||
|
||||
dma->device_issue_pending(chan);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL
|
||||
#include <asm/async_tx.h>
|
||||
#else
|
||||
#define async_tx_find_channel(dep, type, dst, dst_count, src, src_count, len) \
|
||||
__async_tx_find_channel(dep, type)
|
||||
struct dma_chan *
|
||||
__async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
|
||||
enum dma_transaction_type tx_type);
|
||||
__async_tx_find_channel(struct async_submit_ctl *submit,
|
||||
enum dma_transaction_type tx_type);
|
||||
#endif /* CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL */
|
||||
#else
|
||||
static inline void async_tx_issue_pending_all(void)
|
||||
@@ -84,10 +116,16 @@ static inline void async_tx_issue_pending_all(void)
|
||||
do { } while (0);
|
||||
}
|
||||
|
||||
static inline void async_tx_issue_pending(struct dma_async_tx_descriptor *tx)
|
||||
{
|
||||
do { } while (0);
|
||||
}
|
||||
|
||||
static inline struct dma_chan *
|
||||
async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
|
||||
enum dma_transaction_type tx_type, struct page **dst, int dst_count,
|
||||
struct page **src, int src_count, size_t len)
|
||||
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)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -99,46 +137,70 @@ async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
|
||||
* @cb_fn_param: parameter to pass to the callback routine
|
||||
*/
|
||||
static inline void
|
||||
async_tx_sync_epilog(dma_async_tx_callback cb_fn, void *cb_fn_param)
|
||||
async_tx_sync_epilog(struct async_submit_ctl *submit)
|
||||
{
|
||||
if (cb_fn)
|
||||
cb_fn(cb_fn_param);
|
||||
if (submit->cb_fn)
|
||||
submit->cb_fn(submit->cb_param);
|
||||
}
|
||||
|
||||
void
|
||||
async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
|
||||
enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
|
||||
dma_async_tx_callback cb_fn, void *cb_fn_param);
|
||||
typedef union {
|
||||
unsigned long addr;
|
||||
struct page *page;
|
||||
dma_addr_t dma;
|
||||
} addr_conv_t;
|
||||
|
||||
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)
|
||||
{
|
||||
args->flags = flags;
|
||||
args->depend_tx = tx;
|
||||
args->cb_fn = cb_fn;
|
||||
args->cb_param = cb_param;
|
||||
args->scribble = scribble;
|
||||
}
|
||||
|
||||
void async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
|
||||
struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *
|
||||
async_xor(struct page *dest, struct page **src_list, unsigned int offset,
|
||||
int src_cnt, size_t len, enum async_tx_flags flags,
|
||||
struct dma_async_tx_descriptor *depend_tx,
|
||||
dma_async_tx_callback cb_fn, void *cb_fn_param);
|
||||
int src_cnt, size_t len, struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *
|
||||
async_xor_zero_sum(struct page *dest, struct page **src_list,
|
||||
unsigned int offset, int src_cnt, size_t len,
|
||||
u32 *result, enum async_tx_flags flags,
|
||||
struct dma_async_tx_descriptor *depend_tx,
|
||||
dma_async_tx_callback cb_fn, void *cb_fn_param);
|
||||
async_xor_val(struct page *dest, struct page **src_list, unsigned int offset,
|
||||
int src_cnt, size_t len, enum sum_check_flags *result,
|
||||
struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *
|
||||
async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
|
||||
unsigned int src_offset, size_t len, enum async_tx_flags flags,
|
||||
struct dma_async_tx_descriptor *depend_tx,
|
||||
dma_async_tx_callback cb_fn, void *cb_fn_param);
|
||||
unsigned int src_offset, size_t len,
|
||||
struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *
|
||||
async_memset(struct page *dest, int val, unsigned int offset,
|
||||
size_t len, enum async_tx_flags flags,
|
||||
struct dma_async_tx_descriptor *depend_tx,
|
||||
dma_async_tx_callback cb_fn, void *cb_fn_param);
|
||||
size_t len, struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *async_trigger_callback(struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *
|
||||
async_trigger_callback(enum async_tx_flags flags,
|
||||
struct dma_async_tx_descriptor *depend_tx,
|
||||
dma_async_tx_callback cb_fn, void *cb_fn_param);
|
||||
async_gen_syndrome(struct page **blocks, unsigned int offset, int src_cnt,
|
||||
size_t len, struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *
|
||||
async_syndrome_val(struct page **blocks, unsigned int offset, int src_cnt,
|
||||
size_t len, enum sum_check_flags *pqres, struct page *spare,
|
||||
struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *
|
||||
async_raid6_2data_recov(int src_num, size_t bytes, int faila, int failb,
|
||||
struct page **ptrs, struct async_submit_ctl *submit);
|
||||
|
||||
struct dma_async_tx_descriptor *
|
||||
async_raid6_datap_recov(int src_num, size_t bytes, int faila,
|
||||
struct page **ptrs, struct async_submit_ctl *submit);
|
||||
|
||||
void async_tx_quiesce(struct dma_async_tx_descriptor **tx);
|
||||
#endif /* _ASYNC_TX_H_ */
|
||||
|
||||
+105
-11
@@ -52,11 +52,11 @@ enum dma_status {
|
||||
enum dma_transaction_type {
|
||||
DMA_MEMCPY,
|
||||
DMA_XOR,
|
||||
DMA_PQ_XOR,
|
||||
DMA_PQ,
|
||||
DMA_DUAL_XOR,
|
||||
DMA_PQ_UPDATE,
|
||||
DMA_ZERO_SUM,
|
||||
DMA_PQ_ZERO_SUM,
|
||||
DMA_XOR_VAL,
|
||||
DMA_PQ_VAL,
|
||||
DMA_MEMSET,
|
||||
DMA_MEMCPY_CRC32C,
|
||||
DMA_INTERRUPT,
|
||||
@@ -70,18 +70,23 @@ enum dma_transaction_type {
|
||||
|
||||
/**
|
||||
* enum dma_ctrl_flags - DMA flags to augment operation preparation,
|
||||
* control completion, and communicate status.
|
||||
* control completion, and communicate status.
|
||||
* @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of
|
||||
* this transaction
|
||||
* this transaction
|
||||
* @DMA_CTRL_ACK - the descriptor cannot be reused until the client
|
||||
* acknowledges receipt, i.e. has has a chance to establish any
|
||||
* dependency chains
|
||||
* acknowledges receipt, i.e. has has a chance to establish any dependency
|
||||
* chains
|
||||
* @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s)
|
||||
* @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s)
|
||||
* @DMA_COMPL_SRC_UNMAP_SINGLE - set to do the source dma-unmapping as single
|
||||
* (if not set, do the source dma-unmapping as page)
|
||||
* @DMA_COMPL_DEST_UNMAP_SINGLE - set to do the destination dma-unmapping as single
|
||||
* (if not set, do the destination dma-unmapping as page)
|
||||
* @DMA_PREP_PQ_DISABLE_P - prevent generation of P while generating Q
|
||||
* @DMA_PREP_PQ_DISABLE_Q - prevent generation of Q while generating P
|
||||
* @DMA_PREP_CONTINUE - indicate to a driver that it is reusing buffers as
|
||||
* sources that were the result of a previous operation, in the case of a PQ
|
||||
* operation it continues the calculation with new sources
|
||||
*/
|
||||
enum dma_ctrl_flags {
|
||||
DMA_PREP_INTERRUPT = (1 << 0),
|
||||
@@ -90,8 +95,30 @@ enum dma_ctrl_flags {
|
||||
DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3),
|
||||
DMA_COMPL_SRC_UNMAP_SINGLE = (1 << 4),
|
||||
DMA_COMPL_DEST_UNMAP_SINGLE = (1 << 5),
|
||||
DMA_PREP_PQ_DISABLE_P = (1 << 6),
|
||||
DMA_PREP_PQ_DISABLE_Q = (1 << 7),
|
||||
DMA_PREP_CONTINUE = (1 << 8),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum sum_check_bits - bit position of pq_check_flags
|
||||
*/
|
||||
enum sum_check_bits {
|
||||
SUM_CHECK_P = 0,
|
||||
SUM_CHECK_Q = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum pq_check_flags - result of async_{xor,pq}_zero_sum operations
|
||||
* @SUM_CHECK_P_RESULT - 1 if xor zero sum error, 0 otherwise
|
||||
* @SUM_CHECK_Q_RESULT - 1 if reed-solomon zero sum error, 0 otherwise
|
||||
*/
|
||||
enum sum_check_flags {
|
||||
SUM_CHECK_P_RESULT = (1 << SUM_CHECK_P),
|
||||
SUM_CHECK_Q_RESULT = (1 << SUM_CHECK_Q),
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* dma_cap_mask_t - capabilities bitmap modeled after cpumask_t.
|
||||
* See linux/cpumask.h
|
||||
@@ -213,6 +240,7 @@ struct dma_async_tx_descriptor {
|
||||
* @global_node: list_head for global dma_device_list
|
||||
* @cap_mask: one or more dma_capability flags
|
||||
* @max_xor: maximum number of xor sources, 0 if no capability
|
||||
* @max_pq: maximum number of PQ sources and PQ-continue capability
|
||||
* @dev_id: unique device ID
|
||||
* @dev: struct device reference for dma mapping api
|
||||
* @device_alloc_chan_resources: allocate resources and return the
|
||||
@@ -220,7 +248,9 @@ struct dma_async_tx_descriptor {
|
||||
* @device_free_chan_resources: release DMA channel's resources
|
||||
* @device_prep_dma_memcpy: prepares a memcpy operation
|
||||
* @device_prep_dma_xor: prepares a xor operation
|
||||
* @device_prep_dma_zero_sum: prepares a zero_sum operation
|
||||
* @device_prep_dma_xor_val: prepares a xor validation operation
|
||||
* @device_prep_dma_pq: prepares a pq operation
|
||||
* @device_prep_dma_pq_val: prepares a pqzero_sum operation
|
||||
* @device_prep_dma_memset: prepares a memset operation
|
||||
* @device_prep_dma_interrupt: prepares an end of chain interrupt operation
|
||||
* @device_prep_slave_sg: prepares a slave dma operation
|
||||
@@ -235,7 +265,9 @@ struct dma_device {
|
||||
struct list_head channels;
|
||||
struct list_head global_node;
|
||||
dma_cap_mask_t cap_mask;
|
||||
int max_xor;
|
||||
unsigned short max_xor;
|
||||
unsigned short max_pq;
|
||||
#define DMA_HAS_PQ_CONTINUE (1 << 15)
|
||||
|
||||
int dev_id;
|
||||
struct device *dev;
|
||||
@@ -249,9 +281,17 @@ struct dma_device {
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
|
||||
struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
|
||||
unsigned int src_cnt, size_t len, unsigned long flags);
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)(
|
||||
struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt,
|
||||
size_t len, u32 *result, unsigned long flags);
|
||||
size_t len, enum sum_check_flags *result, unsigned long flags);
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_pq)(
|
||||
struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
|
||||
unsigned int src_cnt, const unsigned char *scf,
|
||||
size_t len, unsigned long flags);
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)(
|
||||
struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
|
||||
unsigned int src_cnt, const unsigned char *scf, size_t len,
|
||||
enum sum_check_flags *pqres, unsigned long flags);
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
|
||||
struct dma_chan *chan, dma_addr_t dest, int value, size_t len,
|
||||
unsigned long flags);
|
||||
@@ -270,6 +310,60 @@ struct dma_device {
|
||||
void (*device_issue_pending)(struct dma_chan *chan);
|
||||
};
|
||||
|
||||
static inline void
|
||||
dma_set_maxpq(struct dma_device *dma, int maxpq, int has_pq_continue)
|
||||
{
|
||||
dma->max_pq = maxpq;
|
||||
if (has_pq_continue)
|
||||
dma->max_pq |= DMA_HAS_PQ_CONTINUE;
|
||||
}
|
||||
|
||||
static inline bool dmaf_continue(enum dma_ctrl_flags flags)
|
||||
{
|
||||
return (flags & DMA_PREP_CONTINUE) == DMA_PREP_CONTINUE;
|
||||
}
|
||||
|
||||
static inline bool dmaf_p_disabled_continue(enum dma_ctrl_flags flags)
|
||||
{
|
||||
enum dma_ctrl_flags mask = DMA_PREP_CONTINUE | DMA_PREP_PQ_DISABLE_P;
|
||||
|
||||
return (flags & mask) == mask;
|
||||
}
|
||||
|
||||
static inline bool dma_dev_has_pq_continue(struct dma_device *dma)
|
||||
{
|
||||
return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE;
|
||||
}
|
||||
|
||||
static unsigned short dma_dev_to_maxpq(struct dma_device *dma)
|
||||
{
|
||||
return dma->max_pq & ~DMA_HAS_PQ_CONTINUE;
|
||||
}
|
||||
|
||||
/* dma_maxpq - reduce maxpq in the face of continued operations
|
||||
* @dma - dma device with PQ capability
|
||||
* @flags - to check if DMA_PREP_CONTINUE and DMA_PREP_PQ_DISABLE_P are set
|
||||
*
|
||||
* When an engine does not support native continuation we need 3 extra
|
||||
* source slots to reuse P and Q with the following coefficients:
|
||||
* 1/ {00} * P : remove P from Q', but use it as a source for P'
|
||||
* 2/ {01} * Q : use Q to continue Q' calculation
|
||||
* 3/ {00} * Q : subtract Q from P' to cancel (2)
|
||||
*
|
||||
* In the case where P is disabled we only need 1 extra source:
|
||||
* 1/ {01} * Q : use Q to continue Q' calculation
|
||||
*/
|
||||
static inline int dma_maxpq(struct dma_device *dma, enum dma_ctrl_flags flags)
|
||||
{
|
||||
if (dma_dev_has_pq_continue(dma) || !dmaf_continue(flags))
|
||||
return dma_dev_to_maxpq(dma);
|
||||
else if (dmaf_p_disabled_continue(flags))
|
||||
return dma_dev_to_maxpq(dma) - 1;
|
||||
else if (dmaf_continue(flags))
|
||||
return dma_dev_to_maxpq(dma) - 3;
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* --- public DMA engine API --- */
|
||||
|
||||
#ifdef CONFIG_DMA_ENGINE
|
||||
|
||||
Reference in New Issue
Block a user