diff options
| -rw-r--r-- | drivers/hwmon/coretemp.c | 93 |
1 files changed, 37 insertions, 56 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 3ae16c37bd92..cda09cf2e84b 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
| @@ -103,9 +103,10 @@ struct temp_data { | |||
| 103 | 103 | ||
| 104 | /* Platform Data per Physical CPU */ | 104 | /* Platform Data per Physical CPU */ |
| 105 | struct platform_data { | 105 | struct platform_data { |
| 106 | struct device *hwmon_dev; | 106 | struct device *hwmon_dev; |
| 107 | u16 phys_proc_id; | 107 | u16 phys_proc_id; |
| 108 | struct temp_data *core_data[MAX_CORE_DATA]; | 108 | struct cpumask cpumask; |
| 109 | struct temp_data *core_data[MAX_CORE_DATA]; | ||
| 109 | struct device_attribute name_attr; | 110 | struct device_attribute name_attr; |
| 110 | }; | 111 | }; |
| 111 | 112 | ||
| @@ -491,16 +492,6 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, | |||
| 491 | if (attr_no > MAX_CORE_DATA - 1) | 492 | if (attr_no > MAX_CORE_DATA - 1) |
| 492 | return -ERANGE; | 493 | return -ERANGE; |
| 493 | 494 | ||
| 494 | /* | ||
| 495 | * Provide a single set of attributes for all HT siblings of a core | ||
| 496 | * to avoid duplicate sensors (the processor ID and core ID of all | ||
| 497 | * HT siblings of a core are the same). | ||
| 498 | * Skip if a HT sibling of this core is already registered. | ||
| 499 | * This is not an error. | ||
| 500 | */ | ||
| 501 | if (pdata->core_data[attr_no] != NULL) | ||
| 502 | return 0; | ||
| 503 | |||
| 504 | tdata = init_temp_data(cpu, pkg_flag); | 495 | tdata = init_temp_data(cpu, pkg_flag); |
| 505 | if (!tdata) | 496 | if (!tdata) |
| 506 | return -ENOMEM; | 497 | return -ENOMEM; |
| @@ -665,24 +656,11 @@ static void coretemp_device_remove(unsigned int cpu) | |||
| 665 | mutex_unlock(&pdev_list_mutex); | 656 | mutex_unlock(&pdev_list_mutex); |
| 666 | } | 657 | } |
| 667 | 658 | ||
| 668 | static int get_online_core_in_package(struct platform_data *pdata) | ||
| 669 | { | ||
| 670 | int i; | ||
| 671 | |||
| 672 | /* Find online cores, except pkgtemp data */ | ||
| 673 | for (i = MAX_CORE_DATA - 1; i >= 0; --i) { | ||
| 674 | if (pdata->core_data[i] && | ||
| 675 | !pdata->core_data[i]->is_pkg_data) { | ||
| 676 | return pdata->core_data[i]->cpu; | ||
| 677 | } | ||
| 678 | } | ||
| 679 | return nr_cpu_ids; | ||
| 680 | } | ||
| 681 | |||
| 682 | static void get_core_online(unsigned int cpu) | 659 | static void get_core_online(unsigned int cpu) |
| 683 | { | 660 | { |
| 684 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 685 | struct platform_device *pdev = coretemp_get_pdev(cpu); | 661 | struct platform_device *pdev = coretemp_get_pdev(cpu); |
| 662 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 663 | struct platform_data *pdata; | ||
| 686 | int err; | 664 | int err; |
| 687 | 665 | ||
| 688 | /* | 666 | /* |
| @@ -707,6 +685,8 @@ static void get_core_online(unsigned int cpu) | |||
| 707 | err = coretemp_device_add(cpu); | 685 | err = coretemp_device_add(cpu); |
| 708 | if (err) | 686 | if (err) |
| 709 | return; | 687 | return; |
| 688 | |||
| 689 | pdev = coretemp_get_pdev(cpu); | ||
| 710 | /* | 690 | /* |
| 711 | * Check whether pkgtemp support is available. | 691 | * Check whether pkgtemp support is available. |
| 712 | * If so, add interfaces for pkgtemp. | 692 | * If so, add interfaces for pkgtemp. |
| @@ -714,60 +694,60 @@ static void get_core_online(unsigned int cpu) | |||
| 714 | if (cpu_has(c, X86_FEATURE_PTS)) | 694 | if (cpu_has(c, X86_FEATURE_PTS)) |
| 715 | coretemp_add_core(cpu, 1); | 695 | coretemp_add_core(cpu, 1); |
| 716 | } | 696 | } |
| 697 | |||
| 698 | pdata = platform_get_drvdata(pdev); | ||
| 717 | /* | 699 | /* |
| 718 | * Physical CPU device already exists. | 700 | * Check whether a thread sibling is already online. If not add the |
| 719 | * So, just add interfaces for this core. | 701 | * interface for this CPU core. |
| 720 | */ | 702 | */ |
| 721 | coretemp_add_core(cpu, 0); | 703 | if (!cpumask_intersects(&pdata->cpumask, topology_sibling_cpumask(cpu))) |
| 704 | coretemp_add_core(cpu, 0); | ||
| 705 | |||
| 706 | cpumask_set_cpu(cpu, &pdata->cpumask); | ||
| 722 | } | 707 | } |
| 723 | 708 | ||
| 724 | static void put_core_offline(unsigned int cpu) | 709 | static void put_core_offline(unsigned int cpu) |
| 725 | { | 710 | { |
| 726 | struct platform_device *pdev = coretemp_get_pdev(cpu); | 711 | struct platform_device *pdev = coretemp_get_pdev(cpu); |
| 727 | struct platform_data *pdata; | 712 | struct platform_data *pd; |
| 728 | struct temp_data *tdata; | 713 | struct temp_data *tdata; |
| 729 | int i, indx, target; | 714 | int indx, target; |
| 730 | 715 | ||
| 731 | /* If the physical CPU device does not exist, just return */ | 716 | /* If the physical CPU device does not exist, just return */ |
| 732 | if (!pdev) | 717 | if (!pdev) |
| 733 | return; | 718 | return; |
| 734 | 719 | ||
| 735 | pdata = platform_get_drvdata(pdev); | ||
| 736 | |||
| 737 | indx = TO_ATTR_NO(cpu); | ||
| 738 | |||
| 739 | /* The core id is too big, just return */ | 720 | /* The core id is too big, just return */ |
| 721 | indx = TO_ATTR_NO(cpu); | ||
| 740 | if (indx > MAX_CORE_DATA - 1) | 722 | if (indx > MAX_CORE_DATA - 1) |
| 741 | return; | 723 | return; |
| 742 | 724 | ||
| 743 | if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu) | 725 | pd = platform_get_drvdata(pdev); |
| 744 | coretemp_remove_core(pdata, indx); | 726 | tdata = pd->core_data[indx]; |
| 727 | |||
| 728 | cpumask_clear_cpu(cpu, &pd->cpumask); | ||
| 745 | 729 | ||
| 746 | /* | 730 | /* |
| 747 | * If a HT sibling of a core is taken offline, but another HT sibling | 731 | * If this is the last thread sibling, remove the CPU core |
| 748 | * of the same core is still online, register the alternate sibling. | 732 | * interface, If there is still a sibling online, transfer the |
| 749 | * This ensures that exactly one set of attributes is provided as long | 733 | * target cpu of that core interface to it. |
| 750 | * as at least one HT sibling of a core is online. | ||
| 751 | */ | 734 | */ |
| 752 | for_each_sibling(i, cpu) { | 735 | target = cpumask_any_and(&pd->cpumask, topology_sibling_cpumask(cpu)); |
| 753 | if (i != cpu) { | 736 | if (target >= nr_cpu_ids) { |
| 754 | get_core_online(i); | 737 | coretemp_remove_core(pd, indx); |
| 755 | /* | 738 | } else if (tdata && tdata->cpu == cpu) { |
| 756 | * Display temperature sensor data for one HT sibling | 739 | mutex_lock(&tdata->update_lock); |
| 757 | * per core only, so abort the loop after one such | 740 | tdata->cpu = target; |
| 758 | * sibling has been found. | 741 | mutex_unlock(&tdata->update_lock); |
| 759 | */ | ||
| 760 | break; | ||
| 761 | } | ||
| 762 | } | 742 | } |
| 743 | |||
| 763 | /* | 744 | /* |
| 764 | * If all cores in this pkg are offline, remove the device. | 745 | * If all cores in this pkg are offline, remove the device. |
| 765 | * coretemp_device_remove calls unregister_platform_device, | 746 | * coretemp_device_remove calls unregister_platform_device, |
| 766 | * which in turn calls coretemp_remove. This removes the | 747 | * which in turn calls coretemp_remove. This removes the |
| 767 | * pkgtemp entry and does other clean ups. | 748 | * pkgtemp entry and does other clean ups. |
| 768 | */ | 749 | */ |
| 769 | target = get_online_core_in_package(pdata); | 750 | if (cpumask_empty(&pd->cpumask)) { |
| 770 | if (target >= nr_cpu_ids) { | ||
| 771 | coretemp_device_remove(cpu); | 751 | coretemp_device_remove(cpu); |
| 772 | return; | 752 | return; |
| 773 | } | 753 | } |
| @@ -775,8 +755,9 @@ static void put_core_offline(unsigned int cpu) | |||
| 775 | * Check whether this core is the target for the package | 755 | * Check whether this core is the target for the package |
| 776 | * interface. We need to assign it to some other cpu. | 756 | * interface. We need to assign it to some other cpu. |
| 777 | */ | 757 | */ |
| 778 | tdata = pdata->core_data[PKG_SYSFS_ATTR_NO]; | 758 | tdata = pd->core_data[PKG_SYSFS_ATTR_NO]; |
| 779 | if (tdata && tdata->cpu == cpu) { | 759 | if (tdata && tdata->cpu == cpu) { |
| 760 | target = cpumask_first(&pd->cpumask); | ||
| 780 | mutex_lock(&tdata->update_lock); | 761 | mutex_lock(&tdata->update_lock); |
| 781 | tdata->cpu = target; | 762 | tdata->cpu = target; |
| 782 | mutex_unlock(&tdata->update_lock); | 763 | mutex_unlock(&tdata->update_lock); |
