From patchwork Fri Sep 15 17:28:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shiju Jose X-Patchwork-Id: 13387306 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95BDBEED61C for ; Fri, 15 Sep 2023 17:29:15 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D8AD16B036C; Fri, 15 Sep 2023 13:29:10 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id D3AA36B0372; Fri, 15 Sep 2023 13:29:10 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B66506B0383; Fri, 15 Sep 2023 13:29:10 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 9D73B6B0372 for ; Fri, 15 Sep 2023 13:29:10 -0400 (EDT) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 76ADF1A05A9 for ; Fri, 15 Sep 2023 17:29:10 +0000 (UTC) X-FDA: 81239517660.11.ABD6FB9 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by imf13.hostedemail.com (Postfix) with ESMTP id 5D6072002E for ; Fri, 15 Sep 2023 17:29:08 +0000 (UTC) Authentication-Results: imf13.hostedemail.com; dkim=none; dmarc=pass (policy=quarantine) header.from=huawei.com; spf=pass (imf13.hostedemail.com: domain of shiju.jose@huawei.com designates 185.176.79.56 as permitted sender) smtp.mailfrom=shiju.jose@huawei.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1694798948; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FHAU3zMpaz6YfNbIxl84w6JNtmNTEhNBeSn1h4RlwOo=; b=oAzyKTxZCd+aLHxgS9ZSPaodEnF82d4VZJpaTPRtOsFrFbgSVFofYfGuYZJGJN4whExRm3 qMJah0c0in1DNXbFgVdFiLiLS1s7by6IpUPesUWzX4TpuyNWGoRMtvWmr7iTjpDa/SClAp Hmu1+qqywfN2xy0hNOCWkWzYxpLAdSU= ARC-Authentication-Results: i=1; imf13.hostedemail.com; dkim=none; dmarc=pass (policy=quarantine) header.from=huawei.com; spf=pass (imf13.hostedemail.com: domain of shiju.jose@huawei.com designates 185.176.79.56 as permitted sender) smtp.mailfrom=shiju.jose@huawei.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1694798948; a=rsa-sha256; cv=none; b=jP10BV1sSopWrnJ6K8NfXIn+G6MA8vKOY0lLq/fy1kmuoNOrELe1bvCwmd9oz0y5bbr7Ht aW5PvKL80UVdxF18IEUcbPisiE/c3+KIIDj0TRjhKkt6VKVp9XjB2Iqr/uj4+YgtSqoSmq tPBguGURBukOdmh07NLzN6UYSP/LPQE= Received: from lhrpeml500006.china.huawei.com (unknown [172.18.147.226]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4RnLdz49S5z67nH3; Sat, 16 Sep 2023 01:24:23 +0800 (CST) Received: from SecurePC30232.china.huawei.com (10.122.247.234) by lhrpeml500006.china.huawei.com (7.191.161.198) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.31; Fri, 15 Sep 2023 18:29:06 +0100 From: To: , , CC: , , , , , , , , , , , , , , , , , , , , , Subject: [RFC PATCH 5/9] ACPI:RASF: Add common library for RASF and RAS2 PCC interfaces Date: Sat, 16 Sep 2023 01:28:14 +0800 Message-ID: <20230915172818.761-6-shiju.jose@huawei.com> X-Mailer: git-send-email 2.35.1.windows.2 In-Reply-To: <20230915172818.761-1-shiju.jose@huawei.com> References: <20230915172818.761-1-shiju.jose@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.234] X-ClientProxiedBy: lhrpeml500001.china.huawei.com (7.191.163.213) To lhrpeml500006.china.huawei.com (7.191.161.198) X-CFilter-Loop: Reflected X-Rspam-User: X-Stat-Signature: haaa1kpxbwf5kq4m3fjh74jsoyhn4fbq X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: 5D6072002E X-HE-Tag: 1694798948-95778 X-HE-Meta: U2FsdGVkX1+/ChETBK0CfYDD+l5a4aIQKVUrkzXWjpZxgjaPO09JG1drYjtXTcTuRt+qdiWjDYTdGEoa507RmFk5ZPHq7DiuerCkN8E5ZSNigW/BllZbxrIzC0tR3NihM4APZx7llnED4gErIL5/Mn0WQkOE8/eLgkQhVszd6kRav8GkZrAqpqDQwItN2fHvcmYouiYyKCarLT9QTlGj3PU94GGQQmiUESDn7vatKTxhXK5zGUPFcs9ka/zMh/zXyS/wmxvUuC3twP/xsCKe/tsRVBXX4wlnKwa9wvGPhmo/IzMq9xsaL1SawnASIsGXf7GE5SOAn1aX8SLgI2APBrLXyRueTiux5FsL1bTsaE60hUsfQ0YK8L3bLY1gRfzmF+0ik50qjHDDWLcrwr4t5n4xrEL4Pt5NBtP/23v3hB0QzazjChraRzsYzsqoHQnMMGqQ88kFSH/QJuk2J3b22t4QWAC193GiKMvMIg1DigQJgBJ4LRKNDIrVXhWOwE+m0VCl5L1zXtOV5d7vzrXjne6IjFC5AU8GK52psdYmwd8EP6DXng3+bC1DWKBGSsgvsAiRjpRdf16jQDmlaBzkjMoAIoMJ3Dj0+xfWZiySPlNkmshtyUMESLbjPSfOwjhm9Off7Sa63xwrSjsHjS+pWy0+w0U3TESt+nJw57CEjgMnXa6SbFTpQmskXEDfx7luG5TjkcXoGlrQ5k1imG9xSikzK+fdHGjUCyoMvB+mTGwuWzaW/8bsRSlwc4bbjhwbCle4eBTWRJv+5oCC3vlX3OUVn4XFVtTdxxURCpMBk34TIg6JKzxWHT15DpG2O3v1L8WAKwcsPo3XgUtyPLEnx2wWYeH/GJPrCXUWeEM3+2yA8v2D5sFcBZNdAESRMoXhCh6RXFRPoxSP+h6lfSeC9f4jN9hz4wOv9ZhUF6utWcxbwIKSFsl07KwRF9RQ2wNRcNXcC0EdjiedvuHnghj 0ix/jOVp fWCp0R7dXGeJM7guv1sSAGpGXxmxzkkR3nzviiqZky2cXDui3/MJX23ulKvvogFOZU4P61/bOL8bDHoTGNqmk4pnSKD2UpCYZKrc6TazxofCB+4oYI4YRzYAX61t6R/w2EPbMhRR5K71yEatTBrsAYni8CImzqmXdBcCtH/tADoq3z2WOrseu9qJKuABYGRueHTAsWDzZbi/2rMA= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: A Somasundaram The code contains PCC interfaces for RASF and RAS2 table, functions to send RASF commands as per ACPI 5.1 and RAS2 commands as per ACPI 6.5 & upwards revision. References for this implementation, ACPI specification, section 5.2.20 for RASF table, section 5.2.21 for RAS2 table and chapter 14 for PCC (Platform Communication Channel). Driver uses PCC interfaces to communicate to the ACPI HW. This code implements PCC interfaces and the functions to send the RASF/RAS2 commands to be used by OSPM. Signed-off-by: A Somasundaram Co-developed-by: Shiju Jose Signed-off-by: Shiju Jose --- drivers/acpi/Kconfig | 12 +- drivers/acpi/Makefile | 2 +- drivers/acpi/rasf_acpi.c | 26 --- drivers/acpi/rasf_acpi_common.c | 272 ++++++++++++++++++++++++++++++++ include/acpi/rasf_acpi.h | 40 +++++ 5 files changed, 322 insertions(+), 30 deletions(-) create mode 100755 drivers/acpi/rasf_acpi_common.c diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index e5fd8edc5b35..057f7fbc9887 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -283,10 +283,16 @@ config ACPI_RASF bool "ACPI RASF driver" depends on ACPI_PROCESSOR select MAILBOX + select PCC help - The driver adds support for extraction of RASF table from OS - system table. Driver adds platform device which binds to the - RASF memory driver. + The driver adds support for PCC (platform communication + channel) interfaces to communicate with the ACPI complaint + hardware platform supports RASF(RAS Feature table) or + and RAS2(RAS2 Feature table). + The driver adds support for RASF(extraction of RASF tables + from OS system table), PCC interfaces and OSPM interfaces to + send RASF & RAS2 commands. Driver adds platform device which + binds to the RASF/RAS2 memory driver. config ACPI_PROCESSOR tristate "Processor" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index f8a1263f6128..dd62d936cbe1 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -104,7 +104,7 @@ obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o -obj-$(CONFIG_ACPI_RASF) += rasf_acpi.o +obj-$(CONFIG_ACPI_RASF) += rasf_acpi_common.o rasf_acpi.o obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o obj-$(CONFIG_ACPI_PPTT) += pptt.o obj-$(CONFIG_ACPI_PFRUT) += pfr_update.o pfr_telemetry.o diff --git a/drivers/acpi/rasf_acpi.c b/drivers/acpi/rasf_acpi.c index b30ba2a5e4ff..4c752fab9c4c 100755 --- a/drivers/acpi/rasf_acpi.c +++ b/drivers/acpi/rasf_acpi.c @@ -25,32 +25,6 @@ #include #include -static struct platform_device *rasf_add_platform_device(char *name, const void *data, - size_t size) -{ - int ret; - struct platform_device *pdev; - - pdev = platform_device_alloc(name, PLATFORM_DEVID_AUTO); - if (!pdev) - return NULL; - - ret = platform_device_add_data(pdev, data, size); - if (ret) - goto dev_put; - - ret = platform_device_add(pdev); - if (ret) - goto dev_put; - - return pdev; - -dev_put: - platform_device_put(pdev); - - return NULL; -} - int __init rasf_acpi_init(void) { acpi_status status; diff --git a/drivers/acpi/rasf_acpi_common.c b/drivers/acpi/rasf_acpi_common.c new file mode 100755 index 000000000000..3ee34f5d12d3 --- /dev/null +++ b/drivers/acpi/rasf_acpi_common.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * rasf_acpi_common.c - ACPI RASF table processing common functions + * + * (C) Copyright 2014, 2015 Hewlett-Packard Enterprises. + * + * Copyright (c) 2023 HiSilicon Limited. + * + * Support for + * RASF - ACPI 6.5 Specification, section 5.2.20 + * RAS2 - ACPI 6.5 Specification, section 5.2.21 + * PCC(Platform Communications Channel) - ACPI 6.5 Specification, + * chapter 14. + * + * Code contains common functions for RASF. + * PCC(Platform communication channel) interfaces for the RASF & RAS2 + * and the functions for sending RASF & RAS2 commands to the ACPI HW. + */ + +#define pr_fmt(fmt) "ACPI RASF COMMON: " fmt + +#include +#include +#include +#include +#include +#include + +static int rasf_check_pcc_chan(struct rasf_context *rasf_ctx) +{ + int ret = -EIO; + struct acpi_rasf_shared_memory __iomem *generic_comm_base = rasf_ctx->pcc_comm_addr; + ktime_t next_deadline = ktime_add(ktime_get(), rasf_ctx->deadline); + + while (!ktime_after(ktime_get(), next_deadline)) { + /* + * As per ACPI spec, the PCC space wil be initialized by + * platform and should have set the command completion bit when + * PCC can be used by OSPM + */ + if (readw_relaxed(&generic_comm_base->status) & RASF_PCC_CMD_COMPLETE) { + ret = 0; + break; + } + /* + * Reducing the bus traffic in case this loop takes longer than + * a few retries. + */ + udelay(10); + } + + return ret; +} + +/** + * rasf_send_pcc_cmd() - Send RASF command via PCC channel + * @rasf_ctx: pointer to the rasf context structure + * @cmd: command to send + * + * Returns: 0 on success, an error otherwise + */ +int rasf_send_pcc_cmd(struct rasf_context *rasf_ctx, u16 cmd) +{ + int ret = -EIO; + struct acpi_rasf_shared_memory *generic_comm_base = + (struct acpi_rasf_shared_memory *)rasf_ctx->pcc_comm_addr; + static ktime_t last_cmd_cmpl_time, last_mpar_reset; + static int mpar_count; + unsigned int time_delta; + + if (cmd == RASF_PCC_CMD_EXEC) { + ret = rasf_check_pcc_chan(rasf_ctx); + if (ret) + return ret; + } + + /* + * Handle the Minimum Request Turnaround Time(MRTT) + * "The minimum amount of time that OSPM must wait after the completion + * of a command before issuing the next command, in microseconds" + */ + if (rasf_ctx->pcc_mrtt) { + time_delta = ktime_us_delta(ktime_get(), last_cmd_cmpl_time); + if (rasf_ctx->pcc_mrtt > time_delta) + udelay(rasf_ctx->pcc_mrtt - time_delta); + } + + /* + * Handle the non-zero Maximum Periodic Access Rate(MPAR) + * "The maximum number of periodic requests that the subspace channel can + * support, reported in commands per minute. 0 indicates no limitation." + * + * This parameter should be ideally zero or large enough so that it can + * handle maximum number of requests that all the cores in the system can + * collectively generate. If it is not, we will follow the spec and just + * not send the request to the platform after hitting the MPAR limit in + * any 60s window + */ + if (rasf_ctx->pcc_mpar) { + if (mpar_count == 0) { + time_delta = ktime_ms_delta(ktime_get(), last_mpar_reset); + if (time_delta < 60 * MSEC_PER_SEC) { + pr_debug("PCC cmd not sent due to MPAR limit"); + return -EIO; + } + last_mpar_reset = ktime_get(); + mpar_count = rasf_ctx->pcc_mpar; + } + mpar_count--; + } + + /* Write to the shared comm region. */ + writew_relaxed(cmd, &generic_comm_base->command); + + /* Flip CMD COMPLETE bit */ + writew_relaxed(0, &generic_comm_base->status); + + /* Ring doorbell */ + ret = mbox_send_message(rasf_ctx->pcc_channel, &cmd); + if (ret < 0) { + pr_err("Err sending PCC mbox message. cmd:%d, ret:%d\n", + cmd, ret); + return ret; + } + + /* + * For READs we need to ensure the cmd completed to ensure + * the ensuing read()s can proceed. For WRITEs we dont care + * because the actual write()s are done before coming here + * and the next READ or WRITE will check if the channel + * is busy/free at the entry of this call. + * + * If Minimum Request Turnaround Time is non-zero, we need + * to record the completion time of both READ and WRITE + * command for proper handling of MRTT, so we need to check + * for pcc_mrtt in addition to CMD_READ + */ + if (cmd == RASF_PCC_CMD_EXEC || rasf_ctx->pcc_mrtt) { + ret = rasf_check_pcc_chan(rasf_ctx); + if (rasf_ctx->pcc_mrtt) + last_cmd_cmpl_time = ktime_get(); + } + + if (rasf_ctx->pcc_channel->mbox->txdone_irq) + mbox_chan_txdone(rasf_ctx->pcc_channel, ret); + else + mbox_client_txdone(rasf_ctx->pcc_channel, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(rasf_send_pcc_cmd); + +/** + * rasf_register_pcc_channel() - Register PCC channel + * @rasf_ctx: pointer to the rasf context structure + * + * Returns: 0 on success, an error otherwise + */ +int rasf_register_pcc_channel(struct rasf_context *rasf_ctx) +{ + u64 usecs_lat; + unsigned int len; + struct pcc_mbox_chan *pcc_chan; + struct mbox_client *rasf_mbox_cl; + struct acpi_pcct_hw_reduced *rasf_ss; + + rasf_mbox_cl = &rasf_ctx->mbox_client; + if (!rasf_mbox_cl || rasf_ctx->pcc_subspace_idx < 0) + return -EINVAL; + + pcc_chan = pcc_mbox_request_channel(rasf_mbox_cl, + rasf_ctx->pcc_subspace_idx); + + if (IS_ERR(pcc_chan)) { + pr_err("Failed to find PCC channel for subspace %d\n", + rasf_ctx->pcc_subspace_idx); + return -ENODEV; + } + rasf_ctx->pcc_chan = pcc_chan; + rasf_ctx->pcc_channel = pcc_chan->mchan; + /* + * The PCC mailbox controller driver should + * have parsed the PCCT (global table of all + * PCC channels) and stored pointers to the + * subspace communication region in con_priv. + */ + rasf_ss = rasf_ctx->pcc_channel->con_priv; + + if (!rasf_ss) { + pr_err("No PCC subspace found for RASF\n"); + pcc_mbox_free_channel(rasf_ctx->pcc_chan); + return -ENODEV; + } + + /* + * This is the shared communication region + * for the OS and Platform to communicate over. + */ + rasf_ctx->comm_base_addr = rasf_ss->base_address; + len = rasf_ss->length; + pr_debug("PCC subspace for RASF=0x%llx len=%d\n", + rasf_ctx->comm_base_addr, len); + + /* + * rasf_ss->latency is just a Nominal value. In reality + * the remote processor could be much slower to reply. + * So add an arbitrary amount of wait on top of Nominal. + */ + usecs_lat = RASF_NUM_RETRIES * rasf_ss->latency; + rasf_ctx->deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC); + rasf_ctx->pcc_mrtt = rasf_ss->min_turnaround_time; + rasf_ctx->pcc_mpar = rasf_ss->max_access_rate; + rasf_ctx->pcc_comm_addr = acpi_os_ioremap(rasf_ctx->comm_base_addr, len); + pr_debug("pcc_comm_addr=%p\n", rasf_ctx->pcc_comm_addr); + + /* Set flag so that we dont come here for each CPU. */ + rasf_ctx->pcc_channel_acquired = true; + + return 0; +} +EXPORT_SYMBOL_GPL(rasf_register_pcc_channel); + +/** + * rasf_unregister_pcc_channel() - Unregister PCC channel + * @rasf_ctx: pointer to the rasf context structure + * + * Returns: 0 on success, an error otherwise + */ +int rasf_unregister_pcc_channel(struct rasf_context *rasf_ctx) +{ + if (!rasf_ctx->pcc_chan) + return -EINVAL; + + pcc_mbox_free_channel(rasf_ctx->pcc_chan); + + return 0; +} +EXPORT_SYMBOL_GPL(rasf_unregister_pcc_channel); + +/** + * rasf_add_platform_device() - Add a platform device for RASF + * @name: name of the device we're adding + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * Returns: pointer to platform device on success, an error otherwise + */ +struct platform_device *rasf_add_platform_device(char *name, const void *data, + size_t size) +{ + int ret; + struct platform_device *pdev; + + pdev = platform_device_alloc(name, PLATFORM_DEVID_AUTO); + if (!pdev) + return NULL; + + ret = platform_device_add_data(pdev, data, size); + if (ret) + goto dev_put; + + ret = platform_device_add(pdev); + if (ret) + goto dev_put; + + return pdev; + +dev_put: + platform_device_put(pdev); + + return NULL; +} diff --git a/include/acpi/rasf_acpi.h b/include/acpi/rasf_acpi.h index 1c4c3e94d472..e91a451c5dc1 100755 --- a/include/acpi/rasf_acpi.h +++ b/include/acpi/rasf_acpi.h @@ -11,9 +11,49 @@ #define _RASF_ACPI_H #include +#include +#include #include +#include + +#define RASF_PCC_CMD_COMPLETE 1 + +/* RASF specific PCC commands */ +#define RASF_PCC_CMD_EXEC 0x01 #define RASF_FAILURE 0 #define RASF_SUCCESS 1 +/* + * Arbitrary Retries for PCC commands. + */ +#define RASF_NUM_RETRIES 600 + +/* + * Data structures for PCC communication and RASF table + */ +struct rasf_context { + struct device *dev; + int id; + struct mbox_client mbox_client; + struct mbox_chan *pcc_channel; + struct pcc_mbox_chan *pcc_chan; + void __iomem *pcc_comm_addr; + u64 comm_base_addr; + int pcc_subspace_idx; + bool pcc_channel_acquired; + ktime_t deadline; + unsigned int pcc_mpar; + unsigned int pcc_mrtt; + spinlock_t spinlock; /* Lock to provide mutually exclusive access to PCC channel */ + struct device *scrub_dev; + u8 n_regions; + const struct rasf_hw_scrub_ops *ops; +}; + +struct platform_device *rasf_add_platform_device(char *name, const void *data, + size_t size); +int rasf_send_pcc_cmd(struct rasf_context *rasf_ctx, u16 cmd); +int rasf_register_pcc_channel(struct rasf_context *rasf_ctx); +int rasf_unregister_pcc_channel(struct rasf_context *rasf_ctx); #endif /* _RASF_ACPI_H */