Received: by 2002:a05:7412:b10a:b0:f3:1519:9f41 with SMTP id az10csp546933rdb; Thu, 30 Nov 2023 11:24:04 -0800 (PST) X-Google-Smtp-Source: AGHT+IGisYZy5cAVVwVQ60iHCa9xbvKWATMRlbXRWg0MpYe+L5Ka9TtPiijxH+4ZfFJyn01JtLgO X-Received: by 2002:a17:902:d50c:b0:1cf:ee3a:238f with SMTP id b12-20020a170902d50c00b001cfee3a238fmr12856082plg.56.1701372244058; Thu, 30 Nov 2023 11:24:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701372244; cv=none; d=google.com; s=arc-20160816; b=pNcabDZjcfM25HSk5v/Oi3LFSxKWfePfHD1k351RyDZ2PcKGypNFjYmcJOA+bpagQy OACryllyM3NxPIp22W/a3lWVdQXBDwaT/wVktFqjEcfU3rwj8tEsDskB+xnhy7eWaAFC PzjiFIGlCt5Z+dr1qlG6GKk5z9GCsZsRSFx7xG02nyw1stzIfYOaxJ0jrxW22Ck3YqrZ zWHrkL1BbfhxUMHJL4s7H03mR9CiYlEe4OpJzU4O0xc+FxoSleaM4Cc7B6aoliJUBr64 QdbiA0FoLLEJUmbHLZZWda77WgqoqUCeQXGHhtjte0r38uqumDGPslQ8kC+6aDuG1KtM L+3Q== 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=xtUkVWQwA06eqJVajSD69sY3fhUalaluBebuFHYBcy0=; fh=qThSIRufdAcTXHIWmo+/3LGhqx2rE7BOIGxpM+Tyyp8=; b=NNGQFaQmcmDgGU36T8AZuO2BjYPlg21F8iDGF7Ne8/MnSFgBUUIQ85w5na+rXqIqmJ zL3p1MZGGC6zr4K5bxQN5SpkZrUdZXyYUM96/+pj+Txiv09+zux6Z5/zrrObUuJEmt0M 7uZAU7K7iIQ70No0Gv4WGOKL5x/jsdK8CGPcMRRPcRVyaVnTpXuMc4WgWPJVe8lNpNEA 48eQj/s9M2Q6eq58waNZQuekXtyiG5NeyWDkLuqFqPuyl7nqzDBdPJWPtWm/9Cc3iIFm XDm0JUHweljFw7H/J8xeGmuecjYhjjEZvN6S0ZjKeNup3LhoZ1rKA6spoIKNoWmquICc 7Zog== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 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. [23.128.96.37]) by mx.google.com with ESMTPS id v1-20020a1709029a0100b001cf5c99a61csi1724072plp.180.2023.11.30.11.24.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Nov 2023 11:24:04 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) client-ip=23.128.96.37; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 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 10587802401B; Thu, 30 Nov 2023 11:24:03 -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 S1376387AbjK3TXs (ORCPT + 99 others); Thu, 30 Nov 2023 14:23:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47828 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376409AbjK3TXb (ORCPT ); Thu, 30 Nov 2023 14:23:31 -0500 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AAD710FA; Thu, 30 Nov 2023 11:23:36 -0800 (PST) Received: from mail.maildlp.com (unknown [172.18.186.216]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4Sh5fY6CBtz6DBCT; Fri, 1 Dec 2023 03:21:57 +0800 (CST) Received: from lhrpeml500006.china.huawei.com (unknown [7.191.161.198]) by mail.maildlp.com (Postfix) with ESMTPS id A61A61402CD; Fri, 1 Dec 2023 03:23:34 +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, 30 Nov 2023 19:23:33 +0000 From: To: , , , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v4 09/11] cxl/memscrub: Register CXL device DDR5 ECS with scrub configure driver Date: Fri, 1 Dec 2023 03:23:11 +0800 Message-ID: <20231130192314.1220-10-shiju.jose@huawei.com> X-Mailer: git-send-email 2.35.1.windows.2 In-Reply-To: <20231130192314.1220-1-shiju.jose@huawei.com> References: <20231130192314.1220-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: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500006.china.huawei.com (7.191.161.198) X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, 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, 30 Nov 2023 11:24:03 -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 4d778ffa3322..f1273615bbdd 100644 --- a/drivers/cxl/core/memscrub.c +++ b/drivers/cxl/core/memscrub.c @@ -473,6 +473,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); @@ -590,9 +595,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; @@ -739,10 +743,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; @@ -762,6 +987,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