From patchwork Fri Aug 12 16:41:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhang Rui X-Patchwork-Id: 12942380 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B83FFC25B0E for ; Fri, 12 Aug 2022 16:38:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232082AbiHLQiO (ORCPT ); Fri, 12 Aug 2022 12:38:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38082 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238656AbiHLQiI (ORCPT ); Fri, 12 Aug 2022 12:38:08 -0400 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D551AABF2A; Fri, 12 Aug 2022 09:38:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1660322286; x=1691858286; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=NUyQpSQ+bGRYNVMYb0DJKJiMv8VBcicLoCZ/INNs+rE=; b=EH+3kezdI0bVzq4z2chqDwwmF3SzvzgjdxFfqxAXmHHEHAI3lQwoMWIZ 9jdEfz69UnKmXrGLr5aiuf9TdgIMDL9n7zc36IXJhuWAH4KsHJh3Fgny3 1kq3qVawFaJKMkrWesf8e80neR50EYiqqNZQUJx47D3AuoQucWMaTb3G4 qFVXoPCgIbTcv2gqL3dl9FVUgdbVZSfIh0YlR0bOpcc0BLpJ3ecqV30ny XfuXxxUc7qsD9fEvaGugBKCpj9HQ87ufkVoxGs37k4lJXJbK+FH3uZ3OZ onkcLg85FEdmKj50BLpdLv6cZWXtQBrpGJueZmRD7WOpjeZlcFyo3p4Uc w==; X-IronPort-AV: E=McAfee;i="6400,9594,10437"; a="377921603" X-IronPort-AV: E=Sophos;i="5.93,233,1654585200"; d="scan'208";a="377921603" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2022 09:38:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,233,1654585200"; d="scan'208";a="782012297" Received: from power-sh.sh.intel.com ([10.239.183.122]) by orsmga005.jf.intel.com with ESMTP; 12 Aug 2022 09:38:03 -0700 From: Zhang Rui To: linux-kernel@vger.kernel.org, x86@kernel.org, linux-hwmon@vger.kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, hpa@zytor.com, corbet@lwn.net, fenghua.yu@intel.com, jdelvare@suse.com, linux@roeck-us.net, len.brown@intel.com, rui.zhang@intel.com Subject: [PATCH 3/7] hwmon/coretemp: Handle large core id value Date: Sat, 13 Aug 2022 00:41:40 +0800 Message-Id: <20220812164144.30829-4-rui.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220812164144.30829-1-rui.zhang@intel.com> References: <20220812164144.30829-1-rui.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org The coretemp driver supports up to a hard-coded limit of 128 cores. Today, the driver can not support a core with an id above that limit. Yet, the encoding of core_id's is arbitrary (BIOS APIC-id) and so they may be sparse and they may be large. Update the driver to map arbitrary core_id numbers into appropriate array indexes so that 128 cores can be supported, no matter the encoding of core_ids's. Acked-by: Len Brown Signed-off-by: Zhang Rui Acked-by: Guenter Roeck --- drivers/hwmon/coretemp.c | 55 +++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index ccf0af5b988a..3f0f7d7612ae 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -46,9 +46,6 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) -#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id) -#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO) - #ifdef CONFIG_SMP #define for_each_sibling(i, cpu) \ for_each_cpu(i, topology_sibling_cpumask(cpu)) @@ -91,6 +88,8 @@ struct temp_data { struct platform_data { struct device *hwmon_dev; u16 pkg_id; + u16 cpu_map[NUM_REAL_CORES]; + struct ida ida; struct cpumask cpumask; struct temp_data *core_data[MAX_CORE_DATA]; struct device_attribute name_attr; @@ -441,7 +440,7 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) MSR_IA32_THERM_STATUS; tdata->is_pkg_data = pkg_flag; tdata->cpu = cpu; - tdata->cpu_core_id = TO_CORE_ID(cpu); + tdata->cpu_core_id = topology_core_id(cpu); tdata->attr_size = MAX_CORE_ATTRS; mutex_init(&tdata->update_lock); return tdata; @@ -454,7 +453,7 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, struct platform_data *pdata = platform_get_drvdata(pdev); struct cpuinfo_x86 *c = &cpu_data(cpu); u32 eax, edx; - int err, attr_no; + int err, index, attr_no; /* * Find attr number for sysfs: @@ -462,14 +461,26 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, * The attr number is always core id + 2 * The Pkgtemp will always show up as temp1_*, if available */ - attr_no = pkg_flag ? PKG_SYSFS_ATTR_NO : TO_ATTR_NO(cpu); + if (pkg_flag) + attr_no = PKG_SYSFS_ATTR_NO; + else { + index = ida_alloc(&pdata->ida, GFP_KERNEL); + if (index < 0) + return index; + pdata->cpu_map[index] = topology_core_id(cpu); + attr_no = index + BASE_SYSFS_ATTR_NO; + } - if (attr_no > MAX_CORE_DATA - 1) - return -ERANGE; + if (attr_no > MAX_CORE_DATA - 1) { + err = -ERANGE; + goto ida_free; + } tdata = init_temp_data(cpu, pkg_flag); - if (!tdata) - return -ENOMEM; + if (!tdata) { + err = -ENOMEM; + goto ida_free; + } /* Test if we can access the status register */ err = rdmsr_safe_on_cpu(cpu, tdata->status_reg, &eax, &edx); @@ -505,6 +516,9 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, exit_free: pdata->core_data[attr_no] = NULL; kfree(tdata); +ida_free: + if (!pkg_flag) + ida_free(&pdata->ida, index); return err; } @@ -524,6 +538,8 @@ static void coretemp_remove_core(struct platform_data *pdata, int indx) kfree(pdata->core_data[indx]); pdata->core_data[indx] = NULL; + + ida_free(&pdata->ida, indx - BASE_SYSFS_ATTR_NO); } static int coretemp_probe(struct platform_device *pdev) @@ -537,6 +553,7 @@ static int coretemp_probe(struct platform_device *pdev) return -ENOMEM; pdata->pkg_id = pdev->id; + ida_init(&pdata->ida); platform_set_drvdata(pdev, pdata); pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, @@ -553,6 +570,7 @@ static int coretemp_remove(struct platform_device *pdev) if (pdata->core_data[i]) coretemp_remove_core(pdata, i); + ida_destroy(&pdata->ida); return 0; } @@ -647,7 +665,7 @@ static int coretemp_cpu_offline(unsigned int cpu) struct platform_device *pdev = coretemp_get_pdev(cpu); struct platform_data *pd; struct temp_data *tdata; - int indx, target; + int i, indx = -1, target; /* * Don't execute this on suspend as the device remove locks @@ -660,12 +678,19 @@ static int coretemp_cpu_offline(unsigned int cpu) if (!pdev) return 0; - /* The core id is too big, just return */ - indx = TO_ATTR_NO(cpu); - if (indx > MAX_CORE_DATA - 1) + pd = platform_get_drvdata(pdev); + + for (i = 0; i < NUM_REAL_CORES; i++) { + if (pd->cpu_map[i] == topology_core_id(cpu)) { + indx = i + BASE_SYSFS_ATTR_NO; + break; + } + } + + /* Too many cores and this core is not pupolated, just return */ + if (indx < 0) return 0; - pd = platform_get_drvdata(pdev); tdata = pd->core_data[indx]; cpumask_clear_cpu(cpu, &pd->cpumask);