ioat(4): ioat_get_dmaengine(): Add M_WAITOK mode

Sponsored by:	EMC / Isilon Storage Division
This commit is contained in:
Conrad Meyer 2016-04-09 13:15:34 +00:00
parent 806929d514
commit 0ff814e854
4 changed files with 36 additions and 7 deletions

View File

@ -314,6 +314,9 @@ ioat_detach(device_t device)
mtx_lock(IOAT_REFLK); mtx_lock(IOAT_REFLK);
ioat->quiescing = TRUE; ioat->quiescing = TRUE;
ioat->destroying = TRUE;
wakeup(&ioat->quiescing);
ioat_channel[ioat->chan_idx] = NULL; ioat_channel[ioat->chan_idx] = NULL;
ioat_drain_locked(ioat); ioat_drain_locked(ioat);
@ -739,18 +742,40 @@ ioat_reset_hw_task(void *ctx, int pending __unused)
* User API functions * User API functions
*/ */
bus_dmaengine_t bus_dmaengine_t
ioat_get_dmaengine(uint32_t index) ioat_get_dmaengine(uint32_t index, int flags)
{ {
struct ioat_softc *sc; struct ioat_softc *ioat;
KASSERT((flags & ~(M_NOWAIT | M_WAITOK)) == 0,
("invalid flags: 0x%08x", flags));
KASSERT((flags & (M_NOWAIT | M_WAITOK)) != (M_NOWAIT | M_WAITOK),
("invalid wait | nowait"));
if (index >= ioat_channel_index) if (index >= ioat_channel_index)
return (NULL); return (NULL);
sc = ioat_channel[index]; ioat = ioat_channel[index];
if (sc == NULL || sc->quiescing) if (ioat == NULL || ioat->destroying)
return (NULL); return (NULL);
return (&ioat_get(sc, IOAT_DMAENGINE_REF)->dmaengine); if (ioat->quiescing) {
if ((flags & M_NOWAIT) != 0)
return (NULL);
mtx_lock(IOAT_REFLK);
while (ioat->quiescing && !ioat->destroying)
msleep(&ioat->quiescing, IOAT_REFLK, 0, "getdma", 0);
mtx_unlock(IOAT_REFLK);
if (ioat->destroying)
return (NULL);
}
/*
* There's a race here between the quiescing check and HW reset or
* module destroy.
*/
return (&ioat_get(ioat, IOAT_DMAENGINE_REF)->dmaengine);
} }
void void
@ -1571,6 +1596,7 @@ ioat_reset_hw(struct ioat_softc *ioat)
out: out:
mtx_lock(IOAT_REFLK); mtx_lock(IOAT_REFLK);
ioat->quiescing = FALSE; ioat->quiescing = FALSE;
wakeup(&ioat->quiescing);
mtx_unlock(IOAT_REFLK); mtx_unlock(IOAT_REFLK);
if (error == 0) if (error == 0)

View File

@ -68,8 +68,10 @@ typedef void (*bus_dmaengine_callback_t)(void *arg, int error);
/* /*
* Called first to acquire a reference to the DMA channel * Called first to acquire a reference to the DMA channel
*
* Flags may be M_WAITOK or M_NOWAIT.
*/ */
bus_dmaengine_t ioat_get_dmaengine(uint32_t channel_index); bus_dmaengine_t ioat_get_dmaengine(uint32_t channel_index, int flags);
/* Release the DMA channel */ /* Release the DMA channel */
void ioat_put_dmaengine(bus_dmaengine_t dmaengine); void ioat_put_dmaengine(bus_dmaengine_t dmaengine);

View File

@ -410,6 +410,7 @@ struct ioat_softc {
struct task reset_task; struct task reset_task;
boolean_t quiescing; boolean_t quiescing;
boolean_t destroying;
boolean_t is_resize_pending; boolean_t is_resize_pending;
boolean_t is_completion_pending; boolean_t is_completion_pending;
boolean_t is_reset_pending; boolean_t is_reset_pending;

View File

@ -388,7 +388,7 @@ ioat_dma_test(void *arg)
return; return;
} }
dmaengine = ioat_get_dmaengine(test->channel_index); dmaengine = ioat_get_dmaengine(test->channel_index, M_NOWAIT);
if (dmaengine == NULL) { if (dmaengine == NULL) {
ioat_test_log(0, "Couldn't acquire dmaengine\n"); ioat_test_log(0, "Couldn't acquire dmaengine\n");
test->status[IOAT_TEST_NO_DMA_ENGINE]++; test->status[IOAT_TEST_NO_DMA_ENGINE]++;