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
This commit is contained in:
Conrad Meyer 2016-02-13 22:51:25 +00:00
parent d2c55e5ad0
commit 374b05e1ff
2 changed files with 22 additions and 0 deletions

View file

@ -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;
}
/*

View file

@ -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;