Received: by 2002:a05:7412:40d:b0:e2:908c:2ebd with SMTP id 13csp277160rdf; Tue, 21 Nov 2023 02:23:47 -0800 (PST) X-Google-Smtp-Source: AGHT+IGZE85KsTnapeVb7rVXMfKKpwB9qLVFDw+VkuL1TUafJgsghHRExu2wj+YCyrY2qHz6wPDZ X-Received: by 2002:a17:902:e9c4:b0:1ce:5853:1ff2 with SMTP id 4-20020a170902e9c400b001ce58531ff2mr10402561plk.11.1700562226930; Tue, 21 Nov 2023 02:23:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700562226; cv=none; d=google.com; s=arc-20160816; b=Ux6oEvu4sYyGYXw7nmHNoT34R1CVS+xV3MtrZa5zSQ0hHB44jl4ZnUDNKyH6f8GTue eIQxFi0zucPbpS9lbuFCjSLAV8tGKDmyiGcorAcbVr8xUsq+y73C7Ru1PZT4/Z1wI7dp Wi6KRIVOmGx6B8lR8ywzX5vHipnJVPyaB1/t2edISbm/hxaXg86pwLrKhjcu+r456KRo vtWloDrxqmz1YgwecBAMSywJfjgnc3nS5M/9v9SNGeh/uCKaXFjRiLP8WwkpwmqrZoVM a4Al9SLavYWbUXLn1jwog3YM/UAhd23Sc7Gd7vdSw34fIejIWDHhBsGqDlQDnOvk0Ag0 L43g== 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=+FYGeUIBrpefIp3NcnlzlXxWTlHC8jpVygzLF1reoVk=; fh=qThSIRufdAcTXHIWmo+/3LGhqx2rE7BOIGxpM+Tyyp8=; b=KmiVinqmlAtZPI5/0jUzihLhJwRc8Fetb0C62DtVbNe/gcHgBKRzzwdpcetq7VHXvZ 8uIsvowa55pyDWCTLup2EJCOOkV3hgs8DmwXXe8cws7r1CAK4IIkRw79ekbwJ20oJNh8 GgMcqDWURQ/2Xp9C8T6riLhBXs+ZdbtwKnQzbY3vEXQBUO0IMC4GsPskQ5iA8CpIiMJF jXaLGnrv7C63e66kagJFPbGUqLsXaa2ujLBQQggnS/bxe7/AC/xaZb0kTUYk6me095Hz UMYwFSudFeYgs3gk0gK3i+JdrJwe/2NFYKbr0RMNWnE8f4jv4XB621wiOUBNILwTgilu 9lcg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 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 fry.vger.email (fry.vger.email. [23.128.96.38]) by mx.google.com with ESMTPS id b13-20020a170902d30d00b001cc43368c9bsi9646848plc.630.2023.11.21.02.23.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Nov 2023 02:23:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) client-ip=23.128.96.38; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 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 fry.vger.email (Postfix) with ESMTP id 405628053CD2; Tue, 21 Nov 2023 02:22:02 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233767AbjKUKUx (ORCPT + 99 others); Tue, 21 Nov 2023 05:20:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60448 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233230AbjKUKUD (ORCPT ); Tue, 21 Nov 2023 05:20:03 -0500 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0068C1732; Tue, 21 Nov 2023 02:19:09 -0800 (PST) Received: from lhrpeml500006.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4SZL0n0nswz6K8tD; Tue, 21 Nov 2023 18:17:45 +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; Tue, 21 Nov 2023 10:19:07 +0000 From: To: , , , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v2 09/10] cxl/memscrub: Register CXL device DDR5 ECS with scrub configure driver Date: Tue, 21 Nov 2023 18:18:42 +0800 Message-ID: <20231121101844.1161-10-shiju.jose@huawei.com> X-Mailer: git-send-email 2.35.1.windows.2 In-Reply-To: <20231121101844.1161-1-shiju.jose@huawei.com> References: <20231121101844.1161-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: lhrpeml100005.china.huawei.com (7.191.160.25) To lhrpeml500006.china.huawei.com (7.191.161.198) X-CFilter-Loop: Reflected X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email 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 (fry.vger.email [0.0.0.0]); Tue, 21 Nov 2023 02:22:02 -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 | 234 ++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/drivers/cxl/core/memscrub.c b/drivers/cxl/core/memscrub.c index 213be4396b98..52fc0af20664 100644 --- a/drivers/cxl/core/memscrub.c +++ b/drivers/cxl/core/memscrub.c @@ -464,6 +464,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); @@ -729,10 +734,231 @@ static int 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; @@ -752,6 +978,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