aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2010-07-23 18:47:56 -0400
committerDan Williams <dan.j.williams@intel.com>2010-08-04 17:18:17 -0400
commit556ab45f9a775bfa4762bacc0a4afb5b44b067bc (patch)
tree6caf3f7c72617d50d78c4197b872fd0a22b18c99 /drivers
parent128f904ac87cb6e63921e80f378fdf9ba532c0f6 (diff)
ioat2: catch and recover from broken vtd configurations v6
On some platforms (MacPro3,1) the BIOS assigns the ioatdma device to the incorrect iommu causing faults when the driver initializes. Add a quirk to catch this misconfiguration and try falling back to untranslated operation (which works in the MacPro3,1 case). Assuming there are other platforms with misconfigured iommus teach the ioatdma driver to treat initialization failures as non-fatal (just fail the driver load and emit a warning instead of triggering a BUG_ON). This can be classified as a boot regression since 2.6.32 on affected platforms since the ioatdma module did not autoload prior to that kernel. Cc: <stable@kernel.org> Acked-by: David Woodhouse <David.Woodhouse@intel.com> Reported-by: Chris Li <lkml@chrisli.org> Tested-by: Chris Li <lkml@chrisli.org> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/ioat/dma.h1
-rw-r--r--drivers/dma/ioat/dma_v2.c24
-rw-r--r--drivers/dma/ioat/dma_v3.c5
-rw-r--r--drivers/pci/intel-iommu.c28
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
498void 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
546bool reshape_ring(struct ioat2_dma_chan *ioat, int order) 565bool 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
3032static 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}
3058DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
3059
3032static void __init init_no_remapping_devices(void) 3060static void __init init_no_remapping_devices(void)
3033{ 3061{
3034 struct dmar_drhd_unit *drhd; 3062 struct dmar_drhd_unit *drhd;