From patchwork Mon Aug 10 05:22:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasant Hegde X-Patchwork-Id: 505514 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id AA4E51401F6 for ; Mon, 10 Aug 2015 15:22:28 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 781B31A0CCE for ; Mon, 10 Aug 2015 15:22:28 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from e28smtp06.in.ibm.com (e28smtp06.in.ibm.com [122.248.162.6]) (using TLSv1 with cipher CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 5362A1A03A0 for ; Mon, 10 Aug 2015 15:22:24 +1000 (AEST) Received: from /spool/local by e28smtp06.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 10 Aug 2015 10:52:21 +0530 Received: from d28dlp01.in.ibm.com (9.184.220.126) by e28smtp06.in.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 10 Aug 2015 10:52:20 +0530 X-Helo: d28dlp01.in.ibm.com X-MailFrom: hegdevasant@linux.vnet.ibm.com X-RcptTo: skiboot@lists.ozlabs.org Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by d28dlp01.in.ibm.com (Postfix) with ESMTP id D0D8BE004C for ; Mon, 10 Aug 2015 10:56:37 +0530 (IST) Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay03.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t7A5MI496554024 for ; Mon, 10 Aug 2015 10:52:18 +0530 Received: from d28av03.in.ibm.com (localhost [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t7A5MKUf031734 for ; Mon, 10 Aug 2015 10:52:20 +0530 Received: from hegdevasant.in.ibm.com (hegdevasant.in.ibm.com [9.124.35.172]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t7A5MKYC031719; Mon, 10 Aug 2015 10:52:20 +0530 From: Vasant Hegde To: skiboot@lists.ozlabs.org Date: Mon, 10 Aug 2015 10:52:13 +0530 Message-Id: <1439184133-20524-1-git-send-email-hegdevasant@linux.vnet.ibm.com> X-Mailer: git-send-email 2.1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15081005-0021-0000-0000-000006BC5D40 Subject: [Skiboot] [PATCH v3] IPMI: Fix eSEL logging X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alistair Popple MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Presently we are passing PEL log without adding Extended SEL record. Hence logging eSEL event is failing. This patch sends Extended SEL structure before sending actual PEL log. So that BMC understands its eSEL log and logs it appropriately. eSEL format: : : Note that we use sensor type "System Event (0x12)" for logging OPAL events. Signed-off-by: Vasant Hegde Cc: Alistair Popple Cc: Jeremy Kerr --- hw/ipmi/ipmi-sel.c | 125 +++++++++++++++++++++++++++++++++++++++++++++----- hw/ipmi/ipmi-sensor.c | 5 ++ include/ipmi.h | 3 ++ 3 files changed, 121 insertions(+), 12 deletions(-) diff --git a/hw/ipmi/ipmi-sel.c b/hw/ipmi/ipmi-sel.c index e672ecf..f03f19e 100644 --- a/hw/ipmi/ipmi-sel.c +++ b/hw/ipmi/ipmi-sel.c @@ -44,6 +44,74 @@ #define RELEASE_PNOR 0x00 #define REQUEST_PNOR 0x01 +/* 32.1 SEL Event Records type */ +#define SEL_REC_TYPE_SYS_EVENT 0x02 +#define SEL_REC_TYPE_AMI_ESEL 0xDF + +/* OEM SEL generator ID for AMI */ +#define SEL_GENERATOR_ID_AMI 0x2000 + +/* IPMI SEL version */ +#define SEL_EVM_VER_1 0x03 +#define SEL_EVM_VER_2 0x04 + +/* + * Sensor type for System events + * + * Sensor information (type, number, etc) is passed to us via + * device tree. Currently we are using System Event type to + * log OPAL events. + */ +#define SENSOR_TYPE_SYS_EVENT 0x12 + +/* + * 42.1 Event/Reading Type Codes + * + * Note that device hotplug and availability related events + * are not defined as we are not using those events type. + */ +#define SEL_EVENT_DIR_TYPE_UNSPECIFIED 0x00 +#define SEL_EVENT_DIR_TYPE_THRESHOLD 0x01 +#define SEL_EVENT_DIR_TYPE_STATE 0x03 +#define SEL_EVENT_DIR_TYPE_PREDICTIVE 0x04 +#define SEL_EVENT_DIR_TYPE_LIMIT 0x05 +#define SEL_EVENT_DIR_TYPE_PERFORMANCE 0x06 +#define SEL_EVENT_DIR_TYPE_TRANSITION 0x07 +#define SEL_EVENT_DIR_TYPE_OEM 0x70 + +/* + * 42.1 Event/Reading Type Codes + */ +#define SEL_DATA1_AMI 0xAA +#define SEL_DATA1_DEASSERTED 0x00 +#define SEL_DATA1_ASSERTED 0x01 +#define SEL_DATA1_OK 0x00 +#define SEL_DATA1_NON_CRIT_FROM_OK 0x01 +#define SEL_DATA1_CRIT_FROM_LESS_SEV 0x02 +#define SEL_DATA1_NON_REC_FROM_LESS_SEV 0x03 +#define SEL_DATA1_NON_CRIT 0x04 +#define SEL_DATA1_CRITICAL 0x05 +#define SEL_DATA1_NON_RECOVERABLE 0X06 +#define SEL_DATA1_MONITOR 0x07 +#define SEL_DATA1_INFORMATIONAL 0x08 + +/* SEL Record Entry */ +struct sel_record { + le16 record_id; + uint8_t record_type; + le32 timestamp; + le16 generator_id; + uint8_t evm_ver; + uint8_t sensor_type; + uint8_t sensor_number; + uint8_t event_dir_type; + uint8_t event_data1; + uint8_t event_data2; + uint8_t event_data3; +} __packed; + +static struct sel_record sel_record; + struct oem_sel { /* SEL header */ uint8_t id[2]; @@ -65,6 +133,21 @@ struct oem_sel { #define ESEL_HDR_SIZE 7 + +/* Initialize eSEL record */ +static void ipmi_init_esel_record(void) +{ + memset(&sel_record, 0, sizeof(struct sel_record)); + sel_record.record_type = SEL_REC_TYPE_AMI_ESEL; + sel_record.generator_id = SEL_GENERATOR_ID_AMI; + sel_record.evm_ver = SEL_EVM_VER_2; + sel_record.sensor_type = SENSOR_TYPE_SYS_EVENT; + sel_record.sensor_number = + ipmi_get_sensor_number(SENSOR_TYPE_SYS_EVENT); + sel_record.event_dir_type = SEL_EVENT_DIR_TYPE_OEM; + sel_record.event_data1 = SEL_DATA1_AMI; +} + static void ipmi_elog_error(struct ipmi_msg *msg) { if (msg->cc == IPMI_LOST_ARBITRATION_ERR) @@ -79,7 +162,8 @@ static void ipmi_elog_error(struct ipmi_msg *msg) /* Goes through the required steps to add a complete eSEL: * * 1. Get a reservation - * 2. Partially add data to the SEL + * 2. Add eSEL header + * 3. Partially add data to the SEL * * Because a reservation is needed we need to ensure eSEL's are added * as a single transaction as concurrent/interleaved adds would cancel @@ -96,15 +180,21 @@ static void ipmi_elog_error(struct ipmi_msg *msg) */ static void ipmi_elog_poll(struct ipmi_msg *msg) { + static bool first = false; static char pel_buf[MAX_PEL_SIZE]; static size_t pel_size; - static int index = 0; + static size_t esel_size; + static int esel_index = 0; + int pel_index; static unsigned int reservation_id = 0; static unsigned int record_id = 0; struct errorlog *elog_buf = (struct errorlog *) msg->user_data; size_t req_size; + ipmi_init_esel_record(); + if (msg->cmd == IPMI_CMD(IPMI_RESERVE_SEL)) { + first = true; reservation_id = msg->data[0]; reservation_id |= msg->data[1] << 8; if (!reservation_id) { @@ -118,7 +208,8 @@ static void ipmi_elog_poll(struct ipmi_msg *msg) } pel_size = create_pel_log(elog_buf, pel_buf, MAX_PEL_SIZE); - index = 0; + esel_size = pel_size + sizeof(struct sel_record); + esel_index = 0; record_id = 0; } else { record_id = msg->data[0]; @@ -126,21 +217,21 @@ static void ipmi_elog_poll(struct ipmi_msg *msg) } /* Start or continue the IPMI_PARTIAL_ADD_SEL */ - if (index >= pel_size) { + if (esel_index >= esel_size) { /* We're all done. Invalidate the resevation id to * ensure we get an error if we cut in on another eSEL * message. */ reservation_id = 0; - index = 0; + esel_index = 0; opal_elog_complete(elog_buf, true); ipmi_free_msg(msg); return; } - if ((pel_size - index) < (IPMI_MAX_REQ_SIZE - ESEL_HDR_SIZE)) { + if ((esel_size - esel_index) < (IPMI_MAX_REQ_SIZE - ESEL_HDR_SIZE)) { /* Last data to send */ msg->data[6] = 1; - req_size = pel_size - index + ESEL_HDR_SIZE; + req_size = esel_size - esel_index + ESEL_HDR_SIZE; } else { msg->data[6] = 0; req_size = IPMI_MAX_REQ_SIZE; @@ -153,11 +244,21 @@ static void ipmi_elog_poll(struct ipmi_msg *msg) msg->data[1] = (reservation_id >> 8) & 0xff; msg->data[2] = record_id & 0xff; msg->data[3] = (record_id >> 8) & 0xff; - msg->data[4] = index & 0xff; - msg->data[5] = (index >> 8) & 0xff; - - memcpy(&msg->data[ESEL_HDR_SIZE], &pel_buf[index], msg->req_size - ESEL_HDR_SIZE); - index += msg->req_size - ESEL_HDR_SIZE; + msg->data[4] = esel_index & 0xff; + msg->data[5] = (esel_index >> 8) & 0xff; + + if (first) { + first = false; + memcpy(&msg->data[ESEL_HDR_SIZE], + &sel_record, sizeof(struct sel_record)); + esel_index = sizeof(struct sel_record); + msg->req_size = esel_index + ESEL_HDR_SIZE; + } else { + pel_index = esel_index - sizeof(struct sel_record); + memcpy(&msg->data[ESEL_HDR_SIZE], + &pel_buf[pel_index], msg->req_size - ESEL_HDR_SIZE); + esel_index += msg->req_size - ESEL_HDR_SIZE; + } ipmi_queue_msg_head(msg); return; diff --git a/hw/ipmi/ipmi-sensor.c b/hw/ipmi/ipmi-sensor.c index d890534..c8723ae 100644 --- a/hw/ipmi/ipmi-sensor.c +++ b/hw/ipmi/ipmi-sensor.c @@ -36,6 +36,11 @@ struct set_sensor_req { u8 event_data[3]; }; +uint8_t ipmi_get_sensor_number(uint8_t sensor_type) +{ + return sensors[sensor_type]; +} + int ipmi_set_boot_count(void) { struct set_sensor_req req; diff --git a/include/ipmi.h b/include/ipmi.h index 3aaa041..f34fbbe 100644 --- a/include/ipmi.h +++ b/include/ipmi.h @@ -258,6 +258,9 @@ void ipmi_wdt_final_reset(void); /* Discover id of settable ipmi sensors */ void ipmi_sensor_init(void); +/* Get sensor number for given sensor type */ +uint8_t ipmi_get_sensor_number(uint8_t sensor_type); + /* Set the boot count once the OS is up and running */ int ipmi_set_boot_count(void);