git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
vserver 1.9.5.x5
[linux-2.6.git]
/
arch
/
ppc64
/
kernel
/
xics.c
diff --git
a/arch/ppc64/kernel/xics.c
b/arch/ppc64/kernel/xics.c
index
ae15d22
..
929dff1
100644
(file)
--- a/
arch/ppc64/kernel/xics.c
+++ b/
arch/ppc64/kernel/xics.c
@@
-24,7
+24,6
@@
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/smp.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/smp.h>
-#include <asm/naca.h>
#include <asm/rtas.h>
#include <asm/xics.h>
#include <asm/hvcall.h>
#include <asm/rtas.h>
#include <asm/xics.h>
#include <asm/hvcall.h>
@@
-85,13
+84,14
@@
struct xics_ipl {
} qirr;
};
} qirr;
};
-static struct xics_ipl *xics_per_cpu[NR_CPUS];
+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 unsigned int default_server = 0xFF;
/* also referenced in smp.c... */
unsigned int default_distrib_server = 0;
static int xics_irq_8259_cascade = 0;
static int xics_irq_8259_cascade_real = 0;
static unsigned int default_server = 0xFF;
/* also referenced in smp.c... */
unsigned int default_distrib_server = 0;
+unsigned int interrupt_server_size = 8;
/*
* XICS only has a single IPI, so encode the messages per CPU
/*
* XICS only has a single IPI, so encode the messages per CPU
@@
-116,22
+116,22
@@
typedef struct {
static int pSeries_xirr_info_get(int n_cpu)
{
static int pSeries_xirr_info_get(int n_cpu)
{
- return
xics_per_cpu[n_cpu]->xirr.word
;
+ return
in_be32(&xics_per_cpu[n_cpu]->xirr.word)
;
}
static void pSeries_xirr_info_set(int n_cpu, int value)
{
}
static void pSeries_xirr_info_set(int n_cpu, int value)
{
-
xics_per_cpu[n_cpu]->xirr.word = value
;
+
out_be32(&xics_per_cpu[n_cpu]->xirr.word, value)
;
}
static void pSeries_cppr_info(int n_cpu, u8 value)
{
}
static void pSeries_cppr_info(int n_cpu, u8 value)
{
-
xics_per_cpu[n_cpu]->xirr.bytes[0] = value
;
+
out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value)
;
}
static void pSeries_qirr_info(int n_cpu, u8 value)
{
}
static void pSeries_qirr_info(int n_cpu, u8 value)
{
-
xics_per_cpu[n_cpu]->qirr.bytes[0] = value
;
+
out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value)
;
}
static xics_ops pSeries_ops = {
}
static xics_ops pSeries_ops = {
@@
-216,12
+216,15
@@
xics_ops pSeriesLP_ops = {
static unsigned int xics_startup(unsigned int virq)
{
static unsigned int xics_startup(unsigned int virq)
{
- virq = irq_offset_down(virq);
- if (radix_tree_insert(&irq_map, virt_irq_to_real(virq),
- &virt_irq_to_real_map[virq]) == -ENOMEM)
+ unsigned int irq;
+
+ irq = irq_offset_down(virq);
+ if (radix_tree_insert(&irq_map, virt_irq_to_real(irq),
+ &virt_irq_to_real_map[irq]) == -ENOMEM)
printk(KERN_CRIT "Out of memory creating real -> virtual"
" IRQ mapping for irq %u (real 0x%x)\n",
printk(KERN_CRIT "Out of memory creating real -> virtual"
" IRQ mapping for irq %u (real 0x%x)\n",
- virq, virt_irq_to_real(virq));
+ virq, virt_irq_to_real(irq));
+ xics_enable_irq(virq);
return 0; /* return value is ignored */
}
return 0; /* return value is ignored */
}
@@
-239,28
+242,24
@@
static unsigned int real_irq_to_virt(unsigned int real_irq)
static int get_irq_server(unsigned int irq)
{
unsigned int server;
static int get_irq_server(unsigned int irq)
{
unsigned int server;
-
-#ifdef CONFIG_IRQ_ALL_CPUS
/* For the moment only implement delivery to all cpus or one cpu */
/* For the moment only implement delivery to all cpus or one cpu */
- if (smp_threads_ready) {
- cpumask_t cpumask = irq_affinity[irq];
- cpumask_t tmp = CPU_MASK_NONE;
- if (cpus_equal(cpumask, CPU_MASK_ALL)) {
- server = default_distrib_server;
- } else {
- cpus_and(tmp, cpu_online_map, cpumask);
+ cpumask_t cpumask = irq_affinity[irq];
+ cpumask_t tmp = CPU_MASK_NONE;
-
if (cpus_empty(tmp)
)
-
server = default_distrib
_server;
- else
- server = get_hard_smp_processor_id(first_cpu(tmp));
- }
+
if (!distribute_irqs
)
+
return default
_server;
+
+ if (cpus_equal(cpumask, CPU_MASK_ALL)) {
+ server = default_distrib_server;
} else {
} else {
- server = default_server;
+ cpus_and(tmp, cpu_online_map, cpumask);
+
+ if (cpus_empty(tmp))
+ server = default_distrib_server;
+ else
+ server = get_hard_smp_processor_id(first_cpu(tmp));
}
}
-#else
- server = default_server;
-#endif
+
return server;
}
return server;
}
@@
-454,7
+453,7
@@
void xics_init_IRQ(void)
struct xics_interrupt_node {
unsigned long addr;
unsigned long size;
struct xics_interrupt_node {
unsigned long addr;
unsigned long size;
- } inodes[NR_CPUS];
+ } in
tn
odes[NR_CPUS];
ppc64_boot_msg(0x20, "XICS Init");
ppc64_boot_msg(0x20, "XICS Init");
@@
-481,13
+480,13
@@
nextnode:
panic("xics_init_IRQ: can't find interrupt reg property");
while (ilen) {
panic("xics_init_IRQ: can't find interrupt reg property");
while (ilen) {
- in
odes[indx].addr = (unsigned long
long)*ireg++ << 32;
+ in
tnodes[indx].addr = (unsigned
long)*ireg++ << 32;
ilen -= sizeof(uint);
ilen -= sizeof(uint);
- inodes[indx].addr |= *ireg++;
+ in
tn
odes[indx].addr |= *ireg++;
ilen -= sizeof(uint);
ilen -= sizeof(uint);
- in
odes[indx].size = (unsigned long
long)*ireg++ << 32;
+ in
tnodes[indx].size = (unsigned
long)*ireg++ << 32;
ilen -= sizeof(uint);
ilen -= sizeof(uint);
- inodes[indx].size |= *ireg++;
+ in
tn
odes[indx].size |= *ireg++;
ilen -= sizeof(uint);
indx++;
if (indx >= NR_CPUS) break;
ilen -= sizeof(uint);
indx++;
if (indx >= NR_CPUS) break;
@@
-501,20
+500,25
@@
nextnode:
np;
np = of_find_node_by_type(np, "cpu")) {
ireg = (uint *)get_property(np, "reg", &ilen);
np;
np = of_find_node_by_type(np, "cpu")) {
ireg = (uint *)get_property(np, "reg", &ilen);
- if (ireg && ireg[0] == hard_smp_processor_id()) {
- ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+ if (ireg && ireg[0] == boot_cpuid_phys) {
+ ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s",
+ &ilen);
i = ilen / sizeof(int);
if (ireg && i > 0) {
default_server = ireg[0];
default_distrib_server = ireg[i-1]; /* take last element */
}
i = ilen / sizeof(int);
if (ireg && i > 0) {
default_server = ireg[0];
default_distrib_server = ireg[i-1]; /* take last element */
}
+ ireg = (uint *)get_property(np,
+ "ibm,interrupt-server#-size", NULL);
+ if (ireg)
+ interrupt_server_size = *ireg;
break;
}
}
of_node_put(np);
break;
}
}
of_node_put(np);
- intr_base = inodes[0].addr;
- intr_size =
(ulong)i
nodes[0].size;
+ intr_base = in
tn
odes[0].addr;
+ intr_size =
int
nodes[0].size;
np = of_find_node_by_type(NULL, "interrupt-controller");
if (!np) {
np = of_find_node_by_type(NULL, "interrupt-controller");
if (!np) {
@@
-535,16
+539,18
@@
nextnode:
if (systemcfg->platform == PLATFORM_PSERIES) {
#ifdef CONFIG_SMP
for_each_cpu(i) {
if (systemcfg->platform == PLATFORM_PSERIES) {
#ifdef CONFIG_SMP
for_each_cpu(i) {
+ int hard_id;
+
/* FIXME: Do this dynamically! --RR */
if (!cpu_present(i))
continue;
/* FIXME: Do this dynamically! --RR */
if (!cpu_present(i))
continue;
- xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr,
- (ulong)inodes[get_hard_smp_processor_id(i)].size,
- _PAGE_NO_CACHE);
+
+ hard_id = get_hard_smp_processor_id(i);
+ xics_per_cpu[i] = ioremap(intnodes[hard_id].addr,
+ intnodes[hard_id].size);
}
#else
}
#else
- xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size,
- _PAGE_NO_CACHE);
+ xics_per_cpu[0] = ioremap(intr_base, intr_size);
#endif /* CONFIG_SMP */
} else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
ops = &pSeriesLP_ops;
#endif /* CONFIG_SMP */
} else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
ops = &pSeriesLP_ops;
@@
-569,13
+575,13
@@
nextnode:
*/
static int __init xics_setup_i8259(void)
{
*/
static int __init xics_setup_i8259(void)
{
- if (
naca->
interrupt_controller == IC_PPC_XIC &&
+ if (
ppc64_
interrupt_controller == IC_PPC_XIC &&
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 "
"cascade\n");
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 "
"cascade\n");
- i8259_init();
+ i8259_init(
0
);
}
return 0;
}
}
return 0;
}
@@
-638,20
+644,16
@@
static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
/* Interrupts are disabled. */
void xics_migrate_irqs_away(void)
{
/* Interrupts are disabled. */
void xics_migrate_irqs_away(void)
{
- int set_indicator = rtas_token("set-indicator");
- const unsigned int giqs = 9005UL; /* Global Interrupt Queue Server */
- int status = 0;
+ int status;
unsigned int irq, virq, cpu = smp_processor_id();
unsigned int irq, virq, cpu = smp_processor_id();
- BUG_ON(set_indicator == RTAS_UNKNOWN_SERVICE);
-
/* Reject any interrupt that was queued to us... */
ops->cppr_info(cpu, 0);
iosync();
/* Reject any interrupt that was queued to us... */
ops->cppr_info(cpu, 0);
iosync();
- /*
Refuse any new interrupts...
*/
-
rtas_call(set_indicator, 3, 1, &status, giqs
,
-
hard_smp_processor_id()
, 0);
+ /*
remove ourselves from the global interrupt queue
*/
+
status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE
,
+
(1UL << interrupt_server_size) - 1 - default_distrib_server
, 0);
WARN_ON(status != 0);
/* Allow IPIs again... */
WARN_ON(status != 0);
/* Allow IPIs again... */