* [PATCH] sparsemem/bootmem: catch greater than section size allocations
From: Nishanth Aravamudan @ 2012-02-24 19:33 UTC (permalink / raw)
To: Andrew Morton
Cc: Anton Blanchard, Dave Hansen, linux-mm, Paul Mackerras,
Robert Jennings, linuxppc-dev
While testing AMS (Active Memory Sharing) / CMO (Cooperative Memory
Overcommit) on powerpc, we tripped the following:
kernel BUG at mm/bootmem.c:483!
cpu 0x0: Vector: 700 (Program Check) at [c000000000c03940]
pc: c000000000a62bd8: .alloc_bootmem_core+0x90/0x39c
lr: c000000000a64bcc: .sparse_early_usemaps_alloc_node+0x84/0x29c
sp: c000000000c03bc0
msr: 8000000000021032
current = 0xc000000000b0cce0
paca = 0xc000000001d80000
pid = 0, comm = swapper
kernel BUG at mm/bootmem.c:483!
enter ? for help
[c000000000c03c80] c000000000a64bcc
.sparse_early_usemaps_alloc_node+0x84/0x29c
[c000000000c03d50] c000000000a64f10 .sparse_init+0x12c/0x28c
[c000000000c03e20] c000000000a474f4 .setup_arch+0x20c/0x294
[c000000000c03ee0] c000000000a4079c .start_kernel+0xb4/0x460
[c000000000c03f90] c000000000009670 .start_here_common+0x1c/0x2c
This is
BUG_ON(limit && goal + size > limit);
and after some debugging, it seems that
goal = 0x7ffff000000
limit = 0x80000000000
and sparse_early_usemaps_alloc_node ->
sparse_early_usemaps_alloc_pgdat_section -> alloc_bootmem_section calls
return alloc_bootmem_section(usemap_size() * count, section_nr);
This is on a system with 8TB available via the AMS pool, and as a quirk
of AMS in firmware, all of that memory shows up in node 0. So, we end up
with an allocation that will fail the goal/limit constraints. In theory,
we could "fall-back" to alloc_bootmem_node() in
sparse_early_usemaps_alloc_node(), but since we actually have HOTREMOVE
defined, we'll BUG_ON() instead. A simple solution appears to be to
disable the limit check if the size of the allocation in
alloc_bootmem_secition exceeds the section size.
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: Dave Hansen <haveblue@us.ibm.com>
Cc: Anton Blanchard <anton@au1.ibm.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ben Herrenschmidt <benh@kernel.crashing.org>
Cc: Robert Jennings <rcj@linux.vnet.ibm.com>
Cc: linux-mm@kvack.org
Cc: linuxppc-dev@lists.ozlabs.org
---
include/linux/mmzone.h | 2 ++
mm/bootmem.c | 5 ++++-
2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 650ba2f..4176834 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -967,6 +967,8 @@ static inline unsigned long early_pfn_to_nid(unsigned long pfn)
* PA_SECTION_SHIFT physical address to/from section number
* PFN_SECTION_SHIFT pfn to/from section number
*/
+#define BYTES_PER_SECTION (1UL << SECTION_SIZE_BITS)
+
#define SECTIONS_SHIFT (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
#define PA_SECTION_SHIFT (SECTION_SIZE_BITS)
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 668e94d..5cbbc76 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -770,7 +770,10 @@ void * __init alloc_bootmem_section(unsigned long size,
pfn = section_nr_to_pfn(section_nr);
goal = pfn << PAGE_SHIFT;
- limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
+ if (size > BYTES_PER_SECTION)
+ limit = 0;
+ else
+ limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
--
1.7.5.4
^ permalink raw reply related
* Re: warnings from drivers/tty/ehv_bytechan.c
From: gregkh @ 2012-02-24 21:50 UTC (permalink / raw)
To: Tabi Timur-B04825; +Cc: Stephen Rothwell, ppc-dev
In-Reply-To: <4F424985.2020706@freescale.com>
On Mon, Feb 20, 2012 at 01:24:22PM +0000, Tabi Timur-B04825 wrote:
> Stephen Rothwell wrote:
> > console_initcall() is not defined for modules.
>
> Hmmm... the patch you posted is a good short-term fix, but I wonder if
> makes sense for the driver to support modules at all. I have this in the
> driver:
>
> #include <linux/module.h>
> ...
> module_init(ehv_bc_init);
> module_exit(ehv_bc_exit);
>
> although to be honest, I can't remember the last time I tried to compile
> it as a module.
>
> The problem stems from the fact that it's a console driver *and* a tty
> driver. It makes sense that a tty driver can be compiled as a module, but
> not a console driver.
>
> So Greg, can I do something like this:
>
> #ifdef MODULE
> module_initcall(ehv_bc_console_init)
> #else
> console_initcall(ehv_bc_console_init);
> #endif
Sure, something like that is fine, but if the code really can't be a
module, why not just fix the Kconfig file to enforce this properly
instead?
thanks,
greg k-h
^ permalink raw reply
* Re: warnings from drivers/tty/ehv_bytechan.c
From: Timur Tabi @ 2012-02-24 22:00 UTC (permalink / raw)
To: gregkh@linuxfoundation.org; +Cc: Stephen Rothwell, ppc-dev
In-Reply-To: <20120224215008.GB25330@kroah.com>
gregkh@linuxfoundation.org wrote:
> Sure, something like that is fine, but if the code really can't be a
> module, why not just fix the Kconfig file to enforce this properly
> instead?
That's the simplest approach, for use. The TTY portion of the driver can
be used as a module. Is there any real value in loading a TTY driver as a
module? In this case, the console support for byte channels would not be
available.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: warnings from drivers/tty/ehv_bytechan.c
From: gregkh @ 2012-02-24 22:06 UTC (permalink / raw)
To: Timur Tabi; +Cc: Stephen Rothwell, ppc-dev
In-Reply-To: <4F48086C.5010407@freescale.com>
On Fri, Feb 24, 2012 at 04:00:12PM -0600, Timur Tabi wrote:
> gregkh@linuxfoundation.org wrote:
> > Sure, something like that is fine, but if the code really can't be a
> > module, why not just fix the Kconfig file to enforce this properly
> > instead?
>
> That's the simplest approach, for use. The TTY portion of the driver can
> be used as a module. Is there any real value in loading a TTY driver as a
> module?
Depends on the hardware it supports :)
> In this case, the console support for byte channels would not be
> available.
Then it doesn't make sense, right?
thanks,
greg k-h
^ permalink raw reply
* Re: warnings from drivers/tty/ehv_bytechan.c
From: Timur Tabi @ 2012-02-24 22:15 UTC (permalink / raw)
To: gregkh@linuxfoundation.org; +Cc: Stephen Rothwell, ppc-dev
In-Reply-To: <20120224220623.GA29400@kroah.com>
gregkh@linuxfoundation.org wrote:
>> > That's the simplest approach, for use. The TTY portion of the driver can
>> > be used as a module. Is there any real value in loading a TTY driver as a
>> > module?
> Depends on the hardware it supports :)
>
>> > In this case, the console support for byte channels would not be
>> > available.
> Then it doesn't make sense, right?
I guess that's my question. Is there a real use case for having console
output go to the serial port, and TTY go to a byte channel? Even if you
wanted to do that, I supposed you don't need to load the byte channel
driver as a module to get that behavior.
Anyway, that's all academic. A more important question is: now that the
driver can't be compiled as a module, should I change module_init() to
something else (like device_initcall)?
Should I remove this line?
#include <linux/module.h>
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: warnings from drivers/tty/ehv_bytechan.c
From: gregkh @ 2012-02-24 22:19 UTC (permalink / raw)
To: Timur Tabi; +Cc: Stephen Rothwell, ppc-dev
In-Reply-To: <4F480BE8.9080606@freescale.com>
On Fri, Feb 24, 2012 at 04:15:04PM -0600, Timur Tabi wrote:
> gregkh@linuxfoundation.org wrote:
> >> > That's the simplest approach, for use. The TTY portion of the driver can
> >> > be used as a module. Is there any real value in loading a TTY driver as a
> >> > module?
>
> > Depends on the hardware it supports :)
> >
> >> > In this case, the console support for byte channels would not be
> >> > available.
>
> > Then it doesn't make sense, right?
>
> I guess that's my question. Is there a real use case for having console
> output go to the serial port, and TTY go to a byte channel? Even if you
> wanted to do that, I supposed you don't need to load the byte channel
> driver as a module to get that behavior.
>
> Anyway, that's all academic. A more important question is: now that the
> driver can't be compiled as a module, should I change module_init() to
> something else (like device_initcall)?
>
> Should I remove this line?
>
> #include <linux/module.h>
No, no need to, leave it as-is if it builds properly.
greg k-h
^ permalink raw reply
* Re: [PATCH 09/24] PCI, powerpc: Register busn_res for root buses
From: Jesse Barnes @ 2012-02-24 22:24 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: linux-arch, Tony Luck, linuxppc-dev, linux-kernel,
Dominik Brodowski, Linus Torvalds, Paul Mackerras, linux-pci,
Andrew Morton, Yinghai Lu
In-Reply-To: <CAErSpo7_WGjitDZz4XH+77f65Uz1ynd5_USN+D17D09Eux1iQQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 5202 bytes --]
On Thu, 23 Feb 2012 12:51:30 -0800
Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Thu, Feb 23, 2012 at 12:25 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > On Fri, 10 Feb 2012 08:35:58 +1100
> > Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> >
> >> On Thu, 2012-02-09 at 11:24 -0800, Bjorn Helgaas wrote:
> >> > My point is that the interface between the arch and the PCI core
> >> > should be simply the arch telling the core "this is the range of bus
> >> > numbers you can use." If the firmware doesn't give you the HW limits,
> >> > that's the arch's problem. If you want to assume 0..255 are
> >> > available, again, that's the arch's decision.
> >> >
> >> > But the answer to the question "what bus numbers are available to me"
> >> > depends only on the host bridge HW configuration. It does not depend
> >> > on what pci_scan_child_bus() found. Therefore, I think we can come up
> >> > with a design where pci_bus_update_busn_res_end() is unnecessary.
> >>
> >> In an ideal world yes. In a world where there are reverse engineered
> >> platforms on which we aren't 100% sure how thing actually work under the
> >> hood and have the code just adapt on "what's there" (and try to fix it
> >> up -sometimes-), thinks can get a bit murky :-)
> >>
> >> But yes, I see your point. As for what is the "correct" setting that
> >> needs to be done so that the patch doesn't end up a regression for us,
> >> I'll have to dig into some ancient HW to dbl check a few things. I hope
> >> 0...255 will just work but I can't guarantee it.
> >>
> >> What I'll probably do is constraint the core to the values in
> >> hose->min/max, and update selected platforms to put 0..255 in there when
> >> I know for sure they can cope.
> >
> > But I think the point is, can't we intiialize the busn resource after
> > the first & last bus numbers have been determined? E.g. rather than
> > Yinghai's current:
> > + pci_bus_insert_busn_res(bus, hose->first_busno, hose->last_busno);
> > +
> > /* Get probe mode and perform scan */
> > mode = PCI_PROBE_NORMAL;
> > if (node && ppc_md.pci_probe_mode)
> > @@ -1742,8 +1744,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
> > of_scan_bus(node, bus);
> > }
> >
> > - if (mode == PCI_PROBE_NORMAL)
> > + if (mode == PCI_PROBE_NORMAL) {
> > + pci_bus_update_busn_res_end(bus, 255);
> > hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
> > + pci_bus_update_busn_res_end(bus, bus->subordinate);
> > + }
> >
> > we'd have something more like:
> >
> > /* Get probe mode and perform scan */
> > mode = PCI_PROBE_NORMAL;
> > if (node && ppc_md.pci_probe_mode)
> > @@ -1742,8 +1744,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
> > of_scan_bus(node, bus);
> > }
> >
> > if (mode == PCI_PROBE_NORMAL)
> > hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
> >
> > + pci_bus_insert_busn_res(bus, hose->first_busno, hose->last_busno);
> >
> > since we should have the final bus range by then? Setting the end to
> > 255 and then changing it again doesn't make sense; and definitely makes
> > the code hard to follow.
>
> I have two issues here:
>
> 1) hose->last_busno is currently the highest bus number found by
> pci_scan_child_bus(). If I understand correctly,
> pci_bus_insert_busn_res() is supposed to update the core's idea of the
> host bridge's bus number aperture. (Actually, I guess it just updates
> the *end* of the aperture, since we supply the start directly to
> pci_scan_root_bus()). The aperture and the highest bus number we
> found are not related, except that we should have:
>
> hose->first_busno <= bus->subordinate <= hose->last_busno
>
> If we set the aperture to [first_busno - last_busno], we artificially
> prevent some hotplug.
Oh true, we'll need to allocate any extra bus number space somehow so
that hot plug of bridges is possible in the future w/o renumbering
(until our glorious future when we can move resources on the fly by
stopping drivers).
>
> 2) We already have a way to add resources to a root bus: the
> pci_add_resource() used to add I/O port and MMIO apertures. I think
> it'd be a lot simpler to just use that same interface for the bus
> number aperture, e.g.,
>
> pci_add_resource(&resources, hose->io_space);
> pci_add_resource(&resources, hose->mem_space);
> pci_add_resource(&resources, hose->busnr_space);
> bus = pci_scan_root_bus(dev, next_busno, pci_ops, sysdata, &resources);
>
> This is actually a bit redundant, since "next_busno" should be the
> same as hose->busnr_space->start. So if we adopted this approach, we
> might want to eventually drop the "next_busno" argument.
Yeah that would be nice, the call would certainly make more sense that
way.
--
Jesse Barnes, Intel Open Source Technology Center
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: warnings from drivers/tty/ehv_bytechan.c
From: Scott Wood @ 2012-02-24 23:25 UTC (permalink / raw)
To: Timur Tabi; +Cc: gregkh@linuxfoundation.org, ppc-dev, Stephen Rothwell
In-Reply-To: <4F480BE8.9080606@freescale.com>
On 02/24/2012 04:15 PM, Timur Tabi wrote:
> gregkh@linuxfoundation.org wrote:
>>>> That's the simplest approach, for use. The TTY portion of the driver can
>>>> be used as a module. Is there any real value in loading a TTY driver as a
>>>> module?
>
>> Depends on the hardware it supports :)
>>
>>>> In this case, the console support for byte channels would not be
>>>> available.
>
>> Then it doesn't make sense, right?
>
> I guess that's my question. Is there a real use case for having console
> output go to the serial port, and TTY go to a byte channel?
Sure -- you could be using the byte channel for inter-partition
communication, or just not have enough serial ports for all of this
partition's needs.
It looks like the usual pattern is to have a separate kconfig for the
console part, and have that be a bool that depends on the tristate tty
driver being "y".
> Even if you
> wanted to do that, I supposed you don't need to load the byte channel
> driver as a module to get that behavior.
Right, though that could be said about all (most?) modules.
Probably not that important in this particular case, though. I can see
people wanting to use byte channel but not caring about console, and I
can see people wanting to build a generic kernel that supports byte
channels, but I don't think there's much overlap between the two.
-Scott
^ permalink raw reply
* Re: [PATCH 33/37] KVM: PPC: bookehv: remove unused code
From: Scott Wood @ 2012-02-24 23:31 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1330093591-19523-34-git-send-email-agraf@suse.de>
On 02/24/2012 08:26 AM, Alexander Graf wrote:
> There was some unused code in the exit code path that must have been
> a leftover from earlier iterations. While it did no hard, it's superfluous
> and thus should be removed.
s/hard/harm/ -- at that assumes exit timing wasn't enabled. :-)
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
> arch/powerpc/kvm/bookehv_interrupts.S | 3 ---
> 1 files changed, 0 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
> index 021d087..b1c099b 100644
> --- a/arch/powerpc/kvm/bookehv_interrupts.S
> +++ b/arch/powerpc/kvm/bookehv_interrupts.S
> @@ -112,9 +112,6 @@
> * appropriate for the exception type).
> */
> cmpw r6, r8
> - .if \flags & NEED_EMU
> - lwz r9, KVM_LPID(r9)
> - .endif
> beq 1f
> mfmsr r7
> .if \srr0 != SPRN_MCSRR0 && \srr0 != SPRN_CSRR0
Can also remove "lwz r9, VCPU_KVM(r4)".
-Scott
^ permalink raw reply
* Re: [PATCH 35/37] KVM: PPC: booke: Support perfmon interrupts
From: Scott Wood @ 2012-02-24 23:33 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1330093591-19523-36-git-send-email-agraf@suse.de>
On 02/24/2012 08:26 AM, Alexander Graf wrote:
> When during guest context we get a performance monitor interrupt, we
> currently bail out and oops. Let's route it to its correct handler
> instead.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
> arch/powerpc/kvm/booke.c | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 7adef28..423701b 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -677,6 +677,10 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
> r = RESUME_GUEST;
> break;
>
> + case BOOKE_INTERRUPT_PERFORMANCE_MONITOR:
> + r = RESUME_GUEST;
> + break;
> +
> case BOOKE_INTERRUPT_HV_PRIV:
> r = emulation_exit(run, vcpu);
> break;
Why do we need to call timer_interrupt() explicitly, but can rely on
automatic retriggering for perfmon?
-Scott
^ permalink raw reply
* Re: [PATCH 36/37] KVM: PPC: booke: expose guest registers on irq reinject
From: Scott Wood @ 2012-02-24 23:40 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1330093591-19523-37-git-send-email-agraf@suse.de>
On 02/24/2012 08:26 AM, Alexander Graf wrote:
> +static void kvmppc_fill_pt_regs(struct kvm_vcpu *vcpu, struct pt_regs *regs)
> {
> - int r = RESUME_HOST;
> + int i;
>
> - /* update before a new last_exit_type is rewritten */
> - kvmppc_update_timing_stats(vcpu);
> + for (i = 0; i < 32; i++)
> + regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
> + regs->nip = vcpu->arch.pc;
> + regs->msr = vcpu->arch.shared->msr;
> + regs->ctr = vcpu->arch.ctr;
> + regs->link = vcpu->arch.lr;
> + regs->xer = kvmppc_get_xer(vcpu);
> + regs->ccr = kvmppc_get_cr(vcpu);
> + regs->dar = get_guest_dear(vcpu);
> + regs->dsisr = get_guest_esr(vcpu);
> +}
How much overhead does this add to every interrupt? Can't we keep this
to the minimum that perf cares about?
> +
> +static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu,
> + unsigned int exit_nr)
> +{
> + struct pt_regs regs = *current->thread.regs;
>
> + kvmppc_fill_pt_regs(vcpu, ®s);
Why are you copying out of current->thread.regs? That's old junk data,
set by some previous exception and possibly overwritten since.
-Scott
^ permalink raw reply
* [PATCH] powerpc/prom: bump up maximum size of properties
From: Nishanth Aravamudan @ 2012-02-25 0:23 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev, Anton Blanchard, Paul Mackerras, Robert Jennings
On a 16TB system (using AMS/CMO), I get:
WARNING: ignoring large property [/ibm,dynamic-reconfiguration-memory] ibm,dynamic-memory length 0x000000000017ffec
and significantly less memory is thus shown to the partition. As far as
I can tell, the constant used is arbitrary, but bump it up to 2MB, which
covers the above property (approximately 1.5MB).
With this patch, the kernel does see all of the system memory on the
16TB system.
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: Anton Blanchard <anton@au1.ibm.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Robert Jennings <rcj@linux.vnet.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
---
arch/powerpc/kernel/prom_init.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index eca626e..0bf0ccc 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -53,7 +53,7 @@
* ensure that we don't lose things like the interrupt-map property
* on a PCI-PCI bridge.
*/
-#define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024)
+#define MAX_PROPERTY_LENGTH (2UL * 1024 * 1024)
/*
* Eventually bump that one up
--
1.7.5.4
^ permalink raw reply related
* Re: [PATCH 09/24] PCI, powerpc: Register busn_res for root buses
From: Yinghai Lu @ 2012-02-25 7:47 UTC (permalink / raw)
To: Jesse Barnes
Cc: linux-arch, Tony Luck, linuxppc-dev, linux-kernel,
Dominik Brodowski, Paul Mackerras, linux-pci, Bjorn Helgaas,
Andrew Morton, Linus Torvalds
In-Reply-To: <20120224142430.58f5e5ef@jbarnes-desktop>
On Fri, Feb 24, 2012 at 2:24 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wr=
ote:
> On Thu, 23 Feb 2012 12:51:30 -0800
> Bjorn Helgaas <bhelgaas@google.com> wrote:
>> 2) We already have a way to add resources to a root bus: the
>> pci_add_resource() used to add I/O port and MMIO apertures. =A0I think
>> it'd be a lot simpler to just use that same interface for the bus
>> number aperture, e.g.,
>>
>> =A0 =A0 pci_add_resource(&resources, hose->io_space);
>> =A0 =A0 pci_add_resource(&resources, hose->mem_space);
>> =A0 =A0 pci_add_resource(&resources, hose->busnr_space);
>> =A0 =A0 bus =3D pci_scan_root_bus(dev, next_busno, pci_ops, sysdata, &re=
sources);
>>
>> This is actually a bit redundant, since "next_busno" should be the
>> same as hose->busnr_space->start. =A0So if we adopted this approach, we
>> might want to eventually drop the "next_busno" argument.
>
> Yeah that would be nice, the call would certainly make more sense that
> way.
no, I don't think so.
using pci_add_resource will need to create dummy resource abut bus range.
there is lots of pci_scan_root_bus(), and those user does not bus end
yet before scan.
so could just hide pci_insert_busn_res in pci_scan_root_bus, and
update busn_res end there.
other arch like x86, ia64, powerpc, sparc, will insert exact bus range
between pci_create_root_bus and
pci_scan_child_bus, will not need to update busn_res end.
please check v7 of this patchset.
git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.gi=
t
for-pci-busn-alloc
It should be clean and have minimum lines of change.
Thanks
Yinghai
^ permalink raw reply
* Re: [PATCH 35/37] KVM: PPC: booke: Support perfmon interrupts
From: Alexander Graf @ 2012-02-26 11:58 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <4F481E66.8010408@freescale.com>
On 25.02.2012, at 00:33, Scott Wood wrote:
> On 02/24/2012 08:26 AM, Alexander Graf wrote:
>> When during guest context we get a performance monitor interrupt, we
>> currently bail out and oops. Let's route it to its correct handler
>> instead.
>>=20
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>> ---
>> arch/powerpc/kvm/booke.c | 4 ++++
>> 1 files changed, 4 insertions(+), 0 deletions(-)
>>=20
>> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
>> index 7adef28..423701b 100644
>> --- a/arch/powerpc/kvm/booke.c
>> +++ b/arch/powerpc/kvm/booke.c
>> @@ -677,6 +677,10 @@ int kvmppc_handle_exit(struct kvm_run *run, =
struct kvm_vcpu *vcpu,
>> r =3D RESUME_GUEST;
>> break;
>>=20
>> + case BOOKE_INTERRUPT_PERFORMANCE_MONITOR:
>> + r =3D RESUME_GUEST;
>> + break;
>> +
>> case BOOKE_INTERRUPT_HV_PRIV:
>> r =3D emulation_exit(run, vcpu);
>> break;
>=20
> Why do we need to call timer_interrupt() explicitly, but can rely on
> automatic retriggering for perfmon?
We don't rely on automatic retriggering for perfmon. There are 2 =
different places where we need to handle an incoming exit code - the =
"reinject" code path and the "big switch over all exits" code path. This =
one deals with the latter.
Alex
^ permalink raw reply
* Re: [PATCH 36/37] KVM: PPC: booke: expose guest registers on irq reinject
From: Alexander Graf @ 2012-02-26 11:59 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <4F481FE1.1080404@freescale.com>
On 25.02.2012, at 00:40, Scott Wood wrote:
> On 02/24/2012 08:26 AM, Alexander Graf wrote:
>> +static void kvmppc_fill_pt_regs(struct kvm_vcpu *vcpu, struct =
pt_regs *regs)
>> {
>> - int r =3D RESUME_HOST;
>> + int i;
>>=20
>> - /* update before a new last_exit_type is rewritten */
>> - kvmppc_update_timing_stats(vcpu);
>> + for (i =3D 0; i < 32; i++)
>> + regs->gpr[i] =3D kvmppc_get_gpr(vcpu, i);
>> + regs->nip =3D vcpu->arch.pc;
>> + regs->msr =3D vcpu->arch.shared->msr;
>> + regs->ctr =3D vcpu->arch.ctr;
>> + regs->link =3D vcpu->arch.lr;
>> + regs->xer =3D kvmppc_get_xer(vcpu);
>> + regs->ccr =3D kvmppc_get_cr(vcpu);
>> + regs->dar =3D get_guest_dear(vcpu);
>> + regs->dsisr =3D get_guest_esr(vcpu);
>> +}
>=20
> How much overhead does this add to every interrupt? Can't we keep =
this
> to the minimum that perf cares about?
I would rather not make assumptions on what perf cares about - maybe we =
want to one day implement "perf kvm" and then perf could rely on pretty =
much anything in there.
>=20
>> +
>> +static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu,
>> + unsigned int exit_nr)
>> +{
>> + struct pt_regs regs =3D *current->thread.regs;
>>=20
>> + kvmppc_fill_pt_regs(vcpu, ®s);
>=20
> Why are you copying out of current->thread.regs? That's old junk =
data,
> set by some previous exception and possibly overwritten since.
Because it gives us good default values for anything we don't set. Do =
you have other recommendations?
Alex
^ permalink raw reply
* Re: [PATCH] powerpc/prom: bump up maximum size of properties
From: Benjamin Herrenschmidt @ 2012-02-26 23:22 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: linuxppc-dev, Anton Blanchard, Paul Mackerras, Robert Jennings
In-Reply-To: <1330129422-2648-1-git-send-email-nacc@us.ibm.com>
On Fri, 2012-02-24 at 16:23 -0800, Nishanth Aravamudan wrote:
> On a 16TB system (using AMS/CMO), I get:
>
> WARNING: ignoring large property [/ibm,dynamic-reconfiguration-memory] ibm,dynamic-memory length 0x000000000017ffec
>
> and significantly less memory is thus shown to the partition. As far as
> I can tell, the constant used is arbitrary, but bump it up to 2MB, which
> covers the above property (approximately 1.5MB).
>
> With this patch, the kernel does see all of the system memory on the
> 16TB system.
Why not go all the way to either removing the limit, or setting it to
something much bigger ? That's just asking to break again when we get an
even bigger system.
The limit was originally set because of Apple machines carrying ROM
images in the device-tree, at a time where we were much more memory
constrained than we are now.
But even then, it never represented such a large gain and in the end,
was probably not -that- useful.
I'd say bump it to something really large like 16M or remove the limit
alltogether.
Cheers,
Ben.
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> Cc: Anton Blanchard <anton@au1.ibm.com>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Robert Jennings <rcj@linux.vnet.ibm.com>
> Cc: linuxppc-dev@lists.ozlabs.org
> ---
> arch/powerpc/kernel/prom_init.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index eca626e..0bf0ccc 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -53,7 +53,7 @@
> * ensure that we don't lose things like the interrupt-map property
> * on a PCI-PCI bridge.
> */
> -#define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024)
> +#define MAX_PROPERTY_LENGTH (2UL * 1024 * 1024)
>
> /*
> * Eventually bump that one up
^ permalink raw reply
* Re: [PATCH 1/2] powerpc: Move GE GPIO and PIC drivers
From: Benjamin Herrenschmidt @ 2012-02-26 23:37 UTC (permalink / raw)
To: Martyn Welch; +Cc: Wim Van Sebroeck, linuxppc-dev, linux-kernel
In-Reply-To: <1328614121-17803-2-git-send-email-martyn.welch@ge.com>
On Tue, 2012-02-07 at 11:28 +0000, Martyn Welch wrote:
> Move the GE GPIO and PIC drivers to allow these to be used by non-86xx
> boards.
Hi, Sorry for the late review...
> Signed-off-by: Martyn Welch <martyn.welch@ge.com>
> ---
> arch/powerpc/platforms/86xx/Kconfig | 3 +
> arch/powerpc/platforms/86xx/Makefile | 7 +-
> arch/powerpc/platforms/86xx/gef_gpio.c | 171 --------------------
> arch/powerpc/platforms/86xx/gef_pic.c | 252 ------------------------------
> arch/powerpc/platforms/86xx/gef_pic.h | 11 --
> arch/powerpc/platforms/86xx/gef_ppc9a.c | 3 +-
> arch/powerpc/platforms/86xx/gef_sbc310.c | 3 +-
> arch/powerpc/platforms/86xx/gef_sbc610.c | 3 +-
> arch/powerpc/platforms/Kconfig | 7 +
> arch/powerpc/platforms/Makefile | 3 +
> arch/powerpc/platforms/ge_gpio.c | 171 ++++++++++++++++++++
> arch/powerpc/platforms/ge_pic.c | 252 ++++++++++++++++++++++++++++++
> arch/powerpc/platforms/ge_pic.h | 11 ++
So I don't like having files showing up there. In fact, I want to move
the only other one here, it's not the right place for it
(fsl_uli1575.c).
Please contemplate using arch/powerpc/sysdev instead. Maybe make a
subdir in there (geip or something like that ?)
Also, use git mv so that the file moves appear as such in the history,
this will make review easier by clearly separating the move from actual
changes to the files.
Cheers,
Ben.
> drivers/watchdog/Kconfig | 2 +-
> 14 files changed, 457 insertions(+), 442 deletions(-)
> delete mode 100644 arch/powerpc/platforms/86xx/gef_gpio.c
> delete mode 100644 arch/powerpc/platforms/86xx/gef_pic.c
> delete mode 100644 arch/powerpc/platforms/86xx/gef_pic.h
> create mode 100644 arch/powerpc/platforms/ge_gpio.c
> create mode 100644 arch/powerpc/platforms/ge_pic.c
> create mode 100644 arch/powerpc/platforms/ge_pic.h
>
> diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
> index 8d6599d..2015022 100644
> --- a/arch/powerpc/platforms/86xx/Kconfig
> +++ b/arch/powerpc/platforms/86xx/Kconfig
> @@ -39,6 +39,7 @@ config GEF_PPC9A
> select MMIO_NVRAM
> select GENERIC_GPIO
> select ARCH_REQUIRE_GPIOLIB
> + select GE_FPGA
> help
> This option enables support for the GE PPC9A.
>
> @@ -48,6 +49,7 @@ config GEF_SBC310
> select MMIO_NVRAM
> select GENERIC_GPIO
> select ARCH_REQUIRE_GPIOLIB
> + select GE_FPGA
> help
> This option enables support for the GE SBC310.
>
> @@ -58,6 +60,7 @@ config GEF_SBC610
> select GENERIC_GPIO
> select ARCH_REQUIRE_GPIOLIB
> select HAS_RAPIDIO
> + select GE_FPGA
> help
> This option enables support for the GE SBC610.
>
> diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
> index 4b0d7b1..ede815d 100644
> --- a/arch/powerpc/platforms/86xx/Makefile
> +++ b/arch/powerpc/platforms/86xx/Makefile
> @@ -7,7 +7,6 @@ obj-$(CONFIG_SMP) += mpc86xx_smp.o
> obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o
> obj-$(CONFIG_SBC8641D) += sbc8641d.o
> obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o
> -gef-gpio-$(CONFIG_GPIOLIB) += gef_gpio.o
> -obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o gef_pic.o $(gef-gpio-y)
> -obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o gef_pic.o $(gef-gpio-y)
> -obj-$(CONFIG_GEF_PPC9A) += gef_ppc9a.o gef_pic.o $(gef-gpio-y)
> +obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o
> +obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o
> +obj-$(CONFIG_GEF_PPC9A) += gef_ppc9a.o
> diff --git a/arch/powerpc/platforms/86xx/gef_gpio.c b/arch/powerpc/platforms/86xx/gef_gpio.c
> deleted file mode 100644
> index 2a70336..0000000
> --- a/arch/powerpc/platforms/86xx/gef_gpio.c
> +++ /dev/null
> @@ -1,171 +0,0 @@
> -/*
> - * Driver for GE FPGA based GPIO
> - *
> - * Author: Martyn Welch <martyn.welch@ge.com>
> - *
> - * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
> - *
> - * This file is licensed under the terms of the GNU General Public License
> - * version 2. This program is licensed "as is" without any warranty of any
> - * kind, whether express or implied.
> - */
> -
> -/* TODO
> - *
> - * Configuration of output modes (totem-pole/open-drain)
> - * Interrupt configuration - interrupts are always generated the FPGA relies on
> - * the I/O interrupt controllers mask to stop them propergating
> - */
> -
> -#include <linux/kernel.h>
> -#include <linux/compiler.h>
> -#include <linux/init.h>
> -#include <linux/io.h>
> -#include <linux/of.h>
> -#include <linux/of_device.h>
> -#include <linux/of_platform.h>
> -#include <linux/of_gpio.h>
> -#include <linux/gpio.h>
> -#include <linux/slab.h>
> -#include <linux/module.h>
> -
> -#define GEF_GPIO_DIRECT 0x00
> -#define GEF_GPIO_IN 0x04
> -#define GEF_GPIO_OUT 0x08
> -#define GEF_GPIO_TRIG 0x0C
> -#define GEF_GPIO_POLAR_A 0x10
> -#define GEF_GPIO_POLAR_B 0x14
> -#define GEF_GPIO_INT_STAT 0x18
> -#define GEF_GPIO_OVERRUN 0x1C
> -#define GEF_GPIO_MODE 0x20
> -
> -static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
> -{
> - unsigned int data;
> -
> - data = ioread32be(reg);
> - /* value: 0=low; 1=high */
> - if (value & 0x1)
> - data = data | (0x1 << offset);
> - else
> - data = data & ~(0x1 << offset);
> -
> - iowrite32be(data, reg);
> -}
> -
> -
> -static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
> -{
> - unsigned int data;
> - struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
> -
> - data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
> - data = data | (0x1 << offset);
> - iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
> -
> - return 0;
> -}
> -
> -static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
> -{
> - unsigned int data;
> - struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
> -
> - /* Set direction before switching to input */
> - _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
> -
> - data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
> - data = data & ~(0x1 << offset);
> - iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
> -
> - return 0;
> -}
> -
> -static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
> -{
> - unsigned int data;
> - int state = 0;
> - struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
> -
> - data = ioread32be(mmchip->regs + GEF_GPIO_IN);
> - state = (int)((data >> offset) & 0x1);
> -
> - return state;
> -}
> -
> -static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
> -{
> - struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
> -
> - _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
> -}
> -
> -static int __init gef_gpio_init(void)
> -{
> - struct device_node *np;
> - int retval;
> - struct of_mm_gpio_chip *gef_gpio_chip;
> -
> - for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
> -
> - pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
> -
> - /* Allocate chip structure */
> - gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
> - if (!gef_gpio_chip) {
> - pr_err("%s: Unable to allocate structure\n",
> - np->full_name);
> - continue;
> - }
> -
> - /* Setup pointers to chip functions */
> - gef_gpio_chip->gc.of_gpio_n_cells = 2;
> - gef_gpio_chip->gc.ngpio = 19;
> - gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
> - gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
> - gef_gpio_chip->gc.get = gef_gpio_get;
> - gef_gpio_chip->gc.set = gef_gpio_set;
> -
> - /* This function adds a memory mapped GPIO chip */
> - retval = of_mm_gpiochip_add(np, gef_gpio_chip);
> - if (retval) {
> - kfree(gef_gpio_chip);
> - pr_err("%s: Unable to add GPIO\n", np->full_name);
> - }
> - }
> -
> - for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
> -
> - pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
> -
> - /* Allocate chip structure */
> - gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
> - if (!gef_gpio_chip) {
> - pr_err("%s: Unable to allocate structure\n",
> - np->full_name);
> - continue;
> - }
> -
> - /* Setup pointers to chip functions */
> - gef_gpio_chip->gc.of_gpio_n_cells = 2;
> - gef_gpio_chip->gc.ngpio = 6;
> - gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
> - gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
> - gef_gpio_chip->gc.get = gef_gpio_get;
> - gef_gpio_chip->gc.set = gef_gpio_set;
> -
> - /* This function adds a memory mapped GPIO chip */
> - retval = of_mm_gpiochip_add(np, gef_gpio_chip);
> - if (retval) {
> - kfree(gef_gpio_chip);
> - pr_err("%s: Unable to add GPIO\n", np->full_name);
> - }
> - }
> -
> - return 0;
> -};
> -arch_initcall(gef_gpio_init);
> -
> -MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
> -MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
> -MODULE_LICENSE("GPL");
> diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c
> deleted file mode 100644
> index 94594e5..0000000
> --- a/arch/powerpc/platforms/86xx/gef_pic.c
> +++ /dev/null
> @@ -1,252 +0,0 @@
> -/*
> - * Interrupt handling for GE FPGA based PIC
> - *
> - * Author: Martyn Welch <martyn.welch@ge.com>
> - *
> - * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
> - *
> - * This file is licensed under the terms of the GNU General Public License
> - * version 2. This program is licensed "as is" without any warranty of any
> - * kind, whether express or implied.
> - */
> -
> -#include <linux/stddef.h>
> -#include <linux/kernel.h>
> -#include <linux/init.h>
> -#include <linux/irq.h>
> -#include <linux/interrupt.h>
> -#include <linux/spinlock.h>
> -
> -#include <asm/byteorder.h>
> -#include <asm/io.h>
> -#include <asm/prom.h>
> -#include <asm/irq.h>
> -
> -#include "gef_pic.h"
> -
> -#define DEBUG
> -#undef DEBUG
> -
> -#ifdef DEBUG
> -#define DBG(fmt...) do { printk(KERN_DEBUG "gef_pic: " fmt); } while (0)
> -#else
> -#define DBG(fmt...) do { } while (0)
> -#endif
> -
> -#define GEF_PIC_NUM_IRQS 32
> -
> -/* Interrupt Controller Interface Registers */
> -#define GEF_PIC_INTR_STATUS 0x0000
> -
> -#define GEF_PIC_INTR_MASK(cpu) (0x0010 + (0x4 * cpu))
> -#define GEF_PIC_CPU0_INTR_MASK GEF_PIC_INTR_MASK(0)
> -#define GEF_PIC_CPU1_INTR_MASK GEF_PIC_INTR_MASK(1)
> -
> -#define GEF_PIC_MCP_MASK(cpu) (0x0018 + (0x4 * cpu))
> -#define GEF_PIC_CPU0_MCP_MASK GEF_PIC_MCP_MASK(0)
> -#define GEF_PIC_CPU1_MCP_MASK GEF_PIC_MCP_MASK(1)
> -
> -
> -static DEFINE_RAW_SPINLOCK(gef_pic_lock);
> -
> -static void __iomem *gef_pic_irq_reg_base;
> -static struct irq_host *gef_pic_irq_host;
> -static int gef_pic_cascade_irq;
> -
> -/*
> - * Interrupt Controller Handling
> - *
> - * The interrupt controller handles interrupts for most on board interrupts,
> - * apart from PCI interrupts. For example on SBC610:
> - *
> - * 17:31 RO Reserved
> - * 16 RO PCI Express Doorbell 3 Status
> - * 15 RO PCI Express Doorbell 2 Status
> - * 14 RO PCI Express Doorbell 1 Status
> - * 13 RO PCI Express Doorbell 0 Status
> - * 12 RO Real Time Clock Interrupt Status
> - * 11 RO Temperature Interrupt Status
> - * 10 RO Temperature Critical Interrupt Status
> - * 9 RO Ethernet PHY1 Interrupt Status
> - * 8 RO Ethernet PHY3 Interrupt Status
> - * 7 RO PEX8548 Interrupt Status
> - * 6 RO Reserved
> - * 5 RO Watchdog 0 Interrupt Status
> - * 4 RO Watchdog 1 Interrupt Status
> - * 3 RO AXIS Message FIFO A Interrupt Status
> - * 2 RO AXIS Message FIFO B Interrupt Status
> - * 1 RO AXIS Message FIFO C Interrupt Status
> - * 0 RO AXIS Message FIFO D Interrupt Status
> - *
> - * Interrupts can be forwarded to one of two output lines. Nothing
> - * clever is done, so if the masks are incorrectly set, a single input
> - * interrupt could generate interrupts on both output lines!
> - *
> - * The dual lines are there to allow the chained interrupts to be easily
> - * passed into two different cores. We currently do not use this functionality
> - * in this driver.
> - *
> - * Controller can also be configured to generate Machine checks (MCP), again on
> - * two lines, to be attached to two different cores. It is suggested that these
> - * should be masked out.
> - */
> -
> -void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
> -{
> - struct irq_chip *chip = irq_desc_get_chip(desc);
> - unsigned int cascade_irq;
> -
> - /*
> - * See if we actually have an interrupt, call generic handling code if
> - * we do.
> - */
> - cascade_irq = gef_pic_get_irq();
> -
> - if (cascade_irq != NO_IRQ)
> - generic_handle_irq(cascade_irq);
> -
> - chip->irq_eoi(&desc->irq_data);
> -}
> -
> -static void gef_pic_mask(struct irq_data *d)
> -{
> - unsigned long flags;
> - unsigned int hwirq = irqd_to_hwirq(d);
> - u32 mask;
> -
> - raw_spin_lock_irqsave(&gef_pic_lock, flags);
> - mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
> - mask &= ~(1 << hwirq);
> - out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
> - raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
> -}
> -
> -static void gef_pic_mask_ack(struct irq_data *d)
> -{
> - /* Don't think we actually have to do anything to ack an interrupt,
> - * we just need to clear down the devices interrupt and it will go away
> - */
> - gef_pic_mask(d);
> -}
> -
> -static void gef_pic_unmask(struct irq_data *d)
> -{
> - unsigned long flags;
> - unsigned int hwirq = irqd_to_hwirq(d);
> - u32 mask;
> -
> - raw_spin_lock_irqsave(&gef_pic_lock, flags);
> - mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
> - mask |= (1 << hwirq);
> - out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
> - raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
> -}
> -
> -static struct irq_chip gef_pic_chip = {
> - .name = "gefp",
> - .irq_mask = gef_pic_mask,
> - .irq_mask_ack = gef_pic_mask_ack,
> - .irq_unmask = gef_pic_unmask,
> -};
> -
> -
> -/* When an interrupt is being configured, this call allows some flexibilty
> - * in deciding which irq_chip structure is used
> - */
> -static int gef_pic_host_map(struct irq_host *h, unsigned int virq,
> - irq_hw_number_t hwirq)
> -{
> - /* All interrupts are LEVEL sensitive */
> - irq_set_status_flags(virq, IRQ_LEVEL);
> - irq_set_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
> -
> - return 0;
> -}
> -
> -static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct,
> - const u32 *intspec, unsigned int intsize,
> - irq_hw_number_t *out_hwirq, unsigned int *out_flags)
> -{
> -
> - *out_hwirq = intspec[0];
> - if (intsize > 1)
> - *out_flags = intspec[1];
> - else
> - *out_flags = IRQ_TYPE_LEVEL_HIGH;
> -
> - return 0;
> -}
> -
> -static struct irq_host_ops gef_pic_host_ops = {
> - .map = gef_pic_host_map,
> - .xlate = gef_pic_host_xlate,
> -};
> -
> -
> -/*
> - * Initialisation of PIC, this should be called in BSP
> - */
> -void __init gef_pic_init(struct device_node *np)
> -{
> - unsigned long flags;
> -
> - /* Map the devices registers into memory */
> - gef_pic_irq_reg_base = of_iomap(np, 0);
> -
> - raw_spin_lock_irqsave(&gef_pic_lock, flags);
> -
> - /* Initialise everything as masked. */
> - out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_INTR_MASK, 0);
> - out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_INTR_MASK, 0);
> -
> - out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_MCP_MASK, 0);
> - out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_MCP_MASK, 0);
> -
> - raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
> -
> - /* Map controller */
> - gef_pic_cascade_irq = irq_of_parse_and_map(np, 0);
> - if (gef_pic_cascade_irq == NO_IRQ) {
> - printk(KERN_ERR "SBC610: failed to map cascade interrupt");
> - return;
> - }
> -
> - /* Setup an irq_host structure */
> - gef_pic_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
> - GEF_PIC_NUM_IRQS,
> - &gef_pic_host_ops, NO_IRQ);
> - if (gef_pic_irq_host == NULL)
> - return;
> -
> - /* Chain with parent controller */
> - irq_set_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
> -}
> -
> -/*
> - * This is called when we receive an interrupt with apparently comes from this
> - * chip - check, returning the highest interrupt generated or return NO_IRQ
> - */
> -unsigned int gef_pic_get_irq(void)
> -{
> - u32 cause, mask, active;
> - unsigned int virq = NO_IRQ;
> - int hwirq;
> -
> - cause = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_STATUS);
> -
> - mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
> -
> - active = cause & mask;
> -
> - if (active) {
> - for (hwirq = GEF_PIC_NUM_IRQS - 1; hwirq > -1; hwirq--) {
> - if (active & (0x1 << hwirq))
> - break;
> - }
> - virq = irq_linear_revmap(gef_pic_irq_host,
> - (irq_hw_number_t)hwirq);
> - }
> -
> - return virq;
> -}
> -
> diff --git a/arch/powerpc/platforms/86xx/gef_pic.h b/arch/powerpc/platforms/86xx/gef_pic.h
> deleted file mode 100644
> index 6149916..0000000
> --- a/arch/powerpc/platforms/86xx/gef_pic.h
> +++ /dev/null
> @@ -1,11 +0,0 @@
> -#ifndef __GEF_PIC_H__
> -#define __GEF_PIC_H__
> -
> -#include <linux/init.h>
> -
> -void gef_pic_cascade(unsigned int, struct irq_desc *);
> -unsigned int gef_pic_get_irq(void);
> -void gef_pic_init(struct device_node *);
> -
> -#endif /* __GEF_PIC_H__ */
> -
> diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
> index 60ce07e..132917d 100644
> --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c
> +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
> @@ -38,8 +38,9 @@
> #include <sysdev/fsl_pci.h>
> #include <sysdev/fsl_soc.h>
>
> +#include <platforms/ge_pic.h>
> +
> #include "mpc86xx.h"
> -#include "gef_pic.h"
>
> #undef DEBUG
>
> diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
> index 3ecee25..3d7894d 100644
> --- a/arch/powerpc/platforms/86xx/gef_sbc310.c
> +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
> @@ -38,8 +38,9 @@
> #include <sysdev/fsl_pci.h>
> #include <sysdev/fsl_soc.h>
>
> +#include <platforms/ge_pic.h>
> +
> #include "mpc86xx.h"
> -#include "gef_pic.h"
>
> #undef DEBUG
>
> diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
> index 5090d60..4f6b6a4 100644
> --- a/arch/powerpc/platforms/86xx/gef_sbc610.c
> +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
> @@ -38,8 +38,9 @@
> #include <sysdev/fsl_pci.h>
> #include <sysdev/fsl_soc.h>
>
> +#include <platforms/ge_pic.h>
> +
> #include "mpc86xx.h"
> -#include "gef_pic.h"
>
> #undef DEBUG
>
> diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
> index 0cfb46d..2578e82 100644
> --- a/arch/powerpc/platforms/Kconfig
> +++ b/arch/powerpc/platforms/Kconfig
> @@ -363,4 +363,11 @@ config XILINX_PCI
> bool "Xilinx PCI host bridge support"
> depends on PCI && XILINX_VIRTEX
>
> +config GE_FPGA
> + bool
> + default n
> + help
> + Support for common GPIO and interrupt routing functionality provided
> + on some GE Single Board Computers.
> +
> endmenu
> diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
> index 2635a22..38742cf 100644
> --- a/arch/powerpc/platforms/Makefile
> +++ b/arch/powerpc/platforms/Makefile
> @@ -3,6 +3,9 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
>
> obj-$(CONFIG_FSL_ULI1575) += fsl_uli1575.o
>
> +gef-gpio-$(CONFIG_GPIOLIB) += ge_gpio.o
> +obj-$(CONFIG_GE_FPGA) += ge_pic.o $(gef-gpio-y)
> +
> obj-$(CONFIG_PPC_PMAC) += powermac/
> obj-$(CONFIG_PPC_CHRP) += chrp/
> obj-$(CONFIG_40x) += 40x/
> diff --git a/arch/powerpc/platforms/ge_gpio.c b/arch/powerpc/platforms/ge_gpio.c
> new file mode 100644
> index 0000000..2a70336
> --- /dev/null
> +++ b/arch/powerpc/platforms/ge_gpio.c
> @@ -0,0 +1,171 @@
> +/*
> + * Driver for GE FPGA based GPIO
> + *
> + * Author: Martyn Welch <martyn.welch@ge.com>
> + *
> + * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +/* TODO
> + *
> + * Configuration of output modes (totem-pole/open-drain)
> + * Interrupt configuration - interrupts are always generated the FPGA relies on
> + * the I/O interrupt controllers mask to stop them propergating
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/compiler.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_gpio.h>
> +#include <linux/gpio.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +
> +#define GEF_GPIO_DIRECT 0x00
> +#define GEF_GPIO_IN 0x04
> +#define GEF_GPIO_OUT 0x08
> +#define GEF_GPIO_TRIG 0x0C
> +#define GEF_GPIO_POLAR_A 0x10
> +#define GEF_GPIO_POLAR_B 0x14
> +#define GEF_GPIO_INT_STAT 0x18
> +#define GEF_GPIO_OVERRUN 0x1C
> +#define GEF_GPIO_MODE 0x20
> +
> +static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
> +{
> + unsigned int data;
> +
> + data = ioread32be(reg);
> + /* value: 0=low; 1=high */
> + if (value & 0x1)
> + data = data | (0x1 << offset);
> + else
> + data = data & ~(0x1 << offset);
> +
> + iowrite32be(data, reg);
> +}
> +
> +
> +static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
> +{
> + unsigned int data;
> + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
> +
> + data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
> + data = data | (0x1 << offset);
> + iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
> +
> + return 0;
> +}
> +
> +static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
> +{
> + unsigned int data;
> + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
> +
> + /* Set direction before switching to input */
> + _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
> +
> + data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
> + data = data & ~(0x1 << offset);
> + iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
> +
> + return 0;
> +}
> +
> +static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
> +{
> + unsigned int data;
> + int state = 0;
> + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
> +
> + data = ioread32be(mmchip->regs + GEF_GPIO_IN);
> + state = (int)((data >> offset) & 0x1);
> +
> + return state;
> +}
> +
> +static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
> +{
> + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
> +
> + _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
> +}
> +
> +static int __init gef_gpio_init(void)
> +{
> + struct device_node *np;
> + int retval;
> + struct of_mm_gpio_chip *gef_gpio_chip;
> +
> + for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
> +
> + pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
> +
> + /* Allocate chip structure */
> + gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
> + if (!gef_gpio_chip) {
> + pr_err("%s: Unable to allocate structure\n",
> + np->full_name);
> + continue;
> + }
> +
> + /* Setup pointers to chip functions */
> + gef_gpio_chip->gc.of_gpio_n_cells = 2;
> + gef_gpio_chip->gc.ngpio = 19;
> + gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
> + gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
> + gef_gpio_chip->gc.get = gef_gpio_get;
> + gef_gpio_chip->gc.set = gef_gpio_set;
> +
> + /* This function adds a memory mapped GPIO chip */
> + retval = of_mm_gpiochip_add(np, gef_gpio_chip);
> + if (retval) {
> + kfree(gef_gpio_chip);
> + pr_err("%s: Unable to add GPIO\n", np->full_name);
> + }
> + }
> +
> + for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
> +
> + pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
> +
> + /* Allocate chip structure */
> + gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
> + if (!gef_gpio_chip) {
> + pr_err("%s: Unable to allocate structure\n",
> + np->full_name);
> + continue;
> + }
> +
> + /* Setup pointers to chip functions */
> + gef_gpio_chip->gc.of_gpio_n_cells = 2;
> + gef_gpio_chip->gc.ngpio = 6;
> + gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
> + gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
> + gef_gpio_chip->gc.get = gef_gpio_get;
> + gef_gpio_chip->gc.set = gef_gpio_set;
> +
> + /* This function adds a memory mapped GPIO chip */
> + retval = of_mm_gpiochip_add(np, gef_gpio_chip);
> + if (retval) {
> + kfree(gef_gpio_chip);
> + pr_err("%s: Unable to add GPIO\n", np->full_name);
> + }
> + }
> +
> + return 0;
> +};
> +arch_initcall(gef_gpio_init);
> +
> +MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
> +MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
> +MODULE_LICENSE("GPL");
> diff --git a/arch/powerpc/platforms/ge_pic.c b/arch/powerpc/platforms/ge_pic.c
> new file mode 100644
> index 0000000..a1ccef2
> --- /dev/null
> +++ b/arch/powerpc/platforms/ge_pic.c
> @@ -0,0 +1,252 @@
> +/*
> + * Interrupt handling for GE FPGA based PIC
> + *
> + * Author: Martyn Welch <martyn.welch@ge.com>
> + *
> + * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <linux/stddef.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/spinlock.h>
> +
> +#include <asm/byteorder.h>
> +#include <asm/io.h>
> +#include <asm/prom.h>
> +#include <asm/irq.h>
> +
> +#include <platforms/ge_pic.h>
> +
> +#define DEBUG
> +#undef DEBUG
> +
> +#ifdef DEBUG
> +#define DBG(fmt...) do { printk(KERN_DEBUG "gef_pic: " fmt); } while (0)
> +#else
> +#define DBG(fmt...) do { } while (0)
> +#endif
> +
> +#define GEF_PIC_NUM_IRQS 32
> +
> +/* Interrupt Controller Interface Registers */
> +#define GEF_PIC_INTR_STATUS 0x0000
> +
> +#define GEF_PIC_INTR_MASK(cpu) (0x0010 + (0x4 * cpu))
> +#define GEF_PIC_CPU0_INTR_MASK GEF_PIC_INTR_MASK(0)
> +#define GEF_PIC_CPU1_INTR_MASK GEF_PIC_INTR_MASK(1)
> +
> +#define GEF_PIC_MCP_MASK(cpu) (0x0018 + (0x4 * cpu))
> +#define GEF_PIC_CPU0_MCP_MASK GEF_PIC_MCP_MASK(0)
> +#define GEF_PIC_CPU1_MCP_MASK GEF_PIC_MCP_MASK(1)
> +
> +
> +static DEFINE_RAW_SPINLOCK(gef_pic_lock);
> +
> +static void __iomem *gef_pic_irq_reg_base;
> +static struct irq_host *gef_pic_irq_host;
> +static int gef_pic_cascade_irq;
> +
> +/*
> + * Interrupt Controller Handling
> + *
> + * The interrupt controller handles interrupts for most on board interrupts,
> + * apart from PCI interrupts. For example on SBC610:
> + *
> + * 17:31 RO Reserved
> + * 16 RO PCI Express Doorbell 3 Status
> + * 15 RO PCI Express Doorbell 2 Status
> + * 14 RO PCI Express Doorbell 1 Status
> + * 13 RO PCI Express Doorbell 0 Status
> + * 12 RO Real Time Clock Interrupt Status
> + * 11 RO Temperature Interrupt Status
> + * 10 RO Temperature Critical Interrupt Status
> + * 9 RO Ethernet PHY1 Interrupt Status
> + * 8 RO Ethernet PHY3 Interrupt Status
> + * 7 RO PEX8548 Interrupt Status
> + * 6 RO Reserved
> + * 5 RO Watchdog 0 Interrupt Status
> + * 4 RO Watchdog 1 Interrupt Status
> + * 3 RO AXIS Message FIFO A Interrupt Status
> + * 2 RO AXIS Message FIFO B Interrupt Status
> + * 1 RO AXIS Message FIFO C Interrupt Status
> + * 0 RO AXIS Message FIFO D Interrupt Status
> + *
> + * Interrupts can be forwarded to one of two output lines. Nothing
> + * clever is done, so if the masks are incorrectly set, a single input
> + * interrupt could generate interrupts on both output lines!
> + *
> + * The dual lines are there to allow the chained interrupts to be easily
> + * passed into two different cores. We currently do not use this functionality
> + * in this driver.
> + *
> + * Controller can also be configured to generate Machine checks (MCP), again on
> + * two lines, to be attached to two different cores. It is suggested that these
> + * should be masked out.
> + */
> +
> +void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
> +{
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + unsigned int cascade_irq;
> +
> + /*
> + * See if we actually have an interrupt, call generic handling code if
> + * we do.
> + */
> + cascade_irq = gef_pic_get_irq();
> +
> + if (cascade_irq != NO_IRQ)
> + generic_handle_irq(cascade_irq);
> +
> + chip->irq_eoi(&desc->irq_data);
> +}
> +
> +static void gef_pic_mask(struct irq_data *d)
> +{
> + unsigned long flags;
> + unsigned int hwirq = irqd_to_hwirq(d);
> + u32 mask;
> +
> + raw_spin_lock_irqsave(&gef_pic_lock, flags);
> + mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
> + mask &= ~(1 << hwirq);
> + out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
> + raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
> +}
> +
> +static void gef_pic_mask_ack(struct irq_data *d)
> +{
> + /* Don't think we actually have to do anything to ack an interrupt,
> + * we just need to clear down the devices interrupt and it will go away
> + */
> + gef_pic_mask(d);
> +}
> +
> +static void gef_pic_unmask(struct irq_data *d)
> +{
> + unsigned long flags;
> + unsigned int hwirq = irqd_to_hwirq(d);
> + u32 mask;
> +
> + raw_spin_lock_irqsave(&gef_pic_lock, flags);
> + mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
> + mask |= (1 << hwirq);
> + out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
> + raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
> +}
> +
> +static struct irq_chip gef_pic_chip = {
> + .name = "gefp",
> + .irq_mask = gef_pic_mask,
> + .irq_mask_ack = gef_pic_mask_ack,
> + .irq_unmask = gef_pic_unmask,
> +};
> +
> +
> +/* When an interrupt is being configured, this call allows some flexibilty
> + * in deciding which irq_chip structure is used
> + */
> +static int gef_pic_host_map(struct irq_host *h, unsigned int virq,
> + irq_hw_number_t hwirq)
> +{
> + /* All interrupts are LEVEL sensitive */
> + irq_set_status_flags(virq, IRQ_LEVEL);
> + irq_set_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
> +
> + return 0;
> +}
> +
> +static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct,
> + const u32 *intspec, unsigned int intsize,
> + irq_hw_number_t *out_hwirq, unsigned int *out_flags)
> +{
> +
> + *out_hwirq = intspec[0];
> + if (intsize > 1)
> + *out_flags = intspec[1];
> + else
> + *out_flags = IRQ_TYPE_LEVEL_HIGH;
> +
> + return 0;
> +}
> +
> +static struct irq_host_ops gef_pic_host_ops = {
> + .map = gef_pic_host_map,
> + .xlate = gef_pic_host_xlate,
> +};
> +
> +
> +/*
> + * Initialisation of PIC, this should be called in BSP
> + */
> +void __init gef_pic_init(struct device_node *np)
> +{
> + unsigned long flags;
> +
> + /* Map the devices registers into memory */
> + gef_pic_irq_reg_base = of_iomap(np, 0);
> +
> + raw_spin_lock_irqsave(&gef_pic_lock, flags);
> +
> + /* Initialise everything as masked. */
> + out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_INTR_MASK, 0);
> + out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_INTR_MASK, 0);
> +
> + out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_MCP_MASK, 0);
> + out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_MCP_MASK, 0);
> +
> + raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
> +
> + /* Map controller */
> + gef_pic_cascade_irq = irq_of_parse_and_map(np, 0);
> + if (gef_pic_cascade_irq == NO_IRQ) {
> + printk(KERN_ERR "SBC610: failed to map cascade interrupt");
> + return;
> + }
> +
> + /* Setup an irq_host structure */
> + gef_pic_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
> + GEF_PIC_NUM_IRQS,
> + &gef_pic_host_ops, NO_IRQ);
> + if (gef_pic_irq_host == NULL)
> + return;
> +
> + /* Chain with parent controller */
> + irq_set_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
> +}
> +
> +/*
> + * This is called when we receive an interrupt with apparently comes from this
> + * chip - check, returning the highest interrupt generated or return NO_IRQ
> + */
> +unsigned int gef_pic_get_irq(void)
> +{
> + u32 cause, mask, active;
> + unsigned int virq = NO_IRQ;
> + int hwirq;
> +
> + cause = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_STATUS);
> +
> + mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
> +
> + active = cause & mask;
> +
> + if (active) {
> + for (hwirq = GEF_PIC_NUM_IRQS - 1; hwirq > -1; hwirq--) {
> + if (active & (0x1 << hwirq))
> + break;
> + }
> + virq = irq_linear_revmap(gef_pic_irq_host,
> + (irq_hw_number_t)hwirq);
> + }
> +
> + return virq;
> +}
> +
> diff --git a/arch/powerpc/platforms/ge_pic.h b/arch/powerpc/platforms/ge_pic.h
> new file mode 100644
> index 0000000..6149916
> --- /dev/null
> +++ b/arch/powerpc/platforms/ge_pic.h
> @@ -0,0 +1,11 @@
> +#ifndef __GEF_PIC_H__
> +#define __GEF_PIC_H__
> +
> +#include <linux/init.h>
> +
> +void gef_pic_cascade(unsigned int, struct irq_desc *);
> +unsigned int gef_pic_get_irq(void);
> +void gef_pic_init(struct device_node *);
> +
> +#endif /* __GEF_PIC_H__ */
> +
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 877b107..2955c3f 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -1039,7 +1039,7 @@ config LANTIQ_WDT
>
> config GEF_WDT
> tristate "GE Watchdog Timer"
> - depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A
> + depends on GE_FPGA
> ---help---
> Watchdog timer found in a number of GE single board computers.
>
^ permalink raw reply
* Re: [PATCH 2/2] powerpc: Board support for GE IMP3A
From: Benjamin Herrenschmidt @ 2012-02-26 23:42 UTC (permalink / raw)
To: Martyn Welch; +Cc: Wim Van Sebroeck, linuxppc-dev, linux-kernel
In-Reply-To: <1328614121-17803-3-git-send-email-martyn.welch@ge.com>
On Tue, 2012-02-07 at 11:28 +0000, Martyn Welch wrote:
> +
> + if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
> + mpic = mpic_alloc(NULL, 0,
> + MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
> + MPIC_SINGLE_DEST_CPU,
> + 0, 256, " OpenPIC ");
> + } else {
> + mpic = mpic_alloc(NULL, 0,
> + MPIC_WANTS_RESET |
> + MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
> + MPIC_SINGLE_DEST_CPU,
> + 0, 256, " OpenPIC ");
> + }
> +
Can you rebase this on top of powerpc-next ? There have been some mpic
changes from Kyle Moffett that clash with this (mostly some of the flags
are gone, the remaining ones you should just put in the device-tree).
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] powerpc: icswx: fix race condition where threads do not get their ACOP register updated in time.
From: Benjamin Herrenschmidt @ 2012-02-26 23:47 UTC (permalink / raw)
To: Jimi Xenidis; +Cc: linuxppc-dev, Anton Blanchard
In-Reply-To: <1329948466-325-1-git-send-email-jimix@pobox.com>
>
> + /*
> + * We could be here because another thread has enabled acop
> + * but the ACOP register has yet to be updated.
> + *
> + * This should have been taken care of by the IPI to sync all
> + * the threads (see smp_call_function(sync_cop, mm, 1)), but
> + * that could take forever if there are a significant amount
> + * of threads.
> + *
> + * Given the number of threads on some of these systems,
> + * perhaps this is the best way to sync ACOP rather than whack
> + * every thread with an IPI.
> + */
This is actually pretty standard stuff... If it was me I would make it
all lazy and avoid the IPI completely but it doesn't necessarily hurt
that much. In any case the "recovery" is indeed needed and you should
probably also remove the pr_debug, it's really just spam.
> + if (acop_copro_type_bit(ct) && current->active_mm->context.acop) {
Shouldn't that be "&" ? In fact, gcc would even warn so either make
it acop_check_copro(acop, ct) or do a (x & y) != 0
Cheers,
Ben.
> + pr_debug("%s[%d]: Spurrious ACOP Fault, CT: %d, bit: 0x%llx "
> + "SPR: 0x%lx, mm->acop: 0x%lx\n",
> + current->comm, current->pid,
> + ct, acop_copro_type_bit(ct), mfspr(SPRN_ACOP),
> + current->active_mm->context.acop);
> +
> + sync_cop(current->active_mm);
> + return 0;
> + }
> +
> + /* check for alternate policy */
> if (!acop_use_cop(ct))
> return 0;
>
> /* at this point the CT is unknown to the system */
> - pr_warn("%s[%d]: Coprocessor %d is unavailable",
> + pr_warn("%s[%d]: Coprocessor %d is unavailable\n",
> current->comm, current->pid, ct);
>
> /* get inst if we don't already have it */
> diff --git a/arch/powerpc/mm/icswx.h b/arch/powerpc/mm/icswx.h
> index 42176bd..6dedc08 100644
> --- a/arch/powerpc/mm/icswx.h
> +++ b/arch/powerpc/mm/icswx.h
> @@ -59,4 +59,10 @@ extern void free_cop_pid(int free_pid);
>
> extern int acop_handle_fault(struct pt_regs *regs, unsigned long address,
> unsigned long error_code);
> +
> +static inline u64 acop_copro_type_bit(unsigned int type)
> +{
> + return 1ULL << (63 - type);
> +}
> +
> #endif /* !_ARCH_POWERPC_MM_ICSWX_H_ */
^ permalink raw reply
* Re: [PATCH/RFC] rapidio: temporarily exclude FSL_RIO from 64 bit builds
From: Paul Gortmaker @ 2012-02-27 1:26 UTC (permalink / raw)
To: benh; +Cc: Gang.Liu, linux-next, linuxppc-dev
In-Reply-To: <1329865853-17277-1-git-send-email-paul.gortmaker@windriver.com>
Hi Ben,
Given a week has passed with the absence of any feedback
with respect to SRIO on 64 bit, are you OK with applying the
below patch[1] pretty much as-is?
Thanks,
Paul.
[1] http://patchwork.ozlabs.org/patch/142383/
---
On Tue, Feb 21, 2012 at 6:10 PM, Paul Gortmaker
<paul.gortmaker@windriver.com> wrote:
> The following are seen while using the corenet64_smp_defconfig:
>
> arch/powerpc/sysdev/fsl_rmu.c:315: error: cast from pointer to integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:320: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:320: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:320: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:330: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:332: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:339: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:340: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:341: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:348: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:348: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:348: error: cast to pointer from integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:659: error: cast from pointer to integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:659: error: format '%8.8x' expects type 'un=
signed int', but argument 5 has type 'size_t'
> arch/powerpc/sysdev/fsl_rmu.c:985: error: cast from pointer to integer of=
different size
> arch/powerpc/sysdev/fsl_rmu.c:997: error: cast to pointer from integer of=
different size
>
> A quick inspection of the code leaves one with the impression
> that it was not explicitly written with 64 bit support in mind,
> so just block that as a possible config selection for now.
>
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
>
> ---
>
> [This is seen in linux-next -- not sure if this is the right way to go
> =A0but at least it will give the issue some visibility to the right ppl.]
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 75f061e..5ad8013 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -773,7 +773,7 @@ config RAPIDIO
>
> =A0config FSL_RIO
> =A0 =A0 =A0 =A0bool "Freescale Embedded SRIO Controller support"
> - =A0 =A0 =A0 depends on RAPIDIO && HAS_RAPIDIO
> + =A0 =A0 =A0 depends on RAPIDIO && HAS_RAPIDIO && (BROKEN || !PPC64)
> =A0 =A0 =A0 =A0default "n"
> =A0 =A0 =A0 =A0---help---
> =A0 =A0 =A0 =A0 =A0Include support for RapidIO controller on Freescale em=
bedded
> --
> 1.7.9.1
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH/RFC] rapidio: temporarily exclude FSL_RIO from 64 bit builds
From: Benjamin Herrenschmidt @ 2012-02-27 1:49 UTC (permalink / raw)
To: Paul Gortmaker; +Cc: Gang.Liu, linux-next, linuxppc-dev
In-Reply-To: <CAP=VYLroaEKncpy7VBobJdXijnDS5UdTV7qPG2A--SicnGvFSg@mail.gmail.com>
On Sun, 2012-02-26 at 20:26 -0500, Paul Gortmaker wrote:
> Hi Ben,
>
> Given a week has passed with the absence of any feedback
> with respect to SRIO on 64 bit, are you OK with applying the
> below patch[1] pretty much as-is?
It can't hurt, I'll put it in. That's normally Kumar's side of things
but then with him leaving FSL things are a bit in flux right now.
Cheers,
Ben.
> Thanks,
> Paul.
>
> [1] http://patchwork.ozlabs.org/patch/142383/
>
> ---
>
> On Tue, Feb 21, 2012 at 6:10 PM, Paul Gortmaker
> <paul.gortmaker@windriver.com> wrote:
> > The following are seen while using the corenet64_smp_defconfig:
> >
> > arch/powerpc/sysdev/fsl_rmu.c:315: error: cast from pointer to integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:320: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:320: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:320: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:330: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:332: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:339: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:340: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:341: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:348: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:348: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:348: error: cast to pointer from integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:659: error: cast from pointer to integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:659: error: format '%8.8x' expects type 'unsigned int', but argument 5 has type 'size_t'
> > arch/powerpc/sysdev/fsl_rmu.c:985: error: cast from pointer to integer of different size
> > arch/powerpc/sysdev/fsl_rmu.c:997: error: cast to pointer from integer of different size
> >
> > A quick inspection of the code leaves one with the impression
> > that it was not explicitly written with 64 bit support in mind,
> > so just block that as a possible config selection for now.
> >
> > Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
> >
> > ---
> >
> > [This is seen in linux-next -- not sure if this is the right way to go
> > but at least it will give the issue some visibility to the right ppl.]
> >
> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > index 75f061e..5ad8013 100644
> > --- a/arch/powerpc/Kconfig
> > +++ b/arch/powerpc/Kconfig
> > @@ -773,7 +773,7 @@ config RAPIDIO
> >
> > config FSL_RIO
> > bool "Freescale Embedded SRIO Controller support"
> > - depends on RAPIDIO && HAS_RAPIDIO
> > + depends on RAPIDIO && HAS_RAPIDIO && (BROKEN || !PPC64)
> > default "n"
> > ---help---
> > Include support for RapidIO controller on Freescale embedded
> > --
> > 1.7.9.1
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* linux-next: build failure after merge of the final tree
From: Stephen Rothwell @ 2012-02-27 6:37 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-next, ppc-dev, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1565 bytes --]
Hi all,
After merging the final tree, today's linux-next build (powerpc
ppc44x_defconfig) failed like this:
arch/powerpc/kernel/pci-common.c: In function 'pcibios_setup_phb_resources':
arch/powerpc/kernel/pci-common.c:1520:4: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
Caused by commit 6c5705fec63d ("powerpc/PCI: get rid of device resource
fixups") from the pci tree. In this build, resource_size_t is 64 bits
while pointers are only 32.
I applied the following fix patch.
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Mon, 27 Feb 2012 17:33:48 +1100
Subject: [PATCH] powerpc/PCI: fix up for mismatch between resource_size_t and
pointer size
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/pci-common.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 910b9de..808ecbb 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1517,7 +1517,7 @@ static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, s
(unsigned long long)res->end,
(unsigned long)res->flags);
pci_add_resource_offset(resources, res,
- (resource_size_t) hose->io_base_virt - _IO_BASE);
+ (resource_size_t)(unsigned long)hose->io_base_virt - _IO_BASE);
/* Hookup PHB Memory resources */
for (i = 0; i < 3; ++i) {
--
1.7.9.1
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply related
* Re: [PATCH/RFC] rapidio: temporarily exclude FSL_RIO from 64 bit builds
From: Liu Gang @ 2012-02-27 6:48 UTC (permalink / raw)
To: Paul Gortmaker; +Cc: Alexandre.Bounine, linux-next, linuxppc-dev
In-Reply-To: <CAP=VYLroaEKncpy7VBobJdXijnDS5UdTV7qPG2A--SicnGvFSg@mail.gmail.com>
On Sun, 2012-02-26 at 20:26 -0500, Paul Gortmaker wrote:
> Hi Ben,
>
> Given a week has passed with the absence of any feedback
> with respect to SRIO on 64 bit, are you OK with applying the
> below patch[1] pretty much as-is?
Hi, Paul, Ben,
Sorry for the late reply because of my other urgent issues. I also found
these errors of 64bit building last week. I'll provide patch for this
issue as soon as possible.
Thanks.
Best Regards,
Liu Gang
^ permalink raw reply
* Re: linux-next: build failure after merge of the final tree
From: Benjamin Herrenschmidt @ 2012-02-27 9:19 UTC (permalink / raw)
To: Stephen Rothwell
Cc: Bjorn Helgaas, linux-next, ppc-dev, linux-kernel, Jesse Barnes
In-Reply-To: <20120227173747.853e7fbe3ce3afab8939720b@canb.auug.org.au>
On Mon, 2012-02-27 at 17:37 +1100, Stephen Rothwell wrote:
> pci_add_resource_offset(resources, res,
> - (resource_size_t) hose->io_base_virt - _IO_BASE);
> + (resource_size_t)(unsigned long)hose->io_base_virt - _IO_BASE);
We have to be careful here as we do want sign extension to happen (yeah
it's odd, but it's the way we do IOs on ppc32 :-) Maybe I should change
it one day).
So we probably want to do:
(resource_size_t)(long long)(hose->io_base_virt - _IO_BASE)
Basically, IO resources are relative to _IO_BASE which on ppc32 is
basically the virtual address where we map the first PHB IO space.
Subsequent PHB mappings can end up below _IO_BASE, leading to negative
resource values for IO BARs on those busses. It all works fine because
even an unsigned addition will do the right thing as long as the value
is fully sign extended.
Cheers,
Ben.
^ permalink raw reply
* [PATCH 1/2] powerpc/e500: make load_up_spe a normal fuction
From: Olivia Yin @ 2012-02-27 10:59 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev; +Cc: Liu Yu, Olivia Yin
So that we can call it in kernel.
Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
arch/powerpc/kernel/head_fsl_booke.S | 23 ++++++-----------------
1 files changed, 6 insertions(+), 17 deletions(-)
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index d5d78c4..c96e025 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -539,8 +539,10 @@ interrupt_base:
/* SPE Unavailable */
START_EXCEPTION(SPEUnavailable)
NORMAL_EXCEPTION_PROLOG
- bne load_up_spe
- addi r3,r1,STACK_FRAME_OVERHEAD
+ beq 1f
+ bl load_up_spe
+ b fast_exception_return
+1: addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_EE_LITE(0x2010, KernelSPE)
#else
EXCEPTION(0x2020, SPEUnavailable, unknown_exception, EXC_XFER_EE)
@@ -743,7 +745,7 @@ tlb_write_entry:
/* Note that the SPE support is closely modeled after the AltiVec
* support. Changes to one are likely to be applicable to the
* other! */
-load_up_spe:
+_GLOBAL(load_up_spe)
/*
* Disable SPE for the task which had SPE previously,
* and save its SPE registers in its thread_struct.
@@ -791,20 +793,7 @@ load_up_spe:
subi r4,r5,THREAD
stw r4,last_task_used_spe@l(r3)
#endif /* !CONFIG_SMP */
- /* restore registers and return */
-2: REST_4GPRS(3, r11)
- lwz r10,_CCR(r11)
- REST_GPR(1, r11)
- mtcr r10
- lwz r10,_LINK(r11)
- mtlr r10
- REST_GPR(10, r11)
- mtspr SPRN_SRR1,r9
- mtspr SPRN_SRR0,r12
- REST_GPR(9, r11)
- REST_GPR(12, r11)
- lwz r11,GPR11(r11)
- rfi
+ blr
/*
* SPE unavailable trap from kernel - print a message, but let
--
1.6.4
^ permalink raw reply related
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