From 73cf209ffb134bd6018a4bfdb67e65d98a1ee8eb Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Sun, 1 Oct 2006 20:23:50 +0000 Subject: [PATCH] Put a bit of hysteresis into both BUSY SCSI status returns and CAM_RESRC_UNAVAIL returns. Delay a tunable amount for either between retries. This came up because the MPT IOC was returning "IOC out of resources" for some user and this caused a CAM_RESRC_UNAVAIL return. Putting a bit of delay between retries helped them out. There was some discussion that an async event should be used to clear CAM_RESRC_UNAVAIL. That's probably a better notion eventually. Reviewed by: scsi@freebsd.org (ade, scott) MFC after: 1 week --- sys/cam/cam_periph.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 35bfdbd260a..fcc80b8852b 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -86,6 +86,14 @@ struct periph_driver **periph_drivers; MALLOC_DEFINE(M_CAMPERIPH, "CAM periph", "CAM peripheral buffers"); +static int periph_selto_delay = 1000; +TUNABLE_INT("kern.cam.periph_selto_delay", &periph_selto_delay); +static int periph_noresrc_delay = 500; +TUNABLE_INT("kern.cam.periph_noresrc_delay", &periph_noresrc_delay); +static int periph_busy_delay = 500; +TUNABLE_INT("kern.cam.periph_busy_delay", &periph_busy_delay); + + void periphdriver_register(void *data) { @@ -1544,7 +1552,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags, int error, printed = 0; int openings; u_int32_t relsim_flags; - u_int32_t timeout; + u_int32_t timeout = 0; action_string = NULL; status = ccb->ccb_h.status; @@ -1636,11 +1644,11 @@ cam_periph_error(union ccb *ccb, cam_flags camflags, } /* - * Wait a second to give the device + * Wait a bit to give the device * time to recover before we try again. */ relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; - timeout = 1000; + timeout = periph_selto_delay; break; } } @@ -1699,8 +1707,16 @@ cam_periph_error(union ccb *ccb, cam_flags camflags, } break; case CAM_RESRC_UNAVAIL: + /* Wait a bit for the resource shortage to abate. */ + timeout = periph_noresrc_delay; + /* FALLTHROUGH */ case CAM_BUSY: - /* timeout??? */ + if (timeout == 0) { + /* Wait a bit for the busy condition to abate. */ + timeout = periph_busy_delay; + } + relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; + /* FALLTHROUGH */ default: /* decrement the number of retries */ if (ccb->ccb_h.retry_count > 0) {