.. | .. |
---|
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) |
---|