This patch adds the code to allocate vectors in each domains. This
patch also contains the basic code to eliminate identity mapping
between IA-64 vectors and linux IRQs.

Signed-off-by: Kenji Kaneshige <[EMAIL PROTECTED]>

---

 linux-2.6.13-rc1-kanesige/arch/ia64/kernel/irq_ia64.c |  129 ++++++++++++++----
 linux-2.6.13-rc1-kanesige/include/asm-ia64/hw_irq.h   |    4 
 2 files changed, 107 insertions(+), 26 deletions(-)

diff -puN arch/ia64/kernel/irq_ia64.c~vector-domain-ia64-assign_irq_gsv 
arch/ia64/kernel/irq_ia64.c
--- 
linux-2.6.13-rc1/arch/ia64/kernel/irq_ia64.c~vector-domain-ia64-assign_irq_gsv  
    2005-07-13 14:51:42.000000000 +0900
+++ linux-2.6.13-rc1-kanesige/arch/ia64/kernel/irq_ia64.c       2005-07-13 
16:12:35.000000000 +0900
@@ -63,44 +63,124 @@ EXPORT_SYMBOL(isa_irq_to_vector_map);
 int ia64_irq_to_gsv_map[NR_IRQS] = { [0 ... NR_IRQS-1] = -1 };
 int ia64_gsv_to_irq_map[NR_GSVS] = { [0 ... NR_GSVS-1] = -1 };
 
-static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
+static unsigned long 
ia64_vector_mask[NR_VECTOR_DOMAINS][BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
 
-int
-assign_irq_vector_nopanic (int irq)
+static int
+ia64_alloc_vector (unsigned int domain)
+{
+       int pos, vec;
+       do {
+               pos = find_first_zero_bit(ia64_vector_mask[domain],
+                                         IA64_NUM_DEVICE_VECTORS);
+               vec = IA64_FIRST_DEVICE_VECTOR + pos;
+               if (vec > IA64_LAST_DEVICE_VECTOR)
+                       return -ENOSPC;
+       } while (test_and_set_bit(pos, ia64_vector_mask[domain]));
+       return vec;
+}
+
+static void
+ia64_free_vector (unsigned int domain, unsigned int vector)
+{
+       int pos;
+
+       if (domain >= NR_VECTOR_DOMAINS ||
+           vector < IA64_FIRST_DEVICE_VECTOR ||
+           vector > IA64_LAST_DEVICE_VECTOR)
+               return;
+
+       pos = vector - IA64_FIRST_DEVICE_VECTOR;
+       if (!test_and_clear_bit(pos, ia64_vector_mask[domain]))
+               printk(KERN_WARNING "%s: double free vector!\n", __FUNCTION__);
+}
+
+static unsigned long ia64_irq_mask[BITS_TO_LONGS(NR_IRQS)];
+
+static int
+ia64_alloc_irq (void)
+{
+       int irq;
+       do {
+               irq = find_first_zero_bit(ia64_irq_mask, NR_IRQS);
+               if (irq > NR_IRQS)
+                       return -1;
+       } while (test_and_set_bit(irq, ia64_irq_mask));
+       return irq;
+}
+
+static void
+ia64_free_irq (unsigned int irq)
+{
+       if (irq >= NR_IRQS)
+               return;
+
+       if (!test_and_clear_bit(irq, ia64_irq_mask))
+               printk(KERN_WARNING "%s: double free irq!\n", __FUNCTION__);
+}
+
+static int
+assign_irq_gsv_domain (int irq, int domain)
 {
-       int pos, vector;
- again:
-       pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS);
-       vector = IA64_FIRST_DEVICE_VECTOR + pos;
-       if (vector > IA64_LAST_DEVICE_VECTOR)
-               return -1;
-       if (test_and_set_bit(pos, ia64_vector_mask))
-               goto again;
-       return vector;
+       int vector, gsv;
+
+       if ((vector = ia64_alloc_vector(domain)) < 0)
+               return -ENOSPC;
+
+       if ((irq = ia64_alloc_irq()) < 0) {
+               ia64_free_vector(domain, vector);
+               return -ENOSPC;
+       }
+
+       gsv = domain_vector_to_gsv(domain, vector);
+       ia64_irq_to_gsv_map[irq] = gsv;
+       ia64_gsv_to_irq_map[gsv] = irq;
+
+       return gsv;
 }
 
 int
-assign_irq_vector (int irq)
+assign_irq_gsv (int irq, int domain)
 {
-       int vector = assign_irq_vector_nopanic(irq);
+       static int next_domain = -1;
+       int i, gsv = -ENOSPC;
 
-       if (vector < 0)
-               panic("assign_irq_vector: out of interrupt vectors!");
+       if (domain == AUTO_ASSIGN) {
+               for (i = 0; i < NR_VECTOR_DOMAINS; i++) {
+                       if (++next_domain >= NR_VECTOR_DOMAINS)
+                               next_domain = 0;
+                       if (!cpus_weight(ia64_domain_to_cpumask(next_domain)))
+                               continue;
+                       gsv = assign_irq_gsv_domain(irq, next_domain);
+                       if (gsv >= 0)
+                               break;
+               }
+       } else
+               gsv = assign_irq_gsv_domain(irq, domain);
 
-       return vector;
+       return gsv;
 }
 
 void
-free_irq_vector (int vector)
+free_irq_gsv (int gsv)
 {
-       int pos;
+       int vector, domain, irq = gsv_to_irq(gsv);
 
-       if (vector < IA64_FIRST_DEVICE_VECTOR || vector > 
IA64_LAST_DEVICE_VECTOR)
+       if (gsv >= NR_GSVS || irq > NR_IRQS)
                return;
 
-       pos = vector - IA64_FIRST_DEVICE_VECTOR;
-       if (!test_and_clear_bit(pos, ia64_vector_mask))
-               printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
+       ia64_irq_to_gsv_map[irq] = -1;
+       ia64_gsv_to_irq_map[gsv] = -1;
+
+       vector = gsv_to_vector(gsv);
+       domain = gsv_to_domain(gsv);
+       ia64_free_vector(domain, vector);
+       ia64_free_irq(irq);
+}
+
+int
+assign_irq_vector (int irq)
+{
+       return gsv_to_vector(assign_irq_gsv(irq, 0));
 }
 
 #ifdef CONFIG_SMP
@@ -293,7 +373,7 @@ ia64_send_ipi (int cpu, int vector, int 
 void __init
 ia64_vector_domain_init (void)
 {
-       int domain, vec, gsv;
+       int vec, gsv;
 
        /* Attach BSP to domain #0 */
        ia64_attach_cpu_to_domain(0);
@@ -307,6 +387,7 @@ ia64_vector_domain_init (void)
                    vec > IA64_LAST_DEVICE_VECTOR) {
                        ia64_gsv_to_irq_map[gsv] = vec;
                        ia64_irq_to_gsv_map[vec] = vec;
+                       set_bit(vec, ia64_irq_mask);
                }
        }
 }
diff -puN include/asm-ia64/hw_irq.h~vector-domain-ia64-assign_irq_gsv 
include/asm-ia64/hw_irq.h
--- 
linux-2.6.13-rc1/include/asm-ia64/hw_irq.h~vector-domain-ia64-assign_irq_gsv    
    2005-07-13 14:51:42.000000000 +0900
+++ linux-2.6.13-rc1-kanesige/include/asm-ia64/hw_irq.h 2005-07-13 
16:04:54.000000000 +0900
@@ -93,9 +93,9 @@ extern cpumask_t ia64_domain_cpumask[NR_
 
 extern struct hw_interrupt_type irq_type_ia64_lsapic;  /* CPU-internal 
interrupt controller */
 
-extern int assign_irq_vector_nopanic (int irq); /* allocate a free vector 
without panic */
 extern int assign_irq_vector (int irq);        /* allocate a free vector */
-extern void free_irq_vector (int vector);
+extern int assign_irq_gsv (int irq, int domain);
+extern void free_irq_gsv (int gsv);
 extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int 
redirect);
 extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
 extern void __init ia64_vector_domain_init(void);

_


-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to