ID: 85 - Supermicro memory ecc error display

Commit adds memory ECC error display for Supermicro boards and adds a
Supermicro oem sensor type for SEL.
This commit is contained in:
Zdenek Styblik 2013-12-17 04:56:18 +00:00
parent 3a852a8849
commit 2d7fe32687
3 changed files with 196 additions and 4 deletions

View File

@ -281,7 +281,8 @@ typedef enum IPMI_OEM {
IPMI_OEM_KONTRON = 15000,
IPMI_OEM_PPS = 16394,
IPMI_OEM_AMI = 20974,
IPMI_OEM_NOKIA_SIEMENS_NETWORKS = 28458
IPMI_OEM_NOKIA_SIEMENS_NETWORKS = 28458,
IPMI_OEM_SUPERMICRO_47488 = 47488
} IPMI_OEM;
extern const struct valstr completion_code_vals[];

View File

@ -107,6 +107,7 @@ struct standard_spec_sel_rec{
#define SENSOR_TYPE_OEM_NFATAL_ERROR 0xC2
#define SENSOR_TYPE_OEM_FATAL_ERROR 0xC3
#define SENSOR_TYPE_TXT_CMD_ERROR 0x20
#define SENSOR_TYPE_SUPERMICRO_OEM 0xD0
/* End of Macro for DELL Specific */
#define SEL_OEM_TS_DATA_LEN 6
#define SEL_OEM_NOTS_DATA_LEN 13
@ -676,6 +677,56 @@ static struct ipmi_event_sensor_types sensor_specific_types[] __attribute__((unu
{ 0x00, 0x00, 0x00, 0x00, NULL, NULL },
};
static uint16_t supermicro_x9dal[] = {
0x0635
};
static uint16_t supermicro_x9db[] = {
0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637
};
static uint16_t supermicro_x9sb[] = {
0x0651
};
static uint16_t supermicro_x9[] = {
0x0635, 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0x0651
};
static uint16_t supermicro_b8[] = {
0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e
};
static uint16_t supermicro_h8[] = {
0xa111, 0x0408, 0x0811, 0x1411, 0x0911, 0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11,
0xbc11, 0xa911, 0xaa11, 0xbd11, 0xcb11, 0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611,
0x2511, 0xbf11, 0x1511, 0x2211, 0x2411, 0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211,
0xa311, 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, 0xcf11, 0x2011, 0x1811
};
static uint16_t supermicro_p8[] = {
0x6480, 0x7380, 0x6280, 0x7480, 0x5980
};
static uint16_t supermicro_x8[] = {
0xa880, 0x0403, 0x0100, 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006,
0x040a, 0xf280, 0x060f, 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614,
0x060c, 0x0003, 0x040b, 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e,
0x061a, 0xf580, 0x062e, 0x0009
};
static uint16_t supermicro_X8[] = {
0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e, 0xa111, 0x0408, 0x0811, 0x1411, 0x0911,
0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11, 0xbc11, 0xa911, 0xaa11, 0xbd11, 0xcb11,
0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611, 0x2511, 0xbf11, 0x1511, 0x2211, 0x2411,
0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211, 0xa311, 0x1311, 0xba11, 0xa711, 0xd111,
0x1711, 0xcf11, 0x2011, 0x1811, 0x6480, 0x7380, 0x6280, 0x7480, 0x5980, 0xa880, 0x0403, 0x0100,
0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, 0x040a, 0xf280, 0x060f,
0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, 0x060c, 0x0003, 0x040b,
0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, 0x061a, 0xf580, 0x062e,
0x0009
};
int ipmi_sel_main(struct ipmi_intf *, int, char **);
void ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt);
void ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_record * evt);

View File

@ -322,7 +322,6 @@ ipmi_get_oem(struct ipmi_intf * intf)
return IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id);
}
static int
ipmi_sel_add_entry(struct ipmi_intf * intf, struct sel_event_record * rec)
{
@ -526,6 +525,115 @@ get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
return description;
}
char *
get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
char *desc = NULL;
char *str;
int chipset_type = 1;
int data1;
int data2;
int data3;
int length;
int sensor_type;
uint8_t i = 0;
uint16_t oem_id = 0;
/* Get the OEM event Bytes of the SEL Records byte 13, 14, 15 to
* data1,data2,data3
*/
data1 = rec->sel_type.standard_type.event_data[0];
data2 = rec->sel_type.standard_type.event_data[1];
data3 = rec->sel_type.standard_type.event_data[2];
/* Check for the Standard Event type == 0x6F */
if (rec->sel_type.standard_type.event_type != 0x6F) {
return NULL;
}
/* Allocate mem for te Description string */
desc = (char *)malloc(SIZE_OF_DESC);
if (desc == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return NULL;
}
memset(desc,0,SIZE_OF_DESC);
sensor_type = rec->sel_type.standard_type.sensor_type;
switch (sensor_type) {
case SENSOR_TYPE_MEMORY:
memset(&req, 0, sizeof (req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.lun = 0;
req.msg.cmd = BMC_GET_DEVICE_ID;
req.msg.data = NULL;
req.msg.data_len = 0;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, " Error getting system info");
if (desc != NULL) {
free(desc);
desc = NULL;
}
return NULL;
} else if (rsp->ccode > 0) {
lprintf(LOG_ERR, " Error getting system info: %s",
val2str(rsp->ccode, completion_code_vals));
if (desc != NULL) {
free(desc);
desc = NULL;
}
return NULL;
}
/* check the chipset type */
oem_id = ipmi_get_oem_id(intf);
if (oem_id == 0) {
return NULL;
}
length = sizeof(supermicro_X8);
for (i = 0; i < length; i++) {
if (oem_id == supermicro_X8[i]) {
chipset_type = 0;
break;
}
}
length = sizeof(supermicro_x9);
for (i = 0; i < length; i++) {
if (oem_id == supermicro_x9[i]) {
chipset_type = 2;
break;
}
}
if (chipset_type == 0) {
snprintf(desc, SIZE_OF_DESC, "@DIMM%2X(CPU%x)",
data2,
(data3 & 0x03) + 1);
} else if (chipset_type == 1) {
snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)",
(data2 >> 4) + 0x40 + (data3 & 0x3) * 4,
(data2 & 0xf) + 0x27, (data3 & 0x03) + 1);
} else if (chipset_type == 2) {
snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)",
(data2 >> 4) + 0x40 + (data3 & 0x3) * 3,
(data2 & 0xf) + 0x27, (data3 & 0x03) + 1);
} else {
snprintf(desc, SIZE_OF_DESC, "");
}
break;
case SENSOR_TYPE_SUPERMICRO_OEM:
if (data1 == 0x80 && data3 == 0xFF) {
if (data2 == 0x0) {
snprintf(desc, SIZE_OF_DESC, "BMC unexpected reset");
} else if (data2 == 0x1) {
snprintf(desc, SIZE_OF_DESC, "BMC cold reset");
} else if (data2 == 0x2) {
snprintf(desc, SIZE_OF_DESC, "BMC warm reset");
}
}
break;
}
return desc;
}
/*
* Function : Decoding the SEL OEM Bytes for the DELL Platforms.
* Description : The below fucntion will decode the SEL Events OEM Bytes for the Dell specific Sensors only.
@ -1067,6 +1175,10 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
case IPMI_OEM_DELL: // Dell Decoding of the OEM Bytes from SEL Record.
desc = get_dell_evt_desc(intf, rec);
break;
case IPMI_OEM_SUPERMICRO:
case IPMI_OEM_SUPERMICRO_47488:
desc = get_supermicro_evt_desc(intf, rec);
break;
case IPMI_OEM_UNKNOWN:
default:
break;
@ -1092,7 +1204,6 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
*desc = ipmi_get_oem_desc(intf, rec);
return;
} else if (rec->sel_type.standard_type.event_type == 0x6f) {
if( rec->sel_type.standard_type.sensor_type >= 0xC0 && rec->sel_type.standard_type.sensor_type < 0xF0) {
IPMI_OEM iana = ipmi_get_oem(intf);
@ -1116,12 +1227,27 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
sfx = ipmi_get_oem_desc(intf, rec);
}
break;
case IPMI_OEM_SUPERMICRO:
case IPMI_OEM_SUPERMICRO_47488:
evt = sensor_specific_types;
code = rec->sel_type.standard_type.sensor_type;
sfx = ipmi_get_oem_desc(intf, rec);
break;
/* add your oem sensor assignation here */
}
if( evt == NULL ){
lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description",
rec->sel_type.standard_type.sensor_type );
}
} else {
switch (ipmi_get_oem(intf)) {
case IPMI_OEM_SUPERMICRO:
case IPMI_OEM_SUPERMICRO_47488:
evt = sensor_specific_types;
code = rec->sel_type.standard_type.sensor_type;
sfx = ipmi_get_oem_desc(intf, rec);
break;
}
}
if( evt == NULL ){
evt = sensor_specific_types;
@ -1210,6 +1336,9 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
if(0x01 == offset)
flag = 0x01;
break;
case SENSOR_TYPE_SUPERMICRO_OEM:
flag = 0x02;
break;
default:
break;
}
@ -1222,6 +1351,10 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
return;
}
memset(*desc, 0, 48 + SIZE_OF_DESC);
if (flag == 0x02) {
sprintf(*desc, "%s", sfx);
return;
}
sprintf(*desc, "(%s)",sfx);
}
free(sfx);
@ -1776,10 +1909,17 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt)
}
}
else if (evt->sel_type.standard_type.event_type == 0x6f) {
int print_sensor = 1;
switch (ipmi_get_oem(intf)) {
case IPMI_OEM_SUPERMICRO:
case IPMI_OEM_SUPERMICRO_47488:
print_sensor = 0;
break;
}
/*
* Sensor-Specific Discrete
*/
if (evt->sel_type.standard_type.sensor_type == 0xC &&
if (print_sensor && evt->sel_type.standard_type.sensor_type == 0xC && /*TODO*/
evt->sel_type.standard_type.sensor_num == 0 &&
(evt->sel_type.standard_type.event_data[0] & 0x30) == 0x20) {
/* break down memory ECC reporting if we can */