xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Oleksandr Tyshchenko <olekstysh@gmail.com>
To: xen-devel@lists.xenproject.org
Cc: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Julien Grall <julien.grall@linaro.org>
Subject: [RFC PATCH 29/31] xen/arm: Introduce CPUFreq Interface component
Date: Thu,  9 Nov 2017 19:10:19 +0200	[thread overview]
Message-ID: <1510247421-24094-30-git-send-email-olekstysh@gmail.com> (raw)
In-Reply-To: <1510247421-24094-1-git-send-email-olekstysh@gmail.com>

From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>

This patch adds an interface component which performs following steps:
1. Initialize everything needed SCPI based CPUFreq driver to be functional
   (SCPI Message protocol, mailbox to communicate with SCP, etc).
   Also preliminary check if SCPI DVFS clock nodes offered by SCP are
   present in a device tree.
2. Register SCPI based CPUFreq driver.
3. Populate CPUs. Get DVFS info (OPP list and the latency information)
   for all DVFS capable CPUs using SCPI protocol, convert these capabilities
   into PM data the CPUFreq framework expects to see followed by
   uploading it.

Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/cpufreq/cpufreq_if.c | 522 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 522 insertions(+)
 create mode 100644 xen/arch/arm/cpufreq/cpufreq_if.c

diff --git a/xen/arch/arm/cpufreq/cpufreq_if.c b/xen/arch/arm/cpufreq/cpufreq_if.c
new file mode 100644
index 0000000..2451d00
--- /dev/null
+++ b/xen/arch/arm/cpufreq/cpufreq_if.c
@@ -0,0 +1,522 @@
+/*
+ * xen/arch/arm/cpufreq/cpufreq_if.c
+ *
+ * CPUFreq interface component
+ *
+ * Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
+ * Copyright (c) 2017 EPAM Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/device_tree.h>
+#include <xen/err.h>
+#include <xen/sched.h>
+#include <xen/cpufreq.h>
+#include <xen/pmstat.h>
+#include <xen/guest_access.h>
+
+#include "scpi_protocol.h"
+
+/*
+ * TODO:
+ * 1. Add __init to required funcs
+ * 2. Put get_cpu_device() into common place
+ */
+
+static struct scpi_ops *scpi_ops;
+
+extern int scpi_cpufreq_register_driver(void);
+
+#define dev_name(dev) dt_node_full_name(dev_to_dt(dev))
+
+struct device *get_cpu_device(unsigned int cpu)
+{
+    if ( cpu < nr_cpu_ids && cpu_possible(cpu) )
+        return dt_to_dev(cpu_dt_nodes[cpu]);
+    else
+        return NULL;
+}
+
+static bool is_dvfs_capable(unsigned int cpu)
+{
+    static const struct dt_device_match scpi_dvfs_clock_match[] =
+    {
+        DT_MATCH_COMPATIBLE("arm,scpi-dvfs-clocks"),
+        { /* sentinel */ },
+    };
+    struct device *cpu_dev;
+    struct dt_phandle_args clock_spec;
+    struct scpi_dvfs_info *info;
+    u32 domain;
+    int i, ret, count;
+
+    cpu_dev = get_cpu_device(cpu);
+    if ( !cpu_dev )
+    {
+        printk("cpu%d: failed to get device\n", cpu);
+        return false;
+    }
+
+    /* First of all find a clock node this CPU is a consumer of */
+    ret = dt_parse_phandle_with_args(cpu_dev->of_node,
+                                     "clocks",
+                                     "#clock-cells",
+                                     0,
+                                     &clock_spec);
+    if ( ret )
+    {
+        printk("cpu%d: failed to get clock node\n", cpu);
+        return false;
+    }
+
+    /* Make sure it is an available DVFS clock node */
+    if ( !dt_match_node(scpi_dvfs_clock_match, clock_spec.np) ||
+         !dt_device_is_available(clock_spec.np) )
+    {
+        printk("cpu%d: clock node '%s' is either non-DVFS or non-available\n",
+               cpu, dev_name(&clock_spec.np->dev));
+        return false;
+    }
+
+    /*
+     * Actually we already have a power domain id this CPU belongs to,
+     * it is a stored in args[0] CPU clock specifier, so we could ask SCP
+     * to provide its DVFS info. But we want to dig a little bit deeper
+     * to make sure that everything is correct.
+     */
+
+    /* Check how many clock ids a DVFS clock node has */
+    ret = dt_property_count_elems_of_size(clock_spec.np,
+                                          "clock-indices",
+                                          sizeof(u32));
+    if ( ret < 0 )
+    {
+        printk("cpu%d: failed to get clock-indices count in '%s'\n",
+               cpu, dev_name(&clock_spec.np->dev));
+        return false;
+    }
+    count = ret;
+
+    /* Check if a clock id the CPU clock specifier points to is present */
+    for ( i = 0; i < count; i++ )
+    {
+        ret = dt_property_read_u32_index(clock_spec.np,
+                                         "clock-indices",
+                                         i,
+                                         &domain);
+        if ( ret )
+        {
+            printk("cpu%d: failed to get clock index in '%s'\n",
+                   cpu, dev_name(&clock_spec.np->dev));
+            return false;
+        }
+
+        /* Match found */
+        if ( clock_spec.args[0] == domain )
+            break;
+    }
+
+    if ( i == count )
+    {
+        printk("cpu%d: failed to find matching clk_id (pd) %d\n",
+               cpu, clock_spec.args[0]);
+        return false;
+    }
+
+    /*
+     * Check if a SCP is aware of this power domain. SCPI Message protocol
+     * driver will populate power domain's DVFS info then.
+     */
+    info = scpi_ops->dvfs_get_info(domain);
+    if ( IS_ERR(info) )
+    {
+        printk("cpu%d: failed to get DVFS info of pd%u\n", cpu, domain);
+        return false;
+    }
+
+    printk(XENLOG_DEBUG "cpu%d: is DVFS capable, belongs to pd%u\n",
+           cpu, domain);
+
+    return true;
+}
+
+static int get_sharing_cpus(unsigned int cpu, cpumask_t *mask)
+{
+    struct device *cpu_dev = get_cpu_device(cpu), *tcpu_dev;
+    unsigned int tcpu;
+    int domain, tdomain;
+
+    BUG_ON(!cpu_dev);
+
+    domain = scpi_ops->device_domain_id(cpu_dev);
+    if ( domain < 0 )
+        return domain;
+
+    cpumask_clear(mask);
+    cpumask_set_cpu(cpu, mask);
+
+    for_each_online_cpu( tcpu )
+    {
+        if ( tcpu == cpu )
+            continue;
+
+        tcpu_dev = get_cpu_device(tcpu);
+        if ( !tcpu_dev )
+            continue;
+
+        tdomain = scpi_ops->device_domain_id(tcpu_dev);
+        if ( tdomain == domain )
+            cpumask_set_cpu(tcpu, mask);
+    }
+
+    return 0;
+}
+
+static int get_transition_latency(struct device *cpu_dev)
+{
+    return scpi_ops->get_transition_latency(cpu_dev);
+}
+
+static struct scpi_dvfs_info *get_dvfs_info(struct device *cpu_dev)
+{
+    int domain;
+
+    domain = scpi_ops->device_domain_id(cpu_dev);
+    if ( domain < 0 )
+        return ERR_PTR(-EINVAL);
+
+    return scpi_ops->dvfs_get_info(domain);
+}
+
+static int init_cpufreq_table(unsigned int cpu,
+                              struct cpufreq_frequency_table **table)
+{
+    struct cpufreq_frequency_table *freq_table = NULL;
+    struct device *cpu_dev = get_cpu_device(cpu);
+    struct scpi_dvfs_info *info;
+    struct scpi_opp *opp;
+    int i;
+
+    BUG_ON(!cpu_dev);
+
+    info = get_dvfs_info(cpu_dev);
+    if ( IS_ERR(info) )
+        return PTR_ERR(info);
+
+    if ( !info->opps )
+        return -EIO;
+
+    freq_table = xzalloc_array(struct cpufreq_frequency_table, info->count + 1);
+    if ( !freq_table )
+        return -ENOMEM;
+
+    for ( opp = info->opps, i = 0; i < info->count; i++, opp++ )
+    {
+        freq_table[i].index = i;
+        /* Convert Hz -> kHz */
+        freq_table[i].frequency = opp->freq / 1000;
+    }
+
+    freq_table[i].index = i;
+    freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+    *table = &freq_table[0];
+
+    return 0;
+}
+
+static void free_cpufreq_table(struct cpufreq_frequency_table **table)
+{
+    if ( !table )
+        return;
+
+    xfree(*table);
+    *table = NULL;
+}
+
+static int upload_cpufreq_data(cpumask_t *mask,
+                               struct cpufreq_frequency_table *table)
+{
+    struct xen_processor_performance *perf;
+    struct xen_processor_px *states;
+    uint32_t platform_limit = 0, state_count = 0;
+    unsigned int max_freq = 0, prev_freq = 0, cpu = cpumask_first(mask);
+    int i, latency, ret = 0;
+
+    perf = xzalloc(struct xen_processor_performance);
+    if ( !perf )
+        return -ENOMEM;
+
+    /* Check frequency table and find max frequency */
+    for ( i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++ )
+    {
+        unsigned int freq = table[i].frequency;
+
+        if ( freq == CPUFREQ_ENTRY_INVALID )
+            continue;
+
+        if ( table[i].index != state_count || freq <= prev_freq )
+        {
+            printk("cpu%d: frequency table format error\n", cpu);
+            ret = -EINVAL;
+            goto out;
+        }
+
+        prev_freq = freq;
+        state_count++;
+        if ( freq > max_freq )
+            max_freq = freq;
+    }
+
+    /*
+     * The frequency table we have is just a temporary place for storing
+     * provided by SCP DVFS info. Create performance states array.
+     */
+    if ( !state_count )
+    {
+        printk("cpu%d: no available performance states\n", cpu);
+        ret = -EINVAL;
+        goto out;
+    }
+
+    states = xzalloc_array(struct xen_processor_px, state_count);
+    if ( !states )
+    {
+        ret = -ENOMEM;
+        goto out;
+    }
+
+    set_xen_guest_handle(perf->states, states);
+    perf->state_count = state_count;
+
+    latency = get_transition_latency(get_cpu_device(cpu));
+
+    /* Performance states must start from higher values */
+    for ( i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++ )
+    {
+        unsigned int freq = table[i].frequency;
+        unsigned int index = state_count - 1 - table[i].index;
+
+        if ( freq == CPUFREQ_ENTRY_INVALID )
+            continue;
+
+        if ( freq == max_freq )
+            platform_limit = index;
+
+        /* Convert kHz -> MHz */
+        states[index].core_frequency = freq / 1000;
+        /* Convert ns -> us */
+        states[index].transition_latency = DIV_ROUND_UP(latency, 1000);
+    }
+
+    perf->flags = XEN_PX_DATA; /* all info in a one-shot */
+    perf->platform_limit = platform_limit;
+    perf->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+    perf->domain_info.domain = cpumask_first(mask);
+    perf->domain_info.num_processors = cpumask_weight(mask);
+
+    /* Iterate through all CPUs which are on the same boat */
+    for_each_cpu( cpu, mask )
+    {
+        ret = set_px_pminfo(cpu, perf);
+        if ( ret )
+        {
+            printk("cpu%d: failed to set Px states (%d)\n", cpu, ret);
+            break;
+        }
+
+        printk(XENLOG_DEBUG "cpu%d: set Px states\n", cpu);
+    }
+
+    xfree(states);
+out:
+    xfree(perf);
+
+    return ret;
+}
+
+static int __init scpi_cpufreq_postinit(void)
+{
+    struct cpufreq_frequency_table *freq_table = NULL;
+    cpumask_t processed_cpus, shared_cpus;
+    unsigned int cpu;
+    int ret = -ENODEV;
+
+    cpumask_clear(&processed_cpus);
+
+    for_each_online_cpu( cpu )
+    {
+        if ( cpumask_test_cpu(cpu, &processed_cpus) )
+            continue;
+
+        if ( !is_dvfs_capable(cpu) )
+            continue;
+
+        ret = get_sharing_cpus(cpu, &shared_cpus);
+        if ( ret )
+        {
+            printk("cpu%d: failed to get sharing cpumask (%d)\n", cpu, ret);
+            return ret;
+        }
+
+        BUG_ON(cpumask_empty(&shared_cpus));
+        cpumask_or(&processed_cpus, &processed_cpus, &shared_cpus);
+
+        /* Create intermediate frequency table */
+        ret = init_cpufreq_table(cpu, &freq_table);
+        if ( ret )
+        {
+            printk("cpu%d: failed to initialize frequency table (%d)\n",
+                   cpu, ret);
+            return ret;
+        }
+
+        ret = upload_cpufreq_data(&shared_cpus, freq_table);
+        /* Destroy intermediate frequency table */
+        free_cpufreq_table(&freq_table);
+        if ( ret )
+        {
+            printk("cpu%d: failed to upload cpufreq data (%d)\n", cpu, ret);
+            return ret;
+        }
+
+        printk(XENLOG_DEBUG "cpu%d: uploaded cpufreq data\n", cpu);
+    }
+
+    return ret;
+}
+
+static int __init scpi_cpufreq_preinit(void)
+{
+    struct dt_device_node *scpi, *clk, *dvfs_clk;
+    int ret;
+
+    /* Initialize SCPI Message protocol */
+    ret = scpi_init();
+    if ( ret )
+    {
+        printk("failed to initialize SCPI (%d)\n", ret);
+        return ret;
+    }
+
+    /* Sanity check */
+    if ( !get_scpi_ops() || !get_scpi_dev() )
+        return -ENXIO;
+
+    scpi = get_scpi_dev()->of_node;
+    scpi_ops = get_scpi_ops();
+
+    ret = -ENODEV;
+
+    /*
+     * Check for clock related nodes for now. But it might additional nodes,
+     * like thermal sensor, etc.
+     */
+    dt_for_each_child_node( scpi, clk )
+    {
+        /*
+         * First of all there must be a container node which contains all
+         * clocks provided by SCP.
+         */
+        if ( !dt_device_is_compatible(clk, "arm,scpi-clocks") )
+            continue;
+
+        /*
+         * As we are interested in DVFS feature only, check for DVFS clock
+         * sub-node. At the current stage check for it presence only.
+         * Without it there is no point to register SCPI based CPUFreq. We will
+         * perform a thorough check later when populating DVFS clock consumers.
+         */
+        dt_for_each_child_node( clk, dvfs_clk )
+        {
+            if ( !dt_device_is_compatible(dvfs_clk, "arm,scpi-dvfs-clocks") )
+                continue;
+
+            return 0;
+        }
+
+        break;
+    }
+
+    printk("failed to find SCPI DVFS clocks (%d)\n", ret);
+
+    return ret;
+}
+
+/* TODO Implement me */
+static void scpi_cpufreq_deinit(void)
+{
+
+}
+
+static int __init cpufreq_driver_init(void)
+{
+    int ret;
+
+    if ( cpufreq_controller != FREQCTL_xen )
+        return 0;
+
+    /*
+     * Initialize everything needed SCPI based CPUFreq driver to be functional
+     * (SCPI Message protocol, mailbox to communicate with SCP, etc).
+     * Also preliminary check if SCPI DVFS clock nodes offered by SCP are
+     * present in a device tree.
+     */
+    ret = scpi_cpufreq_preinit();
+    if ( ret )
+        goto out;
+
+    /* Register SCPI based CPUFreq driver */
+    ret = scpi_cpufreq_register_driver();
+    if ( ret )
+        goto out;
+
+    /*
+     * Populate CPUs. Get DVFS info (OPP list and the latency information)
+     * for all DVFS capable CPUs using SCPI protocol, convert these capabilities
+     * into PM data the CPUFreq framework expects to see followed by
+     * uploading it.
+     *
+     * Actually it is almost the same PM data which hwdom uploads in case of
+     * x86 via platform hypercall after parsing ACPI tables. In our case we
+     * don't need hwdom to be involved in, since we already have everything in
+     * hand. Moreover, the hwdom doesn't even know anything about physical CPUs.
+     * Not completely sure that it is the best place to do so, but certainly
+     * it must be after driver registration.
+     */
+    ret = scpi_cpufreq_postinit();
+
+out:
+    if ( ret )
+    {
+        printk("failed to initialize SCPI based CPUFreq (%d)\n", ret);
+        scpi_cpufreq_deinit();
+        return ret;
+    }
+
+    printk("initialized SCPI based CPUFreq\n");
+
+    return 0;
+}
+__initcall(cpufreq_driver_init);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2017-11-09 17:11 UTC|newest]

Thread overview: 108+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-09 17:09 [RFC PATCH 00/31] CPUFreq on ARM Oleksandr Tyshchenko
2017-11-09 17:09 ` [RFC PATCH 01/31] cpufreq: move cpufreq.h file to the xen/include/xen location Oleksandr Tyshchenko
2017-12-02  0:35   ` Stefano Stabellini
2017-11-09 17:09 ` [RFC PATCH 02/31] pm: move processor_perf.h " Oleksandr Tyshchenko
2017-12-02  0:41   ` Stefano Stabellini
2017-11-09 17:09 ` [RFC PATCH 03/31] pmstat: move pmstat.c file to the xen/drivers/pm/stat.c location Oleksandr Tyshchenko
2017-12-02  0:47   ` Stefano Stabellini
2018-05-07 15:36   ` Jan Beulich
2018-05-18 11:14     ` Oleksandr Tyshchenko
2018-05-18 11:35       ` Jan Beulich
2018-05-18 14:13         ` Oleksandr Tyshchenko
2018-05-18 14:21           ` Jan Beulich
2017-11-09 17:09 ` [RFC PATCH 04/31] cpufreq: make turbo settings to be configurable Oleksandr Tyshchenko
2017-12-02  1:06   ` Stefano Stabellini
2017-12-02 17:25     ` Oleksandr Tyshchenko
2017-12-04 11:58       ` Andre Przywara
2017-12-05 15:23         ` Oleksandr Tyshchenko
2017-12-04 22:18       ` Stefano Stabellini
2017-12-05 11:13         ` Oleksandr Tyshchenko
2017-12-05 19:24           ` Stefano Stabellini
2017-12-06 11:28             ` Oleksandr Tyshchenko
2018-05-07 15:39   ` Jan Beulich
2018-05-18 14:36     ` Oleksandr Tyshchenko
2018-05-18 14:41       ` Jan Beulich
2017-11-09 17:09 ` [RFC PATCH 05/31] pmstat: make pmstat functions more generalizable Oleksandr Tyshchenko
2017-12-02  1:21   ` Stefano Stabellini
2017-12-04 16:21     ` Oleksandr Tyshchenko
2017-12-04 22:30       ` Stefano Stabellini
2017-11-09 17:09 ` [RFC PATCH 06/31] cpufreq: make cpufreq driver " Oleksandr Tyshchenko
2017-12-02  1:37   ` Stefano Stabellini
2017-12-04 19:34     ` Oleksandr Tyshchenko
2017-12-04 22:46       ` Stefano Stabellini
2017-12-05 19:29         ` Oleksandr Tyshchenko
2017-12-05 20:48           ` Stefano Stabellini
2017-12-06  7:54             ` Jan Beulich
2017-12-06 23:44               ` Stefano Stabellini
2017-12-07  8:45                 ` Jan Beulich
2017-12-07 20:31                   ` Oleksandr Tyshchenko
2017-12-08  8:07                     ` Jan Beulich
2017-12-08 12:16                       ` Oleksandr Tyshchenko
2017-11-09 17:09 ` [RFC PATCH 07/31] xenpm: Clarify xenpm usage Oleksandr Tyshchenko
2017-11-09 17:13   ` Wei Liu
2017-12-02  1:28     ` Stefano Stabellini
2017-11-09 17:09 ` [RFC PATCH 08/31] xen/device-tree: Add dt_count_phandle_with_args helper Oleksandr Tyshchenko
2017-11-09 17:09 ` [RFC PATCH 09/31] xen/device-tree: Add dt_property_for_each_string macros Oleksandr Tyshchenko
2017-12-04 23:24   ` Stefano Stabellini
2017-12-05 14:19     ` Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 10/31] xen/device-tree: Add dt_property_read_u32_index helper Oleksandr Tyshchenko
2017-12-04 23:29   ` Stefano Stabellini
2017-11-09 17:10 ` [RFC PATCH 11/31] xen/device-tree: Add dt_property_count_elems_of_size helper Oleksandr Tyshchenko
2017-12-04 23:29   ` Stefano Stabellini
2017-11-09 17:10 ` [RFC PATCH 12/31] xen/device-tree: Add dt_property_read_string_helper and friends Oleksandr Tyshchenko
2017-12-04 23:29   ` Stefano Stabellini
2017-11-09 17:10 ` [RFC PATCH 13/31] xen/arm: Add driver_data field to struct device Oleksandr Tyshchenko
2017-12-04 23:31   ` Stefano Stabellini
2017-12-05 11:26   ` Julien Grall
2017-12-05 12:57     ` Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 14/31] xen/arm: Add DEVICE_MAILBOX device class Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 15/31] xen/arm: Store device-tree node per cpu Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 16/31] arm: add SMC wrapper that is compatible with SMCCC Oleksandr Tyshchenko
2017-12-05  2:30   ` Stefano Stabellini
2017-12-05 15:33     ` Volodymyr Babchuk
2017-12-05 17:21       ` Stefano Stabellini
2017-12-05 14:58   ` Julien Grall
2017-12-05 17:08     ` Volodymyr Babchuk
2017-12-05 17:08       ` Julien Grall
2017-12-05 17:20       ` Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 17/31] xen/arm: Add ARM System Control and Power Interface (SCPI) protocol Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 18/31] xen/arm: Add mailbox infrastructure Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 19/31] xen/arm: Introduce ARM SMC based mailbox Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 20/31] xen/arm: Add common header file wrappers.h Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 21/31] xen/arm: Add rxdone_auto flag to mbox_controller structure Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 22/31] xen/arm: Add Xen changes to SCPI protocol Oleksandr Tyshchenko
2017-12-05 21:20   ` Stefano Stabellini
2017-12-05 21:41     ` Julien Grall
2017-12-06 10:08       ` Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 23/31] xen/arm: Add Xen changes to mailbox infrastructure Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 24/31] xen/arm: Add Xen changes to ARM SMC based mailbox Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 25/31] xen/arm: Use non-blocking mode for SCPI protocol Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 26/31] xen/arm: Don't set txdone_poll flag for ARM SMC mailbox Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 27/31] cpufreq: hack: perf->states isn't a real guest handle on ARM Oleksandr Tyshchenko
2017-12-05 21:34   ` Stefano Stabellini
2017-11-09 17:10 ` [RFC PATCH 28/31] xen/arm: Introduce SCPI based CPUFreq driver Oleksandr Tyshchenko
2017-11-09 17:10 ` Oleksandr Tyshchenko [this message]
2017-12-05 22:25   ` [RFC PATCH 29/31] xen/arm: Introduce CPUFreq Interface component Stefano Stabellini
2017-12-06 10:54     ` Oleksandr Tyshchenko
2017-12-07  1:40       ` Stefano Stabellini
2017-11-09 17:10 ` [RFC PATCH 30/31] xen/arm: Build CPUFreq components Oleksandr Tyshchenko
2017-11-09 17:10 ` [RFC PATCH 31/31] xen/arm: Enable CPUFreq on ARM Oleksandr Tyshchenko
2017-11-09 17:18 ` [RFC PATCH 00/31] " Andrii Anisov
2017-11-13 19:40   ` Oleksandr Tyshchenko
2017-11-13 15:21 ` Andre Przywara
2017-11-13 19:40   ` Oleksandr Tyshchenko
2017-11-14 10:49     ` Andre Przywara
2017-11-14 20:46       ` Oleksandr Tyshchenko
2017-11-15  3:03         ` Jassi Brar
2017-11-15 13:28           ` Andre Przywara
2017-11-15 15:18             ` Jassi Brar
2017-11-15 14:28         ` Andre Przywara
2017-11-16 14:57           ` Oleksandr Tyshchenko
2017-11-16 17:04             ` Andre Przywara
2017-11-17 14:01               ` Julien Grall
2017-11-17 18:36                 ` Oleksandr Tyshchenko
2017-11-17 14:55               ` Oleksandr Tyshchenko
2017-11-17 16:41                 ` Andre Przywara
2017-11-17 17:22                   ` Oleksandr Tyshchenko
2017-12-05 22:26 ` Stefano Stabellini
2017-12-06 10:10   ` Oleksandr Tyshchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1510247421-24094-30-git-send-email-olekstysh@gmail.com \
    --to=olekstysh@gmail.com \
    --cc=julien.grall@linaro.org \
    --cc=oleksandr_tyshchenko@epam.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).