diff options
Diffstat (limited to 'drivers/dma/ioat/dma_v2.c')
-rw-r--r-- | drivers/dma/ioat/dma_v2.c | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 8f1f7f05deaa..5f7a500e18d0 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c | |||
@@ -239,20 +239,50 @@ void __ioat2_restart_chan(struct ioat2_dma_chan *ioat) | |||
239 | __ioat2_start_null_desc(ioat); | 239 | __ioat2_start_null_desc(ioat); |
240 | } | 240 | } |
241 | 241 | ||
242 | static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) | 242 | int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo) |
243 | { | 243 | { |
244 | struct ioat_chan_common *chan = &ioat->base; | 244 | unsigned long end = jiffies + tmo; |
245 | unsigned long phys_complete; | 245 | int err = 0; |
246 | u32 status; | 246 | u32 status; |
247 | 247 | ||
248 | status = ioat_chansts(chan); | 248 | status = ioat_chansts(chan); |
249 | if (is_ioat_active(status) || is_ioat_idle(status)) | 249 | if (is_ioat_active(status) || is_ioat_idle(status)) |
250 | ioat_suspend(chan); | 250 | ioat_suspend(chan); |
251 | while (is_ioat_active(status) || is_ioat_idle(status)) { | 251 | while (is_ioat_active(status) || is_ioat_idle(status)) { |
252 | if (end && time_after(jiffies, end)) { | ||
253 | err = -ETIMEDOUT; | ||
254 | break; | ||
255 | } | ||
252 | status = ioat_chansts(chan); | 256 | status = ioat_chansts(chan); |
253 | cpu_relax(); | 257 | cpu_relax(); |
254 | } | 258 | } |
255 | 259 | ||
260 | return err; | ||
261 | } | ||
262 | |||
263 | int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo) | ||
264 | { | ||
265 | unsigned long end = jiffies + tmo; | ||
266 | int err = 0; | ||
267 | |||
268 | ioat_reset(chan); | ||
269 | while (ioat_reset_pending(chan)) { | ||
270 | if (end && time_after(jiffies, end)) { | ||
271 | err = -ETIMEDOUT; | ||
272 | break; | ||
273 | } | ||
274 | cpu_relax(); | ||
275 | } | ||
276 | |||
277 | return err; | ||
278 | } | ||
279 | |||
280 | static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) | ||
281 | { | ||
282 | struct ioat_chan_common *chan = &ioat->base; | ||
283 | unsigned long phys_complete; | ||
284 | |||
285 | ioat2_quiesce(chan, 0); | ||
256 | if (ioat_cleanup_preamble(chan, &phys_complete)) | 286 | if (ioat_cleanup_preamble(chan, &phys_complete)) |
257 | __cleanup(ioat, phys_complete); | 287 | __cleanup(ioat, phys_complete); |
258 | 288 | ||
@@ -318,6 +348,19 @@ void ioat2_timer_event(unsigned long data) | |||
318 | spin_unlock_bh(&chan->cleanup_lock); | 348 | spin_unlock_bh(&chan->cleanup_lock); |
319 | } | 349 | } |
320 | 350 | ||
351 | static int ioat2_reset_hw(struct ioat_chan_common *chan) | ||
352 | { | ||
353 | /* throw away whatever the channel was doing and get it initialized */ | ||
354 | u32 chanerr; | ||
355 | |||
356 | ioat2_quiesce(chan, msecs_to_jiffies(100)); | ||
357 | |||
358 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | ||
359 | writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); | ||
360 | |||
361 | return ioat2_reset_sync(chan, msecs_to_jiffies(200)); | ||
362 | } | ||
363 | |||
321 | /** | 364 | /** |
322 | * ioat2_enumerate_channels - find and initialize the device's channels | 365 | * ioat2_enumerate_channels - find and initialize the device's channels |
323 | * @device: the device to be enumerated | 366 | * @device: the device to be enumerated |
@@ -360,6 +403,10 @@ int ioat2_enumerate_channels(struct ioatdma_device *device) | |||
360 | (unsigned long) ioat); | 403 | (unsigned long) ioat); |
361 | ioat->xfercap_log = xfercap_log; | 404 | ioat->xfercap_log = xfercap_log; |
362 | spin_lock_init(&ioat->ring_lock); | 405 | spin_lock_init(&ioat->ring_lock); |
406 | if (device->reset_hw(&ioat->base)) { | ||
407 | i = 0; | ||
408 | break; | ||
409 | } | ||
363 | } | 410 | } |
364 | dma->chancnt = i; | 411 | dma->chancnt = i; |
365 | return i; | 412 | return i; |
@@ -467,7 +514,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) | |||
467 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); | 514 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); |
468 | struct ioat_chan_common *chan = &ioat->base; | 515 | struct ioat_chan_common *chan = &ioat->base; |
469 | struct ioat_ring_ent **ring; | 516 | struct ioat_ring_ent **ring; |
470 | u32 chanerr; | ||
471 | int order; | 517 | int order; |
472 | 518 | ||
473 | /* have we already been set up? */ | 519 | /* have we already been set up? */ |
@@ -477,12 +523,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) | |||
477 | /* Setup register to interrupt and write completion status on error */ | 523 | /* Setup register to interrupt and write completion status on error */ |
478 | writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET); | 524 | writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET); |
479 | 525 | ||
480 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | ||
481 | if (chanerr) { | ||
482 | dev_err(to_dev(chan), "CHANERR = %x, clearing\n", chanerr); | ||
483 | writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); | ||
484 | } | ||
485 | |||
486 | /* allocate a completion writeback area */ | 526 | /* allocate a completion writeback area */ |
487 | /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ | 527 | /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ |
488 | chan->completion = pci_pool_alloc(chan->device->completion_pool, | 528 | chan->completion = pci_pool_alloc(chan->device->completion_pool, |
@@ -746,13 +786,7 @@ void ioat2_free_chan_resources(struct dma_chan *c) | |||
746 | tasklet_disable(&chan->cleanup_task); | 786 | tasklet_disable(&chan->cleanup_task); |
747 | del_timer_sync(&chan->timer); | 787 | del_timer_sync(&chan->timer); |
748 | device->cleanup_tasklet((unsigned long) ioat); | 788 | device->cleanup_tasklet((unsigned long) ioat); |
749 | 789 | device->reset_hw(chan); | |
750 | /* Delay 100ms after reset to allow internal DMA logic to quiesce | ||
751 | * before removing DMA descriptor resources. | ||
752 | */ | ||
753 | writeb(IOAT_CHANCMD_RESET, | ||
754 | chan->reg_base + IOAT_CHANCMD_OFFSET(chan->device->version)); | ||
755 | mdelay(100); | ||
756 | 790 | ||
757 | spin_lock_bh(&ioat->ring_lock); | 791 | spin_lock_bh(&ioat->ring_lock); |
758 | descs = ioat2_ring_space(ioat); | 792 | descs = ioat2_ring_space(ioat); |
@@ -839,6 +873,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) | |||
839 | int err; | 873 | int err; |
840 | 874 | ||
841 | device->enumerate_channels = ioat2_enumerate_channels; | 875 | device->enumerate_channels = ioat2_enumerate_channels; |
876 | device->reset_hw = ioat2_reset_hw; | ||
842 | device->cleanup_tasklet = ioat2_cleanup_tasklet; | 877 | device->cleanup_tasklet = ioat2_cleanup_tasklet; |
843 | device->timer_fn = ioat2_timer_event; | 878 | device->timer_fn = ioat2_timer_event; |
844 | device->self_test = ioat_dma_self_test; | 879 | device->self_test = ioat_dma_self_test; |