| .. | .. |
|---|
| 550 | 550 | ida_free(&pdata->ida, indx - BASE_SYSFS_ATTR_NO); |
|---|
| 551 | 551 | } |
|---|
| 552 | 552 | |
|---|
| 553 | | -static int coretemp_probe(struct platform_device *pdev) |
|---|
| 553 | +static int coretemp_device_add(int zoneid) |
|---|
| 554 | 554 | { |
|---|
| 555 | | - struct device *dev = &pdev->dev; |
|---|
| 555 | + struct platform_device *pdev; |
|---|
| 556 | 556 | struct platform_data *pdata; |
|---|
| 557 | + int err; |
|---|
| 557 | 558 | |
|---|
| 558 | 559 | /* Initialize the per-zone data structures */ |
|---|
| 559 | | - pdata = devm_kzalloc(dev, sizeof(struct platform_data), GFP_KERNEL); |
|---|
| 560 | + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); |
|---|
| 560 | 561 | if (!pdata) |
|---|
| 561 | 562 | return -ENOMEM; |
|---|
| 562 | 563 | |
|---|
| 563 | | - pdata->pkg_id = pdev->id; |
|---|
| 564 | + pdata->pkg_id = zoneid; |
|---|
| 564 | 565 | ida_init(&pdata->ida); |
|---|
| 565 | | - platform_set_drvdata(pdev, pdata); |
|---|
| 566 | | - |
|---|
| 567 | | - pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, |
|---|
| 568 | | - pdata, NULL); |
|---|
| 569 | | - return PTR_ERR_OR_ZERO(pdata->hwmon_dev); |
|---|
| 570 | | -} |
|---|
| 571 | | - |
|---|
| 572 | | -static int coretemp_remove(struct platform_device *pdev) |
|---|
| 573 | | -{ |
|---|
| 574 | | - struct platform_data *pdata = platform_get_drvdata(pdev); |
|---|
| 575 | | - int i; |
|---|
| 576 | | - |
|---|
| 577 | | - for (i = MAX_CORE_DATA - 1; i >= 0; --i) |
|---|
| 578 | | - if (pdata->core_data[i]) |
|---|
| 579 | | - coretemp_remove_core(pdata, i); |
|---|
| 580 | | - |
|---|
| 581 | | - ida_destroy(&pdata->ida); |
|---|
| 582 | | - return 0; |
|---|
| 583 | | -} |
|---|
| 584 | | - |
|---|
| 585 | | -static struct platform_driver coretemp_driver = { |
|---|
| 586 | | - .driver = { |
|---|
| 587 | | - .name = DRVNAME, |
|---|
| 588 | | - }, |
|---|
| 589 | | - .probe = coretemp_probe, |
|---|
| 590 | | - .remove = coretemp_remove, |
|---|
| 591 | | -}; |
|---|
| 592 | | - |
|---|
| 593 | | -static struct platform_device *coretemp_device_add(unsigned int cpu) |
|---|
| 594 | | -{ |
|---|
| 595 | | - int err, zoneid = topology_logical_die_id(cpu); |
|---|
| 596 | | - struct platform_device *pdev; |
|---|
| 597 | | - |
|---|
| 598 | | - if (zoneid < 0) |
|---|
| 599 | | - return ERR_PTR(-ENOMEM); |
|---|
| 600 | 566 | |
|---|
| 601 | 567 | pdev = platform_device_alloc(DRVNAME, zoneid); |
|---|
| 602 | | - if (!pdev) |
|---|
| 603 | | - return ERR_PTR(-ENOMEM); |
|---|
| 604 | | - |
|---|
| 605 | | - err = platform_device_add(pdev); |
|---|
| 606 | | - if (err) { |
|---|
| 607 | | - platform_device_put(pdev); |
|---|
| 608 | | - return ERR_PTR(err); |
|---|
| 568 | + if (!pdev) { |
|---|
| 569 | + err = -ENOMEM; |
|---|
| 570 | + goto err_free_pdata; |
|---|
| 609 | 571 | } |
|---|
| 610 | 572 | |
|---|
| 573 | + err = platform_device_add(pdev); |
|---|
| 574 | + if (err) |
|---|
| 575 | + goto err_put_dev; |
|---|
| 576 | + |
|---|
| 577 | + platform_set_drvdata(pdev, pdata); |
|---|
| 611 | 578 | zone_devices[zoneid] = pdev; |
|---|
| 612 | | - return pdev; |
|---|
| 579 | + return 0; |
|---|
| 580 | + |
|---|
| 581 | +err_put_dev: |
|---|
| 582 | + platform_device_put(pdev); |
|---|
| 583 | +err_free_pdata: |
|---|
| 584 | + kfree(pdata); |
|---|
| 585 | + return err; |
|---|
| 586 | +} |
|---|
| 587 | + |
|---|
| 588 | +static void coretemp_device_remove(int zoneid) |
|---|
| 589 | +{ |
|---|
| 590 | + struct platform_device *pdev = zone_devices[zoneid]; |
|---|
| 591 | + struct platform_data *pdata = platform_get_drvdata(pdev); |
|---|
| 592 | + |
|---|
| 593 | + ida_destroy(&pdata->ida); |
|---|
| 594 | + kfree(pdata); |
|---|
| 595 | + platform_device_unregister(pdev); |
|---|
| 613 | 596 | } |
|---|
| 614 | 597 | |
|---|
| 615 | 598 | static int coretemp_cpu_online(unsigned int cpu) |
|---|
| .. | .. |
|---|
| 633 | 616 | if (!cpu_has(c, X86_FEATURE_DTHERM)) |
|---|
| 634 | 617 | return -ENODEV; |
|---|
| 635 | 618 | |
|---|
| 636 | | - if (!pdev) { |
|---|
| 619 | + pdata = platform_get_drvdata(pdev); |
|---|
| 620 | + if (!pdata->hwmon_dev) { |
|---|
| 621 | + struct device *hwmon; |
|---|
| 622 | + |
|---|
| 637 | 623 | /* Check the microcode version of the CPU */ |
|---|
| 638 | 624 | if (chk_ucode_version(cpu)) |
|---|
| 639 | 625 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 644 | 630 | * online. So, initialize per-pkg data structures and |
|---|
| 645 | 631 | * then bring this core online. |
|---|
| 646 | 632 | */ |
|---|
| 647 | | - pdev = coretemp_device_add(cpu); |
|---|
| 648 | | - if (IS_ERR(pdev)) |
|---|
| 649 | | - return PTR_ERR(pdev); |
|---|
| 633 | + hwmon = hwmon_device_register_with_groups(&pdev->dev, DRVNAME, |
|---|
| 634 | + pdata, NULL); |
|---|
| 635 | + if (IS_ERR(hwmon)) |
|---|
| 636 | + return PTR_ERR(hwmon); |
|---|
| 637 | + pdata->hwmon_dev = hwmon; |
|---|
| 650 | 638 | |
|---|
| 651 | 639 | /* |
|---|
| 652 | 640 | * Check whether pkgtemp support is available. |
|---|
| .. | .. |
|---|
| 656 | 644 | coretemp_add_core(pdev, cpu, 1); |
|---|
| 657 | 645 | } |
|---|
| 658 | 646 | |
|---|
| 659 | | - pdata = platform_get_drvdata(pdev); |
|---|
| 660 | 647 | /* |
|---|
| 661 | 648 | * Check whether a thread sibling is already online. If not add the |
|---|
| 662 | 649 | * interface for this CPU core. |
|---|
| .. | .. |
|---|
| 675 | 662 | struct temp_data *tdata; |
|---|
| 676 | 663 | int i, indx = -1, target; |
|---|
| 677 | 664 | |
|---|
| 678 | | - /* |
|---|
| 679 | | - * Don't execute this on suspend as the device remove locks |
|---|
| 680 | | - * up the machine. |
|---|
| 681 | | - */ |
|---|
| 665 | + /* No need to tear down any interfaces for suspend */ |
|---|
| 682 | 666 | if (cpuhp_tasks_frozen) |
|---|
| 683 | 667 | return 0; |
|---|
| 684 | 668 | |
|---|
| 685 | 669 | /* If the physical CPU device does not exist, just return */ |
|---|
| 686 | | - if (!pdev) |
|---|
| 687 | | - return 0; |
|---|
| 688 | | - |
|---|
| 689 | 670 | pd = platform_get_drvdata(pdev); |
|---|
| 671 | + if (!pd->hwmon_dev) |
|---|
| 672 | + return 0; |
|---|
| 690 | 673 | |
|---|
| 691 | 674 | for (i = 0; i < NUM_REAL_CORES; i++) { |
|---|
| 692 | 675 | if (pd->cpu_map[i] == topology_core_id(cpu)) { |
|---|
| .. | .. |
|---|
| 718 | 701 | } |
|---|
| 719 | 702 | |
|---|
| 720 | 703 | /* |
|---|
| 721 | | - * If all cores in this pkg are offline, remove the device. This |
|---|
| 722 | | - * will invoke the platform driver remove function, which cleans up |
|---|
| 723 | | - * the rest. |
|---|
| 704 | + * If all cores in this pkg are offline, remove the interface. |
|---|
| 724 | 705 | */ |
|---|
| 706 | + tdata = pd->core_data[PKG_SYSFS_ATTR_NO]; |
|---|
| 725 | 707 | if (cpumask_empty(&pd->cpumask)) { |
|---|
| 726 | | - zone_devices[topology_logical_die_id(cpu)] = NULL; |
|---|
| 727 | | - platform_device_unregister(pdev); |
|---|
| 708 | + if (tdata) |
|---|
| 709 | + coretemp_remove_core(pd, PKG_SYSFS_ATTR_NO); |
|---|
| 710 | + hwmon_device_unregister(pd->hwmon_dev); |
|---|
| 711 | + pd->hwmon_dev = NULL; |
|---|
| 728 | 712 | return 0; |
|---|
| 729 | 713 | } |
|---|
| 730 | 714 | |
|---|
| .. | .. |
|---|
| 732 | 716 | * Check whether this core is the target for the package |
|---|
| 733 | 717 | * interface. We need to assign it to some other cpu. |
|---|
| 734 | 718 | */ |
|---|
| 735 | | - tdata = pd->core_data[PKG_SYSFS_ATTR_NO]; |
|---|
| 736 | 719 | if (tdata && tdata->cpu == cpu) { |
|---|
| 737 | 720 | target = cpumask_first(&pd->cpumask); |
|---|
| 738 | 721 | mutex_lock(&tdata->update_lock); |
|---|
| .. | .. |
|---|
| 751 | 734 | |
|---|
| 752 | 735 | static int __init coretemp_init(void) |
|---|
| 753 | 736 | { |
|---|
| 754 | | - int err; |
|---|
| 737 | + int i, err; |
|---|
| 755 | 738 | |
|---|
| 756 | 739 | /* |
|---|
| 757 | 740 | * CPUID.06H.EAX[0] indicates whether the CPU has thermal |
|---|
| .. | .. |
|---|
| 767 | 750 | if (!zone_devices) |
|---|
| 768 | 751 | return -ENOMEM; |
|---|
| 769 | 752 | |
|---|
| 770 | | - err = platform_driver_register(&coretemp_driver); |
|---|
| 771 | | - if (err) |
|---|
| 772 | | - goto outzone; |
|---|
| 753 | + for (i = 0; i < max_zones; i++) { |
|---|
| 754 | + err = coretemp_device_add(i); |
|---|
| 755 | + if (err) |
|---|
| 756 | + goto outzone; |
|---|
| 757 | + } |
|---|
| 773 | 758 | |
|---|
| 774 | 759 | err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/coretemp:online", |
|---|
| 775 | 760 | coretemp_cpu_online, coretemp_cpu_offline); |
|---|
| 776 | 761 | if (err < 0) |
|---|
| 777 | | - goto outdrv; |
|---|
| 762 | + goto outzone; |
|---|
| 778 | 763 | coretemp_hp_online = err; |
|---|
| 779 | 764 | return 0; |
|---|
| 780 | 765 | |
|---|
| 781 | | -outdrv: |
|---|
| 782 | | - platform_driver_unregister(&coretemp_driver); |
|---|
| 783 | 766 | outzone: |
|---|
| 767 | + while (i--) |
|---|
| 768 | + coretemp_device_remove(i); |
|---|
| 784 | 769 | kfree(zone_devices); |
|---|
| 785 | 770 | return err; |
|---|
| 786 | 771 | } |
|---|
| .. | .. |
|---|
| 788 | 773 | |
|---|
| 789 | 774 | static void __exit coretemp_exit(void) |
|---|
| 790 | 775 | { |
|---|
| 776 | + int i; |
|---|
| 777 | + |
|---|
| 791 | 778 | cpuhp_remove_state(coretemp_hp_online); |
|---|
| 792 | | - platform_driver_unregister(&coretemp_driver); |
|---|
| 779 | + for (i = 0; i < max_zones; i++) |
|---|
| 780 | + coretemp_device_remove(i); |
|---|
| 793 | 781 | kfree(zone_devices); |
|---|
| 794 | 782 | } |
|---|
| 795 | 783 | module_exit(coretemp_exit) |
|---|