Merge branches 'pm-cpuidle' and 'pm-devfreq'

* pm-cpuidle:
  cpuidle: record state entry rejection statistics
  cpuidle: psci: Allow PM domain to be initialized even if no OSI mode
  firmware: psci: Extend psci_set_osi_mode() to allow reset to PC mode
  ACPI: processor: Print more information when acpi_processor_evaluate_cst() fails
  cpuidle: tegra: Correctly handle result of arm_cpuidle_simple_enter()

* pm-devfreq:
  PM / devfreq: tegra30: Improve initial hardware resetting
  PM / devfreq: event: Change prototype of devfreq_event_get_edev_by_phandle function
  PM / devfreq: Change prototype of devfreq_get_devfreq_by_phandle function
  PM / devfreq: Add devfreq_get_devfreq_by_node function
This commit is contained in:
Rafael J. Wysocki 2020-10-13 14:39:52 +02:00
commit fe5975b1b8
17 changed files with 185 additions and 91 deletions

View File

@ -528,6 +528,10 @@ object corresponding to it, as follows:
Total number of times the hardware has been asked by the given CPU to
enter this idle state.
``rejected``
Total number of times a request to enter this idle state on the given
CPU was rejected.
The :file:`desc` and :file:`name` files both contain strings. The difference
between them is that the name is expected to be more concise, while the
description may be longer and it may contain white space or special characters.
@ -572,6 +576,11 @@ particular case. For these reasons, the only reliable way to find out how
much time has been spent by the hardware in different idle states supported by
it is to use idle state residency counters in the hardware, if available.
Generally, an interrupt received when trying to enter an idle state causes the
idle state entry request to be rejected, in which case the ``CPUIdle`` driver
may return an error code to indicate that this was the case. The :file:`usage`
and :file:`rejected` files report the number of times the given idle state
was entered successfully or rejected, respectively.
.. _cpu-pm-qos:

View File

@ -798,22 +798,34 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
memset(&cx, 0, sizeof(cx));
element = &cst->package.elements[i];
if (element->type != ACPI_TYPE_PACKAGE)
if (element->type != ACPI_TYPE_PACKAGE) {
acpi_handle_info(handle, "_CST C%d type(%x) is not package, skip...\n",
i, element->type);
continue;
}
if (element->package.count != 4)
if (element->package.count != 4) {
acpi_handle_info(handle, "_CST C%d package count(%d) is not 4, skip...\n",
i, element->package.count);
continue;
}
obj = &element->package.elements[0];
if (obj->type != ACPI_TYPE_BUFFER)
if (obj->type != ACPI_TYPE_BUFFER) {
acpi_handle_info(handle, "_CST C%d package element[0] type(%x) is not buffer, skip...\n",
i, obj->type);
continue;
}
reg = (struct acpi_power_register *)obj->buffer.pointer;
obj = &element->package.elements[1];
if (obj->type != ACPI_TYPE_INTEGER)
if (obj->type != ACPI_TYPE_INTEGER) {
acpi_handle_info(handle, "_CST C[%d] package element[1] type(%x) is not integer, skip...\n",
i, obj->type);
continue;
}
cx.type = obj->integer.value;
/*
@ -850,6 +862,8 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
cx.entry_method = ACPI_CSTATE_HALT;
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
} else {
acpi_handle_info(handle, "_CST C%d declares FIXED_HARDWARE C-state but not supported in hardware, skip...\n",
i);
continue;
}
} else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
@ -857,6 +871,8 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
cx.address);
} else {
acpi_handle_info(handle, "_CST C%d space_id(%x) neither FIXED_HARDWARE nor SYSTEM_IO, skip...\n",
i, reg->space_id);
continue;
}
@ -864,14 +880,20 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
cx.valid = 1;
obj = &element->package.elements[2];
if (obj->type != ACPI_TYPE_INTEGER)
if (obj->type != ACPI_TYPE_INTEGER) {
acpi_handle_info(handle, "_CST C%d package element[2] type(%x) not integer, skip...\n",
i, obj->type);
continue;
}
cx.latency = obj->integer.value;
obj = &element->package.elements[3];
if (obj->type != ACPI_TYPE_INTEGER)
if (obj->type != ACPI_TYPE_INTEGER) {
acpi_handle_info(handle, "_CST C%d package element[3] type(%x) not integer, skip...\n",
i, obj->type);
continue;
}
memcpy(&info->states[++last_index], &cx, sizeof(cx));
}

View File

@ -105,7 +105,7 @@ static void psci_pd_free_states(struct genpd_power_state *states,
kfree(states);
}
static int psci_pd_init(struct device_node *np)
static int psci_pd_init(struct device_node *np, bool use_osi)
{
struct generic_pm_domain *pd;
struct psci_pd_provider *pd_provider;
@ -135,11 +135,16 @@ static int psci_pd_init(struct device_node *np)
pd->free_states = psci_pd_free_states;
pd->name = kbasename(pd->name);
pd->power_off = psci_pd_power_off;
pd->states = states;
pd->state_count = state_count;
pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN;
/* Allow power off when OSI has been successfully enabled. */
if (use_osi)
pd->power_off = psci_pd_power_off;
else
pd->flags |= GENPD_FLAG_ALWAYS_ON;
/* Use governor for CPU PM domains if it has some states to manage. */
pd_gov = state_count > 0 ? &pm_domain_cpu_gov : NULL;
@ -190,7 +195,7 @@ static void psci_pd_remove(void)
}
}
static int psci_pd_init_topology(struct device_node *np, bool add)
static int psci_pd_init_topology(struct device_node *np)
{
struct device_node *node;
struct of_phandle_args child, parent;
@ -203,9 +208,7 @@ static int psci_pd_init_topology(struct device_node *np, bool add)
child.np = node;
child.args_count = 0;
ret = add ? of_genpd_add_subdomain(&parent, &child) :
of_genpd_remove_subdomain(&parent, &child);
ret = of_genpd_add_subdomain(&parent, &child);
of_node_put(parent.np);
if (ret) {
of_node_put(node);
@ -216,14 +219,20 @@ static int psci_pd_init_topology(struct device_node *np, bool add)
return 0;
}
static int psci_pd_add_topology(struct device_node *np)
static bool psci_pd_try_set_osi_mode(void)
{
return psci_pd_init_topology(np, true);
}
int ret;
static void psci_pd_remove_topology(struct device_node *np)
{
psci_pd_init_topology(np, false);
if (!psci_has_osi_support())
return false;
ret = psci_set_osi_mode(true);
if (ret) {
pr_warn("failed to enable OSI mode: %d\n", ret);
return false;
}
return true;
}
static void psci_cpuidle_domain_sync_state(struct device *dev)
@ -244,14 +253,14 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *node;
bool use_osi;
int ret = 0, pd_count = 0;
if (!np)
return -ENODEV;
/* Currently limit the hierarchical topology to be used in OSI mode. */
if (!psci_has_osi_support())
return 0;
/* If OSI mode is supported, let's try to enable it. */
use_osi = psci_pd_try_set_osi_mode();
/*
* Parse child nodes for the "#power-domain-cells" property and
@ -261,7 +270,7 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
if (!of_find_property(node, "#power-domain-cells", NULL))
continue;
ret = psci_pd_init(node);
ret = psci_pd_init(node, use_osi);
if (ret)
goto put_node;
@ -270,30 +279,24 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
/* Bail out if not using the hierarchical CPU topology. */
if (!pd_count)
return 0;
goto no_pd;
/* Link genpd masters/subdomains to model the CPU topology. */
ret = psci_pd_add_topology(np);
ret = psci_pd_init_topology(np);
if (ret)
goto remove_pd;
/* Try to enable OSI mode. */
ret = psci_set_osi_mode();
if (ret) {
pr_warn("failed to enable OSI mode: %d\n", ret);
psci_pd_remove_topology(np);
goto remove_pd;
}
pr_info("Initialized CPU PM domain topology\n");
return 0;
put_node:
of_node_put(node);
remove_pd:
if (pd_count)
psci_pd_remove();
psci_pd_remove();
pr_err("failed to create CPU PM domains ret=%d\n", ret);
no_pd:
if (use_osi)
psci_set_osi_mode(false);
return ret;
}

View File

@ -172,7 +172,7 @@ static int tegra_cpuidle_coupled_barrier(struct cpuidle_device *dev)
static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
int index, unsigned int cpu)
{
int ret;
int err;
/*
* CC6 state is the "CPU cluster power-off" state. In order to
@ -183,9 +183,9 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
* CPU cores, GIC and L2 cache).
*/
if (index == TEGRA_CC6) {
ret = tegra_cpuidle_coupled_barrier(dev);
if (ret)
return ret;
err = tegra_cpuidle_coupled_barrier(dev);
if (err)
return err;
}
local_fiq_disable();
@ -194,15 +194,15 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
switch (index) {
case TEGRA_C7:
ret = tegra_cpuidle_c7_enter();
err = tegra_cpuidle_c7_enter();
break;
case TEGRA_CC6:
ret = tegra_cpuidle_cc6_enter(cpu);
err = tegra_cpuidle_cc6_enter(cpu);
break;
default:
ret = -EINVAL;
err = -EINVAL;
break;
}
@ -210,7 +210,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
tegra_pm_clear_cpu_in_lp2();
local_fiq_enable();
return ret;
return err ?: index;
}
static int tegra_cpuidle_adjust_state_index(int index, unsigned int cpu)
@ -236,21 +236,27 @@ static int tegra_cpuidle_enter(struct cpuidle_device *dev,
int index)
{
unsigned int cpu = cpu_logical_map(dev->cpu);
int err;
int ret;
index = tegra_cpuidle_adjust_state_index(index, cpu);
if (dev->states_usage[index].disable)
return -1;
if (index == TEGRA_C1)
err = arm_cpuidle_simple_enter(dev, drv, index);
ret = arm_cpuidle_simple_enter(dev, drv, index);
else
err = tegra_cpuidle_state_enter(dev, index, cpu);
ret = tegra_cpuidle_state_enter(dev, index, cpu);
if (err && (err != -EINTR || index != TEGRA_CC6))
pr_err_once("failed to enter state %d err: %d\n", index, err);
if (ret < 0) {
if (ret != -EINTR || index != TEGRA_CC6)
pr_err_once("failed to enter state %d err: %d\n",
index, ret);
index = -1;
} else {
index = ret;
}
return err ? -1 : index;
return index;
}
static int tegra114_enter_s2idle(struct cpuidle_device *dev,

View File

@ -297,6 +297,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
}
} else {
dev->last_residency_ns = 0;
dev->states_usage[index].rejected++;
}
return entered_state;

View File

@ -256,6 +256,7 @@ define_show_state_time_function(exit_latency)
define_show_state_time_function(target_residency)
define_show_state_function(power_usage)
define_show_state_ull_function(usage)
define_show_state_ull_function(rejected)
define_show_state_str_function(name)
define_show_state_str_function(desc)
define_show_state_ull_function(above)
@ -312,6 +313,7 @@ define_one_state_ro(latency, show_state_exit_latency);
define_one_state_ro(residency, show_state_target_residency);
define_one_state_ro(power, show_state_power_usage);
define_one_state_ro(usage, show_state_usage);
define_one_state_ro(rejected, show_state_rejected);
define_one_state_ro(time, show_state_time);
define_one_state_rw(disable, show_state_disable, store_state_disable);
define_one_state_ro(above, show_state_above);
@ -325,6 +327,7 @@ static struct attribute *cpuidle_state_default_attrs[] = {
&attr_residency.attr,
&attr_power.attr,
&attr_usage.attr,
&attr_rejected.attr,
&attr_time.attr,
&attr_disable.attr,
&attr_above.attr,

View File

@ -213,20 +213,21 @@ EXPORT_SYMBOL_GPL(devfreq_event_reset_event);
* devfreq_event_get_edev_by_phandle() - Get the devfreq-event dev from
* devicetree.
* @dev : the pointer to the given device
* @phandle_name: name of property holding a phandle value
* @index : the index into list of devfreq-event device
*
* Note that this function return the pointer of devfreq-event device.
*/
struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(struct device *dev,
int index)
const char *phandle_name, int index)
{
struct device_node *node;
struct devfreq_event_dev *edev;
if (!dev->of_node)
if (!dev->of_node || !phandle_name)
return ERR_PTR(-EINVAL);
node = of_parse_phandle(dev->of_node, "devfreq-events", index);
node = of_parse_phandle(dev->of_node, phandle_name, index);
if (!node)
return ERR_PTR(-ENODEV);
@ -258,19 +259,20 @@ EXPORT_SYMBOL_GPL(devfreq_event_get_edev_by_phandle);
/**
* devfreq_event_get_edev_count() - Get the count of devfreq-event dev
* @dev : the pointer to the given device
* @phandle_name: name of property holding a phandle value
*
* Note that this function return the count of devfreq-event devices.
*/
int devfreq_event_get_edev_count(struct device *dev)
int devfreq_event_get_edev_count(struct device *dev, const char *phandle_name)
{
int count;
if (!dev->of_node) {
if (!dev->of_node || !phandle_name) {
dev_err(dev, "device does not have a device node entry\n");
return -EINVAL;
}
count = of_property_count_elems_of_size(dev->of_node, "devfreq-events",
count = of_property_count_elems_of_size(dev->of_node, phandle_name,
sizeof(u32));
if (count < 0) {
dev_err(dev,

View File

@ -984,47 +984,74 @@ EXPORT_SYMBOL(devm_devfreq_add_device);
#ifdef CONFIG_OF
/*
* devfreq_get_devfreq_by_phandle - Get the devfreq device from devicetree
* @dev - instance to the given device
* @index - index into list of devfreq
* devfreq_get_devfreq_by_node - Get the devfreq device from devicetree
* @node - pointer to device_node
*
* return the instance of devfreq device
*/
struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
{
struct device_node *node;
struct devfreq *devfreq;
if (!dev)
return ERR_PTR(-EINVAL);
if (!dev->of_node)
return ERR_PTR(-EINVAL);
node = of_parse_phandle(dev->of_node, "devfreq", index);
if (!node)
return ERR_PTR(-ENODEV);
return ERR_PTR(-EINVAL);
mutex_lock(&devfreq_list_lock);
list_for_each_entry(devfreq, &devfreq_list, node) {
if (devfreq->dev.parent
&& devfreq->dev.parent->of_node == node) {
mutex_unlock(&devfreq_list_lock);
of_node_put(node);
return devfreq;
}
}
mutex_unlock(&devfreq_list_lock);
return ERR_PTR(-ENODEV);
}
/*
* devfreq_get_devfreq_by_phandle - Get the devfreq device from devicetree
* @dev - instance to the given device
* @phandle_name - name of property holding a phandle value
* @index - index into list of devfreq
*
* return the instance of devfreq device
*/
struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
const char *phandle_name, int index)
{
struct device_node *node;
struct devfreq *devfreq;
if (!dev || !phandle_name)
return ERR_PTR(-EINVAL);
if (!dev->of_node)
return ERR_PTR(-EINVAL);
node = of_parse_phandle(dev->of_node, phandle_name, index);
if (!node)
return ERR_PTR(-ENODEV);
devfreq = devfreq_get_devfreq_by_node(node);
of_node_put(node);
return ERR_PTR(-EPROBE_DEFER);
return devfreq;
}
#else
struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
{
return ERR_PTR(-ENODEV);
}
struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
const char *phandle_name, int index)
{
return ERR_PTR(-ENODEV);
}
#endif /* CONFIG_OF */
EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_node);
EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_phandle);
/**

View File

@ -193,7 +193,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
* Get the devfreq-event devices to get the current utilization of
* buses. This raw data will be used in devfreq ondemand governor.
*/
count = devfreq_event_get_edev_count(dev);
count = devfreq_event_get_edev_count(dev, "devfreq-events");
if (count < 0) {
dev_err(dev, "failed to get the count of devfreq-event dev\n");
ret = count;
@ -209,7 +209,8 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
}
for (i = 0; i < count; i++) {
bus->edev[i] = devfreq_event_get_edev_by_phandle(dev, i);
bus->edev[i] = devfreq_event_get_edev_by_phandle(dev,
"devfreq-events", i);
if (IS_ERR(bus->edev[i])) {
ret = -EPROBE_DEFER;
goto err_regulator;
@ -360,7 +361,7 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
profile->exit = exynos_bus_passive_exit;
/* Get the instance of parent devfreq device */
parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
parent_devfreq = devfreq_get_devfreq_by_phandle(dev, "devfreq", 0);
if (IS_ERR(parent_devfreq))
return -EPROBE_DEFER;

View File

@ -341,7 +341,7 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
return PTR_ERR(data->dmc_clk);
}
data->edev = devfreq_event_get_edev_by_phandle(dev, 0);
data->edev = devfreq_event_get_edev_by_phandle(dev, "devfreq-events", 0);
if (IS_ERR(data->edev))
return -EPROBE_DEFER;

View File

@ -822,8 +822,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
return err;
}
reset_control_assert(tegra->reset);
err = clk_prepare_enable(tegra->clock);
if (err) {
dev_err(&pdev->dev,
@ -831,7 +829,11 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
return err;
}
reset_control_deassert(tegra->reset);
err = reset_control_reset(tegra->reset);
if (err) {
dev_err(&pdev->dev, "Failed to reset hardware: %d\n", err);
goto disable_clk;
}
rate = clk_round_rate(tegra->emc_clock, ULONG_MAX);
if (rate < 0) {

View File

@ -151,12 +151,15 @@ static u32 psci_get_version(void)
return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
}
int psci_set_osi_mode(void)
int psci_set_osi_mode(bool enable)
{
unsigned long suspend_mode;
int err;
err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE,
PSCI_1_0_SUSPEND_MODE_OSI, 0, 0);
suspend_mode = enable ? PSCI_1_0_SUSPEND_MODE_OSI :
PSCI_1_0_SUSPEND_MODE_PC;
err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE, suspend_mode, 0, 0);
return psci_to_linux_errno(err);
}
@ -546,8 +549,7 @@ static int __init psci_1_0_init(struct device_node *np)
pr_info("OSI mode supported.\n");
/* Default to PC mode. */
invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE,
PSCI_1_0_SUSPEND_MODE_PC, 0, 0);
psci_set_osi_mode(false);
}
return 0;

View File

@ -1293,7 +1293,8 @@ static int exynos5_performance_counters_init(struct exynos5_dmc *dmc)
int counters_size;
int ret, i;
dmc->num_counters = devfreq_event_get_edev_count(dmc->dev);
dmc->num_counters = devfreq_event_get_edev_count(dmc->dev,
"devfreq-events");
if (dmc->num_counters < 0) {
dev_err(dmc->dev, "could not get devfreq-event counters\n");
return dmc->num_counters;
@ -1306,7 +1307,8 @@ static int exynos5_performance_counters_init(struct exynos5_dmc *dmc)
for (i = 0; i < dmc->num_counters; i++) {
dmc->counter[i] =
devfreq_event_get_edev_by_phandle(dmc->dev, i);
devfreq_event_get_edev_by_phandle(dmc->dev,
"devfreq-events", i);
if (IS_ERR_OR_NULL(dmc->counter[i]))
return -EPROBE_DEFER;
}

View File

@ -38,6 +38,7 @@ struct cpuidle_state_usage {
u64 time_ns;
unsigned long long above; /* Number of times it's been too deep */
unsigned long long below; /* Number of times it's been too shallow */
unsigned long long rejected; /* Number of times idle entry was rejected */
#ifdef CONFIG_SUSPEND
unsigned long long s2idle_usage;
unsigned long long s2idle_time; /* in US */

View File

@ -106,8 +106,11 @@ extern int devfreq_event_get_event(struct devfreq_event_dev *edev,
struct devfreq_event_data *edata);
extern int devfreq_event_reset_event(struct devfreq_event_dev *edev);
extern struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(
struct device *dev, int index);
extern int devfreq_event_get_edev_count(struct device *dev);
struct device *dev,
const char *phandle_name,
int index);
extern int devfreq_event_get_edev_count(struct device *dev,
const char *phandle_name);
extern struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev,
struct devfreq_event_desc *desc);
extern int devfreq_event_remove_edev(struct devfreq_event_dev *edev);
@ -152,12 +155,15 @@ static inline int devfreq_event_reset_event(struct devfreq_event_dev *edev)
}
static inline struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(
struct device *dev, int index)
struct device *dev,
const char *phandle_name,
int index)
{
return ERR_PTR(-EINVAL);
}
static inline int devfreq_event_get_edev_count(struct device *dev)
static inline int devfreq_event_get_edev_count(struct device *dev,
const char *phandle_name)
{
return -EINVAL;
}

View File

@ -261,7 +261,9 @@ void devm_devfreq_unregister_notifier(struct device *dev,
struct devfreq *devfreq,
struct notifier_block *nb,
unsigned int list);
struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index);
struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node);
struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
const char *phandle_name, int index);
#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
/**
@ -414,8 +416,13 @@ static inline void devm_devfreq_unregister_notifier(struct device *dev,
{
}
static inline struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
{
return ERR_PTR(-ENODEV);
}
static inline struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
int index)
const char *phandle_name, int index)
{
return ERR_PTR(-ENODEV);
}

View File

@ -18,7 +18,7 @@ bool psci_tos_resident_on(int cpu);
int psci_cpu_suspend_enter(u32 state);
bool psci_power_state_is_valid(u32 state);
int psci_set_osi_mode(void);
int psci_set_osi_mode(bool enable);
bool psci_has_osi_support(void);
struct psci_operations {