diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_sdma.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_sdma.c | 91 |
1 files changed, 69 insertions, 22 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c index 5918cafb880b..1974df7a9f78 100644 --- a/drivers/infiniband/hw/ipath/ipath_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_sdma.c | |||
@@ -230,7 +230,6 @@ static void dump_sdma_state(struct ipath_devdata *dd) | |||
230 | static void sdma_abort_task(unsigned long opaque) | 230 | static void sdma_abort_task(unsigned long opaque) |
231 | { | 231 | { |
232 | struct ipath_devdata *dd = (struct ipath_devdata *) opaque; | 232 | struct ipath_devdata *dd = (struct ipath_devdata *) opaque; |
233 | int kick = 0; | ||
234 | u64 status; | 233 | u64 status; |
235 | unsigned long flags; | 234 | unsigned long flags; |
236 | 235 | ||
@@ -308,30 +307,26 @@ static void sdma_abort_task(unsigned long opaque) | |||
308 | /* done with sdma state for a bit */ | 307 | /* done with sdma state for a bit */ |
309 | spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); | 308 | spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); |
310 | 309 | ||
311 | /* restart sdma engine */ | 310 | /* |
311 | * Don't restart sdma here. Wait until link is up to ACTIVE. | ||
312 | * VL15 MADs used to bring the link up use PIO, and multiple | ||
313 | * link transitions otherwise cause the sdma engine to be | ||
314 | * stopped and started multiple times. | ||
315 | * The disable is done here, including the shadow, so the | ||
316 | * state is kept consistent. | ||
317 | * See ipath_restart_sdma() for the actual starting of sdma. | ||
318 | */ | ||
312 | spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); | 319 | spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); |
313 | dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE; | 320 | dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE; |
314 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | 321 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, |
315 | dd->ipath_sendctrl); | 322 | dd->ipath_sendctrl); |
316 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | 323 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); |
317 | dd->ipath_sendctrl |= INFINIPATH_S_SDMAENABLE; | ||
318 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
319 | dd->ipath_sendctrl); | ||
320 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | ||
321 | spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); | 324 | spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); |
322 | kick = 1; | ||
323 | ipath_dbg("sdma restarted from abort\n"); | ||
324 | |||
325 | /* now clear status bits */ | ||
326 | spin_lock_irqsave(&dd->ipath_sdma_lock, flags); | ||
327 | __clear_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status); | ||
328 | __clear_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status); | ||
329 | __clear_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status); | ||
330 | 325 | ||
331 | /* make sure I see next message */ | 326 | /* make sure I see next message */ |
332 | dd->ipath_sdma_abort_jiffies = 0; | 327 | dd->ipath_sdma_abort_jiffies = 0; |
333 | 328 | ||
334 | goto unlock; | 329 | goto done; |
335 | } | 330 | } |
336 | 331 | ||
337 | resched: | 332 | resched: |
@@ -353,10 +348,8 @@ resched_noprint: | |||
353 | 348 | ||
354 | unlock: | 349 | unlock: |
355 | spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); | 350 | spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); |
356 | 351 | done: | |
357 | /* kick upper layers */ | 352 | return; |
358 | if (kick) | ||
359 | ipath_ib_piobufavail(dd->verbs_dev); | ||
360 | } | 353 | } |
361 | 354 | ||
362 | /* | 355 | /* |
@@ -481,10 +474,14 @@ int setup_sdma(struct ipath_devdata *dd) | |||
481 | tasklet_init(&dd->ipath_sdma_abort_task, sdma_abort_task, | 474 | tasklet_init(&dd->ipath_sdma_abort_task, sdma_abort_task, |
482 | (unsigned long) dd); | 475 | (unsigned long) dd); |
483 | 476 | ||
484 | /* Turn on SDMA */ | 477 | /* |
478 | * No use to turn on SDMA here, as link is probably not ACTIVE | ||
479 | * Just mark it RUNNING and enable the interrupt, and let the | ||
480 | * ipath_restart_sdma() on link transition to ACTIVE actually | ||
481 | * enable it. | ||
482 | */ | ||
485 | spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); | 483 | spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); |
486 | dd->ipath_sendctrl |= INFINIPATH_S_SDMAENABLE | | 484 | dd->ipath_sendctrl |= INFINIPATH_S_SDMAINTENABLE; |
487 | INFINIPATH_S_SDMAINTENABLE; | ||
488 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); | 485 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); |
489 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | 486 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); |
490 | __set_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status); | 487 | __set_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status); |
@@ -572,6 +569,56 @@ void teardown_sdma(struct ipath_devdata *dd) | |||
572 | sdma_descq, sdma_descq_phys); | 569 | sdma_descq, sdma_descq_phys); |
573 | } | 570 | } |
574 | 571 | ||
572 | /* | ||
573 | * [Re]start SDMA, if we use it, and it's not already OK. | ||
574 | * This is called on transition to link ACTIVE, either the first or | ||
575 | * subsequent times. | ||
576 | */ | ||
577 | void ipath_restart_sdma(struct ipath_devdata *dd) | ||
578 | { | ||
579 | unsigned long flags; | ||
580 | int needed = 1; | ||
581 | |||
582 | if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA)) | ||
583 | goto bail; | ||
584 | |||
585 | /* | ||
586 | * First, make sure we should, which is to say, | ||
587 | * check that we are "RUNNING" (not in teardown) | ||
588 | * and not "SHUTDOWN" | ||
589 | */ | ||
590 | spin_lock_irqsave(&dd->ipath_sdma_lock, flags); | ||
591 | if (!test_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status) | ||
592 | || test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) | ||
593 | needed = 0; | ||
594 | else { | ||
595 | __clear_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status); | ||
596 | __clear_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status); | ||
597 | __clear_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status); | ||
598 | } | ||
599 | spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); | ||
600 | if (!needed) { | ||
601 | ipath_dbg("invalid attempt to restart SDMA, status 0x%016llx\n", | ||
602 | dd->ipath_sdma_status); | ||
603 | goto bail; | ||
604 | } | ||
605 | spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); | ||
606 | /* | ||
607 | * First clear, just to be safe. Enable is only done | ||
608 | * in chip on 0->1 transition | ||
609 | */ | ||
610 | dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE; | ||
611 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); | ||
612 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | ||
613 | dd->ipath_sendctrl |= INFINIPATH_S_SDMAENABLE; | ||
614 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); | ||
615 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | ||
616 | spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); | ||
617 | |||
618 | bail: | ||
619 | return; | ||
620 | } | ||
621 | |||
575 | static inline void make_sdma_desc(struct ipath_devdata *dd, | 622 | static inline void make_sdma_desc(struct ipath_devdata *dd, |
576 | u64 *sdmadesc, u64 addr, u64 dwlen, u64 dwoffset) | 623 | u64 *sdmadesc, u64 addr, u64 dwlen, u64 dwoffset) |
577 | { | 624 | { |