Make SCSI_DELAY setable at boot time and runtime via the

kern.cam.scsi_delay tunable/sysctl.

Reviewed by:	mdodd, njl
This commit is contained in:
Brooks Davis 2002-09-02 20:10:19 +00:00
parent 60c1ef970b
commit 3a93719872
6 changed files with 89 additions and 25 deletions

View File

@ -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

View File

@ -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:

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */
/*

View File

@ -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