[PATCH v2] xen/arm: register clocks used by the hypervisor
Dirk Behme
dirk.behme at de.bosch.com
Thu Jul 7 23:48:40 PDT 2016
Hi,
On 06.07.2016 03:34, Michael Turquette wrote:
> Hi!
>
> Quoting Dirk Behme (2016-06-30 03:32:32)
>> Some clocks might be used by the Xen hypervisor and not by the Linux
>> kernel. If these are not registered by the Linux kernel, they might be
>> disabled by clk_disable_unused() as the kernel doesn't know that they
>> are used. The clock of the serial console handled by Xen is one
>> example for this. It might be disabled by clk_disable_unused() which
>> stops the whole serial output, even from Xen, then.
>
> This whole thread had me confused until I realized that it all boiled
> down to some nomenclature issues (for me).
>
> This code does not _register_ any clocks. It simply gets them and
> enables them, which is what every other clk consumer in the Linux kernel
> does. More details below.
>
>>
>> Up to now, the workaround for this has been to use the Linux kernel
>> command line parameter 'clk_ignore_unused'. See Xen bug
>>
>> http://bugs.xenproject.org/xen/bug/45
>
> clk_ignore_unused is a band-aid, not a proper medical solution. Setting
> that flag will not turn clocks on for you, nor will it guarantee that
> those clocks are never turned off in the future. It looks like you
> figured this out correctly in the patch below but it is worth repeating.
>
> Also the new CLK_IS_CRITICAL flag might be of interest to you, but that
> flag only exists as a way to enable clocks that must be enabled for the
> system to function (hence, "critical") AND when those same clocks do not
> have an accompanying Linux driver to consume them and enable them.
>
>>
>> too.
>>
>> To fix this, we will add the "unused" clocks in Xen to the hypervisor
>> node. The Linux kernel has to register the clocks from the hypervisor
>> node, then.
>>
>> Therefore, check if there is a "clocks" entry in the hypervisor node
>> and if so register the given clocks to the Linux kernel clock
>> framework and with this mark them as used. This prevents the clocks
>> from being disabled.
>>
>> Signed-off-by: Dirk Behme <dirk.behme at de.bosch.com>
>> ---
>> Changes in v2:
>> - Rebase against git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git for-linus-4.8
>> - Add changes to Documentation/devicetree/bindings/arm/xen.txt
>>
>> Documentation/devicetree/bindings/arm/xen.txt | 11 +++++++
>> arch/arm/xen/enlighten.c | 47 +++++++++++++++++++++++++++
>> 2 files changed, 58 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/xen.txt b/Documentation/devicetree/bindings/arm/xen.txt
>> index c9b9321..55dfd3b 100644
>> --- a/Documentation/devicetree/bindings/arm/xen.txt
>> +++ b/Documentation/devicetree/bindings/arm/xen.txt
>> @@ -17,6 +17,17 @@ the following properties:
>> A GIC node is also required.
>> This property is unnecessary when booting Dom0 using ACPI.
>>
>> +Optional properties:
>> +
>> +- clocks: one or more clocks to be registered.
>
> s/registered/consumed/
>
> For appropriate DT binding script to steal I picked one at random:
>
> Documentation/devicetree/bindings/clock/ti/clockdomain.txt
>
>> + Xen hypervisor drivers might replace native drivers, resulting in
>> + clocks not registered by these native drivers. To avoid that these
>> + unregistered clocks are disabled, then, e.g. by clk_disable_unused(),
>> + register them in the hypervisor node.
>> + An example for this are the clocks of the serial driver. If the clocks
>> + used by the serial hardware interface are not registered by the serial
>> + driver the serial output might stop once clk_disable_unused() is called.
>> +
>> To support UEFI on Xen ARM virtual platforms, Xen populates the FDT "uefi" node
>> under /hypervisor with following parameters:
>>
>> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
>> index 47acb36..5c546d0 100644
>> --- a/arch/arm/xen/enlighten.c
>> +++ b/arch/arm/xen/enlighten.c
>> @@ -24,6 +24,7 @@
>> #include <linux/of_fdt.h>
>> #include <linux/of_irq.h>
>> #include <linux/of_address.h>
>> +#include <linux/clk-provider.h>
>
> s/clk-provider.h/clk.h/
>
> clk-provider.h is only used for providers and this bit of code is a
> consumer.
It seems we need clk-provider.h for of_clk_get_parent_count()?
>> #include <linux/cpuidle.h>
>> #include <linux/cpufreq.h>
>> #include <linux/cpu.h>
>> @@ -444,6 +445,52 @@ static int __init xen_pm_init(void)
>> }
>> late_initcall(xen_pm_init);
>>
>> +/*
>> + * Check if we want to register some clocks, that they
>> + * are not freed because unused by clk_disable_unused().
>> + * E.g. the serial console clock.
>> + */
>> +static int __init xen_arm_register_clks(void)
>> +{
>> + struct clk *clk;
>> + struct device_node *xen_node;
>> + unsigned int i, count;
>> + int ret = 0;
>> +
>> + xen_node = of_find_compatible_node(NULL, NULL, "xen,xen");
>> + if (!xen_node) {
>> + pr_err("Xen support was detected before, but it has disappeared\n");
>> + return -EINVAL;
>> + }
>> +
>> + count = of_clk_get_parent_count(xen_node);
>> + if (!count)
>> + goto out;
>> +
>> + for (i = 0; i < count; i++) {
>> + clk = of_clk_get(xen_node, i);
>
> Is there a struct device we can use here?
It doesn't look so. Julien?
> It would be better to use
> devm_clk_get if possible.
Best regards
Dirk
More information about the linux-arm-kernel
mailing list