mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
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: <[email protected]> Acked-by: David Woodhouse <[email protected]> Reported-by: Chris Li <[email protected]> Tested-by: Chris Li <[email protected]> Signed-off-by: Dan Williams <[email protected]>
This commit is contained in:
parent
128f904ac8
commit
556ab45f9a
4 changed files with 55 additions and 3 deletions
|
|
@ -97,6 +97,7 @@ struct ioat_chan_common {
|
|||
#define IOAT_RESET_PENDING 2
|
||||
#define IOAT_KOBJ_INIT_FAIL 3
|
||||
#define IOAT_RESHAPE_PENDING 4
|
||||
#define IOAT_RUN 5
|
||||
struct timer_list timer;
|
||||
#define COMPLETION_TIMEOUT msecs_to_jiffies(100)
|
||||
#define IDLE_TIMEOUT msecs_to_jiffies(2000)
|
||||
|
|
|
|||
|
|
@ -287,7 +287,10 @@ void ioat2_timer_event(unsigned long data)
|
|||
chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
|
||||
dev_err(to_dev(chan), "%s: Channel halted (%x)\n",
|
||||
__func__, chanerr);
|
||||
BUG_ON(is_ioat_bug(chanerr));
|
||||
if (test_bit(IOAT_RUN, &chan->state))
|
||||
BUG_ON(is_ioat_bug(chanerr));
|
||||
else /* we never got off the ground */
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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
|
|||
return ring;
|
||||
}
|
||||
|
||||
void ioat2_free_chan_resources(struct dma_chan *c);
|
||||
|
||||
/* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring
|
||||
* @chan: channel to be initialized
|
||||
*/
|
||||
|
|
@ -500,6 +505,7 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
|
|||
struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
|
||||
struct ioat_chan_common *chan = &ioat->base;
|
||||
struct ioat_ring_ent **ring;
|
||||
u64 status;
|
||||
int order;
|
||||
|
||||
/* have we already been set up? */
|
||||
|
|
@ -540,7 +546,20 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
|
|||
tasklet_enable(&chan->cleanup_task);
|
||||
ioat2_start_null_desc(ioat);
|
||||
|
||||
return 1 << ioat->alloc_order;
|
||||
/* check that we got off the ground */
|
||||
udelay(5);
|
||||
status = ioat_chansts(chan);
|
||||
if (is_ioat_active(status) || is_ioat_idle(status)) {
|
||||
set_bit(IOAT_RUN, &chan->state);
|
||||
return 1 << ioat->alloc_order;
|
||||
} else {
|
||||
u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
|
||||
|
||||
dev_WARN(to_dev(chan),
|
||||
"failed to start channel chanerr: %#x\n", chanerr);
|
||||
ioat2_free_chan_resources(c);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
bool reshape_ring(struct ioat2_dma_chan *ioat, int order)
|
||||
|
|
@ -778,6 +797,7 @@ void ioat2_free_chan_resources(struct dma_chan *c)
|
|||
del_timer_sync(&chan->timer);
|
||||
device->cleanup_fn((unsigned long) c);
|
||||
device->reset_hw(chan);
|
||||
clear_bit(IOAT_RUN, &chan->state);
|
||||
|
||||
spin_lock_bh(&chan->cleanup_lock);
|
||||
spin_lock_bh(&ioat->prep_lock);
|
||||
|
|
|
|||
|
|
@ -361,7 +361,10 @@ static void ioat3_timer_event(unsigned long data)
|
|||
chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
|
||||
dev_err(to_dev(chan), "%s: Channel halted (%x)\n",
|
||||
__func__, chanerr);
|
||||
BUG_ON(is_ioat_bug(chanerr));
|
||||
if (test_bit(IOAT_RUN, &chan->state))
|
||||
BUG_ON(is_ioat_bug(chanerr));
|
||||
else /* we never got off the ground */
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we haven't made progress and we have already
|
||||
|
|
|
|||
Loading…
Reference in a new issue