alpha 2.4.11-pre3: fix pc164 srm interrupts

From: Richard Henderson (rth@dot.cygnus.com)
Date: Thu Oct 04 2001 - 20:25:52 EST


>From Jay Estabrook:

(1) The PC164 broken interupt mask hack was only applied to the MILO
    interrupt handler, and not the SRM interrupt handler.

(2) SRM sometimes mis-identifies a PC164 as an EB164, which results
    in our interrupt fixes not being installed. Fix this by noticing
    that an EB164 is never an EV56.

r~

diff -rup 2.4.10-dist/arch/alpha/kernel/setup.c 2.4.10/arch/alpha/kernel/setup.c
--- 2.4.10-dist/arch/alpha/kernel/setup.c Sun Aug 12 10:38:47 2001
+++ 2.4.10/arch/alpha/kernel/setup.c Thu Oct 4 16:05:16 2001
@@ -85,7 +93,7 @@ unsigned char aux_device_present = 0xaa;
 
 static struct alpha_machine_vector *get_sysvec(long, long, long);
 static struct alpha_machine_vector *get_sysvec_byname(const char *);
-static void get_sysnames(long, long, char **, char **);
+static void get_sysnames(long, long, long, char **, char **);
 
 static char command_line[COMMAND_LINE_SIZE];
 char saved_command_line[COMMAND_LINE_SIZE];
@@ -537,14 +545,14 @@ setup_arch(char **cmdline_p)
         /*
          * Indentify and reconfigure for the current system.
          */
+ cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
+
         get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
- &type_name, &var_name);
+ cpu->type, &type_name, &var_name);
         if (*var_name == '0')
                 var_name = "";
 
         if (!vec) {
- cpu = (struct percpu_struct*)
- ((char*)hwrpb + hwrpb->processor_offset);
                 vec = get_sysvec(hwrpb->sys_type, hwrpb->sys_variation,
                                  cpu->type);
         }
@@ -801,6 +809,8 @@ get_sysvec(long type, long variation, lo
                 /* Member ID is a bit-field. */
                 long member = (variation >> 10) & 0x3f;
 
+ cpu &= 0xffffffff; /* make it usable */
+
                 switch (type) {
                 case ST_DEC_ALCOR:
                         if (member < N(alcor_indices))
@@ -809,6 +819,10 @@ get_sysvec(long type, long variation, lo
                 case ST_DEC_EB164:
                         if (member < N(eb164_indices))
                                 vec = eb164_vecs[eb164_indices[member]];
+ /* PC164 may show as EB164 variation with EV56 CPU,
+ but, since no true EB164 had anything but EV5... */
+ if (vec == &eb164_mv && cpu == EV56_CPU)
+ vec = &pc164_mv;
                         break;
                 case ST_DEC_EB64P:
                         if (member < N(eb64p_indices))
@@ -827,21 +841,18 @@ get_sysvec(long type, long variation, lo
                                 vec = tsunami_vecs[tsunami_indices[member]];
                         break;
                 case ST_DEC_1000:
- cpu &= 0xffffffff;
                         if (cpu == EV5_CPU || cpu == EV56_CPU)
                                 vec = &mikasa_primo_mv;
                         else
                                 vec = &mikasa_mv;
                         break;
                 case ST_DEC_NORITAKE:
- cpu &= 0xffffffff;
                         if (cpu == EV5_CPU || cpu == EV56_CPU)
                                 vec = &noritake_primo_mv;
                         else
                                 vec = &noritake_mv;
                         break;
                 case ST_DEC_2100_A500:
- cpu &= 0xffffffff;
                         if (cpu == EV5_CPU || cpu == EV56_CPU)
                                 vec = &sable_gamma_mv;
                         else
@@ -905,7 +916,7 @@ get_sysvec_byname(const char *name)
 }
 
 static void
-get_sysnames(long type, long variation,
+get_sysnames(long type, long variation, long cpu,
              char **type_name, char **variation_name)
 {
         long member;
@@ -938,12 +949,18 @@ get_sysnames(long type, long variation,
 
         member = (variation >> 10) & 0x3f; /* member ID is a bit-field */
 
+ cpu &= 0xffffffff; /* make it usable */
+
         switch (type) { /* select by family */
         default: /* default to variation "0" for now */
                 break;
         case ST_DEC_EB164:
                 if (member < N(eb164_indices))
                         *variation_name = eb164_names[eb164_indices[member]];
+ /* PC164 may show as EB164 variation, but with EV56 CPU,
+ so, since no true EB164 had anything but EV5... */
+ if (eb164_indices[member] == 0 && cpu == EV56_CPU)
+ *variation_name = eb164_names[1]; /* make it PC164 */
                 break;
         case ST_DEC_ALCOR:
                 if (member < N(alcor_indices))
@@ -1054,7 +1071,7 @@ int get_cpuinfo(char *buffer)
                 cpu_name = cpu_names[cpu_index];
 
         get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
- &systype_name, &sysvariation_name);
+ cpu->type, &systype_name, &sysvariation_name);
 
         nr_processors = get_nr_processors(cpu, hwrpb->nr_processors);
 
diff -rup 2.4.10-dist/arch/alpha/kernel/sys_cabriolet.c 2.4.10/arch/alpha/kernel/sys_cabriolet.c
--- 2.4.10-dist/arch/alpha/kernel/sys_cabriolet.c Wed Jan 24 15:16:23 2001
+++ 2.4.10/arch/alpha/kernel/sys_cabriolet.c Thu Oct 4 16:09:03 2001
@@ -106,12 +106,12 @@ cabriolet_device_interrupt(unsigned long
 }
 
 static void __init
-cabriolet_init_irq(void)
+common_init_irq(void (*srm_dev_int)(unsigned long v, struct pt_regs *r))
 {
         init_i8259a_irqs();
 
         if (alpha_using_srm) {
- alpha_mv.device_interrupt = srm_device_interrupt;
+ alpha_mv.device_interrupt = srm_dev_int;
                 init_srm_irqs(35, 0);
         }
         else {
@@ -131,29 +131,47 @@ cabriolet_init_irq(void)
         setup_irq(16+4, &isa_cascade_irqaction);
 }
 
+static void __init
+cabriolet_init_irq(void)
+{
+ common_init_irq(srm_device_interrupt);
+}
+
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
+/* In theory, the PC164 has the same interrupt hardware as the other
+ Cabriolet based systems. However, something got screwed up late
+ in the development cycle which broke the interrupt masking hardware.
+ Repeat, it is not possible to mask and ack interrupts. At all.
+
+ In an attempt to work around this, while processing interrupts,
+ we do not allow the IPL to drop below what it is currently. This
+ prevents the possibility of recursion.
+
+ ??? Another option might be to force all PCI devices to use edge
+ triggered rather than level triggered interrupts. That might be
+ too invasive though. */
+
 static void
-pc164_device_interrupt(unsigned long v, struct pt_regs *r)
+pc164_srm_device_interrupt(unsigned long v, struct pt_regs *r)
 {
- /* In theory, the PC164 has the same interrupt hardware as
- the other Cabriolet based systems. However, something
- got screwed up late in the development cycle which broke
- the interrupt masking hardware. Repeat, it is not
- possible to mask and ack interrupts. At all.
-
- In an attempt to work around this, while processing
- interrupts, we do not allow the IPL to drop below what
- it is currently. This prevents the possibility of
- recursion.
-
- ??? Another option might be to force all PCI devices
- to use edge triggered rather than level triggered
- interrupts. That might be too invasive though. */
+ __min_ipl = getipl();
+ srm_device_interrupt(v, r);
+ __min_ipl = 0;
+}
 
+static void
+pc164_device_interrupt(unsigned long v, struct pt_regs *r)
+{
         __min_ipl = getipl();
         cabriolet_device_interrupt(v, r);
         __min_ipl = 0;
 }
+
+static void __init
+pc164_init_irq(void)
+{
+ common_init_irq(pc164_srm_device_interrupt);
+}
 #endif
 
 /*
@@ -419,7 +437,7 @@ struct alpha_machine_vector pc164_mv __i
         device_interrupt: pc164_device_interrupt,
 
         init_arch: cia_init_arch,
- init_irq: cabriolet_init_irq,
+ init_irq: pc164_init_irq,
         init_rtc: common_init_rtc,
         init_pci: alphapc164_init_pci,
         pci_map_irq: alphapc164_map_irq,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Oct 07 2001 - 21:00:35 EST