Multiple vector domain support - IOSAPIC support
RFC PATCH 7/10 Multiple vector domain support - IOSAPIC support
This patch changes IOSAPIC code to support multiple vector domain.
Signed-off-by Kenji Kaneshige <[email protected]>
---
linux-2.6.13-rc1-kanesige/arch/ia64/kernel/iosapic.c | 354 +++++++++++-------- 1 files changed, 220 insertions(+), 134 deletions(-)
arch/ia64/kernel/iosapic.c renamed from arch/ia64/kernel/iosapic.c~vector-domain-ia64-iosapic +220 -134
@@ -123,7 +123,7 @@ static struct iosapic_intr_info { unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */ unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ -} iosapic_intr_info[IA64_NUM_VECTORS ]; +} iosapic_intr_info[NR_GSVS ]; static struct iosapic { char __iomem *addr; /* base address of IOSAPIC */
@@ -157,12 +157,12 @@ find_iosapic (unsigned int gsi) }static inline int -_gsi_to_vector (unsigned int gsi) +gsi_to_gsv (unsigned int gsi) {struct iosapic_intr_info *info;struct iosapic_rte_info *rte; -for (info = iosapic_intr_info; info < iosapic_intr_info +IA64_NUM_VECTORS ; ++info) +for (info = iosapic_intr_info; info < iosapic_intr_info +NR_GSVS ; ++info)list_for_each_entry (rte, &info->rtes, rte_list)if (rte->gsi_base + rte->rte_index = gsi)return info - iosapic_intr_info;
@@ -176,7 +176,7 @@ _gsi_to_vector (unsigned int gsi)inline int gsi_to_vector (unsigned int gsi) { -return _gsi_to_vector (gsi); +return gsv_to_vector (gsi_to_gsv (gsi)); }int
@@ -184,31 +184,29 @@ gsi_to_irq (unsigned int gsi) {unsigned long flags;int irq; -/* -* XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq -* numbers... -*/ +spin_lock_irqsave (&iosapic_lock, flags); { - irq =_gsi_to_vector (gsi); + irq =gsv_to_irq (gsi_to_gsv (gsi)); }spin_unlock_irqrestore (&iosapic_lock, flags);return irq; } -static struct iosapic_rte_info *gsi_vector_to_rte (unsigned int gsi,unsigned int vec) +static struct iosapic_rte_info * +gsi_gsv_to_rte (unsigned int gsi,unsigned int gsv) {struct iosapic_rte_info *rte; -list_for_each_entry (rte, &iosapic_intr_info[vec].rtes, rte_list) +list_for_each_entry (rte, &iosapic_intr_info[gsv].rtes, rte_list)if (rte->gsi_base + rte->rte_index = gsi)return rte;return NULL ; }static void -set_rte (unsigned int gsi,unsigned int vector,unsigned int dest,int mask) +set_rte (unsigned int gsi,unsigned int gsv,unsigned int dest,int mask) {unsigned long pol, trigger, dmode;u32 low32, high32;
@@ -216,30 +214,26 @@ set_rte (unsigned int gsi, unsigned intint rte_index;char redir;struct iosapic_rte_info *rte; +unsigned int vector =gsv_to_vector (gsv);DBG (KERN_DEBUG "IOSAPIC: routing vector %d to 0x%x\n" , vector, dest); - rte =gsi_vector_to_rte (gsi, vector); + rte =gsi_gsv_to_rte (gsi, gsv);if (!rte)return ;/* not an IOSAPIC interrupt */ rte_index = rte->rte_index; addr = rte->addr; - pol = iosapic_intr_info[vector].polarity; - trigger = iosapic_intr_info[vector].trigger; - dmode = iosapic_intr_info[vector].dmode; + pol = iosapic_intr_info[gsv].polarity; + trigger = iosapic_intr_info[gsv].trigger; + dmode = iosapic_intr_info[gsv].dmode; redir = (dmode =IOSAPIC_LOWEST_PRIORITY ) ?1 :0 ;#ifdef CONFIG_SMP { -unsigned int irq; - -for (irq =0 ; irq <NR_IRQS ; ++irq) -if (irq_to_vector (irq) = vector) { -set_irq_affinity_info (irq, (int )(dest &0xffff ), redir); -break ; - } +unsigned int irq =gsv_to_irq (gsv); +set_irq_affinity_info (irq, (int )(dest &0xffff ), redir); }#endif
@@ -254,8 +248,8 @@ set_rte (unsigned int gsi, unsigned intiosapic_write (addr,IOSAPIC_RTE_HIGH (rte_index), high32);iosapic_write (addr,IOSAPIC_RTE_LOW (rte_index), low32); - iosapic_intr_info[vector].low32 = low32; - iosapic_intr_info[vector].dest = dest; + iosapic_intr_info[gsv].low32 = low32; + iosapic_intr_info[gsv].dest = dest; } static void
@@ -271,17 +265,17 @@ mask_irq (unsigned int irq)char __iomem *addr;u32 low32;int rte_index; -ia64_vector vec =irq_to_vector (irq); +unsigned int gsv =irq_to_gsv (irq);struct iosapic_rte_info *rte; -if (list_empty (&iosapic_intr_info[vec].rtes)) +if (list_empty (&iosapic_intr_info[gsv].rtes))return ;/* not an IOSAPIC interrupt! */ spin_lock_irqsave (&iosapic_lock, flags); {/* set only the mask bit */ - low32 = iosapic_intr_info[vec].low32 |=IOSAPIC_MASK ; -list_for_each_entry (rte, &iosapic_intr_info[vec].rtes, rte_list) { + low32 = iosapic_intr_info[gsv].low32 |=IOSAPIC_MASK ; +list_for_each_entry (rte, &iosapic_intr_info[gsv].rtes, rte_list) { addr = rte->addr; rte_index = rte->rte_index;iosapic_write (addr,IOSAPIC_RTE_LOW (rte_index), low32);
@@ -297,16 +291,16 @@ unmask_irq (unsigned int irq)char __iomem *addr;u32 low32;int rte_index; -ia64_vector vec =irq_to_vector (irq); +unsigned int gsv =irq_to_gsv (irq);struct iosapic_rte_info *rte; -if (list_empty (&iosapic_intr_info[vec].rtes)) +if (list_empty (&iosapic_intr_info[gsv].rtes))return ;/* not an IOSAPIC interrupt! */ spin_lock_irqsave (&iosapic_lock, flags); { - low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK ; -list_for_each_entry (rte, &iosapic_intr_info[vec].rtes, rte_list) { + low32 = iosapic_intr_info[gsv].low32 &= ~IOSAPIC_MASK ; +list_for_each_entry (rte, &iosapic_intr_info[gsv].rtes, rte_list) { addr = rte->addr; rte_index = rte->rte_index;iosapic_write (addr,IOSAPIC_RTE_LOW (rte_index), low32);
@@ -322,21 +316,27 @@ iosapic_set_affinity (unsigned int irq,#ifdef CONFIG_SMP unsigned long flags;u32 high32, low32; -int dest, rte_index; +int cpu, dest, rte_index, gsv;char __iomem *addr;int redir = (irq &IA64_IRQ_REDIRECTED ) ?1 :0 ; -ia64_vector vec;struct iosapic_rte_info *rte; irq &= (~IA64_IRQ_REDIRECTED ); - vec =irq_to_vector (irq); + gsv =irq_to_gsv (irq);if (cpus_empty (mask))return ; - dest =cpu_physical_id (first_cpu (mask)); + cpu =first_cpu (mask); + dest =cpu_physical_id (cpu); -if (list_empty (&iosapic_intr_info[vec].rtes)) +/* +* XXX - IRQ migration between different domains is not supported yet. +*/ +if (!cpu_isset (cpu,ia64_domain_to_cpumask (gsv_to_domain (gsv)))) +return ; + +if (list_empty (&iosapic_intr_info[gsv].rtes))return ;/* not an IOSAPIC interrupt */ set_irq_affinity_info (irq, dest, redir);
@@ -346,7 +346,7 @@ iosapic_set_affinity (unsigned int irq,spin_lock_irqsave (&iosapic_lock, flags); { - low32 = iosapic_intr_info[vec].low32 & ~(7 <<IOSAPIC_DELIVERY_SHIFT ); + low32 = iosapic_intr_info[gsv].low32 & ~(7 <<IOSAPIC_DELIVERY_SHIFT );if (redir)/* change delivery mode to lowest priority */
@@ -355,9 +355,9 @@ iosapic_set_affinity (unsigned int irq,/* change delivery mode to fixed */ low32 |= (IOSAPIC_FIXED <<IOSAPIC_DELIVERY_SHIFT ); - iosapic_intr_info[vec].low32 = low32; - iosapic_intr_info[vec].dest = dest; -list_for_each_entry (rte, &iosapic_intr_info[vec].rtes, rte_list) { + iosapic_intr_info[gsv].low32 = low32; + iosapic_intr_info[gsv].dest = dest; +list_for_each_entry (rte, &iosapic_intr_info[gsv].rtes, rte_list) { addr = rte->addr; rte_index = rte->rte_index;iosapic_write (addr,IOSAPIC_RTE_HIGH (rte_index), high32);
@@ -382,11 +382,12 @@ iosapic_startup_level_irq (unsigned intstatic void iosapic_end_level_irq (unsigned int irq) { -ia64_vector vec =irq_to_vector (irq); +unsigned int gsv =irq_to_gsv (irq); +ia64_vector vec =gsv_to_vector (gsv);struct iosapic_rte_info *rte;move_irq (irq); -list_for_each_entry (rte, &iosapic_intr_info[vec].rtes, rte_list) +list_for_each_entry (rte, &iosapic_intr_info[gsv].rtes, rte_list)iosapic_eoi (rte->addr, vec); }
@@ -467,9 +468,10 @@ iosapic_version (char __iomem *addr)return iosapic_read (addr,IOSAPIC_VERSION ); } -static int iosapic_find_sharable_vector (unsigned long trigger,unsigned long pol) +static int +__iosapic_find_sharable_gsv (unsigned long trigger,unsigned long pol,int domain) { -int i, vector =-1 , min_count =-1 ; +int i, min_count =-1 , gsv =-1 ;struct iosapic_intr_info *info;/*
@@ -479,20 +481,38 @@ static int iosapic_find_sharable_vectorif (trigger =IOSAPIC_EDGE )return -1 ; -for (i =IA64_FIRST_DEVICE_VECTOR ; i <=IA64_LAST_DEVICE_VECTOR ; i++) { +for (i =domain_vector_to_gsv (domain,IA64_FIRST_DEVICE_VECTOR ); + i <=domain_vector_to_gsv (domain,IA64_LAST_DEVICE_VECTOR ); i++) { info = &iosapic_intr_info[i];if (info->trigger = trigger && info->polarity = pol && (info->dmode =IOSAPIC_FIXED || info->dmode =IOSAPIC_LOWEST_PRIORITY )) {if (min_count =-1 || info->count < min_count) { - vector = i; + gsv = i; min_count = info->count; } } } -if (vector <0 ) -panic ("%s: out of interrupt vectors!\n" , __FUNCTION__); +return gsv; +} + +static int +iosapic_find_sharable_gsv (unsigned long trigger,unsigned long pol,int domain) +{ +static int next_domain =0 ; +int i, gsv; -return vector; +if (domain =AUTO_ASSIGN ) { +for (i =0 ; i <NR_VECTOR_DOMAINS ; i++) { + gsv =__iosapic_find_sharable_gsv (trigger, pol, next_domain++); +if (next_domain >=NR_VECTOR_DOMAINS ) + next_domain =0 ; +if (gsv >=0 ) +break ; + } +return gsv; + } +else +return __iosapic_find_sharable_gsv (trigger, pol, domain); }/*
@@ -500,20 +520,21 @@ static int iosapic_find_sharable_vector* assign a new vector for the other and make the vector available */ static void __init -iosapic_reassign_vector (int vector) +iosapic_reassign_gsv (unsigned int gsv) { -int new_vector; +int new_gsv; -if (!list_empty (&iosapic_intr_info[vector].rtes)) { - new_vector =assign_irq_vector (AUTO_ASSIGN ); -printk (KERN_INFO "Reassigning vector %d to %d\n" , vector, new_vector); -memcpy (&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], +if (!list_empty (&iosapic_intr_info[gsv].rtes)) { + new_gsv =assign_irq_gsv (AUTO_ASSIGN ,gsv_to_domain (gsv)); +printk (KERN_INFO "Reassigning vector %d to %d\n" , +gsv_to_vector (gsv),gsv_to_vector (new_gsv)); +memcpy (&iosapic_intr_info[new_gsv], &iosapic_intr_info[gsv],sizeof (struct iosapic_intr_info )); -INIT_LIST_HEAD (&iosapic_intr_info[new_vector].rtes); -list_move (iosapic_intr_info[vector].rtes.next, &iosapic_intr_info[new_vector].rtes); -memset (&iosapic_intr_info[vector],0 ,sizeof (struct iosapic_intr_info )); - iosapic_intr_info[vector].low32 =IOSAPIC_MASK ; -INIT_LIST_HEAD (&iosapic_intr_info[vector].rtes); +INIT_LIST_HEAD (&iosapic_intr_info[new_gsv].rtes); +list_move (iosapic_intr_info[gsv].rtes.next, &iosapic_intr_info[new_gsv].rtes); +memset (&iosapic_intr_info[gsv],0 ,sizeof (struct iosapic_intr_info )); + iosapic_intr_info[gsv].low32 =IOSAPIC_MASK ; +INIT_LIST_HEAD (&iosapic_intr_info[gsv].rtes); } }
@@ -556,13 +577,13 @@ static void iosapic_free_rte (struct ioskfree (rte); } -static inline int vector_is_shared (int vector) +static inline int gsv_is_shared (unsigned int gsv) { -return (iosapic_intr_info[vector].count >1 ); +return (iosapic_intr_info[gsv].count >1 ); }static void -register_intr (unsigned int gsi,int vector,unsigned char delivery, +register_intr (unsigned int gsi,unsigned int gsv,unsigned char delivery,unsigned long polarity,unsigned long trigger) {irq_desc_t *idesc;
@@ -582,7 +603,7 @@ register_intr (unsigned int gsi, int vec iosapic_address = iosapic_lists[index].addr; gsi_base = iosapic_lists[index].gsi_base; - rte =gsi_vector_to_rte (gsi, vector); + rte =gsi_gsv_to_rte (gsi, gsv);if (!rte) { rte =iosapic_alloc_rte ();if (!rte) {
@@ -595,48 +616,99 @@ register_intr (unsigned int gsi, int vec rte->addr = iosapic_address; rte->gsi_base = gsi_base; rte->refcnt++; -list_add_tail (&rte->rte_list, &iosapic_intr_info[vector].rtes); - iosapic_intr_info[vector].count++; +list_add_tail (&rte->rte_list, &iosapic_intr_info[gsv].rtes); + iosapic_intr_info[gsv].count++; iosapic_lists[index].rtes_inuse++; } -else if (vector_is_shared (vector)) { -struct iosapic_intr_info *info = &iosapic_intr_info[vector]; +else if (gsv_is_shared (gsv)) { +struct iosapic_intr_info *info = &iosapic_intr_info[gsv];if (info->trigger != trigger || info->polarity != polarity) {printk (KERN_WARNING "%s: cannot override the interrupt\n" , __FUNCTION__);return ; } } - iosapic_intr_info[vector].polarity = polarity; - iosapic_intr_info[vector].dmode = delivery; - iosapic_intr_info[vector].trigger = trigger; + iosapic_intr_info[gsv].polarity = polarity; + iosapic_intr_info[gsv].dmode = delivery; + iosapic_intr_info[gsv].trigger = trigger;if (trigger =IOSAPIC_EDGE ) irq_type = &irq_type_iosapic_edge;else irq_type = &irq_type_iosapic_level; - idesc =irq_descp (vector); + idesc =irq_descp (gsv_to_irq (gsv));if (idesc->handler != irq_type) {if (idesc->handler != &no_irq_type)printk (KERN_WARNING "%s: changing vector %d from %s to %s\n" , - __FUNCTION__, vector, idesc->handler->typename, irq_type->typename); + __FUNCTION__,gsv_to_vector (gsv), + idesc->handler->typename, irq_type->typename); idesc->handler = irq_type; } } +int +get_target_domain (unsigned int gsi) +{ +#ifdef CONFIG_VECTOR_DOMAIN +/* +* Some interrupts (ACPI SCI, for instance) are registered +* before the BSP is marked as online. +*/ +if (!cpu_online (smp_processor_id ())) +return ia64_cpu_to_domain (smp_processor_id ()); + +#ifdef CONFIG_NUMA + { +int num_cpus, cpu_index, iosapic_index, numa_cpu, i =0 ; +cpumask_t cpu_mask; + + iosapic_index =find_iosapic (gsi); +if (iosapic_index <0 || + iosapic_lists[iosapic_index].node =MAX_NUMNODES ) + goto skip_numa_setup; + + cpu_mask =node_to_cpumask (iosapic_lists[iosapic_index].node); + +for_each_cpu_mask (numa_cpu, cpu_mask) { +if (!cpu_online (numa_cpu)) +cpu_clear (numa_cpu, cpu_mask); + } + + num_cpus =cpus_weight (cpu_mask); + +if (!num_cpus) + goto skip_numa_setup; + +/* Use vector assigment to distribute across cpus in node */ + cpu_index = gsi % num_cpus; + +for (numa_cpu =first_cpu (cpu_mask) ; i < cpu_index ; i++) + numa_cpu =next_cpu (numa_cpu, cpu_mask); + +if (numa_cpu !=NR_CPUS ) +return ia64_cpu_to_domain (numa_cpu); + } +skip_numa_setup: +#endif + +#endif /* CONFIG_VECTOR_DOMAIN */ +return AUTO_ASSIGN ; +} +static unsigned int -get_target_cpu (unsigned int gsi,int vector) +get_target_cpu (unsigned int gsi,unsigned int gsv) {#ifdef CONFIG_SMP static int cpu =-1 ; +int domain;/* * In case of vector shared by multiple RTEs, all RTEs that * share the vector need to use the same destination CPU. */ -if (!list_empty (&iosapic_intr_info[vector].rtes)) -return iosapic_intr_info[vector].dest; +if (!list_empty (&iosapic_intr_info[gsv].rtes)) +return iosapic_intr_info[gsv].dest;/* * If the platform supports redirection via XTP, let it
@@ -652,6 +724,8 @@ get_target_cpu (unsigned int gsi, int veif (!cpu_online (smp_processor_id ()))return cpu_physical_id (smp_processor_id ()); + domain =gsv_to_domain (gsv); +#ifdef CONFIG_NUMA {int num_cpus, cpu_index, iosapic_index, numa_cpu, i =0 ;
@@ -662,7 +736,9 @@ get_target_cpu (unsigned int gsi, int ve iosapic_lists[iosapic_index].node = MAX_NUMNODES) goto skip_numa_setup; - cpu_mask =node_to_cpumask (iosapic_lists[iosapic_index].node); +cpus_and (cpu_mask, +node_to_cpumask (iosapic_lists[iosapic_index].node), +ia64_domain_to_cpumask (domain));for_each_cpu_mask (numa_cpu, cpu_mask) {if (!cpu_online (numa_cpu))
@@ -675,7 +751,7 @@ get_target_cpu (unsigned int gsi, int ve goto skip_numa_setup;/* Use vector assigment to distribute across cpus in node */ - cpu_index = vector % num_cpus; + cpu_index = gsv % num_cpus;for (numa_cpu =first_cpu (cpu_mask) ; i < cpu_index ; i++) numa_cpu =next_cpu (numa_cpu, cpu_mask);
@@ -693,7 +769,7 @@ skip_numa_setup:do {if (++cpu >=NR_CPUS ) cpu =0 ; - }while (!cpu_online (cpu)); + }while (!cpu_isset (cpu,ia64_domain_to_cpumask (domain)));return cpu_physical_id (cpu);#else
@@ -710,11 +786,12 @@ int iosapic_register_intr (unsigned int gsi, unsigned long polarity, unsigned long trigger) { - int vector, mask = 1; + int mask = 1, domain, gsv;unsigned int dest;unsigned long flags;struct iosapic_rte_info *rte;u32 low32; +irq_desc_t *idesc; again:/* * If this GSI has already been registered (i.e., it's a
@@ -723,54 +800,59 @@ again:*/ spin_lock_irqsave (&iosapic_lock, flags); { - vector =gsi_to_vector (gsi); -if (vector >0 ) { - rte =gsi_vector_to_rte (gsi, vector); + gsv =gsi_to_gsv (gsi); +if (gsv >0 ) { + rte =gsi_gsv_to_rte (gsi, gsv); rte->refcnt++;spin_unlock_irqrestore (&iosapic_lock, flags); -return vector; +return gsv_to_irq (gsv); } }spin_unlock_irqrestore (&iosapic_lock, flags); + domain =get_target_domain (gsi);/* If vector is running out, we try to find a sharable vector */ - vector =assign_irq_vector_nopanic (AUTO_ASSIGN ); -if (vector <0 ) - vector =iosapic_find_sharable_vector (trigger, polarity); + gsv =assign_irq_gsv (AUTO_ASSIGN , domain); +if (gsv <0 ) { + gsv =iosapic_find_sharable_gsv (trigger, polarity, domain); +if (gsv <0 ) +panic ("%s: out of interrupt vectors!\n" , __FUNCTION__); + } -spin_lock_irqsave (&irq_descp (vector)->lock, flags); + idesc =irq_descp (gsv_to_irq (gsv)); +spin_lock_irqsave (&idesc->lock, flags);spin_lock (&iosapic_lock); { -if (gsi_to_vector (gsi) >0 ) { -if (list_empty (&iosapic_intr_info[vector].rtes)) -free_irq_vector (vector); +if (gsi_to_gsv (gsi) >0 ) { +if (list_empty (&iosapic_intr_info[gsv].rtes)) +free_irq_gsv (gsv);spin_unlock (&iosapic_lock); -spin_unlock_irqrestore (&irq_descp (vector)->lock, flags); +spin_unlock_irqrestore (&idesc->lock, flags); goto again; } - dest =get_target_cpu (gsi, vector); -register_intr (gsi, vector,IOSAPIC_LOWEST_PRIORITY , + dest =get_target_cpu (gsi, gsv); +register_intr (gsi, gsv,IOSAPIC_LOWEST_PRIORITY , polarity, trigger);/* * If the vector is shared and already unmasked for * other interrupt sources, don't mask it. */ - low32 = iosapic_intr_info[vector].low32; -if (vector_is_shared (vector) && !(low32 &IOSAPIC_MASK )) + low32 = iosapic_intr_info[gsv].low32; +if (gsv_is_shared (gsv) && !(low32 &IOSAPIC_MASK )) mask =0 ; -set_rte (gsi, vector, dest, mask); +set_rte (gsi, gsv, dest, mask); }spin_unlock (&iosapic_lock); -spin_unlock_irqrestore (&irq_descp (vector)->lock, flags); +spin_unlock_irqrestore (&idesc->lock, flags);printk (KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n" , gsi, (trigger =IOSAPIC_EDGE ?"edge" :"level" ), (polarity =IOSAPIC_POL_HIGH ?"high" :"low" ), -cpu_logical_id (dest), dest, vector); +cpu_logical_id (dest), dest,gsv_to_vector (gsv)); -return vector; +return gsv_to_irq (gsv); }#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
@@ -778,11 +860,11 @@ void iosapic_unregister_intr (unsigned int gsi) {unsigned long flags; -int irq, vector, index; +int irq, index;irq_desc_t *idesc;u32 low32;unsigned long trigger, polarity; -unsigned int dest; +unsigned int gsv, dest;struct iosapic_rte_info *rte;/*
@@ -796,13 +878,13 @@ iosapic_unregister_intr (unsigned int gsWARN_ON (1 );return ; } - vector =irq_to_vector (irq); + gsv =irq_to_gsv (irq); idesc =irq_descp (irq);spin_lock_irqsave (&idesc->lock, flags);spin_lock (&iosapic_lock); { -if ((rte =gsi_vector_to_rte (gsi, vector)) =NULL ) { +if ((rte =gsi_gsv_to_rte (gsi, gsv)) =NULL ) {printk (KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n" , gsi);WARN_ON (1 ); goto out;
@@ -812,36 +894,36 @@ iosapic_unregister_intr (unsigned int gs goto out;/* Mask the interrupt */ - low32 = iosapic_intr_info[vector].low32 |IOSAPIC_MASK ; + low32 = iosapic_intr_info[gsv].low32 |IOSAPIC_MASK ;iosapic_write (rte->addr,IOSAPIC_RTE_LOW (rte->rte_index), low32);/* Remove the rte entry from the list */ list_del (&rte->rte_list); - iosapic_intr_info[vector].count--; + iosapic_intr_info[gsv].count--;iosapic_free_rte (rte); index =find_iosapic (gsi); iosapic_lists[index].rtes_inuse--;WARN_ON (iosapic_lists[index].rtes_inuse <0 ); - trigger = iosapic_intr_info[vector].trigger; - polarity = iosapic_intr_info[vector].polarity; - dest = iosapic_intr_info[vector].dest; + trigger = iosapic_intr_info[gsv].trigger; + polarity = iosapic_intr_info[gsv].polarity; + dest = iosapic_intr_info[gsv].dest;printk (KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n" , gsi, (trigger =IOSAPIC_EDGE ?"edge" :"level" ), (polarity =IOSAPIC_POL_HIGH ?"high" :"low" ), -cpu_logical_id (dest), dest, vector); +cpu_logical_id (dest), dest,gsv_to_vector (gsv)); -if (list_empty (&iosapic_intr_info[vector].rtes)) { +if (list_empty (&iosapic_intr_info[gsv].rtes)) {/* Sanity check */ -BUG_ON (iosapic_intr_info[vector].count); +BUG_ON (iosapic_intr_info[gsv].count);/* Clear the interrupt controller descriptor */ idesc->handler = &no_irq_type;/* Clear the interrupt information */ -memset (&iosapic_intr_info[vector],0 ,sizeof (struct iosapic_intr_info )); - iosapic_intr_info[vector].low32 |=IOSAPIC_MASK ; -INIT_LIST_HEAD (&iosapic_intr_info[vector].rtes); +memset (&iosapic_intr_info[gsv],0 ,sizeof (struct iosapic_intr_info )); + iosapic_intr_info[gsv].low32 |=IOSAPIC_MASK ; +INIT_LIST_HEAD (&iosapic_intr_info[gsv].rtes);if (idesc->action) {printk (KERN_ERR "interrupt handlers still exist on IRQ %u\n" , irq);
@@ -849,7 +931,7 @@ iosapic_unregister_intr (unsigned int gs }/* Free the interrupt vector */ -free_irq_vector (vector); +free_irq_gsv (gsv); } } out:
@@ -869,25 +951,26 @@ iosapic_register_platform_intr (u32 int_ {static const char *const name[] = {"unknown" ,"PMI" ,"INIT" ,"CPEI" };unsigned char delivery; -int vector, mask =0 ; -unsigned int dest = ((id <<8 ) | eid) &0xffff ; +int mask =0 ; +unsigned int gsv, dest = ((id <<8 ) | eid) &0xffff ; +int domain =ia64_cpu_to_domain (cpu_logical_id (dest));switch (int_type) {case ACPI_INTERRUPT_PMI : - vector = iosapic_vector; + gsv =domain_vector_to_gsv (domain, iosapic_vector);/* * since PMI vector is alloc'd by FW(ACPI) not by kernel, * we need to make sure the vector is available */ -iosapic_reassign_vector (vector); +iosapic_reassign_gsv (gsv); delivery =IOSAPIC_PMI ;break ;case ACPI_INTERRUPT_INIT : - vector =assign_irq_vector (AUTO_ASSIGN ); + gsv =assign_irq_gsv (AUTO_ASSIGN , domain); delivery =IOSAPIC_INIT ;break ;case ACPI_INTERRUPT_CPEI : - vector =IA64_CPE_VECTOR ; + gsv =domain_vector_to_gsv (domain,IA64_CPE_VECTOR ); delivery =IOSAPIC_LOWEST_PRIORITY ; mask =1 ;break ;
@@ -896,16 +979,16 @@ iosapic_register_platform_intr (u32 int_return -1 ; } -register_intr (gsi, vector, delivery, polarity, trigger); +register_intr (gsi, gsv, delivery, polarity, trigger);printk (KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n" , int_type <ARRAY_SIZE (name) ? name[int_type] :"unknown" , int_type, gsi, (trigger =IOSAPIC_EDGE ?"edge" :"level" ), (polarity =IOSAPIC_POL_HIGH ?"high" :"low" ), -cpu_logical_id (dest), dest, vector); +cpu_logical_id (dest), dest,gsv_to_vector (gsv)); -set_rte (gsi, vector, dest, mask); -return vector; +set_rte (gsi, gsv, dest, mask); +return gsv_to_vector (gsv); }
@@ -919,28 +1002,31 @@ iosapic_override_isa_irq (unsigned int i unsigned long trigger) {int vector; +unsigned int gsv;unsigned int dest =cpu_physical_id (smp_processor_id ()); +unsigned int domain =ia64_cpu_to_domain (smp_processor_id ()); vector =isa_irq_to_vector (isa_irq); + gsv =domain_vector_to_gsv (domain, vector); -register_intr (gsi, vector,IOSAPIC_LOWEST_PRIORITY , polarity, trigger); +register_intr (gsi, gsv,IOSAPIC_LOWEST_PRIORITY , polarity, trigger);DBG ("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n" , isa_irq, gsi, trigger =IOSAPIC_EDGE ?"edge" :"level" , polarity =IOSAPIC_POL_HIGH ?"high" :"low" ,cpu_logical_id (dest), dest, vector); -set_rte (gsi, vector, dest,1 ); +set_rte (gsi, gsv, dest,1 ); }void __init iosapic_system_init (int system_pcat_compat) { -int vector; +unsigned int gsv; -for (vector =0 ; vector <IA64_NUM_VECTORS ; ++vector) { - iosapic_intr_info[vector].low32 =IOSAPIC_MASK ; -INIT_LIST_HEAD (&iosapic_intr_info[vector].rtes);/* mark as unused */ +for (gsv =0 ; gsv <NR_GSVS ; ++gsv) { + iosapic_intr_info[gsv].low32 =IOSAPIC_MASK ; +INIT_LIST_HEAD (&iosapic_intr_info[gsv].rtes);/* mark as unused */ } pcat_compat = system_pcat_compat;
_