[PARISC] remove global_ack_eiem

Kudos to Thibaut Varene for spotting the (mis)use of appropriately named
global_ack_eiem. This took a long time to figure out and both insight
from myself, Kyle McMartin, and James Bottomley were required to narrow
down which bit of code could have this race condition.

The symptom was interrupts stopped getting delivered while some workload
was generating IO interrupts on two different CPUs. One of the interrupt
sources would get masked off and stay unmasked. Problem was global_ack_eiem
was accessed with read/modified/write sequence and not protected by
a spinlock.

PA-RISC doesn't need a global ack flag though. External Interrupts
are _always_ delivered to a single CPU (except for "global broadcast
interrupt" which AFAIK currently is not used.) So we don't have to worry
about any given IRQ vector getting delivered to more than one CPU.

Tested on a500 and rp34xx boxen. rsync to/from gsyprf11 (a500)
would lock up the box since NIC (tg3) interrupt and SCSI (sym2)
were on "opposite" CPUs (2 CPU system). Put them on the same CPU
or apply this patch and 10GB of data would rsync completely.

Please apply the following critical patch.

thanks,
grant

Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
Acked-by: Thibaut VARENE <T-Bone@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>

authored by Grant Grundler and committed by Kyle McMartin 462b529f c3d4ed4e

+8 -18
+8 -18
arch/parisc/kernel/irq.c
··· 46 static volatile unsigned long cpu_eiem = 0; 47 48 /* 49 - ** ack bitmap ... habitually set to 1, but reset to zero 50 ** between ->ack() and ->end() of the interrupt to prevent 51 ** re-interruption of a processing interrupt. 52 - */ 53 - static volatile unsigned long global_ack_eiem = ~0UL; 54 - /* 55 - ** Local bitmap, same as above but for per-cpu interrupts 56 */ 57 static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL; 58 ··· 90 int cpu = smp_processor_id(); 91 92 /* Clear in EIEM so we can no longer process */ 93 - if (CHECK_IRQ_PER_CPU(irq_desc[irq].status)) 94 - per_cpu(local_ack_eiem, cpu) &= ~mask; 95 - else 96 - global_ack_eiem &= ~mask; 97 98 /* disable the interrupt */ 99 - set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu)); 100 /* and now ack it */ 101 mtctl(mask, 23); 102 } ··· 105 int cpu = smp_processor_id(); 106 107 /* set it in the eiems---it's no longer in process */ 108 - if (CHECK_IRQ_PER_CPU(irq_desc[irq].status)) 109 - per_cpu(local_ack_eiem, cpu) |= mask; 110 - else 111 - global_ack_eiem |= mask; 112 113 /* enable the interrupt */ 114 - set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu)); 115 } 116 117 #ifdef CONFIG_SMP ··· 345 local_irq_disable(); 346 irq_enter(); 347 348 - eirr_val = mfctl(23) & cpu_eiem & global_ack_eiem & 349 - per_cpu(local_ack_eiem, cpu); 350 if (!eirr_val) 351 goto set_out; 352 irq = eirr_to_irq(eirr_val); ··· 371 return; 372 373 set_out: 374 - set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu)); 375 goto out; 376 } 377
··· 46 static volatile unsigned long cpu_eiem = 0; 47 48 /* 49 + ** local ACK bitmap ... habitually set to 1, but reset to zero 50 ** between ->ack() and ->end() of the interrupt to prevent 51 ** re-interruption of a processing interrupt. 52 */ 53 static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL; 54 ··· 94 int cpu = smp_processor_id(); 95 96 /* Clear in EIEM so we can no longer process */ 97 + per_cpu(local_ack_eiem, cpu) &= ~mask; 98 99 /* disable the interrupt */ 100 + set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu)); 101 + 102 /* and now ack it */ 103 mtctl(mask, 23); 104 } ··· 111 int cpu = smp_processor_id(); 112 113 /* set it in the eiems---it's no longer in process */ 114 + per_cpu(local_ack_eiem, cpu) |= mask; 115 116 /* enable the interrupt */ 117 + set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu)); 118 } 119 120 #ifdef CONFIG_SMP ··· 354 local_irq_disable(); 355 irq_enter(); 356 357 + eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu); 358 if (!eirr_val) 359 goto set_out; 360 irq = eirr_to_irq(eirr_val); ··· 381 return; 382 383 set_out: 384 + set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu)); 385 goto out; 386 } 387