Received: by 2002:a05:7412:419a:b0:f3:1519:9f41 with SMTP id i26csp506698rdh; Thu, 23 Nov 2023 09:44:55 -0800 (PST) X-Google-Smtp-Source: AGHT+IFV8oI8enp3LY58A/5jpR8GnuYDLdc/q/ohPGL6iLktsG3lIxk8RaAazW1Cv4V31QcHWLFq X-Received: by 2002:a17:902:be12:b0:1c3:1f0c:fb82 with SMTP id r18-20020a170902be1200b001c31f0cfb82mr184242pls.41.1700761495217; Thu, 23 Nov 2023 09:44:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700761495; cv=none; d=google.com; s=arc-20160816; b=qq2mIUNO6/rST1SdzB9L6sct0HuzXAWyCNq6bLNj11f3Ao5S4b5MFPeV/BFr+nwe/6 K3nRDfb9CWRgPNNuwY5cL3qUjPb6IsEyymef4oU+n0U/pRNxO5APkPAfyhXiOtIfVS82 neWBYkh2E6bHbSsRmNq1IltkUGdimEThZ4OeePrDT0HQqs5uMHv460H4ACdaBGYeNkX8 bSkZD/ybuqwqBbd8TTNGbbtSz6uRSXG7AqrAT40rSIEJHkJArteeuGljWR5xTsHGA7yp rx0LLwX1E4IU6menfwsGPlpgBvaCrYy5hc0Lz8SLdvr9hK7s33rme/zk5VINBTaQldmv HdnQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=h39DNW7irXEtv45GOKYPqSvCdSod3xDlDMT3ZC3K6EU=; fh=qThSIRufdAcTXHIWmo+/3LGhqx2rE7BOIGxpM+Tyyp8=; b=TDAi89CbZ1dvm0Nrv+Fu5sVCMCcYSl0EhNgFAH8gG7vf5fekqwIE0Dob0sci/HsCwd vSuCDhRQYlK+XtC1irlh4aiN35H4Jo8Veq+qXs9oQLTy76K2I/boBh+W/3BU8+zFtPRl 74CgwcAEI9uZha3V0V1BT3GbZzEdkm7oqHc0R99Z+b+59fSDpDrZLCq5qKznWUr/jMtw sQ7GmFvTZeqq1KpCU8v8JNV31CDbP2ODh6OxtEvZ79mIasE86Z+sEGz1kRoKRYYqTmrF 5FvcqK5yufgZQLESorv5G+/t48TU52Y3wZ91YQZKqcvXilp5abmCPbPDEcRo3/e7nCEF g2Ug== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Return-Path: Received: from snail.vger.email (snail.vger.email. [2620:137:e000::3:7]) by mx.google.com with ESMTPS id n12-20020a170902d2cc00b001cc50c56980si1598341plc.411.2023.11.23.09.44.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Nov 2023 09:44:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) client-ip=2620:137:e000::3:7; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 20D8482D1857; Thu, 23 Nov 2023 09:44:54 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346038AbjKWRog (ORCPT + 99 others); Thu, 23 Nov 2023 12:44:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36360 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1345782AbjKWRoJ (ORCPT ); Thu, 23 Nov 2023 12:44:09 -0500 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89D1610E7; Thu, 23 Nov 2023 09:44:14 -0800 (PST) Received: from lhrpeml500006.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4Sblk31pMTz6K5pv; Fri, 24 Nov 2023 01:39:55 +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.35; Thu, 23 Nov 2023 17:44:11 +0000 From: To: , , , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v3 09/11] cxl/memscrub: Register CXL device DDR5 ECS with scrub configure driver Date: Fri, 24 Nov 2023 01:43:52 +0800 Message-ID: <20231123174355.1176-10-shiju.jose@huawei.com> X-Mailer: git-send-email 2.35.1.windows.2 In-Reply-To: <20231123174355.1176-1-shiju.jose@huawei.com> References: <20231123174355.1176-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.122.247.234] X-ClientProxiedBy: lhrpeml100003.china.huawei.com (7.191.160.210) To lhrpeml500006.china.huawei.com (7.191.161.198) X-CFilter-Loop: Reflected X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_BLOCKED,RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Thu, 23 Nov 2023 09:44:54 -0800 (PST) From: Shiju Jose Register with the scrub configure driver to expose the sysfs attributes to the user for configuring the CXL memory device's ECS feature. Add the callback functions to support configuring the CXL memory device ECS. Signed-off-by: Shiju Jose --- drivers/cxl/core/memscrub.c | 239 +++++++++++++++++++++++++++++++++++- 1 file changed, 236 insertions(+), 3 deletions(-) diff --git a/drivers/cxl/core/memscrub.c b/drivers/cxl/core/memscrub.c index c09f9fa5044a..d4227ecb91d7 100644 --- a/drivers/cxl/core/memscrub.c +++ b/drivers/cxl/core/memscrub.c @@ -460,6 +460,11 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_patrol_scrub_init, CXL); #define CXL_MEMDEV_ECS_GET_FEAT_VERSION 0x01 #define CXL_MEMDEV_ECS_SET_FEAT_VERSION 0x01 +#define CXL_DDR5_ECS "cxl_ecs" + +/* The default number of regions for CXL memory device ECS */ +#define CXL_MEMDEV_ECS_NUM_REGIONS 1 + static const uuid_t cxl_ecs_uuid = UUID_INIT(0xe5b13f22, 0x2328, 0x4a14, 0xb8, 0xba, 0xb9, 0x69, 0x1e, \ 0x89, 0x33, 0x86); @@ -577,9 +582,8 @@ static int cxl_mem_ecs_get_attrbs(struct device *dev, int fru_id, return 0; } -static int __maybe_unused -cxl_mem_ecs_set_attrbs(struct device *dev, int fru_id, - struct cxl_memdev_ecs_params *params, u8 param_type) +static int cxl_mem_ecs_set_attrbs(struct device *dev, int fru_id, + struct cxl_memdev_ecs_params *params, u8 param_type) { struct cxl_memdev_ecs_feat_read_attrbs *rd_attrbs __free(kvfree) = NULL; struct cxl_memdev_ecs_set_feat_pi *set_pi __free(kvfree) = NULL; @@ -726,10 +730,231 @@ cxl_mem_ecs_set_attrbs(struct device *dev, int fru_id, return 0; } +static int cxl_mem_ecs_log_entry_type_write(struct device *dev, int region_id, long val) +{ + struct cxl_memdev_ecs_params params; + int ret; + + params.log_entry_type = val; + ret = cxl_mem_ecs_set_attrbs(dev, region_id, ¶ms, + CXL_MEMDEV_ECS_PARAM_LOG_ENTRY_TYPE); + if (ret) { + dev_err(dev->parent, "Set CXL ECS params for log entry type fail ret=%d\n", + ret); + return ret; + } + + return 0; +} + +static int cxl_mem_ecs_threshold_write(struct device *dev, int region_id, long val) +{ + struct cxl_memdev_ecs_params params; + int ret; + + params.threshold = val; + ret = cxl_mem_ecs_set_attrbs(dev, region_id, ¶ms, + CXL_MEMDEV_ECS_PARAM_THRESHOLD); + if (ret) { + dev_err(dev->parent, "Set CXL ECS params for threshold fail ret=%d\n", + ret); + return ret; + } + + return 0; +} + +static int cxl_mem_ecs_mode_write(struct device *dev, int region_id, long val) +{ + struct cxl_memdev_ecs_params params; + int ret; + + params.mode = val; + ret = cxl_mem_ecs_set_attrbs(dev, region_id, ¶ms, + CXL_MEMDEV_ECS_PARAM_MODE); + if (ret) { + dev_err(dev->parent, "Set CXL ECS params for mode fail ret=%d\n", + ret); + return ret; + } + + return 0; +} + +static int cxl_mem_ecs_reset_counter_write(struct device *dev, int region_id, long val) +{ + struct cxl_memdev_ecs_params params; + int ret; + + params.reset_counter = val; + ret = cxl_mem_ecs_set_attrbs(dev, region_id, ¶ms, + CXL_MEMDEV_ECS_PARAM_RESET_COUNTER); + if (ret) { + dev_err(dev->parent, "Set CXL ECS params for reset ECC counter fail ret=%d\n", + ret); + return ret; + } + + return 0; +} + +/** + * cxl_mem_ecs_is_visible() - Callback to return attribute visibility + * @drv_data: Pointer to driver-private data structure passed + * as argument to devm_scrub_device_register(). + * @attr: Scrub attribute + * @region_id: ID of the memory region + * + * Returns: 0 on success, an error otherwise + */ +static umode_t cxl_mem_ecs_is_visible(const void *drv_data, u32 attr, int region_id) +{ + switch (attr) { + case scrub_reset_counter: + return 0200; + case scrub_ecs_log_entry_type_per_dram: + case scrub_ecs_log_entry_type_per_memory_media: + case scrub_mode_counts_rows: + case scrub_mode_counts_codewords: + case scrub_threshold_available: + return 0444; + case scrub_ecs_log_entry_type: + case scrub_mode: + case scrub_threshold: + return 0644; + default: + return 0; + } +} + +/** + * cxl_mem_ecs_read() - Read callback for data attributes + * @dev: Pointer to scrub device + * @attr: Scrub attribute + * @region_id: ID of the memory region + * @val: Pointer to the returned data + * + * Returns: 0 on success, an error otherwise + */ +static int cxl_mem_ecs_read(struct device *dev, u32 attr, int region_id, u64 *val) +{ + struct cxl_memdev_ecs_params params; + int ret; + + if (attr == scrub_ecs_log_entry_type || + attr == scrub_ecs_log_entry_type_per_dram || + attr == scrub_ecs_log_entry_type_per_memory_media || + attr == scrub_mode || + attr == scrub_mode_counts_rows || + attr == scrub_mode_counts_codewords || + attr == scrub_threshold) { + ret = cxl_mem_ecs_get_attrbs(dev, region_id, ¶ms); + if (ret) { + dev_err(dev->parent, "Get CXL ECS params fail ret=%d\n", ret); + return ret; + } + } + + switch (attr) { + case scrub_ecs_log_entry_type: + *val = params.log_entry_type; + break; + case scrub_ecs_log_entry_type_per_dram: + if (params.log_entry_type == ECS_LOG_ENTRY_TYPE_DRAM) + *val = 1; + else + *val = 0; + break; + case scrub_ecs_log_entry_type_per_memory_media: + if (params.log_entry_type == ECS_LOG_ENTRY_TYPE_MEM_MEDIA_FRU) + *val = 1; + else + *val = 0; + break; + case scrub_mode: + *val = params.mode; + break; + case scrub_mode_counts_rows: + if (params.mode == ECS_MODE_COUNTS_ROWS) + *val = 1; + else + *val = 0; + break; + case scrub_mode_counts_codewords: + if (params.mode == ECS_MODE_COUNTS_CODEWORDS) + *val = 1; + else + *val = 0; + break; + case scrub_threshold: + *val = params.threshold; + break; + default: + return -ENOTSUPP; + } + + return 0; +} + +/** + * cxl_mem_ecs_write() - Write callback for data attributes + * @dev: Pointer to scrub device + * @attr: Scrub attribute + * @region_id: ID of the memory region + * @val: Value to write + * + * Returns: 0 on success, an error otherwise + */ +static int cxl_mem_ecs_write(struct device *dev, u32 attr, int region_id, u64 val) +{ + switch (attr) { + case scrub_ecs_log_entry_type: + return cxl_mem_ecs_log_entry_type_write(dev, region_id, val); + case scrub_mode: + return cxl_mem_ecs_mode_write(dev, region_id, val); + case scrub_reset_counter: + return cxl_mem_ecs_reset_counter_write(dev, region_id, val); + case scrub_threshold: + return cxl_mem_ecs_threshold_write(dev, region_id, val); + default: + return -ENOTSUPP; + } +} + +/** + * cxl_mem_ecs_read_strings() - Read callback for DDR5 ECS string attributes + * @dev: Pointer to ECS scrub device + * @attr: ECS scrub attribute + * @region_id: ID of the memory media FRU. + * @buf: Pointer to the buffer for copying returned string + * + * Returns: 0 on success, an error otherwise + */ +static int cxl_mem_ecs_read_strings(struct device *dev, u32 attr, + int region_id, char *buf) +{ + + switch (attr) { + case scrub_threshold_available: + return sysfs_emit(buf, "256,1024,4096\n"); + default: + return -ENOTSUPP; + } +} + +static const struct scrub_ops cxl_ecs_ops = { + .is_visible = cxl_mem_ecs_is_visible, + .read = cxl_mem_ecs_read, + .write = cxl_mem_ecs_write, + .read_string = cxl_mem_ecs_read_strings, +}; + int cxl_mem_ddr5_ecs_init(struct cxl_memdev *cxlmd) { + char scrub_name[CXL_MEMDEV_MAX_NAME_LENGTH]; struct cxl_mbox_supp_feat_entry feat_entry; struct cxl_ecs_context *cxl_ecs_ctx; + struct device *cxl_scrub_dev; int nmedia_frus; int ret; @@ -749,6 +974,14 @@ int cxl_mem_ddr5_ecs_init(struct cxl_memdev *cxlmd) cxl_ecs_ctx->nregions = nmedia_frus; cxl_ecs_ctx->get_feat_size = feat_entry.get_feat_size; cxl_ecs_ctx->set_feat_size = feat_entry.set_feat_size; + + snprintf(scrub_name, sizeof(scrub_name), "%s_%s", + CXL_DDR5_ECS, dev_name(&cxlmd->dev)); + cxl_scrub_dev = devm_scrub_device_register(&cxlmd->dev, scrub_name, + cxl_ecs_ctx, &cxl_ecs_ops, + cxl_ecs_ctx->nregions); + if (IS_ERR(cxl_scrub_dev)) + return PTR_ERR(cxl_scrub_dev); } return 0; -- 2.34.1