DF-4401 / fix.diff
--- a/sys/dev/raid/tws/tws_cam.c +++ b/sys/dev/raid/tws/tws_cam.c @@ -1200,11 +1200,14 @@ struct tws_softc *sc = (struct tws_softc *)arg; + /* Serialize entry: check the state under the lock it transitions under + * (callers: ccb-timeout callout, attn-error interrupt, passthru ioctl). */ + lockmgr(&sc->gen_lock, LK_EXCLUSIVE); if ( tws_get_state(sc) == TWS_RESET ) { + lockmgr(&sc->gen_lock, LK_RELEASE); return; } device_printf(sc->tws_dev, "Resetting controller\n"); - lockmgr(&sc->gen_lock, LK_EXCLUSIVE); tws_send_event(sc, TWS_RESET_START); lockmgr(&sc->gen_lock, LK_RELEASE); @@ -1243,22 +1246,23 @@ { struct tws_softc *sc = (struct tws_softc *)arg; - static int timeout_val=0, try=2 ; + int *timeout_val = &sc->reinit_timeout_val; /* per-adapter, not static */ + int *try = &sc->reinit_try; if ( !tws_ctlr_ready(sc) ) { - timeout_val += 5; - if ( timeout_val >= TWS_RESET_TIMEOUT ) { - timeout_val = 0; - if ( try ) + *timeout_val += 5; + if ( *timeout_val >= TWS_RESET_TIMEOUT ) { + *timeout_val = 0; + if ( *try ) tws_assert_soft_reset(sc); - try--; + (*try)--; } callout_reset(&sc->reinit_handle, 5*hz, tws_reinit, sc); return; } - timeout_val=0; - try = 2; + *timeout_val = 0; + *try = 2; sc->obfl_q_overrun = false; if ( tws_init_connect(sc, tws_queue_depth) ) { TWS_TRACE_DEBUG(sc, "initConnect failed", 0, sc->is64bit); --- a/sys/dev/raid/tws/tws.h +++ b/sys/dev/raid/tws/tws.h @@ -256,6 +256,8 @@ struct tws_request *reqs; /* pointer to requests */ struct tws_sense *sense_bufs; /* pointer to sense buffers */ boolean obfl_q_overrun; /* OBFL overrun flag */ + int reinit_timeout_val; /* per-adapter reinit retry cnt */ + int reinit_try; union ccb *scan_ccb; /* pointer to a ccb */ struct tws_request *q_head[TWS_MAX_QS]; /* head pointers to q's */ struct tws_request *q_tail[TWS_MAX_QS]; /* tail pointers to q's */ |