Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp1198173imm; Wed, 11 Jul 2018 19:55:40 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfKIlO3ElvhT7DFeEjyhZVDdG/DPPjozjXkwK4sIpqoxdEYENn54i6tYNVWdX9IG+ZLmNLg X-Received: by 2002:a63:f919:: with SMTP id h25-v6mr386532pgi.401.1531364140294; Wed, 11 Jul 2018 19:55:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531364140; cv=none; d=google.com; s=arc-20160816; b=1LrELf2UTtDDAVq87v25TceSZZrIy0X+qWdLd0RucjQP+ZnUepACFKWvEHwlYZwenZ k4KIEj8NM+RdhxHDiZUFPzVqjTyeqbtmkyMIiSq7IbY2gUnn5lf1A8UjkFy03pPRJikD if+KBDP4t6O+D99ItWK7es5wBaSCguYNgPs0spaKqHsNlkHOdLoD0HKN2bz8cXlBEsKI fcj1tl2Gc46yuRSpReZxz9UHWZgLbd/mGl0RsejULIdwEOM2iPnG+kO9VwGUKdqmIQC4 aLOC6xvGPRSr98zdGsBk9gP5azMfvE2y/oqDZnyptNWZ3lvoxdYD13LBwT/hEs1Jw6wR 4drQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:references:in-reply-to:date :subject:cc:to:from:arc-authentication-results; bh=KIcdCodiyZQ1XhDHF+542ZDCTpj+Xut/jLlZTOYWIoo=; b=tPxLQpRZt7NQcjrdjgonKxYmTbm8iuvcdRYi5u9R0NB18CQ1IdVyT+AO1U1SOJD5vg N7Yy9mXTe2n4CC+F0I/E/Y4QzV0q4w3KNPk+ClaQyWRxsqK6/J3lKvWwE3T5acDrmQQu rX1b8ITPBEc8zR00TYNK5M7+1s6J/hDXgfqaREv1IFaJHd4z/AAHmQl4Of65e4NMmHeY QXXKL0okg9cqxrroqdx+RWs/OnITYSU9fbX/ZVVKLW0jnJpTJU0CQnSFMO2qmv4mUAo4 UPAlux3W/f6o3rPsLfTWWpd//e0GZdeRxQ4T0eyr1xs90LfDuseJ+T7lHmkN906ubAug QUCw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c15-v6si19153126pgw.550.2018.07.11.19.55.25; Wed, 11 Jul 2018 19:55:40 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390357AbeGKVIN (ORCPT + 99 others); Wed, 11 Jul 2018 17:08:13 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:51176 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390339AbeGKVIM (ORCPT ); Wed, 11 Jul 2018 17:08:12 -0400 Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w6BL0jlh122017 for ; Wed, 11 Jul 2018 17:02:01 -0400 Received: from e36.co.us.ibm.com (e36.co.us.ibm.com [32.97.110.154]) by mx0a-001b2d01.pphosted.com with ESMTP id 2k5prk6e89-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 11 Jul 2018 17:02:00 -0400 Received: from localhost by e36.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 11 Jul 2018 15:01:59 -0600 Received: from b03cxnp08028.gho.boulder.ibm.com (9.17.130.20) by e36.co.us.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Wed, 11 Jul 2018 15:01:54 -0600 Received: from b03ledav001.gho.boulder.ibm.com (b03ledav001.gho.boulder.ibm.com [9.17.130.232]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w6BL1rY35243154 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 11 Jul 2018 14:01:53 -0700 Received: from b03ledav001.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8B9B26E050; Wed, 11 Jul 2018 15:01:53 -0600 (MDT) Received: from b03ledav001.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B9E3A6E058; Wed, 11 Jul 2018 15:01:52 -0600 (MDT) Received: from talon7.ibm.com (unknown [9.41.102.69]) by b03ledav001.gho.boulder.ibm.com (Postfix) with ESMTP; Wed, 11 Jul 2018 15:01:52 -0600 (MDT) From: Eddie James To: linux-kernel@vger.kernel.org Cc: linux-hwmon@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, gregkh@linuxfoundation.org, benh@kernel.crashing.org, linux@roeck-us.net, jdelvare@suse.com, mark.rutland@arm.com, openbmc@lists.ozlabs.org, robh+dt@kernel.org, joel@jms.id.au, Eddie James Subject: [PATCH v4 6/9] hwmon (occ): Parse OCC poll response Date: Wed, 11 Jul 2018 16:01:35 -0500 X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1531342898-15790-1-git-send-email-eajames@linux.vnet.ibm.com> References: <1531342898-15790-1-git-send-email-eajames@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18071121-0020-0000-0000-00000E3CAB2C X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00009352; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000266; SDB=6.01059946; UDB=6.00544035; IPR=6.00837866; MB=3.00022107; MTD=3.00000008; XFM=3.00000015; UTC=2018-07-11 21:01:58 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18071121-0021-0000-0000-0000623F8DD0 Message-Id: <1531342898-15790-7-git-send-email-eajames@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-07-11_06:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1806210000 definitions=main-1807110221 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add method to parse the response from the OCC poll command. This only needs to be done during probe(), since the OCC shouldn't change the number or format of sensors while it's running. The parsed response allows quick access to sensor data, as well as information on the number and version of sensors, which we need to instantiate hwmon attributes. Signed-off-by: Eddie James --- drivers/hwmon/occ/common.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/occ/common.h | 55 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c index 1fd3453..73f62aa 100644 --- a/drivers/hwmon/occ/common.c +++ b/drivers/hwmon/occ/common.c @@ -11,6 +11,7 @@ */ #include +#include #include "common.h" @@ -32,6 +33,64 @@ static int occ_poll(struct occ *occ) return occ->send_cmd(occ, cmd); } +/* only need to do this once at startup, as OCC won't change sensors on us */ +static void occ_parse_poll_response(struct occ *occ) +{ + unsigned int i, old_offset, offset = 0, size = 0; + struct occ_sensor *sensor; + struct occ_sensors *sensors = &occ->sensors; + struct occ_response *resp = &occ->resp; + struct occ_poll_response *poll = + (struct occ_poll_response *)&resp->data[0]; + struct occ_poll_response_header *header = &poll->header; + struct occ_sensor_data_block *block = &poll->block; + + dev_info(occ->bus_dev, "OCC found, code level: %.16s\n", + header->occ_code_level); + + for (i = 0; i < header->num_sensor_data_blocks; ++i) { + block = (struct occ_sensor_data_block *)((u8 *)block + offset); + old_offset = offset; + offset = (block->header.num_sensors * + block->header.sensor_length) + sizeof(block->header); + size += offset; + + /* validate all the length/size fields */ + if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) { + dev_warn(occ->bus_dev, "exceeded response buffer\n"); + return; + } + + dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n", + old_offset, offset - 1, block->header.eye_catcher, + block->header.num_sensors); + + /* match sensor block type */ + if (strncmp(block->header.eye_catcher, "TEMP", 4) == 0) + sensor = &sensors->temp; + else if (strncmp(block->header.eye_catcher, "FREQ", 4) == 0) + sensor = &sensors->freq; + else if (strncmp(block->header.eye_catcher, "POWR", 4) == 0) + sensor = &sensors->power; + else if (strncmp(block->header.eye_catcher, "CAPS", 4) == 0) + sensor = &sensors->caps; + else if (strncmp(block->header.eye_catcher, "EXTN", 4) == 0) + sensor = &sensors->extended; + else { + dev_warn(occ->bus_dev, "sensor not supported %.4s\n", + block->header.eye_catcher); + continue; + } + + sensor->num_sensors = block->header.num_sensors; + sensor->version = block->header.sensor_format; + sensor->data = &block->data; + } + + dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size, + sizeof(*header), size + sizeof(*header)); +} + int occ_setup(struct occ *occ, const char *name) { int rc; @@ -46,5 +105,7 @@ int occ_setup(struct occ *occ, const char *name) return rc; } + occ_parse_poll_response(occ); + return 0; } diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h index 775b421..cfcd353 100644 --- a/drivers/hwmon/occ/common.h +++ b/drivers/hwmon/occ/common.h @@ -29,10 +29,65 @@ struct occ_response { __be16 checksum; } __packed; +struct occ_sensor_data_block_header { + u8 eye_catcher[4]; + u8 reserved; + u8 sensor_format; + u8 sensor_length; + u8 num_sensors; +} __packed; + +struct occ_sensor_data_block { + struct occ_sensor_data_block_header header; + u32 data; +} __packed; + +struct occ_poll_response_header { + u8 status; + u8 ext_status; + u8 occs_present; + u8 config_data; + u8 occ_state; + u8 mode; + u8 ips_status; + u8 error_log_id; + __be32 error_log_start_address; + __be16 error_log_length; + u16 reserved; + u8 occ_code_level[16]; + u8 eye_catcher[6]; + u8 num_sensor_data_blocks; + u8 sensor_data_block_header_version; +} __packed; + +struct occ_poll_response { + struct occ_poll_response_header header; + struct occ_sensor_data_block block; +} __packed; + +struct occ_sensor { + u8 num_sensors; + u8 version; + void *data; /* pointer to sensor data start within response */ +}; + +/* + * OCC only provides one sensor data block of each type, but any number of + * sensors within that block. + */ +struct occ_sensors { + struct occ_sensor temp; + struct occ_sensor freq; + struct occ_sensor power; + struct occ_sensor caps; + struct occ_sensor extended; +}; + struct occ { struct device *bus_dev; struct occ_response resp; + struct occ_sensors sensors; u8 poll_cmd_data; /* to perform OCC poll command */ int (*send_cmd)(struct occ *occ, u8 *cmd); -- 1.8.3.1