hwmon: coretemp: update hotplug condition check
[firefly-linux-kernel-4.4.55.git] / drivers / hwmon / coretemp.c
index 2988da150ed6f7a223e64e892eed6d1ca2a18895..c05dc91ff4198a5b01018a4db6dee1b426e14d80 100644 (file)
@@ -53,6 +53,7 @@ struct coretemp_data {
        struct mutex update_lock;
        const char *name;
        u32 id;
+       u16 core_id;
        char valid;             /* zero until following fields are valid */
        unsigned long last_updated;     /* in jiffies */
        int temp;
@@ -75,7 +76,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute
        if (attr->index == SHOW_NAME)
                ret = sprintf(buf, "%s\n", data->name);
        else    /* show label */
-               ret = sprintf(buf, "Core %d\n", data->id);
+               ret = sprintf(buf, "Core %d\n", data->core_id);
        return ret;
 }
 
@@ -304,6 +305,9 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
        }
 
        data->id = pdev->id;
+#ifdef CONFIG_SMP
+       data->core_id = c->cpu_core_id;
+#endif
        data->name = "coretemp";
        mutex_init(&data->update_lock);
 
@@ -405,6 +409,10 @@ struct pdev_entry {
        struct list_head list;
        struct platform_device *pdev;
        unsigned int cpu;
+#ifdef CONFIG_SMP
+       u16 phys_proc_id;
+       u16 cpu_core_id;
+#endif
 };
 
 static LIST_HEAD(pdev_list);
@@ -415,6 +423,22 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
        int err;
        struct platform_device *pdev;
        struct pdev_entry *pdev_entry;
+#ifdef CONFIG_SMP
+       struct cpuinfo_x86 *c = &cpu_data(cpu);
+#endif
+
+       mutex_lock(&pdev_list_mutex);
+
+#ifdef CONFIG_SMP
+       /* Skip second HT entry of each core */
+       list_for_each_entry(pdev_entry, &pdev_list, list) {
+               if (c->phys_proc_id == pdev_entry->phys_proc_id &&
+                   c->cpu_core_id == pdev_entry->cpu_core_id) {
+                       err = 0;        /* Not an error */
+                       goto exit;
+               }
+       }
+#endif
 
        pdev = platform_device_alloc(DRVNAME, cpu);
        if (!pdev) {
@@ -438,7 +462,10 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
 
        pdev_entry->pdev = pdev;
        pdev_entry->cpu = cpu;
-       mutex_lock(&pdev_list_mutex);
+#ifdef CONFIG_SMP
+       pdev_entry->phys_proc_id = c->phys_proc_id;
+       pdev_entry->cpu_core_id = c->cpu_core_id;
+#endif
        list_add_tail(&pdev_entry->list, &pdev_list);
        mutex_unlock(&pdev_list_mutex);
 
@@ -449,6 +476,7 @@ exit_device_free:
 exit_device_put:
        platform_device_put(pdev);
 exit:
+       mutex_unlock(&pdev_list_mutex);
        return err;
 }
 
@@ -474,10 +502,13 @@ static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
        case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
                coretemp_device_add(cpu);
                break;
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                coretemp_device_remove(cpu);
                break;
        }
@@ -538,7 +569,9 @@ exit_devices_unreg:
        }
        mutex_unlock(&pdev_list_mutex);
 exit_driver_unreg:
+#ifndef CONFIG_HOTPLUG_CPU
        platform_driver_unregister(&coretemp_driver);
+#endif
 exit:
        return err;
 }