diff options
-rw-r--r-- | drivers/dma/ioat/dma.h | 1 | ||||
-rw-r--r-- | drivers/dma/ioat/dma_v2.c | 24 | ||||
-rw-r--r-- | drivers/dma/ioat/dma_v3.c | 5 | ||||
-rw-r--r-- | drivers/pci/intel-iommu.c | 28 |
4 files changed, 55 insertions, 3 deletions
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 6d3a73b57e54..5216c8a92a21 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h | |||
@@ -97,6 +97,7 @@ struct ioat_chan_common { | |||
97 | #define IOAT_RESET_PENDING 2 | 97 | #define IOAT_RESET_PENDING 2 |
98 | #define IOAT_KOBJ_INIT_FAIL 3 | 98 | #define IOAT_KOBJ_INIT_FAIL 3 |
99 | #define IOAT_RESHAPE_PENDING 4 | 99 | #define IOAT_RESHAPE_PENDING 4 |
100 | #define IOAT_RUN 5 | ||
100 | struct timer_list timer; | 101 | struct timer_list timer; |
101 | #define COMPLETION_TIMEOUT msecs_to_jiffies(100) | 102 | #define COMPLETION_TIMEOUT msecs_to_jiffies(100) |
102 | #define IDLE_TIMEOUT msecs_to_jiffies(2000) | 103 | #define IDLE_TIMEOUT msecs_to_jiffies(2000) |
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 3c8b32a83794..216f9d383b5b 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c | |||
@@ -287,7 +287,10 @@ void ioat2_timer_event(unsigned long data) | |||
287 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | 287 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); |
288 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", | 288 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", |
289 | __func__, chanerr); | 289 | __func__, chanerr); |
290 | BUG_ON(is_ioat_bug(chanerr)); | 290 | if (test_bit(IOAT_RUN, &chan->state)) |
291 | BUG_ON(is_ioat_bug(chanerr)); | ||
292 | else /* we never got off the ground */ | ||
293 | return; | ||
291 | } | 294 | } |
292 | 295 | ||
293 | /* if we haven't made progress and we have already | 296 | /* if we haven't made progress and we have already |
@@ -492,6 +495,8 @@ static struct ioat_ring_ent **ioat2_alloc_ring(struct dma_chan *c, int order, gf | |||
492 | return ring; | 495 | return ring; |
493 | } | 496 | } |
494 | 497 | ||
498 | void ioat2_free_chan_resources(struct dma_chan *c); | ||
499 | |||
495 | /* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring | 500 | /* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring |
496 | * @chan: channel to be initialized | 501 | * @chan: channel to be initialized |
497 | */ | 502 | */ |
@@ -500,6 +505,7 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) | |||
500 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); | 505 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); |
501 | struct ioat_chan_common *chan = &ioat->base; | 506 | struct ioat_chan_common *chan = &ioat->base; |
502 | struct ioat_ring_ent **ring; | 507 | struct ioat_ring_ent **ring; |
508 | u64 status; | ||
503 | int order; | 509 | int order; |
504 | 510 | ||
505 | /* have we already been set up? */ | 511 | /* have we already been set up? */ |
@@ -540,7 +546,20 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) | |||
540 | tasklet_enable(&chan->cleanup_task); | 546 | tasklet_enable(&chan->cleanup_task); |
541 | ioat2_start_null_desc(ioat); | 547 | ioat2_start_null_desc(ioat); |
542 | 548 | ||
543 | return 1 << ioat->alloc_order; | 549 | /* check that we got off the ground */ |
550 | udelay(5); | ||
551 | status = ioat_chansts(chan); | ||
552 | if (is_ioat_active(status) || is_ioat_idle(status)) { | ||
553 | set_bit(IOAT_RUN, &chan->state); | ||
554 | return 1 << ioat->alloc_order; | ||
555 | } else { | ||
556 | u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | ||
557 | |||
558 | dev_WARN(to_dev(chan), | ||
559 | "failed to start channel chanerr: %#x\n", chanerr); | ||
560 | ioat2_free_chan_resources(c); | ||
561 | return -EFAULT; | ||
562 | } | ||
544 | } | 563 | } |
545 | 564 | ||
546 | bool reshape_ring(struct ioat2_dma_chan *ioat, int order) | 565 | bool reshape_ring(struct ioat2_dma_chan *ioat, int order) |
@@ -778,6 +797,7 @@ void ioat2_free_chan_resources(struct dma_chan *c) | |||
778 | del_timer_sync(&chan->timer); | 797 | del_timer_sync(&chan->timer); |
779 | device->cleanup_fn((unsigned long) c); | 798 | device->cleanup_fn((unsigned long) c); |
780 | device->reset_hw(chan); | 799 | device->reset_hw(chan); |
800 | clear_bit(IOAT_RUN, &chan->state); | ||
781 | 801 | ||
782 | spin_lock_bh(&chan->cleanup_lock); | 802 | spin_lock_bh(&chan->cleanup_lock); |
783 | spin_lock_bh(&ioat->prep_lock); | 803 | spin_lock_bh(&ioat->prep_lock); |
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 1cdd22e1051b..d0f499098479 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c | |||
@@ -361,7 +361,10 @@ static void ioat3_timer_event(unsigned long data) | |||
361 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | 361 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); |
362 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", | 362 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", |
363 | __func__, chanerr); | 363 | __func__, chanerr); |
364 | BUG_ON(is_ioat_bug(chanerr)); | 364 | if (test_bit(IOAT_RUN, &chan->state)) |
365 | BUG_ON(is_ioat_bug(chanerr)); | ||
366 | else /* we never got off the ground */ | ||
367 | return; | ||
365 | } | 368 | } |
366 | 369 | ||
367 | /* if we haven't made progress and we have already | 370 | /* if we haven't made progress and we have already |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 796828fce34c..90938c7a74c1 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -3029,6 +3029,34 @@ static void __init iommu_exit_mempool(void) | |||
3029 | 3029 | ||
3030 | } | 3030 | } |
3031 | 3031 | ||
3032 | static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev) | ||
3033 | { | ||
3034 | struct dmar_drhd_unit *drhd; | ||
3035 | u32 vtbar; | ||
3036 | int rc; | ||
3037 | |||
3038 | /* We know that this device on this chipset has its own IOMMU. | ||
3039 | * If we find it under a different IOMMU, then the BIOS is lying | ||
3040 | * to us. Hope that the IOMMU for this device is actually | ||
3041 | * disabled, and it needs no translation... | ||
3042 | */ | ||
3043 | rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar); | ||
3044 | if (rc) { | ||
3045 | /* "can't" happen */ | ||
3046 | dev_info(&pdev->dev, "failed to run vt-d quirk\n"); | ||
3047 | return; | ||
3048 | } | ||
3049 | vtbar &= 0xffff0000; | ||
3050 | |||
3051 | /* we know that the this iommu should be at offset 0xa000 from vtbar */ | ||
3052 | drhd = dmar_find_matched_drhd_unit(pdev); | ||
3053 | if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000, | ||
3054 | TAINT_FIRMWARE_WORKAROUND, | ||
3055 | "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n")) | ||
3056 | pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; | ||
3057 | } | ||
3058 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu); | ||
3059 | |||
3032 | static void __init init_no_remapping_devices(void) | 3060 | static void __init init_no_remapping_devices(void) |
3033 | { | 3061 | { |
3034 | struct dmar_drhd_unit *drhd; | 3062 | struct dmar_drhd_unit *drhd; |