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.
This commit is contained in:
parent
1d41a49404
commit
2e19fae49f
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user