* Re: [PATCH] Compile failure fix for ppc on 2.6.17-rc4-mm3 (2nd attempt)
From: Segher Boessenkool @ 2006-05-29 16:22 UTC (permalink / raw)
To: Mel Gorman; +Cc: Andrew Morton, linuxppc-dev, vgoyal, linux-kernel
In-Reply-To: <20060529154923.GA9025@skynet.ie>
>>> arch/powerpc/kernel/built-in.o(.init.text+0x77b4): In function
>>> `vrsqrtefp':
>>> : undefined reference to `__udivdi3'
>>> arch/powerpc/kernel/built-in.o(.init.text+0x7800): In function
>>> `vrsqrtefp':
>>> : undefined reference to `__udivdi3'
>>> make: *** [.tmp_vmlinux1] Error 1
>>
>> A function with a name like that doesn't _deserve_ to compile.
Would vector_reciprocal_square_root_estimate_floating_point() be any
better...
Anyway, this is just a machine insn mnemonic, so the function name is
fine
I believe.
> #define push_end(res, size) do { unsigned long __sz = (size) ; \
> - res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
> + resource_size_t farEnd = (res->end + __sz); \
> + do_div(farEnd, (__sz + 1)); \
> + res->end = farEnd * (__sz + 1) + __sz; \
> } while (0)
Size here is a) a misnomer (size + 1 is the actual size) and b) always
a power
of two minus one. So instead, do
#define push_end(res, mask) res->end = -(-res->end & ~(unsigned
long)mask)
(with a do { } while(0) armour if you prefer).
Segher
^ permalink raw reply
* Re: Linux kernel thread with Linux 2.6.x
From: Thiago Galesi @ 2006-05-29 17:13 UTC (permalink / raw)
To: Laurent Lagrange; +Cc: linuxppc-embedded
In-Reply-To: <000201c68335$7c594b90$5201a8c0@GEG2400>
>
> As the interrupt handler can't be scheduled, I have made a kernel thread
> which waits forever on a semaphore.
> This semaphore is set when a received packet interrupt occured.
You should look into tasklets for this. Not that your system is not
OK, but, as you said it, it's not fast enough.
Note that you still have some limitations using tasklets, but it's
more flexible than Interrupt handlers.
^ permalink raw reply
* Re: [PATCH] Compile failure fix for ppc on 2.6.17-rc4-mm3 (2nd attempt)
From: Mel Gorman @ 2006-05-29 17:38 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Andrew Morton, linuxppc-dev, vgoyal, linux-kernel
In-Reply-To: <2ebd96e4a7ea753273b2c5f856ba8c7a@kernel.crashing.org>
On Mon, 29 May 2006, Segher Boessenkool wrote:
>>>> arch/powerpc/kernel/built-in.o(.init.text+0x77b4): In function
>>>> `vrsqrtefp':
>>>> : undefined reference to `__udivdi3'
>>>> arch/powerpc/kernel/built-in.o(.init.text+0x7800): In function
>>>> `vrsqrtefp':
>>>> : undefined reference to `__udivdi3'
>>>> make: *** [.tmp_vmlinux1] Error 1
>>>
>>> A function with a name like that doesn't _deserve_ to compile.
>
> Would vector_reciprocal_square_root_estimate_floating_point() be any
> better...
> Anyway, this is just a machine insn mnemonic, so the function name is fine
> I believe.
>
>> #define push_end(res, size) do { unsigned long __sz = (size) ; \
>> - res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
>> + resource_size_t farEnd = (res->end + __sz); \
>> + do_div(farEnd, (__sz + 1)); \
>> + res->end = farEnd * (__sz + 1) + __sz; \
>> } while (0)
>
> Size here is a) a misnomer (size + 1 is the actual size) and b) always a
> power
> of two minus one. So instead, do
>
> #define push_end(res, mask) res->end = -(-res->end & ~(unsigned long)mask)
>
> (with a do { } while(0) armour if you prefer).
>
It's not doing the same as the old code so is your suggested fix a correct
replacement?
For example, given 0xfff for size the current code rounds res->end to the
next 0x1000 boundary and adds 0xfff. Your propose fix just rounds it to
the next 0x1000 if I'm reading it correctly but is what the code was meant
to do in the first place? Using masks, the equivilant of the current code
is something like;
#define push_end(res, mask) do { \
res->end = -(-res->end & ~(unsigned long)mask); \
res->end += mask; \
} while (0)
--
Mel Gorman
Part-time Phd Student Linux Technology Center
University of Limerick IBM Dublin Software Lab
^ permalink raw reply
* Re: [PATCH] Compile failure fix for ppc on 2.6.17-rc4-mm3 (2nd attempt)
From: Segher Boessenkool @ 2006-05-29 17:56 UTC (permalink / raw)
To: Mel Gorman; +Cc: Andrew Morton, linuxppc-dev, vgoyal, linux-kernel
In-Reply-To: <Pine.LNX.4.64.0605291825500.11234@skynet.skynet.ie>
>>> #define push_end(res, size) do { unsigned long __sz = (size) ; \
>>> - res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
>>> + resource_size_t farEnd = (res->end + __sz); \
>>> + do_div(farEnd, (__sz + 1)); \
>>> + res->end = farEnd * (__sz + 1) + __sz; \
>>> } while (0)
>>
>> Size here is a) a misnomer (size + 1 is the actual size) and b)
>> always a power
>> of two minus one. So instead, do
>>
>> #define push_end(res, mask) res->end = -(-res->end & ~(unsigned
>> long)mask)
>>
>> (with a do { } while(0) armour if you prefer).
>>
>
> It's not doing the same as the old code so is your suggested fix a
> correct replacement?
>
> For example, given 0xfff for size the current code rounds res->end to
> the next 0x1000 boundary and adds 0xfff. Your propose fix just rounds
> it to the next 0x1000 if I'm reading it correctly but is what the code
> was meant to do in the first place? Using masks, the equivilant of the
> current code is something like;
>
> #define push_end(res, mask) do { \
> res->end = -(-res->end & ~(unsigned long)mask); \
> res->end += mask; \
> } while (0)
Yeah forgot a bit, this looks fine.
Segher
^ permalink raw reply
* Re: [PATCH] powerpc: add dmesg command to xmon
From: Olaf Hering @ 2006-05-29 17:58 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds, Arnd Bergmann; +Cc: linuxppc-dev
In-Reply-To: <200605281812.09308.arnd@arndb.de>
On Sun, May 28, Arnd Bergmann wrote:
> On Sunday 28 May 2006 14:07, Olaf Hering wrote:
> > > This whole function looks fishy to me. It seems unnecessarily rude to me to
> > > use kallsyms_lookup_name in order to get at a static variable from another
> > > file. Can't you instead add a global function to kernel/printk.c to return
> > > the buffer?
> >
> > Its possible, but it wont end up in Linus tree.
>
> Hmm, so the idea is that because Linus doesn't like kernel debuggers, we just
> obfuscate the code for any improvements to xmon and hope he doesn't notice?
So lets just ask again for support in generic code for a dmesg command in xmon:
http://lkml.org/lkml/2004/10/28/32
vs. these 2 patches
http://ozlabs.org/pipermail/linuxppc-dev/2006-May/023261.html
http://lkml.org/lkml/2006/5/29/55
or no dmesg at all.
^ permalink raw reply
* Re: [PATCH] Compile failure fix for ppc on 2.6.17-rc4-mm3 (2nd attempt)
From: Mel Gorman @ 2006-05-29 19:05 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Andrew Morton, linuxppc-dev, vgoyal, linux-kernel
In-Reply-To: <c6414fc4b2c627791a49085bf8eea7e8@kernel.crashing.org>
On (29/05/06 19:56), Segher Boessenkool didst pronounce:
> >>> #define push_end(res, size) do { unsigned long __sz = (size) ; \
> >>>- res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
> >>>+ resource_size_t farEnd = (res->end + __sz); \
> >>>+ do_div(farEnd, (__sz + 1)); \
> >>>+ res->end = farEnd * (__sz + 1) + __sz; \
> >>> } while (0)
> >>
> >>Size here is a) a misnomer (size + 1 is the actual size) and b)
> >>always a power
> >>of two minus one. So instead, do
> >>
> >>#define push_end(res, mask) res->end = -(-res->end & ~(unsigned
> >>long)mask)
> >>
> >>(with a do { } while(0) armour if you prefer).
> >>
> >
> >It's not doing the same as the old code so is your suggested fix a
> >correct replacement?
> >
> >For example, given 0xfff for size the current code rounds res->end to
> >the next 0x1000 boundary and adds 0xfff. Your propose fix just rounds
> >it to the next 0x1000 if I'm reading it correctly but is what the code
> >was meant to do in the first place? Using masks, the equivilant of the
> >current code is something like;
> >
> >#define push_end(res, mask) do { \
> > res->end = -(-res->end & ~(unsigned long)mask); \
> > res->end += mask; \
> >} while (0)
>
> Yeah forgot a bit, this looks fine.
>
Ok. The following patch has been successfully boot tested on the same machine
with 64 bit resource_size_t. Because the mask is assumed to be a
power-of-two - 1, I added a comment and a BUG_ON() to be sure.
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
diff -rup -X /usr/src/patchset-0.6/bin//dontdiff linux-2.6.17-rc4-mm3-clean/arch/powerpc/kernel/pci_32.c linux-2.6.17-rc4-mm3-resources-32/arch/powerpc/kernel/pci_32.c
--- linux-2.6.17-rc4-mm3-clean/arch/powerpc/kernel/pci_32.c 2006-05-29 15:55:52.000000000 +0100
+++ linux-2.6.17-rc4-mm3-resources-32/arch/powerpc/kernel/pci_32.c 2006-05-29 19:09:36.000000000 +0100
@@ -1114,8 +1114,16 @@ check_for_io_childs(struct pci_bus *bus,
int i;
int rc = 0;
-#define push_end(res, size) do { unsigned long __sz = (size) ; \
- res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
+ /*
+ * Assuming mask is a power of two - 1, push_end
+ * moves res->end to the end of the next
+ * mask-aligned boundary.
+ * e.g. res->end of 0x1fff moves to 0x2fff
+ */
+#define push_end(res, mask) do { \
+ BUG_ON( ((mask+1) & mask) != 0); \
+ res->end = -(-res->end & ~(unsigned long)mask); \
+ res->end += mask; \
} while (0)
list_for_each_entry(dev, &bus->devices, bus_list) {
^ permalink raw reply
* [RFC/PATCH 0/8] Overhaul of virt IRQ configuration. / Kill ppc64_interrupt_controller.
From: Michal Ostrowski @ 2006-05-29 20:41 UTC (permalink / raw)
To: linuxppc-dev
The following set of patches is aimed at killing the
ppc64_interrupt_controller global variable, and similarly that various
global variables used to tweak the parameters of virtual IRQ re-mapping.
Instead each platform can use a single function to configure IRQ
re-mapping in "init_early()".
Platforms can choose the default configuration (which is to
say identity mappings of IRQ vectors 0..511) or specify their own
configuration: an offset (for ISA vectors), the range that is to be
identity mapped and the range of vectors that may be arbitrarily
re-mapper.
This allows us to remove the special-casing based on
ppc64_interrupt_controller in virt_irq_create_mapping().
Subsequently most uses of ppc64_interrupt_controller are on
configuration paths where we can typically obtain comparable information
by alternate means.
In the end, only pSeries-specific code must be aware of the choice of
PIC and it will check to see if an MPIC has been initialized (and if
not, assume XICS). (Thus no platforms beyond pSeries are affected.)
This code has been tested on pSeries LPAR, G5, and Maple. I'll be
re-testing it on a Power3 with MPIC shortly once a system for testing
becomes available again.
--
Michal Ostrowski <mostrows@watson.ibm.com>
^ permalink raw reply
* [PATCH 1/8] Formalize virtual-IRQ remapping configuration.
From: mostrows @ 2006-05-29 20:42 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
Instead of setting various global various to configure the behavior of
virtual-IRQ remapping, each platform has the option of calling
virt_irq_config() in "init_early" to specify:
- the offset to be used (i.e. NUM_ISA_INTERRUPTS)
- the number of interrupt vectors which are to be mapped 1-1
- the number of interrupt vectors that may be arbitrarily remapped
If virt_irq_config() is not called, the default configuration will be
used (512 identity-mapped interrupts with no offset).
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/kernel/irq.c | 62 ++++++++++++++++----------------
arch/powerpc/kernel/prom.c | 4 --
arch/powerpc/kernel/setup_64.c | 6 +++
arch/powerpc/platforms/iseries/setup.c | 3 +-
arch/powerpc/platforms/pseries/setup.c | 10 +++++
include/asm-powerpc/irq.h | 30 +++++++++++----
6 files changed, 70 insertions(+), 45 deletions(-)
2f99449cbcacf67694e38698ec9860f86ba052e2
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 57d560c..efcb859 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -268,32 +268,35 @@ void __init init_IRQ(void)
#define UNDEFINED_IRQ 0xffffffff
unsigned int virt_irq_to_real_map[NR_IRQS];
-/*
- * Don't use virtual irqs 0, 1, 2 for devices.
- * The pcnet32 driver considers interrupt numbers < 2 to be invalid,
- * and 2 is the XICS IPI interrupt.
- * We limit virtual irqs to __irq_offet_value less than virt_irq_max so
- * that when we offset them we don't end up with an interrupt
- * number >= virt_irq_max.
- */
-#define MIN_VIRT_IRQ 3
-
-unsigned int virt_irq_max;
+static unsigned int min_virt_irq;
static unsigned int max_virt_irq;
static unsigned int nr_virt_irqs;
void
-virt_irq_init(void)
+virt_irq_config(unsigned int offset,
+ unsigned int num_shifted, unsigned int num_remapped)
{
- int i;
+ __irq_offset_value = offset;
+ min_virt_irq = num_shifted;
+ max_virt_irq = num_shifted + num_remapped - 1;
+ nr_virt_irqs = num_remapped;
- if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1)))
- virt_irq_max = NR_IRQS - 1;
- max_virt_irq = virt_irq_max - __irq_offset_value;
- nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1;
+ BUG_ON(max_virt_irq + __irq_offset_value > (NR_IRQS-1));
+}
+void
+virt_irq_init(void)
+{
+ int i;
for (i = 0; i < NR_IRQS; i++)
virt_irq_to_real_map[i] = UNDEFINED_IRQ;
+
+ /* Configure the default mappings; don't remap interrupts,
+ * use 1-1 virt <-> real mappings. Subsequently platforms may
+ * choose to call virt_irq_config with their own custom settings.
+ */
+ virt_irq_config(0, NR_IRQS, 0);
+
}
/* Create a mapping for a real_irq if it doesn't already exist.
@@ -304,30 +307,25 @@ int virt_irq_create_mapping(unsigned int
unsigned int virq, first_virq;
static int warned;
- if (ppc64_interrupt_controller == IC_OPEN_PIC)
- return real_irq; /* no mapping for openpic (for now) */
-
- if (ppc64_interrupt_controller == IC_CELL_PIC)
- return real_irq; /* no mapping for iic either */
-
- /* don't map interrupts < MIN_VIRT_IRQ */
- if (real_irq < MIN_VIRT_IRQ) {
+ /* don't map interrupts < min_virt_irq */
+ if (real_irq < min_virt_irq) {
virt_irq_to_real_map[real_irq] = real_irq;
return real_irq;
}
- /* map to a number between MIN_VIRT_IRQ and max_virt_irq */
+ /* map to a number between min_virt_irq and max_virt_irq */
virq = real_irq;
if (virq > max_virt_irq)
- virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
+ virq = (virq % nr_virt_irqs) + min_virt_irq;
/* search for this number or a free slot */
first_virq = virq;
while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) {
if (virt_irq_to_real_map[virq] == real_irq)
return virq;
+
if (++virq > max_virt_irq)
- virq = MIN_VIRT_IRQ;
+ virq = min_virt_irq;
if (virq == first_virq)
goto nospace; /* oops, no free slots */
}
@@ -338,8 +336,10 @@ int virt_irq_create_mapping(unsigned int
nospace:
if (!warned) {
printk(KERN_CRIT "Interrupt table is full\n");
- printk(KERN_CRIT "Increase virt_irq_max (currently %d) "
- "in your kernel sources and rebuild.\n", virt_irq_max);
+ printk(KERN_CRIT "Modify kernel sources to call "
+ "virt_irq_config() with a larger value "
+ "of \"num_remapped\" (currently %d) and rebuild.\n",
+ nr_virt_irqs);
warned = 1;
}
return NO_IRQ;
@@ -358,7 +358,7 @@ unsigned int real_irq_to_virt_slowpath(u
virq = real_irq;
if (virq > max_virt_irq)
- virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
+ virq = (virq % nr_virt_irqs) + min_virt_irq;
first_virq = virq;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9a07f97..bfbe6a7 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -472,10 +472,6 @@ void __init finish_device_tree(void)
DBG(" -> finish_device_tree\n");
-#ifdef CONFIG_PPC64
- /* Initialize virtual IRQ map */
- virt_irq_init();
-#endif
scan_interrupt_controllers();
/*
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4467c49..4669179 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -389,6 +389,12 @@ void __init setup_system(void)
*/
check_for_initrd();
+
+ /* Configure default setting for virtual IRQ remapping.
+ * ppc_md.init_early() may reconfigure this with virt_irq_config()
+ */
+ virt_irq_init();
+
/*
* Do some platform specific early initializations, that includes
* setting up the hash table pointers. It also sets up some interrupt-mapping
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index a6fd9be..6a7d04b 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -688,8 +688,9 @@ static int __init iseries_probe(void)
/*
* The Hypervisor only allows us up to 256 interrupt
* sources (the irq number is passed in a u8).
+ * This call provides us with vectors 0 .. 255 without remapping.
*/
- virt_irq_max = 255;
+ virt_irq_config(0, 256, 0);
return 1;
}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 5f79f01..9d22265 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -270,7 +270,6 @@ static void __init pSeries_discover_pic
* Setup interrupt mapping options that are needed for finish_device_tree
* to properly parse the OF interrupt tree & do the virtual irq mapping
*/
- __irq_offset_value = NUM_ISA_INTERRUPTS;
ppc64_interrupt_controller = IC_INVALID;
for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
typep = (char *)get_property(np, "compatible", NULL);
@@ -286,6 +285,15 @@ static void __init pSeries_discover_pic
printk("pSeries_discover_pic: failed to recognize"
" interrupt-controller\n");
+ /*
+ * Don't use virtual irqs 0, 1, 2 for devices.
+ * The pcnet32 driver considers interrupt numbers < 2 to be invalid,
+ * and 2 is the XICS IPI interrupt.
+ */
+
+ virt_irq_config(NUM_ISA_INTERRUPTS, 3,
+ NR_IRQS - (3 + NUM_ISA_INTERRUPTS));
+
}
static void pSeries_mach_cpu_die(void)
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 7bc6d73..f2adbc0 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -54,18 +54,32 @@
*/
extern unsigned int virt_irq_to_real_map[NR_IRQS];
-/* The maximum virtual IRQ number that we support. This
- * can be set by the platform and will be reduced by the
- * value of __irq_offset_value. It defaults to and is
- * capped by (NR_IRQS - 1).
- */
-extern unsigned int virt_irq_max;
-
/* Create a mapping for a real_irq if it doesn't already exist.
* Return the virtual irq as a convenience.
*/
int virt_irq_create_mapping(unsigned int real_irq);
-void virt_irq_init(void);
+
+/* Initializes the virtual IRQ re-mapping, before ppc_md.init_early() */
+extern void virt_irq_init(void);
+
+/* virt_irq_config - Configure the division of the virtual IRQ space.
+ * Each platform may call this to set it's own specific
+ * IRQ remapping parameters.
+ * @offset: offset of remapped space (i.e. NUM_ISA_INTERRUPTS).
+ * @num_shifted: number of vectors to be simply shifted to account for
+ * the offset with no other remapping.
+ * @num_remapper: number of vectors that may be arbitrarily remapped.
+ *
+ * Virtual IRQ vectors will have the following mappings to the IRQ vectors
+ * as seen by the approrpiate interrupt controller:
+ * 0 .. offset-1 -> 0 .. offset-1 (1-1 mapping)
+ * offset .. offset+num_shifted-1 -> 0 .. num_shifted-1 (shift by offset)
+ * offset+num_shifted .. offset+num_shifted+num_remapped-1 ->
+ * arbitrary mappings to real irq as required.
+ */
+extern void virt_irq_config(unsigned int offset,
+ unsigned int num_linear,
+ unsigned int num_remapped);
static inline unsigned int virt_irq_to_real(unsigned int virt_irq)
{
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* [PATCH 2/8] PIC discovery re-organization.
From: mostrows @ 2006-05-29 20:42 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
Change pSeries_discover_pic() to simply return the PIC type, rather
than setting the global "ppc64_interrupt_controller" value. They type of
controller present will be passed down as an argument to functions
that need it.
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/platforms/pseries/setup.c | 36 +++++++++++++++++---------------
1 files changed, 19 insertions(+), 17 deletions(-)
3675f032e1b03d6f000ffb08b2487ee9aa44fa2d
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 9d22265..33ae521 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -83,6 +83,7 @@ int fwnmi_active; /* TRUE if an FWNMI h
static void pseries_shared_idle_sleep(void);
static void pseries_dedicated_idle_sleep(void);
+static int pSeries_discover_pic(void);
struct mpic *pSeries_mpic;
@@ -195,8 +196,11 @@ static void pseries_lpar_enable_pmcs(voi
static void __init pSeries_setup_arch(void)
{
+ int int_ctrl = pSeries_discover_pic();
+ ppc64_interrupt_controller = int_ctrl;
+
/* Fixup ppc_md depending on the type of interrupt controller */
- if (ppc64_interrupt_controller == IC_OPEN_PIC) {
+ if (int_ctrl == IC_OPEN_PIC) {
ppc_md.init_IRQ = pSeries_init_mpic;
ppc_md.get_irq = mpic_get_irq;
/* Allocate the mpic now, so that find_and_init_phbs() can
@@ -261,39 +265,30 @@ static int __init pSeries_init_panel(voi
}
arch_initcall(pSeries_init_panel);
-static void __init pSeries_discover_pic(void)
+static int __init pSeries_discover_pic(void)
{
struct device_node *np;
char *typep;
-
/*
* Setup interrupt mapping options that are needed for finish_device_tree
* to properly parse the OF interrupt tree & do the virtual irq mapping
*/
- ppc64_interrupt_controller = IC_INVALID;
+ int int_ctrl = IC_INVALID;
for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
typep = (char *)get_property(np, "compatible", NULL);
if (strstr(typep, "open-pic")) {
- ppc64_interrupt_controller = IC_OPEN_PIC;
+ int_ctrl = IC_OPEN_PIC;
break;
} else if (strstr(typep, "ppc-xicp")) {
- ppc64_interrupt_controller = IC_PPC_XIC;
+ int_ctrl = IC_PPC_XIC;
break;
}
}
- if (ppc64_interrupt_controller == IC_INVALID)
+ if (int_ctrl == IC_INVALID)
printk("pSeries_discover_pic: failed to recognize"
" interrupt-controller\n");
- /*
- * Don't use virtual irqs 0, 1, 2 for devices.
- * The pcnet32 driver considers interrupt numbers < 2 to be invalid,
- * and 2 is the XICS IPI interrupt.
- */
-
- virt_irq_config(NUM_ISA_INTERRUPTS, 3,
- NR_IRQS - (3 + NUM_ISA_INTERRUPTS));
-
+ return int_ctrl;
}
static void pSeries_mach_cpu_die(void)
@@ -346,7 +341,14 @@ static void __init pSeries_init_early(vo
iommu_init_early_pSeries();
- pSeries_discover_pic();
+ /*
+ * Don't use virtual irqs 0, 1, 2 for devices.
+ * The pcnet32 driver considers interrupt numbers < 2 to be invalid,
+ * and 2 is the XICS IPI interrupt.
+ */
+
+ virt_irq_config(NUM_ISA_INTERRUPTS, 3,
+ NR_IRQS - (3 + NUM_ISA_INTERRUPTS));
DBG(" <- pSeries_init_early()\n");
}
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* [PATCH 3/8] Avoid use of ppc64_interrupt_controller.
From: mostrows @ 2006-05-29 20:42 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
xics_irq_8259_cascade being a valid (non -1) value is sufficient criteria
for registering the cascade interrupt vector.
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/platforms/pseries/xics.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
35c3db8657f7716ae93d7423ce49f32a5f008359
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 2d60ea3..0fae097 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -82,8 +82,8 @@ struct xics_ipl {
static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
-static int xics_irq_8259_cascade = 0;
-static int xics_irq_8259_cascade_real = 0;
+static int xics_irq_8259_cascade = -1; /* default to invalid value*/
+static int xics_irq_8259_cascade_real = -1;
static unsigned int default_server = 0xFF;
static unsigned int default_distrib_server = 0;
static unsigned int interrupt_server_size = 8;
@@ -571,8 +571,7 @@ nextnode:
*/
static int __init xics_setup_i8259(void)
{
- if (ppc64_interrupt_controller == IC_PPC_XIC &&
- xics_irq_8259_cascade != -1) {
+ if (xics_irq_8259_cascade != -1) {
if (request_irq(irq_offset_up(xics_irq_8259_cascade),
no_action, 0, "8259 cascade", NULL))
printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 "
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* [PATCH 6/8] Avoid use of ppc64_interrupt_controller.
From: mostrows @ 2006-05-29 20:42 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
Checking the pSeries_mpic pointer will tell us if we have an MPIC
(and if not we assume XICS).
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/platforms/pseries/setup.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
b8d30cee0f0257489bb79c3d36f0afc39b8e63e6
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 38bf976..4ff127b 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -536,7 +536,7 @@ static void pseries_kexec_cpu_down(int c
}
}
- if (ppc64_interrupt_controller == IC_OPEN_PIC)
+ if (pSeries_mpic)
mpic_teardown_this_cpu(secondary);
else
xics_teardown_cpu(secondary);
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* [PATCH 4/8] Avoid use of ppc64_interrupt_controller.
From: mostrows @ 2006-05-29 20:42 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
Existence of "/platform-open-pic" is asserted by pSeries_setup_mpic if
an mpic interrupt controller exists. Thus pSeries_mpic is non-NULL
only if the opprop value obtained here is good. Hence, no need to
check ppc64_intrerrupt_controller.
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/kernel/rtas_pci.c | 8 +++-----
1 files changed, 3 insertions(+), 5 deletions(-)
3a5eaf5436e0c413e154a933867ff5a09c019e3c
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 57b539a..e1dbd53 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -301,10 +301,8 @@ unsigned long __init find_and_init_phbs(
unsigned int *opprop = NULL;
struct device_node *root = of_find_node_by_path("/");
- if (ppc64_interrupt_controller == IC_OPEN_PIC) {
- opprop = (unsigned int *)get_property(root,
- "platform-open-pic", NULL);
- }
+ /* If pSeries_mpic is non-NULL, it's because opprop is non-0. */
+ opprop = (unsigned int *)get_property(root, "platform-open-pic", NULL);
root_size_cells = prom_n_size_cells(root);
@@ -324,7 +322,7 @@ unsigned long __init find_and_init_phbs(
pci_setup_phb_io(phb, index == 0);
#ifdef CONFIG_PPC_PSERIES
/* XXX This code need serious fixing ... --BenH */
- if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
+ if (pSeries_mpic) {
int addr = root_size_cells * (index + 2) - 1;
mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
}
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* [PATCH 5/8] Avoid use of ppc64_interrupt_controller.
From: mostrows @ 2006-05-29 20:42 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
smp_init_pSeries() will use an XICS, unless it is told to explicitly
use an MPIC.
Checking for built-in support of the detect PIC is now consolidated in
pSeries_setup_arch. (Eventually it should be possible to avoid building
code for a PIC if support for it has not been enabled.)
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/platforms/pseries/setup.c | 28 +++++++++++++++++++++-------
arch/powerpc/platforms/pseries/smp.c | 15 +++------------
include/asm-powerpc/smp.h | 6 +++++-
3 files changed, 29 insertions(+), 20 deletions(-)
c294c06d77fbe3be12a705595ecd95f93054943e
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 33ae521..38bf976 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -153,6 +153,9 @@ static void __init pSeries_setup_mpic(vo
struct device_node *root;
int irq_count;
+ ppc_md.init_IRQ = pSeries_init_mpic;
+ ppc_md.get_irq = mpic_get_irq;
+
/* Find the Open PIC if present */
root = of_find_node_by_path("/");
opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL);
@@ -199,21 +202,32 @@ static void __init pSeries_setup_arch(vo
int int_ctrl = pSeries_discover_pic();
ppc64_interrupt_controller = int_ctrl;
+
/* Fixup ppc_md depending on the type of interrupt controller */
- if (int_ctrl == IC_OPEN_PIC) {
- ppc_md.init_IRQ = pSeries_init_mpic;
- ppc_md.get_irq = mpic_get_irq;
+ switch (int_ctrl) {
+ case IC_OPEN_PIC:
+#ifndef CONFIG_MPIC
+ panic("Kernel not configured for MPIC interrupt controller.");
+#else
/* Allocate the mpic now, so that find_and_init_phbs() can
* fill the ISUs */
pSeries_setup_mpic();
- } else {
+ smp_init_pSeries(1);
+#endif
+ break;
+ case IC_PPC_XIC:
+#ifndef CONFIG_XICS
+ panic("Kernel not configured for XICS interrupt controller.");
+#else
ppc_md.init_IRQ = xics_init_IRQ;
ppc_md.get_irq = xics_get_irq;
+ smp_init_pSeries(0);
+#endif
+ break;
+ default:
+ panic("Invalid interrupt controller");
}
-#ifdef CONFIG_SMP
- smp_init_pSeries();
-#endif
/* openpic global configuration register (64-bit format). */
/* openpic Interrupt Source Unit pointer (64-bit format). */
/* python0 facility area (mmio) (64-bit format) REAL address. */
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 3cf78a6..ef8676f 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -417,25 +417,16 @@ static struct smp_ops_t pSeries_xics_smp
#endif
/* This is called very early */
-void __init smp_init_pSeries(void)
+void __init smp_init_pSeries(int uses_mpic)
{
int i;
DBG(" -> smp_init_pSeries()\n");
- switch (ppc64_interrupt_controller) {
-#ifdef CONFIG_MPIC
- case IC_OPEN_PIC:
+ if (uses_mpic) {
smp_ops = &pSeries_mpic_smp_ops;
- break;
-#endif
-#ifdef CONFIG_XICS
- case IC_PPC_XIC:
+ } else {
smp_ops = &pSeries_xics_smp_ops;
- break;
-#endif
- default:
- panic("Invalid interrupt controller");
}
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h
index 4a716f7..11f1830 100644
--- a/include/asm-powerpc/smp.h
+++ b/include/asm-powerpc/smp.h
@@ -75,7 +75,7 @@ extern cpumask_t cpu_sibling_map[NR_CPUS
#define PPC_MSG_DEBUGGER_BREAK 3
void smp_init_iSeries(void);
-void smp_init_pSeries(void);
+void smp_init_pSeries(int uses_mpic);
void smp_init_cell(void);
void smp_setup_cpu_maps(void);
@@ -86,6 +86,10 @@ extern void __cpu_die(unsigned int cpu);
/* for UP */
#define smp_setup_cpu_maps()
+#define smp_init_pSeries(uses_mpic) do {} while(0)
+#define smp_init_iSeries() do {} while(0)
+#define smp_init_cell() do {} while(0)
+
#endif /* CONFIG_SMP */
#ifdef CONFIG_PPC64
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* [PATCH 7/8] Cleaner checks for MPIC on pSeries.
From: mostrows @ 2006-05-29 20:42 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
Instead of checking the pSeries_mpic pointer, use a wrapper
(pSeries_uses_mpic()) that tells us what we want to know.
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/kernel/rtas_pci.c | 2 +-
arch/powerpc/platforms/pseries/setup.c | 2 +-
include/asm-powerpc/mpic.h | 6 ++++++
3 files changed, 8 insertions(+), 2 deletions(-)
082a93566e954ce0cc945b89aced0b28feb7ee60
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index e1dbd53..2a6b729 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -322,7 +322,7 @@ unsigned long __init find_and_init_phbs(
pci_setup_phb_io(phb, index == 0);
#ifdef CONFIG_PPC_PSERIES
/* XXX This code need serious fixing ... --BenH */
- if (pSeries_mpic) {
+ if (pSeries_uses_mpic()) {
int addr = root_size_cells * (index + 2) - 1;
mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 4ff127b..551da6a 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -536,7 +536,7 @@ static void pseries_kexec_cpu_down(int c
}
}
- if (pSeries_mpic)
+ if (pSeries_uses_mpic())
mpic_teardown_this_cpu(secondary);
else
xics_teardown_cpu(secondary);
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index 6b9e781..1f1b2eb 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -287,5 +287,11 @@ extern int mpic_get_irq(struct pt_regs *
/* global mpic for pSeries */
extern struct mpic *pSeries_mpic;
+#ifdef CONFIG_MPIC
+#define pSeries_uses_mpic() (pSeries_mpic != NULL)
+#else
+#define pSeries_uses_mpic() 0
+#endif
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MPIC_H */
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* [PATCH 8/8] Kill the ppc64_interrupt_controller global symbol.
From: mostrows @ 2006-05-29 20:42 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/kernel/irq.c | 1 -
arch/powerpc/kernel/setup_64.c | 2 --
arch/powerpc/platforms/cell/setup.c | 2 --
arch/powerpc/platforms/iseries/setup.c | 2 --
arch/powerpc/platforms/maple/setup.c | 3 ---
arch/powerpc/platforms/powermac/setup.c | 3 ---
arch/powerpc/platforms/pseries/setup.c | 15 +++++++++++----
include/asm-powerpc/irq.h | 11 -----------
8 files changed, 11 insertions(+), 28 deletions(-)
5a0403834813838657ce9a3b762203f6479f36fa
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index efcb859..bee60d5 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -89,7 +89,6 @@ extern atomic_t ipi_sent;
EXPORT_SYMBOL(irq_desc);
int distribute_irqs = 1;
-u64 ppc64_interrupt_controller;
#endif /* CONFIG_PPC64 */
int show_interrupts(struct seq_file *p, void *v)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4669179..f791bcc 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -445,8 +445,6 @@ void __init setup_system(void)
printk("-----------------------------------------------------\n");
printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
- printk("ppc64_interrupt_controller = 0x%ld\n",
- ppc64_interrupt_controller);
printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size());
printk("ppc64_caches.dcache_line_size = 0x%x\n",
ppc64_caches.dline_size);
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 6574b22..e1cf54e 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -117,8 +117,6 @@ static void __init cell_init_early(void)
cell_init_iommu();
- ppc64_interrupt_controller = IC_CELL_PIC;
-
DBG(" <- cell_init_early()\n");
}
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 6a7d04b..ca623c5 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -303,8 +303,6 @@ static void __init iSeries_init_early(vo
{
DBG(" -> iSeries_init_early()\n");
- ppc64_interrupt_controller = IC_ISERIES;
-
#if defined(CONFIG_BLK_DEV_INITRD)
/*
* If the init RAM disk has been configured and there is
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 24c0aef..592972c 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -204,9 +204,6 @@ static void __init maple_init_early(void
*/
hpte_init_native();
- /* Setup interrupt mapping options */
- ppc64_interrupt_controller = IC_OPEN_PIC;
-
iommu_init_early_dart();
DBG(" <- maple_init_early\n");
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 4d15e39..2b2dc75 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -609,9 +609,6 @@ static void __init pmac_init_early(void)
udbg_adb_init(!!strstr(cmd_line, "btextdbg"));
#ifdef CONFIG_PPC64
- /* Setup interrupt mapping options */
- ppc64_interrupt_controller = IC_OPEN_PIC;
-
iommu_init_early_dart();
#endif
}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 551da6a..a85b810 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -83,7 +83,15 @@ int fwnmi_active; /* TRUE if an FWNMI h
static void pseries_shared_idle_sleep(void);
static void pseries_dedicated_idle_sleep(void);
-static int pSeries_discover_pic(void);
+
+/*
+ * List of interrupt controller identifiers; possible return values from
+ * pSeries_discover_pic().
+ */
+#define IC_INVALID 0
+#define IC_OPEN_PIC 1
+#define IC_PPC_XIC 2
+static int pSeries_discover_pic(void);
struct mpic *pSeries_mpic;
@@ -200,9 +208,7 @@ static void pseries_lpar_enable_pmcs(voi
static void __init pSeries_setup_arch(void)
{
int int_ctrl = pSeries_discover_pic();
- ppc64_interrupt_controller = int_ctrl;
-
/* Fixup ppc_md depending on the type of interrupt controller */
switch (int_ctrl) {
case IC_OPEN_PIC:
@@ -279,7 +285,8 @@ static int __init pSeries_init_panel(voi
}
arch_initcall(pSeries_init_panel);
-static int __init pSeries_discover_pic(void)
+
+static int __init pSeries_discover_pic(void)
{
struct device_node *np;
char *typep;
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index f2adbc0..66cfeab 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -88,17 +88,6 @@ static inline unsigned int virt_irq_to_r
extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq);
-/*
- * List of interrupt controllers.
- */
-#define IC_INVALID 0
-#define IC_OPEN_PIC 1
-#define IC_PPC_XIC 2
-#define IC_CELL_PIC 3
-#define IC_ISERIES 4
-
-extern u64 ppc64_interrupt_controller;
-
#else /* 32-bit */
#if defined(CONFIG_40x)
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* Re: [PATCH 7/8] Cleaner checks for MPIC on pSeries.
From: Olof Johansson @ 2006-05-29 20:50 UTC (permalink / raw)
To: mostrows; +Cc: linuxppc-dev
In-Reply-To: <11489353263834-git-send-email-mostrows@watson.ibm.com>
On Mon, May 29, 2006 at 04:42:06PM -0400, mostrows@watson.ibm.com wrote:
> Instead of checking the pSeries_mpic pointer, use a wrapper
> (pSeries_uses_mpic()) that tells us what we want to know.
You might as well kill the SillyCaps while you're at it.
-Olof
> --
> Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
>
> ---
>
> arch/powerpc/kernel/rtas_pci.c | 2 +-
> arch/powerpc/platforms/pseries/setup.c | 2 +-
> include/asm-powerpc/mpic.h | 6 ++++++
> 3 files changed, 8 insertions(+), 2 deletions(-)
>
> 082a93566e954ce0cc945b89aced0b28feb7ee60
> diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
> index e1dbd53..2a6b729 100644
> --- a/arch/powerpc/kernel/rtas_pci.c
> +++ b/arch/powerpc/kernel/rtas_pci.c
> @@ -322,7 +322,7 @@ unsigned long __init find_and_init_phbs(
> pci_setup_phb_io(phb, index == 0);
> #ifdef CONFIG_PPC_PSERIES
> /* XXX This code need serious fixing ... --BenH */
> - if (pSeries_mpic) {
> + if (pSeries_uses_mpic()) {
> int addr = root_size_cells * (index + 2) - 1;
> mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
> }
> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
> index 4ff127b..551da6a 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -536,7 +536,7 @@ static void pseries_kexec_cpu_down(int c
> }
> }
>
> - if (pSeries_mpic)
> + if (pSeries_uses_mpic())
> mpic_teardown_this_cpu(secondary);
> else
> xics_teardown_cpu(secondary);
> diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
> index 6b9e781..1f1b2eb 100644
> --- a/include/asm-powerpc/mpic.h
> +++ b/include/asm-powerpc/mpic.h
> @@ -287,5 +287,11 @@ extern int mpic_get_irq(struct pt_regs *
> /* global mpic for pSeries */
> extern struct mpic *pSeries_mpic;
>
> +#ifdef CONFIG_MPIC
> +#define pSeries_uses_mpic() (pSeries_mpic != NULL)
> +#else
> +#define pSeries_uses_mpic() 0
> +#endif
> +
> #endif /* __KERNEL__ */
> #endif /* _ASM_POWERPC_MPIC_H */
> --
> 1.1.4.g0b63-dirty
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [RFC/PATCH 0/8] Overhaul of virt IRQ configuration. / Kill ppc64_interrupt_controller.
From: Benjamin Herrenschmidt @ 2006-05-29 21:28 UTC (permalink / raw)
To: Michal Ostrowski; +Cc: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
On Mon, 2006-05-29 at 16:41 -0400, Michal Ostrowski wrote:
> The following set of patches is aimed at killing the
> ppc64_interrupt_controller global variable, and similarly that various
> global variables used to tweak the parameters of virtual IRQ re-mapping.
> Instead each platform can use a single function to configure IRQ
> re-mapping in "init_early()".
.../...
Hi ! Interesting.. I've start looking at reworking that with a slightly
different approach though...
We need irq controller instances (which we get from the genirq patch
from Ingo & Thomas Gleixner), and we decided that interrupt controller
nodes are mandatory in the device-tree thus we can do something like:
- Each interrupt controller instance, when allocated, requests a certain
number of interrupts and gets that allocated (gets an offset allocated).
It can locally use the virtual irq remapping too, I'm still toying with
the best way to deal with that. This interrupt controller structure is
associated to the device-node of the controller (or the root node of the
tree if no controller node is found)
- Interrupt 0..15 are reserved. 0 is always invalid. Only ISA PICs that
carry legacy devices can request those (by passing a special flag to the
allocation routine). Any other gets remapped (including powermac MPICs).
That will avoid endless problems that we never properly solved with
legacy drivers and the fact that Linus decided that 0 should be the
invalid interrupt number on all platforms
- Provide in prom_parse.c functions for obtaining the PIC node and
local interrupt number of a given device based on a passed-in array
matching the semantics of an "interrupts" property and a parent node.
Along with a helper that may just take a child node. The former is
needed for PCI devices that have no device node. Provide a
pci_ppc_map_interrupt() that takes a pci_dev and does the interrupt
mapping, either by using the standard OF approach if a device-node is
present, or walking up the PCI tree while doing standard swizzling until
it reaches a device node
- Mapping from a virtual number to a local number can be done by a
helper that does the offset and possible virq mapping if requested by
the controller. Same goes with inverse mapping. Mapping is done locally
by the controller code using that helper.
Ben.
^ permalink raw reply
* Re: [RFC/PATCH 0/8] Overhaul of virt IRQ configuration. / Kill ppc64_interrupt_controller.
From: Paul Mackerras @ 2006-05-29 21:56 UTC (permalink / raw)
To: Michal Ostrowski; +Cc: linuxppc-dev
In-Reply-To: <1148935262.25048.31.camel@brick>
Michal Ostrowski writes:
> Platforms can choose the default configuration (which is to
> say identity mappings of IRQ vectors 0..511) or specify their own
> configuration: an offset (for ISA vectors), the range that is to be
Given that the decree has come down from on high that irq 0 is always
to mean "none" or "no IRQ", I have been thinking that we should use
the ISA offset everywhere, even on machines without any ISA hardware.
Paul.
^ permalink raw reply
* Re: [Done] Re: snd-aoa: Sound gone after snd-aoa updates, on PB5,8
From: Wolfgang Pfeiffer @ 2006-05-29 22:17 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Johannes Berg
In-Reply-To: <1148869725.3918.12.camel@localhost.localdomain>
Hi All
Sorry for responding a bit late: I had to leave the house today ...
On Mon, May 29, 2006 at 12:28:45PM +1000, Benjamin Herrenschmidt wrote:
> On Mon, 2006-05-29 at 04:17 +0200, Wolfgang Pfeiffer wrote:
> > On Mon, May 29, 2006 at 04:00:27AM +0200, Wolfgang Pfeiffer wrote:
> > >
> > > Hi
> > >
> > > After some updates from http://johannes.sipsolutions.net/snd-aoa.git/
> > > in the last few hours/minutes sound's gone here. Without changing
> > > sound settings intentionally here.
> > >
> > >
> >
> > On Debian/unstable:
> > After downgrading libasound2 from 1.0.11-6 to 1.0.11-3 I have sound
> > again: 1.0.11-6 was, IINM, installed a few hours ago, which
> > - as it seems - broke sound here.
>
> Have you tested that it wasn't just the renaming/re-ordering of some
> controls ? Alsa is pretty bad with that, you may just have to go back to
> alsamixer and reset some controls after updating the driver.
That's what I tried after reading your mail:
$ apt-cache policy libasound2
libasound2:
Installed: 1.0.11-6
Candidate: 1.0.11-6
The problem is: with libasound2 1.0.11-6 I cannot even *start*
alsamixer:
------------------------
$ alsamixer
ALSA lib control.c:816:(snd_ctl_open_noupdate) Invalid CTL default
alsamixer: function snd_ctl_open failed for default: No such file or directory
-------------------------
----------------------------
$ alsamixer -c 0
ALSA lib control.c:816:(snd_ctl_open_noupdate) Invalid CTL hw:0
alsamixer: function snd_ctl_open failed for hw:0: No such file or directory
---------------------------
amixer:
------------------------
$ amixer -dD controls
ALSA lib control.c:816:(snd_ctl_open_noupdate) Invalid CTL controls
amixer: Mixer attach controls error: No such file or directory
---------------------------
But the last 2 examples may hint amixer at least sees some sound card:
---------------
$ amixer -c 1 controls
Invalid card number.
Usage: amixer <options> [command]
Available options:
[ ... ]
---------------------
-------------------
$ amixer -c 0 controls
ALSA lib control.c:816:(snd_ctl_open_noupdate) Invalid CTL hw:0
amixer: Control hw:0 open error: No such file or directory
-----------------------
Suggestions? Did I miss something?
Thanks in anticipation
Best Regards
Wolfgang
--
Wolfgang Pfeiffer: /ICQ: 286585973/ + + + /AIM: crashinglinux/
http://profiles.yahoo.com/wolfgangpfeiffer
Key ID: E3037113
http://keyserver.mine.nu/pks/lookup?search=0xE3037113&fingerprint=on
^ permalink raw reply
* Re: [RFC/PATCH 0/8] Overhaul of virt IRQ configuration. / Kill ppc64_interrupt_controller.
From: Michal Ostrowski @ 2006-05-29 23:08 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1148938117.5959.24.camel@localhost.localdomain>
On Tue, 2006-05-30 at 07:28 +1000, Benjamin Herrenschmidt wrote:
> On Mon, 2006-05-29 at 16:41 -0400, Michal Ostrowski wrote:
> > The following set of patches is aimed at killing the
> > ppc64_interrupt_controller global variable, and similarly that various
> > global variables used to tweak the parameters of virtual IRQ re-mapping.
> > Instead each platform can use a single function to configure IRQ
> > re-mapping in "init_early()".
>
> .../...
>
> Hi ! Interesting.. I've start looking at reworking that with a slightly
> different approach though...
>
I'm in total agreement with your assessment of where things should go.
My main motivation here was to kill ppc64_interrupt_controller and to
consolidate our knowledge of the requirements of the different platforms
into a single interface (i.e. virt_irq_config).
As such I see this patch as either a first step, or clean-up along-side,
the changes you're considering.
I did consider at first making more changes than published here; in
particular to address the offsetting issue you and Paul have commented
on.
Current code such as:
virq = virt_irq_create_mapping(irq[0]);
...
np->intrs[intrcount].line = irq_offset_up(virq);
Should be more like:
np->intrs[intrcount].line = virt_irq_create_mapping(irq[0]);
(Where the knowledge regarding all remapping/offsetting is embedded
behind the remapping interfaces. We should kill irq_offset_{up,down}
and replace them with things such as real_irq_to_virt() and
virt_irq_to_real().)
The patches I've sent out were not intended to deal with this, as I
wanted to keep the change set focused and small. However, things similar
to what you've outlined I've been keeping in mind as potential follow-on
work; and I had intended these patches to facilitate that.
--
Michal Ostrowski <mostrows@watson.ibm.com>
^ permalink raw reply
* [PATCH] Provide mechanism for editing builtin command-line in zImage binary.
From: mostrows @ 2006-05-30 2:01 UTC (permalink / raw)
To: linuxppc-dev
zImage will store the builtin command-line in a dedicated section, allowing
it to be easily identified and edited with user-space tools.
zImage will set /chosen/bootargs to the stored builtin command-line setting,
if /chosen/bootargs is empty (emulating the behavior in prom_init.c).
Use of this mechanism avoids the need to modify firmware or rely on a
bootloader to customize kernel arguments (and overall system
behavior). The command line can be edited as needed when a zImage is
copied to a TFTP staging area for download by firmware.
--
Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
---
arch/powerpc/boot/Makefile | 3 ++-
arch/powerpc/boot/main.c | 28 ++++++++++++++++++++++++++++
arch/powerpc/boot/prom.h | 6 ++++++
3 files changed, 36 insertions(+), 1 deletions(-)
38d6b8581e01886e352b699c978a3a5ac6672622
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 840ae59..d7ba474 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -41,7 +41,8 @@ src-boot += $(zlib)
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
-BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj)
+BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj) -I$(O)/include -I$(O)/include2\
+ -D__KERNEL__
quiet_cmd_copy_zlib = COPY $@
cmd_copy_zlib = sed "s@__attribute_used__@@;s@<linux/\([^>]\+\).*@\"\1\"@" $< > $@
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 816446f..eef25de 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -10,6 +10,9 @@
*/
#include <stdarg.h>
#include <stddef.h>
+#include <linux/autoconf.h>
+#include <asm/setup.h>
+
#include "elf.h"
#include "page.h"
#include "string.h"
@@ -33,6 +36,16 @@ extern char _vmlinux_end[];
extern char _initrd_start[];
extern char _initrd_end[];
+#ifdef CONFIG_CMDLINE
+/* Putting this in a seperate section allows for simple tools to
+ * edit this setting after a build (i.e. as the kernel image is being deployed
+ * for booting.
+ */
+static char builtin_cmdline[COMMAND_LINE_SIZE]
+ __attribute__((section("__builtin_cmdline"))) = CONFIG_CMDLINE;
+#endif
+
+
struct addr_range {
unsigned long addr;
unsigned long size;
@@ -204,6 +217,19 @@ static int is_elf32(void *hdr)
return 1;
}
+void export_cmdline(void* chosen_handle)
+{
+#ifdef CONFIG_CMDLINE
+ int len;
+ char cmdline[COMMAND_LINE_SIZE];
+ len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline));
+ if ((len <= 0 || cmdline[0] == 0) && builtin_cmdline[0]) {
+ setprop(chosen_handle, "bootargs", builtin_cmdline,
+ strlen(builtin_cmdline)+1);
+ }
+#endif /* CONFIG_CMDLINE */
+}
+
void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
{
int len;
@@ -289,6 +315,8 @@ void start(unsigned long a1, unsigned lo
memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
}
+ export_cmdline(chosen_handle);
+
/* Skip over the ELF header */
#ifdef DEBUG
printf("... skipping 0x%lx bytes of ELF header\n\r",
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
index 3e2ddd4..f613092 100644
--- a/arch/powerpc/boot/prom.h
+++ b/arch/powerpc/boot/prom.h
@@ -31,4 +31,10 @@ static inline int getprop(void *phandle,
return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
}
+static inline int setprop(void *phandle, const char *name,
+ void *buf, int buflen)
+{
+ return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
+
#endif /* _PPC_BOOT_PROM_H_ */
--
1.1.4.g0b63-dirty
^ permalink raw reply related
* Re: [PATCH] Provide mechanism for editing builtin command-line in zImage binary.
From: Michal Ostrowski @ 2006-05-30 2:27 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <11489544631499-git-send-email-mostrows@watson.ibm.com>
For reference, below is a shell script I use to edit the command-line
embedded in a zImage.
--
Michal Ostrowski <mostrows@watson.ibm.com>
#!/bin/bash
#
# Copyright (C) 2006 Michal Ostrowski <mostrows@watson.ibm.com>, IBM Corp.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
usage(){
echo 'set_builtin_cmdline [--cmd <file>] <input_obj> [<output_obj>]'
echo ' Sets the builtin command line embedded in an object file.'
echo
echo ' If <output_obj> is not specified, <input_obj> is modified'
echo ' in place.'
echo ' If --cmd <file> argument is present contents of embedded'
echo ' command line will be copied from <file>, otherwise from stdin.'
exit 1
}
cmd_file=
while case "$#" in 0) break ;; esac
do
case "$1" in
--cmd)
case "$#" in
1)
usage ;;
*)
cmd_file="$2";
shift;;
esac;;
*)
set x "$@"
shift
break ;;
esac
shift
done
if [ "$#" -lt 1 ]; then
echo "No input object specified." ;
usage;
fi
if [ "$#" -gt 2 ]; then
echo "Unrecognized arguments: $@";
usage;
fi
infile=$1
shift;
if [ ! -r "$infile" ] ; then
echo "Can't read '$infile'.";
usage;
fi
if [ "$#" -eq 0 ] ; then
outfile=$infile;
else
outfile=$1;
if ! cp $infile $outfile ; then
echo "Can't create output: '$outfile' $?"
usage;
fi
shift;
fi
offset=$(objdump -h $infile | \
gawk -- '{if($2=="__builtin_cmdline") {print strtonum("0x" $6);}}')
size=$(objdump -h $infile | \
gawk -- '{if($2=="__builtin_cmdline") {print strtonum("0x" $3);}}')
if [ "$cmd_file" ] ; then
[ -r "$cmd_file" ] || (echo "Can't read '$cmd_file'." ; usage);
cmdline=$(cat $cmd_file);
else
cmdline=$(cat);
fi
if [ "x$offset" != "x" ] ; then
if [ "$offset" -ne 0 ] ; then
set -e
# Zero the destination buffer first
exec 2>/dev/null
dd if=/dev/zero of=$outfile bs=1 seek=$offset conv=notrunc count=$size
echo -n "$cmdline" | \
dd of=$outfile bs=1 seek=$offset conv=notrunc count=$size
exit $?
fi
fi
^ permalink raw reply
* Re: compact flash driver
From: John Wu @ 2006-05-31 3:18 UTC (permalink / raw)
To: KokHow Teh; +Cc: linuxppc-embedded
In-Reply-To: <OFC57CB4FF.BA62E59F-ON4825717D.0019F306@uk.marconicomms.com>
On Mon, 2006-05-29 at 12:45 +0800, KokHow Teh wrote:
>
> >Dear sir
> >Do you have compact flash card driver supported in u-boot.I need it.If
> ^^^^^^
> You have posted your question to the wrong list.
>
> >you don't have it .Can you tell me how the CF card initialize if you
> >know how to initialize it?
>
> Ask more specific question as to what hardware platform you are using.
> Specifically, which CF controller....
>
>
>
Hardware platform is dm320. Specifically is CF 3.0 memory mode.
^ permalink raw reply
* RE: [PATCH/2.6.17-rc4 4/10]Powerpc: Add tsi108 pic support
From: Zang Roy-r61911 @ 2006-05-30 3:28 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
Alexandre.Bounine
>
> On Wed, 2006-05-17 at 18:14 +0800, Zang Roy-r61911 wrote:
> > Add Tundra Semiconductor tsi108 host bridge interrupt
> controller support.
>
> It looks a bit like an hacked up MPIC... Is it different
> enough to justify a separate driver ? Or would it be possible
> to define a TSI108 flag to pass the current mpic driver and
> add the necessary bits to it ?
>
Tsi108 implementation of MPIC has many differences form the original one, the following
code implements it with mpic. Any comment? The following patch is just based on
my previous send out patches.
Integrate Tundra Semiconductor tsi108 host bridge interrupt controller
to mpic arch.
Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/Kconfig linux-2.6.17-rc4-hpc2/arch/powerpc/Kconfig
--- linux-2.6.17-rc4-tun/arch/powerpc/Kconfig 2006-05-28 20:15:21.000000000 -0400
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/Kconfig 2006-05-29 16:04:30.000000000 -0400
@@ -408,7 +408,8 @@ config U3_DART
default n
config MPIC
- depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP
+ depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP \
+ || MPC7448HPC2
bool
default y
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/configs/mpc7448_hpc2_defconfig linux-2.6.17-rc4-hpc2/arch/powerpc/configs/mpc7448_hpc2_defconfig
--- linux-2.6.17-rc4-tun/arch/powerpc/configs/mpc7448_hpc2_defconfig 2006-05-28 20:15:36.000000000 -0400
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/configs/mpc7448_hpc2_defconfig 2006-05-27 19:05:42.000000000 -0400
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.17-rc4
-# Tue May 23 11:29:48 2006
+# Sat May 27 18:45:55 2006
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -110,6 +110,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_PPC_ISERIES is not set
CONFIG_EMBEDDED6xx=y
# CONFIG_APUS is not set
+CONFIG_MPIC=y
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_PPC_MPC106 is not set
@@ -899,6 +900,7 @@ CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_FS is not set
# CONFIG_UNWIND_INFO is not set
# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
# CONFIG_PPC_EARLY_DEBUG_G5 is not set
# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/platforms/embedded6xx/Kconfig linux-2.6.17-rc4-hpc2/arch/powerpc/platforms/embedded6xx/Kconfig
--- linux-2.6.17-rc4-tun/arch/powerpc/platforms/embedded6xx/Kconfig 2006-05-28 20:15:36.000000000 -0400
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/platforms/embedded6xx/Kconfig 2006-05-29 15:55:13.000000000 -0400
@@ -79,6 +79,7 @@ config MPC7448HPC2
select TSI108_BRIDGE
select DEFAULT_UIMAGE
select PPC_UDBG_16550
+ select MPIC
help
Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
platform
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c linux-2.6.17-rc4-hpc2/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
--- linux-2.6.17-rc4-tun/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c 2006-05-28 20:15:36.000000000 -0400
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c 2006-05-29 15:52:59.000000000 -0400
@@ -43,7 +43,16 @@
#include <asm/reg.h>
#include <mm/mmu_decl.h>
#include "mpc7448_hpc2.h"
-#include <asm/tsi108_pic.h>
+#include <asm/tsi108_irq.h>
+#include <asm/mpic.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
#ifndef CONFIG_PCI
isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
@@ -53,6 +62,8 @@ pci_dram_offset = MPC7448_HPC2_PCI_MEM_O
extern int add_bridge(struct device_node *dev);
extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+extern void tsi108_pci_int_init(void);
+extern int tsi108_irq_cascade(struct pt_regs *regs, void *unused);
#ifdef TSI108_ETH
hw_info hw_info_table[TSI108_ETH_MAX_PORTS + 1] = {
@@ -76,10 +87,32 @@ hw_info hw_info_table[TSI108_ETH_MAX_POR
*/
static u_char mpc7448_hpc2_pic_initsenses[] __initdata = {
+ /* External on-board sources */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[0] XINT0 from FPGA */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[1] XINT1 from FPGA */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[2] PHY_INT from both GIGE */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[3] RESERVED */
+ /* Internal Tsi108/109 interrupt sources */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA0 */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA1 */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA2 */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA3 */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* UART0 */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* UART1 */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* I2C */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* GPIO */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* GIGE0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* GIGE1 */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* HLP */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* SDC */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Processor IF */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* PCI/X block */
};
/*
@@ -196,11 +229,42 @@ static void __init mpc7448_hpc2_setup_ar
*/
static void __init mpc7448_hpc2_init_IRQ(void)
{
+ struct mpic *mpic;
+ phys_addr_t mpic_paddr = 0;
+ struct device_node *tsi_pic;
+
+ tsi_pic = of_find_node_by_type(NULL, "open-pic");
+ if (tsi_pic) {
+ unsigned int size;
+ void *prop = get_property(tsi_pic, "reg", &size);
+ mpic_paddr = of_translate_address(tsi_pic, prop);
+ }
+
+ if (mpic_paddr == 0) {
+ printk("%s: No tsi108 PIC found !\n", __FUNCTION__);
+ return;
+ }
+
+ DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__,
+ (u32) mpic_paddr);
- tsi108_pic_init(mpc7448_hpc2_pic_initsenses);
+ mpic = mpic_alloc(mpic_paddr,
+ MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
+ 0, /* num_sources used */
+ TSI108_IRQ_BASE,
+ 0, /* num_sources used */
+ NR_IRQS - 4 /* XXXX */,
+ mpc7448_hpc2_pic_initsenses,
+ sizeof(mpc7448_hpc2_pic_initsenses), "Tsi108_PIC");
+
+ BUG_ON(mpic == NULL); /* XXXX */
+
+ mpic_init(mpic);
+ mpic_setup_cascade(IRQ_TSI108_PCI, tsi108_irq_cascade, mpic);
+ tsi108_pci_int_init();
/* Configure MPIC outputs to CPU0 */
- tsi108_pic_set_output(0, IRQ_SENSE_EDGE, IRQ_POLARITY_NEGATIVE);
+ tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
}
static void __init mpc7448_hpc2_map_io(void)
@@ -269,7 +333,7 @@ define_machine(mpc7448_hpc2){
.setup_arch = mpc7448_hpc2_setup_arch,
.init_IRQ = mpc7448_hpc2_init_IRQ,
.show_cpuinfo = mpc7448_hpc2_show_cpuinfo,
- .get_irq = tsi108_pic_get_irq,
+ .get_irq = mpic_get_irq,
.restart = mpc7448_hpc2_restart,
.calibrate_decr = generic_calibrate_decr,
.setup_io_mappings = mpc7448_hpc2_map_io,
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/sysdev/Makefile linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/Makefile
--- linux-2.6.17-rc4-tun/arch/powerpc/sysdev/Makefile 2006-05-28 20:12:58.000000000 -0400
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/Makefile 2006-05-29 16:06:23.000000000 -0400
@@ -8,4 +8,4 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_PPC_83xx) += ipic.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
-obj-$(CONFIG_TSI108_BRIDGE) += tsi108_common.o tsi108_pic.o
+obj-$(CONFIG_TSI108_BRIDGE) += tsi108_common.o tsi108_pci_int.o
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/sysdev/mpic.c linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/mpic.c
--- linux-2.6.17-rc4-tun/arch/powerpc/sysdev/mpic.c 2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/mpic.c 2006-05-29 16:07:03.000000000 -0400
@@ -81,7 +81,7 @@ static inline void _mpic_write(unsigned
static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
{
unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
- unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+ unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * MPIC_GREG_IPI_STRIDE);
if (mpic->flags & MPIC_BROKEN_IPI)
be = !be;
@@ -90,7 +90,7 @@ static inline u32 _mpic_ipi_read(struct
static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
{
- unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+ unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * MPIC_GREG_IPI_STRIDE);
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
}
@@ -393,7 +393,11 @@ static inline struct mpic * mpic_from_ir
static inline void mpic_eoi(struct mpic *mpic)
{
mpic_cpu_write(MPIC_CPU_EOI, 0);
+#ifndef CONFIG_TSI108_BRIDGE
(void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+#else
+ (void)mpic_cpu_read(MPIC_CPU_OUTPUT);
+#endif
}
#ifdef CONFIG_SMP
@@ -514,9 +518,26 @@ static void mpic_end_irq(unsigned int ir
}
#endif /* CONFIG_MPIC_BROKEN_U3 */
+#ifdef CONFIG_TSI108_BRIDGE
+ if ((irq_desc[irq].status & IRQ_LEVEL) != 0)
+#endif
mpic_eoi(mpic);
}
+#ifdef CONFIG_TSI108_BRIDGE
+static void mpic_ack_irq(unsigned int irq)
+{
+ struct mpic *mpic = mpic_from_irq(irq);
+
+#ifdef DEBUG_IRQ
+ DBG("%s: ack_irq: %d\n", mpic->name, irq);
+#endif
+
+ if ((irq_desc[irq].status & IRQ_LEVEL) == 0)
+ mpic_eoi(mpic);
+}
+#endif /* CONFIG_TSI108_BRIDGE */
+
#ifdef CONFIG_SMP
static void mpic_enable_ipi(unsigned int irq)
@@ -596,6 +617,9 @@ struct mpic * __init mpic_alloc(unsigned
mpic->hc_irq.enable = mpic_enable_irq;
mpic->hc_irq.disable = mpic_disable_irq;
mpic->hc_irq.end = mpic_end_irq;
+#ifdef CONFIG_TSI108_BRIDGE
+ mpic->hc_irq.ack = mpic_ack_irq;
+#endif
if (flags & MPIC_PRIMARY)
mpic->hc_irq.set_affinity = mpic_set_affinity;
#ifdef CONFIG_SMP
@@ -955,8 +979,13 @@ void mpic_send_ipi(unsigned int ipi_no,
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
#endif
+#ifndef CONFIG_TSI108_BRIDGE
mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
+#else /* CONFIG_TSI108_BRIDGE */
+ mpic_write(mpic->gregs, MPIC_CPU_IPI_DISPATCH,
+ mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
+#endif /* !CONFIG_TSI108_BRIDGE */
}
int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
@@ -972,11 +1001,20 @@ int mpic_get_one_irq(struct mpic *mpic,
DBG("%s: cascading ...\n", mpic->name);
#endif
irq = mpic->cascade(regs, mpic->cascade_data);
+#ifdef DEBUG_LOW
+ DBG("%s: cascaded irq: %d\n", mpic->name, irq);
+#endif
+#ifndef CONFIG_TSI108_BRIDGE
mpic_eoi(mpic);
+#endif
return irq;
}
- if (unlikely(irq == MPIC_VEC_SPURRIOUS))
+ if (unlikely(irq == MPIC_VEC_SPURRIOUS)) {
+#ifdef CONFIG_TSI108_BRIDGE
+ mpic_eoi(mpic);
+#endif
return -1;
+ }
if (irq < MPIC_VEC_IPI_0) {
#ifdef DEBUG_IRQ
DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/sysdev/tsi108_common.c linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/tsi108_common.c
--- linux-2.6.17-rc4-tun/arch/powerpc/sysdev/tsi108_common.c 2006-05-28 20:12:58.000000000 -0400
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/tsi108_common.c 2006-05-29 16:08:52.000000000 -0400
@@ -90,9 +90,13 @@ tsi108_direct_write_config(struct pci_bu
{
volatile unsigned char *cfg_addr;
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfunc))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
devfunc, offset) |
- (offset & 0x03));
+ (offset & 0x03));
#ifdef TSI108_PCI_DEBUG
printk("PCI CFG write : ");
@@ -172,6 +176,10 @@ tsi108_direct_read_config(struct pci_bus
volatile unsigned char *cfg_addr;
u32 temp;
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
devfn,
offset) | (offset &
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/sysdev/tsi108_pci_int.c linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/tsi108_pci_int.c
--- linux-2.6.17-rc4-tun/arch/powerpc/sysdev/tsi108_pci_int.c 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/tsi108_pci_int.c 2006-05-29 16:09:04.000000000 -0400
@@ -0,0 +1,219 @@
+/*
+ * (C) Copyright 2005 Tundra Semiconductor Corp.
+ * Alex Bounine, <alexandreb@tundra.com).
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Tsi108 PCI Interrupt Handling (cascaded to MPIC)
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/hardirq.h>
+#include <asm/machdep.h>
+
+#include <asm/tsi108.h>
+#include <asm/tsi108_irq.h>
+
+#undef DEBUG
+#undef DBG_TSI108_INTERRUPT
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+extern u32 get_vir_csrbase(void);
+extern u32 tsi108_read_reg(u32 reg_offset);
+extern void tsi108_write_reg(u32 reg_offset, u32 val);
+
+/*
+ * Low level utility functions
+ */
+
+static void tsi108_pci_int_mask(u_int irq)
+{
+ u_int irp_cfg;
+ int int_line = (irq - IRQ_PCI_INTAD_BASE);
+
+ irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+ mb();
+ irp_cfg |= (1 << int_line); /* INTx_DIR = output */
+ irp_cfg &= ~(3 << (8 + (int_line * 2))); /* INTx_TYPE = unused */
+ tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
+ mb();
+ irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+}
+
+static void tsi108_pci_int_unmask(u_int irq)
+{
+ u_int irp_cfg;
+ int int_line = (irq - IRQ_PCI_INTAD_BASE);
+
+ irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+ mb();
+ irp_cfg &= ~(1 << int_line);
+ irp_cfg |= (3 << (8 + (int_line * 2)));
+ tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
+ mb();
+}
+
+static void init_pci_source(void)
+{
+ tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,
+ 0x0000ff00);
+ tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
+ 0x00400000);
+ mb();
+}
+
+static inline int get_pci_source(void)
+{
+ u_int temp = 0;
+ int irq = -1;
+ int i;
+ u_int pci_irp_stat;
+ static int mask = 0;
+
+ /* Read PCI/X block interrupt status register */
+ pci_irp_stat = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
+ mb();
+
+ if (pci_irp_stat & TSI108_PCI_IRP_STAT_P_INT) {
+ /* Process Interrupt from PCI bus INTA# - INTD# lines */
+ temp =
+ tsi108_read_reg(TSI108_PCI_OFFSET +
+ TSI108_PCI_IRP_INTAD) & 0xf;
+ mb();
+ for (i = 0; i < 4; i++, mask++) {
+ if (temp & (1 << mask % 4)) {
+ irq = IRQ_PCI_INTA + mask % 4;
+ mask++;
+ break;
+ }
+ }
+ }
+#ifdef DBG_TSI108_INTERRUPT
+ else {
+ printk("TSI108_PIC: error in TSI108_PCI_IRP_STAT\n");
+ pci_irp_stat =
+ tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
+ temp =
+ tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_INTAD);
+ mb();
+ printk(">> stat=0x%08x intad=0x%08x ", pci_irp_stat, temp);
+ temp =
+ tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+ mb();
+ printk("cfg_ctl=0x%08x ", temp);
+ temp =
+ tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+ mb();
+ printk("irp_enable=0x%08x\n", temp);
+ }
+#endif /* DBG_TSI108_INTERRUPT */
+
+ return irq;
+}
+
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+static void tsi108_pci_irq_enable(u_int irq)
+{
+ tsi108_pci_int_unmask(irq);
+}
+
+static void tsi108_pci_irq_disable(u_int irq)
+{
+ tsi108_pci_int_mask(irq);
+}
+
+static void tsi108_pci_irq_ack(u_int irq)
+{
+ tsi108_pci_int_mask(irq);
+}
+
+static void tsi108_pci_irq_end(u_int irq)
+{
+ /* Signal EOI to the Tsi108 interrupt controller. */
+ irq_desc[IRQ_TSI108_PCI].handler->end(IRQ_TSI108_PCI);
+ tsi108_pci_int_unmask(irq);
+}
+
+/*
+ * Interrupt controller descriptor for cascaded PCI interrupt controller.
+ */
+
+struct hw_interrupt_type tsi108_pci_irq = {
+ .typename = "tsi108_PCI_int",
+ .enable = tsi108_pci_irq_enable,
+ .disable = tsi108_pci_irq_disable,
+ .ack = tsi108_pci_irq_ack,
+ .end = tsi108_pci_irq_end,
+};
+
+/*
+ * Exported functions
+ */
+
+/*
+ * The Tsi108 PCI interrupts initialization routine.
+ *
+ * The INTA# - INTD# interrupts on the PCI bus are reported by the PCI block
+ * to the MPIC using single interrupt source (IRQ_TSI108_PCI). Therefore the
+ * PCI block has to be treated as a cascaded interrupt controller connected
+ * to the MPIC.
+ */
+
+void __init tsi108_pci_int_init(void)
+{
+ u_int i;
+
+ DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
+
+ for (i = 0; i < NUM_PCI_IRQS; i++) {
+ irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq;
+ irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
+ }
+
+ init_pci_source();
+}
+
+int tsi108_irq_cascade(struct pt_regs *regs, void *unused)
+{
+ return get_pci_source();
+}
diff -pNur -x project.pj linux-2.6.17-rc4-tun/arch/powerpc/sysdev/tsi108_pic.c linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/tsi108_pic.c
--- linux-2.6.17-rc4-tun/arch/powerpc/sysdev/tsi108_pic.c 2006-05-28 20:13:07.000000000 -0400
+++ linux-2.6.17-rc4-hpc2/arch/powerpc/sysdev/tsi108_pic.c 1969-12-31 19:00:00.000000000 -0500
@@ -1,813 +0,0 @@
-/*
- * (C) Copyright 2005 Tundra Semiconductor Corp.
- * Alex Bounine, <alexandreb@tundra.com).
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-/*
- * Tsi108 Interrupt Controller Handling
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/sysdev.h>
-#include <asm/ptrace.h>
-#include <asm/signal.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/hardirq.h>
-#include <asm/machdep.h>
-
-#include <asm/tsi108.h>
-#include <asm/tsi108_irq.h>
-#include <asm/tsi108_pic.h>
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt...) do { printk(fmt); } while(0)
-#else
-#define DBG(fmt...) do { } while(0)
-#endif
-
-extern u32 get_vir_csrbase(void);
-extern u32 tsi108_read_reg(u32 reg_offset);
-extern void tsi108_write_reg(u32 reg_offset, u32 val);
-
-static phys_addr_t tsi108_pic_phy_addr;
-static u32 tsi108_pic_vir_addr;
-
-static int tsi108_pic_cascade_irq = -1;
-static int (*tsi108_pic_cascade_fn) (struct pt_regs *);
-
-/* Global Operations */
-static void tsi108_pic_set_task_priority(u_int pri);
-static void tsi108_pic_set_spurious(u_int vector);
-void tsi108_pic_mask_all(void);
-
-/* Timer Interrupts */
-static void tsi108_pic_inittimer(u_int timer, u_int pri, u_int vector);
-static void tsi108_pic_maptimer(u_int timer, u_int cpumask);
-
-/* Interrupt Sources */
-static void tsi108_pic_enable_irq(u_int irq);
-static void tsi108_pic_disable_irq(u_int irq);
-static void tsi108_pic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
- int is_level);
-static void tsi108_pic_mapirq(u_int irq, u_int cpumask, u_int keepmask);
-static void init_pci_source(void);
-static inline int get_pci_source(int vector);
-int tsi108_pic_set_irq_sense(int irq, int pol, int sense);
-
-/*
- * tsi108_pic interface routines
- */
-static void tsi108_pic_end_irq(unsigned int irq_nr);
-static void tsi108_pic_ack_irq(unsigned int irq_nr);
-void tsi108_pic_set_affinity(unsigned int irq_nr, unsigned long cpumask);
-
-static struct hw_interrupt_type tsi108_pic_irq = {
- "tsi108_pic",
- NULL,
- NULL,
- tsi108_pic_enable_irq,
- tsi108_pic_disable_irq,
- tsi108_pic_ack_irq,
- tsi108_pic_end_irq,
- NULL
-};
-
-static void tsi108_pci_irq_enable(u_int irq);
-static void tsi108_pci_irq_disable(u_int irq);
-static void tsi108_pci_irq_ack(u_int irq);
-static void tsi108_pci_irq_end(u_int irq);
-
-static struct hw_interrupt_type tsi108_pci_irq = {
- "tsi108_PCI_int",
- NULL,
- NULL,
- tsi108_pci_irq_enable,
- tsi108_pci_irq_disable,
- tsi108_pci_irq_ack,
- tsi108_pci_irq_end,
- NULL
-};
-
-#ifdef DBG_TSI108_INTERRUPT
-#define ASSERT(expr) if (!(expr)) { \
- printk("tsi108pic :" \
- "assertion failed! %s[%d]: %s\n", \
- __FUNCTION__, __LINE__, #expr); \
- dump_stack(); \
- }
-#else
-#define ASSERT(expr) do {} while (0)
-#endif
-
-static inline u_int get_vector_offset(u_int irq)
-{
- u_int offset;
-
- if (irq < TSI108_IRQ_BASE || irq >= IRQ_PCI_INTAD_BASE)
- return 0;
-
- if (irq < IRQ_TSI108_MBOX0)
- offset = TSI108_INT_IVPR(irq - TSI108_IRQ_BASE);
- else if (irq < IRQ_TSI108_DBELL0)
- offset = TSI108_INT_MBVPR(irq - IRQ_TSI108_MBOX0);
- else if (irq < IRQ_TSI108_TIMER0)
- offset = TSI108_INT_DVPR(irq - IRQ_TSI108_DBELL0);
- else
- offset = TSI108_INT_GTVPR(irq - IRQ_TSI108_TIMER0);
-
- return offset;
-}
-
-static inline u_int tsi108_pic_read_reg(u_int reg_offset)
-{
- return in_be32((volatile u32 *)(tsi108_pic_vir_addr + reg_offset));
-}
-
-static inline void tsi108_pic_write_reg(u_int reg_offset, u_int val)
-{
- out_be32((volatile u32 *)(tsi108_pic_vir_addr + reg_offset), val);
-}
-
-void tsi108_pic_reset(void)
-{
- tsi108_pic_write_reg(TSI108_INT_GCR, TSI108PIC_INT_GCR_R);
- while (tsi108_pic_read_reg(TSI108_INT_GCR) & TSI108PIC_INT_GCR_R)
- mb();
-}
-
-void tsi108_pic_set_output(int dest_num, u32 sense, u32 polarity)
-{
- u32 temp = 0;
- temp |= (IRQ_SENSE_LEVEL == sense) ?
- (TSI108PIC_INT_CSR_S_LEVEL) : (TSI108PIC_INT_CSR_S_EDGE);
- temp |= (IRQ_POLARITY_POSITIVE == polarity) ?
- (TSI108PIC_INT_CSR_P_HIGH) : (TSI108PIC_INT_CSR_P_LOW);
- tsi108_pic_write_reg(TSI108_INT_CSR(dest_num), temp);
- mb();
-}
-
-int tsi108_pic_source_cfg(int src_num, /* interrupt source number */
- u32 sense, /* interrupt source Sense */
- u32 polarity, /* interrupt source Polarity */
- TSI108_IRQ_MODE mode /* interrupt delivery Mode */
- )
-{
- unsigned temp;
-
- temp = tsi108_pic_read_reg(TSI108_INT_IVPR(src_num));
-
- if (temp & TSI108PIC_ACTIVITY) /* error if source is active */
- return -1;
-
- if (0 == (temp & TSI108PIC_MASK)) {
- temp |= TSI108PIC_MASK; /* mask IRQ prior making changes */
- tsi108_pic_write_reg(TSI108_INT_IVPR(src_num), temp);
- }
-
- temp &= ~(TSI108PIC_INT_IVPR_MODE |
- TSI108PIC_INT_IVPR_S | TSI108PIC_INT_IVPR_P);
-
- temp |= (IRQ_SENSE_LEVEL == sense) ?
- (TSI108PIC_INT_CSR_S_LEVEL) : (TSI108PIC_INT_CSR_S_EDGE);
- temp |= (IRQ_POLARITY_POSITIVE == polarity) ?
- (TSI108PIC_INT_CSR_P_HIGH) : (TSI108PIC_INT_CSR_P_LOW);
-
- tsi108_pic_write_reg(TSI108_INT_IVPR(src_num),
- TSI108PIC_MASK | (mode << 29) | temp);
- return (0);
-}
-
-int tsi108_pic_set_vector(int src_num, /* source number */
- int vect, /* vector number */
- int prio /* interrupt source priority */
- )
-{
- unsigned tmp;
-
- tmp = tsi108_pic_read_reg(TSI108_INT_IVPR(src_num));
-
- if (tmp & TSI108PIC_ACTIVITY) /* error if source is active */
- return -1;
-
- if (0 == (tmp & TSI108PIC_MASK)) {
- tmp |= TSI108PIC_MASK; /* mask IRQ prior making changes */
- tsi108_pic_write_reg(TSI108_INT_IVPR(src_num), tmp);
- }
-
- /* clear bits to be changed */
- tmp &= ~(TSI108PIC_VECTOR_MASK | TSI108PIC_PRIORITY_MASK);
-
- tmp |= (prio << 16) | vect;
- tsi108_pic_write_reg(TSI108_INT_IVPR(src_num), tmp);
- return 0;
-}
-
-void tsi108_pic_mask_all()
-{
- int i;
- unsigned int vp;
-
- /* Mask all external and internal interrupt sources */
- for (i = 0; i < TSI108PIC_MAX_SOURCES; i++) {
- vp = tsi108_pic_read_reg(TSI108_INT_IVPR(i));
- tsi108_pic_write_reg(TSI108_INT_IVPR(i), vp | TSI108PIC_MASK);
- mb();
-
- /* Make sure that irq is masked */
- do {
- vp = tsi108_pic_read_reg(TSI108_INT_IVPR(i));
- } while ((vp & TSI108PIC_ACTIVITY) && !(vp & TSI108PIC_MASK));
- }
-
- /* Mask all timer interrupts */
- for (i = 0; i < TSI108PIC_NUM_TIMERS; i++) {
- vp = tsi108_pic_read_reg(TSI108_INT_GTVPR(i));
- tsi108_pic_write_reg(TSI108_INT_GTVPR(i), vp | TSI108PIC_MASK);
- mb();
-
- do {
- vp = tsi108_pic_read_reg(TSI108_INT_GTVPR(i));
- } while ((vp & TSI108PIC_ACTIVITY) && !(vp & TSI108PIC_MASK));
- }
-
- /* Mask all doorbell interrupts */
- for (i = 0; i < TSI108PIC_NUM_DBELLS; i++) {
- vp = tsi108_pic_read_reg(TSI108_INT_DVPR(i));
- tsi108_pic_write_reg(TSI108_INT_IVPR(i), vp | TSI108PIC_MASK);
- mb();
-
- do {
- vp = tsi108_pic_read_reg(TSI108_INT_DVPR(i));
- } while ((vp & TSI108PIC_ACTIVITY) && !(vp & TSI108PIC_MASK));
- }
-
- /* Mask all mailbox interrupts */
- for (i = 0; i < 4; i++) {
- vp = tsi108_pic_read_reg(TSI108_INT_MBVPR(i));
- tsi108_pic_write_reg(TSI108_INT_MBVPR(i), vp | TSI108PIC_MASK);
- mb();
-
- do {
- vp = tsi108_pic_read_reg(TSI108_INT_MBVPR(i));
- } while ((vp & TSI108PIC_ACTIVITY) && !(vp & TSI108PIC_MASK));
- }
-}
-
-/*
- * The Tsi108 PC initialization routine.
- * A caller routine (usually from platform-specific code has to provide
- * sense/polarity configuration information for four external interrupt
- * sources INT0 - INT3. This should be done in form of four-byte array
- * (one byte per source ) that contains combination of sensitivity/polarity
- * flags defined in asm-ppc/irq.h.
- *
- * Example of PIC initialization call is shown below:
- *
- * u_char your_board_pic_initsenses[] __initdata = {
- * (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), // INT[0]
- * (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), // INT[1]
- * (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), // INT[2]
- * (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE) // INT[3]
- * };
- *
- * tsi108_pic_init(your_board_pic_initsenses);
- */
-
-void __init tsi108_pic_init(u_char * board_init_senses)
-{
- u_int i;
- u32 sense;
-
- struct device_node *tsi_pic;
- tsi_pic = of_find_node_by_type(NULL, "open-pic");
- if (tsi_pic) {
- unsigned int size;
- void *prop = get_property(tsi_pic, "reg", &size);
- tsi108_pic_phy_addr = of_translate_address(tsi_pic, prop);
- }
-
- DBG("%s: Tsi108 pic phy addr = 0x%x\n", __FUNCTION__,
- (u32) tsi108_pic_phy_addr);
- if (tsi108_pic_phy_addr == 0) {
- printk("No tsi108 PIC found !\n");
- return;
- }
-
- tsi108_pic_vir_addr = (u32) ioremap(tsi108_pic_phy_addr, 0x400);
-
- tsi108_pic_reset();
-
- if (ppc_md.progress)
- ppc_md.progress("tsi108_pic_init: enter", 0x122);
-
- /* Initialize timer interrupts */
- for (i = 0; i < TSI108PIC_NUM_TIMERS; i++) {
- /* Disabled, Priority 0 */
- tsi108_pic_inittimer(i, 0, IRQ_TSI108_TIMER0 + i);
- /* No processor */
- tsi108_pic_maptimer(i, 0);
- }
-
- /* Init board-specific external sources */
- for (i = 0; i < 4; i++) {
- sense = board_init_senses[i];
-
- if (sense & IRQ_SENSE_MASK)
- irq_desc[TSI108_IRQ(i)].status |= IRQ_LEVEL;
-
- /* Enabled, Priority 8 */
- tsi108_pic_initirq(i, 8, TSI108_IRQ(i),
- (sense & IRQ_POLARITY_MASK),
- (sense & IRQ_SENSE_MASK));
- /* Map to CPU #0 */
- tsi108_pic_mapirq(TSI108_IRQ(i), 1 << 0, 0);
- }
-
- /* Init remaining internal sources. */
- for (; i < TSI108PIC_MAX_SOURCES; i++) {
- /* Disabled, Priority 8, by default - Positive Edge */
- tsi108_pic_initirq(i, 8, TSI108_IRQ(i),
- IRQ_POLARITY_POSITIVE, IRQ_SENSE_EDGE);
- /* Map to CPU #0 */
- tsi108_pic_mapirq(TSI108_IRQ(i), (1 << 0), 0);
- }
-
- /*
- * Change sensitivity to level for sources that require it.
- */
-
- irq_desc[IRQ_TSI108_GIGE0].status |= IRQ_LEVEL;
- irq_desc[IRQ_TSI108_GIGE1].status |= IRQ_LEVEL;
- irq_desc[IRQ_TSI108_PCI].status |= IRQ_LEVEL;
-
- /* Init descriptors */
- for (i = 0; i < TSI108PIC_MAX_SOURCES; i++)
- irq_desc[i + TSI108_IRQ_BASE].handler = &tsi108_pic_irq;
-
- for (i = 0; i < NUM_PCI_IRQS; i++) {
- irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq;
- irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
- }
-
- /* Initialize the spurious interrupt */
- tsi108_pic_set_spurious(TSI108_IRQ_SPURIOUS);
- tsi108_pic_set_task_priority(0);
-
- init_pci_source();
- tsi108_pic_enable_irq(IRQ_TSI108_PCI);
-
- i = tsi108_pic_read_reg(TSI108_INT_VECTOR(0));
- tsi108_pic_write_reg(TSI108_INT_EOI(0), 0);
-
- if (ppc_md.progress)
- ppc_md.progress("tsi108_pic_init: exit", 0x222);
-}
-
-/*
- * Find out the current interrupt
- */
-static u_int tsi108_pic_get_vect(void)
-{
- u_int vec;
-
- vec = tsi108_pic_read_reg(TSI108_INT_VECTOR(0)) & TSI108PIC_VECTOR_MASK;
-
-#ifdef DBG_TSI108_INTERRUPT
- if (vec == TSI108_IRQ_SPURIOUS)
- printk("TSI108: SPURIOUS vec=0x%08x\n", vec);
- else
- printk("TSI108: read vec=0x%08x\n", vec);
-#endif
- return (vec);
-}
-
-static inline void tsi108_pic_eoi(void)
-{
- tsi108_pic_write_reg(TSI108_INT_EOI(0), 0);
- mb();
-}
-
-static void __init tsi108_pic_set_task_priority(u_int pri)
-{
- ASSERT(pri >= 0 && pri < TSI108PIC_NUM_PRI);
-
- tsi108_pic_write_reg(TSI108_INT_TASKP(0),
- pri & TSI108PIC_INT_TASKP_TASKP);
- mb();
-}
-
-static void tsi108_pic_set_spurious(u_int vec)
-{
- ASSERT(vec == TSI108_IRQ_SPURIOUS);
- tsi108_pic_write_reg(TSI108_INT_SVR, vec);
- mb();
-}
-
-#ifdef CONFIG_SMP
-/*
- * Convert a cpu mask from logical to physical cpu numbers.
- */
-static inline u32 physmask(u32 cpumask)
-{
- int i;
- u32 mask = 0;
-
- for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
- if (cpu_online(i))
- mask |= (cpumask & 1) << smp_hw_index[i];
- return mask;
-}
-#else
-#define physmask(cpumask) (cpumask)
-#endif
-
-/*
- * Initialize a timer interrupt (and disable it)
- *
- * timer: timer number
- * pri: interrupt source priority
- * vec: the vector it will produce
- */
-static void __init tsi108_pic_inittimer(u_int timer, u_int pri, u_int vec)
-{
- unsigned int gtvpr;
-
- ASSERT(timer >= 0 && timer < TSI108PIC_NUM_TIMERS);
- ASSERT(pri >= 0 && pri < TSI108PIC_NUM_PRI);
- ASSERT(vec >= 0 && vec < TSI108PIC_NUM_VECTORS);
-
- gtvpr = tsi108_pic_read_reg(TSI108_INT_GTVPR(timer));
- gtvpr &= ~(TSI108PIC_PRIORITY_MASK | TSI108PIC_VECTOR_MASK);
- gtvpr |= (pri << 16) | vec;
- tsi108_pic_write_reg(TSI108_INT_GTVPR(timer), gtvpr | TSI108PIC_MASK);
- mb();
-}
-
-/*
- * Map a timer interrupt to one or more CPUs
- */
-static void __init tsi108_pic_maptimer(u_int timer, u_int cpumask)
-{
- ASSERT(timer >= 0 && timer < TSI108PIC_NUM_TIMERS);
-
- tsi108_pic_write_reg(TSI108_INT_GTDR(timer), physmask(cpumask));
- mb();
-}
-
-/*
- * Initalize the interrupt source which will generate an NMI.
- * This raises the interrupt's priority from 8 to 9.
- *
- * irq: The logical IRQ which generates an NMI.
- */
-void __init tsi108_pic_init_nmi_irq(u_int irq)
-{
- u_int offset = get_vector_offset(irq);
- u_int vpr = tsi108_pic_read_reg(offset);
- vpr &= ~TSI108PIC_PRIORITY_MASK;
- tsi108_pic_write_reg(offset, vpr | (9 << 16));
- mb();
-}
-
-/*
- *
- * All functions below take an offset'ed irq argument
- *
- */
-
-/*
- * Hookup a cascade to the tsi108 PIC.
- */
-void __init
-tsi108_pic_hookup_cascade(u_int irq, char *name,
- int (*cascade_fn) (struct pt_regs *))
-{
- tsi108_pic_cascade_irq = irq;
- tsi108_pic_cascade_fn = cascade_fn;
- if (request_irq(irq, no_action, SA_INTERRUPT, name, NULL))
- printk("Unable to get Tsi108 PIC IRQ %d for cascade\n",
- irq - TSI108_IRQ_BASE);
-}
-
-/*
- * Enable/disable an external interrupt source
- *
- * Externally called, irq is an offseted system-wide interrupt number
- */
-static void tsi108_pic_enable_irq(u_int irq)
-{
- u32 offset = get_vector_offset(irq);
- u32 vpr = tsi108_pic_read_reg(offset);
-
- /*
- * Undo sensitivity change (see tsi108_pic_disable_irq())
- */
- if (irq_desc[irq].status & IRQ_LEVEL)
- vpr |= TSI108PIC_INT_IVPR_S;
-
- tsi108_pic_write_reg(offset, vpr & ~TSI108PIC_MASK);
- mb();
-}
-
-static void tsi108_pic_disable_irq(u_int irq)
-{
- u32 offset = get_vector_offset(irq);
- u32 vpr = tsi108_pic_read_reg(offset);
-
- /*
- * Switch level interrupt to edge sensitivity to avoid generation
- * of spurious interrupt request. See design note in Tsi108 PIC
- * section of Tsi108 manual.
- */
- if (irq_desc[irq].status & IRQ_LEVEL)
- vpr &= ~TSI108PIC_INT_IVPR_S;
-
- tsi108_pic_write_reg(offset, vpr | TSI108PIC_MASK);
- mb();
- vpr = tsi108_pic_read_reg(offset);
- if (!(vpr & TSI108PIC_MASK))
- printk("TSI108_PIC: Error - Unable disable IRQ %d\n", irq);
-}
-
-/*
- * Initialize an interrupt source (and disable it!)
- *
- * irq: Tsi108 PIC interrupt source number
- * pri: interrupt source priority
- * vec: the vector it will produce
- * pol: polarity (1 for positive, 0 for negative)
- * sense: 1 for level, 0 for edge
- */
-static void __init
-tsi108_pic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
-{
- unsigned int ivpr;
-
- ivpr = TSI108PIC_MASK | (pri << 16) | vec;
- ivpr |= (IRQ_SENSE_LEVEL == sense) ?
- TSI108PIC_INT_IVPR_S_LEVEL : TSI108PIC_INT_IVPR_S_EDGE;
- ivpr |= (IRQ_POLARITY_POSITIVE == pol) ?
- TSI108PIC_INT_IVPR_P_HIGH : TSI108PIC_INT_IVPR_P_LOW;
- tsi108_pic_write_reg(TSI108_INT_IVPR(irq), ivpr);
- mb();
-}
-
-int tsi108_pic_set_irq_sense(int irq, /* PIC source number */
- int pol, /* interrupt source polarity */
- int sense /* interrupt source sense */
- )
-{
- unsigned int ivpr;
-
- ivpr = tsi108_pic_read_reg(TSI108_INT_IVPR(irq));
-
- if (ivpr & TSI108PIC_ACTIVITY) /* error if source is active */
- return -1;
-
- if (0 == (ivpr & TSI108PIC_MASK)) {
- ivpr |= TSI108PIC_MASK; /* mask IRQ prior making changes */
- tsi108_pic_write_reg(TSI108_INT_IVPR(irq), ivpr);
- }
-
- /* clear bits to be changed */
- ivpr &= ~(TSI108PIC_INT_IVPR_P | TSI108PIC_INT_IVPR_S);
-
- ivpr |= (IRQ_SENSE_LEVEL == sense) ?
- TSI108PIC_INT_IVPR_S_LEVEL : TSI108PIC_INT_IVPR_S_EDGE;
- ivpr |= (IRQ_POLARITY_POSITIVE == pol) ?
- TSI108PIC_INT_IVPR_P_HIGH : TSI108PIC_INT_IVPR_P_LOW;
-
- tsi108_pic_write_reg(TSI108_INT_IVPR(irq), ivpr);
- return 0;
-}
-
-/*
- * Map an interrupt source to one or more CPUs
- */
-static void tsi108_pic_mapirq(u_int irq, u_int physmask, u_int keepmask)
-{
- u_int offset = get_vector_offset(irq);
-
- if (0 == offset)
- return;
- if (keepmask != 0)
- physmask |= tsi108_pic_read_reg(offset + 4);
- tsi108_pic_write_reg(offset + 4, physmask);
- mb();
-}
-
-/* No spinlocks, should not be necessary with the Tsi108 PIC
- * (1 register = 1 interrupt and we have the desc lock).
- */
-static void tsi108_pic_ack_irq(unsigned int irq_nr)
-{
- if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
- tsi108_pic_eoi();
-}
-
-static void tsi108_pic_end_irq(unsigned int irq_nr)
-{
- if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
- tsi108_pic_eoi();
-}
-
-void tsi108_pic_set_affinity(unsigned int irq_nr, unsigned long cpumask)
-{
- tsi108_pic_mapirq(irq_nr, physmask(cpumask), 0);
-}
-
-int tsi108_pic_get_irq(struct pt_regs *regs)
-{
- int vector = tsi108_pic_get_vect();
-
- if (vector == TSI108_IRQ_SPURIOUS) {
- vector = -1;
- }
-
- if (vector == IRQ_TSI108_PCI) {
- vector = get_pci_source(vector);
- }
-
- if (vector == -1) {
- tsi108_pic_write_reg(TSI108_INT_EOI(0), 0);
- }
-
- return vector;
-}
-
-static void tsi108_pci_int_mask(u_int irq)
-{
- u_int irp_cfg;
- int int_line = (irq - IRQ_PCI_INTAD_BASE);
-
- irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
- mb();
- irp_cfg |= (1 << int_line); /* INTx_DIR = output */
- irp_cfg &= ~(3 << (8 + (int_line * 2))); /* INTx_TYPE = unused */
- tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
- mb();
- irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
-}
-
-static void tsi108_pci_int_unmask(u_int irq)
-{
- u_int irp_cfg;
- int int_line = (irq - IRQ_PCI_INTAD_BASE);
-
- irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
- mb();
- irp_cfg &= ~(1 << int_line);
- irp_cfg |= (3 << (8 + (int_line * 2)));
- tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
- mb();
-}
-
-static void tsi108_pci_irq_enable(u_int irq)
-{
- tsi108_pci_int_unmask(irq);
-}
-
-static void tsi108_pci_irq_disable(u_int irq)
-{
- tsi108_pci_int_mask(irq);
-}
-
-static void tsi108_pci_irq_ack(u_int irq)
-{
- tsi108_pci_int_mask(irq);
-}
-
-static void tsi108_pci_irq_end(u_int irq)
-{
- tsi108_pic_eoi(); /* eoi IRQ_TSI108_PCI */
- tsi108_pci_int_unmask(irq);
-}
-
-static inline int get_pci_source(int vector)
-{
- u_int temp = 0;
- int irq = -1;
- int i;
- u_int pci_irp_stat;
- static int mask = 0;
-
- /* Read PCI/X block interrupt status register */
- pci_irp_stat = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
- mb();
-
- if (pci_irp_stat & TSI108_PCI_IRP_STAT_P_INT) {
- /* Process Interrupt from PCI bus INTA# - INTD# lines */
- temp =
- tsi108_read_reg(TSI108_PCI_OFFSET +
- TSI108_PCI_IRP_INTAD) & 0xf;
- mb();
- for (i = 0; i < 4; i++, mask++) {
- if (temp & (1 << mask % 4)) {
- irq = IRQ_PCI_INTA + mask % 4;
- mask++;
- break;
- }
- }
- }
-#ifdef DBG_TSI108_INTERRUPT
- else {
- printk("TSI108_PIC: error in TSI108_PCI_IRP_STAT\n");
- pci_irp_stat =
- tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
- temp =
- tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_INTAD);
- mb();
- printk(">> stat=0x%08x intad=0x%08x ", pci_irp_stat, temp);
- temp =
- tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
- mb();
- printk("cfg_ctl=0x%08x ", temp);
- temp =
- tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
- mb();
- printk("irp_enable=0x%08x\n", temp);
- }
-#endif /* DBG_TSI108_INTERRUPT */
-
- return irq;
-}
-
-static void init_pci_source(void)
-{
- tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,
- 0x0000ff00);
- tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
- 0x00400000);
- mb();
-}
-
-static struct sysdev_class tsi108_pic_sysclass = {
- set_kset_name("tsi108_pic"),
-};
-
-static struct sys_device device_tsi108_pic = {
- .id = 0,
- .cls = &tsi108_pic_sysclass,
-};
-
-static struct sysdev_driver driver_tsi108_pic = {
-#ifdef CONFIG_PM /* FIXME: placeholder for future development */
- .suspend = &tsi108_pic_suspend,
- .resume = &tsi108_pic_resume,
-#endif /* CONFIG_PM */
-};
-
-static int __init init_tsi108_pic_sysfs(void)
-{
- int rc;
-
- if (!get_csrbase())
- return -ENODEV;
- printk(KERN_DEBUG "Registering tsi108_pic with sysfs...\n");
- rc = sysdev_class_register(&tsi108_pic_sysclass);
- if (rc) {
- printk(KERN_ERR "Failed registering tsi108_pic sys class\n");
- return -ENODEV;
- }
- rc = sysdev_register(&device_tsi108_pic);
- if (rc) {
- printk(KERN_ERR "Failed registering tsi108_pic sys device\n");
- return -ENODEV;
- }
- rc = sysdev_driver_register(&tsi108_pic_sysclass, &driver_tsi108_pic);
- if (rc) {
- printk(KERN_ERR "Failed registering tsi108_pic sys driver\n");
- return -ENODEV;
- }
- return 0;
-}
-
-subsys_initcall(init_tsi108_pic_sysfs);
diff -pNur -x project.pj linux-2.6.17-rc4-tun/include/asm-powerpc/mpic.h linux-2.6.17-rc4-hpc2/include/asm-powerpc/mpic.h
--- linux-2.6.17-rc4-tun/include/asm-powerpc/mpic.h 2006-03-20 00:53:29.000000000 -0500
+++ linux-2.6.17-rc4-hpc2/include/asm-powerpc/mpic.h 2006-05-29 16:11:03.000000000 -0400
@@ -4,6 +4,7 @@
#include <linux/irq.h>
+#ifndef CONFIG_TSI108_BRIDGE
/*
* Global registers
*/
@@ -37,6 +38,7 @@
#define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0
#define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0
#define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0
+#define MPIC_GREG_IPI_STRIDE 0x10
#define MPIC_GREG_SPURIOUS 0x000e0
#define MPIC_GREG_TIMER_FREQ 0x000f0
@@ -91,6 +93,87 @@
#define MPIC_VECPRI_SENSE_MASK 0x00400000
#define MPIC_IRQ_DESTINATION 0x00010
+#else /* CONFIG_TSI108_BRIDGE */
+
+/* Tsi108 implementation of MPIC has many differences form the original one */
+
+/*
+ * Global registers
+ */
+
+#define MPIC_GREG_BASE 0x00000
+
+#define MPIC_GREG_FEATURE_0 0x00000
+#define MPIC_GREG_FEATURE_LAST_SRC_MASK 0x07ff0000
+#define MPIC_GREG_FEATURE_LAST_SRC_SHIFT 16
+#define MPIC_GREG_FEATURE_LAST_CPU_MASK 0x00001f00
+#define MPIC_GREG_FEATURE_LAST_CPU_SHIFT 8
+#define MPIC_GREG_FEATURE_VERSION_MASK 0xff
+#define MPIC_GREG_GLOBAL_CONF_0 0x00004
+#define MPIC_GREG_GCONF_RESET 0x80000000
+#define MPIC_GREG_GCONF_8259_PTHROU_DIS 0x00000000
+#define MPIC_GREG_IPI_VECTOR_PRI_0 0x00204 /* Doorbell 0 */
+#define MPIC_GREG_IPI_VECTOR_PRI_1 0x00210 /* Doorbell 1 */
+#define MPIC_GREG_IPI_VECTOR_PRI_2 0x0021c /* Doorbell 2 */
+#define MPIC_GREG_IPI_VECTOR_PRI_3 0x00228 /* Doorbell 3 */
+#define MPIC_GREG_IPI_STRIDE 0x0c
+#define MPIC_GREG_SPURIOUS 0x00010
+#define MPIC_GREG_TIMER_FREQ 0x00014
+
+/*
+ * Timer registers
+ */
+#define MPIC_TIMER_BASE 0x0030
+#define MPIC_TIMER_STRIDE 0x10
+
+#define MPIC_TIMER_CURRENT_CNT 0x00000
+#define MPIC_TIMER_BASE_CNT 0x00004
+#define MPIC_TIMER_VECTOR_PRI 0x00008
+#define MPIC_TIMER_DESTINATION 0x0000c
+
+/*
+ * Per-Processor registers
+ */
+
+#define MPIC_CPU_THISBASE 0x00000
+#define MPIC_CPU_BASE 0x00300
+#define MPIC_CPU_STRIDE 0x00040
+
+#define MPIC_CPU_IPI_DISPATCH 0x00200
+#define MPIC_CPU_CURRENT_TASK_PRI 0x00000
+#define MPIC_CPU_TASKPRI_MASK 0x0000000f
+#define MPIC_CPU_INTACK 0x00004
+#define MPIC_CPU_EOI 0x00008
+#define MPIC_CPU_OUTPUT 0x0000c
+#define MPIC_OUTPUT_POLARITY_POSITIVE 0x00000001
+#define MPIC_OUTPUT_POLARITY_NEGATIVE 0x00000000
+#define MPIC_OUTPUT_POLARITY_MASK 0x00000001
+#define MPIC_OUTPUT_SENSE_LEVEL 0x00000002
+#define MPIC_OUTPUT_SENSE_EDGE 0x00000000
+#define MPIC_OUTPUT_SENSE_MASK 0x00000002
+
+/*
+ * Per-source registers
+ */
+
+#define MPIC_IRQ_BASE 0x00100
+#define MPIC_IRQ_STRIDE 0x00008
+#define MPIC_IRQ_VECTOR_PRI 0x00000
+#define MPIC_VECPRI_MASK 0x80000000
+#define MPIC_VECPRI_ACTIVITY 0x40000000 /* Read Only */
+#define MPIC_VECPRI_PRIORITY_MASK 0x000f0000
+#define MPIC_VECPRI_PRIORITY_SHIFT 16
+#define MPIC_VECPRI_VECTOR_MASK 0x000000ff
+#define MPIC_VECPRI_POLARITY_POSITIVE 0x01000000
+#define MPIC_VECPRI_POLARITY_NEGATIVE 0x00000000
+#define MPIC_VECPRI_POLARITY_MASK 0x01000000
+#define MPIC_VECPRI_SENSE_LEVEL 0x02000000
+#define MPIC_VECPRI_SENSE_EDGE 0x00000000
+#define MPIC_VECPRI_SENSE_MASK 0x02000000
+#define MPIC_IRQ_DESTINATION 0x00004
+
+#endif /* CONFIG_TSI108_BRIDGE */
+
#define MPIC_MAX_IRQ_SOURCES 2048
#define MPIC_MAX_CPUS 32
#define MPIC_MAX_ISU 32
diff -pNur -x project.pj linux-2.6.17-rc4-tun/include/asm-powerpc/tsi108_pic.h linux-2.6.17-rc4-hpc2/include/asm-powerpc/tsi108_pic.h
--- linux-2.6.17-rc4-tun/include/asm-powerpc/tsi108_pic.h 2006-05-28 20:13:07.000000000 -0400
+++ linux-2.6.17-rc4-hpc2/include/asm-powerpc/tsi108_pic.h 1969-12-31 19:00:00.000000000 -0500
@@ -1,232 +0,0 @@
-/*
- * (C) Copyright 2005 Tundra Semiconductor Corp.
- * Alex Bounine, <alexandreb@tundra.com).
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-/*
- * arch/ppc/syslib/tsi108_pic.h - Tsi108 Interrupt Controller definitions
- */
-
-#ifndef _LINUX_TSI108_PIC_H
-#define _LINUX_TSI108_PIC_H
-
-#include <asm/tsi108_irq.h>
-
-#ifdef __KERNEL__
-
-/*
- * Tsi108 PIC supports up to 24 interrupt sources and up to 4 processors
- */
-
-#define TSI108PIC_MAX_SOURCES 24
-#define TSI108PIC_MAX_PROCESSORS 4
-
-#define TSI108PIC_NUM_TIMERS 4
-#define TSI108PIC_NUM_DBELLS 4
-#define TSI108PIC_NUM_PROC 4
-#define TSI108PIC_NUM_PRI 16
-#define TSI108PIC_NUM_VECTORS 256
-
-/*
- * Tsi108 PIC Register offsets within block.
- */
-
-/* Registers controlling sources */
-#define TSI108_INT_FRR (0x000)
-#define TSI108_INT_GCR (0x004)
-#define TSI108_INT_SVR (0x010)
-#define TSI108_INT_GTVPR(n) (0x38 + 0x10*(n))
-#define TSI108_INT_GTDR(n) (0x3C + 0x10*(n))
-#define TSI108_INT_IVPR(n) (0x100 + 0x8*(n))
-#define TSI108_INT_IDR(n) (0x104 + 0x8*(n))
-#define TSI108_INT_DVPR(n) (0x204 + 0xC*(n))
-#define TSI108_INT_DDR(n) (0x208 + 0xC*(n))
-#define TSI108_INT_MBVPR(n) (0x284 + 0x10*(n))
-#define TSI108_INT_MBDR(n) (0x288 + 0x10*(n))
-
-/* Registers controlling destinations */
-#define TSI108_INT_TASKP(n) (0x300 + 0x40*(n))
-#define TSI108_INT_VECTOR(n) (0x304 + 0x40*(n))
-#define TSI108_INT_EOI(n) (0x308 + 0x40*(n))
-#define TSI108_INT_CSR(n) (0x30C + 0x40*(n))
-
-/*
- * Generic definitions common for different types of interrupt
- * sources.
- */
-
-#define TSI108PIC_MASK (0x80000000)
-#define TSI108PIC_ACTIVITY (0x40000000)
-#define TSI108PIC_PRIORITY_MASK (0x000f0000)
-#define TSI108PIC_VECTOR_MASK (0x000000ff)
-
-/**********************************************************
- * Register Bit Masks definitions for every register
- */
-
-/* TSI108PIC_INT_FRR : Register Bits Masks Definitions */
-#define TSI108PIC_INT_FRR_VID (0x000000ff)
-#define TSI108PIC_INT_FRR_NCPU (0x00001f00)
-#define TSI108PIC_INT_FRR_NITM (0x0000e000)
-#define TSI108PIC_INT_FRR_NIRQ (0x07ff0000)
-#define TSI108PIC_INT_FRR_NIDOOR (0xe0000000)
-#define TSI108PIC_INT_FRR_RESERVED (0x18000000)
-
-/* TSI108PIC_INT_GCR : Register Bits Masks Definitions */
-#define TSI108PIC_INT_GCR_R (0x80000000)
-#define TSI108PIC_INT_GCR_RESERVED (0x7fffffff)
-
-/* TSI108PIC_INT_ICR : Register Bits Masks Definitions */
-#define TSI108PIC_INT_ICR_R (0x0000000f)
-#define TSI108PIC_INT_ICR_RESERVED (0xfffffff0)
-
-/* TSI108PIC_INT_MVI : Register Bits Masks Definitions */
-#define TSI108PIC_INT_MVI_VID (0x000000ff)
-#define TSI108PIC_INT_MVI_DID (0x0000ff00)
-#define TSI108PIC_INT_MVI_STEP (0x00ff0000)
-#define TSI108PIC_INT_MVI_RESERVED (0xff000000)
-
-/* TSI108PIC_INT_SVR : Register Bits Masks Definitions */
-#define TSI108PIC_INT_SVR_VECTOR (0x000000ff)
-#define TSI108PIC_INT_SVR_RESERVED (0xffffff00)
-
-/* TSI108PIC_INT_TFRR : Register Bits Masks Definitions */
-#define TSI108PIC_INT_TFRR_TIME_FREQ (0xffffffff)
-
-/* TSI108PIC_INT_SOFT_SET : Register Bits Masks Definitions */
-#define TSI108PIC_INT_SOFT_SET_S (0x00ffffff)
-#define TSI108PIC_INT_SOFT_SET_RESERVED (0xff000000)
-
-/* TSI108PIC_INT_SOFT_ENABLE : Register Bits Masks Definitions */
-#define TSI108PIC_INT_SOFT_ENABLE_EN (0x00ffffff)
-#define TSI108PIC_INT_SOFT_ENABLE_RESERVED (0xff000000)
-
-/* TSI108PIC_INT_GTCCR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_GTCCR_COUNT (0x7fffffff)
-#define TSI108PIC_INT_GTCCR_T (0x80000000)
-
-/* TSI108PIC_INT_GTBCR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_GTBCR_B_COUNT (0x7fffffff)
-#define TSI108PIC_INT_GTBCR_CI (0x80000000)
-
-/* TSI108PIC_INT_GTVPR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_GTVPR_VECTOR (0x000000ff)
-#define TSI108PIC_INT_GTVPR_PRIORITY (0x000f0000)
-#define TSI108PIC_INT_GTVPR_PRESCALE (0x00f00000)
-#define TSI108PIC_INT_GTVPR_A (0x40000000)
-#define TSI108PIC_INT_GTVPR_M (0x80000000)
-#define TSI108PIC_INT_GTVPR_RESERVED (0x3f00ff00)
-
-/* TSI108PIC_INT_GTDR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_GTDR_SEL_OUT (0x0000000f)
-#define TSI108PIC_INT_GTDR_RESERVED (0xfffffff0)
-
-/* TSI108PIC_INT_IVPR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_IVPR_VECTOR (0x000000ff)
-#define TSI108PIC_INT_IVPR_PRIORITY (0x000f0000)
-
-#define TSI108PIC_INT_IVPR_P (0x01000000)
-#define TSI108PIC_INT_IVPR_P_LOW (0 << 24)
-#define TSI108PIC_INT_IVPR_P_HIGH (1 << 24)
-
-#define TSI108PIC_INT_IVPR_S (0x02000000)
-#define TSI108PIC_INT_IVPR_S_EDGE (0 << 25)
-#define TSI108PIC_INT_IVPR_S_LEVEL (1 << 25)
-
-#define TSI108PIC_INT_IVPR_MODE (0x20000000)
-#define TSI108PIC_INT_IVPR_A (0x40000000)
-#define TSI108PIC_INT_IVPR_M (0x80000000)
-#define TSI108PIC_INT_IVPR_RESERVED (0x1cf0ff00)
-
-/* TSI108PIC_INT_IDR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_IDR_SEL_OUT (0x0000000f)
-#define TSI108PIC_INT_IDR_RESERVED (0xfffffff0)
-
-/* TSI108PIC_INT_DAR : Register Bits Masks Definitions */
-#define TSI108PIC_INT_DAR_A (0x0000000f)
-#define TSI108PIC_INT_DAR_RESERVED (0xfffffff0)
-
-/* TSI108PIC_INT_DVPR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_DVPR_VECTOR (0x000000ff)
-#define TSI108PIC_INT_DVPR_PRIORITY (0x000f0000)
-#define TSI108PIC_INT_DVPR_A (0x40000000)
-#define TSI108PIC_INT_DVPR_M (0x80000000)
-#define TSI108PIC_INT_DVPR_RESERVED (0x3ff0ff00)
-
-/* TSI108PIC_INT_DDR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_DDR_SEL_OUT (0x0000000f)
-#define TSI108PIC_INT_DDR_RESERVED (0xfffffff0)
-
-/* TSI108PIC_INT_DMR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_DMR_M (0xffffffff)
-
-/* TSI108PIC_INT_MBR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_MBR_M (0xffffffff)
-
-/* TSI108PIC_INT_MBVPR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_MBVPR_VECTOR (0x000000ff)
-#define TSI108PIC_INT_MBVPR_PRIORITY (0x000f0000)
-#define TSI108PIC_INT_MBVPR_A (0x40000000)
-#define TSI108PIC_INT_MBVPR_M (0x80000000)
-#define TSI108PIC_INT_MBVPR_RESERVED (0x3ff0ff00)
-
-/* TSI108PIC_INT_MBDR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_MBDR_SEL_OUT (0x0000000f)
-#define TSI108PIC_INT_MBDR_RESERVED (0xfffffff0)
-
-/* TSI108PIC_INT_TASKP(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_TASKP_TASKP (0x0000000f)
-#define TSI108PIC_INT_TASKP_RESERVED (0xfffffff0)
-
-/* TSI108PIC_INT_VECTOR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_VECTOR_VECTOR (0x000000ff)
-#define TSI108PIC_INT_VECTOR_LS_VECTOR (0xff000000)
-#define TSI108PIC_INT_VECTOR_RESERVED (0x00ffff00)
-
-/* TSI108PIC_INT_EOI(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_EOI_EOI (0x000000ff)
-#define TSI108PIC_INT_EOI_RESERVED (0xffffff00)
-
-/* TSI108PIC_INT_CSR(X) : Register Bits Masks Definitions */
-#define TSI108PIC_INT_CSR_RESERVED (0xfffffffc)
-
-#define TSI108PIC_INT_CSR_P (1 << 0)
-#define TSI108PIC_INT_CSR_P_LOW (0 << 0)
-#define TSI108PIC_INT_CSR_P_HIGH (1 << 0)
-
-#define TSI108PIC_INT_CSR_S (1 << 1)
-#define TSI108PIC_INT_CSR_S_EDGE (0 << 1)
-#define TSI108PIC_INT_CSR_S_LEVEL (1 << 1)
-
-extern void tsi108_pic_init(u_char * board_init_senses);
-extern void tsi108_pic_reset(void);
-extern void tsi108_pic_set_output(int dest_num, u32 sense, u32 polarity);
-extern int tsi108_pic_source_cfg(int src_num, u32 sense,
- u32 polarity, TSI108_IRQ_MODE mode);
-extern int tsi108_pic_set_vector(int src_num, int vect, int prio);
-extern void tsi108_pic_init_nmi_irq(u_int irq);
-extern void tsi108_pic_hookup_cascade(u_int irq, char *name,
- int (*cascade_fn) (struct pt_regs *));
-extern int tsi108_pic_get_irq(struct pt_regs *regs);
-
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_TSI108_PIC_H */
^ permalink raw reply
* [PATCH] powerpc vdso updates
From: Benjamin Herrenschmidt @ 2006-05-30 3:51 UTC (permalink / raw)
To: linuxppc-dev list; +Cc: Ingo Molnar, Paul Mackerras, Linux Kernel list
This patch cleans up some locking & error handling in the ppc vdso and
moves the vdso base pointer from the thread struct to the mm context
where it more logically belongs. It brings the powerpc implementation
closer to Ingo's new x86 one and also adds an arch_vma_name() function
allowing to print [vsdo] in /proc/<pid>/maps if Ingo's x86 vdso patch is
also applied.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
This is 2.6.18 material, hopefully should go along with Ingo's x86 vdso updates. Ingo, if you
change something to arch_vma_name(), please let me know.
Index: linux-work/arch/powerpc/kernel/signal_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/signal_32.c 2006-05-30 13:34:09.000000000 +1000
+++ linux-work/arch/powerpc/kernel/signal_32.c 2006-05-30 13:40:21.000000000 +1000
@@ -757,10 +757,10 @@ static int handle_rt_signal(unsigned lon
/* Save user registers on the stack */
frame = &rt_sf->uc.uc_mcontext;
- if (vdso32_rt_sigtramp && current->thread.vdso_base) {
+ if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
if (save_user_regs(regs, frame, 0))
goto badframe;
- regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
+ regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
} else {
if (save_user_regs(regs, frame, __NR_rt_sigreturn))
goto badframe;
@@ -1029,10 +1029,10 @@ static int handle_signal(unsigned long s
|| __put_user(sig, &sc->signal))
goto badframe;
- if (vdso32_sigtramp && current->thread.vdso_base) {
+ if (vdso32_sigtramp && current->mm->context.vdso_base) {
if (save_user_regs(regs, &frame->mctx, 0))
goto badframe;
- regs->link = current->thread.vdso_base + vdso32_sigtramp;
+ regs->link = current->mm->context.vdso_base + vdso32_sigtramp;
} else {
if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
goto badframe;
Index: linux-work/arch/powerpc/kernel/signal_64.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/signal_64.c 2006-05-30 13:34:09.000000000 +1000
+++ linux-work/arch/powerpc/kernel/signal_64.c 2006-05-30 13:40:21.000000000 +1000
@@ -394,8 +394,8 @@ static int setup_rt_frame(int signr, str
current->thread.fpscr.val = 0;
/* Set up to return from userspace. */
- if (vdso64_rt_sigtramp && current->thread.vdso_base) {
- regs->link = current->thread.vdso_base + vdso64_rt_sigtramp;
+ if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
+ regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
} else {
err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
if (err)
Index: linux-work/arch/powerpc/kernel/vdso.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/vdso.c 2006-05-30 13:34:09.000000000 +1000
+++ linux-work/arch/powerpc/kernel/vdso.c 2006-05-30 13:41:31.000000000 +1000
@@ -223,6 +223,7 @@ int arch_setup_additional_pages(struct l
struct vm_area_struct *vma;
unsigned long vdso_pages;
unsigned long vdso_base;
+ int rc;
#ifdef CONFIG_PPC64
if (test_thread_flag(TIF_32BIT)) {
@@ -237,20 +238,13 @@ int arch_setup_additional_pages(struct l
vdso_base = VDSO32_MBASE;
#endif
- current->thread.vdso_base = 0;
+ current->mm->context.vdso_base = 0;
/* vDSO has a problem and was disabled, just don't "enable" it for the
* process
*/
if (vdso_pages == 0)
return 0;
-
- vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
- if (vma == NULL)
- return -ENOMEM;
-
- memset(vma, 0, sizeof(*vma));
-
/* Add a page to the vdso size for the data page */
vdso_pages ++;
@@ -259,17 +253,23 @@ int arch_setup_additional_pages(struct l
* at vdso_base which is the "natural" base for it, but we might fail
* and end up putting it elsewhere.
*/
+ down_write(&mm->mmap_sem);
vdso_base = get_unmapped_area(NULL, vdso_base,
vdso_pages << PAGE_SHIFT, 0, 0);
- if (vdso_base & ~PAGE_MASK) {
- kmem_cache_free(vm_area_cachep, vma);
- return (int)vdso_base;
+ if (IS_ERR_VALUE(vdso_base)) {
+ rc = vdso_base;
+ goto fail_mmapsem;
}
- current->thread.vdso_base = vdso_base;
+ /* Allocate a VMA structure and fill it up */
+ vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+ if (vma == NULL) {
+ rc = -ENOMEM;
+ goto fail_mmapsem;
+ }
vma->vm_mm = mm;
- vma->vm_start = current->thread.vdso_base;
+ vma->vm_start = vdso_base;
vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT);
/*
@@ -282,23 +282,38 @@ int arch_setup_additional_pages(struct l
* It's fine to use that for setting breakpoints in the vDSO code
* pages though
*/
- vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
vma->vm_flags |= mm->def_flags;
vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
vma->vm_ops = &vdso_vmops;
- down_write(&mm->mmap_sem);
- if (insert_vm_struct(mm, vma)) {
- up_write(&mm->mmap_sem);
- kmem_cache_free(vm_area_cachep, vma);
- return -ENOMEM;
- }
+ /* Insert new VMA */
+ rc = insert_vm_struct(mm, vma);
+ if (rc)
+ goto fail_vma;
+
+ /* Put vDSO base into mm struct and account for memory usage */
+ current->mm->context.vdso_base = vdso_base;
mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
up_write(&mm->mmap_sem);
-
return 0;
+
+ fail_vma:
+ kmem_cache_free(vm_area_cachep, vma);
+ fail_mmapsem:
+ up_write(&mm->mmap_sem);
+ return rc;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base)
+ return "[vdso]";
+ return NULL;
}
+
+
static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
unsigned long *size)
{
Index: linux-work/include/asm-powerpc/elf.h
===================================================================
--- linux-work.orig/include/asm-powerpc/elf.h 2006-05-30 13:34:09.000000000 +1000
+++ linux-work/include/asm-powerpc/elf.h 2006-05-30 13:40:21.000000000 +1000
@@ -294,7 +294,7 @@ do { \
NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
- VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base) \
+ VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base) \
} while (0)
/* PowerPC64 relocations defined by the ABIs */
Index: linux-work/include/asm-powerpc/mmu.h
===================================================================
--- linux-work.orig/include/asm-powerpc/mmu.h 2006-05-30 13:34:09.000000000 +1000
+++ linux-work/include/asm-powerpc/mmu.h 2006-05-30 13:40:21.000000000 +1000
@@ -360,6 +360,7 @@ typedef struct {
#ifdef CONFIG_HUGETLB_PAGE
u16 low_htlb_areas, high_htlb_areas;
#endif
+ unsigned long vdso_base;
} mm_context_t;
Index: linux-work/include/asm-powerpc/page.h
===================================================================
--- linux-work.orig/include/asm-powerpc/page.h 2006-05-30 13:34:09.000000000 +1000
+++ linux-work/include/asm-powerpc/page.h 2006-05-30 13:40:21.000000000 +1000
@@ -198,6 +198,9 @@ extern void copy_user_page(void *to, voi
struct page *p);
extern int page_is_ram(unsigned long pfn);
+struct vm_area_struct;
+extern const char *arch_vma_name(struct vm_area_struct *vma);
+
#include <asm-generic/memory_model.h>
#endif /* __ASSEMBLY__ */
Index: linux-work/include/asm-powerpc/processor.h
===================================================================
--- linux-work.orig/include/asm-powerpc/processor.h 2006-05-30 13:34:09.000000000 +1000
+++ linux-work/include/asm-powerpc/processor.h 2006-05-30 13:40:21.000000000 +1000
@@ -153,7 +153,6 @@ struct thread_struct {
unsigned long start_tb; /* Start purr when proc switched in */
unsigned long accum_tb; /* Total accumilated purr for process */
#endif
- unsigned long vdso_base; /* base of the vDSO library */
unsigned long dabr; /* Data address breakpoint register */
#ifdef CONFIG_ALTIVEC
/* Complete AltiVec register set */
^ 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