From patchwork Tue Mar 31 14:32:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Jain X-Patchwork-Id: 1264782 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48sBrh4Vqtz9sRN for ; Wed, 1 Apr 2020 01:43:00 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 48sBrh0Hh8zDr7f for ; Wed, 1 Apr 2020 01:43:00 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=vaibhav@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (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 48sBd42GNrzDqWZ for ; Wed, 1 Apr 2020 01:32:56 +1100 (AEDT) Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 02VE3eRh034698 for ; Tue, 31 Mar 2020 10:32:53 -0400 Received: from e06smtp07.uk.ibm.com (e06smtp07.uk.ibm.com [195.75.94.103]) by mx0a-001b2d01.pphosted.com with ESMTP id 3043g78b6r-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 31 Mar 2020 10:32:53 -0400 Received: from localhost by e06smtp07.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 31 Mar 2020 15:32:49 +0100 Received: from b06cxnps4076.portsmouth.uk.ibm.com (9.149.109.198) by e06smtp07.uk.ibm.com (192.168.101.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Tue, 31 Mar 2020 15:32:46 +0100 Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 02VEWkSq51445936 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 31 Mar 2020 14:32:46 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 121F6A405F; Tue, 31 Mar 2020 14:32:46 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 81513A4040; Tue, 31 Mar 2020 14:32:43 +0000 (GMT) Received: from vajain21.in.ibm.com.com (unknown [9.85.86.229]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTP; Tue, 31 Mar 2020 14:32:43 +0000 (GMT) From: Vaibhav Jain To: linuxppc-dev@lists.ozlabs.org, linux-nvdimm@lists.01.org Subject: [PATCH v5 1/4] powerpc/papr_scm: Fetch nvdimm health information from PHYP Date: Tue, 31 Mar 2020 20:02:26 +0530 X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200331143229.306718-1-vaibhav@linux.ibm.com> References: <20200331143229.306718-1-vaibhav@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 20033114-0028-0000-0000-000003EF6963 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 20033114-0029-0000-0000-000024B4EC45 Message-Id: <20200331143229.306718-2-vaibhav@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-03-31_04:2020-03-31, 2020-03-31 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 spamscore=0 malwarescore=0 mlxlogscore=999 impostorscore=0 clxscore=1015 phishscore=0 adultscore=0 lowpriorityscore=0 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2003310129 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alastair D'Silva , "Aneesh Kumar K . V" , Jeff Moyer , Oliver O'Halloran , Vishal Verma , Vaibhav Jain , Michael Ellerman , Dan Williams Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" Implement support for fetching nvdimm health information via H_SCM_HEALTH hcall as documented in Ref[1]. The hcall returns a pair of 64-bit big-endian integers which are then stored in 'struct papr_scm_priv' and subsequently partially exposed to user-space via newly introduced dimm specific attribute 'papr_flags'. Also a new asm header named 'papr-scm.h' is added that describes the interface between PHYP and guest kernel. Following flags are reported via 'papr_flags' sysfs attribute contents of which are space separated string flags indicating various nvdimm states: * "not_armed" : Indicating that nvdimm contents wont survive a power cycle. * "save_fail" : Indicating that nvdimm contents couldn't be flushed during last shutdown event. * "restore_fail": Indicating that nvdimm contents couldn't be restored during dimm initialization. * "encrypted" : Dimm contents are encrypted. * "smart_notify": There is health event for the nvdimm. * "scrubbed" : Indicating that contents of the nvdimm have been scrubbed. * "locked" : Indicating that nvdimm contents cant be modified until next power cycle. [1]: commit 58b278f568f0 ("powerpc: Provide initial documentation for PAPR hcalls") Signed-off-by: Vaibhav Jain Reviewed-by: Aneesh Kumar K.V --- Changelog: v4..v5 : None v3..v4 : None v2..v3 : Removed PAPR_SCM_DIMM_HEALTH_NON_CRITICAL as a condition for NVDIMM unarmed [Aneesh] v1..v2 : New patch in the series. --- arch/powerpc/include/asm/papr_scm.h | 48 ++++++++++ arch/powerpc/platforms/pseries/papr_scm.c | 105 +++++++++++++++++++++- 2 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/include/asm/papr_scm.h diff --git a/arch/powerpc/include/asm/papr_scm.h b/arch/powerpc/include/asm/papr_scm.h new file mode 100644 index 000000000000..868d3360f56a --- /dev/null +++ b/arch/powerpc/include/asm/papr_scm.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Structures and defines needed to manage nvdimms for spapr guests. + */ +#ifndef _ASM_POWERPC_PAPR_SCM_H_ +#define _ASM_POWERPC_PAPR_SCM_H_ + +#include +#include + +/* DIMM health bitmap bitmap indicators */ +/* SCM device is unable to persist memory contents */ +#define PAPR_SCM_DIMM_UNARMED PPC_BIT(0) +/* SCM device failed to persist memory contents */ +#define PAPR_SCM_DIMM_SHUTDOWN_DIRTY PPC_BIT(1) +/* SCM device contents are persisted from previous IPL */ +#define PAPR_SCM_DIMM_SHUTDOWN_CLEAN PPC_BIT(2) +/* SCM device contents are not persisted from previous IPL */ +#define PAPR_SCM_DIMM_EMPTY PPC_BIT(3) +/* SCM device memory life remaining is critically low */ +#define PAPR_SCM_DIMM_HEALTH_CRITICAL PPC_BIT(4) +/* SCM device will be garded off next IPL due to failure */ +#define PAPR_SCM_DIMM_HEALTH_FATAL PPC_BIT(5) +/* SCM contents cannot persist due to current platform health status */ +#define PAPR_SCM_DIMM_HEALTH_UNHEALTHY PPC_BIT(6) +/* SCM device is unable to persist memory contents in certain conditions */ +#define PAPR_SCM_DIMM_HEALTH_NON_CRITICAL PPC_BIT(7) +/* SCM device is encrypted */ +#define PAPR_SCM_DIMM_ENCRYPTED PPC_BIT(8) +/* SCM device has been scrubbed and locked */ +#define PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED PPC_BIT(9) + +/* Bits status indicators for health bitmap indicating unarmed dimm */ +#define PAPR_SCM_DIMM_UNARMED_MASK (PAPR_SCM_DIMM_UNARMED | \ + PAPR_SCM_DIMM_HEALTH_UNHEALTHY) + +/* Bits status indicators for health bitmap indicating unflushed dimm */ +#define PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK (PAPR_SCM_DIMM_SHUTDOWN_DIRTY) + +/* Bits status indicators for health bitmap indicating unrestored dimm */ +#define PAPR_SCM_DIMM_BAD_RESTORE_MASK (PAPR_SCM_DIMM_EMPTY) + +/* Bit status indicators for smart event notification */ +#define PAPR_SCM_DIMM_SMART_EVENT_MASK (PAPR_SCM_DIMM_HEALTH_CRITICAL | \ + PAPR_SCM_DIMM_HEALTH_FATAL | \ + PAPR_SCM_DIMM_HEALTH_UNHEALTHY) + +#endif diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index 0b4467e378e5..aaf2e4ab1f75 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -14,6 +14,7 @@ #include #include +#include #define BIND_ANY_ADDR (~0ul) @@ -39,6 +40,13 @@ struct papr_scm_priv { struct resource res; struct nd_region *region; struct nd_interleave_set nd_set; + + /* Protect dimm data from concurrent access */ + struct mutex dimm_mutex; + + /* Health information for the dimm */ + __be64 health_bitmap; + __be64 health_bitmap_valid; }; static int drc_pmem_bind(struct papr_scm_priv *p) @@ -144,6 +152,35 @@ static int drc_pmem_query_n_bind(struct papr_scm_priv *p) return drc_pmem_bind(p); } +static int drc_pmem_query_health(struct papr_scm_priv *p) +{ + unsigned long ret[PLPAR_HCALL_BUFSIZE]; + int64_t rc; + + rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index); + if (rc != H_SUCCESS) { + dev_err(&p->pdev->dev, + "Failed to query health information, Err:%lld\n", rc); + return -ENXIO; + } + + /* Protect modifications to papr_scm_priv with the mutex */ + rc = mutex_lock_interruptible(&p->dimm_mutex); + if (rc) + return rc; + + /* Store the retrieved health information in dimm platform data */ + p->health_bitmap = ret[0]; + p->health_bitmap_valid = ret[1]; + + dev_dbg(&p->pdev->dev, + "Queried dimm health info. Bitmap:0x%016llx Mask:0x%016llx\n", + be64_to_cpu(p->health_bitmap), + be64_to_cpu(p->health_bitmap_valid)); + + mutex_unlock(&p->dimm_mutex); + return 0; +} static int papr_scm_meta_get(struct papr_scm_priv *p, struct nd_cmd_get_config_data_hdr *hdr) @@ -304,6 +341,67 @@ static inline int papr_scm_node(int node) return min_node; } +static ssize_t papr_flags_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvdimm *dimm = to_nvdimm(dev); + struct papr_scm_priv *p = nvdimm_provider_data(dimm); + __be64 health; + int rc; + + rc = drc_pmem_query_health(p); + if (rc) + return rc; + + /* Protect against modifications to papr_scm_priv with the mutex */ + rc = mutex_lock_interruptible(&p->dimm_mutex); + if (rc) + return rc; + + health = p->health_bitmap & p->health_bitmap_valid; + + /* Check for various masks in bitmap and set the buffer */ + if (health & PAPR_SCM_DIMM_UNARMED_MASK) + rc += sprintf(buf, "not_armed "); + + if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK) + rc += sprintf(buf + rc, "save_fail "); + + if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK) + rc += sprintf(buf + rc, "restore_fail "); + + if (health & PAPR_SCM_DIMM_ENCRYPTED) + rc += sprintf(buf + rc, "encrypted "); + + if (health & PAPR_SCM_DIMM_SMART_EVENT_MASK) + rc += sprintf(buf + rc, "smart_notify "); + + if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED) + rc += sprintf(buf + rc, "scrubbed locked "); + + if (rc > 0) + rc += sprintf(buf + rc, "\n"); + + mutex_unlock(&p->dimm_mutex); + return rc; +} +DEVICE_ATTR_RO(papr_flags); + +/* papr_scm specific dimm attributes */ +static struct attribute *papr_scm_nd_attributes[] = { + &dev_attr_papr_flags.attr, + NULL, +}; + +static struct attribute_group papr_scm_nd_attribute_group = { + .attrs = papr_scm_nd_attributes, +}; + +static const struct attribute_group *papr_scm_dimm_attr_groups[] = { + &papr_scm_nd_attribute_group, + NULL, +}; + static int papr_scm_nvdimm_init(struct papr_scm_priv *p) { struct device *dev = &p->pdev->dev; @@ -330,8 +428,8 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) dimm_flags = 0; set_bit(NDD_ALIASING, &dimm_flags); - p->nvdimm = nvdimm_create(p->bus, p, NULL, dimm_flags, - PAPR_SCM_DIMM_CMD_MASK, 0, NULL); + p->nvdimm = nvdimm_create(p->bus, p, papr_scm_dimm_attr_groups, + dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL); if (!p->nvdimm) { dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn); goto err; @@ -415,6 +513,9 @@ static int papr_scm_probe(struct platform_device *pdev) if (!p) return -ENOMEM; + /* Initialize the dimm mutex */ + mutex_init(&p->dimm_mutex); + /* optional DT properties */ of_property_read_u32(dn, "ibm,metadata-size", &metadata_size); From patchwork Tue Mar 31 14:32:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Jain X-Patchwork-Id: 1264784 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48sC3s60X7z9sPJ for ; Wed, 1 Apr 2020 01:52:41 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 48sC3s4g8JzDqHd for ; Wed, 1 Apr 2020 01:52:41 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=vaibhav@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (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 48sBd70BBxzDr6l for ; Wed, 1 Apr 2020 01:32:58 +1100 (AEDT) Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 02VE2rCS012898 for ; Tue, 31 Mar 2020 10:32:56 -0400 Received: from e06smtp02.uk.ibm.com (e06smtp02.uk.ibm.com [195.75.94.98]) by mx0a-001b2d01.pphosted.com with ESMTP id 3022qy86q7-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 31 Mar 2020 10:32:56 -0400 Received: from localhost by e06smtp02.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 31 Mar 2020 15:32:44 +0100 Received: from b06cxnps3074.portsmouth.uk.ibm.com (9.149.109.194) by e06smtp02.uk.ibm.com (192.168.101.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Tue, 31 Mar 2020 15:32:40 +0100 Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 02VEWnhl63242318 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 31 Mar 2020 14:32:49 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4BB4DA4059; Tue, 31 Mar 2020 14:32:49 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A770EA404D; Tue, 31 Mar 2020 14:32:46 +0000 (GMT) Received: from vajain21.in.ibm.com.com (unknown [9.85.86.229]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTP; Tue, 31 Mar 2020 14:32:46 +0000 (GMT) From: Vaibhav Jain To: linuxppc-dev@lists.ozlabs.org, linux-nvdimm@lists.01.org Subject: [PATCH v5 2/4] ndctl/uapi: Introduce NVDIMM_FAMILY_PAPR_SCM as a new NVDIMM DSM family Date: Tue, 31 Mar 2020 20:02:27 +0530 X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200331143229.306718-1-vaibhav@linux.ibm.com> References: <20200331143229.306718-1-vaibhav@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 20033114-0008-0000-0000-00000367D8EF X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 20033114-0009-0000-0000-00004A895DC8 Message-Id: <20200331143229.306718-3-vaibhav@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-03-31_04:2020-03-31, 2020-03-31 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 phishscore=0 malwarescore=0 spamscore=0 mlxlogscore=791 impostorscore=0 suspectscore=0 adultscore=0 clxscore=1015 bulkscore=0 mlxscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2003310129 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alastair D'Silva , "Aneesh Kumar K . V" , Jeff Moyer , Oliver O'Halloran , Vishal Verma , Vaibhav Jain , Michael Ellerman , Dan Williams Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" Add PAPR-scm family of DSM command-set to the white list of NVDIMM command sets. Signed-off-by: Vaibhav Jain Reviewed-by: Aneesh Kumar K.V --- Changelog: v4..v5 : None v3..v4 : None v2..v3 : Updated the patch prefix to 'ndctl/uapi' [Aneesh] v1..v2 : None --- include/uapi/linux/ndctl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h index de5d90212409..99fb60600ef8 100644 --- a/include/uapi/linux/ndctl.h +++ b/include/uapi/linux/ndctl.h @@ -244,6 +244,7 @@ struct nd_cmd_pkg { #define NVDIMM_FAMILY_HPE2 2 #define NVDIMM_FAMILY_MSFT 3 #define NVDIMM_FAMILY_HYPERV 4 +#define NVDIMM_FAMILY_PAPR_SCM 5 #define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\ struct nd_cmd_pkg) From patchwork Tue Mar 31 14:32:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Jain X-Patchwork-Id: 1264792 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48sCGx0twPz9sPk for ; Wed, 1 Apr 2020 02:02:17 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 48sCGv5qYczDqHv for ; Wed, 1 Apr 2020 02:02:15 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=vaibhav@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (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 48sBdJ68PvzDr6l for ; Wed, 1 Apr 2020 01:33:01 +1100 (AEDT) Received: from pps.filterd (m0187473.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 02VESXR0127328 for ; Tue, 31 Mar 2020 10:32:59 -0400 Received: from e06smtp03.uk.ibm.com (e06smtp03.uk.ibm.com [195.75.94.99]) by mx0a-001b2d01.pphosted.com with ESMTP id 30227w3ud9-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 31 Mar 2020 10:32:59 -0400 Received: from localhost by e06smtp03.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 31 Mar 2020 15:32:50 +0100 Received: from b06cxnps4075.portsmouth.uk.ibm.com (9.149.109.197) by e06smtp03.uk.ibm.com (192.168.101.133) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Tue, 31 Mar 2020 15:32:47 +0100 Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps4075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 02VEWqFN52625452 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 31 Mar 2020 14:32:52 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 59354A405D; Tue, 31 Mar 2020 14:32:52 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B4088A4040; Tue, 31 Mar 2020 14:32:49 +0000 (GMT) Received: from vajain21.in.ibm.com.com (unknown [9.85.86.229]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTP; Tue, 31 Mar 2020 14:32:49 +0000 (GMT) From: Vaibhav Jain To: linuxppc-dev@lists.ozlabs.org, linux-nvdimm@lists.01.org Subject: [PATCH v5 3/4] powerpc/papr_scm, uapi: Add support for handling PAPR DSM commands Date: Tue, 31 Mar 2020 20:02:28 +0530 X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200331143229.306718-1-vaibhav@linux.ibm.com> References: <20200331143229.306718-1-vaibhav@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 20033114-0012-0000-0000-0000039BAAB4 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 20033114-0013-0000-0000-000021D8B71C Message-Id: <20200331143229.306718-4-vaibhav@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-03-31_04:2020-03-31, 2020-03-31 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 priorityscore=1501 phishscore=0 malwarescore=0 mlxscore=0 bulkscore=0 impostorscore=0 spamscore=0 suspectscore=0 mlxlogscore=999 lowpriorityscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2003310125 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alastair D'Silva , "Aneesh Kumar K . V" , Jeff Moyer , Oliver O'Halloran , Vishal Verma , Vaibhav Jain , Michael Ellerman , Dan Williams Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" Implement support for handling PAPR DSM commands in papr_scm module. We advertise support for ND_CMD_CALL for the dimm command mask and implement necessary scaffolding in the module to handle ND_CMD_CALL ioctl and DSM commands that we receive. The layout of the DSM commands as we expect from libnvdimm/libndctl is described in newly introduced uapi header 'papr_scm_dsm.h' which defines a new 'struct nd_papr_scm_cmd_pkg' header. This header is used to communicate the DSM command via 'nd_pkg_papr_scm->nd_command' and size of payload that need to be sent/received for servicing the DSM. The PAPR DSM commands are assigned indexes started from 0x10000 to prevent them from overlapping ND_CMD_* values and also makes handling dimm commands in papr_scm_ndctl(). A new function cmd_to_func() is implemented that reads the args to papr_scm_ndctl() and performs sanity tests on them. In case of a DSM command being sent via ND_CMD_CALL a newly introduced function papr_scm_service_dsm() is called to handle the request. Signed-off-by: Vaibhav Jain Reviewed-by: Aneesh Kumar K.V --- Changelog: v4..v5: Fixed a bug in new implementation of papr_scm_ndctl(). v3..v4: Updated papr_scm_ndctl() to delegate DSM command handling to a different function papr_scm_service_dsm(). [Aneesh] v2..v3: Updated the nd_papr_scm_cmd_pkg to use __xx types as its exported to the userspace [Aneesh] v1..v2: New patch in the series. --- arch/powerpc/include/uapi/asm/papr_scm_dsm.h | 161 +++++++++++++++++++ arch/powerpc/platforms/pseries/papr_scm.c | 97 ++++++++++- 2 files changed, 252 insertions(+), 6 deletions(-) create mode 100644 arch/powerpc/include/uapi/asm/papr_scm_dsm.h diff --git a/arch/powerpc/include/uapi/asm/papr_scm_dsm.h b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h new file mode 100644 index 000000000000..c039a49b41b4 --- /dev/null +++ b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * PAPR SCM Device specific methods and struct for libndctl and ndctl + * + * (C) Copyright IBM 2020 + * + * Author: Vaibhav Jain + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_ +#define _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_ + +#include + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +/* + * DSM Envelope: + * + * The ioctl ND_CMD_CALL transfers data between user-space and kernel via + * 'envelopes' which consists of a header and user-defined payload sections. + * The header is described by 'struct nd_papr_scm_cmd_pkg' which expects a + * payload following it and offset of which relative to the struct is provided + * by 'nd_papr_scm_cmd_pkg.payload_offset'. * + * + * +-------------+---------------------+---------------------------+ + * | 64-Bytes | 8-Bytes | Max 184-Bytes | + * +-------------+---------------------+---------------------------+ + * | nd_papr_scm_cmd_pkg | | + * |-------------+ | | + * | nd_cmd_pkg | | | + * +-------------+---------------------+---------------------------+ + * | nd_family | | | + * | nd_size_out | cmd_status | | + * | nd_size_in | payload_version | PAYLOAD | + * | nd_command | payload_offset -----> | + * | nd_fw_size | | | + * +-------------+---------------------+---------------------------+ + * + * DSM Header: + * + * The header is defined as 'struct nd_papr_scm_cmd_pkg' which embeds a + * 'struct nd_cmd_pkg' instance. The DSM command is assigned to member + * 'nd_cmd_pkg.nd_command'. Apart from size information of the envelop which is + * contained in 'struct nd_cmd_pkg', the header also has members following + * members: + * + * 'cmd_status' : (Out) Errors if any encountered while servicing DSM. + * 'payload_version' : (In/Out) Version number associated with the payload. + * 'payload_offset' : (In)Relative offset of payload from start of envelope. + * + * DSM Payload: + * + * The layout of the DSM Payload is defined by various structs shared between + * papr_scm and libndctl so that contents of payload can be interpreted. During + * servicing of a DSM the papr_scm module will read input args from the payload + * field by casting its contents to an appropriate struct pointer based on the + * DSM command. Similarly the output of servicing the DSM command will be copied + * to the payload field using the same struct. + * + * 'libnvdimm' enforces a hard limit of 256 bytes on the envelope size, which + * leaves around 184 bytes for the envelope payload (ignoring any padding that + * the compiler may silently introduce). + * + * Payload Version: + * + * A 'payload_version' field is present in DSM header that indicates a specific + * version of the structure present in DSM Payload for a given DSM command. This + * provides backward compatibility in case the DSM Payload structure evolves + * and different structures are supported by 'papr_scm' and 'libndctl'. + * + * When sending a DSM Payload to 'papr_scm', 'libndctl' should send the version + * of the payload struct it supports via 'payload_version' field. The 'papr_scm' + * module when servicing the DSM envelop checks the 'payload_version' and then + * uses 'payload struct version' == MIN('payload_version field', + * 'max payload-struct-version supported by papr_scm') to service the DSM. After + * servicing the DSM, 'papr_scm' put the negotiated version of payload struct in + * returned 'payload_version' field. + * + * Libndctl on receiving the envelop back from papr_scm again checks the + * 'payload_version' field and based on it use the appropriate version dsm + * struct to parse the results. + * + * Backward Compatibility: + * + * Above scheme of exchanging different versioned DSM struct between libndctl + * and papr_scm should provide backward compatibility until following two + * assumptions/conditions when defining new DSM structs hold: + * + * Let T(X) = { set of attributes in DSM struct 'T' versioned X } + * + * 1. T(X) is a proper subset of T(Y) if X > Y. + * i.e Each new version of DSM struct should retain existing struct + * attributes from previous version + * + * 2. If an entity (libndctl or papr_scm) supports a DSM struct T(X) then + * it should also support T(1), T(2)...T(X - 1). + * i.e When adding support for new version of a DSM struct, libndctl + * and papr_scm should retain support of the existing DSM struct + * version they support. + */ + +/* Papr-scm-header + payload expected with ND_CMD_CALL ioctl from libnvdimm */ +struct nd_papr_scm_cmd_pkg { + struct nd_cmd_pkg hdr; /* Package header containing sub-cmd */ + __s32 cmd_status; /* Out: Sub-cmd status returned back */ + __u16 payload_offset; /* In: offset from start of struct */ + __u16 payload_version; /* In/Out: version of the payload */ + __u8 payload[]; /* In/Out: Sub-cmd data buffer */ +}; + +/* + * Sub commands for ND_CMD_CALL. To prevent overlap from ND_CMD_*, values for + * these enums start at 0x10000. These values are then returned from + * cmd_to_func() making it easy to implement the switch-case block in + * papr_scm_ndctl(). These commands are sent to the kernel via + * 'nd_papr_scm_cmd_pkg.hdr.nd_command' + */ +enum dsm_papr_scm { + DSM_PAPR_SCM_MIN = 0x10000, + DSM_PAPR_SCM_MAX, +}; + +/* Helpers to evaluate the size of PAPR_SCM envelope */ +/* Calculate the papr_scm-header size */ +#define ND_PAPR_SCM_ENVELOPE_CONTENT_HDR_SIZE \ + (sizeof(struct nd_papr_scm_cmd_pkg) - sizeof(struct nd_cmd_pkg)) + +/* Given a type calculate envelope-content size (papr_scm-header + payload) */ +#define ND_PAPR_SCM_ENVELOPE_CONTENT_SIZE(_type_) \ + (sizeof(_type_) + ND_PAPR_SCM_ENVELOPE_CONTENT_HDR_SIZE) + +/* Convert a libnvdimm nd_cmd_pkg to papr_scm specific pkg */ +static struct nd_papr_scm_cmd_pkg *nd_to_papr_cmd_pkg(struct nd_cmd_pkg *cmd) +{ + return (struct nd_papr_scm_cmd_pkg *) cmd; +} + +/* Return the payload pointer for a given pcmd */ +static void *papr_scm_pcmd_to_payload(struct nd_papr_scm_cmd_pkg *pcmd) +{ + if (pcmd->hdr.nd_size_in == 0 && pcmd->hdr.nd_size_out == 0) + return NULL; + else + return (void *)((__u8 *) pcmd + pcmd->payload_offset); +} +#endif /* _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_ */ diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index aaf2e4ab1f75..e8ce96d2249e 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -15,13 +15,15 @@ #include #include +#include #define BIND_ANY_ADDR (~0ul) #define PAPR_SCM_DIMM_CMD_MASK \ ((1ul << ND_CMD_GET_CONFIG_SIZE) | \ (1ul << ND_CMD_GET_CONFIG_DATA) | \ - (1ul << ND_CMD_SET_CONFIG_DATA)) + (1ul << ND_CMD_SET_CONFIG_DATA) | \ + (1ul << ND_CMD_CALL)) struct papr_scm_priv { struct platform_device *pdev; @@ -283,15 +285,92 @@ static int papr_scm_meta_set(struct papr_scm_priv *p, return 0; } +/* + * Validate the inputs args to dimm-control function and return '0' if valid. + * This also does initial sanity validation to ND_CMD_CALL sub-command packages. + */ +static int is_cmd_valid(struct nvdimm *nvdimm, unsigned int cmd, void *buf, + unsigned int buf_len) +{ + unsigned long cmd_mask = PAPR_SCM_DIMM_CMD_MASK; + struct nd_papr_scm_cmd_pkg *pkg = nd_to_papr_cmd_pkg(buf); + + /* Only dimm-specific calls are supported atm */ + if (!nvdimm) + return -EINVAL; + + if (!test_bit(cmd, &cmd_mask)) { + pr_debug("%s: Unsupported cmd=%u\n", __func__, cmd); + return -EINVAL; + } else if (cmd == ND_CMD_CALL) { + + /* Verify the envelop package */ + if (!buf || buf_len < sizeof(struct nd_papr_scm_cmd_pkg)) { + pr_debug("%s: Invalid pkg size=%u\n", __func__, + buf_len); + return -EINVAL; + } + + /* Verify that the DSM command family is valid */ + if (pkg->hdr.nd_family != NVDIMM_FAMILY_PAPR_SCM) { + pr_debug("%s: Invalid pkg family=0x%llx\n", __func__, + pkg->hdr.nd_family); + return -EINVAL; + + } + + /* We except a payload with all DSM commands */ + if (papr_scm_pcmd_to_payload(pkg) == NULL) { + pr_debug("%s: Empty payload for sub-command=0x%llx\n", + __func__, pkg->hdr.nd_command); + return -EINVAL; + } + } + + /* Command looks valid */ + return 0; +} + +static int papr_scm_service_dsm(struct papr_scm_priv *p, + struct nd_papr_scm_cmd_pkg *call_pkg) +{ + /* unknown subcommands return error in packages */ + if (call_pkg->hdr.nd_command <= DSM_PAPR_SCM_MIN || + call_pkg->hdr.nd_command >= DSM_PAPR_SCM_MAX) { + pr_debug("Invalid DSM command 0x%llx\n", + call_pkg->hdr.nd_command); + call_pkg->cmd_status = -EINVAL; + return 0; + } + + /* Depending on the DSM command call appropriate service routine */ + switch (call_pkg->hdr.nd_command) { + default: + pr_debug("Unsupported DSM command 0x%llx\n", + call_pkg->hdr.nd_command); + call_pkg->cmd_status = -ENOENT; + return 0; + } +} + int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) { struct nd_cmd_get_config_size *get_size_hdr; struct papr_scm_priv *p; + struct nd_papr_scm_cmd_pkg *call_pkg = NULL; + int rc; - /* Only dimm-specific calls are supported atm */ - if (!nvdimm) - return -EINVAL; + /* Use a local variable in case cmd_rc pointer is NULL */ + if (cmd_rc == NULL) + cmd_rc = &rc; + + *cmd_rc = is_cmd_valid(nvdimm, cmd, buf, buf_len); + if (*cmd_rc) { + pr_debug("%s: Invalid cmd=0x%x. Err=%d\n", __func__, + cmd, *cmd_rc); + return *cmd_rc; + } p = nvdimm_provider_data(nvdimm); @@ -313,13 +392,19 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, *cmd_rc = papr_scm_meta_set(p, buf); break; + case ND_CMD_CALL: + call_pkg = nd_to_papr_cmd_pkg(buf); + *cmd_rc = papr_scm_service_dsm(p, call_pkg); + break; + default: - return -EINVAL; + dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd); + *cmd_rc = -EINVAL; } dev_dbg(&p->pdev->dev, "returned with cmd_rc = %d\n", *cmd_rc); - return 0; + return *cmd_rc; } static inline int papr_scm_node(int node) From patchwork Tue Mar 31 14:32:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Jain X-Patchwork-Id: 1264788 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48sCB43317z9sPk for ; Wed, 1 Apr 2020 01:58:04 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 48sCB40cBkzDqsh for ; Wed, 1 Apr 2020 01:58:04 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linux.ibm.com (client-ip=148.163.158.5; helo=mx0a-001b2d01.pphosted.com; envelope-from=vaibhav@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com 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 48sBdM3Tp9zDqVT for ; Wed, 1 Apr 2020 01:33:11 +1100 (AEDT) Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 02VE3HpA039829 for ; Tue, 31 Mar 2020 10:33:01 -0400 Received: from e06smtp03.uk.ibm.com (e06smtp03.uk.ibm.com [195.75.94.99]) by mx0b-001b2d01.pphosted.com with ESMTP id 30206yajs2-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 31 Mar 2020 10:33:00 -0400 Received: from localhost by e06smtp03.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 31 Mar 2020 15:32:52 +0100 Received: from b06avi18626390.portsmouth.uk.ibm.com (9.149.26.192) by e06smtp03.uk.ibm.com (192.168.101.133) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Tue, 31 Mar 2020 15:32:50 +0100 Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06avi18626390.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 02VEVqYc47710664 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 31 Mar 2020 14:31:52 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8CDD2A404D; Tue, 31 Mar 2020 14:32:55 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D3379A4059; Tue, 31 Mar 2020 14:32:52 +0000 (GMT) Received: from vajain21.in.ibm.com.com (unknown [9.85.86.229]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTP; Tue, 31 Mar 2020 14:32:52 +0000 (GMT) From: Vaibhav Jain To: linuxppc-dev@lists.ozlabs.org, linux-nvdimm@lists.01.org Subject: [PATCH v5 4/4] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH Date: Tue, 31 Mar 2020 20:02:29 +0530 X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200331143229.306718-1-vaibhav@linux.ibm.com> References: <20200331143229.306718-1-vaibhav@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 20033114-0012-0000-0000-0000039BAAB8 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 20033114-0013-0000-0000-000021D8B71F Message-Id: <20200331143229.306718-5-vaibhav@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-03-31_04:2020-03-31, 2020-03-31 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 malwarescore=0 spamscore=0 lowpriorityscore=0 adultscore=0 mlxlogscore=999 suspectscore=0 bulkscore=0 phishscore=0 priorityscore=1501 mlxscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2003310125 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alastair D'Silva , "Aneesh Kumar K . V" , Jeff Moyer , Oliver O'Halloran , Vishal Verma , Vaibhav Jain , Michael Ellerman , Dan Williams Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" This patch implements support for papr_scm command 'DSM_PAPR_SCM_HEALTH' that returns a newly introduced 'struct nd_papr_scm_dimm_health_stat' instance containing dimm health information back to user space in response to ND_CMD_CALL. This functionality is implemented in newly introduced papr_scm_get_health() that queries the scm-dimm health information and then copies these bitmaps to the package payload whose layout is defined by 'struct papr_scm_ndctl_health'. The patch also introduces a new member a new member 'struct papr_scm_priv.health' thats an instance of 'struct nd_papr_scm_dimm_health_stat' to cache the health information of a scm-dimm. As a result functions drc_pmem_query_health() and papr_flags_show() are updated to populate and use this new struct instead of two be64 integers that we earlier used. Signed-off-by: Vaibhav Jain Reviewed-by: Aneesh Kumar K.V --- Changelog: v4..v5: None v3..v4: Call the DSM_PAPR_SCM_HEALTH service function from papr_scm_service_dsm() instead of papr_scm_ndctl(). [Aneesh] v2..v3: Updated struct nd_papr_scm_dimm_health_stat_v1 to use '__xx' types as its exported to the userspace [Aneesh] Changed the constants DSM_PAPR_SCM_DIMM_XX indicating dimm health from enum to #defines [Aneesh] v1..v2: New patch in the series --- arch/powerpc/include/uapi/asm/papr_scm_dsm.h | 40 +++++++ arch/powerpc/platforms/pseries/papr_scm.c | 109 ++++++++++++++++--- 2 files changed, 132 insertions(+), 17 deletions(-) diff --git a/arch/powerpc/include/uapi/asm/papr_scm_dsm.h b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h index c039a49b41b4..8265125304ca 100644 --- a/arch/powerpc/include/uapi/asm/papr_scm_dsm.h +++ b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h @@ -132,6 +132,7 @@ struct nd_papr_scm_cmd_pkg { */ enum dsm_papr_scm { DSM_PAPR_SCM_MIN = 0x10000, + DSM_PAPR_SCM_HEALTH, DSM_PAPR_SCM_MAX, }; @@ -158,4 +159,43 @@ static void *papr_scm_pcmd_to_payload(struct nd_papr_scm_cmd_pkg *pcmd) else return (void *)((__u8 *) pcmd + pcmd->payload_offset); } + +/* Various scm-dimm health indicators */ +#define DSM_PAPR_SCM_DIMM_HEALTHY 0 +#define DSM_PAPR_SCM_DIMM_UNHEALTHY 1 +#define DSM_PAPR_SCM_DIMM_CRITICAL 2 +#define DSM_PAPR_SCM_DIMM_FATAL 3 + +/* + * Struct exchanged between kernel & ndctl in for PAPR_DSM_PAPR_SMART_HEALTH + * Various bitflags indicate the health status of the dimm. + * + * dimm_unarmed : Dimm not armed. So contents wont persist. + * dimm_bad_shutdown : Previous shutdown did not persist contents. + * dimm_bad_restore : Contents from previous shutdown werent restored. + * dimm_scrubbed : Contents of the dimm have been scrubbed. + * dimm_locked : Contents of the dimm cant be modified until CEC reboot + * dimm_encrypted : Contents of dimm are encrypted. + * dimm_health : Dimm health indicator. + */ +struct nd_papr_scm_dimm_health_stat_v1 { + __u8 dimm_unarmed; + __u8 dimm_bad_shutdown; + __u8 dimm_bad_restore; + __u8 dimm_scrubbed; + __u8 dimm_locked; + __u8 dimm_encrypted; + __u16 dimm_health; +}; + +/* + * Typedef the current struct for dimm_health so that any application + * or kernel recompiled after introducing a new version automatically + * supports the new version. + */ +#define nd_papr_scm_dimm_health_stat nd_papr_scm_dimm_health_stat_v1 + +/* Current version number for the dimm health struct */ +#define ND_PAPR_SCM_DIMM_HEALTH_VERSION 1 + #endif /* _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_ */ diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index e8ce96d2249e..ce94762954e0 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -47,8 +47,7 @@ struct papr_scm_priv { struct mutex dimm_mutex; /* Health information for the dimm */ - __be64 health_bitmap; - __be64 health_bitmap_valid; + struct nd_papr_scm_dimm_health_stat health; }; static int drc_pmem_bind(struct papr_scm_priv *p) @@ -158,6 +157,7 @@ static int drc_pmem_query_health(struct papr_scm_priv *p) { unsigned long ret[PLPAR_HCALL_BUFSIZE]; int64_t rc; + __be64 health; rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index); if (rc != H_SUCCESS) { @@ -172,13 +172,41 @@ static int drc_pmem_query_health(struct papr_scm_priv *p) return rc; /* Store the retrieved health information in dimm platform data */ - p->health_bitmap = ret[0]; - p->health_bitmap_valid = ret[1]; + health = ret[0] & ret[1]; dev_dbg(&p->pdev->dev, "Queried dimm health info. Bitmap:0x%016llx Mask:0x%016llx\n", - be64_to_cpu(p->health_bitmap), - be64_to_cpu(p->health_bitmap_valid)); + be64_to_cpu(ret[0]), + be64_to_cpu(ret[1])); + + memset(&p->health, 0, sizeof(p->health)); + + /* Check for various masks in bitmap and set the buffer */ + if (health & PAPR_SCM_DIMM_UNARMED_MASK) + p->health.dimm_unarmed = true; + + if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK) + p->health.dimm_bad_shutdown = true; + + if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK) + p->health.dimm_bad_restore = true; + + if (health & PAPR_SCM_DIMM_ENCRYPTED) + p->health.dimm_encrypted = true; + + if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED) { + p->health.dimm_locked = true; + p->health.dimm_scrubbed = true; + } + + if (health & PAPR_SCM_DIMM_HEALTH_UNHEALTHY) + p->health.dimm_health = DSM_PAPR_SCM_DIMM_UNHEALTHY; + + if (health & PAPR_SCM_DIMM_HEALTH_CRITICAL) + p->health.dimm_health = DSM_PAPR_SCM_DIMM_CRITICAL; + + if (health & PAPR_SCM_DIMM_HEALTH_FATAL) + p->health.dimm_health = DSM_PAPR_SCM_DIMM_FATAL; mutex_unlock(&p->dimm_mutex); return 0; @@ -331,6 +359,51 @@ static int is_cmd_valid(struct nvdimm *nvdimm, unsigned int cmd, void *buf, return 0; } +/* Fetch the DIMM health info and populate it in provided package. */ +static int papr_scm_get_health(struct papr_scm_priv *p, + struct nd_papr_scm_cmd_pkg *pkg) +{ + int rc; + size_t copysize = sizeof(p->health); + + rc = drc_pmem_query_health(p); + if (rc) + goto out; + /* + * If the requested payload version is greater than one we know + * about, return the payload version we know about and let + * caller/userspace handle. + */ + if (pkg->payload_version > ND_PAPR_SCM_DIMM_HEALTH_VERSION) + pkg->payload_version = ND_PAPR_SCM_DIMM_HEALTH_VERSION; + + if (pkg->hdr.nd_size_out < copysize) { + dev_dbg(&p->pdev->dev, "%s Payload not large enough\n", + __func__); + dev_dbg(&p->pdev->dev, "%s Expected %lu, available %u\n", + __func__, copysize, pkg->hdr.nd_size_out); + rc = -ENOSPC; + goto out; + } + + dev_dbg(&p->pdev->dev, "%s Copying payload size=%lu version=0x%x\n", + __func__, copysize, pkg->payload_version); + + /* Copy a subset of health struct based on copysize */ + memcpy(papr_scm_pcmd_to_payload(pkg), &p->health, copysize); + pkg->hdr.nd_fw_size = copysize; + +out: + /* + * Put the error in out package and return success from function + * so that errors if any are propogated back to userspace. + */ + pkg->cmd_status = rc; + dev_dbg(&p->pdev->dev, "%s completion code = %d\n", __func__, rc); + + return 0; +} + static int papr_scm_service_dsm(struct papr_scm_priv *p, struct nd_papr_scm_cmd_pkg *call_pkg) { @@ -345,6 +418,9 @@ static int papr_scm_service_dsm(struct papr_scm_priv *p, /* Depending on the DSM command call appropriate service routine */ switch (call_pkg->hdr.nd_command) { + case DSM_PAPR_SCM_HEALTH: + return papr_scm_get_health(p, call_pkg); + default: pr_debug("Unsupported DSM command 0x%llx\n", call_pkg->hdr.nd_command); @@ -431,7 +507,6 @@ static ssize_t papr_flags_show(struct device *dev, { struct nvdimm *dimm = to_nvdimm(dev); struct papr_scm_priv *p = nvdimm_provider_data(dimm); - __be64 health; int rc; rc = drc_pmem_query_health(p); @@ -443,26 +518,26 @@ static ssize_t papr_flags_show(struct device *dev, if (rc) return rc; - health = p->health_bitmap & p->health_bitmap_valid; - - /* Check for various masks in bitmap and set the buffer */ - if (health & PAPR_SCM_DIMM_UNARMED_MASK) + if (p->health.dimm_unarmed) rc += sprintf(buf, "not_armed "); - if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK) + if (p->health.dimm_bad_shutdown) rc += sprintf(buf + rc, "save_fail "); - if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK) + if (p->health.dimm_bad_restore) rc += sprintf(buf + rc, "restore_fail "); - if (health & PAPR_SCM_DIMM_ENCRYPTED) + if (p->health.dimm_encrypted) rc += sprintf(buf + rc, "encrypted "); - if (health & PAPR_SCM_DIMM_SMART_EVENT_MASK) + if (p->health.dimm_health) rc += sprintf(buf + rc, "smart_notify "); - if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED) - rc += sprintf(buf + rc, "scrubbed locked "); + if (p->health.dimm_scrubbed) + rc += sprintf(buf + rc, "scrubbed "); + + if (p->health.dimm_locked) + rc += sprintf(buf + rc, "locked "); if (rc > 0) rc += sprintf(buf + rc, "\n");