Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Aug 2002 10:39:33 -0700
From:      Brooks Davis <brooks@one-eyed-alien.net>
To:        scsi@freebsd.org
Subject:   [PATCH] make SCSI_DELAY tunable
Message-ID:  <20020828103933.A24804@Odin.AC.HMC.Edu>

next in thread | raw e-mail | index | archive | help

--azLHFNyN32YCQGCU
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

I've attached a patch which makes the value of SCSI_DELAY setable and
boot time via a tunable and runtime via sysctl.  With it applied you can
set SCSI delay is follows:

 - The classic "options SCSI_DELAY=3D####" kernel option
 - "kern.cam.scsi_delay=3D####" in /boot/loader.conf
 - Stop the boot in the loader and enter "set kern.cam.scsi_delay=3D####"
 - sysctl kern.cam.scsi_delay=3D####

I wrote this to allow me to reduce the annoying boot delay without
recompiling my kernel and it works well for that.  My hope is that for
5.0 we can use this functionality to stop punishing everyone who uses
SCSI for the sins of a few devices.  This should allow us to remove
"options SCSI_DELAY=3D15000" from GENERIC without impacting the ability
to install on slow devices.

I've tested the value setting on current and verified that it actually
works with a slightly different patch to stable.

Comments? Suggestions?

-- Brooks

Index: cam_periph.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/cvs/src/sys/cam/cam_periph.c,v
retrieving revision 1.41
diff -u -p -r1.41 cam_periph.c
--- cam_periph.c	24 Aug 2002 02:51:28 -0000	1.41
+++ cam_periph.c	24 Aug 2002 08:08:23 -0000
@@ -1126,7 +1126,7 @@ cam_periph_async(struct cam_periph *peri
 	case AC_SENT_BDR:
 	case AC_BUS_RESET:
 	{
-		cam_periph_bus_settle(periph, SCSI_DELAY);
+		cam_periph_bus_settle(periph, scsi_delay);
 		break;
 	}
 	default:
Index: cam_xpt.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/cvs/src/sys/cam/cam_xpt.c,v
retrieving revision 1.125
diff -u -p -r1.125 cam_xpt.c
--- cam_xpt.c	25 Aug 2002 13:16:48 -0000	1.125
+++ cam_xpt.c	27 Aug 2002 04:18:32 -0000
@@ -5487,7 +5487,7 @@ proberegister(struct cam_periph *periph,
 	 * For HBAs that don't do bus resets, this won't make a difference.
 	 */
 	cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
-				      SCSI_DELAY);
+				      scsi_delay);
 	probeschedule(periph);
 	return(CAM_REQ_CMP);
 }
@@ -6760,9 +6760,9 @@ xpt_config(void *arg)
 		/* Call manually because we don't have any busses */
 		xpt_finishconfig(xpt_periph, NULL);
 	} else  {
-		if (busses_to_reset > 0 && SCSI_DELAY >=3D 2000) {
+		if (busses_to_reset > 0 && scsi_delay >=3D 2000) {
 			printf("Waiting %d seconds for SCSI "
-			       "devices to settle\n", SCSI_DELAY/1000);
+			       "devices to settle\n", scsi_delay/1000);
 		}
 		xpt_for_all_busses(xptconfigfunc, NULL);
 	}
Index: scsi/scsi_all.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/cvs/src/sys/cam/scsi/scsi_all.c,v
retrieving revision 1.36
diff -u -p -r1.36 scsi_all.c
--- scsi/scsi_all.c	26 Aug 2002 17:13:35 -0000	1.36
+++ scsi/scsi_all.c	27 Aug 2002 04:18:33 -0000
@@ -36,6 +36,8 @@
=20
 #include <sys/systm.h>
 #include <sys/libkern.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
 #else
 #include <errno.h>
 #include <stdio.h>
@@ -61,12 +63,40 @@
 #define EJUSTRETURN     -2              /* don't modify regs, just return =
*/
 #endif /* !_KERNEL */
=20
+/*
+ * This is the default number of seconds we wait for devices to settle
+ * after a SCSI bus reset.
+ */
+#ifndef SCSI_DELAY
+#define SCSI_DELAY 2000
+#endif
+/*
+ * All devices need _some_ sort of bus settle delay, so we'll set it to
+ * a minimum value of 100ms.
+ */
+#ifndef SCSI_MIN_DELAY
+#define SCSI_MIN_DELAY 100
+#endif
+/*
+ * Make sure the user isn't using seconds instead of milliseconds.
+ */
+#if (SCSI_DELAY < SCSI_MIN_DELAY)
+#error "SCSI_DELAY is in milliseconds, not seconds!  Please use a larger v=
alue"
+#endif
+
+int scsi_delay;
+
 static int	ascentrycomp(const void *key, const void *member);
 static int	senseentrycomp(const void *key, const void *member);
 static void	fetchtableentries(int sense_key, int asc, int ascq,
 				  struct scsi_inquiry_data *,
 				  const struct sense_key_table_entry **,
 				  const struct asc_table_entry **);
+#ifdef _KERNEL
+static void	init_scsi_delay(void);
+static int	sysctl_scsi_delay(SYSCTL_HANDLER_ARGS);
+static int	set_scsi_delay(int delay);
+#endif
=20
 #if !defined(SCSI_NO_OP_STRINGS)
=20
@@ -2876,3 +2906,53 @@ scsi_static_inquiry_match(caddr_t inqbuf
 	}
         return (-1);
 }
+
+#ifdef _KERNEL
+static void
+init_scsi_delay(void)
+{
+	int delay;
+
+	delay =3D SCSI_DELAY;
+	TUNABLE_INT_FETCH("kern.cam.scsi_delay", &delay);
+
+	if (set_scsi_delay(delay) !=3D 0) {
+		printf("cam: invalid value for tunable kern.cam.scsi_delay\n");
+		set_scsi_delay(SCSI_DELAY);
+	}
+}
+SYSINIT(scsi_delay, SI_SUB_TUNABLES, SI_ORDER_ANY, init_scsi_delay, NULL);
+
+static int
+sysctl_scsi_delay(SYSCTL_HANDLER_ARGS)
+{
+	int error, delay;
+
+	delay =3D scsi_delay;
+	error =3D sysctl_handle_int(oidp, &delay, sizeof(delay), req);
+	if (error !=3D 0 || req->newptr =3D=3D NULL)
+		return (error);
+	return (set_scsi_delay(delay));
+}
+SYSCTL_PROC(_kern_cam, OID_AUTO, scsi_delay, CTLTYPE_INT|CTLFLAG_RW,
+    0, 0, sysctl_scsi_delay, "I",
+    "Delay to allow devices to settle after a SCSI bus reset (ms)");
+
+static int
+set_scsi_delay(int delay)
+{
+	/*
+         * If someone sets this to 0, we assume that they want the
+         * minimum allowable bus settle delay.
+	 */
+	if (delay =3D=3D 0) {
+		printf("cam: using minimum scsi_delay (%dms)\n",
+		    SCSI_MIN_DELAY);
+		delay =3D SCSI_MIN_DELAY;
+	}
+	if (delay < SCSI_MIN_DELAY)
+		return (EINVAL);
+	scsi_delay =3D delay;
+	return (0);
+}
+#endif /* _KERNEL */
Index: scsi/scsi_all.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/cvs/src/sys/cam/scsi/scsi_all.h,v
retrieving revision 1.19
diff -u -p -r1.19 scsi_all.h
--- scsi/scsi_all.h	4 Jun 2002 17:41:47 -0000	1.19
+++ scsi/scsi_all.h	16 Aug 2002 19:10:59 -0000
@@ -27,30 +27,11 @@
 #include <sys/cdefs.h>
=20
 #ifdef _KERNEL
-#include "opt_scsi.h"
 /*
  * This is the number of seconds we wait for devices to settle after a SCSI
  * bus reset.
  */
-#ifndef SCSI_DELAY
-#define SCSI_DELAY 2000
-#endif
-/*
- * If someone sets this to 0, we assume that they want the minimum
- * allowable bus settle delay.  All devices need _some_ sort of bus settle
- * delay, so we'll set it to a minimum value of 100ms.
- */
-#if (SCSI_DELAY =3D=3D 0)
-#undef SCSI_DELAY
-#define SCSI_DELAY 100
-#endif
-
-/*
- * Make sure the user isn't using seconds instead of milliseconds.
- */
-#if (SCSI_DELAY < 100)
-#error "SCSI_DELAY is in milliseconds, not seconds!  Please use a larger v=
alue"
-#endif
+extern int scsi_delay;
 #endif /* _KERNEL */
=20
 /*

--azLHFNyN32YCQGCU
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE9bQrUXY6L6fI4GtQRAuosAJ0b4xcvO4z1O8u5AHy4NovfCg/n1QCePP/2
01ONTM4OIHU3uI5BQuABdtw=
=6ECY
-----END PGP SIGNATURE-----

--azLHFNyN32YCQGCU--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-scsi" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020828103933.A24804>