mirror of https://gitee.com/openkylin/linux.git
Merge branch 'pm-cpuidle'
* pm-cpuidle: cpuidle: Fix three reference count leaks cpuidle: Convert Qualcomm SPM driver to a generic CPUidle driver Documentation: ABI: make current_governer_ro as a candidate for removal Documentation: cpuidle: update the document cpuidle: sysfs: Remove sysfs_switch and switch attributes cpuidle: Make cpuidle governor switchable to be the default behaviour cpuidle: sysfs: Accept governor name with 15 characters cpuidle: sysfs: Fix the overlap for showing available governors cpuidle: psci: Fixup execution order when entering a domain idle state cpuidle: sysfs: Minor coding style corrections cpuidle: sysfs: Remove the unused define_one_r(o/w) macros
This commit is contained in:
commit
f1ecbf7955
|
@ -0,0 +1,9 @@
|
|||
What: /sys/devices/system/cpu/cpuidle/current_governor_ro
|
||||
Date: April, 2020
|
||||
Contact: linux-pm@vger.kernel.org
|
||||
Description:
|
||||
current_governor_ro shows current using cpuidle governor, but read only.
|
||||
with the update that cpuidle governor can be changed at runtime in default,
|
||||
both current_governor and current_governor_ro co-exist under
|
||||
/sys/devices/system/cpu/cpuidle/ file, it's duplicate so make
|
||||
current_governor_ro obselete.
|
|
@ -106,10 +106,10 @@ Description: CPU topology files that describe a logical CPU's relationship
|
|||
See Documentation/admin-guide/cputopology.rst for more information.
|
||||
|
||||
|
||||
What: /sys/devices/system/cpu/cpuidle/current_driver
|
||||
/sys/devices/system/cpu/cpuidle/current_governer_ro
|
||||
/sys/devices/system/cpu/cpuidle/available_governors
|
||||
What: /sys/devices/system/cpu/cpuidle/available_governors
|
||||
/sys/devices/system/cpu/cpuidle/current_driver
|
||||
/sys/devices/system/cpu/cpuidle/current_governor
|
||||
/sys/devices/system/cpu/cpuidle/current_governer_ro
|
||||
Date: September 2007
|
||||
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
Description: Discover cpuidle policy and mechanism
|
||||
|
@ -119,24 +119,18 @@ Description: Discover cpuidle policy and mechanism
|
|||
consumption during idle.
|
||||
|
||||
Idle policy (governor) is differentiated from idle mechanism
|
||||
(driver)
|
||||
|
||||
current_driver: (RO) displays current idle mechanism
|
||||
|
||||
current_governor_ro: (RO) displays current idle policy
|
||||
|
||||
With the cpuidle_sysfs_switch boot option enabled (meant for
|
||||
developer testing), the following three attributes are visible
|
||||
instead:
|
||||
|
||||
current_driver: same as described above
|
||||
(driver).
|
||||
|
||||
available_governors: (RO) displays a space separated list of
|
||||
available governors
|
||||
available governors.
|
||||
|
||||
current_driver: (RO) displays current idle mechanism.
|
||||
|
||||
current_governor: (RW) displays current idle policy. Users can
|
||||
switch the governor at runtime by writing to this file.
|
||||
|
||||
current_governor_ro: (RO) displays current idle policy.
|
||||
|
||||
See Documentation/admin-guide/pm/cpuidle.rst and
|
||||
Documentation/driver-api/pm/cpuidle.rst for more information.
|
||||
|
||||
|
|
|
@ -159,17 +159,15 @@ governor uses that information depends on what algorithm is implemented by it
|
|||
and that is the primary reason for having more than one governor in the
|
||||
``CPUIdle`` subsystem.
|
||||
|
||||
There are three ``CPUIdle`` governors available, ``menu``, `TEO <teo-gov_>`_
|
||||
and ``ladder``. Which of them is used by default depends on the configuration
|
||||
of the kernel and in particular on whether or not the scheduler tick can be
|
||||
`stopped by the idle loop <idle-cpus-and-tick_>`_. It is possible to change the
|
||||
governor at run time if the ``cpuidle_sysfs_switch`` command line parameter has
|
||||
been passed to the kernel, but that is not safe in general, so it should not be
|
||||
done on production systems (that may change in the future, though). The name of
|
||||
the ``CPUIdle`` governor currently used by the kernel can be read from the
|
||||
:file:`current_governor_ro` (or :file:`current_governor` if
|
||||
``cpuidle_sysfs_switch`` is present in the kernel command line) file under
|
||||
:file:`/sys/devices/system/cpu/cpuidle/` in ``sysfs``.
|
||||
There are four ``CPUIdle`` governors available, ``menu``, `TEO <teo-gov_>`_,
|
||||
``ladder`` and ``haltpoll``. Which of them is used by default depends on the
|
||||
configuration of the kernel and in particular on whether or not the scheduler
|
||||
tick can be `stopped by the idle loop <idle-cpus-and-tick_>`_. Available
|
||||
governors can be read from the :file:`available_governors`, and the governor
|
||||
can be changed at runtime. The name of the ``CPUIdle`` governor currently
|
||||
used by the kernel can be read from the :file:`current_governor_ro` or
|
||||
:file:`current_governor` file under :file:`/sys/devices/system/cpu/cpuidle/`
|
||||
in ``sysfs``.
|
||||
|
||||
Which ``CPUIdle`` driver is used, on the other hand, usually depends on the
|
||||
platform the kernel is running on, but there are platforms with more than one
|
||||
|
|
|
@ -68,9 +68,8 @@ only one in the list (that is, the list was empty before) or the value of its
|
|||
governor currently in use, or the name of the new governor was passed to the
|
||||
kernel as the value of the ``cpuidle.governor=`` command line parameter, the new
|
||||
governor will be used from that point on (there can be only one ``CPUIdle``
|
||||
governor in use at a time). Also, if ``cpuidle_sysfs_switch`` is passed to the
|
||||
kernel in the command line, user space can choose the ``CPUIdle`` governor to
|
||||
use at run time via ``sysfs``.
|
||||
governor in use at a time). Also, user space can choose the ``CPUIdle``
|
||||
governor to use at run time via ``sysfs``.
|
||||
|
||||
Once registered, ``CPUIdle`` governors cannot be unregistered, so it is not
|
||||
practical to put them into loadable kernel modules.
|
||||
|
|
|
@ -2225,6 +2225,7 @@ F: drivers/*/qcom*
|
|||
F: drivers/*/qcom/
|
||||
F: drivers/bluetooth/btqcomsmd.c
|
||||
F: drivers/clocksource/timer-qcom.c
|
||||
F: drivers/cpuidle/cpuidle-qcom-spm.c
|
||||
F: drivers/extcon/extcon-qcom*
|
||||
F: drivers/i2c/busses/i2c-qcom-geni.c
|
||||
F: drivers/i2c/busses/i2c-qup.c
|
||||
|
|
|
@ -94,3 +94,16 @@ config ARM_TEGRA_CPUIDLE
|
|||
select ARM_CPU_SUSPEND
|
||||
help
|
||||
Select this to enable cpuidle for NVIDIA Tegra20/30/114/124 SoCs.
|
||||
|
||||
config ARM_QCOM_SPM_CPUIDLE
|
||||
bool "CPU Idle Driver for Qualcomm Subsystem Power Manager (SPM)"
|
||||
depends on (ARCH_QCOM || COMPILE_TEST) && !ARM64
|
||||
select ARM_CPU_SUSPEND
|
||||
select CPU_IDLE_MULTIPLE_DRIVERS
|
||||
select DT_IDLE_STATES
|
||||
select QCOM_SCM
|
||||
help
|
||||
Select this to enable cpuidle for Qualcomm processors.
|
||||
The Subsystem Power Manager (SPM) controls low power modes for the
|
||||
CPU and L2 cores. It interface with various system drivers to put
|
||||
the cores in low power modes.
|
||||
|
|
|
@ -25,6 +25,7 @@ obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle_psci.o
|
|||
cpuidle_psci-y := cpuidle-psci.o
|
||||
cpuidle_psci-$(CONFIG_PM_GENERIC_DOMAINS_OF) += cpuidle-psci-domain.o
|
||||
obj-$(CONFIG_ARM_TEGRA_CPUIDLE) += cpuidle-tegra.o
|
||||
obj-$(CONFIG_ARM_QCOM_SPM_CPUIDLE) += cpuidle-qcom-spm.o
|
||||
|
||||
###############################################################################
|
||||
# MIPS drivers
|
||||
|
|
|
@ -58,6 +58,10 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
|
|||
u32 state;
|
||||
int ret;
|
||||
|
||||
ret = cpu_pm_enter();
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
/* Do runtime PM to manage a hierarchical CPU toplogy. */
|
||||
pm_runtime_put_sync_suspend(pd_dev);
|
||||
|
||||
|
@ -65,10 +69,12 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
|
|||
if (!state)
|
||||
state = states[idx];
|
||||
|
||||
ret = psci_enter_state(idx, state);
|
||||
ret = psci_cpu_suspend_enter(state) ? -1 : idx;
|
||||
|
||||
pm_runtime_get_sync(pd_dev);
|
||||
|
||||
cpu_pm_exit();
|
||||
|
||||
/* Clear the domain state to start fresh when back from idle. */
|
||||
psci_set_domain_state(0);
|
||||
return ret;
|
||||
|
|
|
@ -19,10 +19,11 @@
|
|||
#include <linux/cpu_pm.h>
|
||||
#include <linux/qcom_scm.h>
|
||||
|
||||
#include <asm/cpuidle.h>
|
||||
#include <asm/proc-fns.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include "dt_idle_states.h"
|
||||
|
||||
#define MAX_PMIC_DATA 2
|
||||
#define MAX_SEQ_DATA 64
|
||||
#define SPM_CTL_INDEX 0x7f
|
||||
|
@ -62,6 +63,7 @@ struct spm_reg_data {
|
|||
};
|
||||
|
||||
struct spm_driver_data {
|
||||
struct cpuidle_driver cpuidle_driver;
|
||||
void __iomem *reg_base;
|
||||
const struct spm_reg_data *reg_data;
|
||||
};
|
||||
|
@ -107,11 +109,6 @@ static const struct spm_reg_data spm_reg_8064_cpu = {
|
|||
.start_index[PM_SLEEP_MODE_SPC] = 2,
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct spm_driver_data *, cpu_spm_drv);
|
||||
|
||||
typedef int (*idle_fn)(void);
|
||||
static DEFINE_PER_CPU(idle_fn*, qcom_idle_ops);
|
||||
|
||||
static inline void spm_register_write(struct spm_driver_data *drv,
|
||||
enum spm_reg reg, u32 val)
|
||||
{
|
||||
|
@ -172,10 +169,9 @@ static int qcom_pm_collapse(unsigned long int unused)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int qcom_cpu_spc(void)
|
||||
static int qcom_cpu_spc(struct spm_driver_data *drv)
|
||||
{
|
||||
int ret;
|
||||
struct spm_driver_data *drv = __this_cpu_read(cpu_spm_drv);
|
||||
|
||||
spm_set_low_power_mode(drv, PM_SLEEP_MODE_SPC);
|
||||
ret = cpu_suspend(0, qcom_pm_collapse);
|
||||
|
@ -190,94 +186,49 @@ static int qcom_cpu_spc(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_idle_enter(unsigned long index)
|
||||
static int spm_enter_idle_state(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int idx)
|
||||
{
|
||||
return __this_cpu_read(qcom_idle_ops)[index]();
|
||||
struct spm_driver_data *data = container_of(drv, struct spm_driver_data,
|
||||
cpuidle_driver);
|
||||
|
||||
return CPU_PM_CPU_IDLE_ENTER_PARAM(qcom_cpu_spc, idx, data);
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_idle_state_match[] __initconst = {
|
||||
{ .compatible = "qcom,idle-state-spc", .data = qcom_cpu_spc },
|
||||
static struct cpuidle_driver qcom_spm_idle_driver = {
|
||||
.name = "qcom_spm",
|
||||
.owner = THIS_MODULE,
|
||||
.states[0] = {
|
||||
.enter = spm_enter_idle_state,
|
||||
.exit_latency = 1,
|
||||
.target_residency = 1,
|
||||
.power_usage = UINT_MAX,
|
||||
.name = "WFI",
|
||||
.desc = "ARM WFI",
|
||||
}
|
||||
};
|
||||
|
||||
static const struct of_device_id qcom_idle_state_match[] = {
|
||||
{ .compatible = "qcom,idle-state-spc", .data = spm_enter_idle_state },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int __init qcom_cpuidle_init(struct device_node *cpu_node, int cpu)
|
||||
static int spm_cpuidle_init(struct cpuidle_driver *drv, int cpu)
|
||||
{
|
||||
const struct of_device_id *match_id;
|
||||
struct device_node *state_node;
|
||||
int i;
|
||||
int state_count = 1;
|
||||
idle_fn idle_fns[CPUIDLE_STATE_MAX];
|
||||
idle_fn *fns;
|
||||
cpumask_t mask;
|
||||
bool use_scm_power_down = false;
|
||||
int ret;
|
||||
|
||||
if (!qcom_scm_is_available())
|
||||
return -EPROBE_DEFER;
|
||||
memcpy(drv, &qcom_spm_idle_driver, sizeof(*drv));
|
||||
drv->cpumask = (struct cpumask *)cpumask_of(cpu);
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
|
||||
if (!state_node)
|
||||
break;
|
||||
/* Parse idle states from device tree */
|
||||
ret = dt_init_idle_driver(drv, qcom_idle_state_match, 1);
|
||||
if (ret <= 0)
|
||||
return ret ? : -ENODEV;
|
||||
|
||||
if (!of_device_is_available(state_node))
|
||||
continue;
|
||||
|
||||
if (i == CPUIDLE_STATE_MAX) {
|
||||
pr_warn("%s: cpuidle states reached max possible\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
|
||||
match_id = of_match_node(qcom_idle_state_match, state_node);
|
||||
if (!match_id)
|
||||
return -ENODEV;
|
||||
|
||||
idle_fns[state_count] = match_id->data;
|
||||
|
||||
/* Check if any of the states allow power down */
|
||||
if (match_id->data == qcom_cpu_spc)
|
||||
use_scm_power_down = true;
|
||||
|
||||
state_count++;
|
||||
}
|
||||
|
||||
if (state_count == 1)
|
||||
goto check_spm;
|
||||
|
||||
fns = devm_kcalloc(get_cpu_device(cpu), state_count, sizeof(*fns),
|
||||
GFP_KERNEL);
|
||||
if (!fns)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 1; i < state_count; i++)
|
||||
fns[i] = idle_fns[i];
|
||||
|
||||
if (use_scm_power_down) {
|
||||
/* We have atleast one power down mode */
|
||||
cpumask_clear(&mask);
|
||||
cpumask_set_cpu(cpu, &mask);
|
||||
qcom_scm_set_warm_boot_addr(cpu_resume_arm, &mask);
|
||||
}
|
||||
|
||||
per_cpu(qcom_idle_ops, cpu) = fns;
|
||||
|
||||
/*
|
||||
* SPM probe for the cpu should have happened by now, if the
|
||||
* SPM device does not exist, return -ENXIO to indicate that the
|
||||
* cpu does not support idle states.
|
||||
*/
|
||||
check_spm:
|
||||
return per_cpu(cpu_spm_drv, cpu) ? 0 : -ENXIO;
|
||||
/* We have atleast one power down mode */
|
||||
return qcom_scm_set_warm_boot_addr(cpu_resume_arm, drv->cpumask);
|
||||
}
|
||||
|
||||
static const struct cpuidle_ops qcom_cpuidle_ops __initconst = {
|
||||
.suspend = qcom_idle_enter,
|
||||
.init = qcom_cpuidle_init,
|
||||
};
|
||||
|
||||
CPUIDLE_METHOD_OF_DECLARE(qcom_idle_v1, "qcom,kpss-acc-v1", &qcom_cpuidle_ops);
|
||||
CPUIDLE_METHOD_OF_DECLARE(qcom_idle_v2, "qcom,kpss-acc-v2", &qcom_cpuidle_ops);
|
||||
|
||||
static struct spm_driver_data *spm_get_drv(struct platform_device *pdev,
|
||||
int *spm_cpu)
|
||||
{
|
||||
|
@ -323,11 +274,15 @@ static int spm_dev_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
const struct of_device_id *match_id;
|
||||
void __iomem *addr;
|
||||
int cpu;
|
||||
int cpu, ret;
|
||||
|
||||
if (!qcom_scm_is_available())
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
drv = spm_get_drv(pdev, &cpu);
|
||||
if (!drv)
|
||||
return -EINVAL;
|
||||
platform_set_drvdata(pdev, drv);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
drv->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
@ -340,6 +295,10 @@ static int spm_dev_probe(struct platform_device *pdev)
|
|||
|
||||
drv->reg_data = match_id->data;
|
||||
|
||||
ret = spm_cpuidle_init(&drv->cpuidle_driver, cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Write the SPM sequences first.. */
|
||||
addr = drv->reg_base + drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY];
|
||||
__iowrite32_copy(addr, drv->reg_data->seq,
|
||||
|
@ -362,13 +321,20 @@ static int spm_dev_probe(struct platform_device *pdev)
|
|||
/* Set up Standby as the default low power mode */
|
||||
spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY);
|
||||
|
||||
per_cpu(cpu_spm_drv, cpu) = drv;
|
||||
return cpuidle_register(&drv->cpuidle_driver, NULL);
|
||||
}
|
||||
|
||||
static int spm_dev_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spm_driver_data *drv = platform_get_drvdata(pdev);
|
||||
|
||||
cpuidle_unregister(&drv->cpuidle_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver spm_driver = {
|
||||
.probe = spm_dev_probe,
|
||||
.remove = spm_dev_remove,
|
||||
.driver = {
|
||||
.name = "saw",
|
||||
.of_match_table = spm_match_table,
|
|
@ -18,14 +18,6 @@
|
|||
|
||||
#include "cpuidle.h"
|
||||
|
||||
static unsigned int sysfs_switch;
|
||||
static int __init cpuidle_sysfs_setup(char *unused)
|
||||
{
|
||||
sysfs_switch = 1;
|
||||
return 1;
|
||||
}
|
||||
__setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
|
||||
|
||||
static ssize_t show_available_governors(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
|
@ -35,10 +27,10 @@ static ssize_t show_available_governors(struct device *dev,
|
|||
|
||||
mutex_lock(&cpuidle_lock);
|
||||
list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
|
||||
if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) -
|
||||
CPUIDLE_NAME_LEN - 2))
|
||||
if (i >= (ssize_t) (PAGE_SIZE - (CPUIDLE_NAME_LEN + 2)))
|
||||
goto out;
|
||||
i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
|
||||
|
||||
i += scnprintf(&buf[i], CPUIDLE_NAME_LEN + 1, "%s ", tmp->name);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -85,58 +77,43 @@ static ssize_t store_current_governor(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
char gov_name[CPUIDLE_NAME_LEN];
|
||||
int ret = -EINVAL;
|
||||
size_t len = count;
|
||||
char gov_name[CPUIDLE_NAME_LEN + 1];
|
||||
int ret;
|
||||
struct cpuidle_governor *gov;
|
||||
|
||||
if (!len || len >= sizeof(gov_name))
|
||||
ret = sscanf(buf, "%" __stringify(CPUIDLE_NAME_LEN) "s", gov_name);
|
||||
if (ret != 1)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(gov_name, buf, len);
|
||||
gov_name[len] = '\0';
|
||||
if (gov_name[len - 1] == '\n')
|
||||
gov_name[--len] = '\0';
|
||||
|
||||
mutex_lock(&cpuidle_lock);
|
||||
|
||||
ret = -EINVAL;
|
||||
list_for_each_entry(gov, &cpuidle_governors, governor_list) {
|
||||
if (strlen(gov->name) == len && !strcmp(gov->name, gov_name)) {
|
||||
if (!strncmp(gov->name, gov_name, CPUIDLE_NAME_LEN)) {
|
||||
ret = cpuidle_switch_governor(gov);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&cpuidle_lock);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
else
|
||||
return count;
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(available_governors, 0444, show_available_governors, NULL);
|
||||
static DEVICE_ATTR(current_driver, 0444, show_current_driver, NULL);
|
||||
static DEVICE_ATTR(current_governor, 0644, show_current_governor,
|
||||
store_current_governor);
|
||||
static DEVICE_ATTR(current_governor_ro, 0444, show_current_governor, NULL);
|
||||
|
||||
static struct attribute *cpuidle_default_attrs[] = {
|
||||
static struct attribute *cpuidle_attrs[] = {
|
||||
&dev_attr_available_governors.attr,
|
||||
&dev_attr_current_driver.attr,
|
||||
&dev_attr_current_governor.attr,
|
||||
&dev_attr_current_governor_ro.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static DEVICE_ATTR(available_governors, 0444, show_available_governors, NULL);
|
||||
static DEVICE_ATTR(current_governor, 0644, show_current_governor,
|
||||
store_current_governor);
|
||||
|
||||
static struct attribute *cpuidle_switch_attrs[] = {
|
||||
&dev_attr_available_governors.attr,
|
||||
&dev_attr_current_driver.attr,
|
||||
&dev_attr_current_governor.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group cpuidle_attr_group = {
|
||||
.attrs = cpuidle_default_attrs,
|
||||
.attrs = cpuidle_attrs,
|
||||
.name = "cpuidle",
|
||||
};
|
||||
|
||||
|
@ -146,9 +123,6 @@ static struct attribute_group cpuidle_attr_group = {
|
|||
*/
|
||||
int cpuidle_add_interface(struct device *dev)
|
||||
{
|
||||
if (sysfs_switch)
|
||||
cpuidle_attr_group.attrs = cpuidle_switch_attrs;
|
||||
|
||||
return sysfs_create_group(&dev->kobj, &cpuidle_attr_group);
|
||||
}
|
||||
|
||||
|
@ -167,11 +141,6 @@ struct cpuidle_attr {
|
|||
ssize_t (*store)(struct cpuidle_device *, const char *, size_t count);
|
||||
};
|
||||
|
||||
#define define_one_ro(_name, show) \
|
||||
static struct cpuidle_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
|
||||
#define define_one_rw(_name, show, store) \
|
||||
static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
|
||||
|
||||
#define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
|
||||
|
||||
struct cpuidle_device_kobj {
|
||||
|
@ -431,12 +400,12 @@ static inline void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *k
|
|||
#define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
|
||||
|
||||
static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr,
|
||||
char * buf)
|
||||
char *buf)
|
||||
{
|
||||
int ret = -EIO;
|
||||
struct cpuidle_state *state = kobj_to_state(kobj);
|
||||
struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
|
||||
struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
|
||||
struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
|
||||
|
||||
if (cattr->show)
|
||||
ret = cattr->show(state, state_usage, buf);
|
||||
|
@ -515,7 +484,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
|
|||
ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
|
||||
&kdev->kobj, "state%d", i);
|
||||
if (ret) {
|
||||
kfree(kobj);
|
||||
kobject_put(&kobj->kobj);
|
||||
goto error_state;
|
||||
}
|
||||
cpuidle_add_s2idle_attr_group(kobj);
|
||||
|
@ -646,7 +615,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
|
|||
ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
|
||||
&kdev->kobj, "driver");
|
||||
if (ret) {
|
||||
kfree(kdrv);
|
||||
kobject_put(&kdrv->kobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -740,7 +709,7 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
|
|||
error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
|
||||
"cpuidle");
|
||||
if (error) {
|
||||
kfree(kdev);
|
||||
kobject_put(&kdev->kobj);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,16 +80,6 @@ config QCOM_PDR_HELPERS
|
|||
tristate
|
||||
select QCOM_QMI_HELPERS
|
||||
|
||||
config QCOM_PM
|
||||
bool "Qualcomm Power Management"
|
||||
depends on ARCH_QCOM && !ARM64
|
||||
select ARM_CPU_SUSPEND
|
||||
select QCOM_SCM
|
||||
help
|
||||
QCOM Platform specific power driver to manage cores and L2 low power
|
||||
modes. It interface with various system drivers to put the cores in
|
||||
low power modes.
|
||||
|
||||
config QCOM_QMI_HELPERS
|
||||
tristate
|
||||
depends on NET
|
||||
|
|
|
@ -8,7 +8,6 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
|
|||
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
|
||||
obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
|
||||
obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
|
||||
obj-$(CONFIG_QCOM_PM) += spm.o
|
||||
obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
|
||||
qmi_helpers-y += qmi_encdec.o qmi_interface.o
|
||||
obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o
|
||||
|
|
Loading…
Reference in New Issue