Author: cem
Date: Sat Feb 13 22:51:25 2016
New Revision: 295605
URL: https://svnweb.freebsd.org/changeset/base/295605

Log:
  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

Modified:
  head/sys/dev/ioat/ioat.c
  head/sys/dev/ioat/ioat_internal.h

Modified: head/sys/dev/ioat/ioat.c
==============================================================================
--- head/sys/dev/ioat/ioat.c    Sat Feb 13 22:51:17 2016        (r295604)
+++ head/sys/dev/ioat/ioat.c    Sat Feb 13 22:51:25 2016        (r295605)
@@ -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 io
 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;
 }
 
 /*

Modified: head/sys/dev/ioat/ioat_internal.h
==============================================================================
--- head/sys/dev/ioat/ioat_internal.h   Sat Feb 13 22:51:17 2016        
(r295604)
+++ head/sys/dev/ioat/ioat_internal.h   Sat Feb 13 22:51:25 2016        
(r295605)
@@ -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;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to