Commit 1140a0c3 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Altix update: irq fixes

From: Pat Gefre <pfg@sgi.com>

arch/ia64/sn/kernel/irq.c
    Need to get the cpu from the passed in pcibr struct
    Made the interrupt list static and gave it a better name - credit jes
    Some lindent'isms
    Took out some code that isn't used ..... yet
parent 4046f9fb
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/bootmem.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/sn/sgi.h> #include <asm/sn/sgi.h>
...@@ -40,8 +41,12 @@ static void force_interrupt(int irq); ...@@ -40,8 +41,12 @@ static void force_interrupt(int irq);
extern void pcibr_force_interrupt(pcibr_intr_t intr); extern void pcibr_force_interrupt(pcibr_intr_t intr);
extern int sn_force_interrupt_flag; extern int sn_force_interrupt_flag;
static pcibr_intr_list_t *pcibr_intr_list; struct sn_intr_list_t {
struct sn_intr_list_t *next;
pcibr_intr_t intr;
};
static struct sn_intr_list_t *sn_intr_list[NR_IRQS];
static unsigned int static unsigned int
...@@ -114,25 +119,23 @@ sn_end_irq(unsigned int irq) ...@@ -114,25 +119,23 @@ sn_end_irq(unsigned int irq)
} }
static void static void
sn_set_affinity_irq(unsigned int irq, cpumask_t mask) sn_set_affinity_irq(unsigned int irq, unsigned long cpu)
{ {
#if CONFIG_SMP #if CONFIG_SMP
int redir = 0; int redir = 0;
pcibr_intr_list_t p = pcibr_intr_list[irq]; struct sn_intr_list_t *p = sn_intr_list[irq];
pcibr_intr_t intr; pcibr_intr_t intr;
int cpu;
extern void sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu); extern void sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu);
extern void sn_tio_redirect_intr(pcibr_intr_t intr, unsigned long cpu); extern void sn_tio_redirect_intr(pcibr_intr_t intr, unsigned long cpu);
if (p == NULL) if (p == NULL)
return; return;
intr = p->il_intr; intr = p->intr;
if (intr == NULL) if (intr == NULL)
return; return;
cpu = first_cpu(mask);
sn_shub_redirect_intr(intr, cpu); sn_shub_redirect_intr(intr, cpu);
(void) set_irq_affinity_info(irq, cpu_physical_id(intr->bi_cpu), redir); (void) set_irq_affinity_info(irq, cpu_physical_id(intr->bi_cpu), redir);
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
...@@ -152,7 +155,8 @@ struct hw_interrupt_type irq_type_sn = { ...@@ -152,7 +155,8 @@ struct hw_interrupt_type irq_type_sn = {
struct irq_desc * struct irq_desc *
sn_irq_desc(unsigned int irq) { sn_irq_desc(unsigned int irq)
{
irq = SN_IVEC_FROM_IRQ(irq); irq = SN_IVEC_FROM_IRQ(irq);
...@@ -160,12 +164,14 @@ sn_irq_desc(unsigned int irq) { ...@@ -160,12 +164,14 @@ sn_irq_desc(unsigned int irq) {
} }
u8 u8
sn_irq_to_vector(u8 irq) { sn_irq_to_vector(u8 irq)
{
return(irq); return(irq);
} }
unsigned int unsigned int
sn_local_vector_to_irq(u8 vector) { sn_local_vector_to_irq(u8 vector)
{
return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector)); return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector));
} }
...@@ -175,7 +181,7 @@ sn_irq_init (void) ...@@ -175,7 +181,7 @@ sn_irq_init (void)
int i; int i;
irq_desc_t *base_desc = _irq_desc; irq_desc_t *base_desc = _irq_desc;
for (i=IA64_FIRST_DEVICE_VECTOR; i<NR_IRQS; i++) { for (i=0; i<NR_IRQS; i++) {
if (base_desc[i].handler == &no_irq_type) { if (base_desc[i].handler == &no_irq_type) {
base_desc[i].handler = &irq_type_sn; base_desc[i].handler = &irq_type_sn;
} }
...@@ -183,60 +189,56 @@ sn_irq_init (void) ...@@ -183,60 +189,56 @@ sn_irq_init (void)
} }
void void
register_pcibr_intr(int irq, pcibr_intr_t intr) { register_pcibr_intr(int irq, pcibr_intr_t intr)
pcibr_intr_list_t p = kmalloc(sizeof(struct pcibr_intr_list_s), GFP_KERNEL); {
pcibr_intr_list_t list; struct sn_intr_list_t *p = kmalloc(sizeof(struct sn_intr_list_t), GFP_KERNEL);
int cpu = SN_CPU_FROM_IRQ(irq); struct sn_intr_list_t *list;
int cpu = intr->bi_cpu;
if (pcibr_intr_list == NULL) {
pcibr_intr_list = kmalloc(sizeof(pcibr_intr_list_t) * NR_IRQS, GFP_KERNEL);
if (pcibr_intr_list == NULL)
pcibr_intr_list = vmalloc(sizeof(pcibr_intr_list_t) * NR_IRQS);
if (pcibr_intr_list == NULL) panic("Could not allocate memory for pcibr_intr_list\n");
memset( (void *)pcibr_intr_list, 0, sizeof(pcibr_intr_list_t) * NR_IRQS);
}
if (pdacpu(cpu)->sn_last_irq < irq) { if (pdacpu(cpu)->sn_last_irq < irq) {
pdacpu(cpu)->sn_last_irq = irq; pdacpu(cpu)->sn_last_irq = irq;
} }
if (pdacpu(cpu)->sn_first_irq > irq) pdacpu(cpu)->sn_first_irq = irq; if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) pdacpu(cpu)->sn_first_irq = irq;
if (!p) panic("Could not allocate memory for pcibr_intr_list_t\n"); if (!p) panic("Could not allocate memory for sn_intr_list_t\n");
if ((list = pcibr_intr_list[irq])) { if ((list = sn_intr_list[irq])) {
while (list->il_next) list = list->il_next; while (list->next) list = list->next;
list->il_next = p; list->next = p;
p->il_next = NULL; p->next = NULL;
p->il_intr = intr; p->intr = intr;
} else { } else {
pcibr_intr_list[irq] = p; sn_intr_list[irq] = p;
p->il_next = NULL; p->next = NULL;
p->il_intr = intr; p->intr = intr;
} }
} }
void void
force_polled_int(void) { force_polled_int(void)
{
int i; int i;
pcibr_intr_list_t p; struct sn_intr_list_t *p;
for (i=0; i<NR_IRQS;i++) { for (i=0; i<NR_IRQS;i++) {
p = pcibr_intr_list[i]; p = sn_intr_list[i];
while (p) { while (p) {
if (p->il_intr){ if (p->intr){
pcibr_force_interrupt(p->il_intr); pcibr_force_interrupt(p->intr);
} }
p = p->il_next; p = p->next;
} }
} }
} }
static void static void
force_interrupt(int irq) { force_interrupt(int irq)
pcibr_intr_list_t p = pcibr_intr_list[irq]; {
struct sn_intr_list_t *p = sn_intr_list[irq];
while (p) { while (p) {
if (p->il_intr) { if (p->intr) {
pcibr_force_interrupt(p->il_intr); pcibr_force_interrupt(p->intr);
} }
p = p->il_next; p = p->next;
} }
} }
...@@ -251,7 +253,8 @@ but we should never miss a real lost interrupt. ...@@ -251,7 +253,8 @@ but we should never miss a real lost interrupt.
*/ */
static void static void
sn_check_intr(int irq, pcibr_intr_t intr) { sn_check_intr(int irq, pcibr_intr_t intr)
{
unsigned long regval; unsigned long regval;
int irr_reg_num; int irr_reg_num;
int irr_bit; int irr_bit;
...@@ -290,68 +293,20 @@ sn_check_intr(int irq, pcibr_intr_t intr) { ...@@ -290,68 +293,20 @@ sn_check_intr(int irq, pcibr_intr_t intr) {
} }
void void
sn_lb_int_war_check(void) { sn_lb_int_war_check(void)
{
int i; int i;
if (pda->sn_first_irq == 0) return; if (pda->sn_first_irq == 0) return;
for (i=pda->sn_first_irq; for (i=pda->sn_first_irq;
i <= pda->sn_last_irq; i++) { i <= pda->sn_last_irq; i++) {
pcibr_intr_list_t p = pcibr_intr_list[i]; struct sn_intr_list_t *p = sn_intr_list[i];
if (p == NULL) { if (p == NULL) {
continue; continue;
} }
while (p) { while (p) {
sn_check_intr(i, p->il_intr); sn_check_intr(i, p->intr);
p = p->il_next; p = p->next;
} }
} }
} }
static inline int
sn_get_next_bit(void) {
int i;
int bit;
for (i = 3; i >= 0; i--) {
if (pda->sn_soft_irr[i] != 0) {
bit = (i * 64) + __ffs(pda->sn_soft_irr[i]);
__change_bit(bit, (volatile void *)pda->sn_soft_irr);
return(bit);
}
}
return IA64_SPURIOUS_INT_VECTOR;
}
void
sn_set_tpr(int vector) {
if (vector > IA64_LAST_DEVICE_VECTOR || vector < IA64_FIRST_DEVICE_VECTOR) {
ia64_setreg(_IA64_REG_CR_TPR, vector);
} else {
ia64_setreg(_IA64_REG_CR_TPR, IA64_LAST_DEVICE_VECTOR);
}
}
static inline void
sn_get_all_ivr(void) {
int vector;
vector = ia64_get_ivr();
while (vector != IA64_SPURIOUS_INT_VECTOR) {
__set_bit(vector, (volatile void *)pda->sn_soft_irr);
ia64_eoi();
if (vector > IA64_LAST_DEVICE_VECTOR) return;
vector = ia64_get_ivr();
}
}
int
sn_get_ivr(void) {
int vector;
vector = sn_get_next_bit();
if (vector == IA64_SPURIOUS_INT_VECTOR) {
sn_get_all_ivr();
vector = sn_get_next_bit();
}
return vector;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment