aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
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/dma
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/dma')
-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
3 files changed, 27 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