diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-03-31 16:43:40 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-03-31 16:43:40 -0700 |
commit | dba43fc4ba2fed63e898867fa973c69c37623939 (patch) | |
tree | 29f4d1fd58f6f5f933c61d48d4fda89d8c6686a0 /drivers/platform/x86/intel-uncore-frequency.c | |
parent | 1f944f976d7ef8a29d1ad296253d3a9387c58e62 (diff) | |
parent | d878bdfba8ffda64265c921cf7497934a607f83a (diff) |
Merge tag 'platform-drivers-x86-v5.7-1' of git://git.infradead.org/linux-platform-drivers-x86
Pull x86 platform driver updates from Andy Shevchenko:
- Fix for improper handling of fan_boost_mode in sysfs for ASUS
laptops.
- On newer ASUS laptops the 1st battery is named differently, here is a
fix.
- Fix Lex 2I385SW to allow both network cards to be used.
- The power integrated circuit driver for Surface 3 has been added.
- Refactor and clean up of Intel PMC driver and enable it on Intel
Jasper Lake.
- Clean up of Dell RBU driver.
- Big update for Intel Speed Select technology support tool and driver.
* tag 'platform-drivers-x86-v5.7-1' of git://git.infradead.org/linux-platform-drivers-x86: (75 commits)
platform/x86: surface3_power: Fix always true condition in mshw0011_space_handler()
platform/x86: surface3_power: Fix Kconfig section ordering
platform/x86: surface3_power: Add missed headers
platform/x86: surface3_power: Reformat GUID assignment
platform/x86: surface3_power: Drop useless macro ACPI_PTR()
platform/x86: surface3_power: Prefix POLL_INTERVAL with SURFACE_3
platform/x86: surface3_power: Simplify mshw0011_adp_psr() to one liner
platform/x86: surface3_power: Use dev_err() instead of pr_err()
platform/x86: surface3_power: Drop unused structure definition
platform/x86: surface3_power: MSHW0011 rev-eng implementation
platform/x86: intel_pmc_core: Make pmc_core_substate_res_show() generic
platform/x86: intel_pmc_core: Make pmc_core_lpm_display() generic for platforms that support sub-states
tools/power/x86/intel-speed-select: Fix a typo in error message
tools/power/x86/intel-speed-select: Update version
tools/power/x86/intel-speed-select: Avoid duplicate Package strings for json
tools/power/x86/intel-speed-select: Add display for enabled cpus count
tools/power/x86/intel-speed-select: Print friendly warning for bad command line
tools/power/x86/intel-speed-select: Fix avx options for turbo-freq feature
tools/power/x86/intel-speed-select: Improve CLX commands
tools/power/x86/intel-speed-select: Show error for invalid CPUs in the options
...
Diffstat (limited to 'drivers/platform/x86/intel-uncore-frequency.c')
-rw-r--r-- | drivers/platform/x86/intel-uncore-frequency.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/drivers/platform/x86/intel-uncore-frequency.c b/drivers/platform/x86/intel-uncore-frequency.c index 859272075a8f..b96d172eb2c1 100644 --- a/drivers/platform/x86/intel-uncore-frequency.c +++ b/drivers/platform/x86/intel-uncore-frequency.c @@ -38,6 +38,7 @@ */ struct uncore_data { struct kobject kobj; + struct completion kobj_unregister; u64 stored_uncore_data; u32 initial_min_freq_khz; u32 initial_max_freq_khz; @@ -52,7 +53,7 @@ static int uncore_max_entries __read_mostly; /* Storage for uncore data for all instances */ static struct uncore_data *uncore_instances; /* Root of the all uncore sysfs kobjs */ -struct kobject uncore_root_kobj; +struct kobject *uncore_root_kobj; /* Stores the CPU mask of the target CPUs to use during uncore read/write */ static cpumask_t uncore_cpu_mask; /* CPU online callback register instance */ @@ -97,6 +98,9 @@ static int uncore_read_ratio(struct uncore_data *data, unsigned int *min, u64 cap; int ret; + if (data->control_cpu < 0) + return -ENXIO; + ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, &cap); if (ret) return ret; @@ -116,6 +120,11 @@ static int uncore_write_ratio(struct uncore_data *data, unsigned int input, mutex_lock(&uncore_lock); + if (data->control_cpu < 0) { + ret = -ENXIO; + goto finish_write; + } + input /= UNCORE_FREQ_KHZ_MULTIPLIER; if (!input || input > 0x7F) { ret = -EINVAL; @@ -217,15 +226,19 @@ static struct attribute *uncore_attrs[] = { NULL }; +static void uncore_sysfs_entry_release(struct kobject *kobj) +{ + struct uncore_data *data = to_uncore_data(kobj); + + complete(&data->kobj_unregister); +} + static struct kobj_type uncore_ktype = { + .release = uncore_sysfs_entry_release, .sysfs_ops = &kobj_sysfs_ops, .default_attrs = uncore_attrs, }; -static struct kobj_type uncore_root_ktype = { - .sysfs_ops = &kobj_sysfs_ops, -}; - /* Caller provides protection */ static struct uncore_data *uncore_get_instance(unsigned int cpu) { @@ -263,8 +276,10 @@ static void uncore_add_die_entry(int cpu) uncore_read_ratio(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz); + init_completion(&data->kobj_unregister); + ret = kobject_init_and_add(&data->kobj, &uncore_ktype, - &uncore_root_kobj, str); + uncore_root_kobj, str); if (!ret) { data->control_cpu = cpu; data->valid = true; @@ -273,18 +288,15 @@ static void uncore_add_die_entry(int cpu) mutex_unlock(&uncore_lock); } -/* Last CPU in this die is offline, so remove sysfs entries */ +/* Last CPU in this die is offline, make control cpu invalid */ static void uncore_remove_die_entry(int cpu) { struct uncore_data *data; mutex_lock(&uncore_lock); data = uncore_get_instance(cpu); - if (data) { - kobject_put(&data->kobj); + if (data) data->control_cpu = -1; - data->valid = false; - } mutex_unlock(&uncore_lock); } @@ -384,11 +396,12 @@ static int __init intel_uncore_init(void) if (!uncore_instances) return -ENOMEM; - ret = kobject_init_and_add(&uncore_root_kobj, &uncore_root_ktype, - &cpu_subsys.dev_root->kobj, - "intel_uncore_frequency"); - if (ret) + uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency", + &cpu_subsys.dev_root->kobj); + if (!uncore_root_kobj) { + ret = -ENOMEM; goto err_free; + } ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "platform/x86/uncore-freq:online", @@ -408,7 +421,7 @@ static int __init intel_uncore_init(void) err_rem_state: cpuhp_remove_state(uncore_hp_state); err_rem_kobj: - kobject_put(&uncore_root_kobj); + kobject_put(uncore_root_kobj); err_free: kfree(uncore_instances); @@ -423,10 +436,12 @@ static void __exit intel_uncore_exit(void) unregister_pm_notifier(&uncore_pm_nb); cpuhp_remove_state(uncore_hp_state); for (i = 0; i < uncore_max_entries; ++i) { - if (uncore_instances[i].valid) + if (uncore_instances[i].valid) { kobject_put(&uncore_instances[i].kobj); + wait_for_completion(&uncore_instances[i].kobj_unregister); + } } - kobject_put(&uncore_root_kobj); + kobject_put(uncore_root_kobj); kfree(uncore_instances); } module_exit(intel_uncore_exit) |