From patchwork Thu Jul 13 06:47:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shilpasri G Bhat X-Patchwork-Id: 787533 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 ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3x7RHN4S8Gz9s2s for ; Thu, 13 Jul 2017 16:48:48 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3x7RHN2vFyzDqlX for ; Thu, 13 Jul 2017 16:48:48 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3x7RGV25BwzDqk8 for ; Thu, 13 Jul 2017 16:48:02 +1000 (AEST) Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v6D6hdtm041148 for ; Thu, 13 Jul 2017 02:48:00 -0400 Received: from e23smtp07.au.ibm.com (e23smtp07.au.ibm.com [202.81.31.140]) by mx0b-001b2d01.pphosted.com with ESMTP id 2bnt3p273s-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 13 Jul 2017 02:48:00 -0400 Received: from localhost by e23smtp07.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 13 Jul 2017 16:47:55 +1000 Received: from d23relay07.au.ibm.com (202.81.31.226) by e23smtp07.au.ibm.com (202.81.31.204) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 13 Jul 2017 16:47:51 +1000 Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay07.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v6D6loDZ27656304 for ; Thu, 13 Jul 2017 16:47:50 +1000 Received: from d23av02.au.ibm.com (localhost [127.0.0.1]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id v6D6lfBU009481 for ; Thu, 13 Jul 2017 16:47:41 +1000 Received: from oc4502181600.in.ibm.com (oc4502181600.in.ibm.com [9.124.35.219]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v6D6lZHl009249; Thu, 13 Jul 2017 16:47:40 +1000 From: Shilpasri G Bhat To: skiboot@lists.ozlabs.org, stewart@linux.vnet.ibm.com, cyrilbur@gmail.com Date: Thu, 13 Jul 2017 12:17:41 +0530 X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1499928462-31192-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com> References: <1499928462-31192-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com> X-TM-AS-MML: disable x-cbid: 17071306-0044-0000-0000-0000027F4EE4 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17071306-0045-0000-0000-0000070FEA8C Message-Id: <1499928462-31192-3-git-send-email-shilpa.bhat@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-07-13_03:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1706020000 definitions=main-1707130102 Subject: [Skiboot] [PATCH V5 2/3] external/opal-occ: Add usersapce wrapper for OPAL-OCC cmd/rsp interface X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ego@linux.vnet.ibm.com MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This patch adds userspace application to issue OCC commands. The opal-occ utility is included within the opal-prd utility. Signed-off-by: Shilpasri G Bhat --- - No changes from V4 external/opal-prd/Makefile | 8 +- external/opal-prd/opal-occ.c | 333 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 339 insertions(+), 2 deletions(-) create mode 100644 external/opal-prd/opal-occ.c diff --git a/external/opal-prd/Makefile b/external/opal-prd/Makefile index ccd3401..6389656 100644 --- a/external/opal-prd/Makefile +++ b/external/opal-prd/Makefile @@ -8,7 +8,7 @@ sbindir = $(prefix)/sbin datadir = $(prefix)/share mandir = $(datadir)/man -all: links arch_links | opal-prd +all: links arch_links | opal-prd opal-occ GET_ARCH = ../../external/common/get_arch.sh include ../../external/common/rules.mk @@ -43,6 +43,9 @@ $(LIBFLASH_OBJS): libflash-%.o : libflash/%.c opal-prd: $(OBJS) $(Q_LINK)$(LINK.o) -o $@ $^ +opal-occ: opal-occ.o + $(Q_LINK)$(LINK.o) -o $@ $^ + version.c: ../../make_version.sh .version @(if [ "a$(OPAL_PRD_VERSION)" = "a" ]; then \ echo "#error You need to set OPAL_PRD_VERSION environment variable" > $@ ;\ @@ -63,10 +66,11 @@ test/test_pnor: test/test_pnor.o pnor.o $(LIBFLASH_OBJS) common-arch_flash.o install: all install -D opal-prd $(DESTDIR)$(sbindir)/opal-prd + install -D opal-occ $(DESTDIR)$(sbindir)/opal-occ install -D -m 0644 opal-prd.8 $(DESTDIR)$(mandir)/man8/opal-prd.8 clean: - $(RM) *.[odsa] opal-prd + $(RM) *.[odsa] opal-prd opal-occ $(RM) test/*.[odsa] test/test_pnor distclean: clean diff --git a/external/opal-prd/opal-occ.c b/external/opal-prd/opal-occ.c new file mode 100644 index 0000000..612cc22 --- /dev/null +++ b/external/opal-prd/opal-occ.c @@ -0,0 +1,333 @@ +/* Copyright 2017 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * imitations under the License. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include + +struct command_info { + enum occ_cmd cmd; + enum occ_cmd_data_length csize; + enum occ_rsp_data_length rsize; +}; + +static struct command_info cmds[] = { + { OCC_CMD_AMESTER_PASS_THRU, + OCC_CMD_DL_AMESTER_PASS_THRU, + OCC_RSP_DL_AMESTER_PASS_THRU + }, + { OCC_CMD_CLEAR_SENSOR_DATA, + OCC_CMD_DL_CLEAR_SENSOR_DATA, + OCC_RSP_DL_CLEAR_SENSOR_DATA + }, + { OCC_CMD_SET_POWER_CAP, + OCC_CMD_DL_SET_POWER_CAP, + OCC_RSP_DL_SET_POWER_CAP + }, + { OCC_CMD_SET_POWER_SHIFTING_RATIO, + OCC_CMD_DL_SET_POWER_SHIFTING_RATIO, + OCC_RSP_DL_SET_POWER_SHIFTING_RATIO + }, + { OCC_CMD_SELECT_SENSOR_GROUPS, + OCC_CMD_DL_SELECT_SENSOR_GROUPS, + OCC_RSP_DL_SELECT_SENSOR_GROUPS + }, +}; + +static void usage(const char *progname) +{ + printf("Usage:\n"); + printf("\t%s -c -p|--power-cap \n", progname); + printf("\t%s -c -s|--power-shift \n", progname); + printf("\t%s -c -l|--clear-sensor-limits " + "\n", progname); + printf("\t%s -c -a|--amester-passthru " + "\n", progname); + printf("\t%s -c -g|--select-sensor-groups \n", progname); +} + +static struct option occ_diag_options[] = { + {"chip", required_argument, NULL, 'c'}, + {"power-cap", required_argument, NULL, 'p'}, + {"power-shift", required_argument, NULL, 's'}, + {"clear-sensor-limits", required_argument, NULL, 'l'}, + {"amester-passthru", required_argument, NULL, 'a'}, + {"select-sensor-groups", required_argument, NULL, 'g'}, + {"help", no_argument, NULL, 'h'}, + {0}, +}; + +int main(int argc, char *argv[]) +{ + char occ_node[15]; + struct opal_occ_cmd_data *cmd; + struct opal_occ_rsp_data *rsp; + char *str; + u64 cmd_data; + int fd, rsp_size, chip = -1, rc, i; + enum occ_cmd ocmd = OCC_CMD_LAST; + + /* Parse options */ + for (;;) { + int c; + + c = getopt_long(argc, argv, "c:p:s:l:a:g:h", occ_diag_options, + NULL); + if (c == -1) + break; + + switch (c) { + case 'c': + chip = atoi(optarg); + break; + case 'p': + ocmd = OCC_CMD_SET_POWER_CAP; + cmd_data = atoi(optarg); + break; + case 's': + ocmd = OCC_CMD_SET_POWER_SHIFTING_RATIO; + cmd_data = atoi(optarg); + break; + case 'l': + ocmd = OCC_CMD_CLEAR_SENSOR_DATA; + str = optarg; + break; + case 'a': + ocmd = OCC_CMD_AMESTER_PASS_THRU; + cmd_data = optind - 1; + break; + case 'g': + ocmd = OCC_CMD_SELECT_SENSOR_GROUPS; + cmd_data = atoi(optarg); + break; + case 'h': + usage(argv[0]); + return EXIT_SUCCESS; + case '?': + default: + usage(argv[0]); + return EXIT_FAILURE; + } + + if (ocmd != OCC_CMD_LAST) + break; + } + + if (ocmd == OCC_CMD_LAST) { + printf("Specify a command\n"); + usage(argv[0]); + return EXIT_FAILURE; + } + + if (chip == -1) { + printf("Requires -c --chip option to be specified\n"); + return EXIT_FAILURE; + } + + snprintf(occ_node, sizeof(occ_node), "/dev/occ%d", chip); + if (access(occ_node, 0)) { + printf("Failed to access node %s\n", occ_node); + return EXIT_FAILURE; + } + + fd = open(occ_node, O_RDWR); + if (fd < 0) { + printf("Can't open OCC device %s: %m", occ_node); + return EXIT_FAILURE; + } + + if (cmds[ocmd].csize) { + cmd = malloc(sizeof(struct opal_occ_cmd_data) + + cmds[ocmd].csize); + if (!cmd) { + rc = -ENOMEM; + goto close_fd; + } + cmd->cmd = ocmd; + cmd->size = cmds[ocmd].csize; + } + + switch (ocmd) { + case OCC_CMD_SET_POWER_CAP: + if (cmd_data >> cmd->size * 8) { + printf("Invalid power cap %d\n", (int)cmd_data); + rc = -EINVAL; + goto free_cdata; + } + + memcpy(cmd->data, &cmd_data, cmd->size); + break; + case OCC_CMD_SET_POWER_SHIFTING_RATIO: + if (cmd_data >> cmd->size * 8) { + printf("Invalid power shift ratio %d\n", (int)cmd_data); + rc = -EINVAL; + goto free_cdata; + } + + memcpy(cmd->data, &cmd_data, cmd->size); + break; + case OCC_CMD_CLEAR_SENSOR_DATA: + if (!strcmp(str, "CSM")) { + cmd_data = OCC_SENSOR_LIMIT_GROUP_CSM; + } else if (!strcmp(str, "Profiler")) { + cmd_data = OCC_SENSOR_LIMIT_GROUP_PROFILER; + } else if (!strcmp(str, "Job-Scheduler")) { + cmd_data = OCC_SENSOR_LIMIT_GROUP_JOB_SCHED; + } else { + printf("Invalid sensor limit group type\n"); + rc = EXIT_FAILURE; + goto free_cdata; + } + + memcpy(cmd->data, &cmd_data, cmd->size); + break; + case OCC_CMD_AMESTER_PASS_THRU: + if (argc - cmd_data > MAX_OPAL_CMD_DATA_LENGTH) { + printf("Too large data\n"); + rc = -EINVAL; + goto close_fd; + } + + cmd = malloc(sizeof(*cmd) + argc - cmd_data); + if (!cmd) { + rc = -ENOMEM; + goto close_fd; + } + cmd->cmd = OCC_CMD_AMESTER_PASS_THRU; + cmd->size = argc - cmd_data; + for (i = 0; i < cmd->size; i++) + sscanf(argv[i + cmd_data], "%hhx", &cmd->data[i]); + break; + case OCC_CMD_SELECT_SENSOR_GROUPS: + if (cmd_data >> cmd->size * 8) { + printf("Invalid mask %d\n", (int)cmd_data); + rc = -EINVAL; + goto free_cdata; + } + memcpy(cmd->data, &cmd_data, cmd->size); + break; + default: + return EXIT_FAILURE; + } + + rc = write(fd, cmd, sizeof(*cmd) + cmd->size); + if (rc < 0) { + printf("Error writing OCC command %m\n"); + goto free_cdata; + } + + if (rc != sizeof(*cmd) + cmd->size) { + printf("Failed to write full command\n"); + goto free_cdata; + } + + if (cmds[ocmd].rsize) + rsp_size = sizeof(*rsp) + cmds[ocmd].rsize; + else + rsp_size = sizeof(*rsp) + MAX_OCC_RSP_DATA_LENGTH; + + rsp = malloc(rsp_size); + if (!rsp) + goto free_cdata; + + rc = read(fd, rsp, rsp_size); + if (rc < 0) { + printf("Error reading OCC response %m\n"); + goto out; + } + + if (rc < sizeof(*rsp)) { + printf("Failed to read OCC response\n"); + goto out; + } + + switch (rsp->status) { + case OCC_SUCCESS: + printf("OCC: Success\n"); + break; + case OCC_INVALID_COMMAND: + printf("OCC: Invalid Command\n"); + goto out; + case OCC_INVALID_CMD_DATA_LENGTH: + printf("OCC: Invalid Command Data length\n"); + goto out; + case OCC_INVALID_DATA: + printf("OCC: Invalid Data\n"); + goto out; + case OCC_INTERNAL_ERROR: + printf("OCC: Internal OCC error\n"); + goto out; + default: + printf("OCC: Unrecognized response status\n"); + goto out; + } + + switch (ocmd) { + case OCC_CMD_SET_POWER_CAP: + printf("Power Cap set to %dW\n", *(u16 *)rsp->data); + break; + case OCC_CMD_SET_POWER_SHIFTING_RATIO: + printf("Power Shifting ratio set to %d%%\n", *(u8 *)rsp->data); + break; + case OCC_CMD_CLEAR_SENSOR_DATA: + printf("Sensor limit cleared for "); + switch (*(u8 *)rsp->data) { + case OCC_SENSOR_LIMIT_GROUP_CSM: + printf("CSM\n"); + break; + case OCC_SENSOR_LIMIT_GROUP_PROFILER: + printf("Profiler\n"); + break; + case OCC_SENSOR_LIMIT_GROUP_JOB_SCHED: + printf("Job-Scheduler\n"); + break; + default: + printf("invalid sensor limit group\n"); + rc = EXIT_FAILURE; + } + break; + case OCC_CMD_AMESTER_PASS_THRU: + printf("Amester response data size = %d\n", rsp->size); + for (i = 0; i < rsp->size; i++) { + printf("%hhx ", rsp->data[i]); + if (i && !(i % 8)) + printf("\n"); + } + printf("\n"); + break; + case OCC_CMD_SELECT_SENSOR_GROUPS: + printf("Sensor group mask set to %d\n", *(u16 *)rsp->data); + break; + default: + break; + } + +out: + free(rsp); +free_cdata: + free(cmd); +close_fd: + close(fd); + return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +}