Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic Redo watchdogs to handle cases of false death of ...



details:   https://anonhg.NetBSD.org/src/rev/d183cc8900b6
branches:  trunk
changeset: 494351:d183cc8900b6
user:      mjacob <mjacob%NetBSD.org@localhost>
date:      Wed Jul 05 22:23:05 2000 +0000

description:
Redo watchdogs to handle cases of false death of commands- time
each command now.. Get rid of SCCLUn stuff. Use an isp_done routine
to handle cases of watchdog and isp_done racing to completion.

diffstat:

 sys/dev/ic/isp_netbsd.c |  297 +++++++++++++++++++++++++++++------------------
 1 files changed, 182 insertions(+), 115 deletions(-)

diffs (truncated from 448 to 300 lines):

diff -r 590eeaa8fafe -r d183cc8900b6 sys/dev/ic/isp_netbsd.c
--- a/sys/dev/ic/isp_netbsd.c   Wed Jul 05 22:21:44 2000 +0000
+++ b/sys/dev/ic/isp_netbsd.c   Wed Jul 05 22:23:05 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: isp_netbsd.c,v 1.25 2000/05/13 16:53:03 he Exp $ */
+/* $NetBSD: isp_netbsd.c,v 1.26 2000/07/05 22:23:05 mjacob Exp $ */
 /*
  * Platform (NetBSD) dependent common attachment code for Qlogic adapters.
  * Matthew Jacob <mjacob%nas.nasa.gov@localhost>
@@ -33,6 +33,8 @@
 #include <dev/ic/isp_netbsd.h>
 #include <sys/scsiio.h>
 
+#define        _XT(xs) ((((xs)->timeout + 999)/1000) + (2 * hz))
+
 static void ispminphys __P((struct buf *));
 static int32_t ispcmd_slow __P((ISP_SCSI_XFER_T *));
 static int32_t ispcmd __P((ISP_SCSI_XFER_T *));
@@ -40,8 +42,8 @@
 ispioctl __P((struct scsipi_link *, u_long, caddr_t, int, struct proc *));
 
 static struct scsipi_device isp_dev = { NULL, NULL, NULL, NULL };
-static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
-static void isp_watch __P((void *));
+static int isp_polled_cmd __P((struct ispsoftc *, ISP_SCSI_XFER_T *));
+static void isp_dog __P((void *));
 static void isp_command_requeue __P((void *));
 static void isp_internal_restart __P((void *));
 
@@ -52,6 +54,7 @@
 isp_attach(isp)
        struct ispsoftc *isp;
 {
+       int maxluns = isp->isp_maxluns - 1;
 
        isp->isp_osinfo._adapter.scsipi_minphys = ispminphys;
        isp->isp_osinfo._adapter.scsipi_ioctl = ispioctl;
@@ -63,6 +66,7 @@
        isp->isp_osinfo._link.device = &isp_dev;
        isp->isp_osinfo._link.adapter = &isp->isp_osinfo._adapter;
        isp->isp_osinfo._link.openings = isp->isp_maxcmds;
+       isp->isp_osinfo._link.scsipi_scsi.max_lun = maxluns;
        TAILQ_INIT(&isp->isp_osinfo.waitq);     /* XXX 2nd Bus? */
 
        if (IS_FC(isp)) {
@@ -71,23 +75,23 @@
                 */
                isp->isp_osinfo._adapter.scsipi_cmd = ispcmd;
                isp->isp_osinfo._link.scsipi_scsi.max_target = MAX_FC_TARG-1;
-#ifdef ISP2100_SCCLUN
                /*
-                * 16 bits worth, but let's be reasonable..
+                * But we have to be reasonable until the midlayer is fixed.
                 */
-               isp->isp_osinfo._link.scsipi_scsi.max_lun = 255;
-#else
-               isp->isp_osinfo._link.scsipi_scsi.max_lun = 15;
-#endif
-               /* set below */
+               if (maxluns > 255)
+                       isp->isp_osinfo._link.scsipi_scsi.max_lun = 255;
        } else {
                sdparam *sdp = isp->isp_param;
                isp->isp_osinfo._adapter.scsipi_cmd = ispcmd_slow;
                isp->isp_osinfo._link.scsipi_scsi.max_target = MAX_TARGETS-1;
-               isp->isp_osinfo._link.scsipi_scsi.max_lun = 7;
                isp->isp_osinfo._link.scsipi_scsi.adapter_target =
                    sdp->isp_initiator_id;
                isp->isp_osinfo.discovered[0] = 1 << sdp->isp_initiator_id;
+               /*
+                * But we have to be reasonable until the midlayer is fixed.
+                */
+               if (maxluns > 7)
+                       isp->isp_osinfo._link.scsipi_scsi.max_lun = 7;
                if (IS_DUALBUS(isp)) {
                        isp->isp_osinfo._link_b = isp->isp_osinfo._link;
                        sdp++;
@@ -96,6 +100,8 @@
                        isp->isp_osinfo._link_b.scsipi_scsi.adapter_target =
                            sdp->isp_initiator_id;
                        isp->isp_osinfo._link_b.scsipi_scsi.channel = 1;
+                       isp->isp_osinfo._link_b.scsipi_scsi.max_lun =
+                           isp->isp_osinfo._link.scsipi_scsi.max_lun;
                }
        }
        isp->isp_osinfo._link.type = BUS_SCSI;
@@ -110,7 +116,6 @@
                        bus++;
                        (void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
                }
-               SYS_DELAY(2*1000000);
        } else {
                int i, j;
                fcparam *fcp = isp->isp_param;
@@ -143,14 +148,6 @@
        }
 
        /*
-        * Start the watchdog.
-        */
-       callout_init(&isp->isp_osinfo._watchdog);
-       isp->isp_dogactive = 1;
-       callout_reset(&isp->isp_osinfo._watchdog, WATCH_INTERVAL * hz,
-           isp_watch, isp);
-
-       /*
         * And attach children (if any).
         */
        config_found((void *)isp, &isp->isp_osinfo._link, scsiprint);
@@ -302,31 +299,46 @@
                splx(s);
                return (SUCCESSFULLY_QUEUED);
        }
-       DISABLE_INTS(isp);
-       result = ispscsicmd(xs);
-       ENABLE_INTS(isp);
 
-       if ((xs->xs_control & XS_CTL_POLL) == 0) {
-               switch (result) {
-               case CMD_QUEUED:
-                       result = SUCCESSFULLY_QUEUED;
-                       break;
-               case CMD_EAGAIN:
-                       result = TRY_AGAIN_LATER;
-                       break;
-               case CMD_RQLATER:
-                       result = SUCCESSFULLY_QUEUED;
-                       callout_reset(&xs->xs_callout, hz,
-                           isp_command_requeue, xs);
-                       break;
-               case CMD_COMPLETE:
-                       result = COMPLETE;
-                       break;
-               }
+       if (xs->xs_control & XS_CTL_POLL) {
+               result = isp_polled_cmd(isp, xs);
                (void) splx(s);
                return (result);
        }
 
+       result = ispscsicmd(xs);
+       switch (result) {
+       case CMD_QUEUED:
+               result = SUCCESSFULLY_QUEUED;
+               if (xs->timeout) {
+                       callout_reset(&xs->xs_callout, _XT(xs), isp_dog, xs);
+               }
+               break;
+       case CMD_EAGAIN:
+               result = TRY_AGAIN_LATER;
+               break;
+       case CMD_RQLATER:
+               result = SUCCESSFULLY_QUEUED;
+               callout_reset(&xs->xs_callout, hz, isp_command_requeue, xs);
+               break;
+       case CMD_COMPLETE:
+               result = COMPLETE;
+               break;
+       }
+       (void) splx(s);
+       return (result);
+}
+
+static int
+isp_polled_cmd(isp, xs)
+       struct ispsoftc *isp;
+       ISP_SCSI_XFER_T *xs;
+{
+       int result;
+       int infinite = 0, mswait;
+
+       result = ispscsicmd(xs);
+
        switch (result) {
        case CMD_QUEUED:
                result = SUCCESSFULLY_QUEUED;
@@ -343,94 +355,151 @@
                break;
                
        }
+
+       if (result != SUCCESSFULLY_QUEUED) {
+               return (result);
+       }
+
        /*
         * If we can't use interrupts, poll on completion.
         */
-       if (result == SUCCESSFULLY_QUEUED) {
-               if (isp_poll(isp, xs, XS_TIME(xs))) {
-                       /*
-                        * If no other error occurred but we didn't finish,
-                        * something bad happened.
-                        */
-                       if (XS_IS_CMD_DONE(xs) == 0) {
-                               if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
-                                       isp_restart(isp);
-                               }
-                               if (XS_NOERR(xs)) {
-                                       XS_SETERR(xs, HBA_BOTCH);
-                               }
+       if ((mswait = XS_TIME(xs)) == 0)
+               infinite = 1;
+
+       while (mswait || infinite) {
+               if (isp_intr((void *)isp)) {
+                       if (XS_CMD_DONE_P(xs)) {
+                               break;
                        }
                }
-               result = COMPLETE;
+               SYS_DELAY(1000);
+               mswait -= 1;
        }
-       (void) splx(s);
+
+       /*
+        * If no other error occurred but we didn't finish,
+        * something bad happened.
+        */
+       if (XS_CMD_DONE_P(xs) == 0) {
+               if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
+                       isp_restart(isp);
+               }
+               if (XS_NOERR(xs)) {
+                       XS_SETERR(xs, HBA_BOTCH);
+               }
+       }
+       result = COMPLETE;
        return (result);
 }
 
-static int
-isp_poll(isp, xs, mswait)
-       struct ispsoftc *isp;
+void
+isp_done(xs)
        ISP_SCSI_XFER_T *xs;
-       int mswait;
 {
-
-       while (mswait) {
-               /* Try the interrupt handling routine */
-               (void)isp_intr((void *)isp);
-
-               /* See if the xs is now done */
-               if (XS_IS_CMD_DONE(xs)) {
-                       return (0);
+       XS_CMD_S_DONE(xs);
+       if (XS_CMD_WDOG_P(xs) == 0) {
+               struct ispsoftc *isp = XS_ISP(xs);
+               callout_stop(&xs->xs_callout);
+               if (XS_CMD_GRACE_P(xs)) {
+                       PRINTF("%s: finished command on borrowed time\n",
+                           isp->isp_name);
                }
-               SYS_DELAY(1000);        /* wait one millisecond */
-               mswait--;
+               XS_CMD_S_CLEAR(xs);
+               scsipi_done(xs);
        }
-       return (1);
 }
 
 static void
-isp_watch(arg)
+isp_dog(arg)
        void *arg;
 {
-       int i;
-       struct ispsoftc *isp = arg;
-       struct scsipi_xfer *xs;
-       int s;
+       ISP_SCSI_XFER_T *xs = arg;
+       struct ispsoftc *isp = XS_ISP(xs);
+       u_int32_t handle;
+       int s = splbio();
 
        /*
-        * Look for completely dead commands (but not polled ones).
+        * We've decided this command is dead. Make sure we're not trying
+        * to kill a command that's already dead by getting it's handle and
+        * and seeing whether it's still alive.
         */
-       s = splbio();
-       for (i = 0; i < isp->isp_maxcmds; i++) {
-               xs = isp->isp_xflist[i];
-               if (xs == NULL) {
-                       continue;
+       handle = isp_find_handle(isp, xs);
+       if (handle) {
+               u_int16_t r, r1, i;
+
+               if (XS_CMD_DONE_P(xs)) {
+                       PRINTF("%s: watchdog found done cmd (handle 0x%x)\n",
+                           isp->isp_name, handle);
+                       (void) splx(s);
+                       return;
                }
-               if (xs->timeout == 0 || (xs->xs_control & XS_CTL_POLL)) {



Home | Main Index | Thread Index | Old Index