* [PATCH v2] hardlockup: detect hard lockups without NMIs using secondary cpus
From: Frederic Weisbecker @ 2013-01-15 0:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1357941108-14138-1-git-send-email-ccross@android.com>
2013/1/11 Colin Cross <ccross@android.com>:
> Emulate NMIs on systems where they are not available by using timer
> interrupts on other cpus. Each cpu will use its softlockup hrtimer
> to check that the next cpu is processing hrtimer interrupts by
> verifying that a counter is increasing.
>
> This patch is useful on systems where the hardlockup detector is not
> available due to a lack of NMIs, for example most ARM SoCs.
> Without this patch any cpu stuck with interrupts disabled can
> cause a hardware watchdog reset with no debugging information,
> but with this patch the kernel can detect the lockup and panic,
> which can result in useful debugging info.
>
> Signed-off-by: Colin Cross <ccross@android.com>
I believe this is pretty much what the RCU stall detector does
already: checks for other CPUs being responsive. The only difference
is on how it checks that. For RCU it's about checking for CPUs
reporting quiescent states when requested to do so. In your case it's
about ensuring the hrtimer interrupt is well handled.
One thing you can do is to enqueue an RCU callback (cal_rcu()) every
minute so you can force other CPUs to report quiescent states
periodically and thus check for lockups.
Now you'll face the same problem in the end: if you don't have NMIs,
you won't have a very useful report.
^ permalink raw reply
* [PATCH 2/5] ARM: mach-shmobile: fix memory size for kota2_defconfig
From: Simon Horman @ 2013-01-14 23:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOesGMiUh-cb4xtizarm1ah06zvawu4r3zV1NOM9bwqXO3SwHg@mail.gmail.com>
On Fri, Jan 11, 2013 at 10:07:00AM -0800, Olof Johansson wrote:
> On Thu, Jan 10, 2013 at 11:17 PM, Simon Horman
> <horms+renesas@verge.net.au> wrote:
> > The CONFIG_MEMORY_SIZE value is interpreted as a 32 bit integer, which
> > makes sense on a system without PAE. It appears that a trailing 0 was
> > appended to the value and after some testing it appears that 0x1e000000 is
> > the correct value.
> >
> > Without this patch, building kota2_defconfig results in:
> >
> > /home/arnd/linux-arm/arch/arm/kernel/setup.c:790:2: warning: large integer implicitly truncated to unsigned type [-Woverflow]
> >
> > Reported-by: Arnd Bergmann <arnd@arndb.de>
> > Cc: Olof Johansson <olof@lixom.net>
> > Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
>
> Acked-by: Olof Johansson <olof@lixom.net>
>
> Or is this the only fix you have right now, so I should just apply it directly?
As far as I know the change does not appear to have any affect
at run-time, at least for the default config. So there is no particular rush.
I'll include this as part of a pull request a little later today.
^ permalink raw reply
* [PATCH v2] hardlockup: detect hard lockups without NMIs using secondary cpus
From: Andrew Morton @ 2013-01-14 23:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1357941108-14138-1-git-send-email-ccross@android.com>
On Fri, 11 Jan 2013 13:51:48 -0800
Colin Cross <ccross@android.com> wrote:
> Emulate NMIs on systems where they are not available by using timer
> interrupts on other cpus. Each cpu will use its softlockup hrtimer
> to check that the next cpu is processing hrtimer interrupts by
> verifying that a counter is increasing.
Seems sensible.
> This patch is useful on systems where the hardlockup detector is not
> available due to a lack of NMIs, for example most ARM SoCs.
> Without this patch any cpu stuck with interrupts disabled can
> cause a hardware watchdog reset with no debugging information,
> but with this patch the kernel can detect the lockup and panic,
> which can result in useful debugging info.
But we don't get the target cpu's stack, yes? That's a pretty big loss.
>
> ...
>
> +#ifdef CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU
> +static unsigned int watchdog_next_cpu(unsigned int cpu)
> +{
> + cpumask_t cpus = watchdog_cpus;
cpumask_t can be tremendously huge and putting one on the stack is
risky. Can we use watchdog_cpus directly here? Perhaps with a lock?
or take a copy into a static local, with a lock?
> + unsigned int next_cpu;
> +
> + next_cpu = cpumask_next(cpu, &cpus);
> + if (next_cpu >= nr_cpu_ids)
> + next_cpu = cpumask_first(&cpus);
> +
> + if (next_cpu == cpu)
> + return nr_cpu_ids;
> +
> + return next_cpu;
> +}
> +
> +static int is_hardlockup_other_cpu(unsigned int cpu)
> +{
> + unsigned long hrint = per_cpu(hrtimer_interrupts, cpu);
> +
> + if (per_cpu(hrtimer_interrupts_saved, cpu) == hrint)
> + return 1;
> +
> + per_cpu(hrtimer_interrupts_saved, cpu) = hrint;
> + return 0;
> +}
This could return a bool type.
> +static void watchdog_check_hardlockup_other_cpu(void)
> +{
> + unsigned int next_cpu;
> +
> + /*
> + * Test for hardlockups every 3 samples. The sample period is
> + * watchdog_thresh * 2 / 5, so 3 samples gets us back to slightly over
> + * watchdog_thresh (over by 20%).
> + */
> + if (__this_cpu_read(hrtimer_interrupts) % 3 != 0)
> + return;
The hardwired interval Seems Wrong. watchdog_thresh is tunable at runtime.
The comment could do with some fleshing out. *why* do we want to test
at an interval "slightly over watchdog_thresh"? What's going on here?
> + /* check for a hardlockup on the next cpu */
> + next_cpu = watchdog_next_cpu(smp_processor_id());
> + if (next_cpu >= nr_cpu_ids)
> + return;
> +
> + smp_rmb();
Mystery barrier (always) needs an explanatory comment, please.
> + if (per_cpu(watchdog_nmi_touch, next_cpu) == true) {
> + per_cpu(watchdog_nmi_touch, next_cpu) = false;
> + return;
> + }
I wonder if a well-timed CPU plug/unplug could result in two CPUs
simultaneously checking one other CPU's state.
> + if (is_hardlockup_other_cpu(next_cpu)) {
> + /* only warn once */
> + if (per_cpu(hard_watchdog_warn, next_cpu) == true)
> + return;
> +
> + if (hardlockup_panic)
> + panic("Watchdog detected hard LOCKUP on cpu %u", next_cpu);
> + else
> + WARN(1, "Watchdog detected hard LOCKUP on cpu %u", next_cpu);
I suggest we use messages here which make it clear to people who read
kernel output that this was triggered by hrtimers, not by NMI. Most
importantly because people will need to know that the CPU which locked
up is *not this CPU* and that any backtrace from the reporting CPU is
misleading.
Also, there was never any sense in making the LOCKUP all-caps ;)
> + per_cpu(hard_watchdog_warn, next_cpu) = true;
> + } else {
> + per_cpu(hard_watchdog_warn, next_cpu) = false;
> + }
> +}
> +#else
> +static inline void watchdog_check_hardlockup_other_cpu(void) { return; }
> +#endif
> +
>
> ...
>
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -191,15 +191,27 @@ config LOCKUP_DETECTOR
> The overhead should be minimal. A periodic hrtimer runs to
> generate interrupts and kick the watchdog task every 4 seconds.
> An NMI is generated every 10 seconds or so to check for hardlockups.
> + If NMIs are not available on the platform, every 12 seconds the
hm. Is the old "4 seconds" still true/accurate/complete?
> + hrtimer interrupt on one cpu will be used to check for hardlockups
> + on the next cpu.
>
> The frequency of hrtimer and NMI events and the soft and hard lockup
> thresholds can be controlled through the sysctl watchdog_thresh.
>
> -config HARDLOCKUP_DETECTOR
> +config HARDLOCKUP_DETECTOR_NMI
> def_bool y
> depends on LOCKUP_DETECTOR && !HAVE_NMI_WATCHDOG
> depends on PERF_EVENTS && HAVE_PERF_EVENTS_NMI
Confused. I'd have expected this to depend on HAVE_NMI_WATCHDOG,
rather than -no-that. What does "HAVE_NMI_WATCHDOG" actually mean and
what's happening here?
>
> ...
>
^ permalink raw reply
* [PATCH v8 5/5] ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND
From: Daniel Mack @ 2013-01-14 23:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114180602.GV14149@atomide.com>
On Jan 15, 2013 2:06 AM, "Tony Lindgren" <tony@atomide.com> wrote:
>
> * Ezequiel Garcia <elezegarcia@gmail.com> [121223 13:49]:
> > On Fri, Dec 14, 2012 at 7:36 AM, Daniel Mack <zonque@gmail.com> wrote:
> > > +
> > > +Example for an AM33xx board:
> > > +
> > > + gpmc: gpmc at 50000000 {
> > > + compatible = "ti,am3352-gpmc";
> > > + ti,hwmods = "gpmc";
> > > + reg = <0x50000000 0x1000000>;
> > > + interrupts = <100>;
> > > + gpmc,num-cs = <8>;
> > > + gpmc,num-waitpins = <2>;
> > > + #address-cells = <2>;
> > > + #size-cells = <1>;
> > > + ranges = <0 0 0x08000000 0x2000>; /* CS0: NAND
*/
> > > +
> > > + nand at 0,0 {
> > > + reg = <0 0 0>; /* CS0, offset 0 */
> >
> > I'm a bit confused by this: what are the other two values in "reg"?
> > I see you've only added a binding for CS.
> >
> > I've extended a bit on your work and added a binding to enable OneNAND
> > device on my IGEP board.
> >
> > I might send some patches in case anyone wants to give it a try.
>
> Daniel, should this be updated to just pass the CS?
No, as Rob pointed out earlier in a thread about this topic, the 'ranges'
feature will help doing the math for the offset calculation eventually, so
we need to pass all three values.
Regards,
Daniel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130114/c232814c/attachment.html>
^ permalink raw reply
* [PATCH] clk: vt8500: Add support for WM8750/WM8850 PLL clocks
From: Mike Turquette @ 2013-01-14 23:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1356657882-18218-1-git-send-email-linux@prisktech.co.nz>
Quoting Tony Prisk (2012-12-27 17:24:41)
> This patch adds support for the new PLL module found in WM8750 and
> WM8850 SoCs.
>
> Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
Tony,
This has been taken into clk-next.
Thanks,
Mike
> ---
> drivers/clk/clk-vt8500.c | 102 +++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 100 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c
> index fe25570..d3fefa4 100644
> --- a/drivers/clk/clk-vt8500.c
> +++ b/drivers/clk/clk-vt8500.c
> @@ -41,6 +41,7 @@ struct clk_device {
>
> #define PLL_TYPE_VT8500 0
> #define PLL_TYPE_WM8650 1
> +#define PLL_TYPE_WM8750 2
>
> struct clk_pll {
> struct clk_hw hw;
> @@ -298,6 +299,16 @@ static __init void vtwm_device_clk_init(struct device_node *node)
> #define WM8650_BITS_TO_VAL(m, d1, d2) \
> ((d2 << 13) | (d1 << 10) | (m & 0x3FF))
>
> +/* Helper macros for PLL_WM8750 */
> +#define WM8750_PLL_MUL(x) (((x >> 16) & 0xFF) + 1)
> +#define WM8750_PLL_DIV(x) ((((x >> 8) & 1) + 1) * (1 << (x & 7)))
> +
> +#define WM8750_BITS_TO_FREQ(r, m, d1, d2) \
> + (r * (m+1) / ((d1+1) * (1 << d2)))
> +
> +#define WM8750_BITS_TO_VAL(f, m, d1, d2) \
> + ((f << 24) | ((m - 1) << 16) | ((d1 - 1) << 8) | d2)
> +
>
> static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
> u32 *multiplier, u32 *prediv)
> @@ -366,11 +377,82 @@ static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
> *divisor2 = div2;
> }
>
> +static u32 wm8750_get_filter(u32 parent_rate, u32 divisor1)
> +{
> + /* calculate frequency (MHz) after pre-divisor */
> + u32 freq = (parent_rate / 1000000) / (divisor1 + 1);
> +
> + if ((freq < 10) || (freq > 200))
> + pr_warn("%s: PLL recommended input frequency 10..200Mhz (requested %d Mhz)\n",
> + __func__, freq);
> +
> + if (freq >= 166)
> + return 7;
> + else if (freq >= 104)
> + return 6;
> + else if (freq >= 65)
> + return 5;
> + else if (freq >= 42)
> + return 4;
> + else if (freq >= 26)
> + return 3;
> + else if (freq >= 16)
> + return 2;
> + else if (freq >= 10)
> + return 1;
> +
> + return 0;
> +}
> +
> +static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
> + u32 *filter, u32 *multiplier, u32 *divisor1, u32 *divisor2)
> +{
> + u32 mul, div1, div2;
> + u32 best_mul, best_div1, best_div2;
> + unsigned long tclk, rate_err, best_err;
> +
> + best_err = (unsigned long)-1;
> +
> + /* Find the closest match (lower or equal to requested) */
> + for (div1 = 1; div1 >= 0; div1--)
> + for (div2 = 7; div2 >= 0; div2--)
> + for (mul = 0; mul <= 255; mul++) {
> + tclk = parent_rate * (mul + 1) / ((div1 + 1) * (1 << div2));
> + if (tclk > rate)
> + continue;
> + /* error will always be +ve */
> + rate_err = rate - tclk;
> + if (rate_err == 0) {
> + *filter = wm8750_get_filter(parent_rate, div1);
> + *multiplier = mul;
> + *divisor1 = div1;
> + *divisor2 = div2;
> + return;
> + }
> +
> + if (rate_err < best_err) {
> + best_err = rate_err;
> + best_mul = mul;
> + best_div1 = div1;
> + best_div2 = div2;
> + }
> + }
> +
> + /* if we got here, it wasn't an exact match */
> + pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
> + rate - best_err);
> +
> + *filter = wm8750_get_filter(parent_rate, best_div1);
> + *multiplier = best_mul;
> + *divisor1 = best_div1;
> + *divisor2 = best_div2;
> +}
> +
> static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> unsigned long parent_rate)
> {
> struct clk_pll *pll = to_clk_pll(hw);
> - u32 mul, div1, div2;
> + u32 filter, mul, div1, div2;
> u32 pll_val;
> unsigned long flags = 0;
>
> @@ -385,6 +467,9 @@ static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
> pll_val = WM8650_BITS_TO_VAL(mul, div1, div2);
> break;
> + case PLL_TYPE_WM8750:
> + wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2);
> + pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2);
> default:
> pr_err("%s: invalid pll type\n", __func__);
> return 0;
> @@ -405,7 +490,7 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> unsigned long *prate)
> {
> struct clk_pll *pll = to_clk_pll(hw);
> - u32 mul, div1, div2;
> + u32 filter, mul, div1, div2;
> long round_rate;
>
> switch (pll->type) {
> @@ -417,6 +502,9 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2);
> round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2);
> break;
> + case PLL_TYPE_WM8750:
> + wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2);
> + round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2);
> default:
> round_rate = 0;
> }
> @@ -440,6 +528,10 @@ static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw,
> pll_freq = parent_rate * WM8650_PLL_MUL(pll_val);
> pll_freq /= WM8650_PLL_DIV(pll_val);
> break;
> + case PLL_TYPE_WM8750:
> + pll_freq = parent_rate * WM8750_PLL_MUL(pll_val);
> + pll_freq /= WM8750_PLL_DIV(pll_val);
> + break;
> default:
> pll_freq = 0;
> }
> @@ -508,10 +600,16 @@ static void __init wm8650_pll_init(struct device_node *node)
> vtwm_pll_clk_init(node, PLL_TYPE_WM8650);
> }
>
> +static void __init wm8750_pll_init(struct device_node *node)
> +{
> + vtwm_pll_clk_init(node, PLL_TYPE_WM8750);
> +}
> +
> static const __initconst struct of_device_id clk_match[] = {
> { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
> { .compatible = "via,vt8500-pll-clock", .data = vt8500_pll_init, },
> { .compatible = "wm,wm8650-pll-clock", .data = wm8650_pll_init, },
> + { .compatible = "wm,wm8750-pll-clock", .data = wm8750_pll_init, },
> { .compatible = "via,vt8500-device-clock",
> .data = vtwm_device_clk_init, },
> { /* sentinel */ }
> --
> 1.7.9.5
^ permalink raw reply
* [PATCH 0/3] clk fixes for 3.8
From: Mike Turquette @ 2013-01-14 23:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1356567272-3420-1-git-send-email-linux@prisktech.co.nz>
Quoting Tony Prisk (2012-12-26 16:14:28)
> Mike,
>
> Three bugfixes for 3.8.
>
Tony,
I've taken these into clk-next.
Thanks,
Mike
> #1 was a boo-boo on my part, function returned the wrong variables.
> #2 is a truncation problem which results in a higher-than-requested clock rate.
> #3 became apparent when the MMC driver started requesting rate=0 during init.
>
> Tony Prisk (3):
> clk: vt8500: Fix error in PLL calculations on non-exact match.
> clk: vt8500: Fix device clock divisor calculations
> clk: vt8500: Fix division-by-0 when requested rate=0
>
> drivers/clk/clk-vt8500.c | 28 +++++++++++++++++++++++-----
> 1 file changed, 23 insertions(+), 5 deletions(-)
>
> --
> 1.7.9.5
^ permalink raw reply
* [kvmarm] [PATCH v5 13/14] KVM: ARM: Handle I/O aborts
From: Christoffer Dall @ 2013-01-14 22:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114223638.GB3937@mudshark.cambridge.arm.com>
On Mon, Jan 14, 2013 at 5:36 PM, Will Deacon <will.deacon@arm.com> wrote:
> On Mon, Jan 14, 2013 at 07:12:49PM +0000, Christoffer Dall wrote:
>> On Mon, Jan 14, 2013 at 2:00 PM, Will Deacon <will.deacon@arm.com> wrote:
>> > On Mon, Jan 14, 2013 at 06:53:14PM +0000, Alexander Graf wrote:
>> >> On 01/14/2013 07:50 PM, Will Deacon wrote:
>> >> > FWIW, KVM only needs this code for handling complex MMIO instructions, which
>> >> > aren't even generated by recent guest kernels. I'm inclined to suggest removing
>> >> > this emulation code from KVM entirely given that it's likely to bitrot as
>> >> > it is executed less and less often.
>> >>
>> >> That'd mean that you heavily limit what type of guests you're executing,
>> >> which I don't think is a good idea.
>> >
>> > To be honest, I don't think we know whether that's true or not. How many
>> > guests out there do writeback accesses to MMIO devices? Even on older
>> > Linux guests, it was dependent on how GCC felt.
>>
>> I don't think bitrot'ing is a valid argument: the code doesn't depend
>> on any other implementation state that's likely to change and break
>> this code (the instruction encoding is not exactly going to change).
>> And we should simply finish the selftest code to test this stuff
>> (which should be finished if the code is unified or not, and is on my
>> todo list).
>
> Maybe `bitrot' is the wrong word. The scenario I envisage is the addition
> of new instructions to the architecture which aren't handled by the current
> code, then we end up with emulation code that works for some percentage of
> the instruction set only. If the code is rarely used, it will likely go
> untouched until it crashes somebody's VM.
>
How is that worse than KVM crashing all VMs that use any of these
instructions for IO?
At least the code we have now has been tested with a number of old
kernels, and we know that it works. As for correctness, it will be the
case for all implementations and this type of code absolutely requires
a test suite.
>> > I see where you're coming from, I just don't think we can quantify it either
>> > way outside of Linux.
>> >
>> FWIW, I know of at least a couple of companies wanting to use KVM for
>> running non-Linux guests as well.
>
> Oh, I don't doubt that. The point is, do we have any idea how they behave
> under KVM? Do they generate complex MMIO accesses? Do they expect firmware
> shims, possibly sitting above hyp? Do they require a signed boot sequence?
> Do they run on Cortex-A15 (the only target CPU we have at the moment)?
>
No we don't know. But there's a fair chance that they do use complex
mmio instructions seeing as older kernels did, without anything
explicitly being involved.
>> But, however a shame, I can more easily maintain this single patch
>> out-of-tree, so I'm willing to drop this logic for now if it gets
>> things moving.
>
> I would hope that, if this code is actually required, you would consider
> merging it with what we have rather than maintaining it out-of-tree.
>
Of course I would, and I would also make an effort to unify the code
if it were merged now, I just don't have the cycles to do the unify
work right now, since it is without doubt a lengthy process.
So from that point of view, I don't quite see how it's better to leave
the code out at this point, but that is not up to me.
-Christoffer
^ permalink raw reply
* [PATCH v5 04/12] ARM: KVM: Initial VGIC infrastructure code
From: Will Deacon @ 2013-01-14 22:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANM98q+y4GoHmqh-CS+fDnfbDbBQHQOY05urer5DMgy9b1X5ng@mail.gmail.com>
On Mon, Jan 14, 2013 at 09:08:54PM +0000, Christoffer Dall wrote:
> On Mon, Jan 14, 2013 at 10:31 AM, Will Deacon <will.deacon@arm.com> wrote:
> > On Tue, Jan 08, 2013 at 06:41:51PM +0000, Christoffer Dall wrote:
> >> + case ACCESS_READ_VALUE:
> >> + *((u32 *)mmio->data) = (regval >> shift) & mask;
> >> + }
> >> + }
> >> +}
> >
> > As I mentioned previously, I suspect that this doesn't work with big-endian
> > systems. Whilst that's reasonable for the moment, a comment would be useful
> > for the unlucky soul that decides to do that work in future (or add
> > accessors for mmio->data as I suggested before).
> >
> admittedly this really hurts my brain, but I think there's actually no
> problem with endianness: whatever comes in mmio->data will have native
> endianness and the vgic is always little-endian, so a guest would have
> to make sure to do its own endianness conversion before writing data,
> or did I get this backwards? (some nasty feeling about if the OS is
> compiled in another endianness than the hardware everything may
> break).
No, you're right. As long as the vgic is always little-endian the access
will be ok.
Sorry for the false alarm,
Will
^ permalink raw reply
* OMAP baseline test results for v3.8-rc3
From: Aaro Koskinen @ 2013-01-14 22:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114211846.GA10699@arwen.pp.htv.fi>
On Mon, Jan 14, 2013 at 11:18:46PM +0200, Felipe Balbi wrote:
> On Mon, Jan 14, 2013 at 10:46:54PM +0200, Aaro Koskinen wrote:
> > [ 0.207946] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
> > [ 0.208129] twl 1-0048: power (irq 343) chaining IRQs 346..353
> > [ 0.209350] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
> > [ 1.218749] omap_i2c omap_i2c.1: timeout waiting for bus ready
> > [ 1.218811] omap_i2c omap_i2c.1: SA 0049 CON 9602 CNT 0004
>
> here's the issue, there is unloaded data in the FIFO. Can you enable
> full I2C debugging logs ?
If I enable I2C DEBUGs, the problem is not reproducible. Everything
looks normal:
[ 0.270141] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
[ 0.270294] twl 1-0048: power (irq 343) chaining IRQs 346..353
[ 0.270477] i2c i2c-1: master_xfer[0] W, addr=0x49, len=1
[ 0.270538] i2c i2c-1: master_xfer[1] R, addr=0x49, len=1
[ 0.270568] omap_i2c omap_i2c.1: addr: 0x0049, len: 1, flags: 0x0, stop: 0
[ 0.270629] omap_i2c omap_i2c.1: IRQ (ISR = 0x0010)
[ 0.270690] omap_i2c omap_i2c.1: IRQ (ISR = 0x0004)
[ 0.270751] omap_i2c omap_i2c.1: addr: 0x0049, len: 1, flags: 0x1, stop: 1
[ 0.270843] omap_i2c omap_i2c.1: IRQ (ISR = 0x0008)
[ 0.270874] omap_i2c omap_i2c.1: IRQ (ISR = 0x0004)
[ 0.270935] i2c i2c-1: master_xfer[0] W, addr=0x49, len=2
[ 0.270965] omap_i2c omap_i2c.1: addr: 0x0049, len: 2, flags: 0x0, stop: 1
[ 0.271026] omap_i2c omap_i2c.1: IRQ (ISR = 0x0010)
[ 0.271118] omap_i2c omap_i2c.1: IRQ (ISR = 0x0004)
[ 0.272155] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
> > > git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git i2c-deferred-STP
> >
> > I could not reproduce the issue with these. Tested around 20 boots.
> > There's a noticeable delay (over 4 secs!) around where I2C is initialized
> > and used for the first time, but no errors and the boot completes:
> >
> > [ 0.187530] SCSI subsystem initialized
> > [ 0.188110] usbcore: registered new interface driver usbfs
> > [ 0.188415] usbcore: registered new interface driver hub
> > [ 0.188781] usbcore: registered new device driver usb
> > [ 0.189453] musb-omap2430 musb-omap2430: invalid resource
> > [ 4.296905] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
> > [ 4.297088] twl 1-0048: power (irq 343) chaining IRQs 346..353
> > [ 4.329010] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
> > [ 4.470123] VUSB1V5: 1500 mV normal standby
> > [ 4.470916] VUSB1V8: 1800 mV normal standby
>
> cool, at least it works, but looks like there is something still weird
> going on. Can you enable full logs so I see what's happening ?
With your patches, all DEBUG logs are identical (there is same
amount I2C of transfers), except there is only a single interrupt per
transfer. Still, the transfers are taking considerably longer, and we
see those delays in the boot:
[ 4.281280] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
[ 4.281433] twl 1-0048: power (irq 343) chaining IRQs 346..353
[ 4.281616] i2c i2c-1: master_xfer[0] W, addr=0x49, len=1
[ 4.281677] i2c i2c-1: master_xfer[1] R, addr=0x49, len=1
[ 4.281707] omap_i2c omap_i2c.1: addr: 0x0049, len: 1, flags: 0x0, stop: 0
[ 4.281799] omap_i2c omap_i2c.1: IRQ (ISR = 0x0010)
[ 4.281829] omap_i2c omap_i2c.1: addr: 0x0049, len: 1, flags: 0x1, stop: 1
[ 4.281921] omap_i2c omap_i2c.1: IRQ (ISR = 0x0008)
[ 4.296905] i2c i2c-1: master_xfer[0] W, addr=0x49, len=2
[ 4.296936] omap_i2c omap_i2c.1: addr: 0x0049, len: 2, flags: 0x0, stop: 1
[ 4.296997] omap_i2c omap_i2c.1: IRQ (ISR = 0x0010)
[ 4.313476] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
This log excerpt has only 3 transfers, but the time duration is already
10x longer compared to vanilla 3.8-rc3.
A.
^ permalink raw reply
* [kvmarm] [PATCH v5 13/14] KVM: ARM: Handle I/O aborts
From: Will Deacon @ 2013-01-14 22:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANM98qJVZ2gAn4xN1GXUzdq2HQK7qqqXwycacn6gESMJaUYR5A@mail.gmail.com>
On Mon, Jan 14, 2013 at 07:12:49PM +0000, Christoffer Dall wrote:
> On Mon, Jan 14, 2013 at 2:00 PM, Will Deacon <will.deacon@arm.com> wrote:
> > On Mon, Jan 14, 2013 at 06:53:14PM +0000, Alexander Graf wrote:
> >> On 01/14/2013 07:50 PM, Will Deacon wrote:
> >> > FWIW, KVM only needs this code for handling complex MMIO instructions, which
> >> > aren't even generated by recent guest kernels. I'm inclined to suggest removing
> >> > this emulation code from KVM entirely given that it's likely to bitrot as
> >> > it is executed less and less often.
> >>
> >> That'd mean that you heavily limit what type of guests you're executing,
> >> which I don't think is a good idea.
> >
> > To be honest, I don't think we know whether that's true or not. How many
> > guests out there do writeback accesses to MMIO devices? Even on older
> > Linux guests, it was dependent on how GCC felt.
>
> I don't think bitrot'ing is a valid argument: the code doesn't depend
> on any other implementation state that's likely to change and break
> this code (the instruction encoding is not exactly going to change).
> And we should simply finish the selftest code to test this stuff
> (which should be finished if the code is unified or not, and is on my
> todo list).
Maybe `bitrot' is the wrong word. The scenario I envisage is the addition
of new instructions to the architecture which aren't handled by the current
code, then we end up with emulation code that works for some percentage of
the instruction set only. If the code is rarely used, it will likely go
untouched until it crashes somebody's VM.
> > I see where you're coming from, I just don't think we can quantify it either
> > way outside of Linux.
> >
> FWIW, I know of at least a couple of companies wanting to use KVM for
> running non-Linux guests as well.
Oh, I don't doubt that. The point is, do we have any idea how they behave
under KVM? Do they generate complex MMIO accesses? Do they expect firmware
shims, possibly sitting above hyp? Do they require a signed boot sequence?
Do they run on Cortex-A15 (the only target CPU we have at the moment)?
> But, however a shame, I can more easily maintain this single patch
> out-of-tree, so I'm willing to drop this logic for now if it gets
> things moving.
I would hope that, if this code is actually required, you would consider
merging it with what we have rather than maintaining it out-of-tree.
Will
^ permalink raw reply
* [PATCH RFT 3/3] ARM: tegra: dts: seaboard: enable keyboard
From: Stephen Warren @ 2013-01-14 22:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F4820C.2050806@wwwdotorg.org>
On 01/14/2013 03:09 PM, Stephen Warren wrote:
> On 01/12/2013 03:02 AM, Laxman Dewangan wrote:
>> On Saturday 12 January 2013 04:39 AM, Stephen Warren wrote:
>>> On 01/11/2013 06:33 AM, Laxman Dewangan wrote:
>>>> Enable tegra based keyboard controller and populate the key matrix for
>>>> seaboard. The key matrix was originally on driver code which is removed
>>>> to have clean driver. The key mapping is now passed through dts file.
>>>>
>>>> Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
>>>> ---
>>>> Requesting for testing on seaboard.
>>>> I generated this patch as Stephen suggested to have one patch for dt
>>>> file
>>>> entry for keys on seaboard.
>>
>> Thanks for testing.
>>> Once I hacked around the above issues, the driver doesn't work very well
>>> at all. There is a *long* delay between when I press a key and when it
>>> shows up (e.g. echo'd to the HDMI console). When I release the key the
>>> same keypress is generated twice. Or perhaps it's a repeat, but since
>>> it's *always* 2 extra keypresses and I doubt I always hold my finger on
>>> the key the exact same amount of time, I think it's key release that
>>> does this not repeat. I assume this would repro on any board, so you
>>> won't need Seaboard to debug it. Harmony is able to read the keyboard
>>> using the KBC.
>>>
>>> Even with the above, I was able to validate that the keymap in the
>>> Seaboard .dts file looks reasonable.
>>>
>>> However, please fix the KBC driver...
>>
>> I did not see any issue with the 3x3 matrix. I think all these about is
>> to tuning debaunce and other parameter also. Another thing is that to
>> make sure that all pinmuxes are properly configured.
>
> OK, I'll go look at some downstream kernels for Seaboard and see if the
> debounce etc. parameters all match up.
How odd. The problems were indeed solved by using the downstream
debounce/... timings. It's odd that using a shorter debounce time leads
to /not/ generating spurious keypress events; perhaps the HW is buggy
for the extremely large debounce value that you chose.
I also noticed that one entry in the keymap had a typo.
Can you please roll the patch below into yours:
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts
b/arch/arm/boot/dts/tegra20-seaboard.dts
index b22522d..2e87330 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -614,8 +614,9 @@
kbc {
status = "okay";
- nvidia,debounce-delay-ms = <640>;
- nvidia,repeat-delay-ms = <1>;
+ nvidia,debounce-delay-ms = <32>;
+ nvidia,repeat-delay-ms = <160>;
+ nvidia,ghost-filter;
nvidia,kbc-row-pins = <0 1 2 3 4 5 6 7 8 9 10 11 12 13
14 15>;
nvidia,kbc-col-pins = <16 17 18 19 20 21 22 23>;
linux,keymap = <0x00020011 /* KEY_W */
@@ -672,7 +673,7 @@
0x0805002A /* KEY_LEFTSHIFT */
0x09050061 /* KEY_RIGHTCTRL */
- 0x0907001B /* KEY_LEFTCTRL */
+ 0x0907001D /* KEY_LEFTCTRL */
0x0B00001A /* KEY_LEFTBRACE */
0x0B010019 /* KEY_P */
^ permalink raw reply related
* [PATCH] arm: mach-zynq/timer.c: fix memory leakage
From: Josh Cartwright @ 2013-01-14 22:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358198331-31949-1-git-send-email-dinggnu@gmail.com>
On Mon, Jan 14, 2013 at 10:18:46PM +0100, Cong Ding wrote:
> the variable ttccs allocated isn't freed when error occurs, so we call kfree
> before return.
>
> Signed-off-by: Cong Ding <dinggnu@gmail.com>
> ---
> arch/arm/mach-zynq/timer.c | 25 ++++++++++++++++---------
> 1 file changed, 16 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
> index f9fbc9c..df04761 100644
> --- a/arch/arm/mach-zynq/timer.c
> +++ b/arch/arm/mach-zynq/timer.c
> @@ -203,15 +203,15 @@ static void __init zynq_ttc_setup_clocksource(struct device_node *np,
>
> err = of_property_read_u32(np, "reg", ®);
> if (WARN_ON(err))
> - return;
> + goto out;
>
> clk = of_clk_get_by_name(np, "cpu_1x");
> if (WARN_ON(IS_ERR(clk)))
> - return;
> + goto out;
>
> err = clk_prepare_enable(clk);
> if (WARN_ON(err))
> - return;
> + goto out;
>
> ttccs->xttc.base_addr = base + reg * 4;
>
> @@ -229,7 +229,10 @@ static void __init zynq_ttc_setup_clocksource(struct device_node *np,
>
> err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE);
> if (WARN_ON(err))
> - return;
> + goto out;
> + return;
> +out:
> + kfree(ttccs);
> }
Okay...hmm. If initialization of the timer fails, you'll have bigger
issues then just a small memory leak. Especially since right now the
TTC is the only supported timer on zynq.
But okay, to be forward looking we should probably properly handle these
error cases.
You've only handled the memory leak here, but there are other potential
leaks that you should be handling (the clk handle, clock event
interrupt, ioremap()'d region, etc). Could you take care of those while
your at it?
Josh
^ permalink raw reply
* [PATCH v5 00/14] KVM/ARM Implementation
From: Christoffer Dall @ 2013-01-14 22:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114160051.GH18935@mudshark.cambridge.arm.com>
On Mon, Jan 14, 2013 at 11:00 AM, Will Deacon <will.deacon@arm.com> wrote:
> Hi Christoffer,
>
> On Tue, Jan 08, 2013 at 06:38:34PM +0000, Christoffer Dall wrote:
>> The following series implements KVM support for ARM processors,
>> specifically on the Cortex-A15 platform.
>
> [...]
>
> This is looking pretty good to me now and I feel that the longer it stays
> out-of-tree, the more issues will creep in (without continual effort from
> yourself and others). I've sent some minor comments (mainly vgic-related)
> so, if you fix those, then you can add:
>
> Reviewed-by: Will Deacon <will.deacon@arm.com>
>
> for the series.
A big thanks!
>
> Now, there's a lot of code here and merging isn't completely
> straightforward. I propose:
>
> * The first series should go via Russell's tree. It depends on my
> perf branch for the CPU type stuff, but that should go in for 3.9
> anyway (also via Russell).
>
Great.
> * The vGIC patches need rebasing on top of Rob Herring's work, which
> he sent a pull for over the weekend:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2013-January/141488.html
>
> In light of that, this stuff will need to go via arm-soc.
>
> * The hyp arch-timers are in a similar situation to the vGIC: Mark Rutland
> is moving those into drivers:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2013-January/140560.html
>
> so the kvm bits will need rebasing appropriately and also sent to
> arm-soc (Mark -- I assume you intend to send a PULL for 3.9 for those
> patches?)
>
> Obviously this is all open for discussion, but that seems like the easiest
> option to me.
>
Makes good sense. Given that there are no other major disputes over
the code we are a couple of people strongly hoping that this can
happen for 3.9.
In any case, I'll do whatever makes the process the easiest for you guys.
Best,
-Christoffer
^ permalink raw reply
* [PATCH v5 3/4] ARM: KVM: arch_timers: Add timer world switch
From: Will Deacon @ 2013-01-14 22:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANM98qLsq7=PRNu4-5-N2GaAuLFOUfpy-yEWb6LpZri3WQ8JwA@mail.gmail.com>
On Mon, Jan 14, 2013 at 10:08:39PM +0000, Christoffer Dall wrote:
> can't we also get rid of the isb on the return path then?
>
> do you agree with this patch:
>
> diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
> index 57cfa84..7e6eedf 100644
> --- a/arch/arm/kvm/interrupts_head.S
> +++ b/arch/arm/kvm/interrupts_head.S
> @@ -492,7 +492,6 @@ vcpu .req r0 @ vcpu pointer always in r0
> str r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
> bic r2, #1 @ Clear ENABLE
> mcr p15, 0, r2, c14, c3, 1 @ CNTV_CTL
> - isb
I'd keep this one as it stops speculation of CVAL until the timer is
disabled.
> mrrc p15, 3, r2, r3, c14 @ CNTV_CVAL
> ldr r4, =VCPU_TIMER_CNTV_CVAL
> @@ -532,18 +531,17 @@ vcpu .req r0 @ vcpu pointer always in r0
> ldr r2, [r4, #KVM_TIMER_CNTVOFF]
> ldr r3, [r4, #(KVM_TIMER_CNTVOFF + 4)]
> mcrr p15, 4, r2, r3, c14 @ CNTVOFF
> - isb
>
> ldr r4, =VCPU_TIMER_CNTV_CVAL
> add vcpu, vcpu, r4
> ldrd r2, r3, [vcpu]
> sub vcpu, vcpu, r4
> mcrr p15, 3, r2, r3, c14 @ CNTV_CVAL
> + isb
>
> ldr r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
> and r2, r2, #3
> mcr p15, 0, r2, c14, c3, 1 @ CNTV_CTL
> - isb
Looks ok to me, but I'll let Marc decide as it's his code.
Will
^ permalink raw reply
* [PATCH v5 03/14] KVM: ARM: Initial skeleton to compile KVM support
From: Christoffer Dall @ 2013-01-14 22:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114184908.GB12489@redhat.com>
On Mon, Jan 14, 2013 at 1:49 PM, Gleb Natapov <gleb@redhat.com> wrote:
> A couple of general question about ABI. If they were already answered
> just refer me to the previous discussion.
>
> On Tue, Jan 08, 2013 at 01:38:55PM -0500, Christoffer Dall wrote:
>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>> index a4df553..4237c27 100644
>> --- a/Documentation/virtual/kvm/api.txt
>> +++ b/Documentation/virtual/kvm/api.txt
>> @@ -293,7 +293,7 @@ kvm_run' (see below).
>> 4.11 KVM_GET_REGS
>>
>> Capability: basic
>> -Architectures: all
>> +Architectures: all except ARM
>> Type: vcpu ioctl
>> Parameters: struct kvm_regs (out)
>> Returns: 0 on success, -1 on error
>> @@ -314,7 +314,7 @@ struct kvm_regs {
>> 4.12 KVM_SET_REGS
>>
>> Capability: basic
>> -Architectures: all
>> +Architectures: all except ARM
>> Type: vcpu ioctl
>> Parameters: struct kvm_regs (in)
>> Returns: 0 on success, -1 on error
>> @@ -600,7 +600,7 @@ struct kvm_fpu {
>> 4.24 KVM_CREATE_IRQCHIP
> Why KVM_GET_REGS/KVM_SET_REGS are not usable for arm?
>
We use the ONE_REG API instead and we don't want to support two
separate APIs to user space.
>>
>> Capability: KVM_CAP_IRQCHIP
>> -Architectures: x86, ia64
>> +Architectures: x86, ia64, ARM
>> Type: vm ioctl
>> Parameters: none
>> Returns: 0 on success, -1 on error
>> @@ -608,7 +608,8 @@ Returns: 0 on success, -1 on error
>> Creates an interrupt controller model in the kernel. On x86, creates a virtual
>> ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a
>> local APIC. IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23
>> -only go to the IOAPIC. On ia64, a IOSAPIC is created.
>> +only go to the IOAPIC. On ia64, a IOSAPIC is created. On ARM, a GIC is
>> +created.
>>
>>
>> 4.25 KVM_IRQ_LINE
>> @@ -1775,6 +1776,14 @@ registers, find a list below:
>> PPC | KVM_REG_PPC_VPA_DTL | 128
>> PPC | KVM_REG_PPC_EPCR | 32
>>
>> +ARM registers are mapped using the lower 32 bits. The upper 16 of that
>> +is the register group type, or coprocessor number:
>> +
>> +ARM core registers have the following id bit patterns:
>> + 0x4002 0000 0010 <index into the kvm_regs struct:16>
>> +
>> +
>> +
>> 4.69 KVM_GET_ONE_REG
>>
>> Capability: KVM_CAP_ONE_REG
>> @@ -2127,6 +2136,46 @@ written, then `n_invalid' invalid entries, invalidating any previously
>> valid entries found.
>>
>>
>> +4.77 KVM_ARM_VCPU_INIT
>> +
>> +Capability: basic
>> +Architectures: arm
>> +Type: vcpu ioctl
>> +Parameters: struct struct kvm_vcpu_init (in)
>> +Returns: 0 on success; -1 on error
>> +Errors:
>> + EINVAL: the target is unknown, or the combination of features is invalid.
>> + ENOENT: a features bit specified is unknown.
>> +
>> +This tells KVM what type of CPU to present to the guest, and what
>> +optional features it should have. This will cause a reset of the cpu
>> +registers to their initial values. If this is not called, KVM_RUN will
>> +return ENOEXEC for that vcpu.
>> +
> Can different vcpus of the same VM be of different type?
>
In the future yes. For example, if we ever want to virtualize a
Big.Little system.
>> +Note that because some registers reflect machine topology, all vcpus
>> +should be created before this ioctl is invoked.
> How cpu hot plug suppose to work?
>
Those CPUs would be added from the beginning, but not powered on, and
would be powered on later on, I suppose. See
https://lists.cs.columbia.edu/pipermail/kvmarm/2013-January/004617.html.
>> +
>> +
>> +4.78 KVM_GET_REG_LIST
>> +
>> +Capability: basic
>> +Architectures: arm
>> +Type: vcpu ioctl
>> +Parameters: struct kvm_reg_list (in/out)
>> +Returns: 0 on success; -1 on error
>> +Errors:
>> + E2BIG: the reg index list is too big to fit in the array specified by
>> + the user (the number required will be written into n).
>> +
>> +struct kvm_reg_list {
>> + __u64 n; /* number of registers in reg[] */
>> + __u64 reg[0];
>> +};
>> +
>> +This ioctl returns the guest registers that are supported for the
>> +KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
>> +
>> +
> Doesn't userspace know what registers are supported by each CPU type?
>
It would know about core registers, but there is a huge space of
co-processors, and we don't emulate all of them or support
getting/setting all of them yet. Surely this is something that will
change over time and we want user space to be able to discover the
available registers for backwards compatibility, migration, etc.
-Christoffer
^ permalink raw reply
* [GIT PULL] timer: vt8500: Move timer code to drivers/clocksource
From: Olof Johansson @ 2013-01-14 22:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358140171-25390-1-git-send-email-linux@prisktech.co.nz>
On Mon, Jan 14, 2013 at 06:09:30PM +1300, Tony Prisk wrote:
> Hi Olof,
>
> Not sure if I have done this correctly but this is the patch to move the
> vt8500/timer.c code into drivers/clocksource.
>
> I based it on timer/cleanup from armsoc (hopefully this is right - if not, a
> few pointers in the right direction would be appreciated).
>
> Regards
> Tony P
>
>
> The following changes since commit 1c2584c3a1c882fec729147a46d822522552e38c:
>
> ARM: sunxi: fix struct sys_timer removal (2013-01-08 10:50:43 -0800)
>
> are available in the git repository at:
>
> git://server.prisktech.co.nz/git/linuxwmt.git tags/vt8500/timer
Thanks, pulled and merged into next/cleanup.
-Olof
^ permalink raw reply
* Early kernel hang with big DTB appended
From: Nicolas Pitre @ 2013-01-14 22:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130111164531.GC13025@pengutronix.de>
On Fri, 11 Jan 2013, Sascha Hauer wrote:
> On Thu, Jan 03, 2013 at 04:55:00PM +0100, Tomasz Figa wrote:
> > Hi,
> >
> > I'm observing strange behavior when booting 3.8-rc1 and -rc2 with appended
> > DTB. The kernel hangs very early when the DTB is bigger than some
> > threshold somewhere around 24 KiB. With fullest possible low level UART
> > debugging (and printk patched to use printascii) I'm receiving following
> > output:
> >
> > Uncompressing Linux... done, booting the kernel.
> > Booting Linux on physical CPU 0xa00
> > Linux version 3.8.0-rc1-00073-gdf6efca-dirty (t.figa at amdc1227) (gcc
> > version 4.5.2 (Gentoo 4.5.2 p1.2, pie-0.4.5) ) #2 SMP PREEMPT Thu Jan 3
> > 15:37:35 CET 2013
> > CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c53c7d
> > CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
> >
> > I tested on two Exynos-based boards (exynos4210-trats and one internal
> > exynos4412-based board) and same happens on both.
> >
> > Do you have any ideas?
>
> Another thing besides the things already mentioned is that the dtb may
> not cross a 1MiB boundary. The Kernel uses a single 1Mib section
> (aligned to 1Mib) to initially map the dtb. Once you cross that boundary
> parts of the dtb won't be accessible for the Kernel anymore.
Crap. You're right. This patch should fix this issue.
@Tomasz: please could you confirm this fixes your initial problem?
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 4eee351f46..61fcb18c7e 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -246,6 +246,7 @@ __create_page_tables:
/*
* Then map boot params address in r2 if specified.
+ * We map 2 sections in case the ATAGs/DTB crosses a section boundary.
*/
mov r0, r2, lsr #SECTION_SHIFT
movs r0, r0, lsl #SECTION_SHIFT
@@ -253,6 +254,8 @@ __create_page_tables:
addne r3, r3, #PAGE_OFFSET
addne r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
orrne r6, r7, r0
+ strne r6, [r3], #1 << PMD_ORDER
+ addne r6, r6, #1 << SECTION_SHIFT
strne r6, [r3]
#ifdef CONFIG_DEBUG_LL
^ permalink raw reply related
* [PATCH] usb: phy: samsung: Add support to set pmu isolation
From: Doug Anderson @ 2013-01-14 22:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1357891738-26259-1-git-send-email-gautam.vivek@samsung.com>
Vivek,
Sorry for being so absent from these reviews. I'll try to look over a
few patches today, but please don't hold up anything on account of my
reviews. I'm definitely a bit of an interested bystander in USB land.
;)
In general things look pretty good here. :) One last comment below...
On Fri, Jan 11, 2013 at 12:08 AM, Vivek Gautam
<gautam.vivek@samsung.com> wrote:> +static int
samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
> +{
> + struct device_node *usbphy_sys;
> +
> + /* Getting node for system controller interface for usb-phy */
> + usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
> + if (!usbphy_sys)
> + dev_warn(sphy->dev, "No sys-controller interface for usb-phy\n");
Seems like you ought to return with an error here. Calling of_iomap()
with a NULL value seems undesirable.
> +
> + sphy->pmuregs = of_iomap(usbphy_sys, 0);
> +
> + of_node_put(usbphy_sys);
> +
> + if (sphy->pmuregs == NULL) {
> + dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
> + return -ENODEV;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * Set isolation here for phy.
> + * Here 'on = true' would mean USB PHY block is isolated, hence
> + * de-activated and vice-versa.
> + */
Thank you very much for this comment. :) This explains one of the
confusions I had earlier...
Once you fix the one error condition above you can add my
"Reviewed-by". Thanks!
-Doug
^ permalink raw reply
* [PATCH RFT 3/3] ARM: tegra: dts: seaboard: enable keyboard
From: Stephen Warren @ 2013-01-14 22:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F134C9.1040203@nvidia.com>
On 01/12/2013 03:02 AM, Laxman Dewangan wrote:
> On Saturday 12 January 2013 04:39 AM, Stephen Warren wrote:
>> On 01/11/2013 06:33 AM, Laxman Dewangan wrote:
>>> Enable tegra based keyboard controller and populate the key matrix for
>>> seaboard. The key matrix was originally on driver code which is removed
>>> to have clean driver. The key mapping is now passed through dts file.
>>>
>>> Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
>>> ---
>>> Requesting for testing on seaboard.
>>> I generated this patch as Stephen suggested to have one patch for dt
>>> file
>>> entry for keys on seaboard.
>
> Thanks for testing.
>> Oh, and the KBC clock is marked TEGRA_PERIPH_NO_RESET for Tegra30, and
>> also for Tegra20 in the ChromeOS kernel; why is the driver trying to
>> assert reset on a clock that doesn't support it?
>
> This is something our kbc controller reset and clock design.
> KBC controller is on Always Power ON domain so that it can work even
> when system is in sleep.
> The KBC clock is enabled through two places, PMC control register and
> CAR register set.
> KBC controller is only reset through PMC control register.
> This is not well implemented either on our downstream or in mainline.
> Sometime back I tried to implement it in downstream but was having lots
> of comment and not able to complete this. Possibly we will talk
> internally that how can we implement this.
I guess there's little point in the KBC driver calling the Tegra clock
reset APIs then. Still, since the code is already there and it's not
doing any harm, I guess it's fine to leave it there; if we ever enhance
the clock driver to implement reset for those clocks via the PMC, it
will all just magically work.
>> Once I hacked around the above issues, the driver doesn't work very well
>> at all. There is a *long* delay between when I press a key and when it
>> shows up (e.g. echo'd to the HDMI console). When I release the key the
>> same keypress is generated twice. Or perhaps it's a repeat, but since
>> it's *always* 2 extra keypresses and I doubt I always hold my finger on
>> the key the exact same amount of time, I think it's key release that
>> does this not repeat. I assume this would repro on any board, so you
>> won't need Seaboard to debug it. Harmony is able to read the keyboard
>> using the KBC.
>>
>> Even with the above, I was able to validate that the keymap in the
>> Seaboard .dts file looks reasonable.
>>
>> However, please fix the KBC driver...
>
> I did not see any issue with the 3x3 matrix. I think all these about is
> to tuning debaunce and other parameter also. Another thing is that to
> make sure that all pinmuxes are properly configured.
OK, I'll go look at some downstream kernels for Seaboard and see if the
debounce etc. parameters all match up.
> However, again I will try to enable kbc on harmony and run it.
That would be extremely useful; I worry that if you tested it on
Tegra114, that means using a downstream kernel only, and also whether
there are any HW differences between SoC versions. That's quite a lot of
variables that could explain the issues I'm seeing.
^ permalink raw reply
* [PATCH v5 3/4] ARM: KVM: arch_timers: Add timer world switch
From: Christoffer Dall @ 2013-01-14 22:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F445BC.6050507@arm.com>
On Mon, Jan 14, 2013 at 12:51 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 14/01/13 15:21, Will Deacon wrote:
>> On Tue, Jan 08, 2013 at 06:43:27PM +0000, Christoffer Dall wrote:
>>> From: Marc Zyngier <marc.zyngier@arm.com>
>>>
>>> Do the necessary save/restore dance for the timers in the world
>>> switch code. In the process, allow the guest to read the physical
>>> counter, which is useful for its own clock_event_device.
>>
>> [...]
>>
>>> @@ -476,6 +513,7 @@ vcpu .req r0 @ vcpu pointer always in r0
>>> * for the host.
>>> *
>>> * Assumes vcpu pointer in vcpu reg
>>> + * Clobbers r2-r4
>>> */
>>> .macro restore_timer_state
>>> @ Disallow physical timer access for the guest
>>> @@ -484,6 +522,30 @@ vcpu .req r0 @ vcpu pointer always in r0
>>> orr r2, r2, #CNTHCTL_PL1PCTEN
>>> bic r2, r2, #CNTHCTL_PL1PCEN
>>> mcr p15, 4, r2, c14, c1, 0 @ CNTHCTL
>>> +
>>> +#ifdef CONFIG_KVM_ARM_TIMER
>>> + ldr r4, [vcpu, #VCPU_KVM]
>>> + ldr r2, [r4, #KVM_TIMER_ENABLED]
>>> + cmp r2, #0
>>> + beq 1f
>>> +
>>> + ldr r2, [r4, #KVM_TIMER_CNTVOFF]
>>> + ldr r3, [r4, #(KVM_TIMER_CNTVOFF + 4)]
>>> + mcrr p15, 4, r2, r3, c14 @ CNTVOFF
>>> + isb
>>> +
>>> + ldr r4, =VCPU_TIMER_CNTV_CVAL
>>> + add vcpu, vcpu, r4
>>> + ldrd r2, r3, [vcpu]
>>> + sub vcpu, vcpu, r4
>>> + mcrr p15, 3, r2, r3, c14 @ CNTV_CVAL
>>> +
>>> + ldr r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
>>> + and r2, r2, #3
>>> + mcr p15, 0, r2, c14, c3, 1 @ CNTV_CTL
>>> + isb
>>
>> How many of these isbs are actually needed, given that we're going to make
>> an exception return to the guest? The last one certainly looks redundant and
>> I can't see the need for ordering CNTVOFF vs CNTV_CVAL. I can see an
>> argument to putting one *before* CNTV_CTL, but you don't have one there!
>
> CNTVOFF directly influences whether or not CNTV_CVAL will trigger or
> not. Maybe I'm just being paranoid and moving the isb after CNTV_CVAL is
> enough.
>
> The last one is definitively superfluous.
>
can't we also get rid of the isb on the return path then?
do you agree with this patch:
diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
index 57cfa84..7e6eedf 100644
--- a/arch/arm/kvm/interrupts_head.S
+++ b/arch/arm/kvm/interrupts_head.S
@@ -492,7 +492,6 @@ vcpu .req r0 @ vcpu pointer always in r0
str r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
bic r2, #1 @ Clear ENABLE
mcr p15, 0, r2, c14, c3, 1 @ CNTV_CTL
- isb
mrrc p15, 3, r2, r3, c14 @ CNTV_CVAL
ldr r4, =VCPU_TIMER_CNTV_CVAL
@@ -532,18 +531,17 @@ vcpu .req r0 @ vcpu pointer always in r0
ldr r2, [r4, #KVM_TIMER_CNTVOFF]
ldr r3, [r4, #(KVM_TIMER_CNTVOFF + 4)]
mcrr p15, 4, r2, r3, c14 @ CNTVOFF
- isb
ldr r4, =VCPU_TIMER_CNTV_CVAL
add vcpu, vcpu, r4
ldrd r2, r3, [vcpu]
sub vcpu, vcpu, r4
mcrr p15, 3, r2, r3, c14 @ CNTV_CVAL
+ isb
ldr r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
and r2, r2, #3
mcr p15, 0, r2, c14, c3, 1 @ CNTV_CTL
- isb
1:
#endif
.endm
--
Thanks,
-Christoffer
^ permalink raw reply related
* [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
From: Christoffer Dall @ 2013-01-14 22:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114154231.GG18935@mudshark.cambridge.arm.com>
On Mon, Jan 14, 2013 at 10:42 AM, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, Jan 08, 2013 at 06:42:11PM +0000, Christoffer Dall wrote:
>> From: Marc Zyngier <marc.zyngier@arm.com>
>>
>> Add VGIC virtual CPU interface code, picking pending interrupts
>> from the distributor and stashing them in the VGIC control interface
>> list registers.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
>> ---
>> arch/arm/include/asm/kvm_vgic.h | 30 ++++
>> arch/arm/kvm/vgic.c | 327 +++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 356 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h
>> index 9ff0d9c..b3133c4 100644
>> --- a/arch/arm/include/asm/kvm_vgic.h
>> +++ b/arch/arm/include/asm/kvm_vgic.h
>> @@ -110,8 +110,33 @@ struct vgic_dist {
>> };
>>
>> struct vgic_cpu {
>> +#ifdef CONFIG_KVM_ARM_VGIC
>> + /* per IRQ to LR mapping */
>> + u8 vgic_irq_lr_map[VGIC_NR_IRQS];
>> +
>> + /* Pending interrupts on this VCPU */
>> + DECLARE_BITMAP( pending_percpu, VGIC_NR_PRIVATE_IRQS);
>> + DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS);
>> +
>> + /* Bitmap of used/free list registers */
>> + DECLARE_BITMAP( lr_used, 64);
>> +
>> + /* Number of list registers on this CPU */
>> + int nr_lr;
>> +
>> + /* CPU vif control registers for world switch */
>> + u32 vgic_hcr;
>> + u32 vgic_vmcr;
>> + u32 vgic_misr; /* Saved only */
>> + u32 vgic_eisr[2]; /* Saved only */
>> + u32 vgic_elrsr[2]; /* Saved only */
>> + u32 vgic_apr;
>> + u32 vgic_lr[64]; /* A15 has only 4... */
>
> Have a #define for the maximum number of list registers.
>
>> +#endif
>> };
>>
>> +#define LR_EMPTY 0xff
>> +
>> struct kvm;
>> struct kvm_vcpu;
>> struct kvm_run;
>> @@ -119,9 +144,14 @@ struct kvm_exit_mmio;
>>
>> #ifdef CONFIG_KVM_ARM_VGIC
>> int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr);
>> +void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu);
>> +void kvm_vgic_sync_from_cpu(struct kvm_vcpu *vcpu);
>
> Same comment as for the arch timer (flush/sync).
>
>> +int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>> bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
>> struct kvm_exit_mmio *mmio);
>>
>> +#define irqchip_in_kernel(k) (!!((k)->arch.vgic.vctrl_base))
>> +
>> #else
>> static inline int kvm_vgic_hyp_init(void)
>> {
>> diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
>> index bd2bd7f..58237d5 100644
>> --- a/arch/arm/kvm/vgic.c
>> +++ b/arch/arm/kvm/vgic.c
>> @@ -152,6 +152,34 @@ static int vgic_irq_is_enabled(struct kvm_vcpu *vcpu, int irq)
>> return vgic_bitmap_get_irq_val(&dist->irq_enabled, vcpu->vcpu_id, irq);
>> }
>>
>> +static int vgic_irq_is_active(struct kvm_vcpu *vcpu, int irq)
>> +{
>> + struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +
>> + return vgic_bitmap_get_irq_val(&dist->irq_active, vcpu->vcpu_id, irq);
>> +}
>> +
>> +static void vgic_irq_set_active(struct kvm_vcpu *vcpu, int irq)
>> +{
>> + struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +
>> + vgic_bitmap_set_irq_val(&dist->irq_active, vcpu->vcpu_id, irq, 1);
>> +}
>> +
>> +static void vgic_irq_clear_active(struct kvm_vcpu *vcpu, int irq)
>> +{
>> + struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +
>> + vgic_bitmap_set_irq_val(&dist->irq_active, vcpu->vcpu_id, irq, 0);
>> +}
>> +
>> +static int vgic_dist_irq_is_pending(struct kvm_vcpu *vcpu, int irq)
>> +{
>> + struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +
>> + return vgic_bitmap_get_irq_val(&dist->irq_state, vcpu->vcpu_id, irq);
>> +}
>> +
>> static void vgic_dist_irq_set(struct kvm_vcpu *vcpu, int irq)
>> {
>> struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> @@ -711,7 +739,30 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)
>>
>> static int compute_pending_for_cpu(struct kvm_vcpu *vcpu)
>> {
>> - return 0;
>> + struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> + unsigned long *pending, *enabled, *pend_percpu, *pend_shared;
>> + unsigned long pending_private, pending_shared;
>> + int vcpu_id;
>> +
>> + vcpu_id = vcpu->vcpu_id;
>> + pend_percpu = vcpu->arch.vgic_cpu.pending_percpu;
>> + pend_shared = vcpu->arch.vgic_cpu.pending_shared;
>> +
>> + pending = vgic_bitmap_get_cpu_map(&dist->irq_state, vcpu_id);
>> + enabled = vgic_bitmap_get_cpu_map(&dist->irq_enabled, vcpu_id);
>> + bitmap_and(pend_percpu, pending, enabled, VGIC_NR_PRIVATE_IRQS);
>> +
>> + pending = vgic_bitmap_get_shared_map(&dist->irq_state);
>> + enabled = vgic_bitmap_get_shared_map(&dist->irq_enabled);
>> + bitmap_and(pend_shared, pending, enabled, VGIC_NR_SHARED_IRQS);
>> + bitmap_and(pend_shared, pend_shared,
>> + vgic_bitmap_get_shared_map(&dist->irq_spi_target[vcpu_id]),
>> + VGIC_NR_SHARED_IRQS);
>> +
>> + pending_private = find_first_bit(pend_percpu, VGIC_NR_PRIVATE_IRQS);
>> + pending_shared = find_first_bit(pend_shared, VGIC_NR_SHARED_IRQS);
>> + return (pending_private < VGIC_NR_PRIVATE_IRQS ||
>> + pending_shared < VGIC_NR_SHARED_IRQS);
>> }
>>
>> /*
>> @@ -737,6 +788,280 @@ static void vgic_update_state(struct kvm *kvm)
>> }
>> }
>>
>> +#define LR_CPUID(lr) \
>> + (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT)
>> +#define MK_LR_PEND(src, irq) \
>> + (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq))
>> +/*
>> + * Queue an interrupt to a CPU virtual interface. Return true on success,
>> + * or false if it wasn't possible to queue it.
>> + */
>> +static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
>> +{
>> + struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>> + int lr;
>> +
>> + /* Sanitize the input... */
>> + BUG_ON(sgi_source_id & ~7);
>> + BUG_ON(sgi_source_id && irq > 15);
>
> You can use your new NR_SGIS definition here.
>
This should address the remaining comments:
commit 43957095ec5476beb198f4c4630dfc3e2f3951db
Author: Christoffer Dall <c.dall@virtualopensystems.com>
Date: Mon Jan 14 16:59:38 2013 -0500
KVM: ARM: vgic: Define VGIC_MAX_LRS
Define maximum number of link registers we can handle instead of using
literals in the code. If an architecture reports more link registers
than we support, only use the number we can support.
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h
index 1ace491..f9d1977 100644
--- a/arch/arm/include/asm/kvm_vgic.h
+++ b/arch/arm/include/asm/kvm_vgic.h
@@ -33,6 +33,7 @@
#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)
#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)
#define VGIC_MAX_CPUS KVM_MAX_VCPUS
+#define VGIC_MAX_LRS 64
/* Sanity checks... */
#if (VGIC_MAX_CPUS > 8)
@@ -120,7 +121,7 @@ struct vgic_cpu {
DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS);
/* Bitmap of used/free list registers */
- DECLARE_BITMAP( lr_used, 64);
+ DECLARE_BITMAP( lr_used, VGIC_MAX_LRS);
/* Number of list registers on this CPU */
int nr_lr;
@@ -132,7 +133,7 @@ struct vgic_cpu {
u32 vgic_eisr[2]; /* Saved only */
u32 vgic_elrsr[2]; /* Saved only */
u32 vgic_apr;
- u32 vgic_lr[64]; /* A15 has only 4... */
+ u32 vgic_lr[VGIC_MAX_LRS];
#endif
};
diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
index a0d283c..90a99fd 100644
--- a/arch/arm/kvm/vgic.c
+++ b/arch/arm/kvm/vgic.c
@@ -1345,6 +1345,8 @@ int kvm_vgic_hyp_init(void)
vgic_nr_lr = readl_relaxed(vgic_vctrl_base + GICH_VTR);
vgic_nr_lr = (vgic_nr_lr & 0x1f) + 1;
+ if (vgic_nr_lr > VGIC_MAX_LRS)
+ vgic_nr_lr = VGIC_MAX_LRS; /* TODO: Clear remaining LRs */
ret = create_hyp_io_mappings(vgic_vctrl_base,
vgic_vctrl_base + resource_size(&vctrl_res),
--
Thanks,
-Christoffer
^ permalink raw reply related
* [PATCH v5 06/12] ARM: KVM: VGIC distributor handling
From: Christoffer Dall @ 2013-01-14 21:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114153955.GF18935@mudshark.cambridge.arm.com>
On Mon, Jan 14, 2013 at 10:39 AM, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, Jan 08, 2013 at 06:42:04PM +0000, Christoffer Dall wrote:
>> From: Marc Zyngier <marc.zyngier@arm.com>
>>
>> Add the GIC distributor emulation code. A number of the GIC features
>> are simply ignored as they are not required to boot a Linux guest.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
>> ---
>> arch/arm/include/asm/kvm_vgic.h | 82 +++++
>> arch/arm/kvm/vgic.c | 593 +++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 674 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h
>> index 270dcd2..9ff0d9c 100644
>> --- a/arch/arm/include/asm/kvm_vgic.h
>> +++ b/arch/arm/include/asm/kvm_vgic.h
>> @@ -19,12 +19,94 @@
>> #ifndef __ASM_ARM_KVM_VGIC_H
>> #define __ASM_ARM_KVM_VGIC_H
>>
>> +#include <linux/kernel.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +#include <linux/irqreturn.h>
>> +#include <linux/spinlock.h>
>> +#include <linux/types.h>
>> #include <asm/hardware/gic.h>
>>
>> +#define VGIC_NR_IRQS 128
>> +#define VGIC_NR_SGIS 16
>
> Now that you have this, you can use it in a few places (see also the BUG_ONs
> in vgic_queue_irq).
>
>> +#define VGIC_NR_PPIS 16
>> +#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)
>> +#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)
>> +#define VGIC_MAX_CPUS KVM_MAX_VCPUS
>> +
>> +/* Sanity checks... */
>> +#if (VGIC_MAX_CPUS > 8)
>> +#error Invalid number of CPU interfaces
>> +#endif
>> +
>> +#if (VGIC_NR_IRQS & 31)
>> +#error "VGIC_NR_IRQS must be a multiple of 32"
>> +#endif
>> +
>> +#if (VGIC_NR_IRQS > 1024)
>> +#error "VGIC_NR_IRQS must be <= 1024"
>> +#endif
>> +
>> +/*
>> + * The GIC distributor registers describing interrupts have two parts:
>> + * - 32 per-CPU interrupts (SGI + PPI)
>> + * - a bunch of shared interrupts (SPI)
>> + */
>> +struct vgic_bitmap {
>> + union {
>> + u32 reg[VGIC_NR_PRIVATE_IRQS / 32];
>> + DECLARE_BITMAP(reg_ul, VGIC_NR_PRIVATE_IRQS);
>> + } percpu[VGIC_MAX_CPUS];
>> + union {
>> + u32 reg[VGIC_NR_SHARED_IRQS / 32];
>> + DECLARE_BITMAP(reg_ul, VGIC_NR_SHARED_IRQS);
>> + } shared;
>> +};
>> +
>> +struct vgic_bytemap {
>> + u32 percpu[VGIC_MAX_CPUS][VGIC_NR_PRIVATE_IRQS / 4];
>> + u32 shared[VGIC_NR_SHARED_IRQS / 4];
>> +};
>> +
>> struct vgic_dist {
>> +#ifdef CONFIG_KVM_ARM_VGIC
>> + spinlock_t lock;
>> +
>> + /* Virtual control interface mapping */
>> + void __iomem *vctrl_base;
>> +
>> /* Distributor and vcpu interface mapping in the guest */
>> phys_addr_t vgic_dist_base;
>> phys_addr_t vgic_cpu_base;
>> +
>> + /* Distributor enabled */
>> + u32 enabled;
>> +
>> + /* Interrupt enabled (one bit per IRQ) */
>> + struct vgic_bitmap irq_enabled;
>> +
>> + /* Interrupt 'pin' level */
>> + struct vgic_bitmap irq_state;
>> +
>> + /* Level-triggered interrupt in progress */
>> + struct vgic_bitmap irq_active;
>> +
>> + /* Interrupt priority. Not used yet. */
>> + struct vgic_bytemap irq_priority;
>> +
>> + /* Level/edge triggered */
>> + struct vgic_bitmap irq_cfg;
>> +
>> + /* Source CPU per SGI and target CPU */
>> + u8 irq_sgi_sources[VGIC_MAX_CPUS][16];
>
> VGIC_NR_SGIS
>
>
>> +static u32 vgic_get_target_reg(struct kvm *kvm, int irq)
>> +{
>> + struct vgic_dist *dist = &kvm->arch.vgic;
>> + struct kvm_vcpu *vcpu;
>> + int i, c;
>> + unsigned long *bmap;
>> + u32 val = 0;
>> +
>> + irq -= VGIC_NR_PRIVATE_IRQS;
>> +
>> + kvm_for_each_vcpu(c, vcpu, kvm) {
>> + bmap = vgic_bitmap_get_shared_map(&dist->irq_spi_target[c]);
>> + for (i = 0; i < GICD_IRQS_PER_ITARGETSR; i++)
>> + if (test_bit(irq + i, bmap))
>> + val |= 1 << (c + i * 8);
>> + }
>> +
>> + return val;
>> +}
>> +
>> +static void vgic_set_target_reg(struct kvm *kvm, u32 val, int irq)
>> +{
>> + struct vgic_dist *dist = &kvm->arch.vgic;
>> + struct kvm_vcpu *vcpu;
>> + int i, c;
>> + unsigned long *bmap;
>> + u32 target;
>> +
>> + BUG_ON(irq & 3);
>> + BUG_ON(irq < VGIC_NR_PRIVATE_IRQS);
>
> This is now different to vgic_Get_target_reg, which doesn't have the
> BUG_ONs. Can we remove these ones too?
>
>> + irq -= VGIC_NR_PRIVATE_IRQS;
>> +
>> + /*
>> + * Pick the LSB in each byte. This ensures we target exactly
>> + * one vcpu per IRQ. If the byte is null, assume we target
>> + * CPU0.
>> + */
>> + for (i = 0; i < GICD_IRQS_PER_ITARGETSR; i++) {
>> + int shift = i * GICD_CPUTARGETS_BITS;
>> + target = ffs((val >> shift) & 0xffU);
>> + target = target ? (target - 1) : 0;
>> + dist->irq_spi_cpu[irq + i] = target;
>> + kvm_for_each_vcpu(c, vcpu, kvm) {
>> + bmap = vgic_bitmap_get_shared_map(&dist->irq_spi_target[c]);
>> + if (c == target)
>> + set_bit(irq + i, bmap);
>> + else
>> + clear_bit(irq + i, bmap);
>> + }
>> + }
>> +}
>
> [...]
>
>> static const struct mmio_range vgic_ranges[] = {
>> + { /* CTRL, TYPER, IIDR */
>> + .base = 0,
>> + .len = 12,
>> + .handle_mmio = handle_mmio_misc,
>> + },
>> + { /* IGROUPRn */
>> + .base = 0x80,
>> + .len = VGIC_NR_IRQS / 8,
>> + .handle_mmio = handle_mmio_raz_wi,
>> + },
>> + { /* ISENABLERn */
>> + .base = 0x100,
>> + .len = VGIC_NR_IRQS / 8,
>> + .handle_mmio = handle_mmio_set_enable_reg,
>> + },
>> + { /* ICENABLERn */
>> + .base = 0x180,
>> + .len = VGIC_NR_IRQS / 8,
>> + .handle_mmio = handle_mmio_clear_enable_reg,
>> + },
>> + { /* ISPENDRn */
>> + .base = 0x200,
>> + .len = VGIC_NR_IRQS / 8,
>> + .handle_mmio = handle_mmio_set_pending_reg,
>> + },
>> + { /* ICPENDRn */
>> + .base = 0x280,
>> + .len = VGIC_NR_IRQS / 8,
>> + .handle_mmio = handle_mmio_clear_pending_reg,
>> + },
>> + { /* ISACTIVERn */
>> + .base = 0x300,
>> + .len = VGIC_NR_IRQS / 8,
>> + .handle_mmio = handle_mmio_raz_wi,
>> + },
>> + { /* ICACTIVERn */
>> + .base = 0x380,
>> + .len = VGIC_NR_IRQS / 8,
>> + .handle_mmio = handle_mmio_raz_wi,
>> + },
>> + { /* IPRIORITYRn */
>> + .base = 0x400,
>> + .len = VGIC_NR_IRQS,
>> + .handle_mmio = handle_mmio_priority_reg,
>> + },
>> + { /* ITARGETSRn */
>> + .base = 0x800,
>> + .len = VGIC_NR_IRQS,
>> + .handle_mmio = handle_mmio_target_reg,
>> + },
>> + { /* ICFGRn */
>> + .base = 0xC00,
>> + .len = VGIC_NR_IRQS / 4,
>> + .handle_mmio = handle_mmio_cfg_reg,
>> + },
>> + { /* SGIRn */
>> + .base = 0xF00,
>> + .len = 4,
>> + .handle_mmio = handle_mmio_sgi_reg,
>> + },
>> {}
>> };
>
> You've added named definitions for these constants to the GIC header file,
> so please replace these immediates with those and delete the comments.
>
The following two commits should address your concerns:
commit ff4648faa6fd3342ce72e537a8068ab21d4085c8
Author: Christoffer Dall <c.dall@virtualopensystems.com>
Date: Mon Jan 14 16:53:21 2013 -0500
KVM: ARM: vgic: Use defines instead of hardcoded numbers.
Address reviewer comments.
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h
index f5f270b..1ace491 100644
--- a/arch/arm/include/asm/kvm_vgic.h
+++ b/arch/arm/include/asm/kvm_vgic.h
@@ -99,7 +99,7 @@ struct vgic_dist {
struct vgic_bitmap irq_cfg;
/* Source CPU per SGI and target CPU */
- u8 irq_sgi_sources[VGIC_MAX_CPUS][16];
+ u8 irq_sgi_sources[VGIC_MAX_CPUS][VGIC_NR_SGIS];
/* Target CPU for each IRQ */
u8 irq_spi_cpu[VGIC_NR_SHARED_IRQS];
diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
index 25daa07..a0d283c 100644
--- a/arch/arm/kvm/vgic.c
+++ b/arch/arm/kvm/vgic.c
@@ -447,9 +447,6 @@ static void vgic_set_target_reg(struct kvm *kvm,
u32 val, int irq)
unsigned long *bmap;
u32 target;
- BUG_ON(irq & 3);
- BUG_ON(irq < VGIC_NR_PRIVATE_IRQS);
-
irq -= VGIC_NR_PRIVATE_IRQS;
/*
@@ -598,63 +595,63 @@ struct mmio_range {
};
static const struct mmio_range vgic_ranges[] = {
- { /* CTRL, TYPER, IIDR */
- .base = 0,
+ {
+ .base = GIC_DIST_CTRL,
.len = 12,
.handle_mmio = handle_mmio_misc,
},
- { /* IGROUPRn */
- .base = 0x80,
+ {
+ .base = GIC_DIST_IGROUP,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_raz_wi,
},
- { /* ISENABLERn */
- .base = 0x100,
+ {
+ .base = GIC_DIST_ENABLE_SET,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_set_enable_reg,
},
- { /* ICENABLERn */
- .base = 0x180,
+ {
+ .base = GIC_DIST_ENABLE_CLEAR,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_clear_enable_reg,
},
- { /* ISPENDRn */
- .base = 0x200,
+ {
+ .base = GIC_DIST_PENDING_SET,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_set_pending_reg,
},
- { /* ICPENDRn */
- .base = 0x280,
+ {
+ .base = GIC_DIST_PENDING_CLEAR,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_clear_pending_reg,
},
- { /* ISACTIVERn */
- .base = 0x300,
+ {
+ .base = GIC_DIST_ACTIVE_SET,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_raz_wi,
},
- { /* ICACTIVERn */
- .base = 0x380,
+ {
+ .base = GIC_DIST_ACTIVE_CLEAR,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_raz_wi,
},
- { /* IPRIORITYRn */
- .base = 0x400,
+ {
+ .base = GIC_DIST_PRI,
.len = VGIC_NR_IRQS,
.handle_mmio = handle_mmio_priority_reg,
},
- { /* ITARGETSRn */
- .base = 0x800,
+ {
+ .base = GIC_DIST_TARGET,
.len = VGIC_NR_IRQS,
.handle_mmio = handle_mmio_target_reg,
},
- { /* ICFGRn */
- .base = 0xC00,
+ {
+ .base = GIC_DIST_CONFIG,
.len = VGIC_NR_IRQS / 4,
.handle_mmio = handle_mmio_cfg_reg,
},
- { /* SGIRn */
- .base = 0xF00,
+ {
+ .base = GIC_DIST_SOFTINT,
.len = 4,
.handle_mmio = handle_mmio_sgi_reg,
},
@@ -856,7 +853,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu,
u8 sgi_source_id, int irq)
/* Sanitize the input... */
BUG_ON(sgi_source_id & ~7);
- BUG_ON(sgi_source_id && irq > 15);
+ BUG_ON(sgi_source_id && irq >= VGIC_NR_SGIS);
BUG_ON(irq >= VGIC_NR_IRQS);
kvm_debug("Queue IRQ%d\n", irq);
--
commit 940c2382e1d1cb6831d35ceeccb02c3d3f76a45c
Author: Christoffer Dall <c.dall@virtualopensystems.com>
Date: Mon Jan 14 16:51:30 2013 -0500
ARM: gic: add missing distributor defintions
Add missing register map offsets for the distributor and rename
GIC_DIST_ACTIVE_BIT to GIC_DIST_ACTIVE_SET to be consistent.
Cc: Marc Zyniger <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
diff --git a/arch/arm/include/asm/hardware/gic.h
b/arch/arm/include/asm/hardware/gic.h
index dd1add1..6cad421 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -22,11 +22,13 @@
#define GIC_DIST_CTRL 0x000
#define GIC_DIST_CTR 0x004
+#define GIC_DIST_IGROUP 0x080
#define GIC_DIST_ENABLE_SET 0x100
#define GIC_DIST_ENABLE_CLEAR 0x180
#define GIC_DIST_PENDING_SET 0x200
#define GIC_DIST_PENDING_CLEAR 0x280
-#define GIC_DIST_ACTIVE_BIT 0x300
+#define GIC_DIST_ACTIVE_SET 0x300
+#define GIC_DIST_ACTIVE_CLEAR 0x380
#define GIC_DIST_PRI 0x400
#define GIC_DIST_TARGET 0x800
#define GIC_DIST_CONFIG 0xc00
--
Thanks,
-Christoffer
^ permalink raw reply related
* [PATCH v2] ARM: let CPUs not being able to run in ARM mode enter in THUMB mode
From: Nicolas Pitre @ 2013-01-14 21:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358162123-30113-1-git-send-email-u.kleine-koenig@pengutronix.de>
On Mon, 14 Jan 2013, Uwe Kleine-K?nig wrote:
> Some ARM cores are not capable to run in ARM mode (e.g. Cortex-M3). So
> obviously these cannot enter the kernel in ARM mode. Make an exception
> for them and let them enter in THUMB mode.
>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Acked-by: Nicolas Pitre <nico@linaro.org>
> ---
> Changes since (implicit) v1,
> id: 1357904397-8476-1-git-send-email-u.kleine-koenig at pengutronix.de:
>
> - drop modification to entry for MMU machines
> - don't select user-visible symbols
> - rename THUMBONLY_CPU to CPU_THUMBONLY
> - move CPU_THUMBONLY definition further down in arch/arm/mm/Kconfig
>
> arch/arm/Kconfig | 3 ++-
> arch/arm/kernel/head-nommu.S | 8 +++++++-
> arch/arm/mm/Kconfig | 9 ++++++++-
> 3 files changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 67874b8..e04c779 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1656,8 +1656,9 @@ config HZ
> default 100
>
> config THUMB2_KERNEL
> - bool "Compile the kernel in Thumb-2 mode"
> + bool "Compile the kernel in Thumb-2 mode" if !CPU_THUMBONLY
> depends on CPU_V7 && !CPU_V6 && !CPU_V6K
> + default y if CPU_THUMBONLY
> select AEABI
> select ARM_ASM_UNIFIED
> select ARM_UNWIND
> diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
> index 3782320..e8ecae2 100644
> --- a/arch/arm/kernel/head-nommu.S
> +++ b/arch/arm/kernel/head-nommu.S
> @@ -32,15 +32,21 @@
> * numbers for r1.
> *
> */
> - .arm
>
> __HEAD
> +
> +#ifdef CONFIG_CPU_THUMBONLY
> + .thumb
> +ENTRY(stext)
> +#else
> + .arm
> ENTRY(stext)
>
> THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM.
> THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
> THUMB( .thumb ) @ switch to Thumb now.
> THUMB(1: )
> +#endif
>
> setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
> @ and irqs disabled
> diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
> index 3fd629d..8defd63 100644
> --- a/arch/arm/mm/Kconfig
> +++ b/arch/arm/mm/Kconfig
> @@ -397,6 +397,13 @@ config CPU_V7
> select CPU_PABRT_V7
> select CPU_TLB_V7 if MMU
>
> +config CPU_THUMBONLY
> + bool
> + # There are no CPUs available with MMU that don't implement an ARM ISA:
> + depends on !MMU
> + help
> + Select this if your CPU doesn't support the 32 bit ARM instructions.
> +
> # Figure out what processor architecture version we should be using.
> # This defines the compiler instruction set which depends on the machine type.
> config CPU_32v3
> @@ -608,7 +615,7 @@ config ARCH_DMA_ADDR_T_64BIT
> bool
>
> config ARM_THUMB
> - bool "Support Thumb user binaries"
> + bool "Support Thumb user binaries" if !CPU_THUMBONLY
> depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON
> default y
> help
> --
> 1.7.10.4
>
^ permalink raw reply
* [PATCH] clk: prima2: enable dt-binding clkdev mapping
From: Mike Turquette @ 2013-01-14 21:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355993491-21233-1-git-send-email-Barry.Song@csr.com>
Quoting Barry Song (2012-12-20 00:51:31)
> From: Barry Song <Baohua.Song@csr.com>
>
> this patche deletes hard code that registers clkdev by things like:
> clk_register_clkdev(clk, NULL, "b0030000.nand");
> clk_register_clkdev(clk, NULL, "b0040000.audio");
> clk_register_clkdev(clk, NULL, "b0080000.usp");
> prima2 clock controller becomes a clock provider and every dt node
> just declares its clock sources by dt prop.
>
> it also makes us easier to extend this driver to support both prima2
> and marco as marco has different address mapping with prima2.
>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>
Barry,
The changes to clk-prima2.c look OK to me. Did you want me to take this
patch through clk-next?
Thanks,
Mike
> ---
> .../devicetree/bindings/clock/prima2-clock.txt | 73 +++++++
> arch/arm/boot/dts/prima2.dtsi | 31 +++-
> drivers/clk/clk-prima2.c | 205 ++++++++------------
> 3 files changed, 183 insertions(+), 126 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/clock/prima2-clock.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/prima2-clock.txt b/Documentation/devicetree/bindings/clock/prima2-clock.txt
> new file mode 100644
> index 0000000..5016979
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/prima2-clock.txt
> @@ -0,0 +1,73 @@
> +* Clock bindings for CSR SiRFprimaII
> +
> +Required properties:
> +- compatible: Should be "sirf,prima2-clkc"
> +- reg: Address and length of the register set
> +- interrupts: Should contain clock controller interrupt
> +- #clock-cells: Should be <1>
> +
> +The clock consumer should specify the desired clock by having the clock
> +ID in its "clocks" phandle cell. The following is a full list of prima2
> +clocks and IDs.
> +
> + Clock ID
> + ---------------------------
> + rtc 0
> + osc 1
> + pll1 2
> + pll2 3
> + pll3 4
> + mem 5
> + sys 6
> + security 7
> + dsp 8
> + gps 9
> + mf 10
> + io 11
> + cpu 12
> + uart0 13
> + uart1 14
> + uart2 15
> + tsc 16
> + i2c0 17
> + i2c1 18
> + spi0 19
> + spi1 20
> + pwmc 21
> + efuse 22
> + pulse 23
> + dmac0 24
> + dmac1 25
> + nand 26
> + audio 27
> + usp0 28
> + usp1 29
> + usp2 30
> + vip 31
> + gfx 32
> + mm 33
> + lcd 34
> + vpp 35
> + mmc01 36
> + mmc23 37
> + mmc45 38
> + usbpll 39
> + usb0 40
> + usb1 41
> +
> +Examples:
> +
> +clks: clock-controller at 88000000 {
> + compatible = "sirf,prima2-clkc";
> + reg = <0x88000000 0x1000>;
> + interrupts = <3>;
> + #clock-cells = <1>;
> +};
> +
> +i2c0: i2c at b00e0000 {
> + cell-index = <0>;
> + compatible = "sirf,prima2-i2c";
> + reg = <0xb00e0000 0x10000>;
> + interrupts = <24>;
> + clocks = <&clks 17>;
> +};
> diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi
> index 055fca5..3329719 100644
> --- a/arch/arm/boot/dts/prima2.dtsi
> +++ b/arch/arm/boot/dts/prima2.dtsi
> @@ -58,10 +58,11 @@
> #size-cells = <1>;
> ranges = <0x88000000 0x88000000 0x40000>;
>
> - clock-controller at 88000000 {
> + clks: clock-controller at 88000000 {
> compatible = "sirf,prima2-clkc";
> reg = <0x88000000 0x1000>;
> interrupts = <3>;
> + #clock-cells = <1>;
> };
>
> reset-controller at 88010000 {
> @@ -85,6 +86,7 @@
> compatible = "sirf,prima2-memc";
> reg = <0x90000000 0x10000>;
> interrupts = <27>;
> + clocks = <&clks 5>;
> };
> };
>
> @@ -104,6 +106,7 @@
> compatible = "sirf,prima2-vpp";
> reg = <0x90020000 0x10000>;
> interrupts = <31>;
> + clocks = <&clks 35>;
> };
> };
>
> @@ -117,6 +120,7 @@
> compatible = "powervr,sgx531";
> reg = <0x98000000 0x8000000>;
> interrupts = <6>;
> + clocks = <&clks 32>;
> };
> };
>
> @@ -130,6 +134,7 @@
> compatible = "sirf,prima2-video-codec";
> reg = <0xa0000000 0x8000000>;
> interrupts = <5>;
> + clocks = <&clks 33>;
> };
> };
>
> @@ -149,12 +154,14 @@
> compatible = "sirf,prima2-gps";
> reg = <0xa8010000 0x10000>;
> interrupts = <7>;
> + clocks = <&clks 9>;
> };
>
> dsp at a9000000 {
> compatible = "sirf,prima2-dsp";
> reg = <0xa9000000 0x1000000>;
> interrupts = <8>;
> + clocks = <&clks 8>;
> };
> };
>
> @@ -174,12 +181,14 @@
> compatible = "sirf,prima2-nand";
> reg = <0xb0030000 0x10000>;
> interrupts = <41>;
> + clocks = <&clks 26>;
> };
>
> audio at b0040000 {
> compatible = "sirf,prima2-audio";
> reg = <0xb0040000 0x10000>;
> interrupts = <35>;
> + clocks = <&clks 27>;
> };
>
> uart0: uart at b0050000 {
> @@ -187,6 +196,7 @@
> compatible = "sirf,prima2-uart";
> reg = <0xb0050000 0x10000>;
> interrupts = <17>;
> + clocks = <&clks 13>;
> };
>
> uart1: uart at b0060000 {
> @@ -194,6 +204,7 @@
> compatible = "sirf,prima2-uart";
> reg = <0xb0060000 0x10000>;
> interrupts = <18>;
> + clocks = <&clks 14>;
> };
>
> uart2: uart at b0070000 {
> @@ -201,6 +212,7 @@
> compatible = "sirf,prima2-uart";
> reg = <0xb0070000 0x10000>;
> interrupts = <19>;
> + clocks = <&clks 15>;
> };
>
> usp0: usp at b0080000 {
> @@ -208,6 +220,7 @@
> compatible = "sirf,prima2-usp";
> reg = <0xb0080000 0x10000>;
> interrupts = <20>;
> + clocks = <&clks 28>;
> };
>
> usp1: usp at b0090000 {
> @@ -215,6 +228,7 @@
> compatible = "sirf,prima2-usp";
> reg = <0xb0090000 0x10000>;
> interrupts = <21>;
> + clocks = <&clks 29>;
> };
>
> usp2: usp at b00a0000 {
> @@ -222,6 +236,7 @@
> compatible = "sirf,prima2-usp";
> reg = <0xb00a0000 0x10000>;
> interrupts = <22>;
> + clocks = <&clks 30>;
> };
>
> dmac0: dma-controller at b00b0000 {
> @@ -229,6 +244,7 @@
> compatible = "sirf,prima2-dmac";
> reg = <0xb00b0000 0x10000>;
> interrupts = <12>;
> + clocks = <&clks 24>;
> };
>
> dmac1: dma-controller at b0160000 {
> @@ -236,11 +252,13 @@
> compatible = "sirf,prima2-dmac";
> reg = <0xb0160000 0x10000>;
> interrupts = <13>;
> + clocks = <&clks 25>;
> };
>
> vip at b00C0000 {
> compatible = "sirf,prima2-vip";
> reg = <0xb00C0000 0x10000>;
> + clocks = <&clks 31>;
> };
>
> spi0: spi at b00d0000 {
> @@ -248,6 +266,7 @@
> compatible = "sirf,prima2-spi";
> reg = <0xb00d0000 0x10000>;
> interrupts = <15>;
> + clocks = <&clks 19>;
> };
>
> spi1: spi at b0170000 {
> @@ -255,6 +274,7 @@
> compatible = "sirf,prima2-spi";
> reg = <0xb0170000 0x10000>;
> interrupts = <16>;
> + clocks = <&clks 20>;
> };
>
> i2c0: i2c at b00e0000 {
> @@ -262,6 +282,7 @@
> compatible = "sirf,prima2-i2c";
> reg = <0xb00e0000 0x10000>;
> interrupts = <24>;
> + clocks = <&clks 17>;
> };
>
> i2c1: i2c at b00f0000 {
> @@ -269,12 +290,14 @@
> compatible = "sirf,prima2-i2c";
> reg = <0xb00f0000 0x10000>;
> interrupts = <25>;
> + clocks = <&clks 18>;
> };
>
> tsc at b0110000 {
> compatible = "sirf,prima2-tsc";
> reg = <0xb0110000 0x10000>;
> interrupts = <33>;
> + clocks = <&clks 16>;
> };
>
> gpio: pinctrl at b0120000 {
> @@ -507,17 +530,20 @@
> pwm at b0130000 {
> compatible = "sirf,prima2-pwm";
> reg = <0xb0130000 0x10000>;
> + clocks = <&clks 21>;
> };
>
> efusesys at b0140000 {
> compatible = "sirf,prima2-efuse";
> reg = <0xb0140000 0x10000>;
> + clocks = <&clks 22>;
> };
>
> pulsec at b0150000 {
> compatible = "sirf,prima2-pulsec";
> reg = <0xb0150000 0x10000>;
> interrupts = <48>;
> + clocks = <&clks 23>;
> };
>
> pci-iobg {
> @@ -616,12 +642,14 @@
> compatible = "chipidea,ci13611a-prima2";
> reg = <0xb8000000 0x10000>;
> interrupts = <10>;
> + clocks = <&clks 40>;
> };
>
> usb1: usb at b00f0000 {
> compatible = "chipidea,ci13611a-prima2";
> reg = <0xb8010000 0x10000>;
> interrupts = <11>;
> + clocks = <&clks 41>;
> };
>
> sata at b00f0000 {
> @@ -634,6 +662,7 @@
> compatible = "sirf,prima2-security";
> reg = <0xb8030000 0x10000>;
> interrupts = <42>;
> + clocks = <&clks 7>;
> };
> };
> };
> diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c
> index a203ecc..f8e9d0c 100644
> --- a/drivers/clk/clk-prima2.c
> +++ b/drivers/clk/clk-prima2.c
> @@ -1025,20 +1025,67 @@ static struct of_device_id rsc_ids[] = {
> {},
> };
>
> +enum prima2_clk_index {
> + /* 0 1 2 3 4 5 6 7 8 9 */
> + rtc, osc, pll1, pll2, pll3, mem, sys, security, dsp, gps,
> + mf, io, cpu, uart0, uart1, uart2, tsc, i2c0, i2c1, spi0,
> + spi1, pwmc, efuse, pulse, dmac0, dmac1, nand, audio, usp0, usp1,
> + usp2, vip, gfx, mm, lcd, vpp, mmc01, mmc23, mmc45, usbpll,
> + usb0, usb1, maxclk,
> +};
> +
> +static __initdata struct clk_hw* prima2_clk_hw_array[maxclk] = {
> + NULL, /* dummy */
> + NULL,
> + &clk_pll1.hw,
> + &clk_pll2.hw,
> + &clk_pll3.hw,
> + &clk_mem.hw,
> + &clk_sys.hw,
> + &clk_security.hw,
> + &clk_dsp.hw,
> + &clk_gps.hw,
> + &clk_mf.hw,
> + &clk_io.hw,
> + &clk_cpu.hw,
> + &clk_uart0.hw,
> + &clk_uart1.hw,
> + &clk_uart2.hw,
> + &clk_tsc.hw,
> + &clk_i2c0.hw,
> + &clk_i2c1.hw,
> + &clk_spi0.hw,
> + &clk_spi1.hw,
> + &clk_pwmc.hw,
> + &clk_efuse.hw,
> + &clk_pulse.hw,
> + &clk_dmac0.hw,
> + &clk_dmac1.hw,
> + &clk_nand.hw,
> + &clk_audio.hw,
> + &clk_usp0.hw,
> + &clk_usp1.hw,
> + &clk_usp2.hw,
> + &clk_vip.hw,
> + &clk_gfx.hw,
> + &clk_mm.hw,
> + &clk_lcd.hw,
> + &clk_vpp.hw,
> + &clk_mmc01.hw,
> + &clk_mmc23.hw,
> + &clk_mmc45.hw,
> + &usb_pll_clk_hw,
> + &clk_usb0.hw,
> + &clk_usb1.hw,
> +};
> +
> +static struct clk *prima2_clks[maxclk];
> +static struct clk_onecell_data clk_data;
> +
> void __init sirfsoc_of_clk_init(void)
> {
> - struct clk *clk;
> struct device_node *np;
> -
> - np = of_find_matching_node(NULL, clkc_ids);
> - if (!np)
> - panic("unable to find compatible clkc node in dtb\n");
> -
> - sirfsoc_clk_vbase = of_iomap(np, 0);
> - if (!sirfsoc_clk_vbase)
> - panic("unable to map clkc registers\n");
> -
> - of_node_put(np);
> + int i;
>
> np = of_find_matching_node(NULL, rsc_ids);
> if (!np)
> @@ -1050,122 +1097,30 @@ void __init sirfsoc_of_clk_init(void)
>
> of_node_put(np);
>
> + np = of_find_matching_node(NULL, clkc_ids);
> + if (!np)
> + return;
> +
> + sirfsoc_clk_vbase = of_iomap(np, 0);
> + if (!sirfsoc_clk_vbase)
> + panic("unable to map clkc registers\n");
>
> /* These are always available (RTC and 26MHz OSC)*/
> - clk = clk_register_fixed_rate(NULL, "rtc", NULL,
> + prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL,
> CLK_IS_ROOT, 32768);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register_fixed_rate(NULL, "osc", NULL,
> + prima2_clks[osc]= clk_register_fixed_rate(NULL, "osc", NULL,
> CLK_IS_ROOT, 26000000);
> - BUG_ON(IS_ERR(clk));
> -
> - clk = clk_register(NULL, &clk_pll1.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_pll2.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_pll3.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_mem.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_sys.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_security.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b8030000.security");
> - clk = clk_register(NULL, &clk_dsp.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_gps.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "a8010000.gps");
> - clk = clk_register(NULL, &clk_mf.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_io.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "io");
> - clk = clk_register(NULL, &clk_cpu.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "cpu");
> - clk = clk_register(NULL, &clk_uart0.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0050000.uart");
> - clk = clk_register(NULL, &clk_uart1.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0060000.uart");
> - clk = clk_register(NULL, &clk_uart2.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0070000.uart");
> - clk = clk_register(NULL, &clk_tsc.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0110000.tsc");
> - clk = clk_register(NULL, &clk_i2c0.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b00e0000.i2c");
> - clk = clk_register(NULL, &clk_i2c1.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b00f0000.i2c");
> - clk = clk_register(NULL, &clk_spi0.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b00d0000.spi");
> - clk = clk_register(NULL, &clk_spi1.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0170000.spi");
> - clk = clk_register(NULL, &clk_pwmc.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0130000.pwm");
> - clk = clk_register(NULL, &clk_efuse.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0140000.efusesys");
> - clk = clk_register(NULL, &clk_pulse.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0150000.pulsec");
> - clk = clk_register(NULL, &clk_dmac0.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b00b0000.dma-controller");
> - clk = clk_register(NULL, &clk_dmac1.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0160000.dma-controller");
> - clk = clk_register(NULL, &clk_nand.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0030000.nand");
> - clk = clk_register(NULL, &clk_audio.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0040000.audio");
> - clk = clk_register(NULL, &clk_usp0.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0080000.usp");
> - clk = clk_register(NULL, &clk_usp1.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b0090000.usp");
> - clk = clk_register(NULL, &clk_usp2.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b00a0000.usp");
> - clk = clk_register(NULL, &clk_vip.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b00c0000.vip");
> - clk = clk_register(NULL, &clk_gfx.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "98000000.graphics");
> - clk = clk_register(NULL, &clk_mm.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "a0000000.multimedia");
> - clk = clk_register(NULL, &clk_lcd.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "90010000.display");
> - clk = clk_register(NULL, &clk_vpp.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "90020000.vpp");
> - clk = clk_register(NULL, &clk_mmc01.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_mmc23.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_mmc45.hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &usb_pll_clk_hw);
> - BUG_ON(IS_ERR(clk));
> - clk = clk_register(NULL, &clk_usb0.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b00e0000.usb");
> - clk = clk_register(NULL, &clk_usb1.hw);
> - BUG_ON(IS_ERR(clk));
> - clk_register_clkdev(clk, NULL, "b00f0000.usb");
> +
> + for (i = pll1; i < maxclk; i++) {
> + prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]);
> + BUG_ON(!prima2_clks[i]);
> + }
> + clk_register_clkdev(prima2_clks[cpu], NULL, "cpu");
> + clk_register_clkdev(prima2_clks[io], NULL, "io");
> + clk_register_clkdev(prima2_clks[mem], NULL, "mem");
> +
> + clk_data.clks = prima2_clks;
> + clk_data.clk_num = maxclk;
> +
> + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> }
> --
> 1.7.5.4
>
>
>
> Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
> More information can be found at www.csr.com. Follow CSR on Twitter at http://twitter.com/CSR_PLC and read our blog at www.csr.com/blog
^ permalink raw reply
* [PATCH 03/16] ARM: b.L: introduce helpers for platform coherency exit/setup
From: Catalin Marinas @ 2013-01-14 21:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130114181006.GB1967@linaro.org>
On Mon, Jan 14, 2013 at 06:10:06PM +0000, Dave Martin wrote:
> On Mon, Jan 14, 2013 at 05:15:28PM +0000, Catalin Marinas wrote:
> > On Mon, Jan 14, 2013 at 05:08:51PM +0000, Dave Martin wrote:
> > > From b64f305c90e7ea585992df2d710f62ec6a7b5395 Mon Sep 17 00:00:00 2001
> > > From: Dave Martin <dave.martin@linaro.org>
> > > Date: Mon, 14 Jan 2013 16:25:47 +0000
> > > Subject: [PATCH] ARM: b.L: Fix outer cache handling for coherency setup/exit helpers
> > >
> > > This patch addresses the following issues:
> > >
> > > * When invalidating stale data from the cache before a read,
> > > outer caches must be invalidated _before_ inner caches, not
> > > after, otherwise stale data may be re-filled from outer to
> > > inner after the inner cache is flushed.
> > >
> > > We still retain an inner clean before touching the outer cache,
> > > to avoid stale data being rewritten from there into the outer
> > > cache after the outer cache is flushed.
> > >
> > > * All the sync_mem() calls synchronise either reads or writes,
> > > but not both. This patch splits sync_mem() into separate
> > > functions for reads and writes, to avoid excessive inner
> > > flushes in the write case.
> > >
> > > The two functions are different from the original sync_mem(),
> > > to fix the above issues.
> > >
> > > Signed-off-by: Dave Martin <dave.martin@linaro.org>
> > > ---
> > > NOTE: This patch is build-tested only.
> > >
> > > arch/arm/common/bL_entry.c | 57 ++++++++++++++++++++++++++++++++++----------
> > > 1 files changed, 44 insertions(+), 13 deletions(-)
> > >
> > > diff --git a/arch/arm/common/bL_entry.c b/arch/arm/common/bL_entry.c
> > > index 1ea4ec9..3e1a404 100644
> > > --- a/arch/arm/common/bL_entry.c
> > > +++ b/arch/arm/common/bL_entry.c
> > > @@ -119,16 +119,47 @@ int bL_cpu_powered_up(void)
> > >
> > > struct bL_sync_struct bL_sync;
> > >
> > > -static void __sync_range(volatile void *p, size_t size)
> > > +/*
> > > + * Ensure preceding writes to *p by this CPU are visible to
> > > + * subsequent reads by other CPUs:
> > > + */
> > > +static void __sync_range_w(volatile void *p, size_t size)
> > > {
> > > char *_p = (char *)p;
> > >
> > > __cpuc_flush_dcache_area(_p, size);
> > > - outer_flush_range(__pa(_p), __pa(_p + size));
> > > + outer_clean_range(__pa(_p), __pa(_p + size));
> > > outer_sync();
> >
> > It's not part of your patch but I thought about commenting here. The
> > outer_clean_range() already has a cache_sync() operation, so no need for
> > the additional outer_sync().
> >
> > > }
> > >
> > > -#define sync_mem(ptr) __sync_range(ptr, sizeof *(ptr))
> > > +/*
> > > + * Ensure preceding writes to *p by other CPUs are visible to
> > > + * subsequent reads by this CPU:
> > > + */
> > > +static void __sync_range_r(volatile void *p, size_t size)
> > > +{
> > > + char *_p = (char *)p;
> > > +
> > > +#ifdef CONFIG_OUTER_CACHE
> > > + if (outer_cache.flush_range) {
> > > + /*
> > > + * Ensure ditry data migrated from other CPUs into our cache
> > > + * are cleaned out safely before the outer cache is cleaned:
> > > + */
> > > + __cpuc_flush_dcache_area(_p, size);
> > > +
> > > + /* Clean and invalidate stale data for *p from outer ... */
> > > + outer_flush_range(__pa(_p), __pa(_p + size));
> > > + outer_sync();
> >
> > Same here.
>
> Ah, right. I've seen code do this in various places, and just copy-
> pasted it under the assumption that it is needed. Our discussion abouto
> ensuring that outer_sync() really does guarantee completion of its
> effects on return still applies.
>
> Are there any situations when outer_sync() should be called explicitly?
outer_sync() on its own ensures the draining of the PL310 write buffer.
DSB drains the CPU write buffers but PL310 doesn't detect it, so a
separate outer_sync() is needed. In general this is required when you
write a Normal Non-cacheable buffer (but bufferable, e.g. DMA coherent)
and you want to ensure data visibility (DSB+outer_sync(), that's what
the mb() macro does).
--
Catalin
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox