diff options
author | cem <cem@FreeBSD.org> | 2016-02-13 22:51:25 +0000 |
---|---|---|
committer | cem <cem@FreeBSD.org> | 2016-02-13 22:51:25 +0000 |
commit | 81a1e6341d7139ef6a6bf605fed8b7bcadd45462 (patch) | |
tree | 417cdac18aa2f77593be164600492e62c21b9f20 /sys/dev | |
parent | 0784d59f3ad5c231751ea561da1d3b7d962e10b6 (diff) | |
download | FreeBSD-src-81a1e6341d7139ef6a6bf605fed8b7bcadd45462.zip FreeBSD-src-81a1e6341d7139ef6a6bf605fed8b7bcadd45462.tar.gz |
ioat(4): On error detected in ithread, defer HW reset to taskqueue
The I/OAT HW reset process may sleep, so it is invalid to perform a
channel reset from the software interrupt thread.
Sponsored by: EMC / Isilon Storage Division
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ioat/ioat.c | 19 | ||||
-rw-r--r-- | sys/dev/ioat/ioat_internal.h | 3 |
2 files changed, 22 insertions, 0 deletions
diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c index 74de8ba..bcc4e9a 100644 --- a/sys/dev/ioat/ioat.c +++ b/sys/dev/ioat/ioat.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <sys/sbuf.h> #include <sys/sysctl.h> +#include <sys/taskqueue.h> #include <sys/time.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -92,6 +93,7 @@ static void ioat_submit_single(struct ioat_softc *ioat); static void ioat_comp_update_map(void *arg, bus_dma_segment_t *seg, int nseg, int error); static int ioat_reset_hw(struct ioat_softc *ioat); +static void ioat_reset_hw_task(void *, int); static void ioat_setup_sysctl(device_t device); static int sysctl_handle_reset(SYSCTL_HANDLER_ARGS); static inline struct ioat_softc *ioat_get(struct ioat_softc *, @@ -308,6 +310,7 @@ ioat_detach(device_t device) ioat = DEVICE2SOFTC(device); ioat_test_detach(); + taskqueue_drain(taskqueue_thread, &ioat->reset_task); mtx_lock(IOAT_REFLK); ioat->quiescing = TRUE; @@ -414,6 +417,7 @@ ioat3_attach(device_t device) mtx_init(&ioat->submit_lock, "ioat_submit", NULL, MTX_DEF); mtx_init(&ioat->cleanup_lock, "ioat_cleanup", NULL, MTX_DEF); callout_init(&ioat->timer, 1); + TASK_INIT(&ioat->reset_task, 0, ioat_reset_hw_task, ioat); /* Establish lock order for Witness */ mtx_lock(&ioat->submit_lock); @@ -712,8 +716,23 @@ out: mtx_unlock(&ioat->submit_lock); ioat_log_message(0, "Resetting channel to recover from error\n"); + error = taskqueue_enqueue(taskqueue_thread, &ioat->reset_task); + KASSERT(error == 0, + ("%s: taskqueue_enqueue failed: %d", __func__, error)); +} + +static void +ioat_reset_hw_task(void *ctx, int pending __unused) +{ + struct ioat_softc *ioat; + int error; + + ioat = ctx; + ioat_log_message(1, "%s: Resetting channel\n", __func__); + error = ioat_reset_hw(ioat); KASSERT(error == 0, ("%s: reset failed: %d", __func__, error)); + (void)error; } /* diff --git a/sys/dev/ioat/ioat_internal.h b/sys/dev/ioat/ioat_internal.h index 42201bd..b33faea 100644 --- a/sys/dev/ioat/ioat_internal.h +++ b/sys/dev/ioat/ioat_internal.h @@ -29,6 +29,8 @@ __FBSDID("$FreeBSD$"); #ifndef __IOAT_INTERNAL_H__ #define __IOAT_INTERNAL_H__ +#include <sys/_task.h> + #define DEVICE2SOFTC(dev) ((struct ioat_softc *) device_get_softc(dev)) #define KTR_IOAT KTR_SPARE3 @@ -405,6 +407,7 @@ struct ioat_softc { bus_addr_t comp_update_bus_addr; struct callout timer; + struct task reset_task; boolean_t quiescing; boolean_t is_resize_pending; |