diff options
Diffstat (limited to 'drivers/dma/ioat/dma_v3.c')
| -rw-r--r-- | drivers/dma/ioat/dma_v3.c | 111 |
1 files changed, 63 insertions, 48 deletions
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index e52cf1eb6839..570dd6320c32 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c | |||
| @@ -342,61 +342,22 @@ static void ioat3_restart_channel(struct ioat2_dma_chan *ioat) | |||
| 342 | __ioat2_restart_chan(ioat); | 342 | __ioat2_restart_chan(ioat); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | static void ioat3_timer_event(unsigned long data) | 345 | static void check_active(struct ioat2_dma_chan *ioat) |
| 346 | { | 346 | { |
| 347 | struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data); | ||
| 348 | struct ioat_chan_common *chan = &ioat->base; | 347 | struct ioat_chan_common *chan = &ioat->base; |
| 349 | 348 | ||
| 350 | if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) { | 349 | if (ioat2_ring_active(ioat)) { |
| 351 | dma_addr_t phys_complete; | 350 | mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); |
| 352 | u64 status; | 351 | return; |
| 353 | 352 | } | |
| 354 | status = ioat_chansts(chan); | ||
| 355 | |||
| 356 | /* when halted due to errors check for channel | ||
| 357 | * programming errors before advancing the completion state | ||
| 358 | */ | ||
| 359 | if (is_ioat_halted(status)) { | ||
| 360 | u32 chanerr; | ||
| 361 | |||
| 362 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | ||
| 363 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", | ||
| 364 | __func__, chanerr); | ||
| 365 | if (test_bit(IOAT_RUN, &chan->state)) | ||
| 366 | BUG_ON(is_ioat_bug(chanerr)); | ||
| 367 | else /* we never got off the ground */ | ||
| 368 | return; | ||
| 369 | } | ||
| 370 | |||
| 371 | /* if we haven't made progress and we have already | ||
| 372 | * acknowledged a pending completion once, then be more | ||
| 373 | * forceful with a restart | ||
| 374 | */ | ||
| 375 | spin_lock_bh(&chan->cleanup_lock); | ||
| 376 | if (ioat_cleanup_preamble(chan, &phys_complete)) | ||
| 377 | __cleanup(ioat, phys_complete); | ||
| 378 | else if (test_bit(IOAT_COMPLETION_ACK, &chan->state)) { | ||
| 379 | spin_lock_bh(&ioat->prep_lock); | ||
| 380 | ioat3_restart_channel(ioat); | ||
| 381 | spin_unlock_bh(&ioat->prep_lock); | ||
| 382 | } else { | ||
| 383 | set_bit(IOAT_COMPLETION_ACK, &chan->state); | ||
| 384 | mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); | ||
| 385 | } | ||
| 386 | spin_unlock_bh(&chan->cleanup_lock); | ||
| 387 | } else { | ||
| 388 | u16 active; | ||
| 389 | 353 | ||
| 354 | if (test_and_clear_bit(IOAT_CHAN_ACTIVE, &chan->state)) | ||
| 355 | mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT); | ||
| 356 | else if (ioat->alloc_order > ioat_get_alloc_order()) { | ||
| 390 | /* if the ring is idle, empty, and oversized try to step | 357 | /* if the ring is idle, empty, and oversized try to step |
| 391 | * down the size | 358 | * down the size |
| 392 | */ | 359 | */ |
| 393 | spin_lock_bh(&chan->cleanup_lock); | 360 | reshape_ring(ioat, ioat->alloc_order - 1); |
| 394 | spin_lock_bh(&ioat->prep_lock); | ||
| 395 | active = ioat2_ring_active(ioat); | ||
| 396 | if (active == 0 && ioat->alloc_order > ioat_get_alloc_order()) | ||
| 397 | reshape_ring(ioat, ioat->alloc_order-1); | ||
| 398 | spin_unlock_bh(&ioat->prep_lock); | ||
| 399 | spin_unlock_bh(&chan->cleanup_lock); | ||
| 400 | 361 | ||
| 401 | /* keep shrinking until we get back to our minimum | 362 | /* keep shrinking until we get back to our minimum |
| 402 | * default size | 363 | * default size |
| @@ -404,6 +365,60 @@ static void ioat3_timer_event(unsigned long data) | |||
| 404 | if (ioat->alloc_order > ioat_get_alloc_order()) | 365 | if (ioat->alloc_order > ioat_get_alloc_order()) |
| 405 | mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT); | 366 | mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT); |
| 406 | } | 367 | } |
| 368 | |||
| 369 | } | ||
| 370 | |||
| 371 | void ioat3_timer_event(unsigned long data) | ||
| 372 | { | ||
| 373 | struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data); | ||
| 374 | struct ioat_chan_common *chan = &ioat->base; | ||
| 375 | dma_addr_t phys_complete; | ||
| 376 | u64 status; | ||
| 377 | |||
| 378 | status = ioat_chansts(chan); | ||
| 379 | |||
| 380 | /* when halted due to errors check for channel | ||
| 381 | * programming errors before advancing the completion state | ||
| 382 | */ | ||
| 383 | if (is_ioat_halted(status)) { | ||
| 384 | u32 chanerr; | ||
| 385 | |||
| 386 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | ||
| 387 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", | ||
| 388 | __func__, chanerr); | ||
| 389 | if (test_bit(IOAT_RUN, &chan->state)) | ||
| 390 | BUG_ON(is_ioat_bug(chanerr)); | ||
| 391 | else /* we never got off the ground */ | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | |||
| 395 | /* if we haven't made progress and we have already | ||
| 396 | * acknowledged a pending completion once, then be more | ||
| 397 | * forceful with a restart | ||
| 398 | */ | ||
| 399 | spin_lock_bh(&chan->cleanup_lock); | ||
| 400 | if (ioat_cleanup_preamble(chan, &phys_complete)) | ||
| 401 | __cleanup(ioat, phys_complete); | ||
| 402 | else if (test_bit(IOAT_COMPLETION_ACK, &chan->state)) { | ||
| 403 | spin_lock_bh(&ioat->prep_lock); | ||
| 404 | ioat3_restart_channel(ioat); | ||
| 405 | spin_unlock_bh(&ioat->prep_lock); | ||
| 406 | spin_unlock_bh(&chan->cleanup_lock); | ||
| 407 | return; | ||
| 408 | } else { | ||
| 409 | set_bit(IOAT_COMPLETION_ACK, &chan->state); | ||
| 410 | mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); | ||
| 411 | } | ||
| 412 | |||
| 413 | |||
| 414 | if (ioat2_ring_active(ioat)) | ||
| 415 | mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); | ||
| 416 | else { | ||
| 417 | spin_lock_bh(&ioat->prep_lock); | ||
| 418 | check_active(ioat); | ||
| 419 | spin_unlock_bh(&ioat->prep_lock); | ||
| 420 | } | ||
| 421 | spin_unlock_bh(&chan->cleanup_lock); | ||
| 407 | } | 422 | } |
| 408 | 423 | ||
| 409 | static enum dma_status | 424 | static enum dma_status |
