The branch main has been updated by avg:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=15910dc0bcb526d575f8cc49efe1f98a5091c88e

commit 15910dc0bcb526d575f8cc49efe1f98a5091c88e
Author:     Andriy Gapon <a...@freebsd.org>
AuthorDate: 2021-12-24 09:02:22 +0000
Commit:     Andriy Gapon <a...@freebsd.org>
CommitDate: 2021-12-24 09:02:22 +0000

    adaspindown: check disk power mode before sending IDLE command
    
    If a disk is already in STANDBY mode, then setting IDLE mode can
    actually spin it up.
    
    Reviewed by:    mav
    MFC after:      4 weeks
    Differential Revision:  https://reviews.freebsd.org/D33588
---
 sys/cam/ata/ata_da.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index c05a9fa49d1c..adfcc0ee1845 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -3611,6 +3611,7 @@ adaspindown(uint8_t cmd, int flags)
        struct ada_softc *softc;
        struct ccb_ataio local_ccb;
        int error;
+       int mode;
 
        CAM_PERIPH_FOREACH(periph, &adadriver) {
                /* If we paniced with lock held - not recurse here. */
@@ -3626,6 +3627,52 @@ adaspindown(uint8_t cmd, int flags)
                        continue;
                }
 
+               /*
+                * Additionally check if we would spin up the drive instead of
+                * spinning it down.
+                */
+               if (cmd == ATA_IDLE_IMMEDIATE) {
+                       memset(&local_ccb, 0, sizeof(local_ccb));
+                       xpt_setup_ccb(&local_ccb.ccb_h, periph->path,
+                           CAM_PRIORITY_NORMAL);
+                       local_ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
+
+                       cam_fill_ataio(&local_ccb, 0, NULL, CAM_DIR_NONE,
+                           0, NULL, 0, ada_default_timeout * 1000);
+                       ata_28bit_cmd(&local_ccb, ATA_CHECK_POWER_MODE,
+                           0, 0, 0);
+                       local_ccb.cmd.flags |= CAM_ATAIO_NEEDRESULT;
+
+                       error = cam_periph_runccb((union ccb *)&local_ccb,
+                           adaerror, /*cam_flags*/0,
+                           /*sense_flags*/ SF_NO_RECOVERY | SF_NO_RETRY,
+                           softc->disk->d_devstat);
+                       if (error != 0) {
+                               xpt_print(periph->path,
+                                   "Failed to read current power mode\n");
+                       } else {
+                               mode = local_ccb.res.sector_count;
+#ifdef DIAGNOSTIC
+                               if (bootverbose) {
+                                       xpt_print(periph->path,
+                                           "disk power mode 0x%02x\n", mode);
+                               }
+#endif
+                               switch (mode) {
+                               case 0x00:
+                               case 0x01:
+                                       if (bootverbose) {
+                                               xpt_print(periph->path,
+                                                   "already spun down\n");
+                                       }
+                                       cam_periph_unlock(periph);
+                                       continue;
+                               default:
+                                       break;
+                               }
+                       }
+               }
+
                if (bootverbose)
                        xpt_print(periph->path, "spin-down\n");
 

Reply via email to