mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
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:
parent
d2c55e5ad0
commit
374b05e1ff
2 changed files with 22 additions and 0 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue