aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ioat
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2013-11-13 13:37:36 -0500
committerDan Williams <dan.j.williams@intel.com>2013-11-14 14:04:41 -0500
commit21e96c7313486390c694919522a76dfea0a86c59 (patch)
tree211439af0431a256def810a915e37ee6519ae4a6 /drivers/dma/ioat
parent5d48b9b5d80e3aa38a5161565398b1e48a650573 (diff)
ioatdma: fix selection of 16 vs 8 source path
When performing continuations there are implied sources that need to be added to the source count. Quoting dma_set_maxpq: /* 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 */ ...fix the selection of the 16 source path to take these implied sources into account. Note this also kills the BUG_ON(src_cnt < 9) check in __ioat3_prep_pq16_lock(). Besides not accounting for implied sources the check is redundant given we already made the path selection. Cc: <stable@vger.kernel.org> Cc: Dave Jiang <dave.jiang@intel.com> Acked-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma/ioat')
-rw-r--r--drivers/dma/ioat/dma_v3.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index f26a35d43ba1..0284908997f8 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -951,9 +951,6 @@ __ioat3_prep_pq16_lock(struct dma_chan *c, enum sum_check_flags *result,
951 u8 op; 951 u8 op;
952 int i, s, idx, num_descs; 952 int i, s, idx, num_descs;
953 953
954 /* this function only handles src_cnt 9 - 16 */
955 BUG_ON(src_cnt < 9);
956
957 /* this function is only called with 9-16 sources */ 954 /* this function is only called with 9-16 sources */
958 op = result ? IOAT_OP_PQ_VAL_16S : IOAT_OP_PQ_16S; 955 op = result ? IOAT_OP_PQ_VAL_16S : IOAT_OP_PQ_16S;
959 956
@@ -1039,13 +1036,21 @@ __ioat3_prep_pq16_lock(struct dma_chan *c, enum sum_check_flags *result,
1039 return &desc->txd; 1036 return &desc->txd;
1040} 1037}
1041 1038
1039static int src_cnt_flags(unsigned int src_cnt, unsigned long flags)
1040{
1041 if (dmaf_p_disabled_continue(flags))
1042 return src_cnt + 1;
1043 else if (dmaf_continue(flags))
1044 return src_cnt + 3;
1045 else
1046 return src_cnt;
1047}
1048
1042static struct dma_async_tx_descriptor * 1049static struct dma_async_tx_descriptor *
1043ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, 1050ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
1044 unsigned int src_cnt, const unsigned char *scf, size_t len, 1051 unsigned int src_cnt, const unsigned char *scf, size_t len,
1045 unsigned long flags) 1052 unsigned long flags)
1046{ 1053{
1047 struct dma_device *dma = chan->device;
1048
1049 /* specify valid address for disabled result */ 1054 /* specify valid address for disabled result */
1050 if (flags & DMA_PREP_PQ_DISABLE_P) 1055 if (flags & DMA_PREP_PQ_DISABLE_P)
1051 dst[0] = dst[1]; 1056 dst[0] = dst[1];
@@ -1065,7 +1070,7 @@ ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
1065 single_source_coef[0] = scf[0]; 1070 single_source_coef[0] = scf[0];
1066 single_source_coef[1] = 0; 1071 single_source_coef[1] = 0;
1067 1072
1068 return (src_cnt > 8) && (dma->max_pq > 8) ? 1073 return src_cnt_flags(src_cnt, flags) > 8 ?
1069 __ioat3_prep_pq16_lock(chan, NULL, dst, single_source, 1074 __ioat3_prep_pq16_lock(chan, NULL, dst, single_source,
1070 2, single_source_coef, len, 1075 2, single_source_coef, len,
1071 flags) : 1076 flags) :
@@ -1073,7 +1078,7 @@ ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
1073 single_source_coef, len, flags); 1078 single_source_coef, len, flags);
1074 1079
1075 } else { 1080 } else {
1076 return (src_cnt > 8) && (dma->max_pq > 8) ? 1081 return src_cnt_flags(src_cnt, flags) > 8 ?
1077 __ioat3_prep_pq16_lock(chan, NULL, dst, src, src_cnt, 1082 __ioat3_prep_pq16_lock(chan, NULL, dst, src, src_cnt,
1078 scf, len, flags) : 1083 scf, len, flags) :
1079 __ioat3_prep_pq_lock(chan, NULL, dst, src, src_cnt, 1084 __ioat3_prep_pq_lock(chan, NULL, dst, src, src_cnt,
@@ -1086,8 +1091,6 @@ ioat3_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
1086 unsigned int src_cnt, const unsigned char *scf, size_t len, 1091 unsigned int src_cnt, const unsigned char *scf, size_t len,
1087 enum sum_check_flags *pqres, unsigned long flags) 1092 enum sum_check_flags *pqres, unsigned long flags)
1088{ 1093{
1089 struct dma_device *dma = chan->device;
1090
1091 /* specify valid address for disabled result */ 1094 /* specify valid address for disabled result */
1092 if (flags & DMA_PREP_PQ_DISABLE_P) 1095 if (flags & DMA_PREP_PQ_DISABLE_P)
1093 pq[0] = pq[1]; 1096 pq[0] = pq[1];
@@ -1099,7 +1102,7 @@ ioat3_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
1099 */ 1102 */
1100 *pqres = 0; 1103 *pqres = 0;
1101 1104
1102 return (src_cnt > 8) && (dma->max_pq > 8) ? 1105 return src_cnt_flags(src_cnt, flags) > 8 ?
1103 __ioat3_prep_pq16_lock(chan, pqres, pq, src, src_cnt, scf, len, 1106 __ioat3_prep_pq16_lock(chan, pqres, pq, src, src_cnt, scf, len,
1104 flags) : 1107 flags) :
1105 __ioat3_prep_pq_lock(chan, pqres, pq, src, src_cnt, scf, len, 1108 __ioat3_prep_pq_lock(chan, pqres, pq, src, src_cnt, scf, len,
@@ -1110,7 +1113,6 @@ static struct dma_async_tx_descriptor *
1110ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src, 1113ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src,
1111 unsigned int src_cnt, size_t len, unsigned long flags) 1114 unsigned int src_cnt, size_t len, unsigned long flags)
1112{ 1115{
1113 struct dma_device *dma = chan->device;
1114 unsigned char scf[src_cnt]; 1116 unsigned char scf[src_cnt];
1115 dma_addr_t pq[2]; 1117 dma_addr_t pq[2];
1116 1118
@@ -1119,7 +1121,7 @@ ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src,
1119 flags |= DMA_PREP_PQ_DISABLE_Q; 1121 flags |= DMA_PREP_PQ_DISABLE_Q;
1120 pq[1] = dst; /* specify valid address for disabled result */ 1122 pq[1] = dst; /* specify valid address for disabled result */
1121 1123
1122 return (src_cnt > 8) && (dma->max_pq > 8) ? 1124 return src_cnt_flags(src_cnt, flags) > 8 ?
1123 __ioat3_prep_pq16_lock(chan, NULL, pq, src, src_cnt, scf, len, 1125 __ioat3_prep_pq16_lock(chan, NULL, pq, src, src_cnt, scf, len,
1124 flags) : 1126 flags) :
1125 __ioat3_prep_pq_lock(chan, NULL, pq, src, src_cnt, scf, len, 1127 __ioat3_prep_pq_lock(chan, NULL, pq, src, src_cnt, scf, len,
@@ -1131,7 +1133,6 @@ ioat3_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src,
1131 unsigned int src_cnt, size_t len, 1133 unsigned int src_cnt, size_t len,
1132 enum sum_check_flags *result, unsigned long flags) 1134 enum sum_check_flags *result, unsigned long flags)
1133{ 1135{
1134 struct dma_device *dma = chan->device;
1135 unsigned char scf[src_cnt]; 1136 unsigned char scf[src_cnt];
1136 dma_addr_t pq[2]; 1137 dma_addr_t pq[2];
1137 1138
@@ -1145,8 +1146,7 @@ ioat3_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src,
1145 flags |= DMA_PREP_PQ_DISABLE_Q; 1146 flags |= DMA_PREP_PQ_DISABLE_Q;
1146 pq[1] = pq[0]; /* specify valid address for disabled result */ 1147 pq[1] = pq[0]; /* specify valid address for disabled result */
1147 1148
1148 1149 return src_cnt_flags(src_cnt, flags) > 8 ?
1149 return (src_cnt > 8) && (dma->max_pq > 8) ?
1150 __ioat3_prep_pq16_lock(chan, result, pq, &src[1], src_cnt - 1, 1150 __ioat3_prep_pq16_lock(chan, result, pq, &src[1], src_cnt - 1,
1151 scf, len, flags) : 1151 scf, len, flags) :
1152 __ioat3_prep_pq_lock(chan, result, pq, &src[1], src_cnt - 1, 1152 __ioat3_prep_pq_lock(chan, result, pq, &src[1], src_cnt - 1,