From patchwork Thu Mar 23 23:47:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lijun Pan X-Patchwork-Id: 9642153 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 56FDB60327 for ; Thu, 23 Mar 2017 23:47:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 446A628438 for ; Thu, 23 Mar 2017 23:47:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 381C426E56; Thu, 23 Mar 2017 23:47:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, T_DKIM_INVALID autolearn=no version=3.3.1 Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A3CD326E56 for ; Thu, 23 Mar 2017 23:47:56 +0000 (UTC) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id DFC178038D; Thu, 23 Mar 2017 16:47:55 -0700 (PDT) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mail-ot0-x242.google.com (mail-ot0-x242.google.com [IPv6:2607:f8b0:4003:c0f::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 067B1802B8 for ; Thu, 23 Mar 2017 16:47:54 -0700 (PDT) Received: by mail-ot0-x242.google.com with SMTP id i50so21105434otd.0 for ; Thu, 23 Mar 2017 16:47:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=el/P1+o5SsVJyd03Ob+YyO0wZhrtGZywJH6ZLQxYgZ4=; b=pKlh/7KwYz1zQlkcDiEeL3KUgEZP1Rb0UlDCdQVExd80b0OSsTH60KlKuuJcWeCcFu jBed/GzC02GgNS5bSUP+byoiQeAi43uEXw0bMuTMnRQ7Mlgo/KLY5umHeOQLhcDlqRFs Es5XmpPc2RX7YAk+4qBqNmLFbV7XopDYr8OXXFpmNiKggkQnaWJk0qDOlYgXH9JVmi8Q 0nJeJy2kXb5TKInTriRLMvm+IT+KPj3DNBi8uOdVGOt2Iaf9pX31rXnfqoCllRLggUxx NxhoFgD9a0hnsqpGxFxuluOyKEeciNhSxcB6mP+Fzv0nbVGTouC7mbRJKW/iNRpq+nyp 0i8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=el/P1+o5SsVJyd03Ob+YyO0wZhrtGZywJH6ZLQxYgZ4=; b=ZdOLw+6ZTE61fprF+48pM9nIHvaSf65HI1GKby9S9unqvPr93FC58o0OdA5ujyuj4v BKqyG3SbAd3+VXmfiswgSMrtLpoS3DWYR+/6zgP9xdSg94EiZWjDaNU8QVzEv37RkKBx s+oUL2snKzn0PvWe+Y5TszLBvkV4SOzl3+6Dm6YfTS8b3f2H4/P60L6o0uqYv6NrLqSC NUrG8rI3hQG6lmshXt728LtqhQGjM7ayCFAxSJg16AVYlwMfXAXTstZNLd7YAuZe2Jk2 eU5TnEeVpmDwuLNV0J7pXyaEoHWOz8H7/UJOJnpCkWYUW5iBuKiQh6W38rj01baCpCD6 D+3A== X-Gm-Message-State: AFeK/H3TLHWH0l4rCgMJcvGGu0UKMz5gppveEYt82HXoBtZm1fhhycnh82XfYN1Z/z8L6w== X-Received: by 10.157.11.20 with SMTP id a20mr3253521ota.8.1490312873135; Thu, 23 Mar 2017 16:47:53 -0700 (PDT) Received: from pear.attlocal.net (75-43-16-87.lightspeed.austtx.sbcglobal.net. [75.43.16.87]) by smtp.gmail.com with ESMTPSA id s186sm292479oie.28.2017.03.23.16.47.52 (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 23 Mar 2017 16:47:52 -0700 (PDT) From: Lijun Pan To: linux-nvdimm@lists.01.org Subject: [PATCH 1/2] ndctl: Microsoft _DSM's support for "ndctl list --health" option Date: Thu, 23 Mar 2017 18:47:50 -0500 Message-Id: <20170323234751.1468-1-lijunpan2000@gmail.com> X-Mailer: git-send-email 2.10.1 (Apple Git-78) X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Lijun Pan , Stuart Hayes MIME-Version: 1.0 Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Virus-Scanned: ClamAV using ClamSMTP From: Lijun Pan Add Microsoft's specific _DSM interface to retrieve the NVDIMM health data from the server platforms supporting this interface. Please refer to Microsoft _DSM spec[1] and JESD245A[2]. [1]. https://msdn.microsoft.com/library/windows/hardware/mt604741 [2]. https://www.jedec.org/sites/default/files/docs/JESD245A.pdf Cc: Stuart Hayes Signed-off-by: Lijun Pan --- ndctl/Makefile.am | 3 +- ndctl/builtin-list.c | 6 ++- ndctl/lib/libndctl.c | 5 ++ ndctl/lib/libndctl.sym | 1 + ndctl/lib/ndctl-msft.h | 57 ++++++++++++++++++++++ ndctl/libndctl.h.in | 1 + ndctl/util/json-msft.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++ util/json.h | 1 + 8 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 ndctl/lib/ndctl-msft.h create mode 100644 ndctl/util/json-msft.c diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am index c563e94..f85f9cb 100644 --- a/ndctl/Makefile.am +++ b/ndctl/Makefile.am @@ -10,7 +10,8 @@ ndctl_SOURCES = ndctl.c \ ../util/log.c \ builtin-list.c \ builtin-test.c \ - ../util/json.c + ../util/json.c \ + util/json-msft.c if ENABLE_SMART ndctl_SOURCES += util/json-smart.c diff --git a/ndctl/builtin-list.c b/ndctl/builtin-list.c index e8d0070..d4e1d23 100644 --- a/ndctl/builtin-list.c +++ b/ndctl/builtin-list.c @@ -349,7 +349,11 @@ int cmd_list(int argc, const char **argv, void *ctx) if (list.health) { struct json_object *jhealth; - jhealth = util_dimm_health_to_json(dimm); + if (ndctl_dimm_get_dsm_family(dimm) == NVDIMM_FAMILY_MSFT) + jhealth = util_dimm_health_to_json_msft(dimm); + else + jhealth = util_dimm_health_to_json(dimm); + if (jhealth) json_object_object_add(jdimm, "health", jhealth); diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c index 565c969..019db9a 100644 --- a/ndctl/lib/libndctl.c +++ b/ndctl/lib/libndctl.c @@ -1361,6 +1361,11 @@ NDCTL_EXPORT unsigned char ndctl_dimm_get_manufacturing_location( return dimm->manufacturing_location; } +NDCTL_EXPORT unsigned long ndctl_dimm_get_dsm_family(struct ndctl_dimm *dimm) +{ + return dimm->dsm_family; +} + NDCTL_EXPORT unsigned short ndctl_dimm_get_format(struct ndctl_dimm *dimm) { return dimm->format[0]; diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym index be2e368..b1d6e6f 100644 --- a/ndctl/lib/libndctl.sym +++ b/ndctl/lib/libndctl.sym @@ -48,6 +48,7 @@ global: ndctl_dimm_get_subsystem_vendor; ndctl_dimm_get_subsystem_device; ndctl_dimm_get_subsystem_revision; + ndctl_dimm_get_dsm_family; ndctl_dimm_get_format; ndctl_dimm_get_formats; ndctl_dimm_get_formatN; diff --git a/ndctl/lib/ndctl-msft.h b/ndctl/lib/ndctl-msft.h new file mode 100644 index 0000000..4985c24 --- /dev/null +++ b/ndctl/lib/ndctl-msft.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016-2017 Dell, Inc. + * Author: Lijun Pan + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + */ + +#ifndef _NDCTL_DELL_H_ +#define _NDCTL_DELL_H_ + +#define DEV_NAME_MAX_LENGTH 12 +#define DEV_ID_MAX_LENGTH 3 +#define DEV_ID_MAX 128 + +/* REFER TO SPEC https://msdn.microsoft.com/en-us/library/windows/hardware/mt604741(v=vs.85).aspx */ +#define SIZE_IN_FUNC0 0 +#define SIZE_IN_FUNC1 0 +#define SIZE_IN_FUNC2 0 +#define SIZE_IN_FUNC3 0 +#define SIZE_IN_FUNC4 0 +#define SIZE_IN_FUNC5 0 +#define SIZE_IN_FUNC7 0 +#define SIZE_IN_FUNC10 0 +#define SIZE_IN_FUNC11 0 +#define SIZE_IN_FUNC12 0 + +#define SIZE_OUT_FUNC0 4 +#define SIZE_OUT_FUNC1 50 +#define SIZE_OUT_FUNC2 12 +#define SIZE_OUT_FUNC3 19 +#define SIZE_OUT_FUNC4 12 +#define SIZE_OUT_FUNC5 6 +#define SIZE_OUT_FUNC7 8 +#define SIZE_OUT_FUNC10 5 +#define SIZE_OUT_FUNC11 13 +#define SIZE_OUT_FUNC12 11 +#define SIZE_OUT_MAX 50 + +#define FUNC0 0 +#define FUNC1 1 +#define FUNC2 2 +#define FUNC3 3 +#define FUNC4 4 +#define FUNC5 5 +#define FUNC7 7 +#define FUNC10 10 +#define FUNC11 11 +#define FUNC12 12 + +#endif diff --git a/ndctl/libndctl.h.in b/ndctl/libndctl.h.in index c27581d..fb2c6e1 100644 --- a/ndctl/libndctl.h.in +++ b/ndctl/libndctl.h.in @@ -129,6 +129,7 @@ unsigned short ndctl_dimm_get_subsystem_device(struct ndctl_dimm *dimm); unsigned short ndctl_dimm_get_manufacturing_date(struct ndctl_dimm *dimm); unsigned char ndctl_dimm_get_manufacturing_location(struct ndctl_dimm *dimm); unsigned short ndctl_dimm_get_subsystem_revision(struct ndctl_dimm *dimm); +unsigned long ndctl_dimm_get_dsm_family(struct ndctl_dimm *dimm); unsigned short ndctl_dimm_get_format(struct ndctl_dimm *dimm); int ndctl_dimm_get_formats(struct ndctl_dimm *dimm); int ndctl_dimm_get_formatN(struct ndctl_dimm *dimm, int i); diff --git a/ndctl/util/json-msft.c b/ndctl/util/json-msft.c new file mode 100644 index 0000000..9e41fde --- /dev/null +++ b/ndctl/util/json-msft.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_NDCTL_H +#include +#else +#include +#endif + +#include "ndctl-msft.h" + +static int call_func(int func_num, int size_in, int size_out, + int fd, unsigned char *payload) { + struct nd_cmd_pkg *pkg; + int error; + int i; + + memset(payload, 0, SIZE_OUT_MAX); + pkg = malloc(sizeof(struct nd_cmd_pkg) + size_in + size_out); + if (!pkg) + return -ENOMEM; + + pkg->nd_family = NVDIMM_FAMILY_MSFT; + pkg->nd_command = func_num; + pkg->nd_size_in = size_in; + pkg->nd_size_out = size_out; + pkg->nd_fw_size = 0; + + for (i = 0; i < 9; i++) + pkg->nd_reserved2[i] = 0; + + for (i = 0; i < size_in; i++) + pkg->nd_payload[i] = 0; + + for (i = 0; i < size_out; i++) + pkg->nd_payload[i + size_in] = 0; + + error = ioctl(fd, ND_IOCTL_CALL, pkg); + + if (error) { + fprintf(stderr, "ioctl returned errno %d\n", errno); + free(pkg); + return error; + } + + for (i = 0; i < size_out; i++) + payload[i] = pkg->nd_payload[i + size_in]; + + free(pkg); + return 0; +} + +struct json_object *util_dimm_health_to_json_msft(struct ndctl_dimm *dimm) +{ + + struct json_object *jhealth = json_object_new_object(); + struct json_object *jobj; + char dev_name[DEV_NAME_MAX_LENGTH + 1]; + unsigned char payload[SIZE_OUT_MAX]; + char str[100]; + int fd; + int error; + int number; + double temp; + + memset(dev_name, 0, DEV_NAME_MAX_LENGTH + 1); + snprintf(dev_name, DEV_NAME_MAX_LENGTH + 1, "/dev/nmem%d", ndctl_dimm_get_id(dimm)); + fd = open(dev_name, O_RDWR); + if (fd == -1) { + fprintf(stderr, "error opening %s errno=%d\n", dev_name, errno); + goto err_fd; + } + + error = call_func(FUNC10, SIZE_IN_FUNC10, SIZE_OUT_FUNC10, fd, payload); + if (!error) { + if (!!(payload[4] & 0x0F)) + jobj = json_object_new_string("critical"); + else + jobj = json_object_new_string("ok"); + if (jobj) + json_object_object_add(jhealth, "health_state", jobj); + } + + error = call_func(FUNC11, SIZE_IN_FUNC11, SIZE_OUT_FUNC11, fd, payload); + if (!error) { + /* refer to JESD245 spec section 7.8 to calculate the temperature */ + number = (payload[7] & 0x0F) << 4 | (payload[6] & 0xF0) >> 4; + temp = number + !!(payload[6] & 0x08) * 0.5 + !!(payload[6] & 0x04) * 0.25; + jobj = json_object_new_double(temp); + if (jobj) + json_object_object_add(jhealth, "temperature_celsius", jobj); + + memset(str, 0, 100); + snprintf(str, 100, "%d%%", payload[10]); + jobj = json_object_new_string(str); + if (jobj) + json_object_object_add(jhealth, "NVM_Lifetime", jobj); + } + + error = call_func(FUNC4, SIZE_IN_FUNC4, SIZE_OUT_FUNC4, fd, payload); + if (!error) { + if (!!(payload[4] & 0x1)) + jobj = json_object_new_string("success"); + else + jobj = json_object_new_string("failure"); + if (jobj) + json_object_object_add(jhealth, "last_save_operation", jobj); + } + + close(fd); + return jhealth; + +err_fd: + json_object_put(jhealth); + + return NULL; +} diff --git a/util/json.h b/util/json.h index a9afb2d..3a41977 100644 --- a/util/json.h +++ b/util/json.h @@ -29,4 +29,5 @@ static inline struct json_object *util_dimm_health_to_json( return NULL; } #endif +struct json_object *util_dimm_health_to_json_msft(struct ndctl_dimm *dimm); #endif /* __NDCTL_JSON_H__ */