From e3a8f7b8b65c6feadab4384fd7097f79c8c1d898 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:20:29 +0900 Subject: [PATCH 01/18] [IA64] Remove block structure for locking in iosapic.c Remove unnecessary indent between spin_lock() and spin_unlock() in iosapic.c. This has no functional changes. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 307 +++++++++++++++++-------------------- 1 file changed, 138 insertions(+), 169 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 37f46527d233..522b13d0bde3 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -209,9 +209,7 @@ gsi_to_irq (unsigned int gsi) * and Linux irq numbers... */ spin_lock_irqsave(&iosapic_lock, flags); - { - irq = _gsi_to_vector(gsi); - } + irq = _gsi_to_vector(gsi); spin_unlock_irqrestore(&iosapic_lock, flags); return irq; @@ -322,15 +320,12 @@ mask_irq (unsigned int irq) 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) { - addr = rte->addr; - rte_index = rte->rte_index; - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); - } + /* 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) { + addr = rte->addr; + rte_index = rte->rte_index; + iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); } spin_unlock_irqrestore(&iosapic_lock, flags); } @@ -349,14 +344,11 @@ unmask_irq (unsigned int irq) 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) { - addr = rte->addr; - rte_index = rte->rte_index; - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); - } + low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; + list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { + addr = rte->addr; + rte_index = rte->rte_index; + iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); } spin_unlock_irqrestore(&iosapic_lock, flags); } @@ -391,28 +383,21 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) high32 = dest << IOSAPIC_DEST_SHIFT; spin_lock_irqsave(&iosapic_lock, flags); - { - low32 = iosapic_intr_info[vec].low32 & - ~(7 << IOSAPIC_DELIVERY_SHIFT); + low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); + if (redir) + /* change delivery mode to lowest priority */ + low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); + else + /* change delivery mode to fixed */ + low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); - if (redir) - /* change delivery mode to lowest priority */ - low32 |= (IOSAPIC_LOWEST_PRIORITY << - IOSAPIC_DELIVERY_SHIFT); - else - /* 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) { - addr = rte->addr; - rte_index = rte->rte_index; - iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), - high32); - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); - } + iosapic_intr_info[vec].low32 = low32; + iosapic_intr_info[vec].dest = dest; + list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { + addr = rte->addr; + rte_index = rte->rte_index; + iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); + iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); } spin_unlock_irqrestore(&iosapic_lock, flags); #endif @@ -797,14 +782,12 @@ iosapic_register_intr (unsigned int gsi, * don't touch the RTE. */ spin_lock_irqsave(&iosapic_lock, flags); - { - vector = gsi_to_vector(gsi); - if (vector > 0) { - rte = gsi_vector_to_rte(gsi, vector); - rte->refcnt++; - spin_unlock_irqrestore(&iosapic_lock, flags); - return vector; - } + vector = gsi_to_vector(gsi); + if (vector > 0) { + rte = gsi_vector_to_rte(gsi, vector); + rte->refcnt++; + spin_unlock_irqrestore(&iosapic_lock, flags); + return vector; } spin_unlock_irqrestore(&iosapic_lock, flags); @@ -818,35 +801,31 @@ iosapic_register_intr (unsigned int gsi, spin_lock_irqsave(&irq_desc[vector].lock, flags); spin_lock(&iosapic_lock); - { - if (gsi_to_vector(gsi) > 0) { - if (list_empty(&iosapic_intr_info[vector].rtes)) - free_irq_vector(vector); - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_desc[vector].lock, - flags); - goto again; - } - - dest = get_target_cpu(gsi, vector); - err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - polarity, trigger); - if (err < 0) { - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_desc[vector].lock, - flags); - return err; - } - - /* - * 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)) - mask = 0; - set_rte(gsi, vector, dest, mask); + if (gsi_to_vector(gsi) > 0) { + if (list_empty(&iosapic_intr_info[vector].rtes)) + free_irq_vector(vector); + spin_unlock(&iosapic_lock); + spin_unlock_irqrestore(&irq_desc[vector].lock, flags); + goto again; } + + dest = get_target_cpu(gsi, vector); + err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, + polarity, trigger); + if (err < 0) { + spin_unlock(&iosapic_lock); + spin_unlock_irqrestore(&irq_desc[vector].lock, flags); + return err; + } + + /* + * 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)) + mask = 0; + set_rte(gsi, vector, dest, mask); spin_unlock(&iosapic_lock); spin_unlock_irqrestore(&irq_desc[vector].lock, flags); @@ -886,69 +865,64 @@ iosapic_unregister_intr (unsigned int gsi) idesc = irq_desc + irq; spin_lock_irqsave(&idesc->lock, flags); spin_lock(&iosapic_lock); - { - if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { - printk(KERN_ERR - "iosapic_unregister_intr(%u) unbalanced\n", - gsi); - WARN_ON(1); - goto out; - } + if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { + printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", + gsi); + WARN_ON(1); + goto out; + } - if (--rte->refcnt > 0) - goto out; + if (--rte->refcnt > 0) + goto out; - /* Mask the interrupt */ - low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; - iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), - low32); + /* Mask the interrupt */ + low32 = iosapic_intr_info[vector].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_free_rte(rte); - index = find_iosapic(gsi); - iosapic_lists[index].rtes_inuse--; - WARN_ON(iosapic_lists[index].rtes_inuse < 0); + /* Remove the rte entry from the list */ + list_del(&rte->rte_list); + iosapic_intr_info[vector].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; - 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); + trigger = iosapic_intr_info[vector].trigger; + polarity = iosapic_intr_info[vector].polarity; + dest = iosapic_intr_info[vector].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); - if (list_empty(&iosapic_intr_info[vector].rtes)) { - /* Sanity check */ - BUG_ON(iosapic_intr_info[vector].count); + if (list_empty(&iosapic_intr_info[vector].rtes)) { + /* Sanity check */ + BUG_ON(iosapic_intr_info[vector].count); - /* Clear the interrupt controller descriptor */ - idesc->chip = &no_irq_type; + /* Clear the interrupt controller descriptor */ + idesc->chip = &no_irq_type; #ifdef CONFIG_SMP - /* Clear affinity */ - cpus_setall(idesc->affinity); + /* Clear affinity */ + cpus_setall(idesc->affinity); #endif - /* 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); + /* 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); - if (idesc->action) { - printk(KERN_ERR - "interrupt handlers still exist on" - "IRQ %u\n", irq); - WARN_ON(1); - } - - /* Free the interrupt vector */ - free_irq_vector(vector); + if (idesc->action) { + printk(KERN_ERR + "interrupt handlers still exist on IRQ %u\n", + irq); + WARN_ON(1); } + + /* Free the interrupt vector */ + free_irq_vector(vector); } out: spin_unlock(&iosapic_lock); @@ -1108,31 +1082,29 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) unsigned long flags; spin_lock_irqsave(&iosapic_lock, flags); - { - addr = ioremap(phys_addr, 0); - ver = iosapic_version(addr); + addr = ioremap(phys_addr, 0); + ver = iosapic_version(addr); - if ((err = iosapic_check_gsi_range(gsi_base, ver))) { - iounmap(addr); - spin_unlock_irqrestore(&iosapic_lock, flags); - return err; - } - - /* - * The MAX_REDIR register holds the highest input pin - * number (starting from 0). - * We add 1 so that we can use it for number of pins (= RTEs) - */ - num_rte = ((ver >> 16) & 0xff) + 1; - - index = iosapic_alloc(); - iosapic_lists[index].addr = addr; - iosapic_lists[index].gsi_base = gsi_base; - iosapic_lists[index].num_rte = num_rte; -#ifdef CONFIG_NUMA - iosapic_lists[index].node = MAX_NUMNODES; -#endif + if ((err = iosapic_check_gsi_range(gsi_base, ver))) { + iounmap(addr); + spin_unlock_irqrestore(&iosapic_lock, flags); + return err; } + + /* + * The MAX_REDIR register holds the highest input pin number + * (starting from 0). We add 1 so that we can use it for + * number of pins (= RTEs) + */ + num_rte = ((ver >> 16) & 0xff) + 1; + + index = iosapic_alloc(); + iosapic_lists[index].addr = addr; + iosapic_lists[index].gsi_base = gsi_base; + iosapic_lists[index].num_rte = num_rte; +#ifdef CONFIG_NUMA + iosapic_lists[index].node = MAX_NUMNODES; +#endif spin_unlock_irqrestore(&iosapic_lock, flags); if ((gsi_base == 0) && pcat_compat) { @@ -1157,25 +1129,22 @@ iosapic_remove (unsigned int gsi_base) unsigned long flags; spin_lock_irqsave(&iosapic_lock, flags); - { - index = find_iosapic(gsi_base); - if (index < 0) { - printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n", - __FUNCTION__, gsi_base); - goto out; - } - - if (iosapic_lists[index].rtes_inuse) { - err = -EBUSY; - printk(KERN_WARNING - "%s: IOSAPIC for GSI base %u is busy\n", - __FUNCTION__, gsi_base); - goto out; - } - - iounmap(iosapic_lists[index].addr); - iosapic_free(index); + index = find_iosapic(gsi_base); + if (index < 0) { + printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n", + __FUNCTION__, gsi_base); + goto out; } + + if (iosapic_lists[index].rtes_inuse) { + err = -EBUSY; + printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n", + __FUNCTION__, gsi_base); + goto out; + } + + iounmap(iosapic_lists[index].addr); + iosapic_free(index); out: spin_unlock_irqrestore(&iosapic_lock, flags); return err; From c5e3f9e5a2152578db7a37090303ce66d03a7c87 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:20:42 +0900 Subject: [PATCH 02/18] [IA64] Remove duplicated members in iosapic_rte_info Remove duplicated members in iosapic_rte_info in iosapic.c. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 60 +++++++++++++++----------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 522b13d0bde3..29ec86c24194 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -117,16 +117,22 @@ static DEFINE_SPINLOCK(iosapic_lock); * These tables map IA-64 vectors to the IOSAPIC pin that generates this * vector. */ +static struct iosapic { + char __iomem *addr; /* base address of IOSAPIC */ + unsigned int gsi_base; /* GSI base */ + unsigned short num_rte; /* # of RTEs on this IOSAPIC */ + int rtes_inuse; /* # of RTEs in use on this IOSAPIC */ +#ifdef CONFIG_NUMA + unsigned short node; /* numa node association via pxm */ +#endif +} iosapic_lists[NR_IOSAPICS]; struct iosapic_rte_info { - struct list_head rte_list; /* node in list of RTEs sharing the - * same vector */ - char __iomem *addr; /* base address of IOSAPIC */ - unsigned int gsi_base; /* first GSI assigned to this - * IOSAPIC */ + struct list_head rte_list; /* RTEs sharing the same vector */ char rte_index; /* IOSAPIC RTE index */ int refcnt; /* reference counter */ unsigned int flags; /* flags */ + struct iosapic *iosapic; } ____cacheline_aligned; static struct iosapic_intr_info { @@ -142,17 +148,6 @@ static struct iosapic_intr_info { unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ } iosapic_intr_info[IA64_NUM_VECTORS]; -static struct iosapic { - char __iomem *addr; /* base address of IOSAPIC */ - unsigned int gsi_base; /* first GSI assigned to this - * IOSAPIC */ - unsigned short num_rte; /* # of RTEs on this IOSAPIC */ - int rtes_inuse; /* # of RTEs in use on this IOSAPIC */ -#ifdef CONFIG_NUMA - unsigned short node; /* numa node association via pxm */ -#endif -} iosapic_lists[NR_IOSAPICS]; - static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ static int iosapic_kmalloc_ok; @@ -184,7 +179,7 @@ _gsi_to_vector (unsigned int gsi) for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info) list_for_each_entry(rte, &info->rtes, rte_list) - if (rte->gsi_base + rte->rte_index == gsi) + if (rte->iosapic->gsi_base + rte->rte_index == gsi) return info - iosapic_intr_info; return -1; } @@ -221,7 +216,7 @@ static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, struct iosapic_rte_info *rte; list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) - if (rte->gsi_base + rte->rte_index == gsi) + if (rte->iosapic->gsi_base + rte->rte_index == gsi) return rte; return NULL; } @@ -243,7 +238,7 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) return; /* not an IOSAPIC interrupt */ rte_index = rte->rte_index; - addr = rte->addr; + addr = rte->iosapic->addr; pol = iosapic_intr_info[vector].polarity; trigger = iosapic_intr_info[vector].trigger; dmode = iosapic_intr_info[vector].dmode; @@ -297,10 +292,10 @@ kexec_disable_iosapic(void) iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) { list_for_each_entry(rte, &info->rtes, rte_list) { - iosapic_write(rte->addr, + iosapic_write(rte->iosapic->addr, IOSAPIC_RTE_LOW(rte->rte_index), IOSAPIC_MASK|vec); - iosapic_eoi(rte->addr, vec); + iosapic_eoi(rte->iosapic->addr, vec); } } } @@ -323,7 +318,7 @@ mask_irq (unsigned int irq) /* 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) { - addr = rte->addr; + addr = rte->iosapic->addr; rte_index = rte->rte_index; iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); } @@ -346,7 +341,7 @@ unmask_irq (unsigned int irq) 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) { - addr = rte->addr; + addr = rte->iosapic->addr; rte_index = rte->rte_index; iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); } @@ -394,7 +389,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) iosapic_intr_info[vec].low32 = low32; iosapic_intr_info[vec].dest = dest; list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { - addr = rte->addr; + addr = rte->iosapic->addr; rte_index = rte->rte_index; iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); @@ -422,7 +417,7 @@ iosapic_end_level_irq (unsigned int irq) move_native_irq(irq); list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) - iosapic_eoi(rte->addr, vec); + iosapic_eoi(rte->iosapic->addr, vec); } #define iosapic_shutdown_level_irq mask_irq @@ -614,10 +609,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, { irq_desc_t *idesc; struct hw_interrupt_type *irq_type; - int rte_index; int index; - unsigned long gsi_base; - void __iomem *iosapic_address; struct iosapic_rte_info *rte; index = find_iosapic(gsi); @@ -627,9 +619,6 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, return -ENODEV; } - iosapic_address = iosapic_lists[index].addr; - gsi_base = iosapic_lists[index].gsi_base; - rte = gsi_vector_to_rte(gsi, vector); if (!rte) { rte = iosapic_alloc_rte(); @@ -639,10 +628,8 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, return -ENOMEM; } - rte_index = gsi - gsi_base; - rte->rte_index = rte_index; - rte->addr = iosapic_address; - rte->gsi_base = gsi_base; + rte->iosapic = &iosapic_lists[index]; + rte->rte_index = gsi - rte->iosapic->gsi_base; rte->refcnt++; list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes); iosapic_intr_info[vector].count++; @@ -877,7 +864,8 @@ iosapic_unregister_intr (unsigned int gsi) /* Mask the interrupt */ low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; - iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32); + iosapic_write(rte->iosapic->addr, + IOSAPIC_RTE_LOW(rte->rte_index), low32); /* Remove the rte entry from the list */ list_del(&rte->rte_list); From 40598cbe9c196f1e84dcfef70541c4a80fd996bb Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:20:54 +0900 Subject: [PATCH 03/18] [IA64] Cleanup lock order in iosapic_register_intr Cleanup order of irq_desc.lock and iosapic_lock in iosapic_register_intr() and iosapic_unregister_intr(). Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 50 +++++++++++++++----------------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 29ec86c24194..b3dcdb7e7fc7 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -505,7 +505,7 @@ iosapic_version (char __iomem *addr) static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol) { - int i, vector = -1, min_count = -1; + int i, vector = -ENOSPC, min_count = -1; struct iosapic_intr_info *info; /* @@ -513,7 +513,7 @@ static int iosapic_find_sharable_vector (unsigned long trigger, * supported yet */ if (trigger == IOSAPIC_EDGE) - return -1; + return -EINVAL; for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { info = &iosapic_intr_info[i]; @@ -762,7 +762,7 @@ iosapic_register_intr (unsigned int gsi, unsigned long flags; struct iosapic_rte_info *rte; u32 low32; -again: + /* * If this GSI has already been registered (i.e., it's a * shared interrupt, or we lost a race to register it), @@ -773,36 +773,24 @@ iosapic_register_intr (unsigned int gsi, if (vector > 0) { rte = gsi_vector_to_rte(gsi, vector); rte->refcnt++; - spin_unlock_irqrestore(&iosapic_lock, flags); - return vector; + goto unlock_iosapic_lock; } - spin_unlock_irqrestore(&iosapic_lock, flags); /* If vector is running out, we try to find a sharable vector */ vector = assign_irq_vector(AUTO_ASSIGN); if (vector < 0) { vector = iosapic_find_sharable_vector(trigger, polarity); if (vector < 0) - return -ENOSPC; - } - - spin_lock_irqsave(&irq_desc[vector].lock, flags); - spin_lock(&iosapic_lock); - if (gsi_to_vector(gsi) > 0) { - if (list_empty(&iosapic_intr_info[vector].rtes)) - free_irq_vector(vector); - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_desc[vector].lock, flags); - goto again; + goto unlock_iosapic_lock; } + spin_lock(&irq_desc[vector].lock); dest = get_target_cpu(gsi, vector); err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); if (err < 0) { - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_desc[vector].lock, flags); - return err; + vector = err; + goto unlock_all; } /* @@ -813,14 +801,15 @@ iosapic_register_intr (unsigned int gsi, if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK)) mask = 0; set_rte(gsi, vector, dest, mask); - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_desc[vector].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); - + unlock_all: + spin_unlock(&irq_desc[vector].lock); + unlock_iosapic_lock: + spin_unlock_irqrestore(&iosapic_lock, flags); return vector; } @@ -849,9 +838,7 @@ iosapic_unregister_intr (unsigned int gsi) } vector = irq_to_vector(irq); - idesc = irq_desc + irq; - spin_lock_irqsave(&idesc->lock, flags); - spin_lock(&iosapic_lock); + spin_lock_irqsave(&iosapic_lock, flags); if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); @@ -862,13 +849,17 @@ iosapic_unregister_intr (unsigned int gsi) if (--rte->refcnt > 0) goto out; + /* Remove the rte entry from the list */ + idesc = irq_desc + irq; + spin_lock(&idesc->lock); + list_del(&rte->rte_list); + spin_unlock(&idesc->lock); + /* Mask the interrupt */ low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; iosapic_write(rte->iosapic->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_free_rte(rte); index = find_iosapic(gsi); @@ -913,8 +904,7 @@ iosapic_unregister_intr (unsigned int gsi) free_irq_vector(vector); } out: - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&idesc->lock, flags); + spin_unlock_irqrestore(&iosapic_lock, flags); } /* From c1726d6f1ad2f1d83e5db1e0142756e9255a82b3 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:21:26 +0900 Subject: [PATCH 04/18] [IA64] Use per iosapic lock for indirect iosapic register access Use per-iosapic lock for indirect iosapic register access. It reduces lock contention. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 57 +++++++++++++++++++------------------- include/asm-ia64/iosapic.h | 4 +-- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index b3dcdb7e7fc7..29fea0a8c2c6 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -125,6 +125,7 @@ static struct iosapic { #ifdef CONFIG_NUMA unsigned short node; /* numa node association via pxm */ #endif + spinlock_t lock; /* lock for indirect reg access */ } iosapic_lists[NR_IOSAPICS]; struct iosapic_rte_info { @@ -153,6 +154,16 @@ static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ static int iosapic_kmalloc_ok; static LIST_HEAD(free_rte_list); +static inline void +iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val) +{ + unsigned long flags; + + spin_lock_irqsave(&iosapic->lock, flags); + __iosapic_write(iosapic->addr, reg, val); + spin_unlock_irqrestore(&iosapic->lock, flags); +} + /* * Find an IOSAPIC associated with a GSI */ @@ -226,7 +237,6 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) { unsigned long pol, trigger, dmode; u32 low32, high32; - char __iomem *addr; int rte_index; char redir; struct iosapic_rte_info *rte; @@ -238,7 +248,6 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) return; /* not an IOSAPIC interrupt */ rte_index = rte->rte_index; - addr = rte->iosapic->addr; pol = iosapic_intr_info[vector].polarity; trigger = iosapic_intr_info[vector].trigger; dmode = iosapic_intr_info[vector].dmode; @@ -268,8 +277,8 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) /* dest contains both id and eid */ high32 = (dest << IOSAPIC_DEST_SHIFT); - iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); + iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); iosapic_intr_info[vector].low32 = low32; iosapic_intr_info[vector].dest = dest; } @@ -292,7 +301,7 @@ kexec_disable_iosapic(void) iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) { list_for_each_entry(rte, &info->rtes, rte_list) { - iosapic_write(rte->iosapic->addr, + iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), IOSAPIC_MASK|vec); iosapic_eoi(rte->iosapic->addr, vec); @@ -304,8 +313,6 @@ kexec_disable_iosapic(void) static void mask_irq (unsigned int irq) { - unsigned long flags; - char __iomem *addr; u32 low32; int rte_index; ia64_vector vec = irq_to_vector(irq); @@ -314,22 +321,17 @@ mask_irq (unsigned int irq) if (list_empty(&iosapic_intr_info[vec].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) { - addr = rte->iosapic->addr; rte_index = rte->rte_index; - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); } - spin_unlock_irqrestore(&iosapic_lock, flags); } static void unmask_irq (unsigned int irq) { - unsigned long flags; - char __iomem *addr; u32 low32; int rte_index; ia64_vector vec = irq_to_vector(irq); @@ -338,14 +340,11 @@ unmask_irq (unsigned int irq) if (list_empty(&iosapic_intr_info[vec].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) { - addr = rte->iosapic->addr; rte_index = rte->rte_index; - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); } - spin_unlock_irqrestore(&iosapic_lock, flags); } @@ -353,13 +352,12 @@ static void iosapic_set_affinity (unsigned int irq, cpumask_t mask) { #ifdef CONFIG_SMP - unsigned long flags; u32 high32, low32; int dest, rte_index; - char __iomem *addr; int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; ia64_vector vec; struct iosapic_rte_info *rte; + struct iosapic *iosapic; irq &= (~IA64_IRQ_REDIRECTED); vec = irq_to_vector(irq); @@ -377,7 +375,6 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) /* dest contains both id and eid */ high32 = dest << IOSAPIC_DEST_SHIFT; - spin_lock_irqsave(&iosapic_lock, flags); low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); if (redir) /* change delivery mode to lowest priority */ @@ -389,12 +386,11 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) iosapic_intr_info[vec].low32 = low32; iosapic_intr_info[vec].dest = dest; list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { - addr = rte->iosapic->addr; + iosapic = rte->iosapic; rte_index = rte->rte_index; - iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); + iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32); } - spin_unlock_irqrestore(&iosapic_lock, flags); #endif } @@ -499,7 +495,7 @@ iosapic_version (char __iomem *addr) * unsigned int reserved2 : 8; * } */ - return iosapic_read(addr, IOSAPIC_VERSION); + return __iosapic_read(addr, IOSAPIC_VERSION); } static int iosapic_find_sharable_vector (unsigned long trigger, @@ -857,8 +853,7 @@ iosapic_unregister_intr (unsigned int gsi) /* Mask the interrupt */ low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; - iosapic_write(rte->iosapic->addr, - IOSAPIC_RTE_LOW(rte->rte_index), low32); + iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32); iosapic_intr_info[vector].count--; iosapic_free_rte(rte); @@ -1060,9 +1055,14 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) unsigned long flags; spin_lock_irqsave(&iosapic_lock, flags); + index = find_iosapic(gsi_base); + if (index >= 0) { + spin_unlock_irqrestore(&iosapic_lock, flags); + return -EBUSY; + } + addr = ioremap(phys_addr, 0); ver = iosapic_version(addr); - if ((err = iosapic_check_gsi_range(gsi_base, ver))) { iounmap(addr); spin_unlock_irqrestore(&iosapic_lock, flags); @@ -1083,6 +1083,7 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) #ifdef CONFIG_NUMA iosapic_lists[index].node = MAX_NUMNODES; #endif + spin_lock_init(&iosapic_lists[index].lock); spin_unlock_irqrestore(&iosapic_lock, flags); if ((gsi_base == 0) && pcat_compat) { diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h index 421cb6b62a7c..09bdc3898df8 100644 --- a/include/asm-ia64/iosapic.h +++ b/include/asm-ia64/iosapic.h @@ -53,13 +53,13 @@ #define NR_IOSAPICS 256 -static inline unsigned int iosapic_read(char __iomem *iosapic, unsigned int reg) +static inline unsigned int __iosapic_read(char __iomem *iosapic, unsigned int reg) { writel(reg, iosapic + IOSAPIC_REG_SELECT); return readl(iosapic + IOSAPIC_WINDOW); } -static inline void iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +static inline void __iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) { writel(reg, iosapic + IOSAPIC_REG_SELECT); writel(val, iosapic + IOSAPIC_WINDOW); From eb21ab24955ee025434ad09cd8e5e1a74c798777 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:21:48 +0900 Subject: [PATCH 05/18] [IA64] Use dynamic irq for iosapic interrupts Use create_irq()/destroy_irq() for iosapic interrupts. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 39 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 29fea0a8c2c6..4c531953e2e1 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -533,12 +533,13 @@ static int iosapic_find_sharable_vector (unsigned long trigger, static void __init iosapic_reassign_vector (int vector) { - int new_vector; + int irq, new_vector; if (!list_empty(&iosapic_intr_info[vector].rtes)) { - new_vector = assign_irq_vector(AUTO_ASSIGN); - if (new_vector < 0) + irq = create_irq(); + if (irq < 0) panic("%s: out of interrupt vectors!\n", __FUNCTION__); + new_vector = irq_to_vector(irq); printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector); memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], @@ -753,7 +754,7 @@ int iosapic_register_intr (unsigned int gsi, unsigned long polarity, unsigned long trigger) { - int vector, mask = 1, err; + int irq, vector, mask = 1, err; unsigned int dest; unsigned long flags; struct iosapic_rte_info *rte; @@ -773,12 +774,13 @@ iosapic_register_intr (unsigned int gsi, } /* If vector is running out, we try to find a sharable vector */ - vector = assign_irq_vector(AUTO_ASSIGN); - if (vector < 0) { + irq = create_irq(); + if (irq < 0) { vector = iosapic_find_sharable_vector(trigger, polarity); if (vector < 0) goto unlock_iosapic_lock; - } + } else + vector = irq_to_vector(irq); spin_lock(&irq_desc[vector].lock); dest = get_target_cpu(gsi, vector); @@ -873,30 +875,18 @@ iosapic_unregister_intr (unsigned int gsi) if (list_empty(&iosapic_intr_info[vector].rtes)) { /* Sanity check */ BUG_ON(iosapic_intr_info[vector].count); - - /* Clear the interrupt controller descriptor */ - idesc->chip = &no_irq_type; - #ifdef CONFIG_SMP /* Clear affinity */ cpus_setall(idesc->affinity); #endif - /* 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); - if (idesc->action) { - printk(KERN_ERR - "interrupt handlers still exist on IRQ %u\n", - irq); - WARN_ON(1); - } - - /* Free the interrupt vector */ - free_irq_vector(vector); + /* Destroy IRQ */ + destroy_irq(irq); } out: spin_unlock_irqrestore(&iosapic_lock, flags); @@ -912,7 +902,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, { static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"}; unsigned char delivery; - int vector, mask = 0; + int irq, vector, mask = 0; unsigned int dest = ((id << 8) | eid) & 0xffff; switch (int_type) { @@ -926,9 +916,10 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, delivery = IOSAPIC_PMI; break; case ACPI_INTERRUPT_INIT: - vector = assign_irq_vector(AUTO_ASSIGN); - if (vector < 0) + irq = create_irq(); + if (irq < 0) panic("%s: out of interrupt vectors!\n", __FUNCTION__); + vector = irq_to_vector(irq); delivery = IOSAPIC_INIT; break; case ACPI_INTERRUPT_CPEI: From 4bbdec7a84ca8ce786c44bc338a37d97a13cbf20 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:22:03 +0900 Subject: [PATCH 06/18] [IA64] Fix invalid irq vector assumption for iosapic Many of IOSAPIC codes depends on the flollowing assumptions, but these would become invalid when multiple vector domain will be supported in the future. - 1:1 mapping between IRQ and vector - IRQ == vector To fix those invalid assumptions, this patch changes iosapic_intr_info[] to be indexed by irq number instead of vector. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 260 ++++++++++++++++++------------------- 1 file changed, 123 insertions(+), 137 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 4c531953e2e1..bcf91dceaf5d 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -147,7 +147,7 @@ static struct iosapic_intr_info { 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_IRQS]; static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ @@ -181,17 +181,18 @@ find_iosapic (unsigned int gsi) return -1; } -static inline int -_gsi_to_vector (unsigned int gsi) +static inline int __gsi_to_irq(unsigned int gsi) { + int irq; struct iosapic_intr_info *info; struct iosapic_rte_info *rte; - for (info = iosapic_intr_info; info < - iosapic_intr_info + IA64_NUM_VECTORS; ++info) + for (irq = 0; irq < NR_IRQS; irq++) { + info = &iosapic_intr_info[irq]; list_for_each_entry(rte, &info->rtes, rte_list) if (rte->iosapic->gsi_base + rte->rte_index == gsi) - return info - iosapic_intr_info; + return irq; + } return -1; } @@ -202,7 +203,10 @@ _gsi_to_vector (unsigned int gsi) inline int gsi_to_vector (unsigned int gsi) { - return _gsi_to_vector(gsi); + int irq = __gsi_to_irq(gsi); + if (irq < 0) + return -1; + return irq_to_vector(irq); } int @@ -210,62 +214,48 @@ gsi_to_irq (unsigned int gsi) { unsigned long flags; int irq; - /* - * XXX fix me: this assumes an identity mapping between IA-64 vector - * and Linux irq numbers... - */ - spin_lock_irqsave(&iosapic_lock, flags); - irq = _gsi_to_vector(gsi); - spin_unlock_irqrestore(&iosapic_lock, flags); + spin_lock_irqsave(&iosapic_lock, flags); + irq = __gsi_to_irq(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 *find_rte(unsigned int irq, unsigned int gsi) { 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[irq].rtes, rte_list) if (rte->iosapic->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 irq, unsigned int dest, int mask) { unsigned long pol, trigger, dmode; u32 low32, high32; int rte_index; char redir; struct iosapic_rte_info *rte; + ia64_vector vector = irq_to_vector(irq); DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest); - rte = gsi_vector_to_rte(gsi, vector); + rte = find_rte(irq, gsi); if (!rte) return; /* not an IOSAPIC interrupt */ rte_index = rte->rte_index; - pol = iosapic_intr_info[vector].polarity; - trigger = iosapic_intr_info[vector].trigger; - dmode = iosapic_intr_info[vector].dmode; + pol = iosapic_intr_info[irq].polarity; + trigger = iosapic_intr_info[irq].trigger; + dmode = iosapic_intr_info[irq].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; - } - } + set_irq_affinity_info(irq, (int)(dest & 0xffff), redir); #endif low32 = ((pol << IOSAPIC_POLARITY_SHIFT) | @@ -279,8 +269,8 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); - iosapic_intr_info[vector].low32 = low32; - iosapic_intr_info[vector].dest = dest; + iosapic_intr_info[irq].low32 = low32; + iosapic_intr_info[irq].dest = dest; } static void @@ -296,9 +286,12 @@ kexec_disable_iosapic(void) { struct iosapic_intr_info *info; struct iosapic_rte_info *rte; - u8 vec = 0; - for (info = iosapic_intr_info; info < - iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) { + ia64_vector vec; + int irq; + + for (irq = 0; irq < NR_IRQS; irq++) { + info = &iosapic_intr_info[irq]; + vec = irq_to_vector(irq); list_for_each_entry(rte, &info->rtes, rte_list) { iosapic_write(rte->iosapic, @@ -315,15 +308,14 @@ mask_irq (unsigned int irq) { u32 low32; int rte_index; - ia64_vector vec = irq_to_vector(irq); struct iosapic_rte_info *rte; - if (list_empty(&iosapic_intr_info[vec].rtes)) + if (list_empty(&iosapic_intr_info[irq].rtes)) return; /* not an IOSAPIC interrupt! */ /* 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[irq].low32 |= IOSAPIC_MASK; + list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) { rte_index = rte->rte_index; iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); } @@ -334,14 +326,13 @@ unmask_irq (unsigned int irq) { u32 low32; int rte_index; - ia64_vector vec = irq_to_vector(irq); struct iosapic_rte_info *rte; - if (list_empty(&iosapic_intr_info[vec].rtes)) + if (list_empty(&iosapic_intr_info[irq].rtes)) return; /* not an IOSAPIC interrupt! */ - low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; - list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { + low32 = iosapic_intr_info[irq].low32 &= ~IOSAPIC_MASK; + list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) { rte_index = rte->rte_index; iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); } @@ -355,19 +346,17 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) u32 high32, low32; int dest, rte_index; int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; - ia64_vector vec; struct iosapic_rte_info *rte; struct iosapic *iosapic; irq &= (~IA64_IRQ_REDIRECTED); - vec = irq_to_vector(irq); if (cpus_empty(mask)) return; dest = cpu_physical_id(first_cpu(mask)); - if (list_empty(&iosapic_intr_info[vec].rtes)) + if (list_empty(&iosapic_intr_info[irq].rtes)) return; /* not an IOSAPIC interrupt */ set_irq_affinity_info(irq, dest, redir); @@ -375,7 +364,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) /* dest contains both id and eid */ high32 = dest << IOSAPIC_DEST_SHIFT; - low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); + low32 = iosapic_intr_info[irq].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); if (redir) /* change delivery mode to lowest priority */ low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); @@ -383,9 +372,9 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) /* 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[irq].low32 = low32; + iosapic_intr_info[irq].dest = dest; + list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) { iosapic = rte->iosapic; rte_index = rte->rte_index; iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); @@ -412,7 +401,7 @@ iosapic_end_level_irq (unsigned int irq) struct iosapic_rte_info *rte; move_native_irq(irq); - list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) + list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) iosapic_eoi(rte->iosapic->addr, vec); } @@ -498,10 +487,9 @@ 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_irq(unsigned long trigger, unsigned long pol) { - int i, vector = -ENOSPC, min_count = -1; + int i, irq = -ENOSPC, min_count = -1; struct iosapic_intr_info *info; /* @@ -511,19 +499,18 @@ static int iosapic_find_sharable_vector (unsigned long trigger, if (trigger == IOSAPIC_EDGE) return -EINVAL; - for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { + for (i = 0; i <= NR_IRQS; 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; + irq = i; min_count = info->count; } } } - - return vector; + return irq; } /* @@ -531,26 +518,25 @@ static int iosapic_find_sharable_vector (unsigned long trigger, * assign a new vector for the other and make the vector available */ static void __init -iosapic_reassign_vector (int vector) +iosapic_reassign_vector (int irq) { - int irq, new_vector; + int new_irq; - if (!list_empty(&iosapic_intr_info[vector].rtes)) { - irq = create_irq(); - if (irq < 0) + if (!list_empty(&iosapic_intr_info[irq].rtes)) { + new_irq = create_irq(); + if (new_irq < 0) panic("%s: out of interrupt vectors!\n", __FUNCTION__); - new_vector = irq_to_vector(irq); printk(KERN_INFO "Reassigning vector %d to %d\n", - vector, new_vector); - memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], + irq_to_vector(irq), irq_to_vector(new_irq)); + memcpy(&iosapic_intr_info[new_irq], &iosapic_intr_info[irq], 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, + INIT_LIST_HEAD(&iosapic_intr_info[new_irq].rtes); + list_move(iosapic_intr_info[irq].rtes.next, + &iosapic_intr_info[new_irq].rtes); + memset(&iosapic_intr_info[irq], 0, sizeof(struct iosapic_intr_info)); - iosapic_intr_info[vector].low32 = IOSAPIC_MASK; - INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); + iosapic_intr_info[irq].low32 = IOSAPIC_MASK; + INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); } } @@ -595,13 +581,13 @@ static void iosapic_free_rte (struct iosapic_rte_info *rte) kfree(rte); } -static inline int vector_is_shared (int vector) +static inline int irq_is_shared (int irq) { - return (iosapic_intr_info[vector].count > 1); + return (iosapic_intr_info[irq].count > 1); } static int -register_intr (unsigned int gsi, int vector, unsigned char delivery, +register_intr (unsigned int gsi, int irq, unsigned char delivery, unsigned long polarity, unsigned long trigger) { irq_desc_t *idesc; @@ -616,7 +602,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, return -ENODEV; } - rte = gsi_vector_to_rte(gsi, vector); + rte = find_rte(irq, gsi); if (!rte) { rte = iosapic_alloc_rte(); if (!rte) { @@ -628,12 +614,12 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, rte->iosapic = &iosapic_lists[index]; rte->rte_index = gsi - rte->iosapic->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[irq].rtes); + iosapic_intr_info[irq].count++; iosapic_lists[index].rtes_inuse++; } - else if (vector_is_shared(vector)) { - struct iosapic_intr_info *info = &iosapic_intr_info[vector]; + else if (irq_is_shared(irq)) { + struct iosapic_intr_info *info = &iosapic_intr_info[irq]; if (info->trigger != trigger || info->polarity != polarity) { printk (KERN_WARNING "%s: cannot override the interrupt\n", @@ -642,21 +628,21 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, } } - iosapic_intr_info[vector].polarity = polarity; - iosapic_intr_info[vector].dmode = delivery; - iosapic_intr_info[vector].trigger = trigger; + iosapic_intr_info[irq].polarity = polarity; + iosapic_intr_info[irq].dmode = delivery; + iosapic_intr_info[irq].trigger = trigger; if (trigger == IOSAPIC_EDGE) irq_type = &irq_type_iosapic_edge; else irq_type = &irq_type_iosapic_level; - idesc = irq_desc + vector; + idesc = irq_desc + irq; if (idesc->chip != irq_type) { if (idesc->chip != &no_irq_type) printk(KERN_WARNING "%s: changing vector %d from %s to %s\n", - __FUNCTION__, vector, + __FUNCTION__, irq_to_vector(irq), idesc->chip->name, irq_type->name); idesc->chip = irq_type; } @@ -664,7 +650,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, } static unsigned int -get_target_cpu (unsigned int gsi, int vector) +get_target_cpu (unsigned int gsi, int irq) { #ifdef CONFIG_SMP static int cpu = -1; @@ -674,8 +660,8 @@ get_target_cpu (unsigned int gsi, int vector) * 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[irq].rtes)) + return iosapic_intr_info[irq].dest; /* * If the platform supports redirection via XTP, let it @@ -692,7 +678,7 @@ get_target_cpu (unsigned int gsi, int vector) return cpu_physical_id(smp_processor_id()); #ifdef CONFIG_ACPI - if (cpe_vector > 0 && vector == IA64_CPEP_VECTOR) + if (cpe_vector > 0 && irq_to_vector(irq) == IA64_CPEP_VECTOR) return get_cpei_target_cpu(); #endif @@ -718,8 +704,8 @@ get_target_cpu (unsigned int gsi, int vector) if (!num_cpus) goto skip_numa_setup; - /* Use vector assignment to distribute across cpus in node */ - cpu_index = vector % num_cpus; + /* Use irq assignment to distribute across cpus in node */ + cpu_index = irq % num_cpus; for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) numa_cpu = next_cpu(numa_cpu, cpu_mask); @@ -754,7 +740,7 @@ int iosapic_register_intr (unsigned int gsi, unsigned long polarity, unsigned long trigger) { - int irq, vector, mask = 1, err; + int irq, mask = 1, err; unsigned int dest; unsigned long flags; struct iosapic_rte_info *rte; @@ -766,9 +752,9 @@ iosapic_register_intr (unsigned int gsi, * don't touch the RTE. */ spin_lock_irqsave(&iosapic_lock, flags); - vector = gsi_to_vector(gsi); - if (vector > 0) { - rte = gsi_vector_to_rte(gsi, vector); + irq = __gsi_to_irq(gsi); + if (irq > 0) { + rte = find_rte(irq, gsi); rte->refcnt++; goto unlock_iosapic_lock; } @@ -776,18 +762,17 @@ iosapic_register_intr (unsigned int gsi, /* If vector is running out, we try to find a sharable vector */ irq = create_irq(); if (irq < 0) { - vector = iosapic_find_sharable_vector(trigger, polarity); - if (vector < 0) + irq = iosapic_find_sharable_irq(trigger, polarity); + if (irq < 0) goto unlock_iosapic_lock; - } else - vector = irq_to_vector(irq); + } - spin_lock(&irq_desc[vector].lock); - dest = get_target_cpu(gsi, vector); - err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, + spin_lock(&irq_desc[irq].lock); + dest = get_target_cpu(gsi, irq); + err = register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); if (err < 0) { - vector = err; + irq = err; goto unlock_all; } @@ -795,27 +780,27 @@ iosapic_register_intr (unsigned int gsi, * 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[irq].low32; + if (irq_is_shared(irq) && !(low32 & IOSAPIC_MASK)) mask = 0; - set_rte(gsi, vector, dest, mask); + set_rte(gsi, irq, dest, mask); 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, irq_to_vector(irq)); unlock_all: - spin_unlock(&irq_desc[vector].lock); + spin_unlock(&irq_desc[irq].lock); unlock_iosapic_lock: spin_unlock_irqrestore(&iosapic_lock, flags); - return vector; + return irq; } 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; @@ -834,10 +819,9 @@ iosapic_unregister_intr (unsigned int gsi) WARN_ON(1); return; } - vector = irq_to_vector(irq); spin_lock_irqsave(&iosapic_lock, flags); - if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { + if ((rte = find_rte(irq, gsi)) == NULL) { printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); WARN_ON(1); @@ -854,36 +838,36 @@ iosapic_unregister_intr (unsigned int gsi) spin_unlock(&idesc->lock); /* Mask the interrupt */ - low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; + low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK; iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32); - iosapic_intr_info[vector].count--; + iosapic_intr_info[irq].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[irq].trigger; + polarity = iosapic_intr_info[irq].polarity; + dest = iosapic_intr_info[irq].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, irq_to_vector(irq)); - if (list_empty(&iosapic_intr_info[vector].rtes)) { + if (list_empty(&iosapic_intr_info[irq].rtes)) { /* Sanity check */ - BUG_ON(iosapic_intr_info[vector].count); + BUG_ON(iosapic_intr_info[irq].count); #ifdef CONFIG_SMP /* Clear affinity */ cpus_setall(idesc->affinity); #endif /* Clear the interrupt information */ - memset(&iosapic_intr_info[vector], 0, + memset(&iosapic_intr_info[irq], 0, sizeof(struct iosapic_intr_info)); - iosapic_intr_info[vector].low32 |= IOSAPIC_MASK; - INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); + iosapic_intr_info[irq].low32 |= IOSAPIC_MASK; + INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); /* Destroy IRQ */ destroy_irq(irq); @@ -908,11 +892,12 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, switch (int_type) { case ACPI_INTERRUPT_PMI: vector = iosapic_vector; + irq = vector; /* FIXME */ /* * 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_vector(irq); delivery = IOSAPIC_PMI; break; case ACPI_INTERRUPT_INIT: @@ -924,6 +909,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, break; case ACPI_INTERRUPT_CPEI: vector = IA64_CPE_VECTOR; + irq = vector; /* FIXME */ delivery = IOSAPIC_LOWEST_PRIORITY; mask = 1; break; @@ -933,7 +919,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, return -1; } - register_intr(gsi, vector, delivery, polarity, trigger); + register_intr(gsi, irq, delivery, polarity, trigger); printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)" @@ -943,7 +929,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), cpu_logical_id(dest), dest, vector); - set_rte(gsi, vector, dest, mask); + set_rte(gsi, irq, dest, mask); return vector; } @@ -955,30 +941,30 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, unsigned long polarity, unsigned long trigger) { - int vector; + int vector, irq; unsigned int dest = cpu_physical_id(smp_processor_id()); vector = isa_irq_to_vector(isa_irq); - - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); + irq = vector; /* FIXME */ + register_intr(gsi, irq, 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, irq, dest, 1); } void __init iosapic_system_init (int system_pcat_compat) { - int vector; + int irq; - for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) { - iosapic_intr_info[vector].low32 = IOSAPIC_MASK; + for (irq = 0; irq < NR_IRQS; ++irq) { + iosapic_intr_info[irq].low32 = IOSAPIC_MASK; /* mark as unused */ - INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); + INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); } pcat_compat = system_pcat_compat; From f8c087f31e1d3fbf1f7d0b3ea5e643f535e7de04 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:22:14 +0900 Subject: [PATCH 07/18] [IA64] Check if irq is sharable Need to check if irq is sharable amoung handlers when searching sharable IOSAPIC irq. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index bcf91dceaf5d..cffb443a557c 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -502,8 +502,9 @@ static int iosapic_find_sharable_irq(unsigned long trigger, unsigned long pol) for (i = 0; i <= NR_IRQS; i++) { info = &iosapic_intr_info[i]; if (info->trigger == trigger && info->polarity == pol && - (info->dmode == IOSAPIC_FIXED || info->dmode == - IOSAPIC_LOWEST_PRIORITY)) { + (info->dmode == IOSAPIC_FIXED || + info->dmode == IOSAPIC_LOWEST_PRIORITY) && + can_request_irq(i, IRQF_SHARED)) { if (min_count == -1 || info->count < min_count) { irq = i; min_count = info->count; From e1b30a392835e92581db09a4e8b4b2ad53a0c370 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:22:23 +0900 Subject: [PATCH 08/18] [IA64] Add mapping table between irq and vector Add mapping tables between irqs and vectors, and its management code. This is necessary for supporting multiple vector domain because 1:1 mapping between irq and vector will be changed to n:1. The irq == vector relationship between irqs and vectors is explicitly remained for percpu interrupts, platform interrupts, isa IRQs and vectors assigned using assign_irq_vector() because some programs might depend on it. And I should consider the following problem. When pci drivers enabled/disabled devices dynamically, its irq number is changed to the different one. Therefore, suspend/resume code may happen problem. To fix this problem, I bound gsi to irq. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 61 ++++++----- arch/ia64/kernel/irq.c | 2 +- arch/ia64/kernel/irq_ia64.c | 199 ++++++++++++++++++++++++++++++------ arch/ia64/kernel/smpboot.c | 4 + include/asm-ia64/hw_irq.h | 15 ++- 5 files changed, 218 insertions(+), 63 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index cffb443a557c..cf27cfb4d165 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -117,6 +117,9 @@ static DEFINE_SPINLOCK(iosapic_lock); * These tables map IA-64 vectors to the IOSAPIC pin that generates this * vector. */ + +#define NO_REF_RTE 0 + static struct iosapic { char __iomem *addr; /* base address of IOSAPIC */ unsigned int gsi_base; /* GSI base */ @@ -204,7 +207,7 @@ inline int gsi_to_vector (unsigned int gsi) { int irq = __gsi_to_irq(gsi); - if (irq < 0) + if (check_irq_used(irq) < 0) return -1; return irq_to_vector(irq); } @@ -619,14 +622,18 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery, iosapic_intr_info[irq].count++; iosapic_lists[index].rtes_inuse++; } - else if (irq_is_shared(irq)) { + else if (rte->refcnt == NO_REF_RTE) { struct iosapic_intr_info *info = &iosapic_intr_info[irq]; - if (info->trigger != trigger || info->polarity != polarity) { + if (info->count > 0 && + (info->trigger != trigger || info->polarity != polarity)){ printk (KERN_WARNING "%s: cannot override the interrupt\n", __FUNCTION__); return -EINVAL; } + rte->refcnt++; + iosapic_intr_info[irq].count++; + iosapic_lists[index].rtes_inuse++; } iosapic_intr_info[irq].polarity = polarity; @@ -756,12 +763,17 @@ iosapic_register_intr (unsigned int gsi, irq = __gsi_to_irq(gsi); if (irq > 0) { rte = find_rte(irq, gsi); - rte->refcnt++; - goto unlock_iosapic_lock; - } + if(iosapic_intr_info[irq].count == 0) { + assign_irq_vector(irq); + dynamic_irq_init(irq); + } else if (rte->refcnt != NO_REF_RTE) { + rte->refcnt++; + goto unlock_iosapic_lock; + } + } else + irq = create_irq(); /* If vector is running out, we try to find a sharable vector */ - irq = create_irq(); if (irq < 0) { irq = iosapic_find_sharable_irq(trigger, polarity); if (irq < 0) @@ -832,18 +844,14 @@ iosapic_unregister_intr (unsigned int gsi) if (--rte->refcnt > 0) goto out; - /* Remove the rte entry from the list */ idesc = irq_desc + irq; - spin_lock(&idesc->lock); - list_del(&rte->rte_list); - spin_unlock(&idesc->lock); + rte->refcnt = NO_REF_RTE; /* Mask the interrupt */ low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK; iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32); iosapic_intr_info[irq].count--; - iosapic_free_rte(rte); index = find_iosapic(gsi); iosapic_lists[index].rtes_inuse--; WARN_ON(iosapic_lists[index].rtes_inuse < 0); @@ -857,21 +865,20 @@ iosapic_unregister_intr (unsigned int gsi) (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), cpu_logical_id(dest), dest, irq_to_vector(irq)); - if (list_empty(&iosapic_intr_info[irq].rtes)) { - /* Sanity check */ - BUG_ON(iosapic_intr_info[irq].count); + if (iosapic_intr_info[irq].count == 0) { #ifdef CONFIG_SMP /* Clear affinity */ cpus_setall(idesc->affinity); #endif /* Clear the interrupt information */ - memset(&iosapic_intr_info[irq], 0, - sizeof(struct iosapic_intr_info)); + iosapic_intr_info[irq].dest = 0; + iosapic_intr_info[irq].dmode = 0; + iosapic_intr_info[irq].polarity = 0; + iosapic_intr_info[irq].trigger = 0; iosapic_intr_info[irq].low32 |= IOSAPIC_MASK; - INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); - /* Destroy IRQ */ - destroy_irq(irq); + /* Destroy and reserve IRQ */ + destroy_and_reserve_irq(irq); } out: spin_unlock_irqrestore(&iosapic_lock, flags); @@ -892,8 +899,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, switch (int_type) { case ACPI_INTERRUPT_PMI: - vector = iosapic_vector; - irq = vector; /* FIXME */ + irq = vector = iosapic_vector; + bind_irq_vector(irq, vector); /* * since PMI vector is alloc'd by FW(ACPI) not by kernel, * we need to make sure the vector is available @@ -909,8 +916,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, delivery = IOSAPIC_INIT; break; case ACPI_INTERRUPT_CPEI: - vector = IA64_CPE_VECTOR; - irq = vector; /* FIXME */ + irq = vector = IA64_CPE_VECTOR; + BUG_ON(bind_irq_vector(irq, vector)); delivery = IOSAPIC_LOWEST_PRIORITY; mask = 1; break; @@ -945,8 +952,8 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, int vector, irq; unsigned int dest = cpu_physical_id(smp_processor_id()); - vector = isa_irq_to_vector(isa_irq); - irq = vector; /* FIXME */ + irq = vector = isa_irq_to_vector(isa_irq); + BUG_ON(bind_irq_vector(irq, vector)); register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", @@ -966,6 +973,8 @@ iosapic_system_init (int system_pcat_compat) iosapic_intr_info[irq].low32 = IOSAPIC_MASK; /* mark as unused */ INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); + + iosapic_intr_info[irq].count = 0; } pcat_compat = system_pcat_compat; diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 407b45870489..cc3ee4ef37af 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -35,7 +35,7 @@ void ack_bad_irq(unsigned int irq) #ifdef CONFIG_IA64_GENERIC unsigned int __ia64_local_vector_to_irq (ia64_vector vec) { - return (unsigned int) vec; + return __get_cpu_var(vector_irq)[vec]; } #endif diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index bc47049f060f..072427c2c3f6 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -46,6 +46,12 @@ #define IRQ_DEBUG 0 +#define IRQ_VECTOR_UNASSIGNED (0) + +#define IRQ_UNUSED (0) +#define IRQ_USED (1) +#define IRQ_RSVD (2) + /* These can be overridden in platform_irq_init */ int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR; int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; @@ -64,46 +70,161 @@ __u8 isa_irq_to_vector_map[16] = { }; EXPORT_SYMBOL(isa_irq_to_vector_map); -static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)]; +DEFINE_SPINLOCK(vector_lock); + +struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = { + [0 ... NR_IRQS - 1] = { .vector = IRQ_VECTOR_UNASSIGNED } +}; + +DEFINE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq) = { + [0 ... IA64_NUM_VECTORS - 1] = IA64_SPURIOUS_INT_VECTOR +}; + +static int irq_status[NR_IRQS] = { + [0 ... NR_IRQS -1] = IRQ_UNUSED +}; + +int check_irq_used(int irq) +{ + if (irq_status[irq] == IRQ_USED) + return 1; + + return -1; +} + +static void reserve_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&vector_lock, flags); + irq_status[irq] = IRQ_RSVD; + spin_unlock_irqrestore(&vector_lock, flags); +} + +static inline int find_unassigned_irq(void) +{ + int irq; + + for (irq = IA64_FIRST_DEVICE_VECTOR; irq < NR_IRQS; irq++) + if (irq_status[irq] == IRQ_UNUSED) + return irq; + return -ENOSPC; +} + +static inline int find_unassigned_vector(void) +{ + int vector; + + for (vector = IA64_FIRST_DEVICE_VECTOR; + vector <= IA64_LAST_DEVICE_VECTOR; vector++) + if (__get_cpu_var(vector_irq[vector]) == IA64_SPURIOUS_INT_VECTOR) + return vector; + return -ENOSPC; +} + +static int __bind_irq_vector(int irq, int vector) +{ + int cpu; + + if (irq_to_vector(irq) == vector) + return 0; + if (irq_to_vector(irq) != IRQ_VECTOR_UNASSIGNED) + return -EBUSY; + for_each_online_cpu(cpu) + per_cpu(vector_irq, cpu)[vector] = irq; + irq_cfg[irq].vector = vector; + irq_status[irq] = IRQ_USED; + return 0; +} + +int bind_irq_vector(int irq, int vector) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&vector_lock, flags); + ret = __bind_irq_vector(irq, vector); + spin_unlock_irqrestore(&vector_lock, flags); + return ret; +} + +static void clear_irq_vector(int irq) +{ + unsigned long flags; + int vector, cpu; + + spin_lock_irqsave(&vector_lock, flags); + BUG_ON((unsigned)irq >= NR_IRQS); + BUG_ON(irq_cfg[irq].vector == IRQ_VECTOR_UNASSIGNED); + vector = irq_cfg[irq].vector; + for_each_online_cpu(cpu) + per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR; + irq_cfg[irq].vector = IRQ_VECTOR_UNASSIGNED; + irq_status[irq] = IRQ_UNUSED; + spin_unlock_irqrestore(&vector_lock, flags); +} int assign_irq_vector (int irq) { - 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 -ENOSPC; - if (test_and_set_bit(pos, ia64_vector_mask)) - goto again; + unsigned long flags; + int vector = -ENOSPC; + + if (irq < 0) { + goto out; + } + spin_lock_irqsave(&vector_lock, flags); + vector = find_unassigned_vector(); + if (vector < 0) + goto out; + BUG_ON(__bind_irq_vector(irq, vector)); + spin_unlock_irqrestore(&vector_lock, flags); + out: return vector; } void free_irq_vector (int vector) { - int pos; - - if (vector < IA64_FIRST_DEVICE_VECTOR || vector > IA64_LAST_DEVICE_VECTOR) + if (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)) - printk(KERN_WARNING "%s: double free!\n", __FUNCTION__); + clear_irq_vector(vector); } int reserve_irq_vector (int vector) { - int pos; - if (vector < IA64_FIRST_DEVICE_VECTOR || vector > IA64_LAST_DEVICE_VECTOR) return -EINVAL; + return !!bind_irq_vector(vector, vector); +} - pos = vector - IA64_FIRST_DEVICE_VECTOR; - return test_and_set_bit(pos, ia64_vector_mask); +/* + * Initialize vector_irq on a new cpu. This function must be called + * with vector_lock held. + */ +void __setup_vector_irq(int cpu) +{ + int irq, vector; + + /* Clear vector_irq */ + for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) + per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR; + /* Mark the inuse vectors */ + for (irq = 0; irq < NR_IRQS; ++irq) { + if ((vector = irq_to_vector(irq)) != IRQ_VECTOR_UNASSIGNED) + per_cpu(vector_irq, cpu)[vector] = irq; + } +} + +void destroy_and_reserve_irq(unsigned int irq) +{ + dynamic_irq_cleanup(irq); + + clear_irq_vector(irq); + reserve_irq(irq); } /* @@ -111,18 +232,29 @@ reserve_irq_vector (int vector) */ int create_irq(void) { - int vector = assign_irq_vector(AUTO_ASSIGN); + unsigned long flags; + int irq, vector; - if (vector >= 0) - dynamic_irq_init(vector); - - return vector; + irq = -ENOSPC; + spin_lock_irqsave(&vector_lock, flags); + vector = find_unassigned_vector(); + if (vector < 0) + goto out; + irq = find_unassigned_irq(); + if (irq < 0) + goto out; + BUG_ON(__bind_irq_vector(irq, vector)); + out: + spin_unlock_irqrestore(&vector_lock, flags); + if (irq >= 0) + dynamic_irq_init(irq); + return irq; } void destroy_irq(unsigned int irq) { dynamic_irq_cleanup(irq); - free_irq_vector(irq); + clear_irq_vector(irq); } #ifdef CONFIG_SMP @@ -301,14 +433,13 @@ register_percpu_irq (ia64_vector vec, struct irqaction *action) irq_desc_t *desc; unsigned int irq; - for (irq = 0; irq < NR_IRQS; ++irq) - if (irq_to_vector(irq) == vec) { - desc = irq_desc + irq; - desc->status |= IRQ_PER_CPU; - desc->chip = &irq_type_ia64_lsapic; - if (action) - setup_irq(irq, action); - } + irq = vec; + BUG_ON(bind_irq_vector(irq, vec)); + desc = irq_desc + irq; + desc->status |= IRQ_PER_CPU; + desc->chip = &irq_type_ia64_lsapic; + if (action) + setup_irq(irq, action); } void __init diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 3c9d8e6089cf..9f5c90b594b9 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -395,9 +395,13 @@ smp_callin (void) fix_b0_for_bsp(); lock_ipi_calllock(); + spin_lock(&vector_lock); + /* Setup the per cpu irq handling data structures */ + __setup_vector_irq(cpuid); cpu_set(cpuid, cpu_online_map); unlock_ipi_calllock(); per_cpu(cpu_state, cpuid) = CPU_ONLINE; + spin_unlock(&vector_lock); smp_setup_percpu_timer(); diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index c054d7a9aaa7..4eff7ff2da82 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h @@ -90,13 +90,24 @@ enum { extern __u8 isa_irq_to_vector_map[16]; #define isa_irq_to_vector(x) isa_irq_to_vector_map[(x)] +struct irq_cfg { + ia64_vector vector; +}; +extern spinlock_t vector_lock; +extern struct irq_cfg irq_cfg[NR_IRQS]; +DECLARE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq); + extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */ +extern int bind_irq_vector(int irq, int vector); extern int assign_irq_vector (int irq); /* allocate a free vector */ extern void free_irq_vector (int vector); extern int reserve_irq_vector (int vector); +extern void __setup_vector_irq(int cpu); 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 int check_irq_used (int irq); +extern void destroy_and_reserve_irq (unsigned int irq); static inline void ia64_resend_irq(unsigned int vector) { @@ -113,7 +124,7 @@ extern irq_desc_t irq_desc[NR_IRQS]; static inline unsigned int __ia64_local_vector_to_irq (ia64_vector vec) { - return (unsigned int) vec; + return __get_cpu_var(vector_irq)[vec]; } #endif @@ -131,7 +142,7 @@ __ia64_local_vector_to_irq (ia64_vector vec) static inline ia64_vector irq_to_vector (int irq) { - return (ia64_vector) irq; + return irq_cfg[irq].vector; } /* From 4994be1b3fe9120c88022ff5c0c33f6312b17adb Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:22:33 +0900 Subject: [PATCH 09/18] [IA64] Add support for vector domain Add fundamental support for multiple vector domain. There still exists only one vector domain even with this patch. IRQ migration across domain is not supported yet by this patch. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 13 ++-- arch/ia64/kernel/irq_ia64.c | 120 ++++++++++++++++++++++++++---------- arch/ia64/kernel/msi_ia64.c | 9 ++- include/asm-ia64/hw_irq.h | 4 +- include/asm-ia64/irq.h | 9 ++- 5 files changed, 113 insertions(+), 42 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index cf27cfb4d165..e647254c2707 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -354,6 +354,8 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) irq &= (~IA64_IRQ_REDIRECTED); + /* IRQ migration across domain is not supported yet */ + cpus_and(mask, mask, irq_to_domain(irq)); if (cpus_empty(mask)) return; @@ -663,6 +665,7 @@ get_target_cpu (unsigned int gsi, int irq) #ifdef CONFIG_SMP static int cpu = -1; extern int cpe_vector; + cpumask_t domain = irq_to_domain(irq); /* * In case of vector shared by multiple RTEs, all RTEs that @@ -701,7 +704,7 @@ get_target_cpu (unsigned int gsi, int irq) goto skip_numa_setup; cpu_mask = node_to_cpumask(iosapic_lists[iosapic_index].node); - + cpus_and(cpu_mask, cpu_mask, domain); for_each_cpu_mask(numa_cpu, cpu_mask) { if (!cpu_online(numa_cpu)) cpu_clear(numa_cpu, cpu_mask); @@ -731,7 +734,7 @@ get_target_cpu (unsigned int gsi, int irq) do { if (++cpu >= NR_CPUS) cpu = 0; - } while (!cpu_online(cpu)); + } while (!cpu_online(cpu) || !cpu_isset(cpu, domain)); return cpu_physical_id(cpu); #else /* CONFIG_SMP */ @@ -900,7 +903,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, switch (int_type) { case ACPI_INTERRUPT_PMI: irq = vector = iosapic_vector; - bind_irq_vector(irq, vector); + bind_irq_vector(irq, vector, CPU_MASK_ALL); /* * since PMI vector is alloc'd by FW(ACPI) not by kernel, * we need to make sure the vector is available @@ -917,7 +920,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, break; case ACPI_INTERRUPT_CPEI: irq = vector = IA64_CPE_VECTOR; - BUG_ON(bind_irq_vector(irq, vector)); + BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL)); delivery = IOSAPIC_LOWEST_PRIORITY; mask = 1; break; @@ -953,7 +956,7 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, unsigned int dest = cpu_physical_id(smp_processor_id()); irq = vector = isa_irq_to_vector(isa_irq); - BUG_ON(bind_irq_vector(irq, vector)); + BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL)); register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 072427c2c3f6..a3667631ed80 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -60,6 +60,8 @@ int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; void __iomem *ipi_base_addr = ((void __iomem *) (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR)); +static cpumask_t vector_allocation_domain(int cpu); + /* * Legacy IRQ to IA-64 vector translation table. */ @@ -73,13 +75,20 @@ EXPORT_SYMBOL(isa_irq_to_vector_map); DEFINE_SPINLOCK(vector_lock); struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = { - [0 ... NR_IRQS - 1] = { .vector = IRQ_VECTOR_UNASSIGNED } + [0 ... NR_IRQS - 1] = { + .vector = IRQ_VECTOR_UNASSIGNED, + .domain = CPU_MASK_NONE + } }; DEFINE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq) = { [0 ... IA64_NUM_VECTORS - 1] = IA64_SPURIOUS_INT_VECTOR }; +static cpumask_t vector_table[IA64_MAX_DEVICE_VECTORS] = { + [0 ... IA64_MAX_DEVICE_VECTORS - 1] = CPU_MASK_NONE +}; + static int irq_status[NR_IRQS] = { [0 ... NR_IRQS -1] = IRQ_UNUSED }; @@ -111,39 +120,54 @@ static inline int find_unassigned_irq(void) return -ENOSPC; } -static inline int find_unassigned_vector(void) +static inline int find_unassigned_vector(cpumask_t domain) { - int vector; + cpumask_t mask; + int pos; - for (vector = IA64_FIRST_DEVICE_VECTOR; - vector <= IA64_LAST_DEVICE_VECTOR; vector++) - if (__get_cpu_var(vector_irq[vector]) == IA64_SPURIOUS_INT_VECTOR) - return vector; + cpus_and(mask, domain, cpu_online_map); + if (cpus_empty(mask)) + return -EINVAL; + + for (pos = 0; pos < IA64_NUM_DEVICE_VECTORS; pos++) { + cpus_and(mask, domain, vector_table[pos]); + if (!cpus_empty(mask)) + continue; + return IA64_FIRST_DEVICE_VECTOR + pos; + } return -ENOSPC; } -static int __bind_irq_vector(int irq, int vector) +static int __bind_irq_vector(int irq, int vector, cpumask_t domain) { - int cpu; + cpumask_t mask; + int cpu, pos; + struct irq_cfg *cfg = &irq_cfg[irq]; - if (irq_to_vector(irq) == vector) + cpus_and(mask, domain, cpu_online_map); + if (cpus_empty(mask)) + return -EINVAL; + if ((cfg->vector == vector) && cpus_equal(cfg->domain, domain)) return 0; - if (irq_to_vector(irq) != IRQ_VECTOR_UNASSIGNED) + if (cfg->vector != IRQ_VECTOR_UNASSIGNED) return -EBUSY; - for_each_online_cpu(cpu) + for_each_cpu_mask(cpu, mask) per_cpu(vector_irq, cpu)[vector] = irq; - irq_cfg[irq].vector = vector; + cfg->vector = vector; + cfg->domain = domain; irq_status[irq] = IRQ_USED; + pos = vector - IA64_FIRST_DEVICE_VECTOR; + cpus_or(vector_table[pos], vector_table[pos], domain); return 0; } -int bind_irq_vector(int irq, int vector) +int bind_irq_vector(int irq, int vector, cpumask_t domain) { unsigned long flags; int ret; spin_lock_irqsave(&vector_lock, flags); - ret = __bind_irq_vector(irq, vector); + ret = __bind_irq_vector(irq, vector, domain); spin_unlock_irqrestore(&vector_lock, flags); return ret; } @@ -151,16 +175,24 @@ int bind_irq_vector(int irq, int vector) static void clear_irq_vector(int irq) { unsigned long flags; - int vector, cpu; + int vector, cpu, pos; + cpumask_t mask; + cpumask_t domain; + struct irq_cfg *cfg = &irq_cfg[irq]; spin_lock_irqsave(&vector_lock, flags); BUG_ON((unsigned)irq >= NR_IRQS); - BUG_ON(irq_cfg[irq].vector == IRQ_VECTOR_UNASSIGNED); - vector = irq_cfg[irq].vector; - for_each_online_cpu(cpu) + BUG_ON(cfg->vector == IRQ_VECTOR_UNASSIGNED); + vector = cfg->vector; + domain = cfg->domain; + cpus_and(mask, cfg->domain, cpu_online_map); + for_each_cpu_mask(cpu, mask) per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR; - irq_cfg[irq].vector = IRQ_VECTOR_UNASSIGNED; + cfg->vector = IRQ_VECTOR_UNASSIGNED; + cfg->domain = CPU_MASK_NONE; irq_status[irq] = IRQ_UNUSED; + pos = vector - IA64_FIRST_DEVICE_VECTOR; + cpus_andnot(vector_table[pos], vector_table[pos], domain); spin_unlock_irqrestore(&vector_lock, flags); } @@ -168,18 +200,26 @@ int assign_irq_vector (int irq) { unsigned long flags; - int vector = -ENOSPC; + int vector, cpu; + cpumask_t domain; + vector = -ENOSPC; + + spin_lock_irqsave(&vector_lock, flags); if (irq < 0) { goto out; } - spin_lock_irqsave(&vector_lock, flags); - vector = find_unassigned_vector(); + for_each_online_cpu(cpu) { + domain = vector_allocation_domain(cpu); + vector = find_unassigned_vector(domain); + if (vector >= 0) + break; + } if (vector < 0) goto out; - BUG_ON(__bind_irq_vector(irq, vector)); - spin_unlock_irqrestore(&vector_lock, flags); + BUG_ON(__bind_irq_vector(irq, vector, domain)); out: + spin_unlock_irqrestore(&vector_lock, flags); return vector; } @@ -198,7 +238,7 @@ reserve_irq_vector (int vector) if (vector < IA64_FIRST_DEVICE_VECTOR || vector > IA64_LAST_DEVICE_VECTOR) return -EINVAL; - return !!bind_irq_vector(vector, vector); + return !!bind_irq_vector(vector, vector, CPU_MASK_ALL); } /* @@ -214,11 +254,19 @@ void __setup_vector_irq(int cpu) per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR; /* Mark the inuse vectors */ for (irq = 0; irq < NR_IRQS; ++irq) { - if ((vector = irq_to_vector(irq)) != IRQ_VECTOR_UNASSIGNED) - per_cpu(vector_irq, cpu)[vector] = irq; + if (!cpu_isset(cpu, irq_cfg[irq].domain)) + continue; + vector = irq_to_vector(irq); + per_cpu(vector_irq, cpu)[vector] = irq; } } +static cpumask_t vector_allocation_domain(int cpu) +{ + return CPU_MASK_ALL; +} + + void destroy_and_reserve_irq(unsigned int irq) { dynamic_irq_cleanup(irq); @@ -233,17 +281,23 @@ void destroy_and_reserve_irq(unsigned int irq) int create_irq(void) { unsigned long flags; - int irq, vector; + int irq, vector, cpu; + cpumask_t domain; - irq = -ENOSPC; + irq = vector = -ENOSPC; spin_lock_irqsave(&vector_lock, flags); - vector = find_unassigned_vector(); + for_each_online_cpu(cpu) { + domain = vector_allocation_domain(cpu); + vector = find_unassigned_vector(domain); + if (vector >= 0) + break; + } if (vector < 0) goto out; irq = find_unassigned_irq(); if (irq < 0) goto out; - BUG_ON(__bind_irq_vector(irq, vector)); + BUG_ON(__bind_irq_vector(irq, vector, domain)); out: spin_unlock_irqrestore(&vector_lock, flags); if (irq >= 0) @@ -434,7 +488,7 @@ register_percpu_irq (ia64_vector vec, struct irqaction *action) unsigned int irq; irq = vec; - BUG_ON(bind_irq_vector(irq, vec)); + BUG_ON(bind_irq_vector(irq, vec, CPU_MASK_ALL)); desc = irq_desc + irq; desc->status |= IRQ_PER_CPU; desc->chip = &irq_type_ia64_lsapic; diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index c81080df70df..1d22670cc88b 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -52,6 +52,11 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) struct msi_msg msg; u32 addr; + /* IRQ migration across domain is not supported yet */ + cpus_and(cpu_mask, cpu_mask, irq_to_domain(irq)); + if (cpus_empty(cpu_mask)) + return; + read_msi_msg(irq, &msg); addr = msg.address_lo; @@ -69,13 +74,15 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) struct msi_msg msg; unsigned long dest_phys_id; int irq, vector; + cpumask_t mask; irq = create_irq(); if (irq < 0) return irq; set_irq_msi(irq, desc); - dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); + cpus_and(mask, irq_to_domain(irq), cpu_online_map); + dest_phys_id = cpu_physical_id(first_cpu(mask)); vector = irq_to_vector(irq); msg.address_hi = 0; diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index 4eff7ff2da82..97ea3900d74a 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h @@ -92,14 +92,16 @@ extern __u8 isa_irq_to_vector_map[16]; struct irq_cfg { ia64_vector vector; + cpumask_t domain; }; extern spinlock_t vector_lock; extern struct irq_cfg irq_cfg[NR_IRQS]; +#define irq_to_domain(x) irq_cfg[(x)].domain DECLARE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq); extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */ -extern int bind_irq_vector(int irq, int vector); +extern int bind_irq_vector(int irq, int vector, cpumask_t domain); extern int assign_irq_vector (int irq); /* allocate a free vector */ extern void free_irq_vector (int vector); extern int reserve_irq_vector (int vector); diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h index 67221615e317..35b360b82e43 100644 --- a/include/asm-ia64/irq.h +++ b/include/asm-ia64/irq.h @@ -14,8 +14,13 @@ #include #include -#define NR_IRQS 256 -#define NR_IRQ_VECTORS NR_IRQS +#define NR_VECTORS 256 + +#if (NR_VECTORS + 32 * NR_CPUS) < 1024 +#define NR_IRQS (NR_VECTORS + 32 * NR_CPUS) +#else +#define NR_IRQS 1024 +#endif static __inline__ int irq_canonicalize (int irq) From cd378f18cf73d92bf0b6e1e6b5759b5dd729a9f2 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:22:48 +0900 Subject: [PATCH 10/18] [IA64] Support irq migration across domain Add support for IRQ migration across vector domain. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 20 +++++++++++++++--- arch/ia64/kernel/irq_ia64.c | 42 ++++++++++++++++++++++++++++++++++--- arch/ia64/kernel/msi_ia64.c | 20 ++++++++++++------ include/asm-ia64/hw_irq.h | 1 + include/asm-ia64/iosapic.h | 2 ++ 5 files changed, 73 insertions(+), 12 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index e647254c2707..c101c8bff27b 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -354,11 +354,13 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) irq &= (~IA64_IRQ_REDIRECTED); - /* IRQ migration across domain is not supported yet */ - cpus_and(mask, mask, irq_to_domain(irq)); + cpus_and(mask, mask, cpu_online_map); if (cpus_empty(mask)) return; + if (reassign_irq_vector(irq, first_cpu(mask))) + return; + dest = cpu_physical_id(first_cpu(mask)); if (list_empty(&iosapic_intr_info[irq].rtes)) @@ -376,6 +378,8 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) else /* change delivery mode to fixed */ low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); + low32 &= IOSAPIC_VECTOR_MASK; + low32 |= irq_to_vector(irq); iosapic_intr_info[irq].low32 = low32; iosapic_intr_info[irq].dest = dest; @@ -404,10 +408,20 @@ iosapic_end_level_irq (unsigned int irq) { ia64_vector vec = irq_to_vector(irq); struct iosapic_rte_info *rte; + int do_unmask_irq = 0; + + if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) { + do_unmask_irq = 1; + mask_irq(irq); + } - move_native_irq(irq); list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) iosapic_eoi(rte->iosapic->addr, vec); + + if (unlikely(do_unmask_irq)) { + move_masked_irq(irq); + unmask_irq(irq); + } } #define iosapic_shutdown_level_irq mask_irq diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index a3667631ed80..22806b94025a 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -172,15 +172,13 @@ int bind_irq_vector(int irq, int vector, cpumask_t domain) return ret; } -static void clear_irq_vector(int irq) +static void __clear_irq_vector(int irq) { - unsigned long flags; int vector, cpu, pos; cpumask_t mask; cpumask_t domain; struct irq_cfg *cfg = &irq_cfg[irq]; - spin_lock_irqsave(&vector_lock, flags); BUG_ON((unsigned)irq >= NR_IRQS); BUG_ON(cfg->vector == IRQ_VECTOR_UNASSIGNED); vector = cfg->vector; @@ -193,6 +191,14 @@ static void clear_irq_vector(int irq) irq_status[irq] = IRQ_UNUSED; pos = vector - IA64_FIRST_DEVICE_VECTOR; cpus_andnot(vector_table[pos], vector_table[pos], domain); +} + +static void clear_irq_vector(int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&vector_lock, flags); + __clear_irq_vector(irq); spin_unlock_irqrestore(&vector_lock, flags); } @@ -275,6 +281,36 @@ void destroy_and_reserve_irq(unsigned int irq) reserve_irq(irq); } +static int __reassign_irq_vector(int irq, int cpu) +{ + struct irq_cfg *cfg = &irq_cfg[irq]; + int vector; + cpumask_t domain; + + if (cfg->vector == IRQ_VECTOR_UNASSIGNED || !cpu_online(cpu)) + return -EINVAL; + if (cpu_isset(cpu, cfg->domain)) + return 0; + domain = vector_allocation_domain(cpu); + vector = find_unassigned_vector(domain); + if (vector < 0) + return -ENOSPC; + __clear_irq_vector(irq); + BUG_ON(__bind_irq_vector(irq, vector, domain)); + return 0; +} + +int reassign_irq_vector(int irq, int cpu) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&vector_lock, flags); + ret = __reassign_irq_vector(irq, cpu); + spin_unlock_irqrestore(&vector_lock, flags); + return ret; +} + /* * Dynamic irq allocate and deallocation for MSI */ diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 1d22670cc88b..2fdbd5c3f213 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -13,6 +13,7 @@ #define MSI_DATA_VECTOR_SHIFT 0 #define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) +#define MSI_DATA_VECTOR_MASK 0xffffff00 #define MSI_DATA_DELIVERY_SHIFT 8 #define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) @@ -50,22 +51,29 @@ static struct irq_chip ia64_msi_chip; static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) { struct msi_msg msg; - u32 addr; + u32 addr, data; + int cpu = first_cpu(cpu_mask); - /* IRQ migration across domain is not supported yet */ - cpus_and(cpu_mask, cpu_mask, irq_to_domain(irq)); - if (cpus_empty(cpu_mask)) + if (!cpu_online(cpu)) + return; + + if (reassign_irq_vector(irq, cpu)) return; read_msi_msg(irq, &msg); addr = msg.address_lo; addr &= MSI_ADDR_DESTID_MASK; - addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); + addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); msg.address_lo = addr; + data = msg.data; + data &= MSI_DATA_VECTOR_MASK; + data |= MSI_DATA_VECTOR(irq_to_vector(irq)); + msg.data = data; + write_msi_msg(irq, &msg); - irq_desc[irq].affinity = cpu_mask; + irq_desc[irq].affinity = cpumask_of_cpu(cpu); } #endif /* CONFIG_SMP */ diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index 97ea3900d74a..efa1b8f7251d 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h @@ -106,6 +106,7 @@ extern int assign_irq_vector (int irq); /* allocate a free vector */ extern void free_irq_vector (int vector); extern int reserve_irq_vector (int vector); extern void __setup_vector_irq(int cpu); +extern int reassign_irq_vector(int irq, int cpu); 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 int check_irq_used (int irq); diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h index 09bdc3898df8..b8f712859140 100644 --- a/include/asm-ia64/iosapic.h +++ b/include/asm-ia64/iosapic.h @@ -47,6 +47,8 @@ #define IOSAPIC_MASK_SHIFT 16 #define IOSAPIC_MASK (1< Date: Tue, 17 Jul 2007 21:22:55 +0900 Subject: [PATCH 11/18] [IA64] Enable percpu vector domain for IA64_GENERIC Add per-CPU vector domain support for IA64_GENERIC. It is enabled by adding the "vector=percpu" boot option. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- Documentation/kernel-parameters.txt | 3 +++ arch/ia64/kernel/irq_ia64.c | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 8363ad3ba018..c48bc2e159ce 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1859,6 +1859,9 @@ and is between 256 and 4096 characters. It is defined in the file vdso=1: enable VDSO (default) vdso=0: disable VDSO mapping + vector= [IA-64,SMP] + vector=percpu: enable percpu vector domain + video= [FB] Frame buffer configuration See Documentation/fb/modedb.txt. diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 22806b94025a..5cb804f9a1ff 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -267,10 +267,36 @@ void __setup_vector_irq(int cpu) } } +#if defined(CONFIG_IA64_GENERIC) +static enum vector_domain_type { + VECTOR_DOMAIN_NONE, + VECTOR_DOMAIN_PERCPU +} vector_domain_type = VECTOR_DOMAIN_NONE; + +static cpumask_t vector_allocation_domain(int cpu) +{ + if (vector_domain_type == VECTOR_DOMAIN_PERCPU) + return cpumask_of_cpu(cpu); + return CPU_MASK_ALL; +} + +static int __init parse_vector_domain(char *arg) +{ + if (!arg) + return -EINVAL; + if (!strcmp(arg, "percpu")) { + vector_domain_type = VECTOR_DOMAIN_PERCPU; + no_int_routing = 1; + } + return 1; +} +early_param("vector", parse_vector_domain); +#else static cpumask_t vector_allocation_domain(int cpu) { return CPU_MASK_ALL; } +#endif void destroy_and_reserve_irq(unsigned int irq) From e5bd762bda0d9aba8739a35f898479dc12e288a1 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Tue, 17 Jul 2007 21:23:03 +0900 Subject: [PATCH 12/18] [IA64] Enable percpu vector domain for IA64_DIG Add per-CPU vector domain support for IA64_DIG. It is enabled by adding the "vector=percpu" boot option. Signed-off-by: Kenji Kaneshige Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/irq_ia64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 5cb804f9a1ff..91797c111162 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -267,7 +267,7 @@ void __setup_vector_irq(int cpu) } } -#if defined(CONFIG_IA64_GENERIC) +#if defined(CONFIG_SMP) && (defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG)) static enum vector_domain_type { VECTOR_DOMAIN_NONE, VECTOR_DOMAIN_PERCPU From 3d7559e677deafefe134f36c1e75f9119b956672 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Mon, 16 Jul 2007 15:33:40 +1000 Subject: [PATCH 13/18] [IA64] fallocate system call sys_fallocate for ia64. This uses an empty slot #1303 erroneously marked as reserved for move_pages (which had already been allocated as syscall #1276) Signed-Off-By: Dave Chinner Signed-off-by: Tony Luck --- arch/ia64/kernel/entry.S | 2 +- include/asm-ia64/unistd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 95f517515235..c36f43c94600 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1581,7 +1581,7 @@ sys_call_table: data8 sys_sync_file_range // 1300 data8 sys_tee data8 sys_vmsplice - data8 sys_ni_syscall // reserved for move_pages + data8 sys_fallocate data8 sys_getcpu data8 sys_epoll_pwait // 1305 data8 sys_utimensat diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index 441c9e001776..315f8de950a2 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h @@ -292,7 +292,7 @@ #define __NR_sync_file_range 1300 #define __NR_tee 1301 #define __NR_vmsplice 1302 -/* 1303 reserved for move_pages */ +#define __NR_fallocate 1303 #define __NR_getcpu 1304 #define __NR_epoll_pwait 1305 #define __NR_utimensat 1306 From bf903d0a4503db8ac166ca6135a59bc5f9b91a45 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Wed, 18 Jul 2007 15:47:34 +0900 Subject: [PATCH 14/18] [IA64] Delete iosapic_free_rte() > arch/ia64/kernel/iosapic.c:597: warning: 'iosapic_free_rte' defined but not used > > This isn't spurious, the only call to iosapic_free_rte() has been removed, but there > is still a call to iosapic_alloc_rte() ... which means we must have a memory leak. I did it on purpose (and gave the warning a miss...) and I consider iosapic_free_rte() is no longer needed. I decided to remain iosapic_rte_info to keep gsi-to-irq binding after device disable. Indeed it needs some extra memory, but it is only "sizeof(iosapic_rte_info) * " bytes and has no memory leak becasue re-enabled devices use the iosapic_rte_info which they used before disabling. Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index c101c8bff27b..91e6dc1e7baf 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -593,14 +593,6 @@ static struct iosapic_rte_info *iosapic_alloc_rte (void) return rte; } -static void iosapic_free_rte (struct iosapic_rte_info *rte) -{ - if (rte->flags & RTE_PREALLOCATED) - list_add_tail(&rte->rte_list, &free_rte_list); - else - kfree(rte); -} - static inline int irq_is_shared (int irq) { return (iosapic_intr_info[irq].count > 1); From ffc720409ae8d1cb16ae4b9c39e9e744e4c59898 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 19 Jul 2007 14:00:34 -0700 Subject: [PATCH 15/18] [IA64] refresh some config files for 64K pagesize Update arch/ia64/defconfig: select 64K pagesize Same for arch/ia64/configs/tiger_defconfig + CONFIG_COMPAT=n Signed-off-by: Tony Luck --- arch/ia64/configs/tiger_defconfig | 320 +++++++++------------------- arch/ia64/defconfig | 338 ++++++++++-------------------- 2 files changed, 213 insertions(+), 445 deletions(-) diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index a1446931b401..205bbc30b0d0 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21-rc3 -# Thu Mar 8 11:07:09 2007 +# Linux kernel version: 2.6.22 +# Thu Jul 19 13:54:47 2007 # CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -19,15 +19,15 @@ CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_IPC_NS is not set CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=20 # CONFIG_CPUSETS is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set @@ -46,18 +46,19 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set @@ -65,12 +66,9 @@ CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y CONFIG_STOP_MACHINE=y - -# -# Block layer -# CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set # # IO Schedulers @@ -91,6 +89,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_IA64=y CONFIG_64BIT=y CONFIG_ZONE_DMA=y +CONFIG_QUICKLIST=y CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -114,8 +113,8 @@ CONFIG_IA64_DIG=y CONFIG_MCKINLEY=y # CONFIG_IA64_PAGE_SIZE_4KB is not set # CONFIG_IA64_PAGE_SIZE_8KB is not set -CONFIG_IA64_PAGE_SIZE_16KB=y -# CONFIG_IA64_PAGE_SIZE_64KB is not set +# CONFIG_IA64_PAGE_SIZE_16KB is not set +CONFIG_IA64_PAGE_SIZE_64KB=y CONFIG_PGTABLE_3=y # CONFIG_PGTABLE_4 is not set # CONFIG_HZ_100 is not set @@ -145,6 +144,9 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_RESOURCES_64BIT=y CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_NR_QUICK=1 +CONFIG_VIRT_TO_BUS=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -152,11 +154,11 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_VIRTUAL_MEM_MAP=y CONFIG_HOLES_IN_ZONE=y -CONFIG_IA32_SUPPORT=y -CONFIG_COMPAT=y +# CONFIG_IA32_SUPPORT is not set CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y +# CONFIG_IA64_MC_ERR_INJECT is not set # CONFIG_IA64_ESI is not set CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set @@ -166,6 +168,7 @@ CONFIG_KEXEC=y # CONFIG_EFI_VARS=y CONFIG_EFI_PCDP=y +CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m @@ -175,7 +178,6 @@ CONFIG_BINFMT_MISC=m CONFIG_PM=y CONFIG_PM_LEGACY=y # CONFIG_PM_DEBUG is not set -# CONFIG_PM_SYSFS_DEPRECATED is not set # # ACPI (Advanced Configuration and Power Interface) Support @@ -205,13 +207,11 @@ CONFIG_ACPI_CONTAINER=m # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_PCI_SYSCALL=y # CONFIG_PCIEPORTBUS is not set +CONFIG_ARCH_SUPPORTS_MSI=y # CONFIG_PCI_MSI is not set # CONFIG_PCI_DEBUG is not set - -# -# PCI Hotplug Support -# CONFIG_HOTPLUG_PCI=m # CONFIG_HOTPLUG_PCI_FAKE is not set CONFIG_HOTPLUG_PCI_ACPI=m @@ -232,7 +232,6 @@ CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -270,20 +269,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_INET6_TUNNEL is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# # CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -309,7 +296,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -324,25 +321,9 @@ CONFIG_FW_LOADER=m # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# # CONFIG_MTD is not set - -# -# Parallel port support -# # CONFIG_PARPORT is not set - -# -# Plug and Play support -# CONFIG_PNP=y # CONFIG_PNP_DEBUG is not set @@ -350,10 +331,7 @@ CONFIG_PNP=y # Protocols # CONFIG_PNPACPI=y - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -370,16 +348,11 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set - -# -# Misc devices -# +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set - -# -# ATA/ATAPI/MFM/RLL support -# CONFIG_IDE=y CONFIG_IDE_MAX_HWIFS=4 CONFIG_BLK_DEV_IDE=y @@ -396,6 +369,7 @@ CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=m # CONFIG_BLK_DEV_IDEACPI is not set # CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes @@ -404,12 +378,12 @@ CONFIG_BLK_DEV_IDESCSI=m # CONFIG_BLK_DEV_IDEPNP is not set CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set +CONFIG_IDEPCI_PCIBUS_ORDER=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set @@ -438,7 +412,6 @@ CONFIG_BLK_DEV_PIIX=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # @@ -446,6 +419,7 @@ CONFIG_IDEDMA_AUTO=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y # CONFIG_SCSI_TGT is not set CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y @@ -468,6 +442,7 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports @@ -514,15 +489,7 @@ CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SRP is not set - -# -# Serial ATA (prod) and Parallel ATA (experimental) drivers -# # CONFIG_ATA is not set - -# -# Multi-device support (RAID and LVM) -# CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -539,6 +506,7 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m # CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set # # Fusion MPT device support @@ -553,46 +521,25 @@ CONFIG_FUSION_CTL=y # # IEEE 1394 (FireWire) support # +# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set - -# -# I2O device support -# # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set - -# -# ARCnet devices -# # CONFIG_ARCNET is not set - -# -# PHY device support -# # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=m # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# CONFIG_NET_TULIP=y # CONFIG_DE2104X is not set CONFIG_TULIP=m @@ -623,10 +570,7 @@ CONFIG_E100=m # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set - -# -# Ethernet (1000 Mbit) -# +CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set CONFIG_E1000=y @@ -639,36 +583,36 @@ CONFIG_E1000=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set - -# -# Ethernet (10000 Mbit) -# +CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set - -# -# Token Ring devices -# +# CONFIG_MLX4_CORE is not set # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) +# Wireless LAN # -# CONFIG_NET_RADIO is not set +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # -# Wan interfaces +# USB Network Adapters # +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -678,18 +622,9 @@ CONFIG_TIGON3=y # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set # CONFIG_NETPOLL_TRAP is not set CONFIG_NET_POLL_CONTROLLER=y - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # @@ -697,6 +632,7 @@ CONFIG_NET_POLL_CONTROLLER=y # CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -722,9 +658,17 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set # CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -790,19 +734,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set CONFIG_EFI_RTC=y -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set CONFIG_AGP=m @@ -821,15 +756,8 @@ CONFIG_HPET=y # CONFIG_HPET_RTC_IRQ is not set CONFIG_HPET_MMAP=y # CONFIG_HANGCHECK_TIMER is not set - -# -# TPM devices -# # CONFIG_TCG_TPM is not set - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set # @@ -837,21 +765,17 @@ CONFIG_HPET_MMAP=y # # CONFIG_SPI is not set # CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83627HF is not set # CONFIG_HWMON_DEBUG_CHIP is not set # @@ -863,17 +787,20 @@ CONFIG_HWMON=y # Multimedia devices # # CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set +# CONFIG_DVB_CORE is not set +CONFIG_DAB=y # CONFIG_USB_DABUSB is not set # # Graphics support # # CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set # CONFIG_FB is not set # @@ -887,16 +814,18 @@ CONFIG_DUMMY_CONSOLE=y # Sound # # CONFIG_SOUND is not set - -# -# HID Devices -# +CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set # -# USB support +# USB Input Devices # +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y @@ -907,8 +836,10 @@ CONFIG_USB=y # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set +# CONFIG_USB_PERSIST is not set # CONFIG_USB_OTG is not set # @@ -918,7 +849,6 @@ CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set # CONFIG_USB_EHCI_TT_NEWSCHED is not set -# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=m # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set @@ -926,6 +856,7 @@ CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set # # USB Device Class drivers @@ -954,42 +885,11 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_KARMA is not set # CONFIG_USB_LIBUSUAL is not set -# -# USB Input Devices -# -CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_TOUCHSCREEN is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_GTCO is not set - # # USB Imaging devices # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET_MII is not set -# CONFIG_USB_USBNET is not set # CONFIG_USB_MON is not set # @@ -1033,10 +933,6 @@ CONFIG_USB_HID=y # USB Gadget Support # # CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# # CONFIG_MMC is not set # @@ -1051,16 +947,8 @@ CONFIG_USB_HID=y # # LED Triggers # - -# -# InfiniBand support -# # CONFIG_INFINIBAND is not set -# -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - # # Real Time Clock # @@ -1080,12 +968,9 @@ CONFIG_USB_HID=y # # -# Auxiliary Display support -# - -# -# Virtualization +# Userspace I/O # +# CONFIG_UIO is not set # CONFIG_MSPEC is not set # @@ -1200,7 +1085,8 @@ CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SUNRPC_BIND34 is not set +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m CONFIG_SMB_NLS_DEFAULT=y @@ -1214,7 +1100,6 @@ CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types @@ -1236,6 +1121,7 @@ CONFIG_SGI_PARTITION=y # CONFIG_SUN_PARTITION is not set # CONFIG_KARMA_PARTITION is not set CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set # # Native Language Support @@ -1292,11 +1178,14 @@ CONFIG_NLS_UTF8=m CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y @@ -1319,8 +1208,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set -CONFIG_LOG_BUF_SHIFT=20 CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set @@ -1343,17 +1232,12 @@ CONFIG_IA64_GRANULE_16MB=y # CONFIG_DISABLE_VHPT is not set # CONFIG_IA64_DEBUG_CMPXCHG is not set # CONFIG_IA64_DEBUG_IRQ is not set -CONFIG_SYSVIPC_COMPAT=y # # Security options # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set - -# -# Cryptographic options -# CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=m @@ -1373,6 +1257,7 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=m CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_BLOWFISH is not set @@ -1390,7 +1275,4 @@ CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set - -# -# Hardware crypto devices -# +CONFIG_CRYPTO_HW=y diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig index 90bd9601cdde..80298ef905eb 100644 --- a/arch/ia64/defconfig +++ b/arch/ia64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21-rc3 -# Thu Mar 8 11:01:03 2007 +# Linux kernel version: 2.6.22 +# Thu Jul 19 13:55:32 2007 # CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -19,15 +19,15 @@ CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_IPC_NS is not set CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=20 # CONFIG_CPUSETS is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set @@ -46,18 +46,19 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set @@ -65,12 +66,9 @@ CONFIG_MODVERSIONS=y # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y - -# -# Block layer -# CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set # # IO Schedulers @@ -91,6 +89,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_IA64=y CONFIG_64BIT=y CONFIG_ZONE_DMA=y +CONFIG_QUICKLIST=y CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -114,8 +113,8 @@ CONFIG_IA64_GENERIC=y CONFIG_MCKINLEY=y # CONFIG_IA64_PAGE_SIZE_4KB is not set # CONFIG_IA64_PAGE_SIZE_8KB is not set -CONFIG_IA64_PAGE_SIZE_16KB=y -# CONFIG_IA64_PAGE_SIZE_64KB is not set +# CONFIG_IA64_PAGE_SIZE_16KB is not set +CONFIG_IA64_PAGE_SIZE_64KB=y CONFIG_PGTABLE_3=y # CONFIG_PGTABLE_4 is not set # CONFIG_HZ_100 is not set @@ -147,6 +146,9 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_NR_QUICK=1 +CONFIG_VIRT_TO_BUS=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -164,7 +166,7 @@ CONFIG_COMPAT=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y -# CONFIG_MC_ERR_INJECT is not set +# CONFIG_IA64_MC_ERR_INJECT is not set CONFIG_SGI_SN=y # CONFIG_IA64_ESI is not set @@ -180,6 +182,7 @@ CONFIG_CRASH_DUMP=y # CONFIG_EFI_VARS=y CONFIG_EFI_PCDP=y +CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m @@ -189,7 +192,6 @@ CONFIG_BINFMT_MISC=m CONFIG_PM=y CONFIG_PM_LEGACY=y # CONFIG_PM_DEBUG is not set -# CONFIG_PM_SYSFS_DEPRECATED is not set # # ACPI (Advanced Configuration and Power Interface) Support @@ -220,13 +222,11 @@ CONFIG_ACPI_CONTAINER=m # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_PCI_SYSCALL=y # CONFIG_PCIEPORTBUS is not set +CONFIG_ARCH_SUPPORTS_MSI=y # CONFIG_PCI_MSI is not set # CONFIG_PCI_DEBUG is not set - -# -# PCI Hotplug Support -# CONFIG_HOTPLUG_PCI=m # CONFIG_HOTPLUG_PCI_FAKE is not set CONFIG_HOTPLUG_PCI_ACPI=m @@ -248,7 +248,6 @@ CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -286,20 +285,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_INET6_TUNNEL is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# # CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -325,7 +312,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -340,25 +337,9 @@ CONFIG_FW_LOADER=m # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# # CONFIG_MTD is not set - -# -# Parallel port support -# # CONFIG_PARPORT is not set - -# -# Plug and Play support -# CONFIG_PNP=y # CONFIG_PNP_DEBUG is not set @@ -366,10 +347,7 @@ CONFIG_PNP=y # Protocols # CONFIG_PNPACPI=y - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -386,16 +364,11 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set - -# -# Misc devices -# +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set CONFIG_SGI_IOC4=y # CONFIG_TIFM_CORE is not set - -# -# ATA/ATAPI/MFM/RLL support -# CONFIG_IDE=y CONFIG_IDE_MAX_HWIFS=4 CONFIG_BLK_DEV_IDE=y @@ -412,6 +385,7 @@ CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=m # CONFIG_BLK_DEV_IDEACPI is not set # CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes @@ -420,12 +394,12 @@ CONFIG_BLK_DEV_IDESCSI=m # CONFIG_BLK_DEV_IDEPNP is not set CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_IDEPCI_PCIBUS_ORDER=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set @@ -455,7 +429,6 @@ CONFIG_BLK_DEV_SGIIOC4=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # @@ -463,6 +436,7 @@ CONFIG_IDEDMA_AUTO=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y # CONFIG_SCSI_TGT is not set CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y @@ -485,6 +459,7 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports @@ -492,7 +467,7 @@ CONFIG_CHR_DEV_SG=m CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set +CONFIG_SCSI_SAS_ATTRS=y # CONFIG_SCSI_SAS_LIBSAS is not set # @@ -531,15 +506,7 @@ CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SRP is not set - -# -# Serial ATA (prod) and Parallel ATA (experimental) drivers -# # CONFIG_ATA is not set - -# -# Multi-device support (RAID and LVM) -# CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -557,6 +524,8 @@ CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m # CONFIG_DM_MULTIPATH_EMC is not set +# CONFIG_DM_MULTIPATH_RDAC is not set +# CONFIG_DM_DELAY is not set # # Fusion MPT device support @@ -564,53 +533,32 @@ CONFIG_DM_MULTIPATH=m CONFIG_FUSION=y CONFIG_FUSION_SPI=y CONFIG_FUSION_FC=m -# CONFIG_FUSION_SAS is not set +CONFIG_FUSION_SAS=y CONFIG_FUSION_MAX_SGE=128 # CONFIG_FUSION_CTL is not set # # IEEE 1394 (FireWire) support # +# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set - -# -# I2O device support -# # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set - -# -# ARCnet devices -# # CONFIG_ARCNET is not set - -# -# PHY device support -# # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=m # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# CONFIG_NET_TULIP=y # CONFIG_DE2104X is not set CONFIG_TULIP=m @@ -641,10 +589,7 @@ CONFIG_E100=m # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set - -# -# Ethernet (1000 Mbit) -# +CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set CONFIG_E1000=y @@ -657,36 +602,36 @@ CONFIG_E1000=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set - -# -# Ethernet (10000 Mbit) -# +CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set - -# -# Token Ring devices -# +# CONFIG_MLX4_CORE is not set # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) +# Wireless LAN # -# CONFIG_NET_RADIO is not set +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # -# Wan interfaces +# USB Network Adapters # +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -696,18 +641,9 @@ CONFIG_TIGON3=y # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set # CONFIG_NETPOLL_TRAP is not set CONFIG_NET_POLL_CONTROLLER=y - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # @@ -715,6 +651,7 @@ CONFIG_NET_POLL_CONTROLLER=y # CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -740,9 +677,17 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set # CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -814,19 +759,10 @@ CONFIG_SERIAL_SGI_IOC4=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set CONFIG_EFI_RTC=y -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set CONFIG_AGP=m @@ -848,15 +784,8 @@ CONFIG_HPET=y CONFIG_HPET_MMAP=y # CONFIG_HANGCHECK_TIMER is not set CONFIG_MMTIMER=y - -# -# TPM devices -# # CONFIG_TCG_TPM is not set - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set # @@ -864,21 +793,17 @@ CONFIG_MMTIMER=y # # CONFIG_SPI is not set # CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83627HF is not set # CONFIG_HWMON_DEBUG_CHIP is not set # @@ -890,17 +815,20 @@ CONFIG_HWMON=y # Multimedia devices # # CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set +# CONFIG_DVB_CORE is not set +CONFIG_DAB=y # CONFIG_USB_DABUSB is not set # # Graphics support # # CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set # CONFIG_FB is not set # @@ -1014,9 +942,10 @@ CONFIG_SND_FM801=m # USB devices # # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set # -# SoC audio support +# System on Chip audio support # # CONFIG_SND_SOC is not set @@ -1025,16 +954,24 @@ CONFIG_SND_FM801=m # # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=m - -# -# HID Devices -# +CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set # -# USB support +# USB Input Devices # +CONFIG_USB_HID=m +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y @@ -1045,8 +982,10 @@ CONFIG_USB=m # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set +# CONFIG_USB_PERSIST is not set # CONFIG_USB_OTG is not set # @@ -1056,7 +995,6 @@ CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set # CONFIG_USB_EHCI_TT_NEWSCHED is not set -# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=m # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set @@ -1064,6 +1002,7 @@ CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=m # CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set # # USB Device Class drivers @@ -1092,48 +1031,11 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_KARMA is not set # CONFIG_USB_LIBUSUAL is not set -# -# USB Input Devices -# -CONFIG_USB_HID=m -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -# CONFIG_USB_HIDDEV is not set - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_TOUCHSCREEN is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_GTCO is not set - # # USB Imaging devices # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET_MII is not set -# CONFIG_USB_USBNET is not set CONFIG_USB_MON=y # @@ -1177,10 +1079,6 @@ CONFIG_USB_MON=y # USB Gadget Support # # CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# # CONFIG_MMC is not set # @@ -1195,10 +1093,6 @@ CONFIG_USB_MON=y # # LED Triggers # - -# -# InfiniBand support -# CONFIG_INFINIBAND=m # CONFIG_INFINIBAND_USER_MAD is not set # CONFIG_INFINIBAND_USER_ACCESS is not set @@ -1206,6 +1100,7 @@ CONFIG_INFINIBAND_ADDR_TRANS=y CONFIG_INFINIBAND_MTHCA=m CONFIG_INFINIBAND_MTHCA_DEBUG=y # CONFIG_INFINIBAND_AMSO1100 is not set +# CONFIG_MLX4_INFINIBAND is not set CONFIG_INFINIBAND_IPOIB=m # CONFIG_INFINIBAND_IPOIB_CM is not set CONFIG_INFINIBAND_IPOIB_DEBUG=y @@ -1213,10 +1108,6 @@ CONFIG_INFINIBAND_IPOIB_DEBUG=y # CONFIG_INFINIBAND_SRP is not set # CONFIG_INFINIBAND_ISER is not set -# -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - # # Real Time Clock # @@ -1236,12 +1127,9 @@ CONFIG_INFINIBAND_IPOIB_DEBUG=y # # -# Auxiliary Display support -# - -# -# Virtualization +# Userspace I/O # +# CONFIG_UIO is not set # CONFIG_MSPEC is not set # @@ -1357,7 +1245,8 @@ CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SUNRPC_BIND34 is not set +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m CONFIG_SMB_NLS_DEFAULT=y @@ -1371,7 +1260,6 @@ CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types @@ -1393,6 +1281,7 @@ CONFIG_SGI_PARTITION=y # CONFIG_SUN_PARTITION is not set # CONFIG_KARMA_PARTITION is not set CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set # # Native Language Support @@ -1449,11 +1338,14 @@ CONFIG_NLS_UTF8=m CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y @@ -1483,8 +1375,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set -CONFIG_LOG_BUF_SHIFT=20 CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set @@ -1514,10 +1406,6 @@ CONFIG_SYSVIPC_COMPAT=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set - -# -# Cryptographic options -# CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=m @@ -1537,6 +1425,7 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=m CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_BLOWFISH is not set @@ -1554,7 +1443,4 @@ CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set - -# -# Hardware crypto devices -# +CONFIG_CRYPTO_HW=y From 0aa366f351d044703e25c8425e508170e80d83b1 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 20 Jul 2007 11:22:30 -0700 Subject: [PATCH 16/18] [IA64] Convert to generic timekeeping/clocksource This is a merge of Peter Keilty's initial patch (which was revived by Bob Picco) for this with Hidetoshi Seto's fixes and scaling improvements. Acked-by: Bob Picco Signed-off-by: Tony Luck --- Documentation/kernel-parameters.txt | 2 + arch/ia64/Kconfig | 6 +- arch/ia64/configs/bigsur_defconfig | 2 +- arch/ia64/configs/gensparse_defconfig | 2 +- arch/ia64/configs/sim_defconfig | 2 +- arch/ia64/configs/sn2_defconfig | 2 +- arch/ia64/configs/tiger_defconfig | 2 +- arch/ia64/configs/zx1_defconfig | 2 +- arch/ia64/defconfig | 2 +- arch/ia64/kernel/asm-offsets.c | 35 +++-- arch/ia64/kernel/cyclone.c | 46 +++++-- arch/ia64/kernel/fsys.S | 177 +++++++++++++------------- arch/ia64/kernel/fsyscall_gtod_data.h | 23 ++++ arch/ia64/kernel/time.c | 96 ++++++++++++-- arch/ia64/sn/kernel/sn2/timer.c | 29 +++-- drivers/acpi/processor_idle.c | 4 +- drivers/char/hpet.c | 70 +++++----- include/linux/clocksource.h | 6 + 18 files changed, 334 insertions(+), 174 deletions(-) create mode 100644 arch/ia64/kernel/fsyscall_gtod_data.h diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 9a541486fb7e..68115d7b0a7a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1154,6 +1154,8 @@ and is between 256 and 4096 characters. It is defined in the file nointroute [IA-64] + nojitter [IA64] Disables jitter checking for ITC timers. + nolapic [IA-32,APIC] Do not enable or use the local APIC. nolapic_timer [IA-32,APIC] Do not use the local APIC timer. diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 616c96e73483..36c7b9682aa6 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -62,7 +62,11 @@ config GENERIC_CALIBRATE_DELAY bool default y -config TIME_INTERPOLATION +config GENERIC_TIME + bool + default y + +config GENERIC_TIME_VSYSCALL bool default y diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig index 90e9c2e61bf4..9eb48c0927b0 100644 --- a/arch/ia64/configs/bigsur_defconfig +++ b/arch/ia64/configs/bigsur_defconfig @@ -85,7 +85,7 @@ CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_TIME_INTERPOLATION=y +CONFIG_GENERIC_TIME=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index 0d29aa2066b3..3a9ed951db08 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -86,7 +86,7 @@ CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_TIME_INTERPOLATION=y +CONFIG_GENERIC_TIME=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y diff --git a/arch/ia64/configs/sim_defconfig b/arch/ia64/configs/sim_defconfig index d9146c31ea13..c420d9f3df98 100644 --- a/arch/ia64/configs/sim_defconfig +++ b/arch/ia64/configs/sim_defconfig @@ -86,7 +86,7 @@ CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_TIME_INTERPOLATION=y +CONFIG_GENERIC_TIME=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index 64e951de4e57..4c9ffc47bc7a 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -93,7 +93,7 @@ CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_TIME_INTERPOLATION=y +CONFIG_GENERIC_TIME=y CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index a1446931b401..e208747d5de4 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -98,7 +98,7 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_TIME_INTERPOLATION=y +CONFIG_GENERIC_TIME=y CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig index 1c7955c16358..4a060fc39934 100644 --- a/arch/ia64/configs/zx1_defconfig +++ b/arch/ia64/configs/zx1_defconfig @@ -96,7 +96,7 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_TIME_INTERPOLATION=y +CONFIG_GENERIC_TIME=y CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig index 90bd9601cdde..461f8ee738fb 100644 --- a/arch/ia64/defconfig +++ b/arch/ia64/defconfig @@ -98,7 +98,7 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_TIME_INTERPOLATION=y +CONFIG_GENERIC_TIME=y CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 2236fabbb3c6..0aebc6f79e95 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c @@ -7,6 +7,7 @@ #define ASM_OFFSETS_C 1 #include +#include #include #include @@ -15,6 +16,7 @@ #include #include "../kernel/sigframe.h" +#include "../kernel/fsyscall_gtod_data.h" #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -256,17 +258,24 @@ void foo(void) BLANK(); /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */ - DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr)); - DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source)); - DEFINE(IA64_TIME_INTERPOLATOR_SHIFT_OFFSET, offsetof (struct time_interpolator, shift)); - DEFINE(IA64_TIME_INTERPOLATOR_NSEC_OFFSET, offsetof (struct time_interpolator, nsec_per_cyc)); - DEFINE(IA64_TIME_INTERPOLATOR_OFFSET_OFFSET, offsetof (struct time_interpolator, offset)); - DEFINE(IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET, offsetof (struct time_interpolator, last_cycle)); - DEFINE(IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET, offsetof (struct time_interpolator, last_counter)); - DEFINE(IA64_TIME_INTERPOLATOR_JITTER_OFFSET, offsetof (struct time_interpolator, jitter)); - DEFINE(IA64_TIME_INTERPOLATOR_MASK_OFFSET, offsetof (struct time_interpolator, mask)); - DEFINE(IA64_TIME_SOURCE_CPU, TIME_SOURCE_CPU); - DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64); - DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32); - DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec)); + DEFINE(IA64_GTOD_LOCK_OFFSET, + offsetof (struct fsyscall_gtod_data_t, lock)); + DEFINE(IA64_GTOD_WALL_TIME_OFFSET, + offsetof (struct fsyscall_gtod_data_t, wall_time)); + DEFINE(IA64_GTOD_MONO_TIME_OFFSET, + offsetof (struct fsyscall_gtod_data_t, monotonic_time)); + DEFINE(IA64_CLKSRC_MASK_OFFSET, + offsetof (struct fsyscall_gtod_data_t, clk_mask)); + DEFINE(IA64_CLKSRC_MULT_OFFSET, + offsetof (struct fsyscall_gtod_data_t, clk_mult)); + DEFINE(IA64_CLKSRC_SHIFT_OFFSET, + offsetof (struct fsyscall_gtod_data_t, clk_shift)); + DEFINE(IA64_CLKSRC_MMIO_OFFSET, + offsetof (struct fsyscall_gtod_data_t, clk_fsys_mmio)); + DEFINE(IA64_CLKSRC_CYCLE_LAST_OFFSET, + offsetof (struct fsyscall_gtod_data_t, clk_cycle_last)); + DEFINE(IA64_ITC_JITTER_OFFSET, + offsetof (struct itc_jitter_data_t, itc_jitter)); + DEFINE(IA64_ITC_LASTCYCLE_OFFSET, + offsetof (struct itc_jitter_data_t, itc_lastcycle)); } diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c index e00b21514f7c..2fd96d9062a1 100644 --- a/arch/ia64/kernel/cyclone.c +++ b/arch/ia64/kernel/cyclone.c @@ -3,6 +3,7 @@ #include #include #include +#include #include /* IBM Summit (EXA) Cyclone counter code*/ @@ -18,13 +19,21 @@ void __init cyclone_setup(void) use_cyclone = 1; } +static void __iomem *cyclone_mc; -struct time_interpolator cyclone_interpolator = { - .source = TIME_SOURCE_MMIO64, - .shift = 16, - .frequency = CYCLONE_TIMER_FREQ, - .drift = -100, - .mask = (1LL << 40) - 1 +static cycle_t read_cyclone(void) +{ + return (cycle_t)readq((void __iomem *)cyclone_mc); +} + +static struct clocksource clocksource_cyclone = { + .name = "cyclone", + .rating = 300, + .read = read_cyclone, + .mask = (1LL << 40) - 1, + .mult = 0, /*to be caluclated*/ + .shift = 16, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; int __init init_cyclone_clock(void) @@ -44,13 +53,15 @@ int __init init_cyclone_clock(void) offset = (CYCLONE_CBAR_ADDR); reg = (u64*)ioremap_nocache(offset, sizeof(u64)); if(!reg){ - printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n"); + printk(KERN_ERR "Summit chipset: Could not find valid CBAR" + " register.\n"); use_cyclone = 0; return -ENODEV; } base = readq(reg); if(!base){ - printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n"); + printk(KERN_ERR "Summit chipset: Could not find valid CBAR" + " value.\n"); use_cyclone = 0; return -ENODEV; } @@ -60,7 +71,8 @@ int __init init_cyclone_clock(void) offset = (base + CYCLONE_PMCC_OFFSET); reg = (u64*)ioremap_nocache(offset, sizeof(u64)); if(!reg){ - printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n"); + printk(KERN_ERR "Summit chipset: Could not find valid PMCC" + " register.\n"); use_cyclone = 0; return -ENODEV; } @@ -71,7 +83,8 @@ int __init init_cyclone_clock(void) offset = (base + CYCLONE_MPCS_OFFSET); reg = (u64*)ioremap_nocache(offset, sizeof(u64)); if(!reg){ - printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n"); + printk(KERN_ERR "Summit chipset: Could not find valid MPCS" + " register.\n"); use_cyclone = 0; return -ENODEV; } @@ -82,7 +95,8 @@ int __init init_cyclone_clock(void) offset = (base + CYCLONE_MPMC_OFFSET); cyclone_timer = (u32*)ioremap_nocache(offset, sizeof(u32)); if(!cyclone_timer){ - printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n"); + printk(KERN_ERR "Summit chipset: Could not find valid MPMC" + " register.\n"); use_cyclone = 0; return -ENODEV; } @@ -93,7 +107,8 @@ int __init init_cyclone_clock(void) int stall = 100; while(stall--) barrier(); if(readl(cyclone_timer) == old){ - printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n"); + printk(KERN_ERR "Summit chipset: Counter not counting!" + " DISABLED\n"); iounmap(cyclone_timer); cyclone_timer = 0; use_cyclone = 0; @@ -101,8 +116,11 @@ int __init init_cyclone_clock(void) } } /* initialize last tick */ - cyclone_interpolator.addr = cyclone_timer; - register_time_interpolator(&cyclone_interpolator); + cyclone_mc = cyclone_timer; + clocksource_cyclone.fsys_mmio = cyclone_timer; + clocksource_cyclone.mult = clocksource_hz2mult(CYCLONE_TIMER_FREQ, + clocksource_cyclone.shift); + clocksource_register(&clocksource_cyclone); return 0; } diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 3f926c2dc708..44841971f077 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -147,12 +147,11 @@ ENTRY(fsys_set_tid_address) FSYS_RETURN END(fsys_set_tid_address) -/* - * Ensure that the time interpolator structure is compatible with the asm code - */ -#if IA64_TIME_INTERPOLATOR_SOURCE_OFFSET !=0 || IA64_TIME_INTERPOLATOR_SHIFT_OFFSET != 2 \ - || IA64_TIME_INTERPOLATOR_JITTER_OFFSET != 3 || IA64_TIME_INTERPOLATOR_NSEC_OFFSET != 4 -#error fsys_gettimeofday incompatible with changes to struct time_interpolator +#if IA64_GTOD_LOCK_OFFSET !=0 +#error fsys_gettimeofday incompatible with changes to struct fsyscall_gtod_data_t +#endif +#if IA64_ITC_JITTER_OFFSET !=0 +#error fsys_gettimeofday incompatible with changes to struct itc_jitter_data_t #endif #define CLOCK_REALTIME 0 #define CLOCK_MONOTONIC 1 @@ -179,126 +178,124 @@ ENTRY(fsys_gettimeofday) // r11 = preserved: saved ar.pfs // r12 = preserved: memory stack // r13 = preserved: thread pointer - // r14 = address of mask / mask + // r14 = address of mask / mask value // r15 = preserved: system call number // r16 = preserved: current task pointer - // r17 = wall to monotonic use - // r18 = time_interpolator->offset - // r19 = address of wall_to_monotonic - // r20 = pointer to struct time_interpolator / pointer to time_interpolator->address - // r21 = shift factor - // r22 = address of time interpolator->last_counter - // r23 = address of time_interpolator->last_cycle - // r24 = adress of time_interpolator->offset - // r25 = last_cycle value - // r26 = last_counter value - // r27 = pointer to xtime + // r17 = (not used) + // r18 = (not used) + // r19 = address of itc_lastcycle + // r20 = struct fsyscall_gtod_data (= address of gtod_lock.sequence) + // r21 = address of mmio_ptr + // r22 = address of wall_time or monotonic_time + // r23 = address of shift / value + // r24 = address mult factor / cycle_last value + // r25 = itc_lastcycle value + // r26 = address clocksource cycle_last + // r27 = (not used) // r28 = sequence number at the beginning of critcal section - // r29 = address of seqlock + // r29 = address of itc_jitter // r30 = time processing flags / memory address // r31 = pointer to result // Predicates // p6,p7 short term use // p8 = timesource ar.itc // p9 = timesource mmio64 - // p10 = timesource mmio32 + // p10 = timesource mmio32 - not used // p11 = timesource not to be handled by asm code - // p12 = memory time source ( = p9 | p10) - // p13 = do cmpxchg with time_interpolator_last_cycle + // p12 = memory time source ( = p9 | p10) - not used + // p13 = do cmpxchg with itc_lastcycle // p14 = Divide by 1000 // p15 = Add monotonic // - // Note that instructions are optimized for McKinley. McKinley can process two - // bundles simultaneously and therefore we continuously try to feed the CPU - // two bundles and then a stop. - tnat.nz p6,p0 = r31 // branch deferred since it does not fit into bundle structure + // Note that instructions are optimized for McKinley. McKinley can + // process two bundles simultaneously and therefore we continuously + // try to feed the CPU two bundles and then a stop. + // + // Additional note that code has changed a lot. Optimization is TBD. + // Comments begin with "?" are maybe outdated. + tnat.nz p6,p0 = r31 // ? branch deferred to fit later bundle mov pr = r30,0xc000 // Set predicates according to function add r2 = TI_FLAGS+IA64_TASK_SIZE,r16 - movl r20 = time_interpolator + movl r20 = fsyscall_gtod_data // load fsyscall gettimeofday data address ;; - ld8 r20 = [r20] // get pointer to time_interpolator structure - movl r29 = xtime_lock + movl r29 = itc_jitter_data // itc_jitter + add r22 = IA64_GTOD_WALL_TIME_OFFSET,r20 // wall_time ld4 r2 = [r2] // process work pending flags - movl r27 = xtime - ;; // only one bundle here - ld8 r21 = [r20] // first quad with control information - and r2 = TIF_ALLWORK_MASK,r2 -(p6) br.cond.spnt.few .fail_einval // deferred branch ;; - add r10 = IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET,r20 - extr r3 = r21,32,32 // time_interpolator->nsec_per_cyc - extr r8 = r21,0,16 // time_interpolator->source +(p15) add r22 = IA64_GTOD_MONO_TIME_OFFSET,r20 // monotonic_time + add r21 = IA64_CLKSRC_MMIO_OFFSET,r20 + add r19 = IA64_ITC_LASTCYCLE_OFFSET,r29 + and r2 = TIF_ALLWORK_MASK,r2 +(p6) br.cond.spnt.few .fail_einval // ? deferred branch + ;; + add r26 = IA64_CLKSRC_CYCLE_LAST_OFFSET,r20 // clksrc_cycle_last cmp.ne p6, p0 = 0, r2 // Fallback if work is scheduled (p6) br.cond.spnt.many fsys_fallback_syscall ;; - cmp.eq p8,p12 = 0,r8 // Check for cpu timer - cmp.eq p9,p0 = 1,r8 // MMIO64 ? - extr r2 = r21,24,8 // time_interpolator->jitter - cmp.eq p10,p0 = 2,r8 // MMIO32 ? - cmp.ltu p11,p0 = 2,r8 // function or other clock -(p11) br.cond.spnt.many fsys_fallback_syscall - ;; - setf.sig f7 = r3 // Setup for scaling of counter -(p15) movl r19 = wall_to_monotonic -(p12) ld8 r30 = [r10] - cmp.ne p13,p0 = r2,r0 // need jitter compensation? - extr r21 = r21,16,8 // shift factor - ;; + // Begin critical section .time_redo: - .pred.rel.mutex p8,p9,p10 - ld4.acq r28 = [r29] // xtime_lock.sequence. Must come first for locking purposes + ld4.acq r28 = [r20] // gtod_lock.sequence, Must take first ;; - and r28 = ~1,r28 // Make sequence even to force retry if odd + and r28 = ~1,r28 // And make sequence even to force retry if odd ;; + ld8 r30 = [r21] // clocksource->mmio_ptr + add r24 = IA64_CLKSRC_MULT_OFFSET,r20 + ld4 r2 = [r29] // itc_jitter value + add r23 = IA64_CLKSRC_SHIFT_OFFSET,r20 + add r14 = IA64_CLKSRC_MASK_OFFSET,r20 + ;; + ld4 r3 = [r24] // clocksource mult value + ld8 r14 = [r14] // clocksource mask value + cmp.eq p8,p9 = 0,r30 // use cpu timer if no mmio_ptr + ;; + setf.sig f7 = r3 // Setup for mult scaling of counter +(p8) cmp.ne p13,p0 = r2,r0 // need itc_jitter compensation, set p13 + ld4 r23 = [r23] // clocksource shift value + ld8 r24 = [r26] // get clksrc_cycle_last value +(p9) cmp.eq p13,p0 = 0,r30 // if mmio_ptr, clear p13 jitter control + ;; + .pred.rel.mutex p8,p9 (p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!! - add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20 -(p9) ld8 r2 = [r30] // readq(ti->address). Could also have latency issues.. -(p10) ld4 r2 = [r30] // readw(ti->address) -(p13) add r23 = IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET,r20 - ;; // could be removed by moving the last add upward - ld8 r26 = [r22] // time_interpolator->last_counter -(p13) ld8 r25 = [r23] // time interpolator->last_cycle - add r24 = IA64_TIME_INTERPOLATOR_OFFSET_OFFSET,r20 -(p15) ld8 r17 = [r19],IA64_TIMESPEC_TV_NSEC_OFFSET - ld8 r9 = [r27],IA64_TIMESPEC_TV_NSEC_OFFSET - add r14 = IA64_TIME_INTERPOLATOR_MASK_OFFSET, r20 +(p9) ld8 r2 = [r30] // MMIO_TIMER. Could also have latency issues.. +(p13) ld8 r25 = [r19] // get itc_lastcycle value + ;; // ? could be removed by moving the last add upward + ld8 r9 = [r22],IA64_TIMESPEC_TV_NSEC_OFFSET // tv_sec ;; - ld8 r18 = [r24] // time_interpolator->offset - ld8 r8 = [r27],-IA64_TIMESPEC_TV_NSEC_OFFSET // xtime.tv_nsec -(p13) sub r3 = r25,r2 // Diff needed before comparison (thanks davidm) + ld8 r8 = [r22],-IA64_TIMESPEC_TV_NSEC_OFFSET // tv_nsec +(p13) sub r3 = r25,r2 // Diff needed before comparison (thanks davidm) ;; - ld8 r14 = [r14] // time_interpolator->mask -(p13) cmp.gt.unc p6,p7 = r3,r0 // check if it is less than last. p6,p7 cleared - sub r10 = r2,r26 // current_counter - last_counter +(p13) cmp.gt.unc p6,p7 = r3,r0 // check if it is less than last. p6,p7 cleared + sub r10 = r2,r24 // current_cycle - last_cycle ;; -(p6) sub r10 = r25,r26 // time we got was less than last_cycle +(p6) sub r10 = r25,r24 // time we got was less than last_cycle (p7) mov ar.ccv = r25 // more than last_cycle. Prep for cmpxchg ;; +(p7) cmpxchg8.rel r3 = [r19],r2,ar.ccv + ;; +(p7) cmp.ne p7,p0 = r25,r3 // if cmpxchg not successful + ;; +(p7) sub r10 = r3,r24 // then use new last_cycle instead + ;; and r10 = r10,r14 // Apply mask ;; setf.sig f8 = r10 nop.i 123 ;; -(p7) cmpxchg8.rel r3 = [r23],r2,ar.ccv -EX(.fail_efault, probe.w.fault r31, 3) // This takes 5 cycles and we have spare time + // fault check takes 5 cycles and we have spare time +EX(.fail_efault, probe.w.fault r31, 3) xmpy.l f8 = f8,f7 // nsec_per_cyc*(counter-last_counter) -(p15) add r9 = r9,r17 // Add wall to monotonic.secs to result secs ;; -(p15) ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET -(p7) cmp.ne p7,p0 = r25,r3 // if cmpxchg not successful redo - // simulate tbit.nz.or p7,p0 = r28,0 + // ? simulate tbit.nz.or p7,p0 = r28,0 getf.sig r2 = f8 mf - add r8 = r8,r18 // Add time interpolator offset ;; - ld4 r10 = [r29] // xtime_lock.sequence -(p15) add r8 = r8, r17 // Add monotonic.nsecs to nsecs - shr.u r2 = r2,r21 - ;; // overloaded 3 bundles! - // End critical section. + ld4 r10 = [r20] // gtod_lock.sequence + shr.u r2 = r2,r23 // shift by factor + ;; // ? overloaded 3 bundles! add r8 = r8,r2 // Add xtime.nsecs - cmp4.ne.or p7,p0 = r28,r10 -(p7) br.cond.dpnt.few .time_redo // sequence number changed ? + cmp4.ne p7,p0 = r28,r10 +(p7) br.cond.dpnt.few .time_redo // sequence number changed, redo + // End critical section. // Now r8=tv->tv_nsec and r9=tv->tv_sec mov r10 = r0 movl r2 = 1000000000 @@ -308,19 +305,19 @@ EX(.fail_efault, probe.w.fault r31, 3) // This takes 5 cycles and we have spare .time_normalize: mov r21 = r8 cmp.ge p6,p0 = r8,r2 -(p14) shr.u r20 = r8, 3 // We can repeat this if necessary just wasting some time +(p14) shr.u r20 = r8, 3 // We can repeat this if necessary just wasting time ;; (p14) setf.sig f8 = r20 (p6) sub r8 = r8,r2 -(p6) add r9 = 1,r9 // two nops before the branch. -(p14) setf.sig f7 = r3 // Chances for repeats are 1 in 10000 for gettod +(p6) add r9 = 1,r9 // two nops before the branch. +(p14) setf.sig f7 = r3 // Chances for repeats are 1 in 10000 for gettod (p6) br.cond.dpnt.few .time_normalize ;; // Divided by 8 though shift. Now divide by 125 // The compiler was able to do that with a multiply // and a shift and we do the same -EX(.fail_efault, probe.w.fault r23, 3) // This also costs 5 cycles -(p14) xmpy.hu f8 = f8, f7 // xmpy has 5 cycles latency so use it... +EX(.fail_efault, probe.w.fault r23, 3) // This also costs 5 cycles +(p14) xmpy.hu f8 = f8, f7 // xmpy has 5 cycles latency so use it ;; mov r8 = r0 (p14) getf.sig r2 = f8 diff --git a/arch/ia64/kernel/fsyscall_gtod_data.h b/arch/ia64/kernel/fsyscall_gtod_data.h new file mode 100644 index 000000000000..490dab55fba3 --- /dev/null +++ b/arch/ia64/kernel/fsyscall_gtod_data.h @@ -0,0 +1,23 @@ +/* + * (c) Copyright 2007 Hewlett-Packard Development Company, L.P. + * Contributed by Peter Keilty + * + * fsyscall gettimeofday data + */ + +struct fsyscall_gtod_data_t { + seqlock_t lock; + struct timespec wall_time; + struct timespec monotonic_time; + cycle_t clk_mask; + u32 clk_mult; + u32 clk_shift; + void *clk_fsys_mmio; + cycle_t clk_cycle_last; +} __attribute__ ((aligned (L1_CACHE_BYTES))); + +struct itc_jitter_data_t { + int itc_jitter; + cycle_t itc_lastcycle; +} __attribute__ ((aligned (L1_CACHE_BYTES))); + diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 3486fe7d6e65..627785c48ea9 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,16 @@ #include #include +#include "fsyscall_gtod_data.h" + +static cycle_t itc_get_cycles(void); + +struct fsyscall_gtod_data_t fsyscall_gtod_data = { + .lock = SEQLOCK_UNLOCKED, +}; + +struct itc_jitter_data_t itc_jitter_data; + volatile int time_keeper_id = 0; /* smp_processor_id() of time-keeper */ #ifdef CONFIG_IA64_DEBUG_IRQ @@ -37,11 +48,16 @@ EXPORT_SYMBOL(last_cli_ip); #endif -static struct time_interpolator itc_interpolator = { - .shift = 16, - .mask = 0xffffffffffffffffLL, - .source = TIME_SOURCE_CPU +static struct clocksource clocksource_itc = { + .name = "itc", + .rating = 350, + .read = itc_get_cycles, + .mask = 0xffffffffffffffff, + .mult = 0, /*to be caluclated*/ + .shift = 16, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static struct clocksource *itc_clocksource; static irqreturn_t timer_interrupt (int irq, void *dev_id) @@ -210,8 +226,6 @@ ia64_init_itm (void) + itc_freq/2)/itc_freq; if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { - itc_interpolator.frequency = local_cpu_data->itc_freq; - itc_interpolator.drift = itc_drift; #ifdef CONFIG_SMP /* On IA64 in an SMP configuration ITCs are never accurately synchronized. * Jitter compensation requires a cmpxchg which may limit @@ -223,15 +237,50 @@ ia64_init_itm (void) * even going backward) if the ITC offsets between the individual CPUs * are too large. */ - if (!nojitter) itc_interpolator.jitter = 1; + if (!nojitter) + itc_jitter_data.itc_jitter = 1; #endif - register_time_interpolator(&itc_interpolator); } /* Setup the CPU local timer tick */ ia64_cpu_local_tick(); + + if (!itc_clocksource) { + /* Sort out mult/shift values: */ + clocksource_itc.mult = + clocksource_hz2mult(local_cpu_data->itc_freq, + clocksource_itc.shift); + clocksource_register(&clocksource_itc); + itc_clocksource = &clocksource_itc; + } } +static cycle_t itc_get_cycles() +{ + u64 lcycle, now, ret; + + if (!itc_jitter_data.itc_jitter) + return get_cycles(); + + lcycle = itc_jitter_data.itc_lastcycle; + now = get_cycles(); + if (lcycle && time_after(lcycle, now)) + return lcycle; + + /* + * Keep track of the last timer value returned. + * In an SMP environment, you could lose out in contention of + * cmpxchg. If so, your cmpxchg returns new value which the + * winner of contention updated to. Use the new value instead. + */ + ret = cmpxchg(&itc_jitter_data.itc_lastcycle, lcycle, now); + if (unlikely(ret != lcycle)) + return ret; + + return now; +} + + static struct irqaction timer_irqaction = { .handler = timer_interrupt, .flags = IRQF_DISABLED | IRQF_IRQPOLL, @@ -307,3 +356,34 @@ ia64_setup_printk_clock(void) if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) ia64_printk_clock = ia64_itc_printk_clock; } + +void update_vsyscall(struct timespec *wall, struct clocksource *c) +{ + unsigned long flags; + + write_seqlock_irqsave(&fsyscall_gtod_data.lock, flags); + + /* copy fsyscall clock data */ + fsyscall_gtod_data.clk_mask = c->mask; + fsyscall_gtod_data.clk_mult = c->mult; + fsyscall_gtod_data.clk_shift = c->shift; + fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio; + fsyscall_gtod_data.clk_cycle_last = c->cycle_last; + + /* copy kernel time structures */ + fsyscall_gtod_data.wall_time.tv_sec = wall->tv_sec; + fsyscall_gtod_data.wall_time.tv_nsec = wall->tv_nsec; + fsyscall_gtod_data.monotonic_time.tv_sec = wall_to_monotonic.tv_sec + + wall->tv_sec; + fsyscall_gtod_data.monotonic_time.tv_nsec = wall_to_monotonic.tv_nsec + + wall->tv_nsec; + + /* normalize */ + while (fsyscall_gtod_data.monotonic_time.tv_nsec >= NSEC_PER_SEC) { + fsyscall_gtod_data.monotonic_time.tv_nsec -= NSEC_PER_SEC; + fsyscall_gtod_data.monotonic_time.tv_sec++; + } + + write_sequnlock_irqrestore(&fsyscall_gtod_data.lock, flags); +} + diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c index 56a88b6df4b4..19e25d2b64fc 100644 --- a/arch/ia64/sn/kernel/sn2/timer.c +++ b/arch/ia64/sn/kernel/sn2/timer.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -22,11 +23,21 @@ extern unsigned long sn_rtc_cycles_per_second; -static struct time_interpolator sn2_interpolator = { - .drift = -1, - .shift = 10, - .mask = (1LL << 55) - 1, - .source = TIME_SOURCE_MMIO64 +static void __iomem *sn2_mc; + +static cycle_t read_sn2(void) +{ + return (cycle_t)readq(sn2_mc); +} + +static struct clocksource clocksource_sn2 = { + .name = "sn2_rtc", + .rating = 300, + .read = read_sn2, + .mask = (1LL << 55) - 1, + .mult = 0, + .shift = 10, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; /* @@ -47,9 +58,11 @@ ia64_sn_udelay (unsigned long usecs) void __init sn_timer_init(void) { - sn2_interpolator.frequency = sn_rtc_cycles_per_second; - sn2_interpolator.addr = RTC_COUNTER_ADDR; - register_time_interpolator(&sn2_interpolator); + sn2_mc = RTC_COUNTER_ADDR; + clocksource_sn2.fsys_mmio = RTC_COUNTER_ADDR; + clocksource_sn2.mult = clocksource_hz2mult(sn_rtc_cycles_per_second, + clocksource_sn2.shift); + clocksource_register(&clocksource_sn2); ia64_udelay = &ia64_sn_udelay; } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 80ffc7829916..bb5d23be4260 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -475,7 +475,7 @@ static void acpi_processor_idle(void) /* Get end time (ticks) */ t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); -#ifdef CONFIG_GENERIC_TIME +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) /* TSC halts in C2, so notify users */ mark_tsc_unstable("possible TSC halt in C2"); #endif @@ -517,7 +517,7 @@ static void acpi_processor_idle(void) acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); } -#ifdef CONFIG_GENERIC_TIME +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) /* TSC halts in C3, so notify users */ mark_tsc_unstable("TSC halts in C3"); #endif diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 0be700f4e8fd..ba0e74ad74bb 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -51,8 +52,34 @@ #define HPET_RANGE_SIZE 1024 /* from HPET spec */ +#if BITS_PER_LONG == 64 +#define write_counter(V, MC) writeq(V, MC) +#define read_counter(MC) readq(MC) +#else +#define write_counter(V, MC) writel(V, MC) +#define read_counter(MC) readl(MC) +#endif + static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; +static void __iomem *hpet_mctr; + +static cycle_t read_hpet(void) +{ + return (cycle_t)read_counter((void __iomem *)hpet_mctr); +} + +static struct clocksource clocksource_hpet = { + .name = "hpet", + .rating = 250, + .read = read_hpet, + .mask = 0xffffffffffffffff, + .mult = 0, /*to be caluclated*/ + .shift = 10, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; +static struct clocksource *hpet_clocksource; + /* A lock for concurrent access by app and isr hpet activity. */ static DEFINE_SPINLOCK(hpet_lock); /* A lock for concurrent intermodule access to hpet and isr hpet activity. */ @@ -79,7 +106,7 @@ struct hpets { struct hpets *hp_next; struct hpet __iomem *hp_hpet; unsigned long hp_hpet_phys; - struct time_interpolator *hp_interpolator; + struct clocksource *hp_clocksource; unsigned long long hp_tick_freq; unsigned long hp_delta; unsigned int hp_ntimer; @@ -94,13 +121,6 @@ static struct hpets *hpets; #define HPET_PERIODIC 0x0004 #define HPET_SHARED_IRQ 0x0008 -#if BITS_PER_LONG == 64 -#define write_counter(V, MC) writeq(V, MC) -#define read_counter(MC) readq(MC) -#else -#define write_counter(V, MC) writel(V, MC) -#define read_counter(MC) readl(MC) -#endif #ifndef readq static inline unsigned long long readq(void __iomem *addr) @@ -737,27 +757,6 @@ static ctl_table dev_root[] = { static struct ctl_table_header *sysctl_header; -static void hpet_register_interpolator(struct hpets *hpetp) -{ -#ifdef CONFIG_TIME_INTERPOLATION - struct time_interpolator *ti; - - ti = kzalloc(sizeof(*ti), GFP_KERNEL); - if (!ti) - return; - - ti->source = TIME_SOURCE_MMIO64; - ti->shift = 10; - ti->addr = &hpetp->hp_hpet->hpet_mc; - ti->frequency = hpetp->hp_tick_freq; - ti->drift = HPET_DRIFT; - ti->mask = -1; - - hpetp->hp_interpolator = ti; - register_time_interpolator(ti); -#endif -} - /* * Adjustment for when arming the timer with * initial conditions. That is, main counter @@ -909,7 +908,16 @@ int hpet_alloc(struct hpet_data *hdp) } hpetp->hp_delta = hpet_calibrate(hpetp); - hpet_register_interpolator(hpetp); + + if (!hpet_clocksource) { + hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc; + CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr); + clocksource_hpet.mult = clocksource_hz2mult(hpetp->hp_tick_freq, + clocksource_hpet.shift); + clocksource_register(&clocksource_hpet); + hpetp->hp_clocksource = &clocksource_hpet; + hpet_clocksource = &clocksource_hpet; + } return 0; } @@ -995,7 +1003,7 @@ static int hpet_acpi_add(struct acpi_device *device) static int hpet_acpi_remove(struct acpi_device *device, int type) { - /* XXX need to unregister interpolator, dealloc mem, etc */ + /* XXX need to unregister clocksource, dealloc mem, etc */ return -EINVAL; } diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index bf297b03a4e4..16ea3374dddf 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -67,6 +67,12 @@ struct clocksource { unsigned long flags; cycle_t (*vread)(void); void (*resume)(void); +#ifdef CONFIG_IA64 + void *fsys_mmio; /* used by fsyscall asm code */ +#define CLKSRC_FSYS_MMIO_SET(mmio, addr) ((mmio) = (addr)) +#else +#define CLKSRC_FSYS_MMIO_SET(mmio, addr) do { } while (0) +#endif /* timekeeping specific data, ignore */ cycle_t cycle_interval; From 1f564ad6d4182859612cbae452122e5eb2d62a76 Mon Sep 17 00:00:00 2001 From: Bob Picco Date: Wed, 18 Jul 2007 15:51:28 -0700 Subject: [PATCH 17/18] [IA64] remove time interpolator Remove time_interpolator code (This is generic code, but only user was ia64. It has been superseded by the CONFIG_GENERIC_TIME code). Signed-off-by: Bob Picco Signed-off-by: John Stultz Signed-off-by: Peter Keilty Signed-off-by: Tony Luck --- Documentation/time_interpolators.txt | 41 ------ include/linux/timex.h | 60 --------- kernel/time.c | 88 ------------- kernel/time/ntp.c | 10 -- kernel/time/timekeeping.c | 4 - kernel/timer.c | 188 --------------------------- 6 files changed, 391 deletions(-) delete mode 100644 Documentation/time_interpolators.txt diff --git a/Documentation/time_interpolators.txt b/Documentation/time_interpolators.txt deleted file mode 100644 index e3b60854fbc2..000000000000 --- a/Documentation/time_interpolators.txt +++ /dev/null @@ -1,41 +0,0 @@ -Time Interpolators ------------------- - -Time interpolators are a base of time calculation between timer ticks and -allow an accurate determination of time down to the accuracy of the time -source in nanoseconds. - -The architecture specific code typically provides gettimeofday and -settimeofday under Linux. The time interpolator provides both if an arch -defines CONFIG_TIME_INTERPOLATION. The arch still must set up timer tick -operations and call the necessary functions to advance the clock. - -With the time interpolator a standardized interface exists for time -interpolation between ticks. The provided logic is highly scalable -and has been tested in SMP situations of up to 512 CPUs. - -If CONFIG_TIME_INTERPOLATION is defined then the architecture specific code -(or the device drivers - like HPET) may register time interpolators. -These are typically defined in the following way: - -static struct time_interpolator my_interpolator { - .frequency = MY_FREQUENCY, - .source = TIME_SOURCE_MMIO32, - .shift = 8, /* scaling for higher accuracy */ - .drift = -1, /* Unknown drift */ - .jitter = 0 /* time source is stable */ -}; - -void time_init(void) -{ - .... - /* Initialization of the timer *. - my_interpolator.address = &my_timer; - register_time_interpolator(&my_interpolator); - .... -} - -For more details see include/linux/timex.h and kernel/timer.c. - -Christoph Lameter , October 31, 2004 - diff --git a/include/linux/timex.h b/include/linux/timex.h index da929dbbea2a..37ac3ff90faf 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -224,66 +224,6 @@ static inline int ntp_synced(void) __x < 0 ? -(-__x >> __s) : __x >> __s; \ }) - -#ifdef CONFIG_TIME_INTERPOLATION - -#define TIME_SOURCE_CPU 0 -#define TIME_SOURCE_MMIO64 1 -#define TIME_SOURCE_MMIO32 2 -#define TIME_SOURCE_FUNCTION 3 - -/* For proper operations time_interpolator clocks must run slightly slower - * than the standard clock since the interpolator may only correct by having - * time jump forward during a tick. A slower clock is usually a side effect - * of the integer divide of the nanoseconds in a second by the frequency. - * The accuracy of the division can be increased by specifying a shift. - * However, this may cause the clock not to be slow enough. - * The interpolator will self-tune the clock by slowing down if no - * resets occur or speeding up if the time jumps per analysis cycle - * become too high. - * - * Setting jitter compensates for a fluctuating timesource by comparing - * to the last value read from the timesource to insure that an earlier value - * is not returned by a later call. The price to pay - * for the compensation is that the timer routines are not as scalable anymore. - */ - -struct time_interpolator { - u16 source; /* time source flags */ - u8 shift; /* increases accuracy of multiply by shifting. */ - /* Note that bits may be lost if shift is set too high */ - u8 jitter; /* if set compensate for fluctuations */ - u32 nsec_per_cyc; /* set by register_time_interpolator() */ - void *addr; /* address of counter or function */ - cycles_t mask; /* mask the valid bits of the counter */ - unsigned long offset; /* nsec offset at last update of interpolator */ - u64 last_counter; /* counter value in units of the counter at last update */ - cycles_t last_cycle; /* Last timer value if TIME_SOURCE_JITTER is set */ - u64 frequency; /* frequency in counts/second */ - long drift; /* drift in parts-per-million (or -1) */ - unsigned long skips; /* skips forward */ - unsigned long ns_skipped; /* nanoseconds skipped */ - struct time_interpolator *next; -}; - -extern void register_time_interpolator(struct time_interpolator *); -extern void unregister_time_interpolator(struct time_interpolator *); -extern void time_interpolator_reset(void); -extern unsigned long time_interpolator_get_offset(void); -extern void time_interpolator_update(long delta_nsec); - -#else /* !CONFIG_TIME_INTERPOLATION */ - -static inline void time_interpolator_reset(void) -{ -} - -static inline void time_interpolator_update(long delta_nsec) -{ -} - -#endif /* !CONFIG_TIME_INTERPOLATION */ - #define TICK_LENGTH_SHIFT 32 #ifdef CONFIG_NO_HZ diff --git a/kernel/time.c b/kernel/time.c index ffe19149d770..e325597f5bf5 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -136,7 +136,6 @@ static inline void warp_clock(void) write_seqlock_irq(&xtime_lock); wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60; xtime.tv_sec += sys_tz.tz_minuteswest * 60; - time_interpolator_reset(); write_sequnlock_irq(&xtime_lock); clock_was_set(); } @@ -309,92 +308,6 @@ struct timespec timespec_trunc(struct timespec t, unsigned gran) } EXPORT_SYMBOL(timespec_trunc); -#ifdef CONFIG_TIME_INTERPOLATION -void getnstimeofday (struct timespec *tv) -{ - unsigned long seq,sec,nsec; - - do { - seq = read_seqbegin(&xtime_lock); - sec = xtime.tv_sec; - nsec = xtime.tv_nsec+time_interpolator_get_offset(); - } while (unlikely(read_seqretry(&xtime_lock, seq))); - - while (unlikely(nsec >= NSEC_PER_SEC)) { - nsec -= NSEC_PER_SEC; - ++sec; - } - tv->tv_sec = sec; - tv->tv_nsec = nsec; -} -EXPORT_SYMBOL_GPL(getnstimeofday); - -int do_settimeofday (struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - { - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - time_interpolator_reset(); - } - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} -EXPORT_SYMBOL(do_settimeofday); - -void do_gettimeofday (struct timeval *tv) -{ - unsigned long seq, nsec, usec, sec, offset; - do { - seq = read_seqbegin(&xtime_lock); - offset = time_interpolator_get_offset(); - sec = xtime.tv_sec; - nsec = xtime.tv_nsec; - } while (unlikely(read_seqretry(&xtime_lock, seq))); - - usec = (nsec + offset) / 1000; - - while (unlikely(usec >= USEC_PER_SEC)) { - usec -= USEC_PER_SEC; - ++sec; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; - - /* - * Make sure xtime.tv_sec [returned by sys_time()] always - * follows the gettimeofday() result precisely. This - * condition is extremely unlikely, it can hit at most - * once per second: - */ - if (unlikely(xtime.tv_sec != tv->tv_sec)) { - unsigned long flags; - - write_seqlock_irqsave(&xtime_lock, flags); - update_wall_time(); - write_sequnlock_irqrestore(&xtime_lock, flags); - } -} -EXPORT_SYMBOL(do_gettimeofday); - -#else /* CONFIG_TIME_INTERPOLATION */ - #ifndef CONFIG_GENERIC_TIME /* * Simulate gettimeofday using do_gettimeofday which only allows a timeval @@ -410,7 +323,6 @@ void getnstimeofday(struct timespec *tv) } EXPORT_SYMBOL_GPL(getnstimeofday); #endif -#endif /* CONFIG_TIME_INTERPOLATION */ /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 438c6b723ee2..b5e352597cbb 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -116,11 +116,6 @@ void second_overflow(void) if (xtime.tv_sec % 86400 == 0) { xtime.tv_sec--; wall_to_monotonic.tv_sec++; - /* - * The timer interpolator will make time change - * gradually instead of an immediate jump by one second - */ - time_interpolator_update(-NSEC_PER_SEC); time_state = TIME_OOP; printk(KERN_NOTICE "Clock: inserting leap second " "23:59:60 UTC\n"); @@ -130,11 +125,6 @@ void second_overflow(void) if ((xtime.tv_sec + 1) % 86400 == 0) { xtime.tv_sec++; wall_to_monotonic.tv_sec--; - /* - * Use of time interpolator for a gradual change of - * time - */ - time_interpolator_update(NSEC_PER_SEC); time_state = TIME_WAIT; printk(KERN_NOTICE "Clock: deleting leap second " "23:59:59 UTC\n"); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 728cedfd3cbd..027d46c906e0 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -466,10 +466,6 @@ void update_wall_time(void) second_overflow(); } - /* interpolator bits */ - time_interpolator_update(clock->xtime_interval - >> clock->shift); - /* accumulate error between NTP and clock interval */ clock->error += current_tick_length(); clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift); diff --git a/kernel/timer.c b/kernel/timer.c index b7792fb03387..dbc03ab14eed 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1349,194 +1349,6 @@ void __init init_timers(void) open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL); } -#ifdef CONFIG_TIME_INTERPOLATION - -struct time_interpolator *time_interpolator __read_mostly; -static struct time_interpolator *time_interpolator_list __read_mostly; -static DEFINE_SPINLOCK(time_interpolator_lock); - -static inline cycles_t time_interpolator_get_cycles(unsigned int src) -{ - unsigned long (*x)(void); - - switch (src) - { - case TIME_SOURCE_FUNCTION: - x = time_interpolator->addr; - return x(); - - case TIME_SOURCE_MMIO64 : - return readq_relaxed((void __iomem *)time_interpolator->addr); - - case TIME_SOURCE_MMIO32 : - return readl_relaxed((void __iomem *)time_interpolator->addr); - - default: return get_cycles(); - } -} - -static inline u64 time_interpolator_get_counter(int writelock) -{ - unsigned int src = time_interpolator->source; - - if (time_interpolator->jitter) - { - cycles_t lcycle; - cycles_t now; - - do { - lcycle = time_interpolator->last_cycle; - now = time_interpolator_get_cycles(src); - if (lcycle && time_after(lcycle, now)) - return lcycle; - - /* When holding the xtime write lock, there's no need - * to add the overhead of the cmpxchg. Readers are - * force to retry until the write lock is released. - */ - if (writelock) { - time_interpolator->last_cycle = now; - return now; - } - /* Keep track of the last timer value returned. The use of cmpxchg here - * will cause contention in an SMP environment. - */ - } while (unlikely(cmpxchg(&time_interpolator->last_cycle, lcycle, now) != lcycle)); - return now; - } - else - return time_interpolator_get_cycles(src); -} - -void time_interpolator_reset(void) -{ - time_interpolator->offset = 0; - time_interpolator->last_counter = time_interpolator_get_counter(1); -} - -#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift) - -unsigned long time_interpolator_get_offset(void) -{ - /* If we do not have a time interpolator set up then just return zero */ - if (!time_interpolator) - return 0; - - return time_interpolator->offset + - GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator); -} - -#define INTERPOLATOR_ADJUST 65536 -#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST - -void time_interpolator_update(long delta_nsec) -{ - u64 counter; - unsigned long offset; - - /* If there is no time interpolator set up then do nothing */ - if (!time_interpolator) - return; - - /* - * The interpolator compensates for late ticks by accumulating the late - * time in time_interpolator->offset. A tick earlier than expected will - * lead to a reset of the offset and a corresponding jump of the clock - * forward. Again this only works if the interpolator clock is running - * slightly slower than the regular clock and the tuning logic insures - * that. - */ - - counter = time_interpolator_get_counter(1); - offset = time_interpolator->offset + - GET_TI_NSECS(counter, time_interpolator); - - if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) - time_interpolator->offset = offset - delta_nsec; - else { - time_interpolator->skips++; - time_interpolator->ns_skipped += delta_nsec - offset; - time_interpolator->offset = 0; - } - time_interpolator->last_counter = counter; - - /* Tuning logic for time interpolator invoked every minute or so. - * Decrease interpolator clock speed if no skips occurred and an offset is carried. - * Increase interpolator clock speed if we skip too much time. - */ - if (jiffies % INTERPOLATOR_ADJUST == 0) - { - if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec) - time_interpolator->nsec_per_cyc--; - if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0) - time_interpolator->nsec_per_cyc++; - time_interpolator->skips = 0; - time_interpolator->ns_skipped = 0; - } -} - -static inline int -is_better_time_interpolator(struct time_interpolator *new) -{ - if (!time_interpolator) - return 1; - return new->frequency > 2*time_interpolator->frequency || - (unsigned long)new->drift < (unsigned long)time_interpolator->drift; -} - -void -register_time_interpolator(struct time_interpolator *ti) -{ - unsigned long flags; - - /* Sanity check */ - BUG_ON(ti->frequency == 0 || ti->mask == 0); - - ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency; - spin_lock(&time_interpolator_lock); - write_seqlock_irqsave(&xtime_lock, flags); - if (is_better_time_interpolator(ti)) { - time_interpolator = ti; - time_interpolator_reset(); - } - write_sequnlock_irqrestore(&xtime_lock, flags); - - ti->next = time_interpolator_list; - time_interpolator_list = ti; - spin_unlock(&time_interpolator_lock); -} - -void -unregister_time_interpolator(struct time_interpolator *ti) -{ - struct time_interpolator *curr, **prev; - unsigned long flags; - - spin_lock(&time_interpolator_lock); - prev = &time_interpolator_list; - for (curr = *prev; curr; curr = curr->next) { - if (curr == ti) { - *prev = curr->next; - break; - } - prev = &curr->next; - } - - write_seqlock_irqsave(&xtime_lock, flags); - if (ti == time_interpolator) { - /* we lost the best time-interpolator: */ - time_interpolator = NULL; - /* find the next-best interpolator */ - for (curr = time_interpolator_list; curr; curr = curr->next) - if (is_better_time_interpolator(curr)) - time_interpolator = curr; - time_interpolator_reset(); - } - write_sequnlock_irqrestore(&xtime_lock, flags); - spin_unlock(&time_interpolator_lock); -} -#endif /* CONFIG_TIME_INTERPOLATION */ - /** * msleep - sleep safely even with waitqueue interruptions * @msecs: Time in milliseconds to sleep for From bd807f9c5b90c236c3d173a5815d620bc1b1316d Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Wed, 18 Jul 2007 07:33:08 -0400 Subject: [PATCH 18/18] [IA64] Prevent people from directly including . Signed-off-by: Robert P. J. Day Signed-off-by: Tony Luck --- include/asm-ia64/rwsem.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/asm-ia64/rwsem.h b/include/asm-ia64/rwsem.h index 2d1640cc240a..8aba06a7b038 100644 --- a/include/asm-ia64/rwsem.h +++ b/include/asm-ia64/rwsem.h @@ -21,6 +21,10 @@ #ifndef _ASM_IA64_RWSEM_H #define _ASM_IA64_RWSEM_H +#ifndef _LINUX_RWSEM_H +#error "Please don't include directly, use instead." +#endif + #include #include