From patchwork Tue Nov 22 17:42:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Gleixner X-Patchwork-Id: 9441751 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 17E4060237 for ; Tue, 22 Nov 2016 17:46:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C7B227DA4 for ; Tue, 22 Nov 2016 17:46:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0148C28596; Tue, 22 Nov 2016 17:46:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6946F27DA4 for ; Tue, 22 Nov 2016 17:46:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933364AbcKVRqA (ORCPT ); Tue, 22 Nov 2016 12:46:00 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:60392 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756325AbcKVRpd (ORCPT ); Tue, 22 Nov 2016 12:45:33 -0500 Received: from localhost ([127.0.0.1] helo=[127.0.1.1]) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1c9F54-0000G6-Fz; Tue, 22 Nov 2016 18:42:06 +0100 Message-Id: <20161122173731.920061058@linutronix.de> User-Agent: quilt/0.63-1 Date: Tue, 22 Nov 2016 17:42:06 -0000 From: Thomas Gleixner To: LKML Cc: Fenghua Yu , Jean Delvare , Guenter Roeck , linux-hwmon@vger.kernel.org, Sebastian Siewior , Peter Zijlstra , x86@kernel.org Subject: [patch 6/6] hwmon/coretemp: Simplify package management References: <20161122173622.771252945@linutronix.de> MIME-Version: 1.0 Content-Disposition: inline; filename=hwmon-coretemp--Simplify-package-management.patch Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Keeping track of the per package platform devices requires an extra object, which is held in a linked list. The maximum number of packages is known at init() time. So the extra object and linked list management can be replaced by an array of platform device pointers in which the per package devices pointers can be stored. Lookup becomes a simple array lookup instead of a list walk. The mutex protecting the list can be removed as well because the array is only accessed from cpu hotplug callbacks which are already serialized. Signed-off-by: Thomas Gleixner --- drivers/hwmon/coretemp.c | 120 ++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 82 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -59,7 +59,6 @@ MODULE_PARM_DESC(tjmax, "TjMax value in #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) -#define TO_PHYS_ID(cpu) (cpu_data(cpu).phys_proc_id) #define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id) #define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO) @@ -104,20 +103,16 @@ struct temp_data { /* Platform Data per Physical CPU */ struct platform_data { struct device *hwmon_dev; - u16 phys_proc_id; + u16 pkg_id; struct cpumask cpumask; struct temp_data *core_data[MAX_CORE_DATA]; struct device_attribute name_attr; }; -struct pdev_entry { - struct list_head list; - struct platform_device *pdev; - u16 phys_proc_id; -}; - -static LIST_HEAD(pdev_list); -static DEFINE_MUTEX(pdev_list_mutex); +/* Keep track of how many package pointers we allocated in init() */ +static int max_packages __read_mostly; +/* Array of package pointers. Serialized by cpu hotplug lock */ +static struct platform_device **pkg_devices; static ssize_t show_label(struct device *dev, struct device_attribute *devattr, char *buf) @@ -127,7 +122,7 @@ static ssize_t show_label(struct device struct temp_data *tdata = pdata->core_data[attr->index]; if (tdata->is_pkg_data) - return sprintf(buf, "Physical id %u\n", pdata->phys_proc_id); + return sprintf(buf, "Package id %u\n", pdata->pkg_id); return sprintf(buf, "Core %u\n", tdata->cpu_core_id); } @@ -439,18 +434,10 @@ static int chk_ucode_version(unsigned in static struct platform_device *coretemp_get_pdev(unsigned int cpu) { - u16 phys_proc_id = TO_PHYS_ID(cpu); - struct pdev_entry *p; - - mutex_lock(&pdev_list_mutex); + int pkgid = topology_logical_package_id(cpu); - list_for_each_entry(p, &pdev_list, list) - if (p->phys_proc_id == phys_proc_id) { - mutex_unlock(&pdev_list_mutex); - return p->pdev; - } - - mutex_unlock(&pdev_list_mutex); + if (pkgid >= 0 && pkgid < max_packages) + return pkg_devices[pkgid]; return NULL; } @@ -561,7 +548,7 @@ static int coretemp_probe(struct platfor if (!pdata) return -ENOMEM; - pdata->phys_proc_id = pdev->id; + pdata->pkg_id = pdev->id; platform_set_drvdata(pdev, pdata); pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, @@ -589,64 +576,26 @@ static struct platform_driver coretemp_d .remove = coretemp_remove, }; -static int coretemp_device_add(unsigned int cpu) +static struct platform_device *coretemp_device_add(unsigned int cpu) { - int err; + int err, pkgid = topology_logical_package_id(cpu); struct platform_device *pdev; - struct pdev_entry *pdev_entry; - mutex_lock(&pdev_list_mutex); + if (pkgid < 0) + return ERR_PTR(-ENOMEM); - pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu)); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL); - if (!pdev_entry) { - err = -ENOMEM; - goto exit_device_put; - } + pdev = platform_device_alloc(DRVNAME, pkgid); + if (!pdev) + return ERR_PTR(-ENOMEM); err = platform_device_add(pdev); if (err) { - pr_err("Device addition failed (%d)\n", err); - goto exit_device_free; + platform_device_put(pdev); + return ERR_PTR(err); } - pdev_entry->pdev = pdev; - pdev_entry->phys_proc_id = pdev->id; - - list_add_tail(&pdev_entry->list, &pdev_list); - mutex_unlock(&pdev_list_mutex); - - return 0; - -exit_device_free: - kfree(pdev_entry); -exit_device_put: - platform_device_put(pdev); -exit: - mutex_unlock(&pdev_list_mutex); - return err; -} - -static void coretemp_device_remove(unsigned int cpu) -{ - struct pdev_entry *p, *n; - u16 phys_proc_id = TO_PHYS_ID(cpu); - - mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { - if (p->phys_proc_id != phys_proc_id) - continue; - platform_device_unregister(p->pdev); - list_del(&p->list); - kfree(p); - } - mutex_unlock(&pdev_list_mutex); + pkg_devices[pkgid] = pdev; + return pdev; } static int coretemp_cpu_online(unsigned int cpu) @@ -654,7 +603,6 @@ static int coretemp_cpu_online(unsigned struct platform_device *pdev = coretemp_get_pdev(cpu); struct cpuinfo_x86 *c = &cpu_data(cpu); struct platform_data *pdata; - int err; /* * CPUID.06H.EAX[0] indicates whether the CPU has thermal @@ -675,11 +623,10 @@ static int coretemp_cpu_online(unsigned * online. So, initialize per-pkg data structures and * then bring this core online. */ - err = coretemp_device_add(cpu); - if (err) - return err; + pdev = coretemp_device_add(cpu); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); - pdev = coretemp_get_pdev(cpu); /* * Check whether pkgtemp support is available. * If so, add interfaces for pkgtemp. @@ -736,15 +683,16 @@ static int coretemp_cpu_offline(unsigned } /* - * If all cores in this pkg are offline, remove the device. - * coretemp_device_remove calls unregister_platform_device, - * which in turn calls coretemp_remove. This removes the - * pkgtemp entry and does other clean ups. + * If all cores in this pkg are offline, remove the device. This + * will invoke the platform driver remove function, which cleans up + * the rest. */ if (cpumask_empty(&pd->cpumask)) { - coretemp_device_remove(cpu); + pkg_devices[topology_logical_package_id(cpu)] = NULL; + platform_device_unregister(pdev); return 0; } + /* * Check whether this core is the target for the package * interface. We need to assign it to some other cpu. @@ -778,6 +726,12 @@ static int __init coretemp_init(void) if (!x86_match_cpu(coretemp_ids)) return -ENODEV; + max_packages = topology_max_packages(); + pkg_devices = kzalloc(max_packages * sizeof(struct platform_device *), + GFP_KERNEL); + if (!pkg_devices) + return -ENOMEM; + err = platform_driver_register(&coretemp_driver); if (err) return err; @@ -791,6 +745,7 @@ static int __init coretemp_init(void) outdrv: platform_driver_unregister(&coretemp_driver); + kfree(pkg_devices); return err; } module_init(coretemp_init) @@ -799,6 +754,7 @@ static void __exit coretemp_exit(void) { cpuhp_remove_state(coretemp_hp_online); platform_driver_unregister(&coretemp_driver); + kfree(pkg_devices); } module_exit(coretemp_exit)