The following reply was made to PR kern/140752; it has been noted by GNATS.

From: dfil...@freebsd.org (dfilter service)
To: bug-follo...@freebsd.org
Cc:  
Subject: Re: kern/140752: commit references a PR
Date: Sun, 24 Oct 2010 16:32:04 +0000 (UTC)

 Author: brucec
 Date: Sun Oct 24 16:31:57 2010
 New Revision: 214279
 URL: http://svn.freebsd.org/changeset/base/214279
 
 Log:
   Mostly revert r203420, and add similar functionality into ada(4) since the
   existing code caused problems with some SCSI controllers.
   
   A new sysctl kern.cam.ada.spindown_shutdown has been added that controls
   whether or not to spin-down disks when shutting down.
   Spinning down the disks unloads/parks the heads - this is
   much better than removing power when the disk is still
   spinning because otherwise an Emergency Unload occurs which may cause damage
   to the actuator.
   
   PR:  kern/140752
   Submitted by:   olli
   Reviewed by: arundel
   Discussed with: mav
   MFC after:   2 weeks
 
 Modified:
   head/share/man/man4/ada.4
   head/sys/cam/ata/ata_da.c
   head/sys/cam/cam_xpt.c
   head/sys/kern/kern_shutdown.c
 
 Modified: head/share/man/man4/ada.4
 ==============================================================================
 --- head/share/man/man4/ada.4  Sun Oct 24 16:10:32 2010        (r214278)
 +++ head/share/man/man4/ada.4  Sun Oct 24 16:31:57 2010        (r214279)
 @@ -118,6 +118,9 @@ This variable determines how long the
  driver will wait before timing out an outstanding command.
  The units for this value are seconds, and the default is currently 30
  seconds.
 +.It kern.cam.ada.spindown_shutdown
 +.Pp
 +This variable determines whether to spin-down disks when shutting down.
  .El
  .Sh FILES
  .Bl -tag -width ".Pa /dev/ada*" -compact
 
 Modified: head/sys/cam/ata/ata_da.c
 ==============================================================================
 --- head/sys/cam/ata/ata_da.c  Sun Oct 24 16:10:32 2010        (r214278)
 +++ head/sys/cam/ata/ata_da.c  Sun Oct 24 16:31:57 2010        (r214279)
 @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/eventhandler.h>
  #include <sys/malloc.h>
  #include <sys/cons.h>
 +#include <sys/reboot.h>
  #include <geom/geom_disk.h>
  #endif /* _KERNEL */
  
 @@ -79,7 +80,8 @@ typedef enum {
        ADA_FLAG_CAN_TRIM       = 0x080,
        ADA_FLAG_OPEN           = 0x100,
        ADA_FLAG_SCTX_INIT      = 0x200,
 -      ADA_FLAG_CAN_CFA        = 0x400
 +      ADA_FLAG_CAN_CFA        = 0x400,
 +      ADA_FLAG_CAN_POWERMGT   = 0x800
  } ada_flags;
  
  typedef enum {
 @@ -180,6 +182,10 @@ static void               adashutdown(void *arg, int 
  #define       ADA_DEFAULT_SEND_ORDERED        1
  #endif
  
 +#ifndef       ADA_DEFAULT_SPINDOWN_SHUTDOWN
 +#define       ADA_DEFAULT_SPINDOWN_SHUTDOWN   1
 +#endif
 +
  /*
   * Most platforms map firmware geometry to actual, but some don't.  If
   * not overridden, default to nothing.
 @@ -191,6 +197,7 @@ static void                adashutdown(void *arg, int 
  static int ada_retry_count = ADA_DEFAULT_RETRY;
  static int ada_default_timeout = ADA_DEFAULT_TIMEOUT;
  static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED;
 +static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN;
  
  SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0,
              "CAM Direct Access Disk driver");
 @@ -203,6 +210,9 @@ TUNABLE_INT("kern.cam.ada.default_timeou
  SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW,
             &ada_send_ordered, 0, "Send Ordered Tags");
  TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered);
 +SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RW,
 +           &ada_spindown_shutdown, 0, "Spin down upon shutdown");
 +TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown);
  
  /*
   * ADA_ORDEREDTAG_INTERVAL determines how often, relative
 @@ -665,6 +675,8 @@ adaregister(struct cam_periph *periph, v
                softc->flags |= ADA_FLAG_CAN_48BIT;
        if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE)
                softc->flags |= ADA_FLAG_CAN_FLUSHCACHE;
 +      if (cgd->ident_data.support.command1 & ATA_SUPPORT_POWERMGT)
 +              softc->flags |= ADA_FLAG_CAN_POWERMGT;
        if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ &&
            cgd->inq_flags & SID_CmdQue)
                softc->flags |= ADA_FLAG_CAN_NCQ;
 @@ -1227,6 +1239,56 @@ adashutdown(void * arg, int howto)
                                         /*getcount_only*/0);
                cam_periph_unlock(periph);
        }
 +
 +      if (ada_spindown_shutdown == 0 ||
 +          (howto & (RB_HALT | RB_POWEROFF)) == 0)
 +              return;
 +
 +      TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
 +              union ccb ccb;
 +
 +              /* If we paniced with lock held - not recurse here. */
 +              if (cam_periph_owned(periph))
 +                      continue;
 +              cam_periph_lock(periph);
 +              softc = (struct ada_softc *)periph->softc;
 +              /*
 +               * We only spin-down the drive if it is capable of it..
 +               */
 +              if ((softc->flags & ADA_FLAG_CAN_POWERMGT) == 0) {
 +                      cam_periph_unlock(periph);
 +                      continue;
 +              }
 +
 +              if (bootverbose)
 +                      xpt_print(periph->path, "spin-down\n");
 +
 +              xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
 +
 +              ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
 +              cam_fill_ataio(&ccb.ataio,
 +                                  1,
 +                                  adadone,
 +                                  CAM_DIR_NONE,
 +                                  0,
 +                                  NULL,
 +                                  0,
 +                                  ada_default_timeout*1000);
 +
 +              ata_28bit_cmd(&ccb.ataio, ATA_STANDBY_IMMEDIATE, 0, 0, 0);
 +              xpt_polled_action(&ccb);
 +
 +              if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
 +                      xpt_print(periph->path, "Spin-down disk failed\n");
 +
 +              if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
 +                      cam_release_devq(ccb.ccb_h.path,
 +                                       /*relsim_flags*/0,
 +                                       /*reduction*/0,
 +                                       /*timeout*/0,
 +                                       /*getcount_only*/0);
 +              cam_periph_unlock(periph);
 +      }
  }
  
  #endif /* _KERNEL */
 
 Modified: head/sys/cam/cam_xpt.c
 ==============================================================================
 --- head/sys/cam/cam_xpt.c     Sun Oct 24 16:10:32 2010        (r214278)
 +++ head/sys/cam/cam_xpt.c     Sun Oct 24 16:31:57 2010        (r214279)
 @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
  #include <sys/time.h>
  #include <sys/conf.h>
  #include <sys/fcntl.h>
 -#include <sys/reboot.h>
  #include <sys/interrupt.h>
  #include <sys/sbuf.h>
  #include <sys/taskqueue.h>
 @@ -153,10 +152,6 @@ static struct xpt_softc xsoftc;
  TUNABLE_INT("kern.cam.boot_delay", &xsoftc.boot_delay);
  SYSCTL_INT(_kern_cam, OID_AUTO, boot_delay, CTLFLAG_RDTUN,
             &xsoftc.boot_delay, 0, "Bus registration wait time");
 -static int    xpt_power_down = 0;
 -TUNABLE_INT("kern.cam.power_down", &xpt_power_down);
 -SYSCTL_INT(_kern_cam, OID_AUTO, power_down, CTLFLAG_RW,
 -           &xpt_power_down, 0, "Power down devices on shutdown");
  
  /* Queues for our software interrupt handler */
  typedef TAILQ_HEAD(cam_isrq, ccb_hdr) cam_isrq_t;
 @@ -250,7 +245,6 @@ static struct cam_ed*
                 xpt_find_device(struct cam_et *target, lun_id_t lun_id);
  static void    xpt_config(void *arg);
  static xpt_devicefunc_t xptpassannouncefunc;
 -static void    xpt_shutdown(void *arg, int howto);
  static void    xptaction(struct cam_sim *sim, union ccb *work_ccb);
  static void    xptpoll(struct cam_sim *sim);
  static void    camisr(void *);
 @@ -4538,12 +4532,6 @@ xpt_config(void *arg)
  #endif /* CAM_DEBUG_BUS */
  #endif /* CAMDEBUG */
  
 -      /* Register our shutdown event handler */
 -      if ((EVENTHANDLER_REGISTER(shutdown_final, xpt_shutdown, 
 -                                 NULL, SHUTDOWN_PRI_FIRST)) == NULL) {
 -              printf("xpt_config: failed to register shutdown event.\n");
 -      }
 -
        periphdriver_init(1);
        xpt_hold_boot();
        callout_init(&xsoftc.boot_callout, 1);
 @@ -4625,87 +4613,6 @@ xpt_finishconfig_task(void *context, int
        free(context, M_CAMXPT);
  }
  
 -/*
 - * Power down all devices when we are going to power down the system.
 - */
 -static void
 -xpt_shutdown_dev_done(struct cam_periph *periph, union ccb *done_ccb)
 -{
 -
 -      /* No-op. We're polling. */
 -      return;
 -}
 -
 -static int
 -xpt_shutdown_dev(struct cam_ed *device, void *arg)
 -{
 -      union ccb ccb;
 -      struct cam_path path;
 -
 -      if (device->flags & CAM_DEV_UNCONFIGURED)
 -              return (1);
 -
 -      if (device->protocol == PROTO_ATA) {
 -              /* Only power down device if it supports power management. */
 -              if ((device->ident_data.support.command1 &
 -                  ATA_SUPPORT_POWERMGT) == 0)
 -                      return (1);
 -      } else if (device->protocol != PROTO_SCSI)
 -              return (1);
 -
 -      xpt_compile_path(&path,
 -                       NULL,
 -                       device->target->bus->path_id,
 -                       device->target->target_id,
 -                       device->lun_id);
 -      xpt_setup_ccb(&ccb.ccb_h, &path, CAM_PRIORITY_NORMAL);
 -      if (device->protocol == PROTO_ATA) {
 -              cam_fill_ataio(&ccb.ataio,
 -                                  1,
 -                                  xpt_shutdown_dev_done,
 -                                  CAM_DIR_NONE,
 -                                  0,
 -                                  NULL,
 -                                  0,
 -                                  30*1000);
 -              ata_28bit_cmd(&ccb.ataio, ATA_SLEEP, 0, 0, 0);
 -      } else {
 -              scsi_start_stop(&ccb.csio,
 -                              /*retries*/1,
 -                              xpt_shutdown_dev_done,
 -                              MSG_SIMPLE_Q_TAG,
 -                              /*start*/FALSE,
 -                              /*load/eject*/FALSE,
 -                              /*immediate*/TRUE,
 -                              SSD_FULL_SIZE,
 -                              /*timeout*/50*1000);
 -      }
 -      xpt_polled_action(&ccb);
 -
 -      if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
 -              xpt_print(&path, "Device power down failed\n");
 -      if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
 -              cam_release_devq(ccb.ccb_h.path,
 -                               /*relsim_flags*/0,
 -                               /*reduction*/0,
 -                               /*timeout*/0,
 -                               /*getcount_only*/0);
 -      xpt_release_path(&path);
 -      return (1);
 -}
 -
 -static void
 -xpt_shutdown(void * arg, int howto)
 -{
 -
 -      if (!xpt_power_down)
 -              return;
 -      if ((howto & RB_POWEROFF) == 0)
 -              return;
 -
 -      xpt_for_all_devices(xpt_shutdown_dev, NULL);
 -}
 -
  cam_status
  xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg,
                   struct cam_path *path)
 
 Modified: head/sys/kern/kern_shutdown.c
 ==============================================================================
 --- head/sys/kern/kern_shutdown.c      Sun Oct 24 16:10:32 2010        
(r214278)
 +++ head/sys/kern/kern_shutdown.c      Sun Oct 24 16:31:57 2010        
(r214279)
 @@ -144,7 +144,7 @@ shutdown_conf(void *unused)
  {
  
        EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL,
 -          SHUTDOWN_PRI_FIRST + 100);
 +          SHUTDOWN_PRI_FIRST);
        EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL,
            SHUTDOWN_PRI_LAST + 100);
        EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL,
 _______________________________________________
 svn-src-...@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"
 
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to