diff options
| -rw-r--r-- | arch/arm/include/asm/hardware/iop3xx-adma.h | 76 | ||||
| -rw-r--r-- | arch/arm/include/asm/hardware/iop_adma.h | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop13xx/include/mach/adma.h | 107 | ||||
| -rw-r--r-- | drivers/dma/iop-adma.c | 437 |
4 files changed, 577 insertions, 44 deletions
diff --git a/arch/arm/include/asm/hardware/iop3xx-adma.h b/arch/arm/include/asm/hardware/iop3xx-adma.h index 26eefea02314..1a8c7279a28b 100644 --- a/arch/arm/include/asm/hardware/iop3xx-adma.h +++ b/arch/arm/include/asm/hardware/iop3xx-adma.h | |||
| @@ -187,11 +187,74 @@ union iop3xx_desc { | |||
| 187 | void *ptr; | 187 | void *ptr; |
| 188 | }; | 188 | }; |
| 189 | 189 | ||
| 190 | /* No support for p+q operations */ | ||
| 191 | static inline int | ||
| 192 | iop_chan_pq_slot_count(size_t len, int src_cnt, int *slots_per_op) | ||
| 193 | { | ||
| 194 | BUG(); | ||
| 195 | return 0; | ||
| 196 | } | ||
| 197 | |||
| 198 | static inline void | ||
| 199 | iop_desc_init_pq(struct iop_adma_desc_slot *desc, int src_cnt, | ||
| 200 | unsigned long flags) | ||
| 201 | { | ||
| 202 | BUG(); | ||
| 203 | } | ||
| 204 | |||
| 205 | static inline void | ||
| 206 | iop_desc_set_pq_addr(struct iop_adma_desc_slot *desc, dma_addr_t *addr) | ||
| 207 | { | ||
| 208 | BUG(); | ||
| 209 | } | ||
| 210 | |||
| 211 | static inline void | ||
| 212 | iop_desc_set_pq_src_addr(struct iop_adma_desc_slot *desc, int src_idx, | ||
| 213 | dma_addr_t addr, unsigned char coef) | ||
| 214 | { | ||
| 215 | BUG(); | ||
| 216 | } | ||
| 217 | |||
| 218 | static inline int | ||
| 219 | iop_chan_pq_zero_sum_slot_count(size_t len, int src_cnt, int *slots_per_op) | ||
| 220 | { | ||
| 221 | BUG(); | ||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static inline void | ||
| 226 | iop_desc_init_pq_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, | ||
| 227 | unsigned long flags) | ||
| 228 | { | ||
| 229 | BUG(); | ||
| 230 | } | ||
| 231 | |||
| 232 | static inline void | ||
| 233 | iop_desc_set_pq_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len) | ||
| 234 | { | ||
| 235 | BUG(); | ||
| 236 | } | ||
| 237 | |||
| 238 | #define iop_desc_set_pq_zero_sum_src_addr iop_desc_set_pq_src_addr | ||
| 239 | |||
| 240 | static inline void | ||
| 241 | iop_desc_set_pq_zero_sum_addr(struct iop_adma_desc_slot *desc, int pq_idx, | ||
| 242 | dma_addr_t *src) | ||
| 243 | { | ||
| 244 | BUG(); | ||
| 245 | } | ||
| 246 | |||
| 190 | static inline int iop_adma_get_max_xor(void) | 247 | static inline int iop_adma_get_max_xor(void) |
| 191 | { | 248 | { |
| 192 | return 32; | 249 | return 32; |
| 193 | } | 250 | } |
| 194 | 251 | ||
| 252 | static inline int iop_adma_get_max_pq(void) | ||
| 253 | { | ||
| 254 | BUG(); | ||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 195 | static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan) | 258 | static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan) |
| 196 | { | 259 | { |
| 197 | int id = chan->device->id; | 260 | int id = chan->device->id; |
| @@ -332,6 +395,11 @@ static inline int iop_chan_zero_sum_slot_count(size_t len, int src_cnt, | |||
| 332 | return slot_cnt; | 395 | return slot_cnt; |
| 333 | } | 396 | } |
| 334 | 397 | ||
| 398 | static inline int iop_desc_is_pq(struct iop_adma_desc_slot *desc) | ||
| 399 | { | ||
| 400 | return 0; | ||
| 401 | } | ||
| 402 | |||
| 335 | static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc, | 403 | static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc, |
| 336 | struct iop_adma_chan *chan) | 404 | struct iop_adma_chan *chan) |
| 337 | { | 405 | { |
| @@ -349,6 +417,14 @@ static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc, | |||
| 349 | return 0; | 417 | return 0; |
| 350 | } | 418 | } |
| 351 | 419 | ||
| 420 | |||
| 421 | static inline u32 iop_desc_get_qdest_addr(struct iop_adma_desc_slot *desc, | ||
| 422 | struct iop_adma_chan *chan) | ||
| 423 | { | ||
| 424 | BUG(); | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 352 | static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc, | 428 | static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc, |
| 353 | struct iop_adma_chan *chan) | 429 | struct iop_adma_chan *chan) |
| 354 | { | 430 | { |
diff --git a/arch/arm/include/asm/hardware/iop_adma.h b/arch/arm/include/asm/hardware/iop_adma.h index 385c6e8cbbd2..bbe8a0475cad 100644 --- a/arch/arm/include/asm/hardware/iop_adma.h +++ b/arch/arm/include/asm/hardware/iop_adma.h | |||
| @@ -106,6 +106,7 @@ struct iop_adma_desc_slot { | |||
| 106 | union { | 106 | union { |
| 107 | u32 *xor_check_result; | 107 | u32 *xor_check_result; |
| 108 | u32 *crc32_result; | 108 | u32 *crc32_result; |
| 109 | u32 *pq_check_result; | ||
| 109 | }; | 110 | }; |
| 110 | }; | 111 | }; |
| 111 | 112 | ||
diff --git a/arch/arm/mach-iop13xx/include/mach/adma.h b/arch/arm/mach-iop13xx/include/mach/adma.h index 1cd31df8924d..6d3782d85a9f 100644 --- a/arch/arm/mach-iop13xx/include/mach/adma.h +++ b/arch/arm/mach-iop13xx/include/mach/adma.h | |||
| @@ -150,6 +150,8 @@ static inline int iop_adma_get_max_xor(void) | |||
| 150 | return 16; | 150 | return 16; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | #define iop_adma_get_max_pq iop_adma_get_max_xor | ||
| 154 | |||
| 153 | static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan) | 155 | static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan) |
| 154 | { | 156 | { |
| 155 | return __raw_readl(ADMA_ADAR(chan)); | 157 | return __raw_readl(ADMA_ADAR(chan)); |
| @@ -211,7 +213,10 @@ iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op) | |||
| 211 | #define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT | 213 | #define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT |
| 212 | #define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT | 214 | #define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT |
| 213 | #define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT | 215 | #define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT |
| 216 | #define IOP_ADMA_PQ_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT | ||
| 214 | #define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o) | 217 | #define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o) |
| 218 | #define iop_chan_pq_slot_count iop_chan_xor_slot_count | ||
| 219 | #define iop_chan_pq_zero_sum_slot_count iop_chan_xor_slot_count | ||
| 215 | 220 | ||
| 216 | static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc, | 221 | static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc, |
| 217 | struct iop_adma_chan *chan) | 222 | struct iop_adma_chan *chan) |
| @@ -220,6 +225,13 @@ static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc, | |||
| 220 | return hw_desc->dest_addr; | 225 | return hw_desc->dest_addr; |
| 221 | } | 226 | } |
| 222 | 227 | ||
| 228 | static inline u32 iop_desc_get_qdest_addr(struct iop_adma_desc_slot *desc, | ||
| 229 | struct iop_adma_chan *chan) | ||
| 230 | { | ||
| 231 | struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc; | ||
| 232 | return hw_desc->q_dest_addr; | ||
| 233 | } | ||
| 234 | |||
| 223 | static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc, | 235 | static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc, |
| 224 | struct iop_adma_chan *chan) | 236 | struct iop_adma_chan *chan) |
| 225 | { | 237 | { |
| @@ -319,6 +331,58 @@ iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, | |||
| 319 | return 1; | 331 | return 1; |
| 320 | } | 332 | } |
| 321 | 333 | ||
| 334 | static inline void | ||
| 335 | iop_desc_init_pq(struct iop_adma_desc_slot *desc, int src_cnt, | ||
| 336 | unsigned long flags) | ||
| 337 | { | ||
| 338 | struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc; | ||
| 339 | union { | ||
| 340 | u32 value; | ||
| 341 | struct iop13xx_adma_desc_ctrl field; | ||
| 342 | } u_desc_ctrl; | ||
| 343 | |||
| 344 | u_desc_ctrl.value = 0; | ||
| 345 | u_desc_ctrl.field.src_select = src_cnt - 1; | ||
| 346 | u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */ | ||
| 347 | u_desc_ctrl.field.pq_xfer_en = 1; | ||
| 348 | u_desc_ctrl.field.p_xfer_dis = !!(flags & DMA_PREP_PQ_DISABLE_P); | ||
| 349 | u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT; | ||
| 350 | hw_desc->desc_ctrl = u_desc_ctrl.value; | ||
| 351 | } | ||
| 352 | |||
| 353 | static inline int iop_desc_is_pq(struct iop_adma_desc_slot *desc) | ||
| 354 | { | ||
| 355 | struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc; | ||
| 356 | union { | ||
| 357 | u32 value; | ||
| 358 | struct iop13xx_adma_desc_ctrl field; | ||
| 359 | } u_desc_ctrl; | ||
| 360 | |||
| 361 | u_desc_ctrl.value = hw_desc->desc_ctrl; | ||
| 362 | return u_desc_ctrl.field.pq_xfer_en; | ||
| 363 | } | ||
| 364 | |||
| 365 | static inline void | ||
| 366 | iop_desc_init_pq_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, | ||
| 367 | unsigned long flags) | ||
| 368 | { | ||
| 369 | struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc; | ||
| 370 | union { | ||
| 371 | u32 value; | ||
| 372 | struct iop13xx_adma_desc_ctrl field; | ||
| 373 | } u_desc_ctrl; | ||
| 374 | |||
| 375 | u_desc_ctrl.value = 0; | ||
| 376 | u_desc_ctrl.field.src_select = src_cnt - 1; | ||
| 377 | u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */ | ||
| 378 | u_desc_ctrl.field.zero_result = 1; | ||
| 379 | u_desc_ctrl.field.status_write_back_en = 1; | ||
| 380 | u_desc_ctrl.field.pq_xfer_en = 1; | ||
| 381 | u_desc_ctrl.field.p_xfer_dis = !!(flags & DMA_PREP_PQ_DISABLE_P); | ||
| 382 | u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT; | ||
| 383 | hw_desc->desc_ctrl = u_desc_ctrl.value; | ||
| 384 | } | ||
| 385 | |||
| 322 | static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc, | 386 | static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc, |
| 323 | struct iop_adma_chan *chan, | 387 | struct iop_adma_chan *chan, |
| 324 | u32 byte_count) | 388 | u32 byte_count) |
| @@ -351,6 +415,7 @@ iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len) | |||
| 351 | } | 415 | } |
| 352 | } | 416 | } |
| 353 | 417 | ||
| 418 | #define iop_desc_set_pq_zero_sum_byte_count iop_desc_set_zero_sum_byte_count | ||
| 354 | 419 | ||
| 355 | static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc, | 420 | static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc, |
| 356 | struct iop_adma_chan *chan, | 421 | struct iop_adma_chan *chan, |
| @@ -361,6 +426,16 @@ static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc, | |||
| 361 | hw_desc->upper_dest_addr = 0; | 426 | hw_desc->upper_dest_addr = 0; |
| 362 | } | 427 | } |
| 363 | 428 | ||
| 429 | static inline void | ||
| 430 | iop_desc_set_pq_addr(struct iop_adma_desc_slot *desc, dma_addr_t *addr) | ||
| 431 | { | ||
| 432 | struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc; | ||
| 433 | |||
| 434 | hw_desc->dest_addr = addr[0]; | ||
| 435 | hw_desc->q_dest_addr = addr[1]; | ||
| 436 | hw_desc->upper_dest_addr = 0; | ||
| 437 | } | ||
| 438 | |||
| 364 | static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc, | 439 | static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc, |
| 365 | dma_addr_t addr) | 440 | dma_addr_t addr) |
| 366 | { | 441 | { |
| @@ -389,6 +464,29 @@ static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc, | |||
| 389 | } | 464 | } |
| 390 | 465 | ||
| 391 | static inline void | 466 | static inline void |
| 467 | iop_desc_set_pq_src_addr(struct iop_adma_desc_slot *desc, int src_idx, | ||
| 468 | dma_addr_t addr, unsigned char coef) | ||
| 469 | { | ||
| 470 | int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op; | ||
| 471 | struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter; | ||
| 472 | struct iop13xx_adma_src *src; | ||
| 473 | int i = 0; | ||
| 474 | |||
| 475 | do { | ||
| 476 | iter = iop_hw_desc_slot_idx(hw_desc, i); | ||
| 477 | src = &iter->src[src_idx]; | ||
| 478 | src->src_addr = addr; | ||
| 479 | src->pq_upper_src_addr = 0; | ||
| 480 | src->pq_dmlt = coef; | ||
| 481 | slot_cnt -= slots_per_op; | ||
| 482 | if (slot_cnt) { | ||
| 483 | i += slots_per_op; | ||
| 484 | addr += IOP_ADMA_PQ_MAX_BYTE_COUNT; | ||
| 485 | } | ||
| 486 | } while (slot_cnt); | ||
| 487 | } | ||
| 488 | |||
| 489 | static inline void | ||
| 392 | iop_desc_init_interrupt(struct iop_adma_desc_slot *desc, | 490 | iop_desc_init_interrupt(struct iop_adma_desc_slot *desc, |
| 393 | struct iop_adma_chan *chan) | 491 | struct iop_adma_chan *chan) |
| 394 | { | 492 | { |
| @@ -399,6 +497,15 @@ iop_desc_init_interrupt(struct iop_adma_desc_slot *desc, | |||
| 399 | } | 497 | } |
| 400 | 498 | ||
| 401 | #define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr | 499 | #define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr |
| 500 | #define iop_desc_set_pq_zero_sum_src_addr iop_desc_set_pq_src_addr | ||
| 501 | |||
| 502 | static inline void | ||
| 503 | iop_desc_set_pq_zero_sum_addr(struct iop_adma_desc_slot *desc, int pq_idx, | ||
| 504 | dma_addr_t *src) | ||
| 505 | { | ||
| 506 | iop_desc_set_xor_src_addr(desc, pq_idx, src[pq_idx]); | ||
| 507 | iop_desc_set_xor_src_addr(desc, pq_idx+1, src[pq_idx+1]); | ||
| 508 | } | ||
| 402 | 509 | ||
| 403 | static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc, | 510 | static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc, |
| 404 | u32 next_desc_addr) | 511 | u32 next_desc_addr) |
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index cecb6d657d55..518f557ef857 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
| 32 | #include <linux/memory.h> | 32 | #include <linux/memory.h> |
| 33 | #include <linux/ioport.h> | 33 | #include <linux/ioport.h> |
| 34 | #include <linux/raid/pq.h> | ||
| 34 | 35 | ||
| 35 | #include <mach/adma.h> | 36 | #include <mach/adma.h> |
| 36 | 37 | ||
| @@ -57,65 +58,110 @@ static void iop_adma_free_slots(struct iop_adma_desc_slot *slot) | |||
| 57 | } | 58 | } |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 61 | static void | ||
| 62 | iop_desc_unmap(struct iop_adma_chan *iop_chan, struct iop_adma_desc_slot *desc) | ||
| 63 | { | ||
| 64 | struct dma_async_tx_descriptor *tx = &desc->async_tx; | ||
| 65 | struct iop_adma_desc_slot *unmap = desc->group_head; | ||
| 66 | struct device *dev = &iop_chan->device->pdev->dev; | ||
| 67 | u32 len = unmap->unmap_len; | ||
| 68 | enum dma_ctrl_flags flags = tx->flags; | ||
| 69 | u32 src_cnt; | ||
| 70 | dma_addr_t addr; | ||
| 71 | dma_addr_t dest; | ||
| 72 | |||
| 73 | src_cnt = unmap->unmap_src_cnt; | ||
| 74 | dest = iop_desc_get_dest_addr(unmap, iop_chan); | ||
| 75 | if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { | ||
| 76 | enum dma_data_direction dir; | ||
| 77 | |||
| 78 | if (src_cnt > 1) /* is xor? */ | ||
| 79 | dir = DMA_BIDIRECTIONAL; | ||
| 80 | else | ||
| 81 | dir = DMA_FROM_DEVICE; | ||
| 82 | |||
| 83 | dma_unmap_page(dev, dest, len, dir); | ||
| 84 | } | ||
| 85 | |||
| 86 | if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { | ||
| 87 | while (src_cnt--) { | ||
| 88 | addr = iop_desc_get_src_addr(unmap, iop_chan, src_cnt); | ||
| 89 | if (addr == dest) | ||
| 90 | continue; | ||
| 91 | dma_unmap_page(dev, addr, len, DMA_TO_DEVICE); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | desc->group_head = NULL; | ||
| 95 | } | ||
| 96 | |||
| 97 | static void | ||
| 98 | iop_desc_unmap_pq(struct iop_adma_chan *iop_chan, struct iop_adma_desc_slot *desc) | ||
| 99 | { | ||
| 100 | struct dma_async_tx_descriptor *tx = &desc->async_tx; | ||
| 101 | struct iop_adma_desc_slot *unmap = desc->group_head; | ||
| 102 | struct device *dev = &iop_chan->device->pdev->dev; | ||
| 103 | u32 len = unmap->unmap_len; | ||
| 104 | enum dma_ctrl_flags flags = tx->flags; | ||
| 105 | u32 src_cnt = unmap->unmap_src_cnt; | ||
| 106 | dma_addr_t pdest = iop_desc_get_dest_addr(unmap, iop_chan); | ||
| 107 | dma_addr_t qdest = iop_desc_get_qdest_addr(unmap, iop_chan); | ||
| 108 | int i; | ||
| 109 | |||
| 110 | if (tx->flags & DMA_PREP_CONTINUE) | ||
| 111 | src_cnt -= 3; | ||
| 112 | |||
| 113 | if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP) && !desc->pq_check_result) { | ||
| 114 | dma_unmap_page(dev, pdest, len, DMA_BIDIRECTIONAL); | ||
| 115 | dma_unmap_page(dev, qdest, len, DMA_BIDIRECTIONAL); | ||
| 116 | } | ||
| 117 | |||
| 118 | if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { | ||
| 119 | dma_addr_t addr; | ||
| 120 | |||
| 121 | for (i = 0; i < src_cnt; i++) { | ||
| 122 | addr = iop_desc_get_src_addr(unmap, iop_chan, i); | ||
| 123 | dma_unmap_page(dev, addr, len, DMA_TO_DEVICE); | ||
| 124 | } | ||
| 125 | if (desc->pq_check_result) { | ||
| 126 | dma_unmap_page(dev, pdest, len, DMA_TO_DEVICE); | ||
| 127 | dma_unmap_page(dev, qdest, len, DMA_TO_DEVICE); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | desc->group_head = NULL; | ||
| 132 | } | ||
| 133 | |||
| 134 | |||
| 60 | static dma_cookie_t | 135 | static dma_cookie_t |
| 61 | iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc, | 136 | iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc, |
| 62 | struct iop_adma_chan *iop_chan, dma_cookie_t cookie) | 137 | struct iop_adma_chan *iop_chan, dma_cookie_t cookie) |
| 63 | { | 138 | { |
| 64 | BUG_ON(desc->async_tx.cookie < 0); | 139 | struct dma_async_tx_descriptor *tx = &desc->async_tx; |
| 65 | if (desc->async_tx.cookie > 0) { | 140 | |
| 66 | cookie = desc->async_tx.cookie; | 141 | BUG_ON(tx->cookie < 0); |
| 67 | desc->async_tx.cookie = 0; | 142 | if (tx->cookie > 0) { |
| 143 | cookie = tx->cookie; | ||
| 144 | tx->cookie = 0; | ||
| 68 | 145 | ||
| 69 | /* call the callback (must not sleep or submit new | 146 | /* call the callback (must not sleep or submit new |
| 70 | * operations to this channel) | 147 | * operations to this channel) |
| 71 | */ | 148 | */ |
| 72 | if (desc->async_tx.callback) | 149 | if (tx->callback) |
| 73 | desc->async_tx.callback( | 150 | tx->callback(tx->callback_param); |
| 74 | desc->async_tx.callback_param); | ||
| 75 | 151 | ||
| 76 | /* unmap dma addresses | 152 | /* unmap dma addresses |
| 77 | * (unmap_single vs unmap_page?) | 153 | * (unmap_single vs unmap_page?) |
| 78 | */ | 154 | */ |
| 79 | if (desc->group_head && desc->unmap_len) { | 155 | if (desc->group_head && desc->unmap_len) { |
| 80 | struct iop_adma_desc_slot *unmap = desc->group_head; | 156 | if (iop_desc_is_pq(desc)) |
| 81 | struct device *dev = | 157 | iop_desc_unmap_pq(iop_chan, desc); |
| 82 | &iop_chan->device->pdev->dev; | 158 | else |
| 83 | u32 len = unmap->unmap_len; | 159 | iop_desc_unmap(iop_chan, desc); |
| 84 | enum dma_ctrl_flags flags = desc->async_tx.flags; | ||
| 85 | u32 src_cnt; | ||
| 86 | dma_addr_t addr; | ||
| 87 | dma_addr_t dest; | ||
| 88 | |||
| 89 | src_cnt = unmap->unmap_src_cnt; | ||
| 90 | dest = iop_desc_get_dest_addr(unmap, iop_chan); | ||
| 91 | if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { | ||
| 92 | enum dma_data_direction dir; | ||
| 93 | |||
| 94 | if (src_cnt > 1) /* is xor? */ | ||
| 95 | dir = DMA_BIDIRECTIONAL; | ||
| 96 | else | ||
| 97 | dir = DMA_FROM_DEVICE; | ||
| 98 | |||
| 99 | dma_unmap_page(dev, dest, len, dir); | ||
| 100 | } | ||
| 101 | |||
| 102 | if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { | ||
| 103 | while (src_cnt--) { | ||
| 104 | addr = iop_desc_get_src_addr(unmap, | ||
| 105 | iop_chan, | ||
| 106 | src_cnt); | ||
| 107 | if (addr == dest) | ||
| 108 | continue; | ||
| 109 | dma_unmap_page(dev, addr, len, | ||
| 110 | DMA_TO_DEVICE); | ||
| 111 | } | ||
| 112 | } | ||
| 113 | desc->group_head = NULL; | ||
| 114 | } | 160 | } |
| 115 | } | 161 | } |
| 116 | 162 | ||
| 117 | /* run dependent operations */ | 163 | /* run dependent operations */ |
| 118 | dma_run_dependencies(&desc->async_tx); | 164 | dma_run_dependencies(tx); |
| 119 | 165 | ||
| 120 | return cookie; | 166 | return cookie; |
| 121 | } | 167 | } |
| @@ -287,7 +333,12 @@ static void iop_adma_tasklet(unsigned long data) | |||
| 287 | { | 333 | { |
| 288 | struct iop_adma_chan *iop_chan = (struct iop_adma_chan *) data; | 334 | struct iop_adma_chan *iop_chan = (struct iop_adma_chan *) data; |
| 289 | 335 | ||
| 290 | spin_lock(&iop_chan->lock); | 336 | /* lockdep will flag depedency submissions as potentially |
| 337 | * recursive locking, this is not the case as a dependency | ||
| 338 | * submission will never recurse a channels submit routine. | ||
| 339 | * There are checks in async_tx.c to prevent this. | ||
| 340 | */ | ||
| 341 | spin_lock_nested(&iop_chan->lock, SINGLE_DEPTH_NESTING); | ||
| 291 | __iop_adma_slot_cleanup(iop_chan); | 342 | __iop_adma_slot_cleanup(iop_chan); |
| 292 | spin_unlock(&iop_chan->lock); | 343 | spin_unlock(&iop_chan->lock); |
| 293 | } | 344 | } |
| @@ -696,6 +747,118 @@ iop_adma_prep_dma_xor_val(struct dma_chan *chan, dma_addr_t *dma_src, | |||
| 696 | return sw_desc ? &sw_desc->async_tx : NULL; | 747 | return sw_desc ? &sw_desc->async_tx : NULL; |
| 697 | } | 748 | } |
| 698 | 749 | ||
| 750 | static struct dma_async_tx_descriptor * | ||
| 751 | iop_adma_prep_dma_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, | ||
| 752 | unsigned int src_cnt, const unsigned char *scf, size_t len, | ||
| 753 | unsigned long flags) | ||
| 754 | { | ||
| 755 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); | ||
| 756 | struct iop_adma_desc_slot *sw_desc, *g; | ||
| 757 | int slot_cnt, slots_per_op; | ||
| 758 | int continue_srcs; | ||
| 759 | |||
| 760 | if (unlikely(!len)) | ||
| 761 | return NULL; | ||
| 762 | BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT); | ||
| 763 | |||
| 764 | dev_dbg(iop_chan->device->common.dev, | ||
| 765 | "%s src_cnt: %d len: %u flags: %lx\n", | ||
| 766 | __func__, src_cnt, len, flags); | ||
| 767 | |||
| 768 | if (dmaf_p_disabled_continue(flags)) | ||
| 769 | continue_srcs = 1+src_cnt; | ||
| 770 | else if (dmaf_continue(flags)) | ||
| 771 | continue_srcs = 3+src_cnt; | ||
| 772 | else | ||
| 773 | continue_srcs = 0+src_cnt; | ||
| 774 | |||
| 775 | spin_lock_bh(&iop_chan->lock); | ||
| 776 | slot_cnt = iop_chan_pq_slot_count(len, continue_srcs, &slots_per_op); | ||
| 777 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); | ||
| 778 | if (sw_desc) { | ||
| 779 | int i; | ||
| 780 | |||
| 781 | g = sw_desc->group_head; | ||
| 782 | iop_desc_set_byte_count(g, iop_chan, len); | ||
| 783 | |||
| 784 | /* even if P is disabled its destination address (bits | ||
| 785 | * [3:0]) must match Q. It is ok if P points to an | ||
| 786 | * invalid address, it won't be written. | ||
| 787 | */ | ||
| 788 | if (flags & DMA_PREP_PQ_DISABLE_P) | ||
| 789 | dst[0] = dst[1] & 0x7; | ||
| 790 | |||
| 791 | iop_desc_set_pq_addr(g, dst); | ||
| 792 | sw_desc->unmap_src_cnt = src_cnt; | ||
| 793 | sw_desc->unmap_len = len; | ||
| 794 | sw_desc->async_tx.flags = flags; | ||
| 795 | for (i = 0; i < src_cnt; i++) | ||
| 796 | iop_desc_set_pq_src_addr(g, i, src[i], scf[i]); | ||
| 797 | |||
| 798 | /* if we are continuing a previous operation factor in | ||
| 799 | * the old p and q values, see the comment for dma_maxpq | ||
| 800 | * in include/linux/dmaengine.h | ||
| 801 | */ | ||
| 802 | if (dmaf_p_disabled_continue(flags)) | ||
| 803 | iop_desc_set_pq_src_addr(g, i++, dst[1], 1); | ||
| 804 | else if (dmaf_continue(flags)) { | ||
| 805 | iop_desc_set_pq_src_addr(g, i++, dst[0], 0); | ||
| 806 | iop_desc_set_pq_src_addr(g, i++, dst[1], 1); | ||
| 807 | iop_desc_set_pq_src_addr(g, i++, dst[1], 0); | ||
| 808 | } | ||
| 809 | iop_desc_init_pq(g, i, flags); | ||
| 810 | } | ||
| 811 | spin_unlock_bh(&iop_chan->lock); | ||
| 812 | |||
| 813 | return sw_desc ? &sw_desc->async_tx : NULL; | ||
| 814 | } | ||
| 815 | |||
| 816 | static struct dma_async_tx_descriptor * | ||
| 817 | iop_adma_prep_dma_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, | ||
| 818 | unsigned int src_cnt, const unsigned char *scf, | ||
| 819 | size_t len, enum sum_check_flags *pqres, | ||
| 820 | unsigned long flags) | ||
| 821 | { | ||
| 822 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); | ||
| 823 | struct iop_adma_desc_slot *sw_desc, *g; | ||
| 824 | int slot_cnt, slots_per_op; | ||
| 825 | |||
| 826 | if (unlikely(!len)) | ||
| 827 | return NULL; | ||
| 828 | BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT); | ||
| 829 | |||
| 830 | dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n", | ||
| 831 | __func__, src_cnt, len); | ||
| 832 | |||
| 833 | spin_lock_bh(&iop_chan->lock); | ||
| 834 | slot_cnt = iop_chan_pq_zero_sum_slot_count(len, src_cnt + 2, &slots_per_op); | ||
| 835 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); | ||
| 836 | if (sw_desc) { | ||
| 837 | /* for validate operations p and q are tagged onto the | ||
| 838 | * end of the source list | ||
| 839 | */ | ||
| 840 | int pq_idx = src_cnt; | ||
| 841 | |||
| 842 | g = sw_desc->group_head; | ||
| 843 | iop_desc_init_pq_zero_sum(g, src_cnt+2, flags); | ||
| 844 | iop_desc_set_pq_zero_sum_byte_count(g, len); | ||
| 845 | g->pq_check_result = pqres; | ||
| 846 | pr_debug("\t%s: g->pq_check_result: %p\n", | ||
| 847 | __func__, g->pq_check_result); | ||
| 848 | sw_desc->unmap_src_cnt = src_cnt+2; | ||
| 849 | sw_desc->unmap_len = len; | ||
| 850 | sw_desc->async_tx.flags = flags; | ||
| 851 | while (src_cnt--) | ||
| 852 | iop_desc_set_pq_zero_sum_src_addr(g, src_cnt, | ||
| 853 | src[src_cnt], | ||
| 854 | scf[src_cnt]); | ||
| 855 | iop_desc_set_pq_zero_sum_addr(g, pq_idx, src); | ||
| 856 | } | ||
| 857 | spin_unlock_bh(&iop_chan->lock); | ||
| 858 | |||
| 859 | return sw_desc ? &sw_desc->async_tx : NULL; | ||
| 860 | } | ||
| 861 | |||
| 699 | static void iop_adma_free_chan_resources(struct dma_chan *chan) | 862 | static void iop_adma_free_chan_resources(struct dma_chan *chan) |
| 700 | { | 863 | { |
| 701 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); | 864 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); |
| @@ -1105,6 +1268,170 @@ out: | |||
| 1105 | return err; | 1268 | return err; |
| 1106 | } | 1269 | } |
| 1107 | 1270 | ||
| 1271 | #ifdef CONFIG_MD_RAID6_PQ | ||
| 1272 | static int __devinit | ||
| 1273 | iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device) | ||
| 1274 | { | ||
| 1275 | /* combined sources, software pq results, and extra hw pq results */ | ||
| 1276 | struct page *pq[IOP_ADMA_NUM_SRC_TEST+2+2]; | ||
| 1277 | /* ptr to the extra hw pq buffers defined above */ | ||
| 1278 | struct page **pq_hw = &pq[IOP_ADMA_NUM_SRC_TEST+2]; | ||
| 1279 | /* address conversion buffers (dma_map / page_address) */ | ||
| 1280 | void *pq_sw[IOP_ADMA_NUM_SRC_TEST+2]; | ||
| 1281 | dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST]; | ||
| 1282 | dma_addr_t pq_dest[2]; | ||
| 1283 | |||
| 1284 | int i; | ||
| 1285 | struct dma_async_tx_descriptor *tx; | ||
| 1286 | struct dma_chan *dma_chan; | ||
| 1287 | dma_cookie_t cookie; | ||
| 1288 | u32 zero_sum_result; | ||
| 1289 | int err = 0; | ||
| 1290 | struct device *dev; | ||
| 1291 | |||
| 1292 | dev_dbg(device->common.dev, "%s\n", __func__); | ||
| 1293 | |||
| 1294 | for (i = 0; i < ARRAY_SIZE(pq); i++) { | ||
| 1295 | pq[i] = alloc_page(GFP_KERNEL); | ||
| 1296 | if (!pq[i]) { | ||
| 1297 | while (i--) | ||
| 1298 | __free_page(pq[i]); | ||
| 1299 | return -ENOMEM; | ||
| 1300 | } | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | /* Fill in src buffers */ | ||
| 1304 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) { | ||
| 1305 | pq_sw[i] = page_address(pq[i]); | ||
| 1306 | memset(pq_sw[i], 0x11111111 * (1<<i), PAGE_SIZE); | ||
| 1307 | } | ||
| 1308 | pq_sw[i] = page_address(pq[i]); | ||
| 1309 | pq_sw[i+1] = page_address(pq[i+1]); | ||
| 1310 | |||
| 1311 | dma_chan = container_of(device->common.channels.next, | ||
| 1312 | struct dma_chan, | ||
| 1313 | device_node); | ||
| 1314 | if (iop_adma_alloc_chan_resources(dma_chan) < 1) { | ||
| 1315 | err = -ENODEV; | ||
| 1316 | goto out; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | dev = dma_chan->device->dev; | ||
| 1320 | |||
| 1321 | /* initialize the dests */ | ||
| 1322 | memset(page_address(pq_hw[0]), 0 , PAGE_SIZE); | ||
| 1323 | memset(page_address(pq_hw[1]), 0 , PAGE_SIZE); | ||
| 1324 | |||
| 1325 | /* test pq */ | ||
| 1326 | pq_dest[0] = dma_map_page(dev, pq_hw[0], 0, PAGE_SIZE, DMA_FROM_DEVICE); | ||
| 1327 | pq_dest[1] = dma_map_page(dev, pq_hw[1], 0, PAGE_SIZE, DMA_FROM_DEVICE); | ||
| 1328 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) | ||
| 1329 | pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE, | ||
| 1330 | DMA_TO_DEVICE); | ||
| 1331 | |||
| 1332 | tx = iop_adma_prep_dma_pq(dma_chan, pq_dest, pq_src, | ||
| 1333 | IOP_ADMA_NUM_SRC_TEST, (u8 *)raid6_gfexp, | ||
| 1334 | PAGE_SIZE, | ||
| 1335 | DMA_PREP_INTERRUPT | | ||
| 1336 | DMA_CTRL_ACK); | ||
| 1337 | |||
| 1338 | cookie = iop_adma_tx_submit(tx); | ||
| 1339 | iop_adma_issue_pending(dma_chan); | ||
| 1340 | msleep(8); | ||
| 1341 | |||
| 1342 | if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != | ||
| 1343 | DMA_SUCCESS) { | ||
| 1344 | dev_err(dev, "Self-test pq timed out, disabling\n"); | ||
| 1345 | err = -ENODEV; | ||
| 1346 | goto free_resources; | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | raid6_call.gen_syndrome(IOP_ADMA_NUM_SRC_TEST+2, PAGE_SIZE, pq_sw); | ||
| 1350 | |||
| 1351 | if (memcmp(pq_sw[IOP_ADMA_NUM_SRC_TEST], | ||
| 1352 | page_address(pq_hw[0]), PAGE_SIZE) != 0) { | ||
| 1353 | dev_err(dev, "Self-test p failed compare, disabling\n"); | ||
| 1354 | err = -ENODEV; | ||
| 1355 | goto free_resources; | ||
| 1356 | } | ||
| 1357 | if (memcmp(pq_sw[IOP_ADMA_NUM_SRC_TEST+1], | ||
| 1358 | page_address(pq_hw[1]), PAGE_SIZE) != 0) { | ||
| 1359 | dev_err(dev, "Self-test q failed compare, disabling\n"); | ||
| 1360 | err = -ENODEV; | ||
| 1361 | goto free_resources; | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | /* test correct zero sum using the software generated pq values */ | ||
| 1365 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 2; i++) | ||
| 1366 | pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE, | ||
| 1367 | DMA_TO_DEVICE); | ||
| 1368 | |||
| 1369 | zero_sum_result = ~0; | ||
| 1370 | tx = iop_adma_prep_dma_pq_val(dma_chan, &pq_src[IOP_ADMA_NUM_SRC_TEST], | ||
| 1371 | pq_src, IOP_ADMA_NUM_SRC_TEST, | ||
| 1372 | raid6_gfexp, PAGE_SIZE, &zero_sum_result, | ||
| 1373 | DMA_PREP_INTERRUPT|DMA_CTRL_ACK); | ||
| 1374 | |||
| 1375 | cookie = iop_adma_tx_submit(tx); | ||
| 1376 | iop_adma_issue_pending(dma_chan); | ||
| 1377 | msleep(8); | ||
| 1378 | |||
| 1379 | if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != | ||
| 1380 | DMA_SUCCESS) { | ||
| 1381 | dev_err(dev, "Self-test pq-zero-sum timed out, disabling\n"); | ||
| 1382 | err = -ENODEV; | ||
| 1383 | goto free_resources; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | if (zero_sum_result != 0) { | ||
| 1387 | dev_err(dev, "Self-test pq-zero-sum failed to validate: %x\n", | ||
| 1388 | zero_sum_result); | ||
| 1389 | err = -ENODEV; | ||
| 1390 | goto free_resources; | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | /* test incorrect zero sum */ | ||
| 1394 | i = IOP_ADMA_NUM_SRC_TEST; | ||
| 1395 | memset(pq_sw[i] + 100, 0, 100); | ||
| 1396 | memset(pq_sw[i+1] + 200, 0, 200); | ||
| 1397 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 2; i++) | ||
| 1398 | pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE, | ||
| 1399 | DMA_TO_DEVICE); | ||
| 1400 | |||
| 1401 | zero_sum_result = 0; | ||
| 1402 | tx = iop_adma_prep_dma_pq_val(dma_chan, &pq_src[IOP_ADMA_NUM_SRC_TEST], | ||
| 1403 | pq_src, IOP_ADMA_NUM_SRC_TEST, | ||
| 1404 | raid6_gfexp, PAGE_SIZE, &zero_sum_result, | ||
| 1405 | DMA_PREP_INTERRUPT|DMA_CTRL_ACK); | ||
| 1406 | |||
| 1407 | cookie = iop_adma_tx_submit(tx); | ||
| 1408 | iop_adma_issue_pending(dma_chan); | ||
| 1409 | msleep(8); | ||
| 1410 | |||
| 1411 | if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != | ||
| 1412 | DMA_SUCCESS) { | ||
| 1413 | dev_err(dev, "Self-test !pq-zero-sum timed out, disabling\n"); | ||
| 1414 | err = -ENODEV; | ||
| 1415 | goto free_resources; | ||
| 1416 | } | ||
| 1417 | |||
| 1418 | if (zero_sum_result != (SUM_CHECK_P_RESULT | SUM_CHECK_Q_RESULT)) { | ||
| 1419 | dev_err(dev, "Self-test !pq-zero-sum failed to validate: %x\n", | ||
| 1420 | zero_sum_result); | ||
| 1421 | err = -ENODEV; | ||
| 1422 | goto free_resources; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | free_resources: | ||
| 1426 | iop_adma_free_chan_resources(dma_chan); | ||
| 1427 | out: | ||
| 1428 | i = ARRAY_SIZE(pq); | ||
| 1429 | while (i--) | ||
| 1430 | __free_page(pq[i]); | ||
| 1431 | return err; | ||
| 1432 | } | ||
| 1433 | #endif | ||
| 1434 | |||
| 1108 | static int __devexit iop_adma_remove(struct platform_device *dev) | 1435 | static int __devexit iop_adma_remove(struct platform_device *dev) |
| 1109 | { | 1436 | { |
| 1110 | struct iop_adma_device *device = platform_get_drvdata(dev); | 1437 | struct iop_adma_device *device = platform_get_drvdata(dev); |
| @@ -1195,6 +1522,13 @@ static int __devinit iop_adma_probe(struct platform_device *pdev) | |||
| 1195 | if (dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask)) | 1522 | if (dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask)) |
| 1196 | dma_dev->device_prep_dma_xor_val = | 1523 | dma_dev->device_prep_dma_xor_val = |
| 1197 | iop_adma_prep_dma_xor_val; | 1524 | iop_adma_prep_dma_xor_val; |
| 1525 | if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { | ||
| 1526 | dma_set_maxpq(dma_dev, iop_adma_get_max_pq(), 0); | ||
| 1527 | dma_dev->device_prep_dma_pq = iop_adma_prep_dma_pq; | ||
| 1528 | } | ||
| 1529 | if (dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask)) | ||
| 1530 | dma_dev->device_prep_dma_pq_val = | ||
| 1531 | iop_adma_prep_dma_pq_val; | ||
| 1198 | if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask)) | 1532 | if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask)) |
| 1199 | dma_dev->device_prep_dma_interrupt = | 1533 | dma_dev->device_prep_dma_interrupt = |
| 1200 | iop_adma_prep_dma_interrupt; | 1534 | iop_adma_prep_dma_interrupt; |
| @@ -1248,13 +1582,28 @@ static int __devinit iop_adma_probe(struct platform_device *pdev) | |||
| 1248 | } | 1582 | } |
| 1249 | 1583 | ||
| 1250 | if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) || | 1584 | if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) || |
| 1251 | dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) { | 1585 | dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) { |
| 1252 | ret = iop_adma_xor_val_self_test(adev); | 1586 | ret = iop_adma_xor_val_self_test(adev); |
| 1253 | dev_dbg(&pdev->dev, "xor self test returned %d\n", ret); | 1587 | dev_dbg(&pdev->dev, "xor self test returned %d\n", ret); |
| 1254 | if (ret) | 1588 | if (ret) |
| 1255 | goto err_free_iop_chan; | 1589 | goto err_free_iop_chan; |
| 1256 | } | 1590 | } |
| 1257 | 1591 | ||
| 1592 | if (dma_has_cap(DMA_PQ, dma_dev->cap_mask) && | ||
| 1593 | dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask)) { | ||
| 1594 | #ifdef CONFIG_MD_RAID6_PQ | ||
| 1595 | ret = iop_adma_pq_zero_sum_self_test(adev); | ||
| 1596 | dev_dbg(&pdev->dev, "pq self test returned %d\n", ret); | ||
| 1597 | #else | ||
| 1598 | /* can not test raid6, so do not publish capability */ | ||
| 1599 | dma_cap_clear(DMA_PQ, dma_dev->cap_mask); | ||
| 1600 | dma_cap_clear(DMA_PQ_VAL, dma_dev->cap_mask); | ||
| 1601 | ret = 0; | ||
| 1602 | #endif | ||
| 1603 | if (ret) | ||
| 1604 | goto err_free_iop_chan; | ||
| 1605 | } | ||
| 1606 | |||
| 1258 | dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: " | 1607 | dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: " |
| 1259 | "( %s%s%s%s%s%s%s)\n", | 1608 | "( %s%s%s%s%s%s%s)\n", |
| 1260 | dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "", | 1609 | dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "", |
