From 3a937198727a3c9d90594d7250c18b61aded6681 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Mon, 2 Sep 2002 20:10:19 +0000 Subject: [PATCH] Make SCSI_DELAY setable at boot time and runtime via the kern.cam.scsi_delay tunable/sysctl. Reviewed by: mdodd, njl --- sys/boot/forth/loader.conf | 1 + sys/cam/cam_periph.c | 2 +- sys/cam/cam_xpt.c | 6 +-- sys/cam/scsi/scsi_all.c | 80 ++++++++++++++++++++++++++++++++++++++ sys/cam/scsi/scsi_all.h | 21 +--------- sys/conf/NOTES | 4 +- 6 files changed, 89 insertions(+), 25 deletions(-) diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf index c4c02704fee6..067f311fe9b1 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 e3c807a258d8..4086ae3e2228 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 bfd15164ce84..c5e76a4028b4 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 b6ca87dcb0fb..d512ede0ed48 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -36,6 +36,8 @@ #include #include +#include +#include #else #include #include @@ -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 9c5993b578c7..beef3d8aea49 100644 --- a/sys/cam/scsi/scsi_all.h +++ b/sys/cam/scsi/scsi_all.h @@ -27,30 +27,11 @@ #include #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 061efca48615..16e5d5d4c9fe 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