Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] PM / OPP: Introduce ti-opp-supply driver
From: Dave Gerlach @ 2017-12-13 20:33 UTC (permalink / raw)
  To: linux-arm-kernel

Some SoCs, such as Texas Instruments DRA7 family, have complex requirements for
scaling voltages and supplies when doing things like DVFS. For example, for
cpufreq on dra7xx, the cpu-supply must be scaled as is normally done however
there is also an Adaptive Body Bias (ABB) regulator that should be scaled at
the same time as the main supply in sequence depending on the transition,
explained earlier by Nishanth Menon here [1]. In addition to this, each
possible operating point has a corresponding optimized voltage value stored in
a register (Adaptive Voltage Scaling Class 0) that can be used instead of the
nominal value.

The OPP framework is now able to to handle DVFS transitions through the
provided dev_pm_opp_set_rate API and cpufreq-dt is doing this. Viresh Kumar
extended this to allow platforms to register a transition helper through the
use of dev_pm_opp_register_set_opp_helper and has also extended the OPP core to
support registering multiple regulators. By providing a TI platform specific
opp_helper function and registering the proepr regulators with the OPP core we
can meet the above requirements for properly changing DVFS state of the cpu
device.

This series introduces a ti-opp-supply driver that overrides the standard
single regulator DVFS transition handler to handle scaling the ABB regulator in
sequence with the normal supply and programing AVS voltages through a custom
opp_helper that is registered. The ti-cpufreq driver is extended to allow
registering the proper regulators needed for the CPU if the platform supports
multi regulators and is also changed to a regular driver so that it can defer
probe if needed as it now may have to if the regulators are not ready.

This series only contains driver changes and binding docs, DT patches will be
sent later but I have pushed them all here for anyone curious [2].

This series is required to enable the highest 1.5GHz OPP on dra7/am57 platforms
that support it but all dra7/am57 platforms will make use of this for all OPPs.

Regards,
Dave

[1] https://marc.info/?l=linux-pm&m=145684495832764&w=2
[2] https://github.com/dgerlach/linux-pm/tree/upstream/v4.15/ti-multireg-support

Dave Gerlach (4):
  cpufreq: ti-cpufreq: Convert to module_platform_driver
  cpufreq: ti-cpufreq: Add support for multiple regulators
  dt-bindings: opp: Introduce ti-opp-supply bindings
  PM / OPP: Add ti-opp-supply driver

 .../bindings/opp/ti-omap5-opp-supply.txt           |  63 +++
 drivers/cpufreq/ti-cpufreq.c                       |  51 ++-
 drivers/opp/Makefile                               |   1 +
 drivers/opp/ti-opp-supply.c                        | 428 +++++++++++++++++++++
 4 files changed, 537 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/opp/ti-omap5-opp-supply.txt
 create mode 100644 drivers/opp/ti-opp-supply.c

-- 
2.15.1

^ permalink raw reply

* [PATCH v8 9/9] KVM: arm/arm64: Update timer and forwarded irq documentation
From: Marc Zyngier @ 2017-12-13 20:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213104602.16383-10-christoffer.dall@linaro.org>

On Wed, 13 Dec 2017 10:46:02 +0000,
Christoffer Dall wrote:
> 
> Now when we've reworked how mapped level-triggered interrupts are
> processed for the timer interrupts, we update the documentation
> correspondingly.

Seems like the documentation is more out of date than we thought, see
below.

> 
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
>  Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt | 50 ++++++++++------------
>  1 file changed, 23 insertions(+), 27 deletions(-)
> 
> diff --git a/Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt b/Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt
> index 38bca2835278..f68c7d95a341 100644
> --- a/Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt
> +++ b/Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt
> @@ -7,9 +7,10 @@ allowing software to inject virtual interrupts to a VM, which the guest
>  OS sees as regular interrupts.  The code is famously known as the VGIC.
>  
>  Some of these virtual interrupts, however, correspond to physical
> -interrupts from real physical devices.  One example could be the
> -architected timer, which itself supports virtualization, and therefore
> -lets a guest OS program the hardware device directly to raise an
> +interrupts from real physical devices.  One example could be the ARM
> +Generic Timers (also known as the "architected timers"), which are
> +directly assigned to a VM while it's running, and therefore
> +makes it possible for guest OSes to program the timers directly to raise an
>  interrupt at some point in time.  When such an interrupt is raised, the
>  host OS initially handles the interrupt and must somehow signal this
>  event as a virtual interrupt to the guest.  Another example could be a
> @@ -37,7 +38,7 @@ inactive.
>  
>  The LRs include an extra bit, called the HW bit.  When this bit is set,
>  KVM must also program an additional field in the LR, the physical IRQ
> -number, to link the virtual with the physical IRQ.
> +number, to link the virtual and physical IRQs together.
>  
>  When the HW bit is set, KVM must EITHER set the Pending OR the Active
>  bit, never both at the same time.
> @@ -59,21 +60,21 @@ The state of forwarded physical interrupts is managed in the following way:
>    - LR.Pending will stay set as long as the guest has not acked the interrupt.
>    - LR.Pending transitions to LR.Active on the guest read of the IAR, as
>      expected.
> -  - On guest EOI, the *physical distributor* active bit gets cleared,
> +  - On guest deactivate, the *physical distributor* active bit gets cleared,
>      but the LR.Active is left untouched (set).

Is this true? I seem to remember that we established it wasn't (back
when we redesigned the vgic). Certainly, the current code relies on
the Active bit being cleared in the LR as well as in the physical
distributor.

>    - KVM clears the LR on VM exits when the physical distributor
>      active state has been cleared.

And this isn't either, if my above assertion stands.

>  
>  (*): The host handling is slightly more complicated.  For some forwarded
> -interrupts (shared), KVM directly sets the active state on the physical
> -distributor before entering the guest, because the interrupt is never actually
> -handled on the host (see details on the timer as an example below).  For other
> -forwarded interrupts (non-shared) the host does not deactivate the interrupt
> -when the host ISR completes, but leaves the interrupt active until the guest
> -deactivates it.  Leaving the interrupt active is allowed, because Linux
> -configures the physical GIC with EOIMode=1, which causes EOI operations to
> -perform a priority drop allowing the GIC to receive other interrupts of the
> -default priority.
> +interrupts (shared), in some cases, KVM directly sets the active state
> +on the physical distributor before entering the guest, because the
> +interrupt is never actually handled on the host (see details on the
> +timer as an example below).  In other cases, the host does not

This isn't true either. We now handle the timer interrupt on the host.

> +deactivate the interrupt when the host ISR completes, but leaves the
> +interrupt active until the guest deactivates it.  Leaving the interrupt
> +active is allowed, because Linux configures the physical GIC with
> +EOIMode=1, which causes EOI operations to perform a priority drop
> +allowing the GIC to receive other interrupts of the default priority.
>  
>  
>  Forwarded Edge and Level Triggered PPIs and SPIs
> @@ -170,18 +171,13 @@ instead:
>  
>  1.  KVM runs the VCPU
>  2.  The guest programs the time to fire in T+100
> -4.  At T+100 the timer fires and a physical IRQ causes the VM to exit
> +3.  At T+100 the timer fires and a physical IRQ causes the VM to exit
>      (note that this initially only traps to EL2 and does not run the host ISR
>      until KVM has returned to the host).
> -5.  With interrupts still disabled on the CPU coming back from the guest, KVM
> -    stores the virtual timer state to memory and disables the virtual hw timer.
> -6.  KVM looks at the timer state (in memory) and injects a forwarded physical
> -    interrupt because it concludes the timer has expired.
> -7.  KVM marks the timer interrupt as active on the physical distributor
> -7.  KVM enables the timer, enables interrupts, and runs the VCPU
> -
> -Notice that again the forwarded physical interrupt is injected to the
> -guest without having actually been handled on the host.  In this case it
> -is because the physical interrupt is never actually seen by the host because the
> -timer is disabled upon guest return, and the virtual forwarded interrupt is
> -injected on the KVM guest entry path.
> +4.  When KVM returns to EL1 and enables interrupts, the timer interrupt
> +    fires again, and the kvm arch timer ISR runs and injects a virtual
> +    interrupt to the guest.
> +5.  Because the timer interrupt has the vcpu affinity set, as the ISR
> +    completes, the physical interrupt stays active on the physical
> +    distributor.
> +6.  KVM enables the timer, enables interrupts, and runs the VCPU
> -- 
> 2.14.2
> 

Thanks,

	M.

^ permalink raw reply

* [PATCH v9 2/2] media: i2c: Add the ov7740 image sensor driver
From: Sakari Ailus @ 2017-12-13 20:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171211013146.2497-3-wenyou.yang@microchip.com>

Hi Wenyou,

Wenyou Yang wrote:
...
> +static int ov7740_start_streaming(struct ov7740 *ov7740)
> +{
> +	int ret;
> +
> +	if (ov7740->fmt) {
> +		ret = regmap_multi_reg_write(ov7740->regmap,
> +					     ov7740->fmt->regs,
> +					     ov7740->fmt->reg_num);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (ov7740->frmsize) {
> +		ret = regmap_multi_reg_write(ov7740->regmap,
> +					     ov7740->frmsize->regs,
> +					     ov7740->frmsize->reg_num);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return __v4l2_ctrl_handler_setup(ov7740->subdev.ctrl_handler);

I believe you're still setting the controls after starting streaming.

-- 
Sakari Ailus
sakari.ailus at iki.fi

^ permalink raw reply

* [PATCH v8 8/9] KVM: arm/arm64: Avoid work when userspace iqchips are not used
From: Marc Zyngier @ 2017-12-13 20:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213104602.16383-9-christoffer.dall@linaro.org>

On Wed, 13 Dec 2017 10:46:01 +0000,
Christoffer Dall wrote:
> 
> We currently check if the VM has a userspace irqchip on every exit from
> the VCPU, and if so, we do some work to ensure correct timer behavior.
> This is unfortunate, as we could avoid doing any work entirely, if we
> didn't have to support irqchip in userspace.
> 
> Realizing the userspace irqchip on ARM is mostly a developer or hobby
> feature, and is unlikely to be used in servers or other scenarios where
> performance is a priority, we can use a refcounted static key to only
> check the irqchip configuration when we have at least one VM that uses
> an irqchip in userspace.
> 
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>

On its own, this doesn't seem to be that useful. As far as I can see,
it saves us a load from the kvm structure before giving up. I think it
is more the cumulative effect of this load that could have an impact,
but you're only dealing with it at a single location.

How about making this a first class helper and redefine
irqchip_in_kernel as such:

static inline bool irqchip_in_kernel(struct kvm *kvm)
{
	if (static_branch_unlikely(&userspace_irqchip_in_use) &&
	    unlikely(!irqchip_in_kernel(kvm)))
		return true;

	return false;
}

and move that static key to a more central location?

> ---
>  virt/kvm/arm/arch_timer.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index f8d09665ddce..73d262c4712b 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -51,6 +51,8 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
>  				 struct arch_timer_context *timer_ctx);
>  static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx);
>  
> +static DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
> +
>  u64 kvm_phys_timer_read(void)
>  {
>  	return timecounter->cc->read(timecounter->cc);
> @@ -562,7 +564,8 @@ static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu)
>  
>  void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
>  {
> -	unmask_vtimer_irq_user(vcpu);
> +	if (static_branch_unlikely(&userspace_irqchip_in_use))
> +		unmask_vtimer_irq_user(vcpu);
>  }
>  
>  int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
> @@ -767,6 +770,8 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
>  	soft_timer_cancel(&timer->bg_timer, &timer->expired);
>  	soft_timer_cancel(&timer->phys_timer, NULL);
>  	kvm_vgic_unmap_phys_irq(vcpu, vtimer->irq.irq);
> +	if (timer->enabled && !irqchip_in_kernel(vcpu->kvm))
> +		static_branch_dec(&userspace_irqchip_in_use);
>  }
>  
>  static bool timer_irqs_are_valid(struct kvm_vcpu *vcpu)
> @@ -819,8 +824,10 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
>  		return 0;
>  
>  	/* Without a VGIC we do not map virtual IRQs to physical IRQs */
> -	if (!irqchip_in_kernel(vcpu->kvm))
> +	if (!irqchip_in_kernel(vcpu->kvm)) {
> +		static_branch_inc(&userspace_irqchip_in_use);
>  		goto no_vgic;
> +	}
>  
>  	if (!vgic_initialized(vcpu->kvm))
>  		return -ENODEV;
> -- 
> 2.14.2
> 

Thanks,

	M.

^ permalink raw reply

* [PATCH][next] net: phy: meson-gxl: make function meson_gxl_read_status static
From: David Miller @ 2017-12-13 20:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171212130311.17185-1-colin.king@canonical.com>

From: Colin King <colin.king@canonical.com>
Date: Tue, 12 Dec 2017 13:03:11 +0000

> From: Colin Ian King <colin.king@canonical.com>
> 
> The function meson_gxl_read_status is local to the source and does
> not need to be in global scope, so make it static.
> 
> Cleans up sparse warning:
> symbol 'meson_gxl_read_status' was not declared. Should it be static?
> 
> Signed-off-by: Colin Ian King <colin.king@canonical.com>

Applied.

^ permalink raw reply

* [PATCH 2/2] ARM: dts: vf610-zii-dev: use XAUI for DSA link ports
From: David Miller @ 2017-12-13 19:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <E1eOgsp-0001Ab-9x@rmk-PC.armlinux.org.uk>

From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Tue, 12 Dec 2017 09:29:51 +0000

> Use XAUI rather than XGMII for DSA link ports, as this is the interface
> mode that the switches actually use. XAUI is the 4 lane bus with clock
> per direction, whereas XGMII is a 32 bit bus with clock.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> ---
> This must be applied along with patch 1 to avoid breakage.

Applied.

^ permalink raw reply

* [PATCH 1/2] net: dsa: allow XAUI phy interface mode
From: David Miller @ 2017-12-13 19:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <E1eOgsk-0001AU-5z@rmk-PC.armlinux.org.uk>

From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Tue, 12 Dec 2017 09:29:46 +0000

> XGMII is a 32-bit bus plus two clock signals per direction.  XAUI is
> four serial lanes per direction.  The 88e6190 supports XAUI but not
> XGMII as it doesn't have enough pins.  The same is true of 88e6176.
> 
> Match on PHY_INTERFACE_MODE_XAUI for the XAUI port type, but keep
> accepting XGMII for backwards compatibility.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Applied.

^ permalink raw reply

* [linux-sunxi] [PATCH v2 3/6] ARM: sun4i: Convert to CCU
From: Kevin Hilman @ 2017-12-13 19:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213171358.oocp24c2mdon45o5@plaes.org>

On Wed, Dec 13, 2017 at 9:13 AM, Priit Laes <plaes@plaes.org> wrote:
> On Wed, Dec 13, 2017 at 05:09:33PM +0000, Priit Laes wrote:
>> On Tue, Dec 12, 2017 at 01:24:52PM -0800, Kevin Hilman wrote:
>> > On Tue, Dec 12, 2017 at 9:26 AM, Priit Laes <plaes@plaes.org> wrote:
>> > > On Mon, Dec 11, 2017 at 02:22:30PM -0800, Kevin Hilman wrote:
>> > >> On Sun, Mar 26, 2017 at 10:20 AM, Priit Laes <plaes@plaes.org> wrote:
>> > >> > Convert sun4i-a10.dtsi to new CCU driver.
>> > >> >
>> > >> > Signed-off-by: Priit Laes <plaes@plaes.org>
>> > >>
>> > >> I finally got around to bisecting a mainline boot failure on
>> > >> sun4i-a10-cubieboard that's been happening for quite a while.  Based
>> > >> on on kernelci.org, it showed up sometime during the v4.15 merge
>> > >> window[1].  It bisected down to this commit (in mainline as commit
>> > >> 41193869f2bdb585ce09bfdd16d9482aadd560ad).
>> > >>
>> > >> When it fails, there is no output on the serial console, so I don't
>> > >> know exactly how it's failing, just that it no longer boots.
>> > >
>> > > We tried out latest 4.15 with various compilers and it works:
>> > > - gcc version 7.1.1 20170622 (Red Hat Cross 7.1.1-3) (GCC) - A10 Gemei G9 tablet
>> > > - gcc 7.2.0-debian - A10 Cubieboard
>> >
>> > And you can reproduce the bug with gcc5 or gcc6?
>>
>> Tried following commits on Gemei G9 (A10 tablet):
>> * 4.15.0-rc3-00037-gd39a01eff9af - latest master
>> * 4.14.0-rc1-00002-g41193869f2bd - the exact commit, causing the issue.
>>
>> With the same Linaro toolchain:
>> (gcc version 5.3.1 20160412 (Linaro GCC 5.3-2016.05))
>
> And I also tried the same dtb and zImage from kernelci page [1] and it works with
> that too...
>
> https://storage.kernelci.org/mainline/master/v4.15-rc3/arm/sunxi_defconfig/

Can you share a full boot-log (including all the u-boot output etc.)
so I can see exactly how the kernel is being loaded?    Especially the
u-boot version?

As $SUBJECT patch seems to be changing clocks around, perhaps this is
an issue where some u-boot dependency is uncovered, and older versions
of u-boot don't play well with this change.

Kevin

^ permalink raw reply

* [PATCH v8 7/9] KVM: arm/arm64: Provide a get_input_level for the arch timer
From: Marc Zyngier @ 2017-12-13 19:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213104602.16383-8-christoffer.dall@linaro.org>

On Wed, 13 Dec 2017 10:46:00 +0000,
Christoffer Dall wrote:
> 
> The VGIC can now support the life-cycle of mapped level-triggered
> interrupts, and we no longer have to read back the timer state on every
> exit from the VM if we had an asserted timer interrupt signal, because
> the VGIC already knows if we hit the unlikely case where the guest
> disables the timer without ACKing the virtual timer interrupt.
> 
> This means we rework a bit of the code to factor out the functionality
> to snapshot the timer state from vtimer_save_state(), and we can reuse
> this functionality in the sync path when we have an irqchip in
> userspace, and also to support our implementation of the
> get_input_level() function for the timer.
> 
> This change also means that we can no longer rely on the timer's view of
> the interrupt line to set the active state, because we no longer
> maintain this state for mapped interrupts when exiting from the guest.
> Instead, we only set the active state if the virtual interrupt is
> active, and otherwise we simply let the timer fire again and raise the
> virtual interrupt from the ISR.
> 
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>

	M.

^ permalink raw reply

* [PATCH v8 3/9] KVM: arm/arm64: Don't cache the timer IRQ level
From: Marc Zyngier @ 2017-12-13 19:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213104602.16383-4-christoffer.dall@linaro.org>

On Wed, 13 Dec 2017 10:45:56 +0000,
Christoffer Dall wrote:
> 
> The timer was modeled after a strict idea of modelling an interrupt line
> level in software, meaning that only transitions in the level needed to
> be reported to the VGIC.  This works well for the timer, because the
> arch timer code is in complete control of the device and can track the
> transitions of the line.
> 
> However, as we are about to support using the HW bit in the VGIC not
> just for the timer, but also for VFIO which cannot track transitions of
> the interrupt line, we have to decide on an interface for level
> triggered mapped interrupts to the GIC, which both the timer and VFIO
> can use.
> 
> VFIO only sees an asserting transition of the physical interrupt line,
> and tells the VGIC when that happens.  That means that part of the
> interrupt flow is offloaded to the hardware.
> 
> To use the same interface for VFIO devices and the timer, we therefore
> have to change the timer (we cannot change VFIO because it doesn't know
> the details of the device it is assigning to a VM).
> 
> Luckily, changing the timer is simple, we just need to stop 'caching'
> the line level, but instead let the VGIC know the state of the timer
> every time there is a potential change in the line level, and when the
> line level should be asserted from the timer ISR.  The VGIC can ignore
> extra notifications using its validate mechanism.
> 
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>

	M.

^ permalink raw reply

* [PATCH 2/2] arm: dts: sun8i: a83t: Add an unit address to the memory node
From: Corentin Labbe @ 2017-12-13 19:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213193715.31039-1-clabbe.montjoie@gmail.com>

This will fix the following warning:
Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name

Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 715719f9ea2e..bddde0141f24 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -160,7 +160,7 @@
 		};
 	};
 
-	memory {
+	memory at 40000000 {
 		reg = <0x40000000 0x80000000>;
 		device_type = "memory";
 	};
-- 
2.13.6

^ permalink raw reply related

* [PATCH 1/2] arm: dts: sun8i: a83t: remove leading zero from cpucfg node address
From: Corentin Labbe @ 2017-12-13 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

This will fix the following warning:
Warning (simple_bus_reg): Node /soc/cpucfg at 01700000 simple-bus unit address format error, expected "1700000"

Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
---
 arch/arm/boot/dts/sun8i-a83t.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 7b372acf4bf6..715719f9ea2e 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -377,7 +377,7 @@
 			#reset-cells = <1>;
 		};
 
-		cpucfg at 01700000 {
+		cpucfg at 1700000 {
 			compatible = "allwinner,sun9i-a80-cpucfg";
 			reg = <0x01700000 0x100>;
 		};
-- 
2.13.6

^ permalink raw reply related

* arm64 crashkernel fails to boot on acpi-only machines due to ACPI regions being no longer mapped as NOMAP
From: Bhupesh SHARMA @ 2017-12-13 19:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu_G8kBEAdAznVauZVAdJOFkr1vmu0Gf6tOwJfH2CgdufA@mail.gmail.com>

Hi Ard, Akashi,

On Wed, Dec 13, 2017 at 5:47 PM, Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> On 13 December 2017 at 12:16, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
>> On Wed, Dec 13, 2017 at 10:49:27AM +0000, Ard Biesheuvel wrote:
>>> On 13 December 2017 at 10:26, AKASHI Takahiro
>>> <takahiro.akashi@linaro.org> wrote:
>>> > Bhupesh, Ard,
>>> >
>>> > On Wed, Dec 13, 2017 at 03:21:59AM +0530, Bhupesh Sharma wrote:
>>> >> Hi Ard, Akashi
>>> >>
>>> > (snip)
>>> >
>>> >> Looking deeper into the issue, since the arm64 kexec-tools uses the
>>> >> 'linux,usable-memory-range' dt property to allow crash dump kernel to
>>> >> identify its own usable memory and exclude, at its boot time, any
>>> >> other memory areas that are part of the panicked kernel's memory.
>>> >> (see https://www.kernel.org/doc/Documentation/devicetree/bindings/chosen.txt
>>> >> , for details)
>>> >
>>> > Right.
>>> >
>>> >> 1). Now when 'kexec -p' is executed, this node is patched up only
>>> >> with the crashkernel memory range:
>>> >>
>>> >>                 /* add linux,usable-memory-range */
>>> >>                 nodeoffset = fdt_path_offset(new_buf, "/chosen");
>>> >>                 result = fdt_setprop_range(new_buf, nodeoffset,
>>> >>                                 PROP_USABLE_MEM_RANGE, &crash_reserved_mem,
>>> >>                                 address_cells, size_cells);
>>> >>
>>> >> (see https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git/tree/kexec/arch/arm64/kexec-arm64.c#n465
>>> >> , for details)
>>> >>
>>> >> 2). This excludes the ACPI reclaim regions irrespective of whether
>>> >> they are marked as System RAM or as RESERVED. As,
>>> >> 'linux,usable-memory-range' dt node is patched up only with
>>> >> 'crash_reserved_mem' and not 'system_memory_ranges'
>>> >>
>>> >> 3). As a result when the crashkernel boots up it doesn't find this
>>> >> ACPI memory and crashes while trying to access the same:
>>> >>
>>> >> # kexec -p /boot/vmlinuz-`uname -r` --initrd=/boot/initramfs-`uname
>>> >> -r`.img --reuse-cmdline -d
>>> >>
>>> >> [snip..]
>>> >>
>>> >> Reserved memory range
>>> >> 000000000e800000-000000002e7fffff (0)
>>> >>
>>> >> Coredump memory ranges
>>> >> 0000000000000000-000000000e7fffff (0)
>>> >> 000000002e800000-000000003961ffff (0)
>>> >> 0000000039d40000-000000003ed2ffff (0)
>>> >> 000000003ed60000-000000003fbfffff (0)
>>> >> 0000001040000000-0000001ffbffffff (0)
>>> >> 0000002000000000-0000002ffbffffff (0)
>>> >> 0000009000000000-0000009ffbffffff (0)
>>> >> 000000a000000000-000000affbffffff (0)
>>> >>
>>> >> 4). So if we revert Ard's patch or just comment the fixing up of the
>>> >> memory cap'ing passed to the crash kernel inside
>>> >> 'arch/arm64/mm/init.c' (see below):
>>> >>
>>> >> static void __init fdt_enforce_memory_region(void)
>>> >> {
>>> >>         struct memblock_region reg = {
>>> >>                 .size = 0,
>>> >>         };
>>> >>
>>> >>         of_scan_flat_dt(early_init_dt_scan_usablemem, &reg);
>>> >>
>>> >>         if (reg.size)
>>> >>                 //memblock_cap_memory_range(reg.base, reg.size); /*
>>> >> comment this out */
>>> >> }
>>> >
>>> > Please just don't do that. It can cause a fatal damage on
>>> > memory contents of the *crashed* kernel.
>>> >
>>> >> 5). Both the above temporary solutions fix the problem.
>>> >>
>>> >> 6). However exposing all System RAM regions to the crashkernel is not
>>> >> advisable and may cause the crashkernel or some crashkernel drivers to
>>> >> fail.
>>> >>
>>> >> 6a). I am trying an approach now, where the ACPI reclaim regions are
>>> >> added to '/proc/iomem' separately as ACPI reclaim regions by the
>>> >> kernel code and on the other hand the user-space 'kexec-tools' will
>>> >> pick up the ACPI reclaim regions from '/proc/iomem' and add it to the
>>> >> dt node 'linux,usable-memory-range'
>>> >
>>> > I still don't understand why we need to carry over the information
>>> > about "ACPI Reclaim memory" to crash dump kernel. In my understandings,
>>> > such regions are free to be reused by the kernel after some point of
>>> > initialization. Why does crash dump kernel need to know about them?
>>> >
>>>
>>> Not really. According to the UEFI spec, they can be reclaimed after
>>> the OS has initialized, i.e., when it has consumed the ACPI tables and
>>> no longer needs them. Of course, in order to be able to boot a kexec
>>> kernel, those regions needs to be preserved, which is why they are
>>> memblock_reserve()'d now.
>>
>> For my better understandings, who is actually accessing such regions
>> during boot time, uefi itself or efistub?
>>
>
> No, only the kernel. This is where the ACPI tables are stored. For
> instance, on QEMU we have
>
>  ACPI: RSDP 0x0000000078980000 000024 (v02 BOCHS )
>  ACPI: XSDT 0x0000000078970000 000054 (v01 BOCHS  BXPCFACP 00000001
>   01000013)
>  ACPI: FACP 0x0000000078930000 00010C (v05 BOCHS  BXPCFACP 00000001
> BXPC 00000001)
>  ACPI: DSDT 0x0000000078940000 0011DA (v02 BOCHS  BXPCDSDT 00000001
> BXPC 00000001)
>  ACPI: APIC 0x0000000078920000 000140 (v03 BOCHS  BXPCAPIC 00000001
> BXPC 00000001)
>  ACPI: GTDT 0x0000000078910000 000060 (v02 BOCHS  BXPCGTDT 00000001
> BXPC 00000001)
>  ACPI: MCFG 0x0000000078900000 00003C (v01 BOCHS  BXPCMCFG 00000001
> BXPC 00000001)
>  ACPI: SPCR 0x00000000788F0000 000050 (v02 BOCHS  BXPCSPCR 00000001
> BXPC 00000001)
>  ACPI: IORT 0x00000000788E0000 00007C (v00 BOCHS  BXPCIORT 00000001
> BXPC 00000001)
>
> covered by
>
>  efi:   0x0000788e0000-0x00007894ffff [ACPI Reclaim Memory ...]
>  ...
>  efi:   0x000078970000-0x00007898ffff [ACPI Reclaim Memory ...]
>
>
>>> So it seems that kexec does not honour the memblock_reserve() table
>>> when booting the next kernel.
>>
>> not really.
>>
>>> > (In other words, can or should we skip some part of ACPI-related init code
>>> > on crash dump kernel?)
>>> >
>>>
>>> I don't think so. And the change to the handling of ACPI reclaim
>>> regions only revealed the bug, not created it (given that other
>>> memblock_reserve regions may be affected as well)
>>
>> As whether we should honor such reserved regions over kexec'ing
>> depends on each one's specific nature, we will have to take care one-by-one.
>> As a matter of fact, no information about "reserved" memblocks is
>> exposed to user space (via proc/iomem).
>>
>
> That is why I suggested (somewhere in this thread?) to not expose them
> as 'System RAM'. Do you think that could solve this?

I agree. So how about my proposal (please see my last reply) - to
expose these regions as "ACPI reclaim regions" in /proc/iomem.

Please note that we already have several instances where the driver
regions are already explicitly labelled by different concise names
across /proc/iomem, for e.g.:

# cat /proc/iomem | grep -i serial

  1c021000-1c02101f : serial

If we expose only the ACPI reclaim regions to the crashkernel (along
with the normal crash kernel memory range), we avoid exposing all
System RAM or reserved regions to the crashkernel which may cause
issues with crashkernel boot or crash coredump save operations.

And we can also accordingly modify the 'kexec-tools' to pick these
regions along with the normal crash kernel memory range and append
them to the 'linux,usable-memory-range' dt node, so that the crash
kernel can operate on them.

If you think this ok, I can try to send a RFC patch later this week.

Please let me know.

Regards,
Bhupesh


>>>
>>> >> 6b). The kernel code currently looks like the following:
>>> >>
>>> >> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
>>> >> index 30ad2f085d1f..867bdec7c692 100644
>>> >> --- a/arch/arm64/kernel/setup.c
>>> >> +++ b/arch/arm64/kernel/setup.c
>>> >> @@ -206,6 +206,7 @@ static void __init request_standard_resources(void)
>>> >>  {
>>> >>      struct memblock_region *region;
>>> >>      struct resource *res;
>>> >> +    phys_addr_t addr_start, addr_end;
>>> >>
>>> >>      kernel_code.start   = __pa_symbol(_text);
>>> >>      kernel_code.end     = __pa_symbol(__init_begin - 1);
>>> >> @@ -218,9 +219,17 @@ static void __init request_standard_resources(void)
>>> >>              res->name  = "reserved";
>>> >>              res->flags = IORESOURCE_MEM;
>>> >>          } else {
>>> >> -            res->name  = "System RAM";
>>> >> -            res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
>>> >> +            addr_start =
>>> >> __pfn_to_phys(memblock_region_reserved_base_pfn(region));
>>> >> +            addr_end =
>>> >> __pfn_to_phys(memblock_region_reserved_end_pfn(region)) - 1;
>>> >> +            if ((efi_mem_type(addr_start) == EFI_ACPI_RECLAIM_MEMORY)
>>> >> || (efi_mem_type(addr_end) == EFI_ACPI_RECLAIM_MEMORY)) {
>>> >> +                res->name  = "ACPI reclaim region";
>>> >> +                res->flags = IORESOURCE_MEM;
>>> >> +            } else {
>>> >> +                res->name  = "System RAM";
>>> >> +                res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
>>> >> +            }
>>> >>          }
>>> >> +
>>> >>          res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
>>> >>          res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
>>> >>
>>> >> @@ -292,6 +301,7 @@ void __init setup_arch(char **cmdline_p)
>>> >>
>>> >>      request_standard_resources();
>>> >>
>>> >> +    efi_memmap_unmap();
>>> >>      early_ioremap_reset();
>>> >>
>>> >>      if (acpi_disabled)
>>> >> diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
>>> >> index 80d1a885def5..a7c522eac640 100644
>>> >> --- a/drivers/firmware/efi/arm-init.c
>>> >> +++ b/drivers/firmware/efi/arm-init.c
>>> >> @@ -259,7 +259,6 @@ void __init efi_init(void)
>>> >>
>>> >>      reserve_regions();
>>> >>      efi_esrt_init();
>>> >> -    efi_memmap_unmap();
>>> >>
>>> >>      memblock_reserve(params.mmap & PAGE_MASK,
>>> >>               PAGE_ALIGN(params.mmap_size +
>>> >>
>>> >>
>>> >> After this change the ACPI reclaim regions are properly recognized in
>>> >> '/proc/iomem':
>>> >>
>>> >> # cat /proc/iomem | grep -i ACPI
>>> >> 396c0000-3975ffff : ACPI reclaim region
>>> >> 39770000-397affff : ACPI reclaim region
>>> >> 398a0000-398bffff : ACPI reclaim region
>>> >>
>>> >> 6c). I am currently changing the 'kexec-tools' and will finish the
>>> >> testing over the next few days.
>>> >>
>>> >> I just wanted to know your opinion on this issue, so that I will be
>>> >> able to propose a fix on the above lines.
>>> >>
>>> >> Also Cc'ing kexec mailing list for more inputs on changes proposed to
>>> >> kexec-tools.
>>> >>
>>> >> Thanks,
>>> >> Bhupesh

^ permalink raw reply

* [PATCH] phy: rockchip-typec: Try to turn the PHY on several times
From: Doug Anderson @ 2017-12-13 19:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAFqH_52coxz73waki18JicDsndG9bzEw6Zbq6TCOST0J3N+NXQ@mail.gmail.com>

Hi,

On Wed, Dec 13, 2017 at 4:41 AM, Enric Balletbo Serra
<eballetbo@gmail.com> wrote:
> Hi Doug,
>
> 2017-12-11 22:45 GMT+01:00 Douglas Anderson <dianders@chromium.org>:
>> Bind / unbind stress testing of the USB controller on rk3399 found
>> that we'd often end up with lots of failures that looked like this:
>>
>>   phy phy-ff800000.phy.9: phy poweron failed --> -110
>>   dwc3 fe900000.dwc3: failed to initialize core
>>   dwc3: probe of fe900000.dwc3 failed with error -110
>>
>> Those errors were sometimes seen at bootup too, in which case USB
>> peripherals wouldn't work until unplugged and re-plugged in.
>>
>> I spent some time trying to figure out why the PHY was failing to
>> power on but I wasn't able to.  Possibly this has to do with the fact
>> that the PHY docs say that the USB controller "needs to be held in
>> reset to hold pipe power state in P2 before initializing the Type C
>> PHY" but that doesn't appear to be easy to do with the dwc3 driver
>> today.  Messing around with the ordering of the reset vs. the PHY
>> initialization in the dwc3 driver didn't seem to fix things.
>>
>> I did, however, find that if I simply retry the power on it seems to
>> have a good chance of working.  So let's add some retries.  I ran a
>> pretty tight bind/unbind loop overnight.  When I did so, I found that
>> I need to retry between 1% and 2% of the time.  Overnight I found only
>> a small handful of times where I needed 2 retries.  I never found a
>> case where I needed 3 retries.
>>
>> I'm completely aware of the fact that this is quite an ugly hack and I
>> wish I didn't have to resort to it, but I have no other real idea how
>> to make this hardware reliable.  If Rockchip in the future can come up
>> with a solution we can always revert this hack.  Until then, let's at
>> least have something that works.
>>
>> This patch is tested atop Enric's latest dwc3 patch series ending at:
>>   https://patchwork.kernel.org/patch/10095527/
>> ...but it could be applied independently of that series without any
>> bad effects.
>>
>> For some more details on this bug, you can refer to:
>>   https://bugs.chromium.org/p/chromium/issues/detail?id=783464
>>
>> Signed-off-by: Douglas Anderson <dianders@chromium.org>
>> ---
>>
>>  drivers/phy/rockchip/phy-rockchip-typec.c | 24 ++++++++++++++++++++++--
>>  1 file changed, 22 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
>> index ee85fa0ca4b0..5c2157156ce1 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-typec.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-typec.c
>> @@ -349,6 +349,8 @@
>>  #define MODE_DFP_USB                   BIT(1)
>>  #define MODE_DFP_DP                    BIT(2)
>>
>> +#define POWER_ON_TRIES                 5
>> +
>
> I did the test of increase the number of tries to 100 because
> unfortunately, even with this patch applied, I can see the problem on
> my kevin with current mainline.
>
> [  244.309094] rockchip-typec-phy ff800000.phy: Turn on failed after 100 loops
>
> That's an extra debug print ^
>
> [  244.317019] phy phy-ff800000.phy.8: phy poweron failed --> -110
> [  244.323824] dwc3 fe900000.dwc3: failed to initialize core
> [  244.330057] dwc3: probe of fe900000.dwc3 failed with error -110
>
> So I'm wondering if there is something else that I need to apply to
> really fix this as you didn't reproduce the issue doing lots of tests
> and I can reproduce the issue very easily.

Ah!  I added that message to the top of my upstream series and,
indeed, I sometimes see the PHY fail to turn on.  Doh.

OK, so here's what I've done:

* The place where I ran the overnight loops was actually the Chrome OS
4.4 kernel.  In that kernel I had a message very similar to yours and
I didn't hit it.  I just re-ran this for 20 minutes now and I can
re-confirm.  In the Chrome OS kernel I never see it needing more than
a 1 (or 2) loops and it doesn't ever get into the "totally failed"
case.

* Previously I ran ~10 minutes with the upstream kernel, but at the
time I didn't have your printout.  After 10 minutes I checked my logs
and I definitely saw the "Needed 1 loops to turn on", so I knew my
patch was doing something useful.  It didn't occur to me to re-confirm
that I didn't get the "totally failed" upstream, though now that I say
it out loud it's stupid that I didn't think to do this.

* Previously when playing with patches on the upstream kernel I saw
lots of problems powering on the PHY and I thought my patch was
helping, but that was all very non-scientific.


So to say it shortly:

* For me, my patch makes things a slightly better even on the upstream
kernel (I do sometimes see the "turned on after 1 tries")

* I can confirm that my patch doesn't fix everything upstream, so
there's something different about the Chrome OS tree still.

---

I also picked all the local patches from the Chrome OS kernel to the
PHY driver and now my PHY driver in the upstream and downstream trees
match.  I can still reproduce problems.  So the issue is somewhere at
a higher level...


So basically something outside the PHY driver is causing it to fail
unexpectedly upstream.  I guess the hacky retry won't work well enough
there after all.  :(

One question: if you get the "failed after 100 loops" and then you do
another unbind / bind, does it work after that?  The original reason I
got the idea to retry was because if I simply tried an unbind / bind
again then things worked OK...


-Doug

^ permalink raw reply

* [xlnx:2017.3_video_ea 6589/6607] warning: (RAPIDIO_DMA_ENGINE && ..) selects DMA_ENGINE which has unmet direct dependencies (DMADEVICES)
From: kbuild test robot @ 2017-12-13 19:14 UTC (permalink / raw)
  To: linux-arm-kernel

tree:   https://github.com/Xilinx/linux-xlnx 2017.3_video_ea
head:   af045f9682c65a0c26afb2f638603d3c01079222
commit: 62a7ed2f02d28f73f2c09d61ecbe1f289aecc6e5 [6589/6607] staging: xilinx: mixer: Initial commit of Xilinx Video Mixer IP DRM driver
config: i386-randconfig-x002-12131628 (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
        git checkout 62a7ed2f02d28f73f2c09d61ecbe1f289aecc6e5
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

warning: (RAPIDIO_DMA_ENGINE && DRM_XILINX && SND_SOC_SH4_SIU && XILINX_DMA_APF && DRM_XILINX_XVMIXER && CRYPTO_DEV_CCP_DD) selects DMA_ENGINE which has unmet direct dependencies (DMADEVICES)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 26870 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171214/c4c96865/attachment-0001.gz>

^ permalink raw reply

* [PATCH v3] net: ethernet: arc: fix error handling in emac_rockchip_probe
From: David Miller @ 2017-12-13 18:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171211231338.5207-1-branislav@radocaj.org>

From: Branislav Radocaj <branislav@radocaj.org>
Date: Tue, 12 Dec 2017 00:13:38 +0100

> If clk_set_rate() fails, we should disable clk before return.
> Found by Linux Driver Verification project (linuxtesting.org).
> 
> Changes since v2 [1]:
> * Merged with latest code changes
> 
> Changes since v1:
> Update made thanks to David's review, much appreciated David.
> * Improved inconsistent failure handling of clock rate setting
> * For completeness of usecase, added arc_emac_probe error handling
> 
> Signed-off-by: Branislav Radocaj <branislav@radocaj.org>

Applied.

^ permalink raw reply

* [PATCH 3/3] clocksource/drivers: integrator-ap: parse the chosen node
From: Alexandre Belloni @ 2017-12-13 18:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213185313.20017-1-alexandre.belloni@free-electrons.com>

The driver currently uses aliases to know whether the timer is the
clocksource or the clockevent. Add the /chosen/linux,clocksource and
/chosen/linux,clockevent parsing while keeping backward compatibility.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/clocksource/Kconfig               |  1 +
 drivers/clocksource/timer-integrator-ap.c | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 9a22d1048fcf..053aca99caf7 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -212,6 +212,7 @@ config KEYSTONE_TIMER
 config INTEGRATOR_AP_TIMER
 	bool "Integrator-ap timer driver" if COMPILE_TEST
 	select CLKSRC_MMIO
+	select TIMER_OF
 	help
 	  Enables support for the Integrator-ap timer.
 
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c
index 62d24690ba02..8f38be724aff 100644
--- a/drivers/clocksource/timer-integrator-ap.c
+++ b/drivers/clocksource/timer-integrator-ap.c
@@ -197,6 +197,17 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
 	rate = clk_get_rate(clk);
 	writel(0, base + TIMER_CTRL);
 
+	if (timer_of_is_clocksource(node))
+		/* The primary timer lacks IRQ, use as clocksource */
+		return integrator_clocksource_init(rate, base);
+
+	if (timer_of_is_clockevent(node)) {
+		/* The secondary timer will drive the clock event */
+		irq = irq_of_parse_and_map(node, 0);
+		return integrator_clockevent_init(rate, base, irq);
+	}
+
+	/* DT ABI compatibility below */
 	err = of_property_read_string(of_aliases,
 				"arm,timer-primary", &path);
 	if (err) {
-- 
2.15.1

^ permalink raw reply related

* [PATCH 2/3] clocksource/drivers: timer-of: parse the chosen node
From: Alexandre Belloni @ 2017-12-13 18:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213185313.20017-1-alexandre.belloni@free-electrons.com>

Add a way for drivers to know whether the timer they are currently handling
is a clocksource or a clockevent.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/clocksource/timer-of.c | 22 ++++++++++++++++++++++
 drivers/clocksource/timer-of.h |  3 +++
 2 files changed, 25 insertions(+)

diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c
index a31990408153..71680eacd390 100644
--- a/drivers/clocksource/timer-of.c
+++ b/drivers/clocksource/timer-of.c
@@ -195,3 +195,25 @@ void __init timer_of_cleanup(struct timer_of *to)
 	if (to->flags & TIMER_OF_BASE)
 		timer_base_exit(&to->of_base);
 }
+
+int __init timer_of_is_type(struct device_node *np, char *type)
+{
+	struct device_node *node, *timer;
+
+	if (!of_chosen)
+		return 0;
+
+	node = of_get_child_by_name(of_chosen, type);
+	if (!node)
+		return 0;
+
+	timer = of_parse_phandle(node, "timer", 0);
+	of_node_put(node);
+	if (!timer)
+		return 0;
+
+	if (timer == np)
+		return 1;
+
+	return 0;
+}
diff --git a/drivers/clocksource/timer-of.h b/drivers/clocksource/timer-of.h
index 3f708f1be43d..24923cfe748d 100644
--- a/drivers/clocksource/timer-of.h
+++ b/drivers/clocksource/timer-of.h
@@ -70,4 +70,7 @@ extern int __init timer_of_init(struct device_node *np,
 
 extern void __init timer_of_cleanup(struct timer_of *to);
 
+extern int __init timer_of_is_type(struct device_node *np, char *type);
+#define timer_of_is_clocksource(np) timer_of_is_type(np, "linux,clocksource")
+#define timer_of_is_clockevent(np) timer_of_is_type(np, "linux,clockevent")
 #endif
-- 
2.15.1

^ permalink raw reply related

* [PATCH 1/3] dt-bindings: chosen: Add clocksource and clockevent selection
From: Alexandre Belloni @ 2017-12-13 18:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213185313.20017-1-alexandre.belloni@free-electrons.com>

The clocksource and clockevent timer are probed early in the boot process.
At that time it is difficult for linux to know whether a particular timer
can be used as the clocksource or the clockevent or by another driver,
especially when they are all identical or have similar features.

Until now, multiple strategies have been used to solve that:
 - use Kconfig option as MXC_USE_EPIT or ATMEL_TCB_CLKSRC_BLOCK
 - use a kernel parameter as the "clocksource" early_param in mach-omap2
 - registering the first seen timer as a clockevent and the second one as
 a clocksource as in rk_timer_init or dw_apb_timer_init

Add a linux,clocksource and a linux,clockevent node in chosen with a timer
property pointing to the timer to use. Other properties, like the targeted
precision may be added later.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 Documentation/devicetree/bindings/chosen.txt | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/Documentation/devicetree/bindings/chosen.txt b/Documentation/devicetree/bindings/chosen.txt
index e3b13ea7d2ae..c7ee3ecb5276 100644
--- a/Documentation/devicetree/bindings/chosen.txt
+++ b/Documentation/devicetree/bindings/chosen.txt
@@ -120,3 +120,23 @@ e.g.
 While this property does not represent a real hardware, the address
 and the size are expressed in #address-cells and #size-cells,
 respectively, of the root node.
+
+linux,clocksource and linux,clockevent
+--------------------------------------
+
+Those nodes have a timer property. This property is a phandle to the timer to be
+chosen as the clocksource or clockevent. This is only useful when the platform
+has multiple identical timers and it is not possible to let linux make the
+correct choice.
+
+/ {
+	chosen {
+		linux,clocksource {
+			timer = <&timer0>;
+		};
+
+		linux,clockevent {
+			timer = <&timer1>;
+		};
+	};
+};
-- 
2.15.1

^ permalink raw reply related

* [PATCH 0/3] clocksource/drivers: introduce DT based selection
From: Alexandre Belloni @ 2017-12-13 18:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Currently, many drivers implement their own strategy when trying to find
which timer to use as the clocksource or the clockevent.

The main issue is that this selection is happen early in the boot
process and the kernel doesn't always have all the information to take
that decision.

So we end up with suboptimal solutions, especially in a multiplatform
kernel setting, as the MXC_USE_EPIT or ATMEL_TCB_CLKSRC_BLOCK kernel
config option.

There is also the clocksource kernel parameter only implemented in
mach-omap2.

Other drivers are registering the first seen timer as a clockevent, the
other one as a clocksource.

Also, this will help in the goal of separating clocksource and
clockevent drivers (see 376bc27150f180d9f5eddec6a14117780177589d)

Patch 1 documents the binding, patch 2 implements the parsing of the
chosen node and finally, patch 3 makes use of the parsing in a driver to
give an overview of how it is working.

Alexandre Belloni (3):
  dt-bindings: chosen: Add clocksource and clockevent selection
  clocksource/drivers: timer-of: parse the chosen node
  clocksource/drivers: integrator-ap: parse the chosen node

 Documentation/devicetree/bindings/chosen.txt | 20 ++++++++++++++++++++
 drivers/clocksource/Kconfig                  |  1 +
 drivers/clocksource/timer-integrator-ap.c    | 11 +++++++++++
 drivers/clocksource/timer-of.c               | 22 ++++++++++++++++++++++
 drivers/clocksource/timer-of.h               |  3 +++
 5 files changed, 57 insertions(+)

-- 
2.15.1

^ permalink raw reply

* [PATCH 3/3] [v6] pinctrl: qcom: qdf2xxx: add support for new ACPI HID QCOM8002
From: Timur Tabi @ 2017-12-13 18:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513189818-7384-1-git-send-email-timur@codeaurora.org>

Newer versions of the firmware for the Qualcomm Datacenter Technologies
QDF2400 restricts access to a subset of the GPIOs on the TLMM.  To
prevent older kernels from accidentally accessing the restricted GPIOs,
we change the ACPI HID for the TLMM block from QCOM8001 to QCOM8002,
and introduce a new property "gpios".  This property is an array of
specific GPIOs that are accessible.  When an older kernel boots on
newer (restricted) firmware, it will fail to probe.

To implement the sparse GPIO map, we register all of the GPIOs, but set
the pin count for the unavailable GPIOs to zero.  The pinctrl-msm
driver will block those unavailable GPIOs from being accessed.

To allow newer kernels to support older firmware, the driver retains
support for QCOM8001.

Signed-off-by: Timur Tabi <timur@codeaurora.org>
---
 drivers/pinctrl/qcom/pinctrl-qdf2xxx.c | 134 +++++++++++++++++++++++++--------
 1 file changed, 103 insertions(+), 31 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
index bb3ce5c3e18b..deb08e08e86d 100644
--- a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
+++ b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
@@ -38,68 +38,139 @@
 /* maximum size of each gpio name (enough room for "gpioXXX" + null) */
 #define NAME_SIZE	8
 
+enum {
+	QDF2XXX_V1,
+	QDF2XXX_V2,
+};
+
 static int qdf2xxx_pinctrl_probe(struct platform_device *pdev)
 {
+	const struct acpi_device_id *id;
 	struct pinctrl_pin_desc *pins;
 	struct msm_pingroup *groups;
 	char (*names)[NAME_SIZE];
 	unsigned int i;
 	u32 num_gpios;
+	unsigned int avail_gpios; /* The number of GPIOs we support */
+	u16 *gpios; /* An array of supported GPIOs */
 	int ret;
 
 	/* Query the number of GPIOs from ACPI */
 	ret = device_property_read_u32(&pdev->dev, "num-gpios", &num_gpios);
 	if (ret < 0) {
-		dev_warn(&pdev->dev, "missing num-gpios property\n");
+		dev_err(&pdev->dev, "missing 'num-gpios' property\n");
 		return ret;
 	}
-
 	if (!num_gpios || num_gpios > MAX_GPIOS) {
-		dev_warn(&pdev->dev, "invalid num-gpios property\n");
+		dev_err(&pdev->dev, "invalid 'num-gpios' property\n");
 		return -ENODEV;
 	}
 
+	/*
+	 * The QCOM8001 HID contains only the number of GPIOs, and assumes
+	 * that all of them are available. avail_gpios is the same as num_gpios.
+	 *
+	 * The QCOM8002 HID introduces the 'gpios' DSD, which lists
+	 * specific GPIOs that the driver is allowed to access.
+	 *
+	 * The make the common code simpler, in both cases we create an
+	 * array of GPIOs that are accessible.  So for QCOM8001, that would
+	 * be all of the GPIOs.
+	 */
+	id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
+
+	if (id->driver_data == QDF2XXX_V1) {
+		avail_gpios = num_gpios;
+
+		gpios = devm_kmalloc_array(&pdev->dev, avail_gpios,
+					   sizeof(gpios[0]), GFP_KERNEL);
+		if (!gpios)
+			return -ENOMEM;
+
+		for (i = 0; i < avail_gpios; i++)
+			gpios[i] = i;
+	} else {
+		/* The number of GPIOs in the approved list */
+		ret = device_property_read_u16_array(&pdev->dev, "gpios",
+						     NULL, 0);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "missing 'gpios' property\n");
+			return ret;
+		}
+		/*
+		 * The number of available GPIOs should be non-zero, and no
+		 * more than the total number of GPIOS.
+		 */
+		if (!ret || ret > num_gpios) {
+			dev_err(&pdev->dev, "invalid 'gpios' property\n");
+			return -ENODEV;
+		}
+		avail_gpios = ret;
+
+		gpios = devm_kmalloc_array(&pdev->dev, avail_gpios,
+					   sizeof(gpios[0]), GFP_KERNEL);
+		if (!gpios)
+			return -ENOMEM;
+
+		ret = device_property_read_u16_array(&pdev->dev, "gpios", gpios,
+						     avail_gpios);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "could not read list of GPIOs\n");
+			return ret;
+		}
+	}
+
 	pins = devm_kcalloc(&pdev->dev, num_gpios,
 		sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
 	groups = devm_kcalloc(&pdev->dev, num_gpios,
 		sizeof(struct msm_pingroup), GFP_KERNEL);
-	names = devm_kcalloc(&pdev->dev, num_gpios, NAME_SIZE, GFP_KERNEL);
+	names = devm_kcalloc(&pdev->dev, avail_gpios, NAME_SIZE, GFP_KERNEL);
 
 	if (!pins || !groups || !names)
 		return -ENOMEM;
 
+	/*
+	 * Initialize the array.  GPIOs not listed in the 'gpios' array
+	 * still need a number, but nothing else.
+	 */
 	for (i = 0; i < num_gpios; i++) {
-		snprintf(names[i], NAME_SIZE, "gpio%u", i);
-
 		pins[i].number = i;
-		pins[i].name = names[i];
-
-		groups[i].npins = 1;
-		groups[i].name = names[i];
 		groups[i].pins = &pins[i].number;
+	}
 
-		groups[i].ctl_reg = 0x10000 * i;
-		groups[i].io_reg = 0x04 + 0x10000 * i;
-		groups[i].intr_cfg_reg = 0x08 + 0x10000 * i;
-		groups[i].intr_status_reg = 0x0c + 0x10000 * i;
-		groups[i].intr_target_reg = 0x08 + 0x10000 * i;
-
-		groups[i].mux_bit = 2;
-		groups[i].pull_bit = 0;
-		groups[i].drv_bit = 6;
-		groups[i].oe_bit = 9;
-		groups[i].in_bit = 0;
-		groups[i].out_bit = 1;
-		groups[i].intr_enable_bit = 0;
-		groups[i].intr_status_bit = 0;
-		groups[i].intr_target_bit = 5;
-		groups[i].intr_target_kpss_val = 1;
-		groups[i].intr_raw_status_bit = 4;
-		groups[i].intr_polarity_bit = 1;
-		groups[i].intr_detection_bit = 2;
-		groups[i].intr_detection_width = 2;
+	/* Populate the entries that are meant to be exposes as GPIOs. */
+	for (i = 0; i < avail_gpios; i++) {
+		unsigned int gpio = gpios[i];
+
+		groups[gpio].npins = 1;
+		snprintf(names[i], NAME_SIZE, "gpio%u", gpio);
+		pins[gpio].name = names[i];
+		groups[gpio].name = names[i];
+
+		groups[gpio].ctl_reg = 0x10000 * gpio;
+		groups[gpio].io_reg = 0x04 + 0x10000 * gpio;
+		groups[gpio].intr_cfg_reg = 0x08 + 0x10000 * gpio;
+		groups[gpio].intr_status_reg = 0x0c + 0x10000 * gpio;
+		groups[gpio].intr_target_reg = 0x08 + 0x10000 * gpio;
+
+		groups[gpio].mux_bit = 2;
+		groups[gpio].pull_bit = 0;
+		groups[gpio].drv_bit = 6;
+		groups[gpio].oe_bit = 9;
+		groups[gpio].in_bit = 0;
+		groups[gpio].out_bit = 1;
+		groups[gpio].intr_enable_bit = 0;
+		groups[gpio].intr_status_bit = 0;
+		groups[gpio].intr_target_bit = 5;
+		groups[gpio].intr_target_kpss_val = 1;
+		groups[gpio].intr_raw_status_bit = 4;
+		groups[gpio].intr_polarity_bit = 1;
+		groups[gpio].intr_detection_bit = 2;
+		groups[gpio].intr_detection_width = 2;
 	}
 
+	devm_kfree(&pdev->dev, gpios);
+
 	qdf2xxx_pinctrl.pins = pins;
 	qdf2xxx_pinctrl.groups = groups;
 	qdf2xxx_pinctrl.npins = num_gpios;
@@ -110,7 +181,8 @@ static int qdf2xxx_pinctrl_probe(struct platform_device *pdev)
 }
 
 static const struct acpi_device_id qdf2xxx_acpi_ids[] = {
-	{"QCOM8001"},
+	{"QCOM8001", QDF2XXX_V1},
+	{"QCOM8002", QDF2XXX_V2},
 	{},
 };
 MODULE_DEVICE_TABLE(acpi, qdf2xxx_acpi_ids);
-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply related

* [PATCH 2/3] [v8] pinctrl: qcom: disable GPIO groups with no pins
From: Timur Tabi @ 2017-12-13 18:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513189818-7384-1-git-send-email-timur@codeaurora.org>

pinctrl-msm only accepts an array of GPIOs from 0 to n-1, and it expects
each group to support have only one pin (npins == 1).

We can support "sparse" GPIO maps if we allow for some groups to have zero
pins (npins == 0).  These pins are "hidden" from the rest of the driver
and gpiolib.

Access to unavailable GPIOs is blocked via a request callback.  If the
requested GPIO is unavailable, -EACCES is returned, which prevents
further access to that GPIO.

Signed-off-by: Timur Tabi <timur@codeaurora.org>
---
 drivers/pinctrl/qcom/pinctrl-msm.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 7a960590ecaa..d45b4c2b5af1 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -507,6 +507,11 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
 	};
 
 	g = &pctrl->soc->groups[offset];
+
+	/* If the GPIO group has no pins, then don't show it. */
+	if (!g->npins)
+		return;
+
 	ctl_reg = readl(pctrl->regs + g->ctl_reg);
 
 	is_out = !!(ctl_reg & BIT(g->oe_bit));
@@ -516,7 +521,7 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
 
 	seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func);
 	seq_printf(s, " %dmA", msm_regval_to_drive(drive));
-	seq_printf(s, " %s", pulls[pull]);
+	seq_printf(s, " %s\n", pulls[pull]);
 }
 
 static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
@@ -524,23 +529,36 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	unsigned gpio = chip->base;
 	unsigned i;
 
-	for (i = 0; i < chip->ngpio; i++, gpio++) {
+	for (i = 0; i < chip->ngpio; i++, gpio++)
 		msm_gpio_dbg_show_one(s, NULL, chip, i, gpio);
-		seq_puts(s, "\n");
-	}
 }
 
 #else
 #define msm_gpio_dbg_show NULL
 #endif
 
+/*
+ * If the requested GPIO has no pins, then treat it as unavailable.
+ * Otherwise, call the standard request function.
+ */
+static int msm_gpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+	struct msm_pinctrl *pctrl = gpiochip_get_data(chip);
+	const struct msm_pingroup *g = &pctrl->soc->groups[offset];
+
+	if (!g->npins)
+		return -EACCES;
+
+	return gpiochip_generic_request(chip, offset);
+}
+
 static const struct gpio_chip msm_gpio_template = {
 	.direction_input  = msm_gpio_direction_input,
 	.direction_output = msm_gpio_direction_output,
 	.get_direction    = msm_gpio_get_direction,
 	.get              = msm_gpio_get,
 	.set              = msm_gpio_set,
-	.request          = gpiochip_generic_request,
+	.request          = msm_gpio_request,
 	.free             = gpiochip_generic_free,
 	.dbg_show         = msm_gpio_dbg_show,
 };
-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply related

* [PATCH 1/3] [v2] Revert "gpio: set up initial state from .get_direction()"
From: Timur Tabi @ 2017-12-13 18:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513189818-7384-1-git-send-email-timur@codeaurora.org>

This reverts commit 72d3200061776264941be1b5a9bb8e926b3b30a5.

We cannot blindly query the direction of all GPIOs when the pins are
first registered.  The get_direction callback normally triggers a
read/write to hardware, but we shouldn't be touching the hardware for
an individual GPIO until after it's been properly claimed.

Signed-off-by: Timur Tabi <timur@codeaurora.org>
---
 drivers/gpio/gpiolib.c | 31 +++++++------------------------
 1 file changed, 7 insertions(+), 24 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 641a5eb552cb..168dd831551d 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1207,31 +1207,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
 		struct gpio_desc *desc = &gdev->descs[i];
 
 		desc->gdev = gdev;
-		/*
-		 * REVISIT: most hardware initializes GPIOs as inputs
-		 * (often with pullups enabled) so power usage is
-		 * minimized. Linux code should set the gpio direction
-		 * first thing; but until it does, and in case
-		 * chip->get_direction is not set, we may expose the
-		 * wrong direction in sysfs.
-		 */
-
-		if (chip->get_direction) {
-			/*
-			 * If we have .get_direction, set up the initial
-			 * direction flag from the hardware.
-			 */
-			int dir = chip->get_direction(chip, i);
 
-			if (!dir)
-				set_bit(FLAG_IS_OUT, &desc->flags);
-		} else if (!chip->direction_input) {
-			/*
-			 * If the chip lacks the .direction_input callback
-			 * we logically assume all lines are outputs.
-			 */
-			set_bit(FLAG_IS_OUT, &desc->flags);
-		}
+		/* REVISIT: most hardware initializes GPIOs as inputs (often
+		 * with pullups enabled) so power usage is minimized. Linux
+		 * code should set the gpio direction first thing; but until
+		 * it does, and in case chip->get_direction is not set, we may
+		 * expose the wrong direction in sysfs.
+		 */
+		desc->flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0;
 	}
 
 #ifdef CONFIG_PINCTRL
-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply related

* [PATCH 0/3] [v10] pinctrl: qcom: add support for sparse GPIOs
From: Timur Tabi @ 2017-12-13 18:30 UTC (permalink / raw)
  To: linux-arm-kernel

A series of patches that add support for GPIO maps that have holes in
them.  That is, even though a client driver has N consecutive GPIOs,
some are just unavailable for whatever reason, and the hardware should
not be accessed for those GPIOs.

Patch 1 reverts an old patch that triggers a get_direction of every
pin upon init, without attempting to request the pins first.  The
direction is already being queried when the pin is requested.

Patch 2 adds support to pinctrl-msm for "unavailable" GPIOs.

Patch 3 extends that support to pinctrl-qdf2xxx.  A recent ACPI change
on QDF2400 platforms blocks access to most pins, so the driver can only
register a subset.

This version drops the availability check in gpiolib, because it's no
necessary.  Instead, just having pinctrl-msm return -EACCES is enough
to block all unavailable GPIOs.  Patch 1 removes the only instance where
an unrequested GPIO is being accessed.

v10:
  Use driver_stuct to obtain ACPI match table entry

Timur Tabi (3):
  [v2] Revert "gpio: set up initial state from .get_direction()"
  [v8] pinctrl: qcom: disable GPIO groups with no pins
  [v6] pinctrl: qcom: qdf2xxx: add support for new ACPI HID QCOM8002

 drivers/gpio/gpiolib.c                 |  31 ++------
 drivers/pinctrl/qcom/pinctrl-msm.c     |  28 +++++--
 drivers/pinctrl/qcom/pinctrl-qdf2xxx.c | 134 +++++++++++++++++++++++++--------
 3 files changed, 133 insertions(+), 60 deletions(-)

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH v5 8/9] arm64: topology: Enable ACPI/PPTT based CPU topology.
From: Lorenzo Pieralisi @ 2017-12-13 18:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171201222330.18863-9-jeremy.linton@arm.com>

Nit: remove the period in $SUBJECT and capitalize with a coherent
policy for the patches touching the same code.

On Fri, Dec 01, 2017 at 04:23:29PM -0600, Jeremy Linton wrote:
> Propagate the topology information from the PPTT tree to the
> cpu_topology array. We can get the thread id, core_id and
> cluster_id by assuming certain levels of the PPTT tree correspond
> to those concepts. The package_id is flagged in the tree and can be
> found by calling find_acpi_cpu_topology_package() which terminates
> its search when it finds an ACPI node flagged as the physical
> package. If the tree doesn't contain enough levels to represent
> all of the requested levels then the root node will be returned
> for all subsequent levels.
> 
> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
> ---
>  arch/arm64/kernel/topology.c | 47 +++++++++++++++++++++++++++++++++++++++++++-
>  include/linux/topology.h     |  2 ++
>  2 files changed, 48 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
> index 74a8a5173a35..198714aca9e8 100644
> --- a/arch/arm64/kernel/topology.c
> +++ b/arch/arm64/kernel/topology.c
> @@ -11,6 +11,7 @@
>   * for more details.
>   */
>  
> +#include <linux/acpi.h>
>  #include <linux/arch_topology.h>
>  #include <linux/cpu.h>
>  #include <linux/cpumask.h>
> @@ -22,6 +23,7 @@
>  #include <linux/sched.h>
>  #include <linux/sched/topology.h>
>  #include <linux/slab.h>
> +#include <linux/smp.h>
>  #include <linux/string.h>
>  
>  #include <asm/cpu.h>
> @@ -300,6 +302,47 @@ static void __init reset_cpu_topology(void)
>  	}
>  }
>  
> +#ifdef CONFIG_ACPI
> +/*
> + * Propagate the topology information of the processor_topology_node tree to the
> + * cpu_topology array.
> + */
> +static int __init parse_acpi_topology(void)
> +{
> +	u64 is_threaded;

Nit: a bool would be preferable.

> +	int cpu;
> +	int topology_id;

int cpu, topology_id;

> +	is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;

> +	for_each_possible_cpu(cpu) {
> +		topology_id = find_acpi_cpu_topology(cpu, 0);
> +		if (topology_id < 0)
> +			return topology_id;
> +
> +		if (is_threaded) {
> +			cpu_topology[cpu].thread_id = topology_id;
> +			topology_id = find_acpi_cpu_topology(cpu, 1);
> +			cpu_topology[cpu].core_id   = topology_id;
> +			topology_id = find_acpi_cpu_topology_package(cpu);
> +			cpu_topology[cpu].physical_id = topology_id;
> +		} else {
> +			cpu_topology[cpu].thread_id  = -1;
> +			cpu_topology[cpu].core_id    = topology_id;
> +			topology_id = find_acpi_cpu_topology_package(cpu);
> +			cpu_topology[cpu].physical_id = topology_id;
> +		}
> +	}

Add a space.

It is probably my fault so apologies if that's the case. The

find_acpi_cpu_topology()

API is a bit strange since it behaves differently according to the
level passed in.

I think it is better to define two calls (it might well have been like
that in one of the previous series versions):

- find_acpi_cpu_package_level() (returns: package level if success, <0 on
  failure)
- acpi_cpu_topology_id()

It would even be better to lump the two calls together but you do not
know how many topology levels are there so it becomes a bit complicated
to handle.

> +	return 0;
> +}
> +
> +#else
> +static int __init parse_acpi_topology(void)

static inline ?

> +{
> +	/*ACPI kernels should be built with PPTT support*/

I think you can remove this comment.

> +	return -EINVAL;
> +}
> +#endif
>  
>  void __init init_cpu_topology(void)
>  {
> @@ -309,6 +352,8 @@ void __init init_cpu_topology(void)
>  	 * Discard anything that was parsed if we hit an error so we
>  	 * don't use partial information.
>  	 */
> -	if (of_have_populated_dt() && parse_dt_topology())
> +	if ((!acpi_disabled) && parse_acpi_topology())
> +		reset_cpu_topology();
> +	else if (of_have_populated_dt() && parse_dt_topology())
>  		reset_cpu_topology();
>  }
> diff --git a/include/linux/topology.h b/include/linux/topology.h
> index cb0775e1ee4b..170ce87edd88 100644
> --- a/include/linux/topology.h
> +++ b/include/linux/topology.h
> @@ -43,6 +43,8 @@
>  		if (nr_cpus_node(node))
>  
>  int arch_update_cpu_topology(void);
> +int find_acpi_cpu_topology(unsigned int cpu, int level);
> +int find_acpi_cpu_topology_package(unsigned int cpu);

I do not think these two declarations:

a) belong in this patch
b) belong in include/linux/topology.h (should be acpi.h)

Lorenzo

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox