forked from luck/tmp_suning_uos_patched
More power management updates for 5.10-rc1
- Move the AVS drivers to new platform-specific locations and get rid of the drivers/power/avs directory (Ulf Hansson). - Add on/off notifiers and idle state accounting support to the generic power domains (genpd) framework (Ulf Hansson, Lina Iyer). - Ulf will maintain the PM domain part of cpuidle-psci (Ulf Hansson). - Make intel_idle disregard ACPI _CST if it cannot use the data returned by that method (Mel Gorman). - Modify intel_pstate to avoid leaving useless sysfs directory structure behind if it cannot be registered (Chen Yu). - Fix domain detection in the RAPL power capping driver and prevent it from failing to enumerate the Psys RAPL domain (Zhang Rui). - Allow acpi-cpufreq to use ACPI _PSD information with Family 19 and later AMD chips (Wei Huang). - Update the driver assumptions comment in intel_idle and fix a kerneldoc comment in the runtime PM framework (Alexander Monakov, Bean Huo). - Avoid unnecessary resets of the cached frequency in the schedutil cpufreq governor to reduce overhead (Wei Wang). - Clean up the cpufreq core a bit (Viresh Kumar). - Make assorted minor janitorial changes (Daniel Lezcano, Geert Uytterhoeven, Hubert Jasudowicz, Tom Rix). - Clean up and optimize the cpupower utility somewhat (Colin Ian King, Martin Kaistra). -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAl+TD4gSHHJqd0Byand5 c29ja2kubmV0AAoJEILEb/54YlRx3AgP/0Fpi50+Kggr7pIXKElwg7ECJA0nOLT6 gp4Vc/J/3r6zqK0ANDgCRlEMckAT61ukll+eU+BlavBrI4ZYj/Homi0+u53t1GjM AOwj1SmQgSBcBavWsBOc8+12X6wYLzyQbyWc53oYH5os537n8s7zkSZuSBcGFUgb wWF4xOeuW/ETsxAzEYmY7LvtBeEmo3UjV0fZPPbo/ro5EHDaOpvO/4EUDjCQxR6b CvyjgLlxuAOFWG/B5lVTCx7S6MmBjHXUIFUizt+TA6YjyGd0mG0i0f7mgzs6hqUD gzERDSlehBC3zPh5O35HNGUG8ulvDi9+ugxuckFHu/j4wEeZswp8AuIpdLI6Mcnc LDb+LTeypAB5d1fzHeSziv8AL08cUAS6QT+q96whYibQs6WA1mE9yXECyg6ZGsLt 1KPAc8KD4ojwjo9vtk9VU0ZaUcVBMnqyK+GK929l0nXohw2Fae6X/NlpQ0D7joZA NM+dWMXpHy6tuVOgdUmrmN+P6vWd8ApWBeufkUFsCzrh3zG57yVaLl2SAjEtpKh0 Emr/kJ8Ox8cf++6mGKseR2ZbkGn0Tz2GD5l3hIAGnIv9Nda3YgCc6RyV7U9se7OW 2xnQvrgXqQKyjjziptVFqDotcC/KXFACr3YZX6GlW675NOMXSGk1ZYI3FbrsM8yd 0/zq7PyYmb0D =TFKg -----END PGP SIGNATURE----- Merge tag 'pm-5.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull more power management updates from Rafael Wysocki: "First of all, the adaptive voltage scaling (AVS) drivers go to new platform-specific locations as planned (this part was reported to have merge conflicts against the new arm-soc updates in linux-next). In addition to that, there are some fixes (intel_idle, intel_pstate, RAPL, acpi_cpufreq), the addition of on/off notifiers and idle state accounting support to the generic power domains (genpd) code and some janitorial changes all over. Specifics: - Move the AVS drivers to new platform-specific locations and get rid of the drivers/power/avs directory (Ulf Hansson). - Add on/off notifiers and idle state accounting support to the generic power domains (genpd) framework (Ulf Hansson, Lina Iyer). - Ulf will maintain the PM domain part of cpuidle-psci (Ulf Hansson). - Make intel_idle disregard ACPI _CST if it cannot use the data returned by that method (Mel Gorman). - Modify intel_pstate to avoid leaving useless sysfs directory structure behind if it cannot be registered (Chen Yu). - Fix domain detection in the RAPL power capping driver and prevent it from failing to enumerate the Psys RAPL domain (Zhang Rui). - Allow acpi-cpufreq to use ACPI _PSD information with Family 19 and later AMD chips (Wei Huang). - Update the driver assumptions comment in intel_idle and fix a kerneldoc comment in the runtime PM framework (Alexander Monakov, Bean Huo). - Avoid unnecessary resets of the cached frequency in the schedutil cpufreq governor to reduce overhead (Wei Wang). - Clean up the cpufreq core a bit (Viresh Kumar). - Make assorted minor janitorial changes (Daniel Lezcano, Geert Uytterhoeven, Hubert Jasudowicz, Tom Rix). - Clean up and optimize the cpupower utility somewhat (Colin Ian King, Martin Kaistra)" * tag 'pm-5.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (23 commits) PM: sleep: remove unreachable break PM: AVS: Drop the avs directory and the corresponding Kconfig PM: AVS: qcom-cpr: Move the driver to the qcom specific drivers PM: runtime: Fix typo in pm_runtime_set_active() helper comment PM: domains: Fix build error for genpd notifiers powercap: Fix typo in Kconfig "Plance" -> "Plane" cpufreq: schedutil: restore cached freq when next_f is not changed acpi-cpufreq: Honor _PSD table setting on new AMD CPUs PM: AVS: smartreflex Move driver to soc specific drivers PM: AVS: rockchip-io: Move the driver to the rockchip specific drivers PM: domains: enable domain idle state accounting PM: domains: Add curly braces to delimit comment + statement block PM: domains: Add support for PM domain on/off notifiers for genpd powercap/intel_rapl: enumerate Psys RAPL domain together with package RAPL domain powercap/intel_rapl: Fix domain detection intel_idle: Ignore _CST if control cannot be taken from the platform cpuidle: Remove pointless stub intel_idle: mention assumption that WBINVD is not needed MAINTAINERS: Add section for cpuidle-psci PM domain cpufreq: intel_pstate: Delete intel_pstate sysfs if failed to register the driver ...
This commit is contained in:
commit
41f762a15a
14
MAINTAINERS
14
MAINTAINERS
|
@ -4585,6 +4585,14 @@ L: linux-arm-kernel@lists.infradead.org
|
|||
S: Supported
|
||||
F: drivers/cpuidle/cpuidle-psci.c
|
||||
|
||||
CPUIDLE DRIVER - ARM PSCI PM DOMAIN
|
||||
M: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
L: linux-arm-kernel@lists.infradead.org
|
||||
S: Supported
|
||||
F: drivers/cpuidle/cpuidle-psci.h
|
||||
F: drivers/cpuidle/cpuidle-psci-domain.c
|
||||
|
||||
CRAMFS FILESYSTEM
|
||||
M: Nicolas Pitre <nico@fluxnic.net>
|
||||
S: Maintained
|
||||
|
@ -5398,11 +5406,11 @@ F: include/linux/debugfs.h
|
|||
F: include/linux/kobj*
|
||||
F: lib/kobj*
|
||||
|
||||
DRIVERS FOR ADAPTIVE VOLTAGE SCALING (AVS)
|
||||
DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
|
||||
M: Nishanth Menon <nm@ti.com>
|
||||
L: linux-pm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/power/avs/
|
||||
F: drivers/soc/ti/smartreflex.c
|
||||
F: include/linux/power/smartreflex.h
|
||||
|
||||
DRM DRIVER FOR ALLWINNER DE2 AND DE3 ENGINE
|
||||
|
@ -14459,7 +14467,7 @@ L: linux-pm@vger.kernel.org
|
|||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
|
||||
F: drivers/power/avs/qcom-cpr.c
|
||||
F: drivers/soc/qcom/cpr.c
|
||||
|
||||
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
|
||||
M: Ilia Lin <ilia.lin@kernel.org>
|
||||
|
|
|
@ -23,7 +23,7 @@ config OMAP_DEBUG_LEDS
|
|||
|
||||
config POWER_AVS_OMAP
|
||||
bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2"
|
||||
depends on POWER_AVS && (ARCH_OMAP3 || ARCH_OMAP4) && PM
|
||||
depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
|
||||
select POWER_SUPPLY
|
||||
help
|
||||
Say Y to enable AVS(Adaptive Voltage Scaling)
|
||||
|
|
|
@ -415,26 +415,45 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
|
|||
s64 elapsed_ns;
|
||||
int ret;
|
||||
|
||||
if (!genpd->power_on)
|
||||
return 0;
|
||||
/* Notify consumers that we are about to power on. */
|
||||
ret = raw_notifier_call_chain_robust(&genpd->power_notifiers,
|
||||
GENPD_NOTIFY_PRE_ON,
|
||||
GENPD_NOTIFY_OFF, NULL);
|
||||
ret = notifier_to_errno(ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!timed)
|
||||
return genpd->power_on(genpd);
|
||||
if (!genpd->power_on)
|
||||
goto out;
|
||||
|
||||
if (!timed) {
|
||||
ret = genpd->power_on(genpd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
time_start = ktime_get();
|
||||
ret = genpd->power_on(genpd);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
|
||||
if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
genpd->states[state_idx].power_on_latency_ns = elapsed_ns;
|
||||
genpd->max_off_time_changed = true;
|
||||
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
|
||||
genpd->name, "on", elapsed_ns);
|
||||
|
||||
out:
|
||||
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
|
||||
return 0;
|
||||
err:
|
||||
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
|
||||
NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -445,27 +464,46 @@ static int _genpd_power_off(struct generic_pm_domain *genpd, bool timed)
|
|||
s64 elapsed_ns;
|
||||
int ret;
|
||||
|
||||
if (!genpd->power_off)
|
||||
return 0;
|
||||
/* Notify consumers that we are about to power off. */
|
||||
ret = raw_notifier_call_chain_robust(&genpd->power_notifiers,
|
||||
GENPD_NOTIFY_PRE_OFF,
|
||||
GENPD_NOTIFY_ON, NULL);
|
||||
ret = notifier_to_errno(ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!timed)
|
||||
return genpd->power_off(genpd);
|
||||
if (!genpd->power_off)
|
||||
goto out;
|
||||
|
||||
if (!timed) {
|
||||
ret = genpd->power_off(genpd);
|
||||
if (ret)
|
||||
goto busy;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
time_start = ktime_get();
|
||||
ret = genpd->power_off(genpd);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto busy;
|
||||
|
||||
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
|
||||
if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
genpd->states[state_idx].power_off_latency_ns = elapsed_ns;
|
||||
genpd->max_off_time_changed = true;
|
||||
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
|
||||
genpd->name, "off", elapsed_ns);
|
||||
|
||||
out:
|
||||
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
|
||||
NULL);
|
||||
return 0;
|
||||
busy:
|
||||
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -550,11 +588,14 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
|
|||
return -EBUSY;
|
||||
|
||||
ret = _genpd_power_off(genpd, true);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
genpd->states[genpd->state_idx].rejected++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
genpd->status = GENPD_STATE_OFF;
|
||||
genpd_update_accounting(genpd);
|
||||
genpd->states[genpd->state_idx].usage++;
|
||||
|
||||
list_for_each_entry(link, &genpd->child_links, child_node) {
|
||||
genpd_sd_counter_dec(link->parent);
|
||||
|
@ -1270,13 +1311,14 @@ static int genpd_restore_noirq(struct device *dev)
|
|||
* first time for the given domain in the present cycle.
|
||||
*/
|
||||
genpd_lock(genpd);
|
||||
if (genpd->suspended_count++ == 0)
|
||||
if (genpd->suspended_count++ == 0) {
|
||||
/*
|
||||
* The boot kernel might put the domain into arbitrary state,
|
||||
* so make it appear as powered off to genpd_sync_power_on(),
|
||||
* so that it tries to power it on in case it was really off.
|
||||
*/
|
||||
genpd->status = GENPD_STATE_OFF;
|
||||
}
|
||||
|
||||
genpd_sync_power_on(genpd, true, 0);
|
||||
genpd_unlock(genpd);
|
||||
|
@ -1592,6 +1634,101 @@ int pm_genpd_remove_device(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
|
||||
|
||||
/**
|
||||
* dev_pm_genpd_add_notifier - Add a genpd power on/off notifier for @dev
|
||||
*
|
||||
* @dev: Device that should be associated with the notifier
|
||||
* @nb: The notifier block to register
|
||||
*
|
||||
* Users may call this function to add a genpd power on/off notifier for an
|
||||
* attached @dev. Only one notifier per device is allowed. The notifier is
|
||||
* sent when genpd is powering on/off the PM domain.
|
||||
*
|
||||
* It is assumed that the user guarantee that the genpd wouldn't be detached
|
||||
* while this routine is getting called.
|
||||
*
|
||||
* Returns 0 on success and negative error values on failures.
|
||||
*/
|
||||
int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
struct generic_pm_domain_data *gpd_data;
|
||||
int ret;
|
||||
|
||||
genpd = dev_to_genpd_safe(dev);
|
||||
if (!genpd)
|
||||
return -ENODEV;
|
||||
|
||||
if (WARN_ON(!dev->power.subsys_data ||
|
||||
!dev->power.subsys_data->domain_data))
|
||||
return -EINVAL;
|
||||
|
||||
gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
|
||||
if (gpd_data->power_nb)
|
||||
return -EEXIST;
|
||||
|
||||
genpd_lock(genpd);
|
||||
ret = raw_notifier_chain_register(&genpd->power_notifiers, nb);
|
||||
genpd_unlock(genpd);
|
||||
|
||||
if (ret) {
|
||||
dev_warn(dev, "failed to add notifier for PM domain %s\n",
|
||||
genpd->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpd_data->power_nb = nb;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_genpd_add_notifier);
|
||||
|
||||
/**
|
||||
* dev_pm_genpd_remove_notifier - Remove a genpd power on/off notifier for @dev
|
||||
*
|
||||
* @dev: Device that is associated with the notifier
|
||||
*
|
||||
* Users may call this function to remove a genpd power on/off notifier for an
|
||||
* attached @dev.
|
||||
*
|
||||
* It is assumed that the user guarantee that the genpd wouldn't be detached
|
||||
* while this routine is getting called.
|
||||
*
|
||||
* Returns 0 on success and negative error values on failures.
|
||||
*/
|
||||
int dev_pm_genpd_remove_notifier(struct device *dev)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
struct generic_pm_domain_data *gpd_data;
|
||||
int ret;
|
||||
|
||||
genpd = dev_to_genpd_safe(dev);
|
||||
if (!genpd)
|
||||
return -ENODEV;
|
||||
|
||||
if (WARN_ON(!dev->power.subsys_data ||
|
||||
!dev->power.subsys_data->domain_data))
|
||||
return -EINVAL;
|
||||
|
||||
gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
|
||||
if (!gpd_data->power_nb)
|
||||
return -ENODEV;
|
||||
|
||||
genpd_lock(genpd);
|
||||
ret = raw_notifier_chain_unregister(&genpd->power_notifiers,
|
||||
gpd_data->power_nb);
|
||||
genpd_unlock(genpd);
|
||||
|
||||
if (ret) {
|
||||
dev_warn(dev, "failed to remove notifier for PM domain %s\n",
|
||||
genpd->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpd_data->power_nb = NULL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_genpd_remove_notifier);
|
||||
|
||||
static int genpd_add_subdomain(struct generic_pm_domain *genpd,
|
||||
struct generic_pm_domain *subdomain)
|
||||
{
|
||||
|
@ -1762,6 +1899,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
|||
INIT_LIST_HEAD(&genpd->parent_links);
|
||||
INIT_LIST_HEAD(&genpd->child_links);
|
||||
INIT_LIST_HEAD(&genpd->dev_list);
|
||||
RAW_INIT_NOTIFIER_HEAD(&genpd->power_notifiers);
|
||||
genpd_lock_init(genpd);
|
||||
genpd->gov = gov;
|
||||
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
|
||||
|
@ -2923,7 +3061,7 @@ static int idle_states_show(struct seq_file *s, void *data)
|
|||
if (ret)
|
||||
return -ERESTARTSYS;
|
||||
|
||||
seq_puts(s, "State Time Spent(ms)\n");
|
||||
seq_puts(s, "State Time Spent(ms) Usage Rejected\n");
|
||||
|
||||
for (i = 0; i < genpd->state_count; i++) {
|
||||
ktime_t delta = 0;
|
||||
|
@ -2935,7 +3073,8 @@ static int idle_states_show(struct seq_file *s, void *data)
|
|||
|
||||
msecs = ktime_to_ms(
|
||||
ktime_add(genpd->states[i].idle_time, delta));
|
||||
seq_printf(s, "S%-13i %lld\n", i, msecs);
|
||||
seq_printf(s, "S%-13i %-14lld %-14llu %llu\n", i, msecs,
|
||||
genpd->states[i].usage, genpd->states[i].rejected);
|
||||
}
|
||||
|
||||
genpd_unlock(genpd);
|
||||
|
|
|
@ -363,7 +363,6 @@ static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
|
|||
case PM_EVENT_THAW:
|
||||
case PM_EVENT_RECOVER:
|
||||
return ops->thaw;
|
||||
break;
|
||||
case PM_EVENT_RESTORE:
|
||||
return ops->restore;
|
||||
#endif /* CONFIG_HIBERNATE_CALLBACKS */
|
||||
|
|
|
@ -691,7 +691,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
|||
cpumask_copy(policy->cpus, topology_core_cpumask(cpu));
|
||||
}
|
||||
|
||||
if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
|
||||
if (check_amd_hwpstate_cpu(cpu) && boot_cpu_data.x86 < 0x19 &&
|
||||
!acpi_pstate_strict) {
|
||||
cpumask_clear(policy->cpus);
|
||||
cpumask_set_cpu(cpu, policy->cpus);
|
||||
cpumask_copy(data->freqdomain_cpus,
|
||||
|
|
|
@ -1454,14 +1454,13 @@ static int cpufreq_online(unsigned int cpu)
|
|||
*/
|
||||
if ((cpufreq_driver->flags & CPUFREQ_NEED_INITIAL_FREQ_CHECK)
|
||||
&& has_target()) {
|
||||
unsigned int old_freq = policy->cur;
|
||||
|
||||
/* Are we running at unknown frequency ? */
|
||||
ret = cpufreq_frequency_table_get_index(policy, policy->cur);
|
||||
ret = cpufreq_frequency_table_get_index(policy, old_freq);
|
||||
if (ret == -EINVAL) {
|
||||
/* Warn user and fix it */
|
||||
pr_warn("%s: CPU%d: Running at unlisted freq: %u KHz\n",
|
||||
__func__, policy->cpu, policy->cur);
|
||||
ret = __cpufreq_driver_target(policy, policy->cur - 1,
|
||||
CPUFREQ_RELATION_L);
|
||||
ret = __cpufreq_driver_target(policy, old_freq - 1,
|
||||
CPUFREQ_RELATION_L);
|
||||
|
||||
/*
|
||||
* Reaching here after boot in a few seconds may not
|
||||
|
@ -1469,8 +1468,8 @@ static int cpufreq_online(unsigned int cpu)
|
|||
* frequency for longer duration. Hence, a BUG_ON().
|
||||
*/
|
||||
BUG_ON(ret);
|
||||
pr_warn("%s: CPU%d: Unlisted initial frequency changed to: %u KHz\n",
|
||||
__func__, policy->cpu, policy->cur);
|
||||
pr_info("%s: CPU%d: Running at unlisted initial frequency: %u KHz, changing to: %u KHz\n",
|
||||
__func__, policy->cpu, old_freq, policy->cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1420,6 +1420,24 @@ static void __init intel_pstate_sysfs_expose_params(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void __init intel_pstate_sysfs_remove(void)
|
||||
{
|
||||
if (!intel_pstate_kobject)
|
||||
return;
|
||||
|
||||
sysfs_remove_group(intel_pstate_kobject, &intel_pstate_attr_group);
|
||||
|
||||
if (!per_cpu_limits) {
|
||||
sysfs_remove_file(intel_pstate_kobject, &max_perf_pct.attr);
|
||||
sysfs_remove_file(intel_pstate_kobject, &min_perf_pct.attr);
|
||||
|
||||
if (x86_match_cpu(intel_pstate_cpu_ee_disable_ids))
|
||||
sysfs_remove_file(intel_pstate_kobject, &energy_efficiency.attr);
|
||||
}
|
||||
|
||||
kobject_put(intel_pstate_kobject);
|
||||
}
|
||||
|
||||
static void intel_pstate_sysfs_expose_hwp_dynamic_boost(void)
|
||||
{
|
||||
int rc;
|
||||
|
@ -3063,8 +3081,10 @@ static int __init intel_pstate_init(void)
|
|||
mutex_lock(&intel_pstate_driver_lock);
|
||||
rc = intel_pstate_register_driver(default_driver);
|
||||
mutex_unlock(&intel_pstate_driver_lock);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
intel_pstate_sysfs_remove();
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (hwp_active) {
|
||||
const struct x86_cpu_id *id;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* intel_idle is a cpuidle driver that loads on specific Intel processors
|
||||
* intel_idle is a cpuidle driver that loads on all Intel CPUs with MWAIT
|
||||
* in lieu of the legacy ACPI processor_idle driver. The intent is to
|
||||
* make Linux more efficient on these processors, as intel_idle knows
|
||||
* more than ACPI, as well as make Linux more immune to ACPI BIOS bugs.
|
||||
|
@ -20,7 +20,11 @@
|
|||
* All CPUs have same idle states as boot CPU
|
||||
*
|
||||
* Chipset BM_STS (bus master status) bit is a NOP
|
||||
* for preventing entry into deep C-stats
|
||||
* for preventing entry into deep C-states
|
||||
*
|
||||
* CPU will flush caches as needed when entering a C-state via MWAIT
|
||||
* (in contrast to entering ACPI C3, in which case the WBINVD
|
||||
* instruction needs to be executed to flush the caches)
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -1212,14 +1216,13 @@ static bool __init intel_idle_acpi_cst_extract(void)
|
|||
if (!intel_idle_cst_usable())
|
||||
continue;
|
||||
|
||||
if (!acpi_processor_claim_cst_control()) {
|
||||
acpi_state_table.count = 0;
|
||||
return false;
|
||||
}
|
||||
if (!acpi_processor_claim_cst_control())
|
||||
break;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
acpi_state_table.count = 0;
|
||||
pr_debug("ACPI _CST not found or not usable\n");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
source "drivers/power/avs/Kconfig"
|
||||
source "drivers/power/reset/Kconfig"
|
||||
source "drivers/power/supply/Kconfig"
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_POWER_AVS) += avs/
|
||||
obj-$(CONFIG_POWER_RESET) += reset/
|
||||
obj-$(CONFIG_POWER_SUPPLY) += supply/
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menuconfig POWER_AVS
|
||||
bool "Adaptive Voltage Scaling class support"
|
||||
help
|
||||
AVS is a power management technique which finely controls the
|
||||
operating voltage of a device in order to optimize (i.e. reduce)
|
||||
its power consumption.
|
||||
At a given operating point the voltage is adapted depending on
|
||||
static factors (chip manufacturing process) and dynamic factors
|
||||
(temperature depending performance).
|
||||
AVS is also called SmartReflex on OMAP devices.
|
||||
|
||||
Say Y here to enable Adaptive Voltage Scaling class support.
|
||||
|
||||
config QCOM_CPR
|
||||
tristate "QCOM Core Power Reduction (CPR) support"
|
||||
depends on POWER_AVS && HAS_IOMEM
|
||||
select PM_OPP
|
||||
select REGMAP
|
||||
help
|
||||
Say Y here to enable support for the CPR hardware found on Qualcomm
|
||||
SoCs like QCS404.
|
||||
|
||||
This driver populates CPU OPPs tables and makes adjustments to the
|
||||
tables based on feedback from the CPR hardware. If you want to do
|
||||
CPUfrequency scaling say Y here.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called qcom-cpr
|
||||
|
||||
config ROCKCHIP_IODOMAIN
|
||||
tristate "Rockchip IO domain support"
|
||||
depends on POWER_AVS && ARCH_ROCKCHIP && OF
|
||||
help
|
||||
Say y here to enable support io domains on Rockchip SoCs. It is
|
||||
necessary for the io domain setting of the SoC to match the
|
||||
voltage supplied by the regulators.
|
|
@ -1,4 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o
|
||||
obj-$(CONFIG_QCOM_CPR) += qcom-cpr.o
|
||||
obj-$(CONFIG_ROCKCHIP_IODOMAIN) += rockchip-io-domain.o
|
|
@ -30,7 +30,7 @@ config INTEL_RAPL
|
|||
|
||||
In RAPL, the platform level settings are divided into domains for
|
||||
fine grained control. These domains include processor package, DRAM
|
||||
controller, CPU core (Power Plance 0), graphics uncore (Power Plane
|
||||
controller, CPU core (Power Plane 0), graphics uncore (Power Plane
|
||||
1), etc.
|
||||
|
||||
config IDLE_INJECT
|
||||
|
|
|
@ -544,7 +544,14 @@ static void rapl_init_domains(struct rapl_package *rp)
|
|||
continue;
|
||||
|
||||
rd->rp = rp;
|
||||
rd->name = rapl_domain_names[i];
|
||||
|
||||
if (i == RAPL_DOMAIN_PLATFORM && rp->id > 0) {
|
||||
snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "psys-%d",
|
||||
cpu_data(rp->lead_cpu).phys_proc_id);
|
||||
} else
|
||||
snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "%s",
|
||||
rapl_domain_names[i]);
|
||||
|
||||
rd->id = i;
|
||||
rd->rpl[0].prim_id = PL1_ENABLE;
|
||||
rd->rpl[0].name = pl1_name;
|
||||
|
@ -1112,13 +1119,17 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
|
|||
}
|
||||
/* now register domains as children of the socket/package */
|
||||
for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
|
||||
struct powercap_zone *parent = rp->power_zone;
|
||||
|
||||
if (rd->id == RAPL_DOMAIN_PACKAGE)
|
||||
continue;
|
||||
if (rd->id == RAPL_DOMAIN_PLATFORM)
|
||||
parent = NULL;
|
||||
/* number of power limits per domain varies */
|
||||
nr_pl = find_nr_power_limit(rd);
|
||||
power_zone = powercap_register_zone(&rd->power_zone,
|
||||
rp->priv->control_type,
|
||||
rd->name, rp->power_zone,
|
||||
rd->name, parent,
|
||||
&zone_ops[rd->id], nr_pl,
|
||||
&constraint_ops);
|
||||
|
||||
|
@ -1145,67 +1156,6 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int rapl_add_platform_domain(struct rapl_if_priv *priv)
|
||||
{
|
||||
struct rapl_domain *rd;
|
||||
struct powercap_zone *power_zone;
|
||||
struct reg_action ra;
|
||||
int ret;
|
||||
|
||||
ra.reg = priv->regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_STATUS];
|
||||
ra.mask = ~0;
|
||||
ret = priv->read_raw(0, &ra);
|
||||
if (ret || !ra.value)
|
||||
return -ENODEV;
|
||||
|
||||
ra.reg = priv->regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_LIMIT];
|
||||
ra.mask = ~0;
|
||||
ret = priv->read_raw(0, &ra);
|
||||
if (ret || !ra.value)
|
||||
return -ENODEV;
|
||||
|
||||
rd = kzalloc(sizeof(*rd), GFP_KERNEL);
|
||||
if (!rd)
|
||||
return -ENOMEM;
|
||||
|
||||
rd->name = rapl_domain_names[RAPL_DOMAIN_PLATFORM];
|
||||
rd->id = RAPL_DOMAIN_PLATFORM;
|
||||
rd->regs[RAPL_DOMAIN_REG_LIMIT] =
|
||||
priv->regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_LIMIT];
|
||||
rd->regs[RAPL_DOMAIN_REG_STATUS] =
|
||||
priv->regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_STATUS];
|
||||
rd->rpl[0].prim_id = PL1_ENABLE;
|
||||
rd->rpl[0].name = pl1_name;
|
||||
rd->rpl[1].prim_id = PL2_ENABLE;
|
||||
rd->rpl[1].name = pl2_name;
|
||||
rd->rp = rapl_find_package_domain(0, priv);
|
||||
|
||||
power_zone = powercap_register_zone(&rd->power_zone, priv->control_type,
|
||||
"psys", NULL,
|
||||
&zone_ops[RAPL_DOMAIN_PLATFORM],
|
||||
2, &constraint_ops);
|
||||
|
||||
if (IS_ERR(power_zone)) {
|
||||
kfree(rd);
|
||||
return PTR_ERR(power_zone);
|
||||
}
|
||||
|
||||
priv->platform_rapl_domain = rd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rapl_add_platform_domain);
|
||||
|
||||
void rapl_remove_platform_domain(struct rapl_if_priv *priv)
|
||||
{
|
||||
if (priv->platform_rapl_domain) {
|
||||
powercap_unregister_zone(priv->control_type,
|
||||
&priv->platform_rapl_domain->power_zone);
|
||||
kfree(priv->platform_rapl_domain);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rapl_remove_platform_domain);
|
||||
|
||||
static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
|
||||
{
|
||||
struct reg_action ra;
|
||||
|
@ -1215,11 +1165,9 @@ static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
|
|||
case RAPL_DOMAIN_PP0:
|
||||
case RAPL_DOMAIN_PP1:
|
||||
case RAPL_DOMAIN_DRAM:
|
||||
case RAPL_DOMAIN_PLATFORM:
|
||||
ra.reg = rp->priv->regs[domain][RAPL_DOMAIN_REG_STATUS];
|
||||
break;
|
||||
case RAPL_DOMAIN_PLATFORM:
|
||||
/* PSYS(PLATFORM) is not a CPU domain, so avoid printng error */
|
||||
return -EINVAL;
|
||||
default:
|
||||
pr_err("invalid domain id %d\n", domain);
|
||||
return -EINVAL;
|
||||
|
@ -1228,7 +1176,7 @@ static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
|
|||
* values, otherwise skip it.
|
||||
*/
|
||||
|
||||
ra.mask = ~0;
|
||||
ra.mask = ENERGY_STATUS_MASK;
|
||||
if (rp->priv->read_raw(cpu, &ra) || !ra.value)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ static struct rapl_if_priv rapl_msr_priv = {
|
|||
.regs[RAPL_DOMAIN_PLATFORM] = {
|
||||
MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0},
|
||||
.limits[RAPL_DOMAIN_PACKAGE] = 2,
|
||||
.limits[RAPL_DOMAIN_PLATFORM] = 2,
|
||||
};
|
||||
|
||||
/* Handles CPU hotplug on multi-socket systems.
|
||||
|
@ -157,9 +158,6 @@ static int rapl_msr_probe(struct platform_device *pdev)
|
|||
goto out;
|
||||
rapl_msr_priv.pcap_rapl_online = ret;
|
||||
|
||||
/* Don't bail out if PSys is not supported */
|
||||
rapl_add_platform_domain(&rapl_msr_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
|
@ -171,7 +169,6 @@ static int rapl_msr_probe(struct platform_device *pdev)
|
|||
static int rapl_msr_remove(struct platform_device *pdev)
|
||||
{
|
||||
cpuhp_remove_state(rapl_msr_priv.pcap_rapl_online);
|
||||
rapl_remove_platform_domain(&rapl_msr_priv);
|
||||
powercap_unregister_control_type(rapl_msr_priv.control_type);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,22 @@ config QCOM_COMMAND_DB
|
|||
resource on a RPM-hardened platform must use this database to get
|
||||
SoC specific identifier and information for the shared resources.
|
||||
|
||||
config QCOM_CPR
|
||||
tristate "QCOM Core Power Reduction (CPR) support"
|
||||
depends on ARCH_QCOM && HAS_IOMEM
|
||||
select PM_OPP
|
||||
select REGMAP
|
||||
help
|
||||
Say Y here to enable support for the CPR hardware found on Qualcomm
|
||||
SoCs like QCS404.
|
||||
|
||||
This driver populates CPU OPPs tables and makes adjustments to the
|
||||
tables based on feedback from the CPR hardware. If you want to do
|
||||
CPUfrequency scaling say Y here.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called qcom-cpr
|
||||
|
||||
config QCOM_GENI_SE
|
||||
tristate "QCOM GENI Serial Engine Driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
|
|
|
@ -3,6 +3,7 @@ CFLAGS_rpmh-rsc.o := -I$(src)
|
|||
obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
|
||||
obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
|
||||
obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
|
||||
obj-$(CONFIG_QCOM_CPR) += cpr.o
|
||||
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
|
||||
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
|
||||
obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
|
||||
|
|
|
@ -14,6 +14,14 @@ config ROCKCHIP_GRF
|
|||
In a lot of cases there also need to be default settings initialized
|
||||
to make some of them conform to expectations of the kernel.
|
||||
|
||||
config ROCKCHIP_IODOMAIN
|
||||
tristate "Rockchip IO domain support"
|
||||
depends on OF
|
||||
help
|
||||
Say y here to enable support io domains on Rockchip SoCs. It is
|
||||
necessary for the io domain setting of the SoC to match the
|
||||
voltage supplied by the regulators.
|
||||
|
||||
config ROCKCHIP_PM_DOMAINS
|
||||
bool "Rockchip generic power domain"
|
||||
depends on PM
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
# Rockchip Soc drivers
|
||||
#
|
||||
obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
|
||||
obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o
|
||||
obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
|
||||
|
|
|
@ -12,3 +12,4 @@ obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
|
|||
obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o
|
||||
obj-$(CONFIG_TI_K3_RINGACC) += k3-ringacc.o
|
||||
obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o
|
||||
obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o
|
||||
|
|
|
@ -271,13 +271,8 @@ struct cpuidle_governor {
|
|||
void (*reflect) (struct cpuidle_device *dev, int index);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CPU_IDLE
|
||||
extern int cpuidle_register_governor(struct cpuidle_governor *gov);
|
||||
extern s64 cpuidle_governor_latency_req(unsigned int cpu);
|
||||
#else
|
||||
static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
|
||||
{return 0;}
|
||||
#endif
|
||||
|
||||
#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, \
|
||||
idx, \
|
||||
|
|
|
@ -79,8 +79,10 @@ struct rapl_power_limit {
|
|||
|
||||
struct rapl_package;
|
||||
|
||||
#define RAPL_DOMAIN_NAME_LENGTH 16
|
||||
|
||||
struct rapl_domain {
|
||||
const char *name;
|
||||
char name[RAPL_DOMAIN_NAME_LENGTH];
|
||||
enum rapl_domain_type id;
|
||||
u64 regs[RAPL_DOMAIN_REG_MAX];
|
||||
struct powercap_zone power_zone;
|
||||
|
@ -152,7 +154,4 @@ struct rapl_package *rapl_find_package_domain(int cpu, struct rapl_if_priv *priv
|
|||
struct rapl_package *rapl_add_package(int cpu, struct rapl_if_priv *priv);
|
||||
void rapl_remove_package(struct rapl_package *rp);
|
||||
|
||||
int rapl_add_platform_domain(struct rapl_if_priv *priv);
|
||||
void rapl_remove_platform_domain(struct rapl_if_priv *priv);
|
||||
|
||||
#endif /* __INTEL_RAPL_H__ */
|
||||
|
|
|
@ -68,6 +68,13 @@ enum gpd_status {
|
|||
GENPD_STATE_OFF, /* PM domain is off */
|
||||
};
|
||||
|
||||
enum genpd_notication {
|
||||
GENPD_NOTIFY_PRE_OFF = 0,
|
||||
GENPD_NOTIFY_OFF,
|
||||
GENPD_NOTIFY_PRE_ON,
|
||||
GENPD_NOTIFY_ON,
|
||||
};
|
||||
|
||||
struct dev_power_governor {
|
||||
bool (*power_down_ok)(struct dev_pm_domain *domain);
|
||||
bool (*suspend_ok)(struct device *dev);
|
||||
|
@ -82,6 +89,8 @@ struct genpd_power_state {
|
|||
s64 power_off_latency_ns;
|
||||
s64 power_on_latency_ns;
|
||||
s64 residency_ns;
|
||||
u64 usage;
|
||||
u64 rejected;
|
||||
struct fwnode_handle *fwnode;
|
||||
ktime_t idle_time;
|
||||
void *data;
|
||||
|
@ -112,6 +121,7 @@ struct generic_pm_domain {
|
|||
cpumask_var_t cpus; /* A cpumask of the attached CPUs */
|
||||
int (*power_off)(struct generic_pm_domain *domain);
|
||||
int (*power_on)(struct generic_pm_domain *domain);
|
||||
struct raw_notifier_head power_notifiers; /* Power on/off notifiers */
|
||||
struct opp_table *opp_table; /* OPP table of the genpd */
|
||||
unsigned int (*opp_to_performance_state)(struct generic_pm_domain *genpd,
|
||||
struct dev_pm_opp *opp);
|
||||
|
@ -178,6 +188,7 @@ struct generic_pm_domain_data {
|
|||
struct pm_domain_data base;
|
||||
struct gpd_timing_data td;
|
||||
struct notifier_block nb;
|
||||
struct notifier_block *power_nb;
|
||||
int cpu;
|
||||
unsigned int performance_state;
|
||||
void *data;
|
||||
|
@ -204,6 +215,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
|||
struct dev_power_governor *gov, bool is_off);
|
||||
int pm_genpd_remove(struct generic_pm_domain *genpd);
|
||||
int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state);
|
||||
int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb);
|
||||
int dev_pm_genpd_remove_notifier(struct device *dev);
|
||||
|
||||
extern struct dev_power_governor simple_qos_governor;
|
||||
extern struct dev_power_governor pm_domain_always_on_gov;
|
||||
|
@ -251,6 +264,17 @@ static inline int dev_pm_genpd_set_performance_state(struct device *dev,
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_genpd_add_notifier(struct device *dev,
|
||||
struct notifier_block *nb)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_genpd_remove_notifier(struct device *dev)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
#define simple_qos_governor (*(struct dev_power_governor *)(NULL))
|
||||
#define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL))
|
||||
#endif
|
||||
|
|
|
@ -479,7 +479,7 @@ static inline int pm_runtime_set_active(struct device *dev)
|
|||
}
|
||||
|
||||
/**
|
||||
* pm_runtime_set_suspended - Set runtime PM status to "active".
|
||||
* pm_runtime_set_suspended - Set runtime PM status to "suspended".
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Set the runtime PM status of @dev to %RPM_SUSPENDED and ensure that
|
||||
|
|
|
@ -441,6 +441,7 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
|
|||
unsigned long util, max;
|
||||
unsigned int next_f;
|
||||
bool busy;
|
||||
unsigned int cached_freq = sg_policy->cached_raw_freq;
|
||||
|
||||
sugov_iowait_boost(sg_cpu, time, flags);
|
||||
sg_cpu->last_update = time;
|
||||
|
@ -464,8 +465,8 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
|
|||
if (busy && next_f < sg_policy->next_freq) {
|
||||
next_f = sg_policy->next_freq;
|
||||
|
||||
/* Reset cached freq as next_freq has changed */
|
||||
sg_policy->cached_raw_freq = 0;
|
||||
/* Restore cached freq as next_freq has changed */
|
||||
sg_policy->cached_raw_freq = cached_freq;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -51,7 +51,7 @@ DESTDIR ?=
|
|||
# Package-related definitions. Distributions can modify the version
|
||||
# and _should_ modify the PACKAGE_BUGREPORT definition
|
||||
|
||||
VERSION= $(shell ./utils/version-gen.sh)
|
||||
VERSION:= $(shell ./utils/version-gen.sh)
|
||||
LIB_MAJ= 0.0.1
|
||||
LIB_MIN= 0
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ int main (void)
|
|||
printf("\tsmi_cmd=0x?? smi_port=0x?? smi_sig=1\n");
|
||||
printf("\nUnfortunately, you have to know what exactly are "
|
||||
"smi_cmd and smi_port, and this\nis system "
|
||||
"dependant.\n");
|
||||
"dependent.\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user