The branch main has been updated by mav:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2e19fae49fd4ab2360971463cee99a62198973b1

commit 2e19fae49fd4ab2360971463cee99a62198973b1
Author:     Alexander Motin <[email protected]>
AuthorDate: 2022-01-13 18:45:28 +0000
Commit:     Alexander Motin <[email protected]>
CommitDate: 2022-01-13 18:57:35 +0000

    sesutil: Avoid setting reserved bits.
    
    Weird side of SES specification is that some bits have different
    meaning or semantics in status and control pages.  This patch fixes
    non-zero writes into reserved fields, that caused errors on some
    enclosures when trying to control locate/fault LEDs, keeping other
    bits unchanged.
    
    MFC after:      2 weeks
    Sposonred by:   iXsystems, Inc.
---
 sys/cam/scsi/scsi_ses.h    | 44 ++++++++++++++++++++++++++++++++++++++++++++
 usr.sbin/sesutil/sesutil.c |  3 ++-
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/sys/cam/scsi/scsi_ses.h b/sys/cam/scsi/scsi_ses.h
index 86cc88ad27f1..8a1c7118f99a 100644
--- a/sys/cam/scsi/scsi_ses.h
+++ b/sys/cam/scsi/scsi_ses.h
@@ -2058,6 +2058,50 @@ union ses_status_element {
        uint8_t                             bytes[4];
 };
 
+/*
+ * Convert element status into control as much as possible.
+ * Some bits have different meaning in status and control,
+ * while others have the same and should be preserved.
+ */
+static inline void
+ses_status_to_ctrl(uint8_t type, uint8_t *bytes)
+{
+       /* Updated to SES4r5. */
+       static const uint8_t mask[][4] = {
+           { 0x60, 0x00, 0x00, 0x00 }, /* UNSPECIFIED */
+           { 0x60, 0x00, 0x4e, 0x3c }, /* DEVICE */
+           { 0x60, 0xc0, 0x00, 0x60 }, /* POWER */
+           { 0x60, 0xc0, 0x00, 0x60 }, /* COOLING/FAN */
+           { 0x60, 0xc0, 0x00, 0x80 }, /* THERM */
+           { 0x60, 0xc0, 0x00, 0x01 }, /* DOORLOCK */
+           { 0x60, 0xc0, 0x00, 0x5f }, /* ALARM */
+           { 0x60, 0xf0, 0x01, 0x00 }, /* ESSC */
+           { 0x60, 0xc0, 0x00, 0x00 }, /* SCC */
+           { 0x60, 0xc0, 0x00, 0x00 }, /* NVRAM */
+           { 0x60, 0x00, 0x00, 0x00 }, /* INV_OP_REASON */
+           { 0x60, 0x00, 0x00, 0xe0 }, /* UPS */
+           { 0x60, 0xc0, 0xff, 0xff }, /* DISPLAY */
+           { 0x60, 0xc0, 0x00, 0x00 }, /* KEYPAD */
+           { 0x60, 0x80, 0x00, 0xff }, /* ENCLOSURE */
+           { 0x60, 0xc0, 0x00, 0x10 }, /* SCSIXVR */
+           { 0x60, 0x80, 0xff, 0xff }, /* LANGUAGE */
+           { 0x60, 0xc0, 0x00, 0x01 }, /* COMPORT */
+           { 0x60, 0xc0, 0x00, 0x00 }, /* VOM */
+           { 0x60, 0xc0, 0x00, 0x00 }, /* AMMETER */
+           { 0x60, 0xc0, 0x00, 0x01 }, /* SCSI_TGT */
+           { 0x60, 0xc0, 0x00, 0x01 }, /* SCSI_INI*/
+           { 0x60, 0xc0, 0x00, 0x00 }, /* SUBENC */
+           { 0x60, 0xff, 0x4e, 0x3c }, /* ARRAY_DEV */
+           { 0x60, 0xc0, 0x00, 0x00 }, /* SAS_EXP */
+           { 0x60, 0x80, 0x00, 0x40 }, /* SAS_CONN */
+       };
+
+       if (type >= sizeof(mask) / sizeof(mask[0]))
+               type = 0;
+       for (int i = 0; i < 4; i++)
+               bytes[i] &= mask[type][i];
+}
+
 /*===================== SCSI SES Status Diagnostic Page =====================*/
 struct ses_status_page {
        struct ses_page_hdr  hdr;
diff --git a/usr.sbin/sesutil/sesutil.c b/usr.sbin/sesutil/sesutil.c
index 9e6098e1da35..d78a9172e454 100644
--- a/usr.sbin/sesutil/sesutil.c
+++ b/usr.sbin/sesutil/sesutil.c
@@ -138,10 +138,11 @@ do_led(int fd, unsigned int idx, elm_type_t type, bool 
onoff, bool setfault)
                close(fd);
                xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
        }
-       slot = (struct ses_ctrl_dev_slot *) &o.cstat[0];
+       ses_status_to_ctrl(type, &o.cstat[0]);
        switch (type) {
        case ELMTYP_DEVICE:
        case ELMTYP_ARRAY_DEV:
+               slot = (struct ses_ctrl_dev_slot *) &o.cstat[0];
                ses_ctrl_common_set_select(&slot->common, 1);
                if (setfault)
                        ses_ctrl_dev_slot_set_rqst_fault(slot, state);

Reply via email to