Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Apr 2014 15:44:43 +0100
From:      "Steven Hartland" <killing@multiplay.co.uk>
To:        "Alexander Motin" <mav@FreeBSD.org>, <src-committers@freebsd.org>, <svn-src-all@freebsd.org>, <svn-src-stable@freebsd.org>, <svn-src-stable-10@freebsd.org>
Subject:   Re: svn commit: r264522 - in stable/10: share/man/man4 sys/cam/scsi
Message-ID:  <0A192F0FA084413FA4840BDCE2F3CAA8@multiplay.co.uk>
References:  <201404161004.s3GA4K4u052569@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Does this need r264311 MFC'ed too mav?

    Regards
    Steve
----- Original Message ----- 
From: "Alexander Motin" <mav@FreeBSD.org>
To: <src-committers@freebsd.org>; <svn-src-all@freebsd.org>; <svn-src-stable@freebsd.org>; <svn-src-stable-10@freebsd.org>
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 ***
> 
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?0A192F0FA084413FA4840BDCE2F3CAA8>