From mboxrd@z Thu Jan 1 00:00:00 1970 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 CDAEEC3DA49 for ; Tue, 30 Jul 2024 08:26:57 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 4BC916B0085; Tue, 30 Jul 2024 04:26:57 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 46C456B0088; Tue, 30 Jul 2024 04:26:57 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 30D536B0089; Tue, 30 Jul 2024 04:26:57 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 0DAA66B0085 for ; Tue, 30 Jul 2024 04:26:57 -0400 (EDT) Received: from smtpin19.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 7E437C0189 for ; Tue, 30 Jul 2024 08:26:56 +0000 (UTC) X-FDA: 82395738432.19.25C2E29 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by imf10.hostedemail.com (Postfix) with ESMTP id C69B2C0008 for ; Tue, 30 Jul 2024 08:26:53 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=none; dmarc=pass (policy=quarantine) header.from=huawei.com; spf=pass (imf10.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=1722327961; 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=QOUl8pxHrxSZCz5YDMP3fTl0xeMgSQAtnBldUv3BB64=; b=mTIfZ5u9qIRi+aa1vzr+nJ4lXUzsqSrm0a5BwrUEnoIGHoPqL8QiXEVjKvWAwinuwCKjNY iMrkvNShms/QmuJiLp1/I/CBMlqZR50iM13UxWqkZ0nXMiTzNqor2ULlNpRx9smaqa5ynY xR9MJ4hvH5HDSiz+8e5wtBupBl5by2I= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1722327961; a=rsa-sha256; cv=none; b=TgeHFQ1xagJWn9HzBCd7z8y+NaGDXihWrX27l68CX5r4LVSu4SHJrr8PSvGGlkqjZ4ZGtA MJrxZhE/RUS9Bv4HYGd+DZ9uTG272PPPgTW7RtSx9nFx9syhJfD50E2vsfUkGp6+Iu254u YrR5G65zpSqWPh/yWAO1M7vk2MdRxjM= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=none; dmarc=pass (policy=quarantine) header.from=huawei.com; spf=pass (imf10.hostedemail.com: domain of shiju.jose@huawei.com designates 185.176.79.56 as permitted sender) smtp.mailfrom=shiju.jose@huawei.com Received: from mail.maildlp.com (unknown [172.18.186.216]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4WY7Yb364bz6K63F; Tue, 30 Jul 2024 16:24:19 +0800 (CST) Received: from lhrpeml500001.china.huawei.com (unknown [7.191.163.213]) by mail.maildlp.com (Postfix) with ESMTPS id D7338140A35; Tue, 30 Jul 2024 16:26:47 +0800 (CST) Received: from lhrpeml500006.china.huawei.com (7.191.161.198) by lhrpeml500001.china.huawei.com (7.191.163.213) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Tue, 30 Jul 2024 09:26:47 +0100 Received: from lhrpeml500006.china.huawei.com ([7.191.161.198]) by lhrpeml500006.china.huawei.com ([7.191.161.198]) with mapi id 15.01.2507.039; Tue, 30 Jul 2024 09:26:47 +0100 From: Shiju Jose To: Fan Ni CC: "linux-edac@vger.kernel.org" , "linux-cxl@vger.kernel.org" , "linux-acpi@vger.kernel.org" , "linux-mm@kvack.org" , "linux-kernel@vger.kernel.org" , "bp@alien8.de" , "tony.luck@intel.com" , "rafael@kernel.org" , "lenb@kernel.org" , "mchehab@kernel.org" , "dan.j.williams@intel.com" , "dave@stgolabs.net" , "Jonathan Cameron" , "dave.jiang@intel.com" , "alison.schofield@intel.com" , "vishal.l.verma@intel.com" , "ira.weiny@intel.com" , "david@redhat.com" , "Vilas.Sridharan@amd.com" , "leo.duran@amd.com" , "Yazen.Ghannam@amd.com" , "rientjes@google.com" , "jiaqiyan@google.com" , "Jon.Grimm@amd.com" , "dave.hansen@linux.intel.com" , "naoya.horiguchi@nec.com" , "james.morse@arm.com" , "jthoughton@google.com" , "somasundaram.a@hpe.com" , "erdemaktas@google.com" , "pgonda@google.com" , "duenwen@google.com" , "mike.malvestuto@intel.com" , "gthelen@google.com" , "wschwartz@amperecomputing.com" , "dferguson@amperecomputing.com" , "wbs@os.amperecomputing.com" , tanxiaofei , "Zengtao (B)" , "Roberto Sassu" , "kangkang.shen@futurewei.com" , wanghuiqiang , Linuxarm Subject: RE: [PATCH v10 11/11] ras: scrub: ACPI RAS2: Add memory ACPI RAS2 driver Thread-Topic: [PATCH v10 11/11] ras: scrub: ACPI RAS2: Add memory ACPI RAS2 driver Thread-Index: AQHa33XeVxQpYU9F6U6E/PTakbhdSLIOOuYAgAC6M4A= Date: Tue, 30 Jul 2024 08:26:47 +0000 Message-ID: References: <20240726160556.2079-1-shiju.jose@huawei.com> <20240726160556.2079-12-shiju.jose@huawei.com> In-Reply-To: Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.48.153.72] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Rspamd-Queue-Id: C69B2C0008 X-Stat-Signature: 99ghetpi8h5dsh6uyojpja9fz18r63m8 X-Rspamd-Server: rspam09 X-Rspam-User: X-HE-Tag: 1722328013-764566 X-HE-Meta: U2FsdGVkX19dpfkeA9fZyD23EYu5aQ0E+F/gTL+r7+JerbGPoP1c0Fz7vF/ECcJJpvmMbnX7Fx4jiOsIdr/IIVnOWDxtdVoELvS9D6kQFQiG2mSnW3dd/cdkI3mX1aujA7RJYgACVnsEatu7sD7t1pyLIMukZdqUdJhuMpXMr+97rC1yRjNdnmEKXUysMwcBt7HIdwF0yTJvu3yH5vhfLoequA83s3yCBwB0fuBYUIEaK32XywraNq9t+tiQmSdrKyhH3+1Dwz0jgoWjpBHQ0g+fuCadXcE8TJRV1/zptAKP+DKyHvpq3FaLttyD9t6QU5I/H+UajPVBeelGTawGwqFpfe6HFLBhplaST51qqMQ0o5zG5/eZt9Mx378uV6CJDiwAJR1uc0GqlmcrK2gcP6H++scFw+LqvRCHWBppT0OdP1pOJoSWtzrArwVzIu0qQGHDsCFjWyjDwec8W5WWtmoSflcq05gCuYX6Va/OZlUhWz9bHmeVrbKJf04jYcq/sgXfo7GY3wcwGR4gBs27Br4CGyu5hMB8xRMEGtfsYxMZshFLqD3gtrrrzwb2yygRbfHqXTMrFxEojZXLJEh/FNT+EY2u1QHum8Nb6P6gGQfj1+PzciqC48RruLn52eFvirSUVsxb4ozUdCr4128BL7S7M3Nf8KYnOgUDyT5D298iXMRcrZDmgTtxiYTJElLxgpnjCwK2ny9tmo0CKERJNRwe3OMlalDjvMIfre8dw9Z0EVqoyOZ3P+1zKX4hYjs47qWq4IjiDoLEAtm0oocKY/tmH5Bk9zSaDYw+RsBs3WtmxmCDosc95+AHBZmCL/0d3QfRcF8XaWqKyZ1cXrEu1HZM3PP62t79WsUa83kghnYPXSqS1L7qKZDLTG7hl12WZCDZHquUlkMbe44s4cIlnZ/1D3yvcGHvIW21fFPs7RF5nu8WxNIO2oEwcTbe2LXO4WlMT0VBXAZhiAMlLLk 7OO8gr7z obXhi5dHIfwe92RpgOzNtgl6bu+yus3FZFIPHn8XiybrTOIkD1sB6gkWcICn7Eop3+UQFUsfNGrSVtAEjCe3NpC8xY7HCTJx24L7k6sUQSn58MPImfhP2QvFAnGzfo/kE2TuHHp6MQmcP0iqJLmuDVSnhI5MMcHweCvM5xCjfAu4vKRRnGmRR94WVB5Ym56KTT54GDvLPCup49byo+cnBfqdEc23S05uXRYdYDt4fcxhoGRBpa5VwUhiECdo9+Rvlpcb1TIMLSDlzrnuNFSV7dL+Mn4pAGxXqcjsMUVE15jd7eui6tskw1Ug2XI2sfoKjuIHdflLpRCfrp5Fif29c7MQTMDvGQ15Jf0EUll4pG5O/ZtSFf7MuZ06N3PtLOZ8lSLhAS/b/tINz9cFfNDkqxL/o3BO06/NU1r3lsaXzxsBPKZu+aL0cvAJLrXlRfzF5LJ+ixgwujOFQdzIgbBMFOtMGyWLJRnwdtFNbgEy9Q9/koGgiQj+c51wxnqYRm/WB4gWam2hzwnvswJo2L/5PY+ePkb6Ti6+MZT+pRY1NSCeJGqUYw3tm08NHBMwHXXL0pjSRVYyBlmik8///t2p/6t3n8MXWBorUVmBrFK5lXmwr7+JV328iSINYMUOqU+FI8/c4Z/bAfrT8+iEuKu7QOt6DsoEYYWKnNbe5qSPze7xFUN/zYeCXJoOzpY860jUNiYGjYoh4z1XRCP0xc3fDtIAJy081CFj99bzixc77qxGDkU09DOX2qvD+oRGaeqgLaOL+qanOCKBMSIkly4Hucc4JzkDjiPJ2NkAcbn/Og0HjDe0uzdULTMApiQDnejpU+JpNto7ZQqerbfN9uvW8rgY42KA8UdAEkBW3HSNh/y5n7Nf+od/0h0L3+S10sYskDY9kiUx1CnBw+F4Kz5xKkJwnsb8o0Uq85Njh 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: List-Subscribe: List-Unsubscribe: >-----Original Message----- >From: Fan Ni >Sent: 29 July 2024 23:19 >To: Shiju Jose >Cc: linux-edac@vger.kernel.org; linux-cxl@vger.kernel.org; linux- >acpi@vger.kernel.org; linux-mm@kvack.org; linux-kernel@vger.kernel.org; >bp@alien8.de; tony.luck@intel.com; rafael@kernel.org; lenb@kernel.org; >mchehab@kernel.org; dan.j.williams@intel.com; dave@stgolabs.net; Jonathan >Cameron ; dave.jiang@intel.com; >alison.schofield@intel.com; vishal.l.verma@intel.com; ira.weiny@intel.com; >david@redhat.com; Vilas.Sridharan@amd.com; leo.duran@amd.com; >Yazen.Ghannam@amd.com; rientjes@google.com; jiaqiyan@google.com; >Jon.Grimm@amd.com; dave.hansen@linux.intel.com; >naoya.horiguchi@nec.com; james.morse@arm.com; jthoughton@google.com; >somasundaram.a@hpe.com; erdemaktas@google.com; pgonda@google.com; >duenwen@google.com; mike.malvestuto@intel.com; gthelen@google.com; >wschwartz@amperecomputing.com; dferguson@amperecomputing.com; >wbs@os.amperecomputing.com; nifan.cxl@gmail.com; tanxiaofei >; Zengtao (B) ; Roberto >Sassu ; kangkang.shen@futurewei.com; >wanghuiqiang ; Linuxarm > >Subject: Re: [PATCH v10 11/11] ras: scrub: ACPI RAS2: Add memory ACPI RAS2 >driver > >On Fri, Jul 26, 2024 at 05:05:55PM +0100, shiju.jose@huawei.com wrote: >> From: Shiju Jose >> >> Memory ACPI RAS2 driver binds to the platform device add by the >s/add/added/ >> ACPI RAS2 table parser. >> >> Driver uses a PCC subspace for communicating with the ACPI compliant >> platform to provide control of memory scrub parameters to the >> userspace via the edac scrub. >> >> Get the scrub attr descriptors from the EDAC scrub and register with >> EDAC RAS feature driver to expose sysfs scrub control attributes to the >userspace. >> For example scrub control for the RAS2 memory device is exposed in >> /sys/bus/edac/devices/acpi_ras2_mem0/scrub/ >> >> Co-developed-by: Jonathan Cameron >> Signed-off-by: Jonathan Cameron >> Signed-off-by: Shiju Jose >> --- >> Documentation/scrub/edac-scrub.rst | 41 +++ >> drivers/ras/Kconfig | 10 + >> drivers/ras/Makefile | 1 + >> drivers/ras/acpi_ras2.c | 415 +++++++++++++++++++++++++++++ >> 4 files changed, 467 insertions(+) >> create mode 100644 drivers/ras/acpi_ras2.c >> >> diff --git a/Documentation/scrub/edac-scrub.rst >> b/Documentation/scrub/edac-scrub.rst >> index 7815d674f496..348f98091ac1 100644 >> --- a/Documentation/scrub/edac-scrub.rst >> +++ b/Documentation/scrub/edac-scrub.rst >> @@ -72,3 +72,44 @@ root@localhost:~# cat >> /sys/bus/edac/devices/cxl_region0/scrub/enable_background >> root@localhost:~# echo 0 > >> /sys/bus/edac/devices/cxl_region0/scrub/enable_background >> root@localhost:~# cat >> /sys/bus/edac/devices/cxl_region0/scrub/enable_background >> 0 >> + >> +2. RAS2 >> +2.1 On demand scrubbing for a specific memory region. >> +root@localhost:~# echo 0x120000 > >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/addr_range_base >> +root@localhost:~# echo 0x150000 > >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/addr_range_size >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/min_cycle_duration >> +1 >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/max_cycle_duration >> +24 >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/current_cycle_duration >> +10 >> +root@localhost:~# echo 15 > >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/current_cycle_duration >> +root@localhost:~# echo 1 > >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/enable_on_demand >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/enable_on_demand >> +1 >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/current_cycle_duration >> +15 >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/addr_range_base >> +0x120000 >> +root@localhost:~# cat >> +//sys/bus/edac/devices/acpi_ras2_mem0/scrub/addr_range_size >> +0x150000 >> +root@localhost:~# echo 0 > >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/enable_on_demand >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/enable_on_demand >> +0 >> + >> +2.2 Background scrubbing the entire memory root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/min_cycle_duration >> +1 >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/max_cycle_duration >> +24 >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/current_cycle_duration >> +10 >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/enable_background >> +0 >> +root@localhost:~# echo 3 > >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/current_cycle_duration >> +root@localhost:~# echo 1 > >> +/sys/bus/edac/devices/acpi_ras2_mem0/enable_background >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/enable_background >> +1 >> +root@localhost:~# cat >> +/sys/bus/edac/devices/acpi_ras2_mem0/scrub/current_cycle_duration >> +3 >> +root@localhost:~# echo 0 > >> +/sys/bus/edac/devices/acpi_ras2_mem0/enable_background >> diff --git a/drivers/ras/Kconfig b/drivers/ras/Kconfig index >> fc4f4bb94a4c..a2635017d80d 100644 >> --- a/drivers/ras/Kconfig >> +++ b/drivers/ras/Kconfig >> @@ -46,4 +46,14 @@ config RAS_FMPM >> Memory will be retired during boot time and run time depending on >> platform-specific policies. >> >> +config MEM_ACPI_RAS2 >> + tristate "Memory ACPI RAS2 driver" >> + depends on ACPI_RAS2 >> + depends on EDAC >> + help >> + The driver binds to the platform device added by the ACPI RAS2 >> + table parser. Use a PCC channel subspace for communicating with >> + the ACPI compliant platform to provide control of memory scrub >> + parameters to the user via the edac scrub. >> + >> endif >> diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile index >> 11f95d59d397..a0e6e903d6b0 100644 >> --- a/drivers/ras/Makefile >> +++ b/drivers/ras/Makefile >> @@ -2,6 +2,7 @@ >> obj-$(CONFIG_RAS) +=3D ras.o >> obj-$(CONFIG_DEBUG_FS) +=3D debugfs.o >> obj-$(CONFIG_RAS_CEC) +=3D cec.o >> +obj-$(CONFIG_MEM_ACPI_RAS2) +=3D acpi_ras2.o >> >> obj-$(CONFIG_RAS_FMPM) +=3D amd/fmpm.o >> obj-y +=3D amd/atl/ >> diff --git a/drivers/ras/acpi_ras2.c b/drivers/ras/acpi_ras2.c new >> file mode 100644 index 000000000000..b2381d5b37d0 >> --- /dev/null >> +++ b/drivers/ras/acpi_ras2.c >> @@ -0,0 +1,415 @@ >> +// SPDX-License-Identifier: GPL-2.0-or-later >> +/* >> + * ACPI RAS2 memory driver >> + * >> + * Copyright (c) 2024 HiSilicon Limited. >> + * >> + */ >> + >> +#define pr_fmt(fmt) "MEMORY ACPI RAS2: " fmt >> + >> +#include >> +#include >> +#include >> + >> +#define RAS2_DEV_NUM_RAS_FEATURES 1 >> + >> +#define RAS2_SUPPORT_HW_PARTOL_SCRUB BIT(0) >> +#define RAS2_TYPE_PATROL_SCRUB 0x0000 >> + >> +#define RAS2_GET_PATROL_PARAMETERS 0x01 >> +#define RAS2_START_PATROL_SCRUBBER 0x02 >> +#define RAS2_STOP_PATROL_SCRUBBER 0x03 >> + >> +#define RAS2_PATROL_SCRUB_SCHRS_IN_MASK GENMASK(15, 8) >> +#define RAS2_PATROL_SCRUB_EN_BACKGROUND BIT(0) >> +#define RAS2_PATROL_SCRUB_SCHRS_OUT_MASK GENMASK(7, 0) >> +#define RAS2_PATROL_SCRUB_MIN_SCHRS_OUT_MASK GENMASK(15, >8) >> +#define RAS2_PATROL_SCRUB_MAX_SCHRS_OUT_MASK GENMASK(23, >16) >> +#define RAS2_PATROL_SCRUB_FLAG_SCRUBBER_RUNNING BIT(0) >> + >> +#define RAS2_SCRUB_NAME_LEN 128 >> + >> +struct acpi_ras2_ps_shared_mem { >> + struct acpi_ras2_shared_memory common; >> + struct acpi_ras2_patrol_scrub_parameter params; }; >> + >> +static int ras2_is_patrol_scrub_support(struct ras2_scrub_ctx >> +*ras2_ctx) { >> + struct acpi_ras2_shared_memory __iomem *common =3D (void *) >> + ras2_ctx->pcc_subspace->pcc_comm_addr; >> + >> + guard(mutex)(&ras2_ctx->lock); >> + common->set_capabilities[0] =3D 0; >> + >> + return common->features[0] & RAS2_SUPPORT_HW_PARTOL_SCRUB; } >> + >> +static int ras2_update_patrol_scrub_params_cache(struct >> +ras2_scrub_ctx *ras2_ctx) { >> + struct acpi_ras2_ps_shared_mem __iomem *ps_sm =3D (void *) >> + ras2_ctx->pcc_subspace- >>pcc_comm_addr; >> + int ret; >> + >> + ps_sm->common.set_capabilities[0] =3D >RAS2_SUPPORT_HW_PARTOL_SCRUB; >> + ps_sm->params.patrol_scrub_command =3D >RAS2_GET_PATROL_PARAMETERS; >> + >> + ret =3D ras2_send_pcc_cmd(ras2_ctx, RAS2_PCC_CMD_EXEC); >> + if (ret) { >> + dev_err(ras2_ctx->dev, "failed to read parameters\n"); >> + return ret; >> + } >> + >> + ras2_ctx->min_scrub_cycle =3D >FIELD_GET(RAS2_PATROL_SCRUB_MIN_SCHRS_OUT_MASK, >> + ps_sm->params.scrub_params_out); >> + ras2_ctx->max_scrub_cycle =3D >FIELD_GET(RAS2_PATROL_SCRUB_MAX_SCHRS_OUT_MASK, >> + ps_sm->params.scrub_params_out); >> + if (!ras2_ctx->bg) { >> + ras2_ctx->base =3D ps_sm->params.actual_address_range[0]; >> + ras2_ctx->size =3D ps_sm->params.actual_address_range[1]; >> + } >> + ras2_ctx->scrub_cycle_secs =3D >FIELD_GET(RAS2_PATROL_SCRUB_SCHRS_OUT_MASK, >> + ps_sm- >>params.scrub_params_out); >> + >> + return 0; >> +} >> + >> +/* Context - lock must be held */ >> +static int ras2_get_patrol_scrub_running(struct ras2_scrub_ctx *ras2_ct= x, >> + bool *running) >> +{ >> + struct acpi_ras2_ps_shared_mem __iomem *ps_sm =3D (void *) >> + ras2_ctx->pcc_subspace- >>pcc_comm_addr; >> + int ret; >> + >> + ps_sm->common.set_capabilities[0] =3D >RAS2_SUPPORT_HW_PARTOL_SCRUB; >> + ps_sm->params.patrol_scrub_command =3D >RAS2_GET_PATROL_PARAMETERS; >> + >> + ret =3D ras2_send_pcc_cmd(ras2_ctx, RAS2_PCC_CMD_EXEC); >> + if (ret) { >> + dev_err(ras2_ctx->dev, "failed to read parameters\n"); >> + return ret; >> + } >> + >> + *running =3D ps_sm->params.flags & >> +RAS2_PATROL_SCRUB_FLAG_SCRUBBER_RUNNING; >> + >> + return 0; >> +} >> + >> +static int ras2_hw_scrub_read_min_scrub_cycle(struct device *dev, void >*drv_data, >> + u32 *min) >> +{ >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + >> + *min =3D ras2_ctx->min_scrub_cycle; >> + >> + return 0; >> +} >> + >> +static int ras2_hw_scrub_read_max_scrub_cycle(struct device *dev, void >*drv_data, >> + u32 *max) >> +{ >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + >> + *max =3D ras2_ctx->max_scrub_cycle; >> + >> + return 0; >> +} >> + >> +static int ras2_hw_scrub_cycle_read(struct device *dev, void *drv_data, >> + u32 *scrub_cycle_secs) >> +{ >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + >> + *scrub_cycle_secs =3D ras2_ctx->scrub_cycle_secs; >> + >> + return 0; >> +} >> + >> +static int ras2_hw_scrub_cycle_write(struct device *dev, void *drv_data= , >> + u32 scrub_cycle_secs) >> +{ >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + bool running; >> + int ret; >> + >> + guard(mutex)(&ras2_ctx->lock); >> + ret =3D ras2_get_patrol_scrub_running(ras2_ctx, &running); >> + if (ret) >> + return ret; >> + >> + if (running) >> + return -EBUSY; >> + >> + if (scrub_cycle_secs < ras2_ctx->min_scrub_cycle || >> + scrub_cycle_secs > ras2_ctx->max_scrub_cycle) >> + return -EINVAL; >> + >> + ras2_ctx->scrub_cycle_secs =3D scrub_cycle_secs; >> + >> + return 0; >> +} >> + >> +static int ras2_hw_scrub_read_range(struct device *dev, void >> +*drv_data, u64 *base, u64 *size) { >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + >> + /* >> + * When BG scrubbing is enabled the actual address range is not valid. >> + * Return -EBUSY now unless findout a method to retrieve actual full P= A >range. >> + */ >> + if (ras2_ctx->bg) >> + return -EBUSY; >> + >> + *base =3D ras2_ctx->base; >> + *size =3D ras2_ctx->size; >> + >> + return 0; >> +} >> + >> +static int ras2_hw_scrub_write_range(struct device *dev, void >> +*drv_data, u64 base, u64 size) { >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + bool running; >> + int ret; >> + >> + guard(mutex)(&ras2_ctx->lock); >> + ret =3D ras2_get_patrol_scrub_running(ras2_ctx, &running); >> + if (ret) >> + return ret; >> + >> + if (running) >> + return -EBUSY; >> + >> + if (!base || !size) { >> + dev_warn(dev, "%s: Invalid address range, base=3D0x%llx >size=3D0x%llx\n", >> + __func__, base, size); >> + return -EINVAL; >> + } >> + >> + ras2_ctx->base =3D base; >> + ras2_ctx->size =3D size; >> + >> + return 0; >> +} >> + >> +static int ras2_hw_scrub_set_enabled_bg(struct device *dev, void >> +*drv_data, bool enable) { >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + struct acpi_ras2_ps_shared_mem __iomem *ps_sm =3D (void *) >> + ras2_ctx->pcc_subspace- >>pcc_comm_addr; >> + bool enabled; >> + int ret; >> + >> + guard(mutex)(&ras2_ctx->lock); >> + ps_sm->common.set_capabilities[0] =3D >RAS2_SUPPORT_HW_PARTOL_SCRUB; >> + ret =3D ras2_get_patrol_scrub_running(ras2_ctx, &enabled); >We have a passed-in argument "enable", we have another local variable >"enabled", will "running" be more accurate instead of "enabled"? The same = as in >ras2_hw_scrub_set_enabled_od() Sure. > >Fan >> + if (ret) >> + return ret; >> + if (enable) { >> + if (ras2_ctx->bg || enabled) >> + return -EBUSY; >> + ps_sm->params.requested_address_range[0] =3D 0; >> + ps_sm->params.requested_address_range[1] =3D 0; >> + ps_sm->params.scrub_params_in &=3D >~RAS2_PATROL_SCRUB_SCHRS_IN_MASK; >> + ps_sm->params.scrub_params_in |=3D >FIELD_PREP(RAS2_PATROL_SCRUB_SCHRS_IN_MASK, >> + ras2_ctx- >>scrub_cycle_secs); >> + ps_sm->params.patrol_scrub_command =3D >RAS2_START_PATROL_SCRUBBER; >> + } else { >> + if (!ras2_ctx->bg) >> + return -EPERM; >> + if (!ras2_ctx->bg && enabled) >> + return -EBUSY; >> + ps_sm->params.patrol_scrub_command =3D >RAS2_STOP_PATROL_SCRUBBER; >> + } >> + ps_sm->params.scrub_params_in &=3D >~RAS2_PATROL_SCRUB_EN_BACKGROUND; >> + ps_sm->params.scrub_params_in |=3D >FIELD_PREP(RAS2_PATROL_SCRUB_EN_BACKGROUND, >> + enable); >> + ret =3D ras2_send_pcc_cmd(ras2_ctx, RAS2_PCC_CMD_EXEC); >> + if (ret) { >> + dev_err(ras2_ctx->dev, "%s: failed to enable(%d) background >scrubbing\n", >> + __func__, enable); > >Similar suggestion as below. Will do. > >> + return ret; >> + } >> + if (enable) { >> + ras2_ctx->bg =3D true; >> + /* Update the cache to account for rounding of supplied >parameters and similar */ >> + ret =3D ras2_update_patrol_scrub_params_cache(ras2_ctx); >> + } else { >> + ret =3D ras2_update_patrol_scrub_params_cache(ras2_ctx); >> + ras2_ctx->bg =3D false; >> + } >> + >> + return ret; >> +} >> + >> +static int ras2_hw_scrub_get_enabled_bg(struct device *dev, void >> +*drv_data, bool *enabled) { >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + >> + *enabled =3D ras2_ctx->bg; >> + >> + return 0; >> +} >> + >> +static int ras2_hw_scrub_set_enabled_od(struct device *dev, void >> +*drv_data, bool enable) { >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + struct acpi_ras2_ps_shared_mem __iomem *ps_sm =3D (void *) >> + ras2_ctx->pcc_subspace- >>pcc_comm_addr; >> + bool enabled; >> + int ret; >> + >> + guard(mutex)(&ras2_ctx->lock); >> + ps_sm->common.set_capabilities[0] =3D >RAS2_SUPPORT_HW_PARTOL_SCRUB; >> + if (ras2_ctx->bg) >> + return -EBUSY; >> + ret =3D ras2_get_patrol_scrub_running(ras2_ctx, &enabled); >> + if (ret) >> + return ret; >> + if (enable) { >> + if (!ras2_ctx->base || !ras2_ctx->size) { >> + dev_warn(ras2_ctx->dev, >> + "%s: Invalid address range, base=3D0x%llx " >> + "size=3D0x%llx\n", __func__, >> + ras2_ctx->base, ras2_ctx->size); >> + return -ERANGE; >> + } >> + if (enabled) >> + return -EBUSY; >> + ps_sm->params.scrub_params_in &=3D >~RAS2_PATROL_SCRUB_SCHRS_IN_MASK; >> + ps_sm->params.scrub_params_in |=3D >FIELD_PREP(RAS2_PATROL_SCRUB_SCHRS_IN_MASK, >> + ras2_ctx- >>scrub_cycle_secs); >> + ps_sm->params.requested_address_range[0] =3D ras2_ctx->base; >> + ps_sm->params.requested_address_range[1] =3D ras2_ctx->size; >> + ps_sm->params.scrub_params_in &=3D >~RAS2_PATROL_SCRUB_EN_BACKGROUND; >> + ps_sm->params.patrol_scrub_command =3D >RAS2_START_PATROL_SCRUBBER; >> + } else { >> + if (!enabled) >> + return 0; >> + ps_sm->params.patrol_scrub_command =3D >RAS2_STOP_PATROL_SCRUBBER; >> + } >> + >> + ret =3D ras2_send_pcc_cmd(ras2_ctx, RAS2_PCC_CMD_EXEC); >> + if (ret) { >> + dev_err(ras2_ctx->dev, "failed to enable(%d) the demand >> +scrubbing\n", enable); >Can we improve the messaging as below to make it clearer? > dev_err(ras2_ctx->dev, "failed to %s the demand scrubbing\n", enab= le ? >"enable":"disable"); Will do. > >Fan >> + return ret; >> + } >> + >> + return ras2_update_patrol_scrub_params_cache(ras2_ctx); >> +} >> + >> +static int ras2_hw_scrub_get_enabled_od(struct device *dev, void >> +*drv_data, bool *enabled) { >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + >> + guard(mutex)(&ras2_ctx->lock); >> + if (ras2_ctx->bg) { >> + *enabled =3D false; >> + return 0; >> + } >> + >> + return ras2_get_patrol_scrub_running(ras2_ctx, enabled); } >> + >> +static int ras2_hw_scrub_get_name(struct device *dev, void *drv_data, >> +char *name) { >> + struct ras2_scrub_ctx *ras2_ctx =3D drv_data; >> + >> + return sysfs_emit(name, "acpi_ras2_mem%d_scrub\n", ras2_ctx->id); } >> + >> +static const struct edac_scrub_ops ras2_scrub_ops =3D { >> + .read_range =3D ras2_hw_scrub_read_range, >> + .write_range =3D ras2_hw_scrub_write_range, >> + .get_enabled_bg =3D ras2_hw_scrub_get_enabled_bg, >> + .set_enabled_bg =3D ras2_hw_scrub_set_enabled_bg, >> + .get_enabled_od =3D ras2_hw_scrub_get_enabled_od, >> + .set_enabled_od =3D ras2_hw_scrub_set_enabled_od, >> + .get_name =3D ras2_hw_scrub_get_name, >> + .min_cycle_read =3D ras2_hw_scrub_read_min_scrub_cycle, >> + .max_cycle_read =3D ras2_hw_scrub_read_max_scrub_cycle, >> + .cycle_duration_read =3D ras2_hw_scrub_cycle_read, >> + .cycle_duration_write =3D ras2_hw_scrub_cycle_write, }; >> + >> +static DEFINE_IDA(ras2_ida); >> + >> +static void ida_release(void *ctx) >> +{ >> + struct ras2_scrub_ctx *ras2_ctx =3D ctx; >> + >> + ida_free(&ras2_ida, ras2_ctx->id); >> +} >> + >> +static int ras2_probe(struct platform_device *pdev) { >> + struct edac_ras_feature ras_features[RAS2_DEV_NUM_RAS_FEATURES]; >> + char scrub_name[RAS2_SCRUB_NAME_LEN]; >> + struct ras2_scrub_ctx *ras2_ctx; >> + int num_ras_features =3D 0; >> + int ret, id; >> + >> + /* RAS2 PCC Channel and Scrub specific context */ >> + ras2_ctx =3D devm_kzalloc(&pdev->dev, sizeof(*ras2_ctx), GFP_KERNEL); >> + if (!ras2_ctx) >> + return -ENOMEM; >> + >> + ras2_ctx->dev =3D &pdev->dev; >> + mutex_init(&ras2_ctx->lock); >> + >> + ret =3D devm_ras2_register_pcc_channel(&pdev->dev, ras2_ctx, >> + *((int *)dev_get_platdata(&pdev- >>dev))); >> + if (ret < 0) { >> + dev_dbg(ras2_ctx->dev, >> + "failed to register pcc channel ret=3D%d\n", ret); >> + return ret; >> + } >> + if (!ras2_is_patrol_scrub_support(ras2_ctx)) >> + return -EOPNOTSUPP; >> + >> + ret =3D ras2_update_patrol_scrub_params_cache(ras2_ctx); >> + if (ret) >> + return ret; >> + >> + id =3D ida_alloc(&ras2_ida, GFP_KERNEL); >> + if (id < 0) >> + return id; >> + >> + ras2_ctx->id =3D id; >> + >> + ret =3D devm_add_action_or_reset(&pdev->dev, ida_release, ras2_ctx); >> + if (ret < 0) >> + return ret; >> + >> + snprintf(scrub_name, sizeof(scrub_name), "acpi_ras2_mem%d", >> + ras2_ctx->id); >> + >> + ras_features[num_ras_features].feat =3D RAS_FEAT_SCRUB; >> + ras_features[num_ras_features].scrub_ops =3D &ras2_scrub_ops; >> + ras_features[num_ras_features].scrub_ctx =3D ras2_ctx; >> + num_ras_features++; >> + >> + return edac_ras_dev_register(&pdev->dev, scrub_name, NULL, >> + num_ras_features, ras_features); } >> + >> +static const struct platform_device_id ras2_id_table[] =3D { >> + { .name =3D "acpi_ras2", }, >> + { } >> +}; >> +MODULE_DEVICE_TABLE(platform, ras2_id_table); >> + >> +static struct platform_driver ras2_driver =3D { >> + .probe =3D ras2_probe, >> + .driver =3D { >> + .name =3D "acpi_ras2", >> + }, >> + .id_table =3D ras2_id_table, >> +}; >> +module_driver(ras2_driver, platform_driver_register, >> +platform_driver_unregister); >> + >> +MODULE_IMPORT_NS(ACPI_RAS2); >> +MODULE_DESCRIPTION("ACPI RAS2 memory driver"); >MODULE_LICENSE("GPL"); >> -- >> 2.34.1 >> Thanks, Shiju