summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorcem <cem@FreeBSD.org>2016-02-13 22:51:25 +0000
committercem <cem@FreeBSD.org>2016-02-13 22:51:25 +0000
commit81a1e6341d7139ef6a6bf605fed8b7bcadd45462 (patch)
tree417cdac18aa2f77593be164600492e62c21b9f20 /sys/dev
parent0784d59f3ad5c231751ea561da1d3b7d962e10b6 (diff)
downloadFreeBSD-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.c19
-rw-r--r--sys/dev/ioat/ioat_internal.h3
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;
OpenPOWER on IntegriCloud