diff options
-rw-r--r-- | drivers/dma/Kconfig | 2 | ||||
-rw-r--r-- | drivers/dma/ioat/dma.h | 1 | ||||
-rw-r--r-- | drivers/dma/ioat/dma_v3.c | 134 | ||||
-rw-r--r-- | drivers/dma/ioat/registers.h | 2 |
4 files changed, 125 insertions, 14 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index aeaea32bcfda..d5c58e839b27 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -63,8 +63,6 @@ config INTEL_IOATDMA | |||
63 | depends on PCI && X86 | 63 | depends on PCI && X86 |
64 | select DMA_ENGINE | 64 | select DMA_ENGINE |
65 | select DCA | 65 | select DCA |
66 | select ASYNC_TX_DISABLE_PQ_VAL_DMA | ||
67 | select ASYNC_TX_DISABLE_XOR_VAL_DMA | ||
68 | help | 66 | help |
69 | Enable support for the Intel(R) I/OAT DMA engine present | 67 | Enable support for the Intel(R) I/OAT DMA engine present |
70 | in recent Intel Xeon chipsets. | 68 | in recent Intel Xeon chipsets. |
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index b16902cd2684..976eba8c06c7 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) | 39 | #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) |
40 | #define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, txd) | 40 | #define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, txd) |
41 | #define to_dev(ioat_chan) (&(ioat_chan)->device->pdev->dev) | 41 | #define to_dev(ioat_chan) (&(ioat_chan)->device->pdev->dev) |
42 | #define to_pdev(ioat_chan) ((ioat_chan)->device->pdev) | ||
42 | 43 | ||
43 | #define chan_num(ch) ((int)((ch)->reg_base - (ch)->device->reg_base) / 0x80) | 44 | #define chan_num(ch) ((int)((ch)->reg_base - (ch)->device->reg_base) / 0x80) |
44 | 45 | ||
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 804522c1300a..9628ba2ff70c 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c | |||
@@ -79,6 +79,8 @@ static const u8 xor_idx_to_field[] = { 1, 4, 5, 6, 7, 0, 1, 2 }; | |||
79 | static const u8 pq_idx_to_desc = 0xf8; | 79 | static const u8 pq_idx_to_desc = 0xf8; |
80 | static const u8 pq_idx_to_field[] = { 1, 4, 5, 0, 1, 2, 4, 5 }; | 80 | static const u8 pq_idx_to_field[] = { 1, 4, 5, 0, 1, 2, 4, 5 }; |
81 | 81 | ||
82 | static void ioat3_eh(struct ioat2_dma_chan *ioat); | ||
83 | |||
82 | static dma_addr_t xor_get_src(struct ioat_raw_descriptor *descs[2], int idx) | 84 | static dma_addr_t xor_get_src(struct ioat_raw_descriptor *descs[2], int idx) |
83 | { | 85 | { |
84 | struct ioat_raw_descriptor *raw = descs[xor_idx_to_desc >> idx & 1]; | 86 | struct ioat_raw_descriptor *raw = descs[xor_idx_to_desc >> idx & 1]; |
@@ -347,6 +349,33 @@ static bool desc_has_ext(struct ioat_ring_ent *desc) | |||
347 | return false; | 349 | return false; |
348 | } | 350 | } |
349 | 351 | ||
352 | static u64 ioat3_get_current_completion(struct ioat_chan_common *chan) | ||
353 | { | ||
354 | u64 phys_complete; | ||
355 | u64 completion; | ||
356 | |||
357 | completion = *chan->completion; | ||
358 | phys_complete = ioat_chansts_to_addr(completion); | ||
359 | |||
360 | dev_dbg(to_dev(chan), "%s: phys_complete: %#llx\n", __func__, | ||
361 | (unsigned long long) phys_complete); | ||
362 | |||
363 | return phys_complete; | ||
364 | } | ||
365 | |||
366 | static bool ioat3_cleanup_preamble(struct ioat_chan_common *chan, | ||
367 | u64 *phys_complete) | ||
368 | { | ||
369 | *phys_complete = ioat3_get_current_completion(chan); | ||
370 | if (*phys_complete == chan->last_completion) | ||
371 | return false; | ||
372 | |||
373 | clear_bit(IOAT_COMPLETION_ACK, &chan->state); | ||
374 | mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); | ||
375 | |||
376 | return true; | ||
377 | } | ||
378 | |||
350 | /** | 379 | /** |
351 | * __cleanup - reclaim used descriptors | 380 | * __cleanup - reclaim used descriptors |
352 | * @ioat: channel (ring) to clean | 381 | * @ioat: channel (ring) to clean |
@@ -365,6 +394,16 @@ static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete) | |||
365 | dev_dbg(to_dev(chan), "%s: head: %#x tail: %#x issued: %#x\n", | 394 | dev_dbg(to_dev(chan), "%s: head: %#x tail: %#x issued: %#x\n", |
366 | __func__, ioat->head, ioat->tail, ioat->issued); | 395 | __func__, ioat->head, ioat->tail, ioat->issued); |
367 | 396 | ||
397 | /* | ||
398 | * At restart of the channel, the completion address and the | ||
399 | * channel status will be 0 due to starting a new chain. Since | ||
400 | * it's new chain and the first descriptor "fails", there is | ||
401 | * nothing to clean up. We do not want to reap the entire submitted | ||
402 | * chain due to this 0 address value and then BUG. | ||
403 | */ | ||
404 | if (!phys_complete) | ||
405 | return; | ||
406 | |||
368 | active = ioat2_ring_active(ioat); | 407 | active = ioat2_ring_active(ioat); |
369 | for (i = 0; i < active && !seen_current; i++) { | 408 | for (i = 0; i < active && !seen_current; i++) { |
370 | struct dma_async_tx_descriptor *tx; | 409 | struct dma_async_tx_descriptor *tx; |
@@ -411,11 +450,22 @@ static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete) | |||
411 | static void ioat3_cleanup(struct ioat2_dma_chan *ioat) | 450 | static void ioat3_cleanup(struct ioat2_dma_chan *ioat) |
412 | { | 451 | { |
413 | struct ioat_chan_common *chan = &ioat->base; | 452 | struct ioat_chan_common *chan = &ioat->base; |
414 | dma_addr_t phys_complete; | 453 | u64 phys_complete; |
415 | 454 | ||
416 | spin_lock_bh(&chan->cleanup_lock); | 455 | spin_lock_bh(&chan->cleanup_lock); |
417 | if (ioat_cleanup_preamble(chan, &phys_complete)) | 456 | |
457 | if (ioat3_cleanup_preamble(chan, &phys_complete)) | ||
418 | __cleanup(ioat, phys_complete); | 458 | __cleanup(ioat, phys_complete); |
459 | |||
460 | if (is_ioat_halted(*chan->completion)) { | ||
461 | u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | ||
462 | |||
463 | if (chanerr & IOAT_CHANERR_HANDLE_MASK) { | ||
464 | mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT); | ||
465 | ioat3_eh(ioat); | ||
466 | } | ||
467 | } | ||
468 | |||
419 | spin_unlock_bh(&chan->cleanup_lock); | 469 | spin_unlock_bh(&chan->cleanup_lock); |
420 | } | 470 | } |
421 | 471 | ||
@@ -430,15 +480,77 @@ static void ioat3_cleanup_event(unsigned long data) | |||
430 | static void ioat3_restart_channel(struct ioat2_dma_chan *ioat) | 480 | static void ioat3_restart_channel(struct ioat2_dma_chan *ioat) |
431 | { | 481 | { |
432 | struct ioat_chan_common *chan = &ioat->base; | 482 | struct ioat_chan_common *chan = &ioat->base; |
433 | dma_addr_t phys_complete; | 483 | u64 phys_complete; |
434 | 484 | ||
435 | ioat2_quiesce(chan, 0); | 485 | ioat2_quiesce(chan, 0); |
436 | if (ioat_cleanup_preamble(chan, &phys_complete)) | 486 | if (ioat3_cleanup_preamble(chan, &phys_complete)) |
437 | __cleanup(ioat, phys_complete); | 487 | __cleanup(ioat, phys_complete); |
438 | 488 | ||
439 | __ioat2_restart_chan(ioat); | 489 | __ioat2_restart_chan(ioat); |
440 | } | 490 | } |
441 | 491 | ||
492 | static void ioat3_eh(struct ioat2_dma_chan *ioat) | ||
493 | { | ||
494 | struct ioat_chan_common *chan = &ioat->base; | ||
495 | struct pci_dev *pdev = to_pdev(chan); | ||
496 | struct ioat_dma_descriptor *hw; | ||
497 | u64 phys_complete; | ||
498 | struct ioat_ring_ent *desc; | ||
499 | u32 err_handled = 0; | ||
500 | u32 chanerr_int; | ||
501 | u32 chanerr; | ||
502 | |||
503 | /* cleanup so tail points to descriptor that caused the error */ | ||
504 | if (ioat3_cleanup_preamble(chan, &phys_complete)) | ||
505 | __cleanup(ioat, phys_complete); | ||
506 | |||
507 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | ||
508 | pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr_int); | ||
509 | |||
510 | dev_dbg(to_dev(chan), "%s: error = %x:%x\n", | ||
511 | __func__, chanerr, chanerr_int); | ||
512 | |||
513 | desc = ioat2_get_ring_ent(ioat, ioat->tail); | ||
514 | hw = desc->hw; | ||
515 | dump_desc_dbg(ioat, desc); | ||
516 | |||
517 | switch (hw->ctl_f.op) { | ||
518 | case IOAT_OP_XOR_VAL: | ||
519 | if (chanerr & IOAT_CHANERR_XOR_P_OR_CRC_ERR) { | ||
520 | *desc->result |= SUM_CHECK_P_RESULT; | ||
521 | err_handled |= IOAT_CHANERR_XOR_P_OR_CRC_ERR; | ||
522 | } | ||
523 | break; | ||
524 | case IOAT_OP_PQ_VAL: | ||
525 | if (chanerr & IOAT_CHANERR_XOR_P_OR_CRC_ERR) { | ||
526 | *desc->result |= SUM_CHECK_P_RESULT; | ||
527 | err_handled |= IOAT_CHANERR_XOR_P_OR_CRC_ERR; | ||
528 | } | ||
529 | if (chanerr & IOAT_CHANERR_XOR_Q_ERR) { | ||
530 | *desc->result |= SUM_CHECK_Q_RESULT; | ||
531 | err_handled |= IOAT_CHANERR_XOR_Q_ERR; | ||
532 | } | ||
533 | break; | ||
534 | } | ||
535 | |||
536 | /* fault on unhandled error or spurious halt */ | ||
537 | if (chanerr ^ err_handled || chanerr == 0) { | ||
538 | dev_err(to_dev(chan), "%s: fatal error (%x:%x)\n", | ||
539 | __func__, chanerr, err_handled); | ||
540 | BUG(); | ||
541 | } | ||
542 | |||
543 | writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); | ||
544 | pci_write_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, chanerr_int); | ||
545 | |||
546 | /* mark faulting descriptor as complete */ | ||
547 | *chan->completion = desc->txd.phys; | ||
548 | |||
549 | spin_lock_bh(&ioat->prep_lock); | ||
550 | ioat3_restart_channel(ioat); | ||
551 | spin_unlock_bh(&ioat->prep_lock); | ||
552 | } | ||
553 | |||
442 | static void check_active(struct ioat2_dma_chan *ioat) | 554 | static void check_active(struct ioat2_dma_chan *ioat) |
443 | { | 555 | { |
444 | struct ioat_chan_common *chan = &ioat->base; | 556 | struct ioat_chan_common *chan = &ioat->base; |
@@ -1441,15 +1553,13 @@ int ioat3_dma_probe(struct ioatdma_device *device, int dca) | |||
1441 | device->cleanup_fn = ioat3_cleanup_event; | 1553 | device->cleanup_fn = ioat3_cleanup_event; |
1442 | device->timer_fn = ioat3_timer_event; | 1554 | device->timer_fn = ioat3_timer_event; |
1443 | 1555 | ||
1444 | #ifdef CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA | 1556 | if (is_xeon_cb32(pdev)) { |
1445 | dma_cap_clear(DMA_PQ_VAL, dma->cap_mask); | 1557 | dma_cap_clear(DMA_XOR_VAL, dma->cap_mask); |
1446 | dma->device_prep_dma_pq_val = NULL; | 1558 | dma->device_prep_dma_xor_val = NULL; |
1447 | #endif | ||
1448 | 1559 | ||
1449 | #ifdef CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA | 1560 | dma_cap_clear(DMA_PQ_VAL, dma->cap_mask); |
1450 | dma_cap_clear(DMA_XOR_VAL, dma->cap_mask); | 1561 | dma->device_prep_dma_pq_val = NULL; |
1451 | dma->device_prep_dma_xor_val = NULL; | 1562 | } |
1452 | #endif | ||
1453 | 1563 | ||
1454 | err = ioat_probe(device); | 1564 | err = ioat_probe(device); |
1455 | if (err) | 1565 | if (err) |
diff --git a/drivers/dma/ioat/registers.h b/drivers/dma/ioat/registers.h index 1391798542b6..c1ad1946809e 100644 --- a/drivers/dma/ioat/registers.h +++ b/drivers/dma/ioat/registers.h | |||
@@ -93,6 +93,8 @@ | |||
93 | #define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004 | 93 | #define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004 |
94 | #define IOAT_CHANCTRL_INT_REARM 0x0001 | 94 | #define IOAT_CHANCTRL_INT_REARM 0x0001 |
95 | #define IOAT_CHANCTRL_RUN (IOAT_CHANCTRL_INT_REARM |\ | 95 | #define IOAT_CHANCTRL_RUN (IOAT_CHANCTRL_INT_REARM |\ |
96 | IOAT_CHANCTRL_ERR_INT_EN |\ | ||
97 | IOAT_CHANCTRL_ERR_COMPLETION_EN |\ | ||
96 | IOAT_CHANCTRL_ANY_ERR_ABORT_EN) | 98 | IOAT_CHANCTRL_ANY_ERR_ABORT_EN) |
97 | 99 | ||
98 | #define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatibility */ | 100 | #define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatibility */ |