From cf66c2650f7bfe5ba9a22ace7d39ef9f52208926 Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sat, 24 Nov 2007 19:19:43 +0000 Subject: [PATCH] Make SCSI_DELAY setable at boot time and runtime via the kern.cam.scsi_delay tunable/sysctl. Obtained-from: FreeBSD --- sys/bus/cam/cam_periph.c | 4 +- sys/bus/cam/cam_xpt.c | 8 ++-- sys/bus/cam/scsi/scsi_all.c | 82 ++++++++++++++++++++++++++++++++++++- sys/bus/cam/scsi/scsi_all.h | 23 +---------- sys/config/LINT | 6 ++- 5 files changed, 93 insertions(+), 30 deletions(-) diff --git a/sys/bus/cam/cam_periph.c b/sys/bus/cam/cam_periph.c index 56894bc920..9775f8ee9e 100644 --- a/sys/bus/cam/cam_periph.c +++ b/sys/bus/cam/cam_periph.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/cam_periph.c,v 1.24.2.3 2003/01/25 19:04:40 dillon Exp $ - * $DragonFly: src/sys/bus/cam/cam_periph.c,v 1.30 2007/11/24 18:55:27 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/cam_periph.c,v 1.31 2007/11/24 19:19:43 pavalos Exp $ */ #include @@ -1105,7 +1105,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/bus/cam/cam_xpt.c b/sys/bus/cam/cam_xpt.c index 4da668b217..2e94ed207a 100644 --- a/sys/bus/cam/cam_xpt.c +++ b/sys/bus/cam/cam_xpt.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/cam_xpt.c,v 1.80.2.18 2002/12/09 17:31:55 gibbs Exp $ - * $DragonFly: src/sys/bus/cam/cam_xpt.c,v 1.42 2007/11/21 20:29:34 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/cam_xpt.c,v 1.43 2007/11/24 19:19:43 pavalos Exp $ */ #include #include @@ -5358,7 +5358,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); } @@ -6632,9 +6632,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) { kprintf("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/bus/cam/scsi/scsi_all.c b/sys/bus/cam/scsi/scsi_all.c index 3314e80baa..6654bb0c6c 100644 --- a/sys/bus/cam/scsi/scsi_all.c +++ b/sys/bus/cam/scsi/scsi_all.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.14.2.11 2003/10/30 15:06:35 thomas Exp $ - * $DragonFly: src/sys/bus/cam/scsi/scsi_all.c,v 1.19 2007/11/24 03:48:31 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/scsi/scsi_all.c,v 1.20 2007/11/24 19:19:43 pavalos Exp $ */ #include @@ -37,6 +37,8 @@ #include #include #include +#include +#include #else @@ -67,12 +69,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) @@ -2934,6 +2964,56 @@ scsi_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) { + kprintf("cam: invalid value for tunable kern.cam.scsi_delay\n"); + set_scsi_delay(SCSI_DELAY); + } +} +SYSINIT(scsi_delay, SI_BOOT1_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) { + kprintf("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 */ + /* * Try make as good a match as possible with * available sub drivers diff --git a/sys/bus/cam/scsi/scsi_all.h b/sys/bus/cam/scsi/scsi_all.h index 2779250f0e..1759afaffe 100644 --- a/sys/bus/cam/scsi/scsi_all.h +++ b/sys/bus/cam/scsi/scsi_all.h @@ -15,7 +15,7 @@ * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * * $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.14.2.5 2003/08/24 03:26:37 ken Exp $ - * $DragonFly: src/sys/bus/cam/scsi/scsi_all.h,v 1.10 2007/11/24 03:48:31 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/scsi/scsi_all.h,v 1.11 2007/11/24 19:19:43 pavalos Exp $ */ /* @@ -33,30 +33,11 @@ #endif #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/config/LINT b/sys/config/LINT index 0e71ac0949..9f03dd229d 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -3,7 +3,7 @@ # as much of the source tree as it can. # # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $ -# $DragonFly: src/sys/config/LINT,v 1.141 2007/11/19 18:49:06 swildner Exp $ +# $DragonFly: src/sys/config/LINT,v 1.142 2007/11/24 19:19:43 pavalos Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -938,7 +938,9 @@ device ses #SCSI SES/SAF-TE 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 -- 2.41.0