patch-2.4.22 linux-2.4.22/arch/ia64/sn/io/sn2/ml_SN_intr.c
Next file: linux-2.4.22/arch/ia64/sn/io/sn2/ml_iograph.c
Previous file: linux-2.4.22/arch/ia64/sn/io/sn2/ml_SN_init.c
Back to the patch index
Back to the overall index
- Lines: 242
- Date:
2003-08-25 04:44:39.000000000 -0700
- Orig file:
linux-2.4.21/arch/ia64/sn/io/sn2/ml_SN_intr.c
- Orig date:
2003-06-13 07:51:30.000000000 -0700
diff -urN linux-2.4.21/arch/ia64/sn/io/sn2/ml_SN_intr.c linux-2.4.22/arch/ia64/sn/io/sn2/ml_SN_intr.c
@@ -4,7 +4,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1992-1997, 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*/
/*
@@ -40,30 +40,13 @@
#include <asm/sal.h>
#include <asm/sn/sn_sal.h>
-extern irqpda_t *irqpdaindr[];
-extern cnodeid_t master_node_get(devfs_handle_t vhdl);
+extern irqpda_t *irqpdaindr;
+extern cnodeid_t master_node_get(vertex_hdl_t vhdl);
extern nasid_t master_nasid;
// Initialize some shub registers for interrupts, both IO and error.
//
-#ifdef BRINGUP2
-static long vec1_opt, ii0_opt;
-static int __init set_vec1_opt(char *str)
-{
- vec1_opt = 1;
- return 1;
-}
-
-static int __init set_ii0_opt(char *str)
-{
- ii0_opt = 1;
- return 1;
-}
-
-__setup("vec1", set_vec1_opt);
-__setup("ii0", set_ii0_opt);
-#endif
void
@@ -78,6 +61,8 @@
nodepda_t *lnodepda;
sh_ii_int0_enable_u_t ii_int_enable;
sh_int_node_id_config_u_t node_id_config;
+ sh_local_int5_config_u_t local5_config;
+ sh_local_int5_enable_u_t local5_enable;
extern void sn_init_cpei_timer(void);
static int timer_added = 0;
@@ -113,6 +98,19 @@
HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_PI_ERROR_MASK), 0);
HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_PI_CRBP_ERROR_MASK), 0);
+ // Config and enable UART interrupt, all nodes.
+
+ local5_config.sh_local_int5_config_regval = 0;
+ local5_config.sh_local_int5_config_s.idx = SGI_UART_VECTOR;
+ local5_config.sh_local_int5_config_s.pid = cpu0;
+ HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_CONFIG),
+ local5_config.sh_local_int5_config_regval);
+
+ local5_enable.sh_local_int5_enable_regval = 0;
+ local5_enable.sh_local_int5_enable_s.uart_int = 1;
+ HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_ENABLE),
+ local5_enable.sh_local_int5_enable_regval);
+
// The II_INT_CONFIG register for cpu 0.
ii_int_config.sh_ii_int0_config_regval = 0;
@@ -139,13 +137,6 @@
// Enable interrupts for II_INT0 and 1.
ii_int_enable.sh_ii_int0_enable_regval = 0;
ii_int_enable.sh_ii_int0_enable_s.ii_enable = 1;
-#if defined(BUS_INT_WAR) && defined(CONFIG_SHUB_1_0_SPECIFIC)
- /* Dont enable any ints from II. We will poll for interrupts. */
- ii_int_enable.sh_ii_int0_enable_s.ii_enable = 0;
-
- /* Enable IPIs. We use them ONLY for send INITs to hung cpus */
- *(volatile long*)GLOBAL_MMR_ADDR(nasid, SH_IPI_INT_ENABLE) = 1;
-#endif
HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_II_INT0_ENABLE),
ii_int_enable.sh_ii_int0_enable_regval);
@@ -167,24 +158,44 @@
int reserve)
{
int i;
- irqpda_t *irqs = irqpdaindr[cpu];
- static int nextvec=IA64_SN2_FIRST_DEVICE_VECTOR;
+ irqpda_t *irqs = irqpdaindr;
+ int min_shared;
if (reserve) {
if (bit < 0) {
- for (i = nextvec; i <= IA64_SN2_LAST_DEVICE_VECTOR; i++) {
+ for (i = IA64_SN2_FIRST_DEVICE_VECTOR; i <= IA64_SN2_LAST_DEVICE_VECTOR; i++) {
if (irqs->irq_flags[i] == 0) {
bit = i;
-#ifdef BRINGUP2
- if (vec1_opt)
- nextvec = i+1;
-#endif
break;
}
}
}
- if (bit < 0) {
- return -1;
+ if (bit < 0) { /* ran out of irqs. Have to share. This will be rare. */
+ min_shared = 256;
+ for (i=IA64_SN2_FIRST_DEVICE_VECTOR; i < IA64_SN2_LAST_DEVICE_VECTOR; i++) {
+ /* Share with the same device class */
+ if (irqpdaindr->current->vendor == irqpdaindr->device_dev[i]->vendor &&
+ irqpdaindr->current->device == irqpdaindr->device_dev[i]->device &&
+ irqpdaindr->share_count[i] < min_shared) {
+ min_shared = irqpdaindr->share_count[i];
+ bit = i;
+ }
+ }
+ min_shared = 256;
+ if (bit < 0) { /* didn't find a matching device, just pick one. This will be */
+ /* exceptionally rare. */
+ for (i=IA64_SN2_FIRST_DEVICE_VECTOR; i < IA64_SN2_LAST_DEVICE_VECTOR; i++) {
+ if (irqpdaindr->share_count[i] < min_shared) {
+ min_shared = irqpdaindr->share_count[i];
+ bit = i;
+ }
+ }
+ }
+ irqpdaindr->share_count[bit]++;
+ }
+ if (irqs->irq_flags[bit] & SN2_IRQ_SHARED) {
+ irqs->irq_flags[bit] |= SN2_IRQ_RESERVED;
+ return bit;
}
if (irqs->irq_flags[bit] & SN2_IRQ_RESERVED) {
return -1;
@@ -208,7 +219,7 @@
intr_reserve_level(cpuid_t cpu,
int bit,
int resflags,
- devfs_handle_t owner_dev,
+ vertex_hdl_t owner_dev,
char *name)
{
return(do_intr_reserve_level(cpu, bit, 1));
@@ -228,9 +239,13 @@
int bit,
int connect)
{
- irqpda_t *irqs = irqpdaindr[cpu];
+ irqpda_t *irqs = irqpdaindr;
if (connect) {
+ if (irqs->irq_flags[bit] & SN2_IRQ_SHARED) {
+ irqs->irq_flags[bit] |= SN2_IRQ_CONNECTED;
+ return bit;
+ }
if (irqs->irq_flags[bit] & SN2_IRQ_CONNECTED) {
return -1;
} else {
@@ -273,28 +288,29 @@
int slice, min_count = 1000;
irqpda_t *irqs;
- for (slice = 0; slice < CPUS_PER_NODE; slice++) {
+ for (slice = CPUS_PER_NODE - 1; slice >= 0; slice--) {
int intrs;
cpu = cnode_slice_to_cpuid(cnode, slice);
- if (cpu == CPU_NONE) {
+ if (cpu == smp_num_cpus) {
continue;
}
- if (!cpu_enabled(cpu)) {
+ if (!cpu_online(cpu)) {
continue;
}
- irqs = irqpdaindr[cpu];
+ irqs = irqpdaindr;
intrs = irqs->num_irq_used;
if (min_count > intrs) {
min_count = intrs;
best_cpu = cpu;
-#ifdef BRINGUP2
- if (ii0_opt)
+ if ( enable_shub_wars_1_1() ) {
+ /* Rather than finding the best cpu, always return the first cpu*/
+ /* This forces all interrupts to the same cpu */
break;
-#endif
+ }
}
}
return best_cpu;
@@ -314,7 +330,7 @@
cnodeid_t cnode,
int req_bit,
int resflags,
- devfs_handle_t owner_dev,
+ vertex_hdl_t owner_dev,
char *name,
int *resp_bit)
{
@@ -336,18 +352,18 @@
// Find the node to assign for this interrupt.
cpuid_t
-intr_heuristic(devfs_handle_t dev,
+intr_heuristic(vertex_hdl_t dev,
device_desc_t dev_desc,
int req_bit,
int resflags,
- devfs_handle_t owner_dev,
+ vertex_hdl_t owner_dev,
char *name,
int *resp_bit)
{
cpuid_t cpuid;
cpuid_t candidate = CPU_NONE;
cnodeid_t candidate_node;
- devfs_handle_t pconn_vhdl;
+ vertex_hdl_t pconn_vhdl;
pcibr_soft_t pcibr_soft;
int bit;
@@ -398,8 +414,8 @@
if (candidate != CPU_NONE) {
printk("Cannot target interrupt to target node (%ld).\n",candidate);
return CPU_NONE; } else {
- printk("Cannot target interrupt to closest node (%d) 0x%p\n",
- master_node_get(dev), (void *)owner_dev);
+ /* printk("Cannot target interrupt to closest node (%d) 0x%p\n",
+ master_node_get(dev), (void *)owner_dev); */
}
// We couldn't put it on the closest node. Try to find another one.
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)