From owner-svn-src-all@FreeBSD.ORG Wed Apr 16 14:45:00 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 60CC79C1; Wed, 16 Apr 2014 14:45:00 +0000 (UTC) Received: from smtp1.multiplay.co.uk (smtp1.multiplay.co.uk [85.236.96.35]) by mx1.freebsd.org (Postfix) with ESMTP id 5056A178A; Wed, 16 Apr 2014 14:44:59 +0000 (UTC) Received: by smtp1.multiplay.co.uk (Postfix, from userid 65534) id 8103A20E7088B; Wed, 16 Apr 2014 14:44:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.multiplay.co.uk X-Spam-Level: ** X-Spam-Status: No, score=2.3 required=8.0 tests=AWL,BAYES_00,DOS_OE_TO_MX, FSL_HELO_NON_FQDN_1,HELO_NO_DOMAIN,RDNS_DYNAMIC,STOX_REPLY_TYPE autolearn=no version=3.3.1 Received: from r2d2 (82-69-141-170.dsl.in-addr.zen.co.uk [82.69.141.170]) by smtp1.multiplay.co.uk (Postfix) with ESMTPS id 1157720E70886; Wed, 16 Apr 2014 14:44:47 +0000 (UTC) Message-ID: <0A192F0FA084413FA4840BDCE2F3CAA8@multiplay.co.uk> From: "Steven Hartland" To: "Alexander Motin" , , , , References: <201404161004.s3GA4K4u052569@svn.freebsd.org> Subject: Re: svn commit: r264522 - in stable/10: share/man/man4 sys/cam/scsi Date: Wed, 16 Apr 2014 15:44:43 +0100 MIME-Version: 1.0 Content-Type: text/plain; format=flowed; charset="utf-8"; reply-type=original Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2900.5931 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.6157 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Apr 2014 14:45:00 -0000 Does this need r264311 MFC'ed too mav? Regards Steve ----- Original Message ----- From: "Alexander Motin" To: ; ; ; Sent: Wednesday, April 16, 2014 11:04 AM Subject: svn commit: r264522 - in stable/10: share/man/man4 sys/cam/scsi > Author: mav > Date: Wed Apr 16 10:04:19 2014 > New Revision: 264522 > URL: http://svnweb.freebsd.org/changeset/base/264522 > > Log: > MFC r264295: > Remove support of LUN-based CD changers from cd(4) driver. > > This code was heavily broken few months ago during CAM locking changes. > Fixing it would require almost complete rewrite. Since there are no > known devices on market using this interface younger then ~15 years, and > they are CD, not even DVD, I don't see much reason to rewrite it. > > This change does not mean those devices won't work. They will just work > slower due to inefficient disks load/unload schedule if several LUNs > accessed same time. > > Modified: > stable/10/share/man/man4/cd.4 > stable/10/sys/cam/scsi/scsi_cd.c > Directory Properties: > stable/10/ (props changed) > > Modified: stable/10/share/man/man4/cd.4 > ============================================================================== > --- stable/10/share/man/man4/cd.4 Wed Apr 16 09:25:20 2014 (r264521) > +++ stable/10/share/man/man4/cd.4 Wed Apr 16 10:04:19 2014 (r264522) > @@ -25,7 +25,7 @@ > .\" > .\" $FreeBSD$ > .\" > -.Dd February 8, 2012 > +.Dd April 9, 2014 > .Dt CD 4 > .Os > .Sh NAME > @@ -33,8 +33,6 @@ > .Nd SCSI CD-ROM driver > .Sh SYNOPSIS > .Cd device cd > -.Cd "options ""CHANGER_MIN_BUSY_SECONDS=3""" > -.Cd "options ""CHANGER_MAX_BUSY_SECONDS=11""" > .Sh DESCRIPTION > The > .Nm > @@ -288,65 +286,6 @@ Some work is planned to support > some of the more common `broken' > .Tn CD-ROM > drives; however, this is not yet under way. > -.Sh CHANGER OPERATION > -This driver has built-in support for LUN-based CD changers. > -A LUN-based CD > -changer is a drive that can hold two or more CDs, but only has one CD > -player mechanism. > -Each CD in the drive shows up as a separate logical unit > -on the > -.Tn SCSI > -bus. > -The > -.Nm > -driver automatically recognizes LUN-based changers, and routes commands for > -changers through an internal scheduler. > -The scheduler prevents changer > -"thrashing", which is caused by sending commands to different LUNs in the > -changer at the same time. > -.Pp > -The scheduler honors minimum and maximum time > -quanta that the driver will spend on a particular LUN. > -The minimum time > -is the guaranteed minimum amount of time that the driver will spend on a > -given LUN, even if there is no outstanding I/O for that LUN. > -The maximum > -time is the maximum amount of time the changer will spend on a LUN if there > -is outstanding I/O for another LUN. > -If there is no outstanding I/O for > -another LUN, the driver will allow indefinite access to a given LUN. > -.Pp > -The minimum and maximum time quanta are configurable via kernel options and > -also via sysctl and kernel tunable variables. > -The kernel options are: > -.Pp > -.Bl -item -compact > -.It > -.Cd "options ""CHANGER_MIN_BUSY_SECONDS=3""" > -.It > -.Cd "options ""CHANGER_MAX_BUSY_SECONDS=11""" > -.El > -.Pp > -The sysctl/kernel tunable variables are: > -.Pp > -.Bl -item -compact > -.It > -.Va kern.cam.cd.changer.min_busy_seconds > -.It > -.Va kern.cam.cd.changer.max_busy_seconds > -.El > -.Pp > -It is suggested that the user try experimenting with the minimum and > -maximum timeouts via the sysctl variables to arrive at the proper values > -for your changer. > -Once you have settled on the proper timeouts for your > -changer, you can then put them in your kernel config file. > -.Pp > -If your system does have a LUN-based changer, you may notice that the > -probe messages for the various LUNs of the changer will continue to appear > -while the boot process is going on. > -This is normal, and is caused by the > -changer scheduling code. > .Sh SYSCTL VARIABLES > The following variables are available as both > .Xr sysctl 8 > @@ -397,12 +336,6 @@ Valid minimum command sizes > are 6 and 10. > Any value above 6 will be rounded to 10, and any value below > 6 will be rounded to 6. > -.It kern.cam.cd.changer.min_busy_seconds > -.It kern.cam.cd.changer.max_busy_seconds > -.Pp > -Tune how long individual LUNs are 'locked' for I/O operations to > -optimize changer operation. > -See CHANGER OPERATION section for information on how to use these items. > .El > .Sh FILES > .Bl -tag -width /dev/cd[0-9][a-h] -compact > @@ -437,21 +370,3 @@ were poorly chosen, and a number of spel > the names of the > .Fn ioctl > commands. > -.Pp > -There is no mechanism currently to set different minimum and maximum > -timeouts for different CD changers; the timeout values set by the kernel > -options or the sysctl variables apply to all LUN-based CD changers in the > -system. > -It is possible to implement such support, but the sysctl > -implementation at least would be rather inelegant, because of the current > -inability of the sysctl code to handle the addition of nodes after compile > -time. > -Thus, it would take one dynamically sized sysctl variable and a > -userland utility to get/set the timeout values. > -Implementation of separate > -timeouts for different CD devices in the kernel config file would likely > -require modification of > -.Xr config 8 > -to support the two timeouts when hardwiring > -.Nm > -devices. > > Modified: stable/10/sys/cam/scsi/scsi_cd.c > ============================================================================== > --- stable/10/sys/cam/scsi/scsi_cd.c Wed Apr 16 09:25:20 2014 (r264521) > +++ stable/10/sys/cam/scsi/scsi_cd.c Wed Apr 16 10:04:19 2014 (r264522) > @@ -87,8 +87,6 @@ typedef enum { > CD_Q_NONE = 0x00, > CD_Q_NO_TOUCH = 0x01, > CD_Q_BCD_TRACKS = 0x02, > - CD_Q_NO_CHANGER = 0x04, > - CD_Q_CHANGER = 0x08, > CD_Q_10_BYTE_ONLY = 0x10 > } cd_quirks; > > @@ -96,8 +94,6 @@ typedef enum { > "\020" \ > "\001NO_TOUCH" \ > "\002BCD_TRACKS" \ > - "\003NO_CHANGER" \ > - "\004CHANGER" \ > "\00510_BYTE_ONLY" > > typedef enum { > @@ -106,7 +102,6 @@ typedef enum { > CD_FLAG_DISC_LOCKED = 0x0004, > CD_FLAG_DISC_REMOVABLE = 0x0008, > CD_FLAG_SAW_MEDIA = 0x0010, > - CD_FLAG_CHANGER = 0x0040, > CD_FLAG_ACTIVE = 0x0080, > CD_FLAG_SCHED_ON_COMP = 0x0100, > CD_FLAG_RETRY_UA = 0x0200, > @@ -123,13 +118,6 @@ typedef enum { > CD_CCB_RETRY_UA = 0x10 > } cd_ccb_state; > > -typedef enum { > - CHANGER_TIMEOUT_SCHED = 0x01, > - CHANGER_SHORT_TMOUT_SCHED = 0x02, > - CHANGER_MANUAL_CALL = 0x04, > - CHANGER_NEED_TIMEOUT = 0x08 > -} cd_changer_flags; > - > #define ccb_state ppriv_field0 > #define ccb_bp ppriv_ptr1 > > @@ -157,9 +145,6 @@ struct cd_softc { > struct cd_params params; > union ccb saved_ccb; > cd_quirks quirks; > - STAILQ_ENTRY(cd_softc) changer_links; > - struct cdchanger *changer; > - int bufs_left; > struct cam_periph *periph; > int minimum_command_size; > int outstanding_cmds; > @@ -189,13 +174,6 @@ struct cd_quirk_entry { > }; > > /* > - * The changer quirk entries aren't strictly necessary. Basically, what > - * they do is tell cdregister() up front that a device is a changer. > - * Otherwise, it will figure that fact out once it sees a LUN on the device > - * that is greater than 0. If it is known up front that a device is a changer, > - * all I/O to the device will go through the changer scheduling routines, as > - * opposed to the "normal" CD code. > - * > * NOTE ON 10_BYTE_ONLY quirks: Any 10_BYTE_ONLY quirks MUST be because > * your device hangs when it gets a 10 byte command. Adding a quirk just > * to get rid of the informative diagnostic message is not acceptable. All > @@ -209,18 +187,6 @@ struct cd_quirk_entry { > static struct cd_quirk_entry cd_quirk_table[] = > { > { > - { T_CDROM, SIP_MEDIA_REMOVABLE, "NRC", "MBR-7", "*"}, > - /*quirks*/ CD_Q_CHANGER > - }, > - { > - { T_CDROM, SIP_MEDIA_REMOVABLE, "PIONEER", "CD-ROM DRM*", > - "*"}, /* quirks */ CD_Q_CHANGER > - }, > - { > - { T_CDROM, SIP_MEDIA_REMOVABLE, "NAKAMICH", "MJ-*", "*"}, > - /* quirks */ CD_Q_CHANGER > - }, > - { > { T_CDROM, SIP_MEDIA_REMOVABLE, "CHINON", "CD-ROM CDS-535","*"}, > /* quirks */ CD_Q_BCD_TRACKS > } > @@ -241,15 +207,11 @@ static void cdasync(void *callback_arg, > static int cdcmdsizesysctl(SYSCTL_HANDLER_ARGS); > static void cdshorttimeout(void *arg); > static void cdschedule(struct cam_periph *periph, int priority); > -static void cdrunchangerqueue(void *arg); > -static void cdchangerschedule(struct cd_softc *softc); > static int cdrunccb(union ccb *ccb, > int (*error_routine)(union ccb *ccb, > u_int32_t cam_flags, > u_int32_t sense_flags), > u_int32_t cam_flags, u_int32_t sense_flags); > -static union ccb *cdgetccb(struct cam_periph *periph, > - u_int32_t priority); > static void cddone(struct cam_periph *periph, > union ccb *start_ccb); > static union cd_pages *cdgetpage(struct cd_mode_params *mode_params); > @@ -311,22 +273,12 @@ PERIPHDRIVER_DECLARE(cd, cddriver); > #ifndef CD_DEFAULT_TIMEOUT > #define CD_DEFAULT_TIMEOUT 30000 > #endif > -#ifndef CHANGER_MIN_BUSY_SECONDS > -#define CHANGER_MIN_BUSY_SECONDS 5 > -#endif > -#ifndef CHANGER_MAX_BUSY_SECONDS > -#define CHANGER_MAX_BUSY_SECONDS 15 > -#endif > > static int cd_poll_period = CD_DEFAULT_POLL_PERIOD; > static int cd_retry_count = CD_DEFAULT_RETRY; > static int cd_timeout = CD_DEFAULT_TIMEOUT; > -static int changer_min_busy_seconds = CHANGER_MIN_BUSY_SECONDS; > -static int changer_max_busy_seconds = CHANGER_MAX_BUSY_SECONDS; > > static SYSCTL_NODE(_kern_cam, OID_AUTO, cd, CTLFLAG_RD, 0, "CAM CDROM driver"); > -static SYSCTL_NODE(_kern_cam_cd, OID_AUTO, changer, CTLFLAG_RD, 0, > - "CD Changer"); > SYSCTL_INT(_kern_cam_cd, OID_AUTO, poll_period, CTLFLAG_RW, > &cd_poll_period, 0, "Media polling period in seconds"); > TUNABLE_INT("kern.cam.cd.poll_period", &cd_poll_period); > @@ -336,30 +288,6 @@ TUNABLE_INT("kern.cam.cd.retry_count", & > SYSCTL_INT(_kern_cam_cd, OID_AUTO, timeout, CTLFLAG_RW, > &cd_timeout, 0, "Timeout, in us, for read operations"); > TUNABLE_INT("kern.cam.cd.timeout", &cd_timeout); > -SYSCTL_INT(_kern_cam_cd_changer, OID_AUTO, min_busy_seconds, CTLFLAG_RW, > - &changer_min_busy_seconds, 0, "Minimum changer scheduling quantum"); > -TUNABLE_INT("kern.cam.cd.changer.min_busy_seconds", &changer_min_busy_seconds); > -SYSCTL_INT(_kern_cam_cd_changer, OID_AUTO, max_busy_seconds, CTLFLAG_RW, > - &changer_max_busy_seconds, 0, "Maximum changer scheduling quantum"); > -TUNABLE_INT("kern.cam.cd.changer.max_busy_seconds", &changer_max_busy_seconds); > - > -struct cdchanger { > - path_id_t path_id; > - target_id_t target_id; > - int num_devices; > - struct camq devq; > - struct timeval start_time; > - struct cd_softc *cur_device; > - struct callout short_handle; > - struct callout long_handle; > - volatile cd_changer_flags flags; > - STAILQ_ENTRY(cdchanger) changer_links; > - STAILQ_HEAD(chdevlist, cd_softc) chluns; > -}; > - > -static struct mtx changerq_mtx; > -static STAILQ_HEAD(changerlist, cdchanger) changerq; > -static int num_changers; > > static MALLOC_DEFINE(M_SCSICD, "scsi_cd", "scsi_cd buffers"); > > @@ -368,9 +296,6 @@ cdinit(void) > { > cam_status status; > > - mtx_init(&changerq_mtx, "cdchangerq", "SCSI CD Changer List", MTX_DEF); > - STAILQ_INIT(&changerq); > - > /* > * Install a global async callback. This callback will > * receive async callbacks like "new device found". > @@ -417,15 +342,6 @@ cdoninvalidate(struct cam_periph *periph > */ > bioq_flush(&softc->bio_queue, NULL, ENXIO); > > - /* > - * If this device is part of a changer, and it was scheduled > - * to run, remove it from the run queue since we just nuked > - * all of its scheduled I/O. > - */ > - if ((softc->flags & CD_FLAG_CHANGER) > - && (softc->pinfo.index != CAM_UNQUEUED_INDEX)) > - camq_remove(&softc->changer->devq, softc->pinfo.index); > - > disk_gone(softc->disk); > } > > @@ -436,73 +352,6 @@ cdcleanup(struct cam_periph *periph) > > softc = (struct cd_softc *)periph->softc; > > - /* > - * In the queued, non-active case, the device in question > - * has already been removed from the changer run queue. Since this > - * device is active, we need to de-activate it, and schedule > - * another device to run. (if there is another one to run) > - */ > - if ((softc->flags & CD_FLAG_CHANGER) > - && (softc->flags & CD_FLAG_ACTIVE)) { > - > - /* > - * The purpose of the short timeout is soley to determine > - * whether the current device has finished or not. Well, > - * since we're removing the active device, we know that it > - * is finished. So, get rid of the short timeout. > - * Otherwise, if we're in the time period before the short > - * timeout fires, and there are no other devices in the > - * queue to run, there won't be any other device put in the > - * active slot. i.e., when we call cdrunchangerqueue() > - * below, it won't do anything. Then, when the short > - * timeout fires, it'll look at the "current device", which > - * we are free below, and possibly panic the kernel on a > - * bogus pointer reference. > - * > - * The long timeout doesn't really matter, since we > - * decrement the qfrozen_cnt to indicate that there is > - * nothing in the active slot now. Therefore, there won't > - * be any bogus pointer references there. > - */ > - if (softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED) { > - callout_stop(&softc->changer->short_handle); > - softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; > - } > - softc->changer->devq.qfrozen_cnt--; > - softc->changer->flags |= CHANGER_MANUAL_CALL; > - cdrunchangerqueue(softc->changer); > - } > - > - /* > - * If we're removing the last device on the changer, go ahead and > - * remove the changer device structure. > - */ > - if ((softc->flags & CD_FLAG_CHANGER) > - && (--softc->changer->num_devices == 0)) { > - > - /* > - * Theoretically, there shouldn't be any timeouts left, but > - * I'm not completely sure that that will be the case. So, > - * it won't hurt to check and see if there are any left. > - */ > - if (softc->changer->flags & CHANGER_TIMEOUT_SCHED) { > - callout_stop(&softc->changer->long_handle); > - softc->changer->flags &= ~CHANGER_TIMEOUT_SCHED; > - } > - > - if (softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED) { > - callout_stop(&softc->changer->short_handle); > - softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; > - } > - > - mtx_lock(&changerq_mtx); > - STAILQ_REMOVE(&changerq, softc->changer, cdchanger, > - changer_links); > - num_changers--; > - mtx_unlock(&changerq_mtx); > - xpt_print(periph->path, "removing changer entry\n"); > - free(softc->changer, M_DEVBUF); > - } > cam_periph_unlock(periph); > if ((softc->flags & CD_FLAG_SCTX_INIT) != 0 > && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { > @@ -834,237 +683,16 @@ cdregister(struct cam_periph *periph, vo > AC_SCSI_AEN | AC_UNIT_ATTENTION, cdasync, periph, periph->path); > > /* > - * If the target lun is greater than 0, we most likely have a CD > - * changer device. Check the quirk entries as well, though, just > - * in case someone has a CD tower with one lun per drive or > - * something like that. Also, if we know up front that a > - * particular device is a changer, we can mark it as such starting > - * with lun 0, instead of lun 1. It shouldn't be necessary to have > - * a quirk entry to define something as a changer, however. > - */ > - if (((cgd->ccb_h.target_lun > 0) > - && ((softc->quirks & CD_Q_NO_CHANGER) == 0)) > - || ((softc->quirks & CD_Q_CHANGER) != 0)) { > - struct cdchanger *nchanger; > - struct cam_periph *nperiph; > - struct cam_path *path; > - cam_status status; > - int found; > - > - /* Set the changer flag in the current device's softc */ > - softc->flags |= CD_FLAG_CHANGER; > - > - /* > - * Now, look around for an existing changer device with the > - * same path and target ID as the current device. > - */ > - mtx_lock(&changerq_mtx); > - for (found = 0, > - nchanger = (struct cdchanger *)STAILQ_FIRST(&changerq); > - nchanger != NULL; > - nchanger = STAILQ_NEXT(nchanger, changer_links)){ > - if ((nchanger->path_id == cgd->ccb_h.path_id) > - && (nchanger->target_id == cgd->ccb_h.target_id)) { > - found = 1; > - break; > - } > - } > - mtx_unlock(&changerq_mtx); > - > - /* > - * If we found a matching entry, just add this device to > - * the list of devices on this changer. > - */ > - if (found == 1) { > - struct chdevlist *chlunhead; > - > - chlunhead = &nchanger->chluns; > - > - /* > - * XXX KDM look at consolidating this code with the > - * code below in a separate function. > - */ > - > - /* > - * Create a path with lun id 0, and see if we can > - * find a matching device > - */ > - status = xpt_create_path(&path, /*periph*/ periph, > - cgd->ccb_h.path_id, > - cgd->ccb_h.target_id, 0); > - > - if ((status == CAM_REQ_CMP) > - && ((nperiph = cam_periph_find(path, "cd")) != NULL)){ > - struct cd_softc *nsoftc; > - > - nsoftc = (struct cd_softc *)nperiph->softc; > - > - if ((nsoftc->flags & CD_FLAG_CHANGER) == 0){ > - nsoftc->flags |= CD_FLAG_CHANGER; > - nchanger->num_devices++; > - if (camq_resize(&nchanger->devq, > - nchanger->num_devices)!=CAM_REQ_CMP){ > - printf("cdregister: " > - "camq_resize " > - "failed, changer " > - "support may " > - "be messed up\n"); > - } > - nsoftc->changer = nchanger; > - nsoftc->pinfo.index =CAM_UNQUEUED_INDEX; > - > - STAILQ_INSERT_TAIL(&nchanger->chluns, > - nsoftc,changer_links); > - } > - xpt_free_path(path); > - } else if (status == CAM_REQ_CMP) > - xpt_free_path(path); > - else { > - printf("cdregister: unable to allocate path\n" > - "cdregister: changer support may be " > - "broken\n"); > - } > - > - nchanger->num_devices++; > - > - softc->changer = nchanger; > - softc->pinfo.index = CAM_UNQUEUED_INDEX; > - > - if (camq_resize(&nchanger->devq, > - nchanger->num_devices) != CAM_REQ_CMP) { > - printf("cdregister: camq_resize " > - "failed, changer support may " > - "be messed up\n"); > - } > - > - STAILQ_INSERT_TAIL(chlunhead, softc, changer_links); > - } > - /* > - * In this case, we don't already have an entry for this > - * particular changer, so we need to create one, add it to > - * the queue, and queue this device on the list for this > - * changer. Before we queue this device, however, we need > - * to search for lun id 0 on this target, and add it to the > - * queue first, if it exists. (and if it hasn't already > - * been marked as part of the changer.) > - */ > - else { > - nchanger = malloc(sizeof(struct cdchanger), > - M_DEVBUF, M_NOWAIT | M_ZERO); > - if (nchanger == NULL) { > - softc->flags &= ~CD_FLAG_CHANGER; > - printf("cdregister: unable to malloc " > - "changer structure\ncdregister: " > - "changer support disabled\n"); > - > - /* > - * Yes, gotos can be gross but in this case > - * I think it's justified.. > - */ > - goto cdregisterexit; > - } > - if (camq_init(&nchanger->devq, 1) != 0) { > - softc->flags &= ~CD_FLAG_CHANGER; > - printf("cdregister: changer support " > - "disabled\n"); > - goto cdregisterexit; > - } > - > - nchanger->path_id = cgd->ccb_h.path_id; > - nchanger->target_id = cgd->ccb_h.target_id; > - > - /* this is superfluous, but it makes things clearer */ > - nchanger->num_devices = 0; > - > - STAILQ_INIT(&nchanger->chluns); > - > - callout_init_mtx(&nchanger->long_handle, > - cam_periph_mtx(periph), 0); > - callout_init_mtx(&nchanger->short_handle, > - cam_periph_mtx(periph), 0); > - > - mtx_lock(&changerq_mtx); > - num_changers++; > - STAILQ_INSERT_TAIL(&changerq, nchanger, > - changer_links); > - mtx_unlock(&changerq_mtx); > - > - /* > - * Create a path with lun id 0, and see if we can > - * find a matching device > - */ > - status = xpt_create_path(&path, /*periph*/ periph, > - cgd->ccb_h.path_id, > - cgd->ccb_h.target_id, 0); > - > - /* > - * If we were able to allocate the path, and if we > - * find a matching device and it isn't already > - * marked as part of a changer, then we add it to > - * the current changer. > - */ > - if ((status == CAM_REQ_CMP) > - && ((nperiph = cam_periph_find(path, "cd")) != NULL) > - && ((((struct cd_softc *)periph->softc)->flags & > - CD_FLAG_CHANGER) == 0)) { > - struct cd_softc *nsoftc; > - > - nsoftc = (struct cd_softc *)nperiph->softc; > - > - nsoftc->flags |= CD_FLAG_CHANGER; > - nchanger->num_devices++; > - if (camq_resize(&nchanger->devq, > - nchanger->num_devices) != CAM_REQ_CMP) { > - printf("cdregister: camq_resize " > - "failed, changer support may " > - "be messed up\n"); > - } > - nsoftc->changer = nchanger; > - nsoftc->pinfo.index = CAM_UNQUEUED_INDEX; > - > - STAILQ_INSERT_TAIL(&nchanger->chluns, > - nsoftc, changer_links); > - xpt_free_path(path); > - } else if (status == CAM_REQ_CMP) > - xpt_free_path(path); > - else { > - printf("cdregister: unable to allocate path\n" > - "cdregister: changer support may be " > - "broken\n"); > - } > - > - softc->changer = nchanger; > - softc->pinfo.index = CAM_UNQUEUED_INDEX; > - nchanger->num_devices++; > - if (camq_resize(&nchanger->devq, > - nchanger->num_devices) != CAM_REQ_CMP) { > - printf("cdregister: camq_resize " > - "failed, changer support may " > - "be messed up\n"); > - } > - STAILQ_INSERT_TAIL(&nchanger->chluns, softc, > - changer_links); > - } > - } > - > - /* > * Schedule a periodic media polling events. > */ > callout_init_mtx(&softc->mediapoll_c, cam_periph_mtx(periph), 0); > if ((softc->flags & CD_FLAG_DISC_REMOVABLE) && > - (softc->flags & CD_FLAG_CHANGER) == 0 && > (cgd->inq_flags & SID_AEN) == 0 && > cd_poll_period != 0) > callout_reset(&softc->mediapoll_c, cd_poll_period * hz, > cdmediapoll, periph); > > -cdregisterexit: > - > - if ((softc->flags & CD_FLAG_CHANGER) == 0) > - xpt_schedule(periph, CAM_PRIORITY_DEV); > - else > - cdschedule(periph, CAM_PRIORITY_DEV); > - > + xpt_schedule(periph, CAM_PRIORITY_DEV); > return(CAM_REQ_CMP); > } > > @@ -1153,251 +781,6 @@ cdclose(struct disk *dp) > return (0); > } > > -static void > -cdshorttimeout(void *arg) > -{ > - struct cdchanger *changer; > - > - changer = (struct cdchanger *)arg; > - > - /* Always clear the short timeout flag, since that's what we're in */ > - changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; > - > - /* > - * Check to see if there is any more pending or outstanding I/O for > - * this device. If not, move it out of the active slot. > - */ > - if ((bioq_first(&changer->cur_device->bio_queue) == NULL) > - && (changer->cur_device->outstanding_cmds == 0)) { > - changer->flags |= CHANGER_MANUAL_CALL; > - cdrunchangerqueue(changer); > - } > -} > - > -/* > - * This is a wrapper for xpt_schedule. It only applies to changers. > - */ > -static void > -cdschedule(struct cam_periph *periph, int priority) > -{ > - struct cd_softc *softc; > - > - softc = (struct cd_softc *)periph->softc; > - > - /* > - * If this device isn't currently queued, and if it isn't > - * the active device, then we queue this device and run the > - * changer queue if there is no timeout scheduled to do it. > - * If this device is the active device, just schedule it > - * to run again. If this device is queued, there should be > - * a timeout in place already that will make sure it runs. > - */ > - if ((softc->pinfo.index == CAM_UNQUEUED_INDEX) > - && ((softc->flags & CD_FLAG_ACTIVE) == 0)) { > - /* > - * We don't do anything with the priority here. > - * This is strictly a fifo queue. > - */ > - softc->pinfo.priority = CAM_PRIORITY_NORMAL; > - softc->pinfo.generation = ++softc->changer->devq.generation; > - camq_insert(&softc->changer->devq, (cam_pinfo *)softc); > - > - /* > - * Since we just put a device in the changer queue, > - * check and see if there is a timeout scheduled for > - * this changer. If so, let the timeout handle > - * switching this device into the active slot. If > - * not, manually call the timeout routine to > - * bootstrap things. > - */ > - if (((softc->changer->flags & CHANGER_TIMEOUT_SCHED)==0) > - && ((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0) > - && ((softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED)==0)){ > - softc->changer->flags |= CHANGER_MANUAL_CALL; > - cdrunchangerqueue(softc->changer); > - } > - } else if ((softc->flags & CD_FLAG_ACTIVE) > - && ((softc->flags & CD_FLAG_SCHED_ON_COMP) == 0)) > - xpt_schedule(periph, priority); > -} > - > -static void > -cdrunchangerqueue(void *arg) > -{ > - struct cd_softc *softc; > - struct cdchanger *changer; > - int called_from_timeout; > - > - changer = (struct cdchanger *)arg; > - > - /* > - * If we have NOT been called from cdstrategy() or cddone(), and > - * instead from a timeout routine, go ahead and clear the > - * timeout flag. > - */ > - if ((changer->flags & CHANGER_MANUAL_CALL) == 0) { > - changer->flags &= ~CHANGER_TIMEOUT_SCHED; > - called_from_timeout = 1; > - } else > - called_from_timeout = 0; > - > - /* Always clear the manual call flag */ > - changer->flags &= ~CHANGER_MANUAL_CALL; > - > - /* nothing to do if the queue is empty */ > - if (changer->devq.entries <= 0) { > - return; > - } > - > - /* > - * If the changer queue is frozen, that means we have an active > - * device. > - */ > - if (changer->devq.qfrozen_cnt > 0) { > - > - /* > - * We always need to reset the frozen count and clear the > - * active flag. > - */ > - changer->devq.qfrozen_cnt--; > - changer->cur_device->flags &= ~CD_FLAG_ACTIVE; > - changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP; > - > - if (changer->cur_device->outstanding_cmds > 0) { > - changer->cur_device->flags |= CD_FLAG_SCHED_ON_COMP; > - changer->cur_device->bufs_left = > - changer->cur_device->outstanding_cmds; > - if (called_from_timeout) { > - callout_reset(&changer->long_handle, > - changer_max_busy_seconds * hz, > - cdrunchangerqueue, changer); > - changer->flags |= CHANGER_TIMEOUT_SCHED; > - } > - return; > - } > - > - /* > - * Check to see whether the current device has any I/O left > - * to do. If so, requeue it at the end of the queue. If > - * not, there is no need to requeue it. > - */ > - if (bioq_first(&changer->cur_device->bio_queue) != NULL) { > - > - changer->cur_device->pinfo.generation = > - ++changer->devq.generation; > - camq_insert(&changer->devq, > - (cam_pinfo *)changer->cur_device); > - } > - } > - > - softc = (struct cd_softc *)camq_remove(&changer->devq, CAMQ_HEAD); > - > - changer->cur_device = softc; > - > - changer->devq.qfrozen_cnt++; > - softc->flags |= CD_FLAG_ACTIVE; > - > - /* Just in case this device is waiting */ > - wakeup(&softc->changer); > - xpt_schedule(softc->periph, CAM_PRIORITY_NORMAL); > - > - /* > - * Get rid of any pending timeouts, and set a flag to schedule new > - * ones so this device gets its full time quantum. > - */ > - if (changer->flags & CHANGER_TIMEOUT_SCHED) { > - callout_stop(&changer->long_handle); > - changer->flags &= ~CHANGER_TIMEOUT_SCHED; > - } > - > - if (changer->flags & CHANGER_SHORT_TMOUT_SCHED) { > - callout_stop(&changer->short_handle); > - changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; > - } > - > - /* > - * We need to schedule timeouts, but we only do this after the > - * first transaction has completed. This eliminates the changer > - * switch time. > - */ > - changer->flags |= CHANGER_NEED_TIMEOUT; > -} > - > -static void > -cdchangerschedule(struct cd_softc *softc) > -{ > - struct cdchanger *changer; > - > - changer = softc->changer; > - > - /* > - * If this is a changer, and this is the current device, > - * and this device has at least the minimum time quantum to > - * run, see if we can switch it out. > - */ > - if ((softc->flags & CD_FLAG_ACTIVE) > - && ((changer->flags & CHANGER_SHORT_TMOUT_SCHED) == 0) > - && ((changer->flags & CHANGER_NEED_TIMEOUT) == 0)) { > - /* > - * We try three things here. The first is that we > - * check to see whether the schedule on completion > - * flag is set. If it is, we decrement the number > - * of buffers left, and if it's zero, we reschedule. > - * Next, we check to see whether the pending buffer > - * queue is empty and whether there are no > - * outstanding transactions. If so, we reschedule. > - * Next, we see if the pending buffer queue is empty. > - * If it is, we set the number of buffers left to > - * the current active buffer count and set the > - * schedule on complete flag. > - */ > - if (softc->flags & CD_FLAG_SCHED_ON_COMP) { > - if (--softc->bufs_left == 0) { > - softc->changer->flags |= > - CHANGER_MANUAL_CALL; > - softc->flags &= ~CD_FLAG_SCHED_ON_COMP; > - cdrunchangerqueue(softc->changer); > - } > - } else if ((bioq_first(&softc->bio_queue) == NULL) > - && (softc->outstanding_cmds == 0)) { > - softc->changer->flags |= CHANGER_MANUAL_CALL; > - cdrunchangerqueue(softc->changer); > - } > - } else if ((softc->changer->flags & CHANGER_NEED_TIMEOUT) > - && (softc->flags & CD_FLAG_ACTIVE)) { > - > - /* > - * Now that the first transaction to this > - * particular device has completed, we can go ahead > - * and schedule our timeouts. > - */ > - if ((changer->flags & CHANGER_TIMEOUT_SCHED) == 0) { > - callout_reset(&changer->long_handle, > - changer_max_busy_seconds * hz, > - cdrunchangerqueue, changer); > - changer->flags |= CHANGER_TIMEOUT_SCHED; > - } else > - printf("cdchangerschedule: already have a long" > - " timeout!\n"); > - > - if ((changer->flags & CHANGER_SHORT_TMOUT_SCHED) == 0) { > - callout_reset(&changer->short_handle, > - changer_min_busy_seconds * hz, > - cdshorttimeout, changer); > - changer->flags |= CHANGER_SHORT_TMOUT_SCHED; > - } else > - printf("cdchangerschedule: already have a short " > - "timeout!\n"); > - > - /* > - * We just scheduled timeouts, no need to schedule > - * more. > - */ > - changer->flags &= ~CHANGER_NEED_TIMEOUT; > - > - } > -} > - > static int > cdrunccb(union ccb *ccb, int (*error_routine)(union ccb *ccb, > u_int32_t cam_flags, > @@ -1414,50 +797,9 @@ cdrunccb(union ccb *ccb, int (*error_rou > error = cam_periph_runccb(ccb, error_routine, cam_flags, sense_flags, > softc->disk->d_devstat); > > - if (softc->flags & CD_FLAG_CHANGER) > - cdchangerschedule(softc); > - > return(error); > } > > -static union ccb * > -cdgetccb(struct cam_periph *periph, u_int32_t priority) > -{ > - struct cd_softc *softc; > - > - softc = (struct cd_softc *)periph->softc; > - > - if (softc->flags & CD_FLAG_CHANGER) { > - /* > - * This should work the first time this device is woken up, > - * but just in case it doesn't, we use a while loop. > - */ > - while ((softc->flags & CD_FLAG_ACTIVE) == 0) { > - /* > - * If this changer isn't already queued, queue it up. > - */ > - if (softc->pinfo.index == CAM_UNQUEUED_INDEX) { > - softc->pinfo.priority = CAM_PRIORITY_NORMAL; > - softc->pinfo.generation = > - ++softc->changer->devq.generation; > - camq_insert(&softc->changer->devq, > - (cam_pinfo *)softc); > - } > - if (((softc->changer->flags & CHANGER_TIMEOUT_SCHED)==0) > - && ((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0) > - && ((softc->changer->flags > - & CHANGER_SHORT_TMOUT_SCHED)==0)) { > - softc->changer->flags |= CHANGER_MANUAL_CALL; > - cdrunchangerqueue(softc->changer); > - } else > - cam_periph_sleep(periph, &softc->changer, > - PRIBIO, "cgticb", 0); > - } > - } > - return(cam_periph_getccb(periph, priority)); > -} > - > - > /* > * Actually translate the requested transfer into one the physical driver > * can understand. The transfer is described by a buf and will include > @@ -1505,14 +847,7 @@ cdstrategy(struct bio *bp) > */ > bioq_disksort(&softc->bio_queue, bp); > > - /* > - * Schedule ourselves for performing the work. We do things > - * differently for changers. > - */ > - if ((softc->flags & CD_FLAG_CHANGER) == 0) > - xpt_schedule(periph, CAM_PRIORITY_NORMAL); > - else > - cdschedule(periph, CAM_PRIORITY_NORMAL); > + xpt_schedule(periph, CAM_PRIORITY_NORMAL); > > cam_periph_unlock(periph); > return; > @@ -1699,9 +1034,6 @@ cddone(struct cam_periph *periph, union > LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); > softc->outstanding_cmds--; > > - if (softc->flags & CD_FLAG_CHANGER) > - cdchangerschedule(softc); > - > biofinish(bp, NULL, 0); > break; > } > @@ -1864,8 +1196,6 @@ cddone(struct cam_periph *periph, union > xpt_announce_periph(periph, announce_buf); > xpt_announce_quirks(periph, softc->quirks, > CD_Q_BIT_STRING); > - if (softc->flags & CD_FLAG_CHANGER) > - cdchangerschedule(softc); > /* > * Create our sysctl variables, now that we know > * we have successfully attached. > @@ -2841,7 +2171,7 @@ cdprevent(struct cam_periph *periph, int > return; > } > > - ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); > + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); > > scsi_prevent(&ccb->csio, > /*retries*/ cd_retry_count, > @@ -3021,7 +2351,7 @@ cdsize(struct cam_periph *periph, u_int3 > > softc = (struct cd_softc *)periph->softc; > > - ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); > + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); > > /* XXX Should be M_WAITOK */ > rcap_buf = malloc(sizeof(struct scsi_read_capacity_data), > @@ -3266,9 +2596,6 @@ cdmediapoll(void *arg) > struct cam_periph *periph = arg; > struct cd_softc *softc = periph->softc; > > - if (softc->flags & CD_FLAG_CHANGER) > - return; > - > if (softc->state == CD_STATE_NORMAL && !softc->tur && > softc->outstanding_cmds == 0) { > if (cam_periph_acquire(periph) == CAM_REQ_CMP) { > @@ -3297,7 +2624,7 @@ cdreadtoc(struct cam_periph *periph, u_i > ntoc = len; > error = 0; > > - ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); > + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); > > csio = &ccb->csio; > > @@ -3344,7 +2671,7 @@ cdreadsubchannel(struct cam_periph *peri > > error = 0; > > - ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); > + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); > > csio = &ccb->csio; > > @@ -3396,7 +2723,7 @@ cdgetmode(struct cam_periph *periph, str > > *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** > >