From e08d902a7ad72f1481abca3aa1ea96ffd059a80d Mon Sep 17 00:00:00 2001 From: Mitsuru IWASAKI Date: Sat, 13 Oct 2007 05:45:45 +0000 Subject: [PATCH] Add NOP-message polling to ciss_periodic(). Disable adapter by detecting adapter is dead. Tested by: Masaki YATSU(on RELENG_6) Reviewed by: scottl MFC after: 1 week --- sys/dev/ciss/ciss.c | 81 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c index 05ca46d7a72..91c004dff48 100644 --- a/sys/dev/ciss/ciss.c +++ b/sys/dev/ciss/ciss.c @@ -183,6 +183,7 @@ static int ciss_name_device(struct ciss_softc *sc, int bus, int target); /* periodic status monitoring */ static void ciss_periodic(void *arg); +static void ciss_disable_adapter(struct ciss_softc *sc); static void ciss_notify_event(struct ciss_softc *sc); static void ciss_notify_complete(struct ciss_request *cr); static int ciss_notify_abort(struct ciss_softc *sc); @@ -3068,6 +3069,9 @@ static void ciss_periodic(void *arg) { struct ciss_softc *sc; + struct ciss_request *cr = NULL; + struct ciss_command *cc = NULL; + int error = 0; debug_called(1); @@ -3082,7 +3086,8 @@ ciss_periodic(void *arg) sc->ciss_heartbeat, sc->ciss_heart_attack); if (sc->ciss_heart_attack == 3) { ciss_printf(sc, "ADAPTER HEARTBEAT FAILED\n"); - /* XXX should reset adapter here */ + ciss_disable_adapter(sc); + return; } } else { sc->ciss_heartbeat = sc->ciss_cfg->heartbeat; @@ -3090,6 +3095,25 @@ ciss_periodic(void *arg) debug(3, "new heartbeat 0x%x", sc->ciss_heartbeat); } + /* + * Send the NOP message and wait for a response. + */ + if ((error = ciss_get_request(sc, &cr)) == 0) { + cc = CISS_FIND_COMMAND(cr); + cc->cdb.cdb_length = 1; + cc->cdb.type = CISS_CDB_TYPE_MESSAGE; + cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; + cc->cdb.direction = CISS_CDB_DIRECTION_WRITE; + cc->cdb.timeout = 0; + cc->cdb.cdb[0] = CISS_OPCODE_MESSAGE_NOP; + + if ((error = ciss_synch_request(cr, 10 * 1000)) != 0) { + ciss_printf(sc, "SENDING NOP MESSAGE FAILED\n"); + } + + ciss_release_request(cr); + } + /* * If the notify event request has died for some reason, or has * not started yet, restart it. @@ -3105,6 +3129,61 @@ ciss_periodic(void *arg) callout_reset(&sc->ciss_periodic, CISS_HEARTBEAT_RATE * hz, ciss_periodic, sc); } +/************************************************************************ + * Disable the adapter. + * + * The all requests in completed queue is failed with hardware error. + * This will cause failover in a multipath configuration. + */ +static void +ciss_disable_adapter(struct ciss_softc *sc) +{ + struct ciss_request *cr; + struct ciss_command *cc; + struct ciss_error_info *ce; + int s; + + s = splcam(); + + CISS_TL_SIMPLE_DISABLE_INTERRUPTS(sc); + pci_disable_busmaster(sc->ciss_dev); + sc->ciss_flags &= ~CISS_FLAG_RUNNING; + + for (;;) { + if ((cr = ciss_dequeue_busy(sc)) == NULL) + break; + + cc = CISS_FIND_COMMAND(cr); + ce = (struct ciss_error_info *)&(cc->sg[0]); + ce->command_status = CISS_CMD_STATUS_HARDWARE_ERROR; + ciss_enqueue_complete(cr); + } + + for (;;) { + if ((cr = ciss_dequeue_complete(sc)) == NULL) + break; + + /* + * If the request has a callback, invoke it. + */ + if (cr->cr_complete != NULL) { + cr->cr_complete(cr); + continue; + } + + /* + * If someone is sleeping on this request, wake them up. + */ + if (cr->cr_flags & CISS_REQ_SLEEP) { + cr->cr_flags &= ~CISS_REQ_SLEEP; + wakeup(cr); + continue; + } + } + + splx(s); +} + /************************************************************************ * Request a notification response from the adapter. *