summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/boot/forth/loader.conf1
-rw-r--r--sys/cam/cam_periph.c2
-rw-r--r--sys/cam/cam_xpt.c6
-rw-r--r--sys/cam/scsi/scsi_all.c80
-rw-r--r--sys/cam/scsi/scsi_all.h21
-rw-r--r--sys/conf/NOTES4
6 files changed, 89 insertions, 25 deletions
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index c4c0270..067f311 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -90,6 +90,7 @@ module_path="/boot/kernel;/boot/modules;/modules" # Set the module search path
#kern.nbuf="" # Set the number of buffer headers
#kern.ncallout="" # Set the maximum # of timer events
#kern.sgrowsiz="" # Set the amount to grow stack
+#kern.cam.scsi_delay="2000" # Delay (in ms) before probing SCSI
#kern.ipc.maxsockets="" # Set the maximum number of sockets avaliable
#kern.ipc.nmbclusters="" # Set the number of mbuf clusters
#kern.ipc.nmbufs="" # Set the maximum number of mbufs
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index e3c807a..4086ae3 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -1126,7 +1126,7 @@ cam_periph_async(struct cam_periph *periph, u_int32_t code,
case AC_SENT_BDR:
case AC_BUS_RESET:
{
- cam_periph_bus_settle(periph, SCSI_DELAY);
+ cam_periph_bus_settle(periph, scsi_delay);
break;
}
default:
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index bfd1516..c5e76a4 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -5487,7 +5487,7 @@ proberegister(struct cam_periph *periph, void *arg)
* 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 >= 2000) {
+ if (busses_to_reset > 0 && scsi_delay >= 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);
}
diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index b6ca87d..d512ede 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -36,6 +36,8 @@
#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 */
+/*
+ * 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 value"
+#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
#if !defined(SCSI_NO_OP_STRINGS)
@@ -2876,3 +2906,53 @@ scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
}
return (-1);
}
+
+#ifdef _KERNEL
+static void
+init_scsi_delay(void)
+{
+ int delay;
+
+ delay = SCSI_DELAY;
+ TUNABLE_INT_FETCH("kern.cam.scsi_delay", &delay);
+
+ if (set_scsi_delay(delay) != 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 = scsi_delay;
+ error = sysctl_handle_int(oidp, &delay, sizeof(delay), req);
+ if (error != 0 || req->newptr == 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 == 0) {
+ printf("cam: using minimum scsi_delay (%dms)\n",
+ SCSI_MIN_DELAY);
+ delay = SCSI_MIN_DELAY;
+ }
+ if (delay < SCSI_MIN_DELAY)
+ return (EINVAL);
+ scsi_delay = delay;
+ return (0);
+}
+#endif /* _KERNEL */
diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h
index 9c5993b..beef3d8 100644
--- a/sys/cam/scsi/scsi_all.h
+++ b/sys/cam/scsi/scsi_all.h
@@ -27,30 +27,11 @@
#include <sys/cdefs.h>
#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 == 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 value"
-#endif
+extern int scsi_delay;
#endif /* _KERNEL */
/*
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 061efca..16e5d5d 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -871,7 +871,9 @@ device pass #CAM passthrough driver
# SCSI_NO_OP_STRINGS: When defined disables opcode descriptions
# SCSI_DELAY: The number of MILLISECONDS to freeze the SIM (scsi adapter)
# queue after a bus reset, and the number of milliseconds to
-# freeze the device queue after a bus device reset.
+# freeze the device queue after a bus device reset. This
+# can be changed at boot and runtime with the
+# kern.cam.scsi_delay tunable/sysctl.
options CAMDEBUG
options CAM_DEBUG_BUS=-1
options CAM_DEBUG_TARGET=-1
OpenPOWER on IntegriCloud