Jan Beulich
2011-Nov-03 14:26 UTC
[Xen-devel] [PATCH 1/2] IRQ: allocate CPU masks dynamically
IRQ: allocate CPU masks dynamically This includes delaying the initialization of dynamically created IRQs until their actual first use and some further elimination of uses of struct irq_cfg. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/ia64/linux-xen/irq_ia64.c +++ b/xen/arch/ia64/linux-xen/irq_ia64.c @@ -303,6 +303,9 @@ int __init request_irq_vector(unsigned i void __init init_IRQ (void) { +#ifdef XEN + BUG_ON(init_irq_data()); +#endif register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); #ifdef CONFIG_SMP register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); --- a/xen/arch/ia64/xen/irq.c +++ b/xen/arch/ia64/xen/irq.c @@ -74,17 +74,30 @@ unsigned int __ia64_local_vector_to_irq /* * Controller mappings for all interrupt sources: */ -irq_desc_t irq_desc[NR_IRQS] = { - [0 ... NR_IRQS-1] = { - .status = IRQ_DISABLED, - .handler = &no_irq_type, - .lock = SPIN_LOCK_UNLOCKED - .arch = { - .vector = -1, - .cpu_mask = CPU_MASK_ALL, - } +irq_desc_t irq_desc[NR_IRQS]; + +int __init arch_init_one_irq_desc(struct irq_desc *desc) +{ + if (!alloc_cpumask_var(&desc->arch.cpu_mask)) + return -ENOMEM; + + desc->arch.vector = -1; + cpumask_setall(desc->arch.cpu_mask); + + return 0; +} + +int __init init_irq_data(void) +{ + unsigned int irq; + + for (irq = 0; irq < NR_IRQS; irq++) { + struct irq_desc *desc = irq_to_desc(irq); + + desc->irq = irq; + init_one_irq_desc(desc); } -}; +} void __do_IRQ_guest(int irq); --- a/xen/arch/x86/i8259.c +++ b/xen/arch/x86/i8259.c @@ -398,7 +398,7 @@ void __init init_IRQ(void) desc->handler = &i8259A_irq_type; per_cpu(vector_irq, cpu)[FIRST_LEGACY_VECTOR + irq] = irq; - cpumask_copy(&desc->arch.cpu_mask, cpumask_of(cpu)); + cpumask_copy(desc->arch.cpu_mask, cpumask_of(cpu)); desc->arch.vector = FIRST_LEGACY_VECTOR + irq; } --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -648,20 +648,21 @@ static int pin_2_irq(int idx, int apic, void /*__init*/ setup_ioapic_dest(void) { int pin, ioapic, irq, irq_entry; - struct irq_cfg *cfg; if (skip_ioapic_setup) return; for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { for (pin = 0; pin < nr_ioapic_entries[ioapic]; pin++) { + struct irq_desc *desc; + irq_entry = find_irq_entry(ioapic, pin, mp_INT); if (irq_entry == -1) continue; irq = pin_2_irq(irq_entry, ioapic, pin); - cfg = irq_cfg(irq); - BUG_ON(cpus_empty(cfg->cpu_mask)); - set_ioapic_affinity_irq(irq_to_desc(irq), &cfg->cpu_mask); + desc = irq_to_desc(irq); + BUG_ON(cpumask_empty(desc->arch.cpu_mask)); + set_ioapic_affinity_irq(desc, desc->arch.cpu_mask); } } @@ -956,12 +957,12 @@ static void __init setup_IO_APIC_irqs(vo struct IO_APIC_route_entry entry; int apic, pin, idx, irq, first_notcon = 1, vector; unsigned long flags; - struct irq_cfg *cfg; apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); for (apic = 0; apic < nr_ioapics; apic++) { for (pin = 0; pin < nr_ioapic_entries[apic]; pin++) { + struct irq_desc *desc; /* * add it to the IO-APIC irq-routing table: @@ -1016,9 +1017,9 @@ static void __init setup_IO_APIC_irqs(vo if (!apic && platform_legacy_irq(irq)) disable_8259A_irq(irq_to_desc(irq)); } - cfg = irq_cfg(irq); + desc = irq_to_desc(irq); SET_DEST(entry.dest.dest32, entry.dest.logical.logical_dest, - cpu_mask_to_apicid(&cfg->cpu_mask)); + cpu_mask_to_apicid(desc->arch.cpu_mask)); spin_lock_irqsave(&ioapic_lock, flags); __ioapic_write_entry(apic, pin, 0, entry); set_native_irq_info(irq, TARGET_CPUS); @@ -2372,7 +2373,7 @@ int ioapic_guest_write(unsigned long phy rte.vector = cfg->vector; SET_DEST(rte.dest.dest32, rte.dest.logical.logical_dest, - cpu_mask_to_apicid(&cfg->cpu_mask)); + cpu_mask_to_apicid(desc->arch.cpu_mask)); io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0)); io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1)); --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -25,6 +25,7 @@ #include <public/physdev.h> static void parse_irq_vector_map_param(char *s); +static int __assign_irq_vector(int irq, struct irq_desc *, const cpumask_t *); /* opt_noirqbalance: If true, software IRQ balancing/affinity is disabled. */ bool_t __read_mostly opt_noirqbalance = 0; @@ -110,7 +111,7 @@ static int __init __bind_irq_vector(int { cpumask_t online_mask; int cpu; - struct irq_cfg *cfg = irq_cfg(irq); + struct irq_desc *desc = irq_to_desc(irq); BUG_ON((unsigned)irq >= nr_irqs); BUG_ON((unsigned)vector >= NR_VECTORS); @@ -118,21 +119,22 @@ static int __init __bind_irq_vector(int cpumask_and(&online_mask, cpu_mask, &cpu_online_map); if (cpumask_empty(&online_mask)) return -EINVAL; - if ((cfg->vector == vector) && cpumask_equal(&cfg->cpu_mask, &online_mask)) + if ( (desc->arch.vector == vector) && + cpumask_equal(desc->arch.cpu_mask, &online_mask) ) return 0; - if (cfg->vector != IRQ_VECTOR_UNASSIGNED) + if ( desc->arch.vector != IRQ_VECTOR_UNASSIGNED ) return -EBUSY; trace_irq_mask(TRC_HW_IRQ_BIND_VECTOR, irq, vector, &online_mask); for_each_cpu_mask(cpu, online_mask) per_cpu(vector_irq, cpu)[vector] = irq; - cfg->vector = vector; - cpumask_copy(&cfg->cpu_mask, &online_mask); - if ( cfg->used_vectors ) + desc->arch.vector = vector; + cpumask_copy(desc->arch.cpu_mask, &online_mask); + if ( desc->arch.used_vectors ) { - ASSERT(!test_bit(vector, cfg->used_vectors)); - set_bit(vector, cfg->used_vectors); + ASSERT(!test_bit(vector, desc->arch.used_vectors)); + set_bit(vector, desc->arch.used_vectors); } - cfg->used = IRQ_USED; + desc->arch.used = IRQ_USED; if (IO_APIC_IRQ(irq)) irq_vector[irq] = vector; return 0; @@ -166,14 +168,17 @@ int create_irq(void) { unsigned long flags; int irq, ret; - irq = -ENOSPC; + struct irq_desc *desc; spin_lock_irqsave(&vector_lock, flags); irq = find_unassigned_irq(); if (irq < 0) goto out; - ret = __assign_irq_vector(irq, irq_cfg(irq), TARGET_CPUS); + desc = irq_to_desc(irq); + ret = init_one_irq_desc(desc); + if (!ret) + ret = __assign_irq_vector(irq, desc, TARGET_CPUS); if (ret < 0) irq = ret; out: @@ -197,7 +202,7 @@ static void dynamic_irq_cleanup(unsigned desc->msi_desc = NULL; desc->handler = &no_irq_type; desc->arch.used_vectors = NULL; - cpumask_setall(&desc->affinity); + cpumask_setall(desc->affinity); spin_unlock_irqrestore(&desc->lock, flags); /* Wait to make sure it''s not being used on another CPU */ @@ -211,38 +216,38 @@ static void __clear_irq_vector(int irq) { int cpu, vector, old_vector; cpumask_t tmp_mask; - struct irq_cfg *cfg = irq_cfg(irq); + struct irq_desc *desc = irq_to_desc(irq); - BUG_ON(!cfg->vector); + BUG_ON(!desc->arch.vector); - /* Always clear cfg->vector */ - vector = cfg->vector; - cpumask_and(&tmp_mask, &cfg->cpu_mask, &cpu_online_map); + /* Always clear desc->arch.vector */ + vector = desc->arch.vector; + cpumask_and(&tmp_mask, desc->arch.cpu_mask, &cpu_online_map); for_each_cpu_mask(cpu, tmp_mask) { ASSERT( per_cpu(vector_irq, cpu)[vector] == irq ); per_cpu(vector_irq, cpu)[vector] = -1; } - cfg->vector = IRQ_VECTOR_UNASSIGNED; - cpumask_clear(&cfg->cpu_mask); + desc->arch.vector = IRQ_VECTOR_UNASSIGNED; + cpumask_clear(desc->arch.cpu_mask); - if ( cfg->used_vectors ) + if ( desc->arch.used_vectors ) { - ASSERT(test_bit(vector, cfg->used_vectors)); - clear_bit(vector, cfg->used_vectors); + ASSERT(test_bit(vector, desc->arch.used_vectors)); + clear_bit(vector, desc->arch.used_vectors); } - cfg->used = IRQ_UNUSED; + desc->arch.used = IRQ_UNUSED; trace_irq_mask(TRC_HW_IRQ_CLEAR_VECTOR, irq, vector, &tmp_mask); - if (likely(!cfg->move_in_progress)) + if ( likely(!desc->arch.move_in_progress) ) return; - /* If we were in motion, also clear cfg->old_vector */ - old_vector = cfg->old_vector; - cpumask_and(&tmp_mask, &cfg->old_cpu_mask, &cpu_online_map); + /* If we were in motion, also clear desc->arch.old_vector */ + old_vector = desc->arch.old_vector; + cpumask_and(&tmp_mask, desc->arch.old_cpu_mask, &cpu_online_map); for_each_cpu_mask(cpu, tmp_mask) { ASSERT( per_cpu(vector_irq, cpu)[old_vector] == irq ); @@ -250,16 +255,16 @@ static void __clear_irq_vector(int irq) per_cpu(vector_irq, cpu)[old_vector] = -1; } - cfg->old_vector = IRQ_VECTOR_UNASSIGNED; - cpumask_clear(&cfg->old_cpu_mask); + desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; + cpumask_clear(desc->arch.old_cpu_mask); - if ( cfg->used_vectors ) + if ( desc->arch.used_vectors ) { - ASSERT(test_bit(old_vector, cfg->used_vectors)); - clear_bit(old_vector, cfg->used_vectors); + ASSERT(test_bit(old_vector, desc->arch.used_vectors)); + clear_bit(old_vector, desc->arch.used_vectors); } - cfg->move_in_progress = 0; + desc->arch.move_in_progress = 0; } void clear_irq_vector(int irq) @@ -296,25 +301,28 @@ int irq_to_vector(int irq) return vector; } -static void __init init_one_irq_desc(struct irq_desc *desc) +int arch_init_one_irq_desc(struct irq_desc *desc) { - desc->status = IRQ_DISABLED; - desc->handler = &no_irq_type; - desc->action = NULL; - desc->msi_desc = NULL; - spin_lock_init(&desc->lock); - cpumask_setall(&desc->affinity); - INIT_LIST_HEAD(&desc->rl_link); -} + if ( !zalloc_cpumask_var(&desc->arch.cpu_mask) ) + return -ENOMEM; + + if ( !alloc_cpumask_var(&desc->arch.old_cpu_mask) ) + { + free_cpumask_var(desc->arch.cpu_mask); + return -ENOMEM; + } -static void __init init_one_irq_cfg(struct irq_cfg *cfg) -{ - cfg->vector = IRQ_VECTOR_UNASSIGNED; - cfg->old_vector = IRQ_VECTOR_UNASSIGNED; - cpumask_clear(&cfg->cpu_mask); - cpumask_clear(&cfg->old_cpu_mask); - cfg->used_vectors = NULL; - cfg->used = IRQ_UNUSED; + if ( !alloc_cpumask_var(&desc->arch.pending_mask) ) + { + free_cpumask_var(desc->arch.old_cpu_mask); + free_cpumask_var(desc->arch.cpu_mask); + return -ENOMEM; + } + + desc->arch.vector = IRQ_VECTOR_UNASSIGNED; + desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; + + return 0; } int __init init_irq_data(void) @@ -331,12 +339,13 @@ int __init init_irq_data(void) if ( !irq_desc || !irq_vector ) return -ENOMEM; - for (irq = 0; irq < nr_irqs; irq++) { + for (irq = 0; irq < nr_irqs_gsi; irq++) { desc = irq_to_desc(irq); desc->irq = irq; init_one_irq_desc(desc); - init_one_irq_cfg(&desc->arch); } + for (; irq < nr_irqs; irq++) + irq_to_desc(irq)->irq = irq; /* Never allocate the hypercall vector or Linux/BSD fast-trap vector. */ set_bit(LEGACY_SYSCALL_VECTOR, used_vectors); @@ -403,7 +412,8 @@ static vmask_t *irq_get_used_vector_mask return ret; } -int __assign_irq_vector(int irq, struct irq_cfg *cfg, const cpumask_t *mask) +static int __assign_irq_vector( + int irq, struct irq_desc *desc, const cpumask_t *mask) { /* * NOTE! The local APIC isn''t very good at handling @@ -426,13 +436,13 @@ int __assign_irq_vector(int irq, struct old_vector = irq_to_vector(irq); if (old_vector) { cpumask_and(&tmp_mask, mask, &cpu_online_map); - if (cpumask_intersects(&tmp_mask, &cfg->cpu_mask)) { - cfg->vector = old_vector; + if (cpumask_intersects(&tmp_mask, desc->arch.cpu_mask)) { + desc->arch.vector = old_vector; return 0; } } - if ((cfg->move_in_progress) || cfg->move_cleanup_count) + if ( desc->arch.move_in_progress || desc->arch.move_cleanup_count ) return -EAGAIN; err = -ENOSPC; @@ -440,9 +450,9 @@ int __assign_irq_vector(int irq, struct /* This is the only place normal IRQs are ever marked * as "in use". If they''re not in use yet, check to see * if we need to assign a global vector mask. */ - if ( cfg->used == IRQ_USED ) + if ( desc->arch.used == IRQ_USED ) { - irq_used_vectors = cfg->used_vectors; + irq_used_vectors = desc->arch.used_vectors; } else irq_used_vectors = irq_get_used_vector_mask(irq); @@ -485,29 +495,29 @@ next: current_offset = offset; local_irq_save(flags); if (old_vector) { - cfg->move_in_progress = 1; - cpumask_copy(&cfg->old_cpu_mask, &cfg->cpu_mask); - cfg->old_vector = cfg->vector; + desc->arch.move_in_progress = 1; + cpumask_copy(desc->arch.old_cpu_mask, desc->arch.cpu_mask); + desc->arch.old_vector = desc->arch.vector; } trace_irq_mask(TRC_HW_IRQ_ASSIGN_VECTOR, irq, vector, &tmp_mask); for_each_cpu_mask(new_cpu, tmp_mask) per_cpu(vector_irq, new_cpu)[vector] = irq; - cfg->vector = vector; - cpumask_copy(&cfg->cpu_mask, &tmp_mask); + desc->arch.vector = vector; + cpumask_copy(desc->arch.cpu_mask, &tmp_mask); - cfg->used = IRQ_USED; - ASSERT((cfg->used_vectors == NULL) - || (cfg->used_vectors == irq_used_vectors)); - cfg->used_vectors = irq_used_vectors; + desc->arch.used = IRQ_USED; + ASSERT((desc->arch.used_vectors == NULL) + || (desc->arch.used_vectors == irq_used_vectors)); + desc->arch.used_vectors = irq_used_vectors; if (IO_APIC_IRQ(irq)) irq_vector[irq] = vector; - if ( cfg->used_vectors ) + if ( desc->arch.used_vectors ) { - ASSERT(!test_bit(vector, cfg->used_vectors)); + ASSERT(!test_bit(vector, desc->arch.used_vectors)); - set_bit(vector, cfg->used_vectors); + set_bit(vector, desc->arch.used_vectors); } err = 0; @@ -521,16 +531,15 @@ int assign_irq_vector(int irq) { int ret; unsigned long flags; - struct irq_cfg *cfg = irq_cfg(irq); struct irq_desc *desc = irq_to_desc(irq); BUG_ON(irq >= nr_irqs || irq <0); spin_lock_irqsave(&vector_lock, flags); - ret = __assign_irq_vector(irq, cfg, TARGET_CPUS); + ret = __assign_irq_vector(irq, desc, TARGET_CPUS); if (!ret) { - ret = cfg->vector; - cpumask_copy(&desc->affinity, &cfg->cpu_mask); + ret = desc->arch.vector; + cpumask_copy(desc->affinity, desc->arch.cpu_mask); } spin_unlock_irqrestore(&vector_lock, flags); return ret; @@ -543,15 +552,16 @@ int assign_irq_vector(int irq) void __setup_vector_irq(int cpu) { int irq, vector; - struct irq_cfg *cfg; /* Clear vector_irq */ for (vector = 0; vector < NR_VECTORS; ++vector) per_cpu(vector_irq, cpu)[vector] = -1; /* Mark the inuse vectors */ for (irq = 0; irq < nr_irqs; ++irq) { - cfg = irq_cfg(irq); - if (!cpu_isset(cpu, cfg->cpu_mask)) + struct irq_desc *desc = irq_to_desc(irq); + + if (!irq_desc_initialized(desc) || + !cpumask_test_cpu(cpu, desc->arch.cpu_mask)) continue; vector = irq_to_vector(irq); per_cpu(vector_irq, cpu)[vector] = irq; @@ -560,12 +570,14 @@ void __setup_vector_irq(int cpu) void move_masked_irq(struct irq_desc *desc) { + cpumask_t *pending_mask = desc->arch.pending_mask; + if (likely(!(desc->status & IRQ_MOVE_PENDING))) return; desc->status &= ~IRQ_MOVE_PENDING; - if (unlikely(cpus_empty(desc->pending_mask))) + if (unlikely(cpumask_empty(pending_mask))) return; if (!desc->handler->set_affinity) @@ -580,10 +592,10 @@ void move_masked_irq(struct irq_desc *de * * For correct operation this depends on the caller masking the irqs. */ - if (likely(cpus_intersects(desc->pending_mask, cpu_online_map))) - desc->handler->set_affinity(desc, &desc->pending_mask); + if ( likely(cpumask_intersects(pending_mask, &cpu_online_map)) ) + desc->handler->set_affinity(desc, pending_mask); - cpumask_clear(&desc->pending_mask); + cpumask_clear(pending_mask); } void move_native_irq(struct irq_desc *desc) @@ -626,7 +638,8 @@ fastcall void smp_irq_move_cleanup_inter if (!desc->arch.move_cleanup_count) goto unlock; - if (vector == desc->arch.vector && cpumask_test_cpu(me, &desc->arch.cpu_mask)) + if ( vector == desc->arch.vector && + cpumask_test_cpu(me, desc->arch.cpu_mask) ) goto unlock; irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); @@ -653,7 +666,7 @@ fastcall void smp_irq_move_cleanup_inter if ( desc->arch.move_cleanup_count == 0 ) { desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; - cpumask_clear(&desc->arch.old_cpu_mask); + cpumask_clear(desc->arch.old_cpu_mask); if ( desc->arch.used_vectors ) { @@ -673,7 +686,7 @@ static void send_cleanup_vector(struct i { cpumask_t cleanup_mask; - cpumask_and(&cleanup_mask, &desc->arch.old_cpu_mask, &cpu_online_map); + cpumask_and(&cleanup_mask, desc->arch.old_cpu_mask, &cpu_online_map); desc->arch.move_cleanup_count = cpumask_weight(&cleanup_mask); genapic->send_IPI_mask(&cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); @@ -690,7 +703,8 @@ void irq_complete_move(struct irq_desc * vector = get_irq_regs()->entry_vector; me = smp_processor_id(); - if (vector == desc->arch.vector && cpumask_test_cpu(me, &desc->arch.cpu_mask)) + if ( vector == desc->arch.vector && + cpumask_test_cpu(me, desc->arch.cpu_mask) ) send_cleanup_vector(desc); } @@ -708,15 +722,15 @@ unsigned int set_desc_affinity(struct ir local_irq_save(flags); lock_vector_lock(); - ret = __assign_irq_vector(irq, &desc->arch, mask); + ret = __assign_irq_vector(irq, desc, mask); unlock_vector_lock(); local_irq_restore(flags); if (ret < 0) return BAD_APICID; - cpumask_copy(&desc->affinity, mask); - cpumask_and(&dest_mask, mask, &desc->arch.cpu_mask); + cpumask_copy(desc->affinity, mask); + cpumask_and(&dest_mask, mask, desc->arch.cpu_mask); return cpu_mask_to_apicid(&dest_mask); } @@ -730,7 +744,7 @@ void irq_set_affinity(struct irq_desc *d ASSERT(spin_is_locked(&desc->lock)); desc->status &= ~IRQ_MOVE_PENDING; wmb(); - cpumask_copy(&desc->pending_mask, mask); + cpumask_copy(desc->arch.pending_mask, mask); wmb(); desc->status |= IRQ_MOVE_PENDING; } @@ -1992,13 +2006,13 @@ static void dump_irqs(unsigned char key) desc = irq_to_desc(irq); - if ( !desc->handler || desc->handler == &no_irq_type ) + if ( !irq_desc_initialized(desc) || desc->handler == &no_irq_type ) continue; spin_lock_irqsave(&desc->lock, flags); cpumask_scnprintf(keyhandler_scratch, sizeof(keyhandler_scratch), - &desc->affinity); + desc->affinity); printk(" IRQ:%4d affinity:%s vec:%02x type=%-15s" " status=%08x ", irq, keyhandler_scratch, desc->arch.vector, @@ -2073,10 +2087,12 @@ void fixup_irqs(void) continue; desc = irq_to_desc(irq); + if ( !irq_desc_initialized(desc) ) + continue; spin_lock(&desc->lock); - cpumask_copy(&affinity, &desc->affinity); + cpumask_copy(&affinity, desc->affinity); if ( !desc->action || cpumask_subset(&affinity, &cpu_online_map) ) { spin_unlock(&desc->lock); --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -125,13 +125,13 @@ void msi_compose_msg(struct irq_desc *de unsigned dest; int vector = desc->arch.vector; - if ( cpumask_empty(&desc->arch.cpu_mask) ) { + if ( cpumask_empty(desc->arch.cpu_mask) ) { dprintk(XENLOG_ERR,"%s, compose msi message error!!\n", __func__); return; } if ( vector ) { - dest = cpu_mask_to_apicid(&desc->arch.cpu_mask); + dest = cpu_mask_to_apicid(desc->arch.cpu_mask); msg->address_hi = MSI_ADDR_BASE_HI; msg->address_lo --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -1011,7 +1011,7 @@ void __init smp_intr_init(void) irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1; per_cpu(vector_irq, cpu)[FIRST_HIPRIORITY_VECTOR + seridx + 1] = irq; irq_to_desc(irq)->arch.vector = FIRST_HIPRIORITY_VECTOR + seridx + 1; - cpumask_copy(&irq_to_desc(irq)->arch.cpu_mask, &cpu_online_map); + cpumask_copy(irq_to_desc(irq)->arch.cpu_mask, &cpu_online_map); } /* IPI for cleanuping vectors after irq move */ --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -5,6 +5,7 @@ obj-y += domctl.o obj-y += domain.o obj-y += event_channel.o obj-y += grant_table.o +obj-y += irq.o obj-y += kernel.o obj-y += keyhandler.o obj-y += kexec.o --- /dev/null +++ a/xen/common/irq.c @@ -0,0 +1,28 @@ +#include <xen/config.h> +#include <xen/irq.h> + +int init_one_irq_desc(struct irq_desc *desc) +{ + int err; + + if (irq_desc_initialized(desc)) + return 0; + + if ( !alloc_cpumask_var(&desc->affinity) ) + return -ENOMEM; + + desc->status = IRQ_DISABLED; + desc->handler = &no_irq_type; + spin_lock_init(&desc->lock); + cpumask_setall(desc->affinity); + INIT_LIST_HEAD(&desc->rl_link); + + err = arch_init_one_irq_desc(desc); + if ( err ) + { + free_cpumask_var(desc->affinity); + desc->handler = NULL; + } + + return err; +} --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1965,17 +1965,18 @@ static int init_vtd_hw(void) struct iommu_flush *flush = NULL; int ret; unsigned long flags; - struct irq_cfg *cfg; /* * Basic VT-d HW init: set VT-d interrupt, clear VT-d faults. */ for_each_drhd_unit ( drhd ) { + struct irq_desc *desc; + iommu = drhd->iommu; - cfg = irq_cfg(iommu->irq); - dma_msi_set_affinity(irq_to_desc(iommu->irq), &cfg->cpu_mask); + desc = irq_to_desc(iommu->irq); + dma_msi_set_affinity(desc, desc->arch.cpu_mask); clear_fault_bits(iommu); --- a/xen/include/asm-ia64/linux-xen/asm/irq.h +++ b/xen/include/asm-ia64/linux-xen/asm/irq.h @@ -18,8 +18,10 @@ struct irq_cfg { #define arch_irq_desc irq_cfg int vector; - cpumask_t cpu_mask; + cpumask_var_t cpu_mask; }; + +int init_irq_data(void); #endif static __inline__ int --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -33,8 +33,9 @@ struct irq_cfg { #define arch_irq_desc irq_cfg s16 vector; /* vector itself is only 8 bits, */ s16 old_vector; /* but we use -1 for unassigned */ - cpumask_t cpu_mask; - cpumask_t old_cpu_mask; + cpumask_var_t cpu_mask; + cpumask_var_t old_cpu_mask; + cpumask_var_t pending_mask; unsigned move_cleanup_count; vmask_t *used_vectors; u8 move_in_progress : 1; @@ -174,8 +175,6 @@ void __setup_vector_irq(int cpu); void move_native_irq(struct irq_desc *); void move_masked_irq(struct irq_desc *); -int __assign_irq_vector(int irq, struct irq_cfg *, const cpumask_t *); - int bind_irq_vector(int irq, int vector, const cpumask_t *); void irq_set_affinity(struct irq_desc *, const cpumask_t *mask); --- a/xen/include/xen/irq.h +++ b/xen/include/xen/irq.h @@ -76,8 +76,7 @@ typedef struct irq_desc { int irq; spinlock_t lock; struct arch_irq_desc arch; - cpumask_t affinity; - cpumask_t pending_mask; /* IRQ migration pending mask */ + cpumask_var_t affinity; /* irq ratelimit */ s_time_t rl_quantum_start; @@ -85,6 +84,11 @@ typedef struct irq_desc { struct list_head rl_link; } __cacheline_aligned irq_desc_t; +int init_one_irq_desc(struct irq_desc *); +int arch_init_one_irq_desc(struct irq_desc *); + +#define irq_desc_initialized(desc) ((desc)->handler != NULL) + #if defined(__ia64__) extern irq_desc_t irq_desc[NR_VECTORS]; @@ -153,7 +157,7 @@ extern irq_desc_t *pirq_spin_lock_irq_de static inline void set_native_irq_info(unsigned int irq, const cpumask_t *mask) { - cpumask_copy(&irq_desc[irq].affinity, mask); + cpumask_copy(irq_to_desc(irq)->affinity, mask); } unsigned int set_desc_affinity(struct irq_desc *, const cpumask_t *); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Andrew Cooper
2011-Nov-03 14:49 UTC
Re: [Xen-devel] [PATCH 1/2] IRQ: allocate CPU masks dynamically
On 03/11/11 14:26, Jan Beulich wrote:> IRQ: allocate CPU masks dynamically > > This includes delaying the initialization of dynamically created IRQs > until their actual first use and some further elimination of uses of > struct irq_cfg. > > Signed-off-by: Jan Beulich <jbeulich@suse.com>Acked-by: Andrew Cooper <andrew.cooper3@citrix.com> One query which may or may not affect the patch. Would we get better caching characteristics if all cpumasks were allocated in consecutive memory, rather than having 3 individual allocs in arch_init_one_irq_desc ? ~Andrew> --- a/xen/arch/ia64/linux-xen/irq_ia64.c > +++ b/xen/arch/ia64/linux-xen/irq_ia64.c > @@ -303,6 +303,9 @@ int __init request_irq_vector(unsigned i > void __init > init_IRQ (void) > { > +#ifdef XEN > + BUG_ON(init_irq_data()); > +#endif > register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); > #ifdef CONFIG_SMP > register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); > --- a/xen/arch/ia64/xen/irq.c > +++ b/xen/arch/ia64/xen/irq.c > @@ -74,17 +74,30 @@ unsigned int __ia64_local_vector_to_irq > /* > * Controller mappings for all interrupt sources: > */ > -irq_desc_t irq_desc[NR_IRQS] = { > - [0 ... NR_IRQS-1] = { > - .status = IRQ_DISABLED, > - .handler = &no_irq_type, > - .lock = SPIN_LOCK_UNLOCKED > - .arch = { > - .vector = -1, > - .cpu_mask = CPU_MASK_ALL, > - } > +irq_desc_t irq_desc[NR_IRQS]; > + > +int __init arch_init_one_irq_desc(struct irq_desc *desc) > +{ > + if (!alloc_cpumask_var(&desc->arch.cpu_mask)) > + return -ENOMEM; > + > + desc->arch.vector = -1; > + cpumask_setall(desc->arch.cpu_mask); > + > + return 0; > +} > + > +int __init init_irq_data(void) > +{ > + unsigned int irq; > + > + for (irq = 0; irq < NR_IRQS; irq++) { > + struct irq_desc *desc = irq_to_desc(irq); > + > + desc->irq = irq; > + init_one_irq_desc(desc); > } > -}; > +} > > void __do_IRQ_guest(int irq); > > --- a/xen/arch/x86/i8259.c > +++ b/xen/arch/x86/i8259.c > @@ -398,7 +398,7 @@ void __init init_IRQ(void) > > desc->handler = &i8259A_irq_type; > per_cpu(vector_irq, cpu)[FIRST_LEGACY_VECTOR + irq] = irq; > - cpumask_copy(&desc->arch.cpu_mask, cpumask_of(cpu)); > + cpumask_copy(desc->arch.cpu_mask, cpumask_of(cpu)); > desc->arch.vector = FIRST_LEGACY_VECTOR + irq; > } > > --- a/xen/arch/x86/io_apic.c > +++ b/xen/arch/x86/io_apic.c > @@ -648,20 +648,21 @@ static int pin_2_irq(int idx, int apic, > void /*__init*/ setup_ioapic_dest(void) > { > int pin, ioapic, irq, irq_entry; > - struct irq_cfg *cfg; > > if (skip_ioapic_setup) > return; > > for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { > for (pin = 0; pin < nr_ioapic_entries[ioapic]; pin++) { > + struct irq_desc *desc; > + > irq_entry = find_irq_entry(ioapic, pin, mp_INT); > if (irq_entry == -1) > continue; > irq = pin_2_irq(irq_entry, ioapic, pin); > - cfg = irq_cfg(irq); > - BUG_ON(cpus_empty(cfg->cpu_mask)); > - set_ioapic_affinity_irq(irq_to_desc(irq), &cfg->cpu_mask); > + desc = irq_to_desc(irq); > + BUG_ON(cpumask_empty(desc->arch.cpu_mask)); > + set_ioapic_affinity_irq(desc, desc->arch.cpu_mask); > } > > } > @@ -956,12 +957,12 @@ static void __init setup_IO_APIC_irqs(vo > struct IO_APIC_route_entry entry; > int apic, pin, idx, irq, first_notcon = 1, vector; > unsigned long flags; > - struct irq_cfg *cfg; > > apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); > > for (apic = 0; apic < nr_ioapics; apic++) { > for (pin = 0; pin < nr_ioapic_entries[apic]; pin++) { > + struct irq_desc *desc; > > /* > * add it to the IO-APIC irq-routing table: > @@ -1016,9 +1017,9 @@ static void __init setup_IO_APIC_irqs(vo > if (!apic && platform_legacy_irq(irq)) > disable_8259A_irq(irq_to_desc(irq)); > } > - cfg = irq_cfg(irq); > + desc = irq_to_desc(irq); > SET_DEST(entry.dest.dest32, entry.dest.logical.logical_dest, > - cpu_mask_to_apicid(&cfg->cpu_mask)); > + cpu_mask_to_apicid(desc->arch.cpu_mask)); > spin_lock_irqsave(&ioapic_lock, flags); > __ioapic_write_entry(apic, pin, 0, entry); > set_native_irq_info(irq, TARGET_CPUS); > @@ -2372,7 +2373,7 @@ int ioapic_guest_write(unsigned long phy > rte.vector = cfg->vector; > > SET_DEST(rte.dest.dest32, rte.dest.logical.logical_dest, > - cpu_mask_to_apicid(&cfg->cpu_mask)); > + cpu_mask_to_apicid(desc->arch.cpu_mask)); > > io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0)); > io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1)); > --- a/xen/arch/x86/irq.c > +++ b/xen/arch/x86/irq.c > @@ -25,6 +25,7 @@ > #include <public/physdev.h> > > static void parse_irq_vector_map_param(char *s); > +static int __assign_irq_vector(int irq, struct irq_desc *, const cpumask_t *); > > /* opt_noirqbalance: If true, software IRQ balancing/affinity is disabled. */ > bool_t __read_mostly opt_noirqbalance = 0; > @@ -110,7 +111,7 @@ static int __init __bind_irq_vector(int > { > cpumask_t online_mask; > int cpu; > - struct irq_cfg *cfg = irq_cfg(irq); > + struct irq_desc *desc = irq_to_desc(irq); > > BUG_ON((unsigned)irq >= nr_irqs); > BUG_ON((unsigned)vector >= NR_VECTORS); > @@ -118,21 +119,22 @@ static int __init __bind_irq_vector(int > cpumask_and(&online_mask, cpu_mask, &cpu_online_map); > if (cpumask_empty(&online_mask)) > return -EINVAL; > - if ((cfg->vector == vector) && cpumask_equal(&cfg->cpu_mask, &online_mask)) > + if ( (desc->arch.vector == vector) && > + cpumask_equal(desc->arch.cpu_mask, &online_mask) ) > return 0; > - if (cfg->vector != IRQ_VECTOR_UNASSIGNED) > + if ( desc->arch.vector != IRQ_VECTOR_UNASSIGNED ) > return -EBUSY; > trace_irq_mask(TRC_HW_IRQ_BIND_VECTOR, irq, vector, &online_mask); > for_each_cpu_mask(cpu, online_mask) > per_cpu(vector_irq, cpu)[vector] = irq; > - cfg->vector = vector; > - cpumask_copy(&cfg->cpu_mask, &online_mask); > - if ( cfg->used_vectors ) > + desc->arch.vector = vector; > + cpumask_copy(desc->arch.cpu_mask, &online_mask); > + if ( desc->arch.used_vectors ) > { > - ASSERT(!test_bit(vector, cfg->used_vectors)); > - set_bit(vector, cfg->used_vectors); > + ASSERT(!test_bit(vector, desc->arch.used_vectors)); > + set_bit(vector, desc->arch.used_vectors); > } > - cfg->used = IRQ_USED; > + desc->arch.used = IRQ_USED; > if (IO_APIC_IRQ(irq)) > irq_vector[irq] = vector; > return 0; > @@ -166,14 +168,17 @@ int create_irq(void) > { > unsigned long flags; > int irq, ret; > - irq = -ENOSPC; > + struct irq_desc *desc; > > spin_lock_irqsave(&vector_lock, flags); > > irq = find_unassigned_irq(); > if (irq < 0) > goto out; > - ret = __assign_irq_vector(irq, irq_cfg(irq), TARGET_CPUS); > + desc = irq_to_desc(irq); > + ret = init_one_irq_desc(desc); > + if (!ret) > + ret = __assign_irq_vector(irq, desc, TARGET_CPUS); > if (ret < 0) > irq = ret; > out: > @@ -197,7 +202,7 @@ static void dynamic_irq_cleanup(unsigned > desc->msi_desc = NULL; > desc->handler = &no_irq_type; > desc->arch.used_vectors = NULL; > - cpumask_setall(&desc->affinity); > + cpumask_setall(desc->affinity); > spin_unlock_irqrestore(&desc->lock, flags); > > /* Wait to make sure it''s not being used on another CPU */ > @@ -211,38 +216,38 @@ static void __clear_irq_vector(int irq) > { > int cpu, vector, old_vector; > cpumask_t tmp_mask; > - struct irq_cfg *cfg = irq_cfg(irq); > + struct irq_desc *desc = irq_to_desc(irq); > > - BUG_ON(!cfg->vector); > + BUG_ON(!desc->arch.vector); > > - /* Always clear cfg->vector */ > - vector = cfg->vector; > - cpumask_and(&tmp_mask, &cfg->cpu_mask, &cpu_online_map); > + /* Always clear desc->arch.vector */ > + vector = desc->arch.vector; > + cpumask_and(&tmp_mask, desc->arch.cpu_mask, &cpu_online_map); > > for_each_cpu_mask(cpu, tmp_mask) { > ASSERT( per_cpu(vector_irq, cpu)[vector] == irq ); > per_cpu(vector_irq, cpu)[vector] = -1; > } > > - cfg->vector = IRQ_VECTOR_UNASSIGNED; > - cpumask_clear(&cfg->cpu_mask); > + desc->arch.vector = IRQ_VECTOR_UNASSIGNED; > + cpumask_clear(desc->arch.cpu_mask); > > - if ( cfg->used_vectors ) > + if ( desc->arch.used_vectors ) > { > - ASSERT(test_bit(vector, cfg->used_vectors)); > - clear_bit(vector, cfg->used_vectors); > + ASSERT(test_bit(vector, desc->arch.used_vectors)); > + clear_bit(vector, desc->arch.used_vectors); > } > > - cfg->used = IRQ_UNUSED; > + desc->arch.used = IRQ_UNUSED; > > trace_irq_mask(TRC_HW_IRQ_CLEAR_VECTOR, irq, vector, &tmp_mask); > > - if (likely(!cfg->move_in_progress)) > + if ( likely(!desc->arch.move_in_progress) ) > return; > > - /* If we were in motion, also clear cfg->old_vector */ > - old_vector = cfg->old_vector; > - cpumask_and(&tmp_mask, &cfg->old_cpu_mask, &cpu_online_map); > + /* If we were in motion, also clear desc->arch.old_vector */ > + old_vector = desc->arch.old_vector; > + cpumask_and(&tmp_mask, desc->arch.old_cpu_mask, &cpu_online_map); > > for_each_cpu_mask(cpu, tmp_mask) { > ASSERT( per_cpu(vector_irq, cpu)[old_vector] == irq ); > @@ -250,16 +255,16 @@ static void __clear_irq_vector(int irq) > per_cpu(vector_irq, cpu)[old_vector] = -1; > } > > - cfg->old_vector = IRQ_VECTOR_UNASSIGNED; > - cpumask_clear(&cfg->old_cpu_mask); > + desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; > + cpumask_clear(desc->arch.old_cpu_mask); > > - if ( cfg->used_vectors ) > + if ( desc->arch.used_vectors ) > { > - ASSERT(test_bit(old_vector, cfg->used_vectors)); > - clear_bit(old_vector, cfg->used_vectors); > + ASSERT(test_bit(old_vector, desc->arch.used_vectors)); > + clear_bit(old_vector, desc->arch.used_vectors); > } > > - cfg->move_in_progress = 0; > + desc->arch.move_in_progress = 0; > } > > void clear_irq_vector(int irq) > @@ -296,25 +301,28 @@ int irq_to_vector(int irq) > return vector; > } > > -static void __init init_one_irq_desc(struct irq_desc *desc) > +int arch_init_one_irq_desc(struct irq_desc *desc) > { > - desc->status = IRQ_DISABLED; > - desc->handler = &no_irq_type; > - desc->action = NULL; > - desc->msi_desc = NULL; > - spin_lock_init(&desc->lock); > - cpumask_setall(&desc->affinity); > - INIT_LIST_HEAD(&desc->rl_link); > -} > + if ( !zalloc_cpumask_var(&desc->arch.cpu_mask) ) > + return -ENOMEM; > + > + if ( !alloc_cpumask_var(&desc->arch.old_cpu_mask) ) > + { > + free_cpumask_var(desc->arch.cpu_mask); > + return -ENOMEM; > + } > > -static void __init init_one_irq_cfg(struct irq_cfg *cfg) > -{ > - cfg->vector = IRQ_VECTOR_UNASSIGNED; > - cfg->old_vector = IRQ_VECTOR_UNASSIGNED; > - cpumask_clear(&cfg->cpu_mask); > - cpumask_clear(&cfg->old_cpu_mask); > - cfg->used_vectors = NULL; > - cfg->used = IRQ_UNUSED; > + if ( !alloc_cpumask_var(&desc->arch.pending_mask) ) > + { > + free_cpumask_var(desc->arch.old_cpu_mask); > + free_cpumask_var(desc->arch.cpu_mask); > + return -ENOMEM; > + } > + > + desc->arch.vector = IRQ_VECTOR_UNASSIGNED; > + desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; > + > + return 0; > } > > int __init init_irq_data(void) > @@ -331,12 +339,13 @@ int __init init_irq_data(void) > if ( !irq_desc || !irq_vector ) > return -ENOMEM; > > - for (irq = 0; irq < nr_irqs; irq++) { > + for (irq = 0; irq < nr_irqs_gsi; irq++) { > desc = irq_to_desc(irq); > desc->irq = irq; > init_one_irq_desc(desc); > - init_one_irq_cfg(&desc->arch); > } > + for (; irq < nr_irqs; irq++) > + irq_to_desc(irq)->irq = irq; > > /* Never allocate the hypercall vector or Linux/BSD fast-trap vector. */ > set_bit(LEGACY_SYSCALL_VECTOR, used_vectors); > @@ -403,7 +412,8 @@ static vmask_t *irq_get_used_vector_mask > return ret; > } > > -int __assign_irq_vector(int irq, struct irq_cfg *cfg, const cpumask_t *mask) > +static int __assign_irq_vector( > + int irq, struct irq_desc *desc, const cpumask_t *mask) > { > /* > * NOTE! The local APIC isn''t very good at handling > @@ -426,13 +436,13 @@ int __assign_irq_vector(int irq, struct > old_vector = irq_to_vector(irq); > if (old_vector) { > cpumask_and(&tmp_mask, mask, &cpu_online_map); > - if (cpumask_intersects(&tmp_mask, &cfg->cpu_mask)) { > - cfg->vector = old_vector; > + if (cpumask_intersects(&tmp_mask, desc->arch.cpu_mask)) { > + desc->arch.vector = old_vector; > return 0; > } > } > > - if ((cfg->move_in_progress) || cfg->move_cleanup_count) > + if ( desc->arch.move_in_progress || desc->arch.move_cleanup_count ) > return -EAGAIN; > > err = -ENOSPC; > @@ -440,9 +450,9 @@ int __assign_irq_vector(int irq, struct > /* This is the only place normal IRQs are ever marked > * as "in use". If they''re not in use yet, check to see > * if we need to assign a global vector mask. */ > - if ( cfg->used == IRQ_USED ) > + if ( desc->arch.used == IRQ_USED ) > { > - irq_used_vectors = cfg->used_vectors; > + irq_used_vectors = desc->arch.used_vectors; > } > else > irq_used_vectors = irq_get_used_vector_mask(irq); > @@ -485,29 +495,29 @@ next: > current_offset = offset; > local_irq_save(flags); > if (old_vector) { > - cfg->move_in_progress = 1; > - cpumask_copy(&cfg->old_cpu_mask, &cfg->cpu_mask); > - cfg->old_vector = cfg->vector; > + desc->arch.move_in_progress = 1; > + cpumask_copy(desc->arch.old_cpu_mask, desc->arch.cpu_mask); > + desc->arch.old_vector = desc->arch.vector; > } > trace_irq_mask(TRC_HW_IRQ_ASSIGN_VECTOR, irq, vector, &tmp_mask); > for_each_cpu_mask(new_cpu, tmp_mask) > per_cpu(vector_irq, new_cpu)[vector] = irq; > - cfg->vector = vector; > - cpumask_copy(&cfg->cpu_mask, &tmp_mask); > + desc->arch.vector = vector; > + cpumask_copy(desc->arch.cpu_mask, &tmp_mask); > > - cfg->used = IRQ_USED; > - ASSERT((cfg->used_vectors == NULL) > - || (cfg->used_vectors == irq_used_vectors)); > - cfg->used_vectors = irq_used_vectors; > + desc->arch.used = IRQ_USED; > + ASSERT((desc->arch.used_vectors == NULL) > + || (desc->arch.used_vectors == irq_used_vectors)); > + desc->arch.used_vectors = irq_used_vectors; > > if (IO_APIC_IRQ(irq)) > irq_vector[irq] = vector; > > - if ( cfg->used_vectors ) > + if ( desc->arch.used_vectors ) > { > - ASSERT(!test_bit(vector, cfg->used_vectors)); > + ASSERT(!test_bit(vector, desc->arch.used_vectors)); > > - set_bit(vector, cfg->used_vectors); > + set_bit(vector, desc->arch.used_vectors); > } > > err = 0; > @@ -521,16 +531,15 @@ int assign_irq_vector(int irq) > { > int ret; > unsigned long flags; > - struct irq_cfg *cfg = irq_cfg(irq); > struct irq_desc *desc = irq_to_desc(irq); > > BUG_ON(irq >= nr_irqs || irq <0); > > spin_lock_irqsave(&vector_lock, flags); > - ret = __assign_irq_vector(irq, cfg, TARGET_CPUS); > + ret = __assign_irq_vector(irq, desc, TARGET_CPUS); > if (!ret) { > - ret = cfg->vector; > - cpumask_copy(&desc->affinity, &cfg->cpu_mask); > + ret = desc->arch.vector; > + cpumask_copy(desc->affinity, desc->arch.cpu_mask); > } > spin_unlock_irqrestore(&vector_lock, flags); > return ret; > @@ -543,15 +552,16 @@ int assign_irq_vector(int irq) > void __setup_vector_irq(int cpu) > { > int irq, vector; > - struct irq_cfg *cfg; > > /* Clear vector_irq */ > for (vector = 0; vector < NR_VECTORS; ++vector) > per_cpu(vector_irq, cpu)[vector] = -1; > /* Mark the inuse vectors */ > for (irq = 0; irq < nr_irqs; ++irq) { > - cfg = irq_cfg(irq); > - if (!cpu_isset(cpu, cfg->cpu_mask)) > + struct irq_desc *desc = irq_to_desc(irq); > + > + if (!irq_desc_initialized(desc) || > + !cpumask_test_cpu(cpu, desc->arch.cpu_mask)) > continue; > vector = irq_to_vector(irq); > per_cpu(vector_irq, cpu)[vector] = irq; > @@ -560,12 +570,14 @@ void __setup_vector_irq(int cpu) > > void move_masked_irq(struct irq_desc *desc) > { > + cpumask_t *pending_mask = desc->arch.pending_mask; > + > if (likely(!(desc->status & IRQ_MOVE_PENDING))) > return; > > desc->status &= ~IRQ_MOVE_PENDING; > > - if (unlikely(cpus_empty(desc->pending_mask))) > + if (unlikely(cpumask_empty(pending_mask))) > return; > > if (!desc->handler->set_affinity) > @@ -580,10 +592,10 @@ void move_masked_irq(struct irq_desc *de > * > * For correct operation this depends on the caller masking the irqs. > */ > - if (likely(cpus_intersects(desc->pending_mask, cpu_online_map))) > - desc->handler->set_affinity(desc, &desc->pending_mask); > + if ( likely(cpumask_intersects(pending_mask, &cpu_online_map)) ) > + desc->handler->set_affinity(desc, pending_mask); > > - cpumask_clear(&desc->pending_mask); > + cpumask_clear(pending_mask); > } > > void move_native_irq(struct irq_desc *desc) > @@ -626,7 +638,8 @@ fastcall void smp_irq_move_cleanup_inter > if (!desc->arch.move_cleanup_count) > goto unlock; > > - if (vector == desc->arch.vector && cpumask_test_cpu(me, &desc->arch.cpu_mask)) > + if ( vector == desc->arch.vector && > + cpumask_test_cpu(me, desc->arch.cpu_mask) ) > goto unlock; > > irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); > @@ -653,7 +666,7 @@ fastcall void smp_irq_move_cleanup_inter > if ( desc->arch.move_cleanup_count == 0 ) > { > desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; > - cpumask_clear(&desc->arch.old_cpu_mask); > + cpumask_clear(desc->arch.old_cpu_mask); > > if ( desc->arch.used_vectors ) > { > @@ -673,7 +686,7 @@ static void send_cleanup_vector(struct i > { > cpumask_t cleanup_mask; > > - cpumask_and(&cleanup_mask, &desc->arch.old_cpu_mask, &cpu_online_map); > + cpumask_and(&cleanup_mask, desc->arch.old_cpu_mask, &cpu_online_map); > desc->arch.move_cleanup_count = cpumask_weight(&cleanup_mask); > genapic->send_IPI_mask(&cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); > > @@ -690,7 +703,8 @@ void irq_complete_move(struct irq_desc * > vector = get_irq_regs()->entry_vector; > me = smp_processor_id(); > > - if (vector == desc->arch.vector && cpumask_test_cpu(me, &desc->arch.cpu_mask)) > + if ( vector == desc->arch.vector && > + cpumask_test_cpu(me, desc->arch.cpu_mask) ) > send_cleanup_vector(desc); > } > > @@ -708,15 +722,15 @@ unsigned int set_desc_affinity(struct ir > > local_irq_save(flags); > lock_vector_lock(); > - ret = __assign_irq_vector(irq, &desc->arch, mask); > + ret = __assign_irq_vector(irq, desc, mask); > unlock_vector_lock(); > local_irq_restore(flags); > > if (ret < 0) > return BAD_APICID; > > - cpumask_copy(&desc->affinity, mask); > - cpumask_and(&dest_mask, mask, &desc->arch.cpu_mask); > + cpumask_copy(desc->affinity, mask); > + cpumask_and(&dest_mask, mask, desc->arch.cpu_mask); > > return cpu_mask_to_apicid(&dest_mask); > } > @@ -730,7 +744,7 @@ void irq_set_affinity(struct irq_desc *d > ASSERT(spin_is_locked(&desc->lock)); > desc->status &= ~IRQ_MOVE_PENDING; > wmb(); > - cpumask_copy(&desc->pending_mask, mask); > + cpumask_copy(desc->arch.pending_mask, mask); > wmb(); > desc->status |= IRQ_MOVE_PENDING; > } > @@ -1992,13 +2006,13 @@ static void dump_irqs(unsigned char key) > > desc = irq_to_desc(irq); > > - if ( !desc->handler || desc->handler == &no_irq_type ) > + if ( !irq_desc_initialized(desc) || desc->handler == &no_irq_type ) > continue; > > spin_lock_irqsave(&desc->lock, flags); > > cpumask_scnprintf(keyhandler_scratch, sizeof(keyhandler_scratch), > - &desc->affinity); > + desc->affinity); > printk(" IRQ:%4d affinity:%s vec:%02x type=%-15s" > " status=%08x ", > irq, keyhandler_scratch, desc->arch.vector, > @@ -2073,10 +2087,12 @@ void fixup_irqs(void) > continue; > > desc = irq_to_desc(irq); > + if ( !irq_desc_initialized(desc) ) > + continue; > > spin_lock(&desc->lock); > > - cpumask_copy(&affinity, &desc->affinity); > + cpumask_copy(&affinity, desc->affinity); > if ( !desc->action || cpumask_subset(&affinity, &cpu_online_map) ) > { > spin_unlock(&desc->lock); > --- a/xen/arch/x86/msi.c > +++ b/xen/arch/x86/msi.c > @@ -125,13 +125,13 @@ void msi_compose_msg(struct irq_desc *de > unsigned dest; > int vector = desc->arch.vector; > > - if ( cpumask_empty(&desc->arch.cpu_mask) ) { > + if ( cpumask_empty(desc->arch.cpu_mask) ) { > dprintk(XENLOG_ERR,"%s, compose msi message error!!\n", __func__); > return; > } > > if ( vector ) { > - dest = cpu_mask_to_apicid(&desc->arch.cpu_mask); > + dest = cpu_mask_to_apicid(desc->arch.cpu_mask); > > msg->address_hi = MSI_ADDR_BASE_HI; > msg->address_lo > --- a/xen/arch/x86/smpboot.c > +++ b/xen/arch/x86/smpboot.c > @@ -1011,7 +1011,7 @@ void __init smp_intr_init(void) > irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1; > per_cpu(vector_irq, cpu)[FIRST_HIPRIORITY_VECTOR + seridx + 1] = irq; > irq_to_desc(irq)->arch.vector = FIRST_HIPRIORITY_VECTOR + seridx + 1; > - cpumask_copy(&irq_to_desc(irq)->arch.cpu_mask, &cpu_online_map); > + cpumask_copy(irq_to_desc(irq)->arch.cpu_mask, &cpu_online_map); > } > > /* IPI for cleanuping vectors after irq move */ > --- a/xen/common/Makefile > +++ b/xen/common/Makefile > @@ -5,6 +5,7 @@ obj-y += domctl.o > obj-y += domain.o > obj-y += event_channel.o > obj-y += grant_table.o > +obj-y += irq.o > obj-y += kernel.o > obj-y += keyhandler.o > obj-y += kexec.o > --- /dev/null > +++ a/xen/common/irq.c > @@ -0,0 +1,28 @@ > +#include <xen/config.h> > +#include <xen/irq.h> > + > +int init_one_irq_desc(struct irq_desc *desc) > +{ > + int err; > + > + if (irq_desc_initialized(desc)) > + return 0; > + > + if ( !alloc_cpumask_var(&desc->affinity) ) > + return -ENOMEM; > + > + desc->status = IRQ_DISABLED; > + desc->handler = &no_irq_type; > + spin_lock_init(&desc->lock); > + cpumask_setall(desc->affinity); > + INIT_LIST_HEAD(&desc->rl_link); > + > + err = arch_init_one_irq_desc(desc); > + if ( err ) > + { > + free_cpumask_var(desc->affinity); > + desc->handler = NULL; > + } > + > + return err; > +} > --- a/xen/drivers/passthrough/vtd/iommu.c > +++ b/xen/drivers/passthrough/vtd/iommu.c > @@ -1965,17 +1965,18 @@ static int init_vtd_hw(void) > struct iommu_flush *flush = NULL; > int ret; > unsigned long flags; > - struct irq_cfg *cfg; > > /* > * Basic VT-d HW init: set VT-d interrupt, clear VT-d faults. > */ > for_each_drhd_unit ( drhd ) > { > + struct irq_desc *desc; > + > iommu = drhd->iommu; > > - cfg = irq_cfg(iommu->irq); > - dma_msi_set_affinity(irq_to_desc(iommu->irq), &cfg->cpu_mask); > + desc = irq_to_desc(iommu->irq); > + dma_msi_set_affinity(desc, desc->arch.cpu_mask); > > clear_fault_bits(iommu); > > --- a/xen/include/asm-ia64/linux-xen/asm/irq.h > +++ b/xen/include/asm-ia64/linux-xen/asm/irq.h > @@ -18,8 +18,10 @@ > struct irq_cfg { > #define arch_irq_desc irq_cfg > int vector; > - cpumask_t cpu_mask; > + cpumask_var_t cpu_mask; > }; > + > +int init_irq_data(void); > #endif > > static __inline__ int > --- a/xen/include/asm-x86/irq.h > +++ b/xen/include/asm-x86/irq.h > @@ -33,8 +33,9 @@ struct irq_cfg { > #define arch_irq_desc irq_cfg > s16 vector; /* vector itself is only 8 bits, */ > s16 old_vector; /* but we use -1 for unassigned */ > - cpumask_t cpu_mask; > - cpumask_t old_cpu_mask; > + cpumask_var_t cpu_mask; > + cpumask_var_t old_cpu_mask; > + cpumask_var_t pending_mask; > unsigned move_cleanup_count; > vmask_t *used_vectors; > u8 move_in_progress : 1; > @@ -174,8 +175,6 @@ void __setup_vector_irq(int cpu); > void move_native_irq(struct irq_desc *); > void move_masked_irq(struct irq_desc *); > > -int __assign_irq_vector(int irq, struct irq_cfg *, const cpumask_t *); > - > int bind_irq_vector(int irq, int vector, const cpumask_t *); > > void irq_set_affinity(struct irq_desc *, const cpumask_t *mask); > --- a/xen/include/xen/irq.h > +++ b/xen/include/xen/irq.h > @@ -76,8 +76,7 @@ typedef struct irq_desc { > int irq; > spinlock_t lock; > struct arch_irq_desc arch; > - cpumask_t affinity; > - cpumask_t pending_mask; /* IRQ migration pending mask */ > + cpumask_var_t affinity; > > /* irq ratelimit */ > s_time_t rl_quantum_start; > @@ -85,6 +84,11 @@ typedef struct irq_desc { > struct list_head rl_link; > } __cacheline_aligned irq_desc_t; > > +int init_one_irq_desc(struct irq_desc *); > +int arch_init_one_irq_desc(struct irq_desc *); > + > +#define irq_desc_initialized(desc) ((desc)->handler != NULL) > + > #if defined(__ia64__) > extern irq_desc_t irq_desc[NR_VECTORS]; > > @@ -153,7 +157,7 @@ extern irq_desc_t *pirq_spin_lock_irq_de > > static inline void set_native_irq_info(unsigned int irq, const cpumask_t *mask) > { > - cpumask_copy(&irq_desc[irq].affinity, mask); > + cpumask_copy(irq_to_desc(irq)->affinity, mask); > } > > unsigned int set_desc_affinity(struct irq_desc *, const cpumask_t *); > >-- Andrew Cooper - Dom0 Kernel Engineer, Citrix XenServer T: +44 (0)1223 225 900, http://www.citrix.com _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-03 15:17 UTC
Re: [Xen-devel] [PATCH 1/2] IRQ: allocate CPU masks dynamically
>>> On 03.11.11 at 15:49, Andrew Cooper <andrew.cooper3@citrix.com> wrote: > On 03/11/11 14:26, Jan Beulich wrote: >> IRQ: allocate CPU masks dynamically >> >> This includes delaying the initialization of dynamically created IRQs >> until their actual first use and some further elimination of uses of >> struct irq_cfg. >> >> Signed-off-by: Jan Beulich <jbeulich@suse.com> > > Acked-by: Andrew Cooper <andrew.cooper3@citrix.com> > > One query which may or may not affect the patch. Would we get better > caching characteristics if all cpumasks were allocated in consecutive > memory, rather than having 3 individual allocs in arch_init_one_irq_desc ?That was what the first version of the patch did, rejected by Keir (and not liked too much by me either). Jan>> --- a/xen/arch/ia64/linux-xen/irq_ia64.c >> +++ b/xen/arch/ia64/linux-xen/irq_ia64.c >> @@ -303,6 +303,9 @@ int __init request_irq_vector(unsigned i >> void __init >> init_IRQ (void) >> { >> +#ifdef XEN >> + BUG_ON(init_irq_data()); >> +#endif >> register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); >> #ifdef CONFIG_SMP >> register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); >> --- a/xen/arch/ia64/xen/irq.c >> +++ b/xen/arch/ia64/xen/irq.c >> @@ -74,17 +74,30 @@ unsigned int __ia64_local_vector_to_irq >> /* >> * Controller mappings for all interrupt sources: >> */ >> -irq_desc_t irq_desc[NR_IRQS] = { >> - [0 ... NR_IRQS-1] = { >> - .status = IRQ_DISABLED, >> - .handler = &no_irq_type, >> - .lock = SPIN_LOCK_UNLOCKED >> - .arch = { >> - .vector = -1, >> - .cpu_mask = CPU_MASK_ALL, >> - } >> +irq_desc_t irq_desc[NR_IRQS]; >> + >> +int __init arch_init_one_irq_desc(struct irq_desc *desc) >> +{ >> + if (!alloc_cpumask_var(&desc->arch.cpu_mask)) >> + return -ENOMEM; >> + >> + desc->arch.vector = -1; >> + cpumask_setall(desc->arch.cpu_mask); >> + >> + return 0; >> +} >> + >> +int __init init_irq_data(void) >> +{ >> + unsigned int irq; >> + >> + for (irq = 0; irq < NR_IRQS; irq++) { >> + struct irq_desc *desc = irq_to_desc(irq); >> + >> + desc->irq = irq; >> + init_one_irq_desc(desc); >> } >> -}; >> +} >> >> void __do_IRQ_guest(int irq); >> >> --- a/xen/arch/x86/i8259.c >> +++ b/xen/arch/x86/i8259.c >> @@ -398,7 +398,7 @@ void __init init_IRQ(void) >> >> desc->handler = &i8259A_irq_type; >> per_cpu(vector_irq, cpu)[FIRST_LEGACY_VECTOR + irq] = irq; >> - cpumask_copy(&desc->arch.cpu_mask, cpumask_of(cpu)); >> + cpumask_copy(desc->arch.cpu_mask, cpumask_of(cpu)); >> desc->arch.vector = FIRST_LEGACY_VECTOR + irq; >> } >> >> --- a/xen/arch/x86/io_apic.c >> +++ b/xen/arch/x86/io_apic.c >> @@ -648,20 +648,21 @@ static int pin_2_irq(int idx, int apic, >> void /*__init*/ setup_ioapic_dest(void) >> { >> int pin, ioapic, irq, irq_entry; >> - struct irq_cfg *cfg; >> >> if (skip_ioapic_setup) >> return; >> >> for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { >> for (pin = 0; pin < nr_ioapic_entries[ioapic]; pin++) { >> + struct irq_desc *desc; >> + >> irq_entry = find_irq_entry(ioapic, pin, mp_INT); >> if (irq_entry == -1) >> continue; >> irq = pin_2_irq(irq_entry, ioapic, pin); >> - cfg = irq_cfg(irq); >> - BUG_ON(cpus_empty(cfg->cpu_mask)); >> - set_ioapic_affinity_irq(irq_to_desc(irq), &cfg->cpu_mask); >> + desc = irq_to_desc(irq); >> + BUG_ON(cpumask_empty(desc->arch.cpu_mask)); >> + set_ioapic_affinity_irq(desc, desc->arch.cpu_mask); >> } >> >> } >> @@ -956,12 +957,12 @@ static void __init setup_IO_APIC_irqs(vo >> struct IO_APIC_route_entry entry; >> int apic, pin, idx, irq, first_notcon = 1, vector; >> unsigned long flags; >> - struct irq_cfg *cfg; >> >> apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); >> >> for (apic = 0; apic < nr_ioapics; apic++) { >> for (pin = 0; pin < nr_ioapic_entries[apic]; pin++) { >> + struct irq_desc *desc; >> >> /* >> * add it to the IO-APIC irq-routing table: >> @@ -1016,9 +1017,9 @@ static void __init setup_IO_APIC_irqs(vo >> if (!apic && platform_legacy_irq(irq)) >> disable_8259A_irq(irq_to_desc(irq)); >> } >> - cfg = irq_cfg(irq); >> + desc = irq_to_desc(irq); >> SET_DEST(entry.dest.dest32, entry.dest.logical.logical_dest, >> - cpu_mask_to_apicid(&cfg->cpu_mask)); >> + cpu_mask_to_apicid(desc->arch.cpu_mask)); >> spin_lock_irqsave(&ioapic_lock, flags); >> __ioapic_write_entry(apic, pin, 0, entry); >> set_native_irq_info(irq, TARGET_CPUS); >> @@ -2372,7 +2373,7 @@ int ioapic_guest_write(unsigned long phy >> rte.vector = cfg->vector; >> >> SET_DEST(rte.dest.dest32, rte.dest.logical.logical_dest, >> - cpu_mask_to_apicid(&cfg->cpu_mask)); >> + cpu_mask_to_apicid(desc->arch.cpu_mask)); >> >> io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0)); >> io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1)); >> --- a/xen/arch/x86/irq.c >> +++ b/xen/arch/x86/irq.c >> @@ -25,6 +25,7 @@ >> #include <public/physdev.h> >> >> static void parse_irq_vector_map_param(char *s); >> +static int __assign_irq_vector(int irq, struct irq_desc *, const cpumask_t > *); >> >> /* opt_noirqbalance: If true, software IRQ balancing/affinity is disabled. > */ >> bool_t __read_mostly opt_noirqbalance = 0; >> @@ -110,7 +111,7 @@ static int __init __bind_irq_vector(int >> { >> cpumask_t online_mask; >> int cpu; >> - struct irq_cfg *cfg = irq_cfg(irq); >> + struct irq_desc *desc = irq_to_desc(irq); >> >> BUG_ON((unsigned)irq >= nr_irqs); >> BUG_ON((unsigned)vector >= NR_VECTORS); >> @@ -118,21 +119,22 @@ static int __init __bind_irq_vector(int >> cpumask_and(&online_mask, cpu_mask, &cpu_online_map); >> if (cpumask_empty(&online_mask)) >> return -EINVAL; >> - if ((cfg->vector == vector) && cpumask_equal(&cfg->cpu_mask, &online_mask)) >> + if ( (desc->arch.vector == vector) && >> + cpumask_equal(desc->arch.cpu_mask, &online_mask) ) >> return 0; >> - if (cfg->vector != IRQ_VECTOR_UNASSIGNED) >> + if ( desc->arch.vector != IRQ_VECTOR_UNASSIGNED ) >> return -EBUSY; >> trace_irq_mask(TRC_HW_IRQ_BIND_VECTOR, irq, vector, &online_mask); >> for_each_cpu_mask(cpu, online_mask) >> per_cpu(vector_irq, cpu)[vector] = irq; >> - cfg->vector = vector; >> - cpumask_copy(&cfg->cpu_mask, &online_mask); >> - if ( cfg->used_vectors ) >> + desc->arch.vector = vector; >> + cpumask_copy(desc->arch.cpu_mask, &online_mask); >> + if ( desc->arch.used_vectors ) >> { >> - ASSERT(!test_bit(vector, cfg->used_vectors)); >> - set_bit(vector, cfg->used_vectors); >> + ASSERT(!test_bit(vector, desc->arch.used_vectors)); >> + set_bit(vector, desc->arch.used_vectors); >> } >> - cfg->used = IRQ_USED; >> + desc->arch.used = IRQ_USED; >> if (IO_APIC_IRQ(irq)) >> irq_vector[irq] = vector; >> return 0; >> @@ -166,14 +168,17 @@ int create_irq(void) >> { >> unsigned long flags; >> int irq, ret; >> - irq = -ENOSPC; >> + struct irq_desc *desc; >> >> spin_lock_irqsave(&vector_lock, flags); >> >> irq = find_unassigned_irq(); >> if (irq < 0) >> goto out; >> - ret = __assign_irq_vector(irq, irq_cfg(irq), TARGET_CPUS); >> + desc = irq_to_desc(irq); >> + ret = init_one_irq_desc(desc); >> + if (!ret) >> + ret = __assign_irq_vector(irq, desc, TARGET_CPUS); >> if (ret < 0) >> irq = ret; >> out: >> @@ -197,7 +202,7 @@ static void dynamic_irq_cleanup(unsigned >> desc->msi_desc = NULL; >> desc->handler = &no_irq_type; >> desc->arch.used_vectors = NULL; >> - cpumask_setall(&desc->affinity); >> + cpumask_setall(desc->affinity); >> spin_unlock_irqrestore(&desc->lock, flags); >> >> /* Wait to make sure it''s not being used on another CPU */ >> @@ -211,38 +216,38 @@ static void __clear_irq_vector(int irq) >> { >> int cpu, vector, old_vector; >> cpumask_t tmp_mask; >> - struct irq_cfg *cfg = irq_cfg(irq); >> + struct irq_desc *desc = irq_to_desc(irq); >> >> - BUG_ON(!cfg->vector); >> + BUG_ON(!desc->arch.vector); >> >> - /* Always clear cfg->vector */ >> - vector = cfg->vector; >> - cpumask_and(&tmp_mask, &cfg->cpu_mask, &cpu_online_map); >> + /* Always clear desc->arch.vector */ >> + vector = desc->arch.vector; >> + cpumask_and(&tmp_mask, desc->arch.cpu_mask, &cpu_online_map); >> >> for_each_cpu_mask(cpu, tmp_mask) { >> ASSERT( per_cpu(vector_irq, cpu)[vector] == irq ); >> per_cpu(vector_irq, cpu)[vector] = -1; >> } >> >> - cfg->vector = IRQ_VECTOR_UNASSIGNED; >> - cpumask_clear(&cfg->cpu_mask); >> + desc->arch.vector = IRQ_VECTOR_UNASSIGNED; >> + cpumask_clear(desc->arch.cpu_mask); >> >> - if ( cfg->used_vectors ) >> + if ( desc->arch.used_vectors ) >> { >> - ASSERT(test_bit(vector, cfg->used_vectors)); >> - clear_bit(vector, cfg->used_vectors); >> + ASSERT(test_bit(vector, desc->arch.used_vectors)); >> + clear_bit(vector, desc->arch.used_vectors); >> } >> >> - cfg->used = IRQ_UNUSED; >> + desc->arch.used = IRQ_UNUSED; >> >> trace_irq_mask(TRC_HW_IRQ_CLEAR_VECTOR, irq, vector, &tmp_mask); >> >> - if (likely(!cfg->move_in_progress)) >> + if ( likely(!desc->arch.move_in_progress) ) >> return; >> >> - /* If we were in motion, also clear cfg->old_vector */ >> - old_vector = cfg->old_vector; >> - cpumask_and(&tmp_mask, &cfg->old_cpu_mask, &cpu_online_map); >> + /* If we were in motion, also clear desc->arch.old_vector */ >> + old_vector = desc->arch.old_vector; >> + cpumask_and(&tmp_mask, desc->arch.old_cpu_mask, &cpu_online_map); >> >> for_each_cpu_mask(cpu, tmp_mask) { >> ASSERT( per_cpu(vector_irq, cpu)[old_vector] == irq ); >> @@ -250,16 +255,16 @@ static void __clear_irq_vector(int irq) >> per_cpu(vector_irq, cpu)[old_vector] = -1; >> } >> >> - cfg->old_vector = IRQ_VECTOR_UNASSIGNED; >> - cpumask_clear(&cfg->old_cpu_mask); >> + desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; >> + cpumask_clear(desc->arch.old_cpu_mask); >> >> - if ( cfg->used_vectors ) >> + if ( desc->arch.used_vectors ) >> { >> - ASSERT(test_bit(old_vector, cfg->used_vectors)); >> - clear_bit(old_vector, cfg->used_vectors); >> + ASSERT(test_bit(old_vector, desc->arch.used_vectors)); >> + clear_bit(old_vector, desc->arch.used_vectors); >> } >> >> - cfg->move_in_progress = 0; >> + desc->arch.move_in_progress = 0; >> } >> >> void clear_irq_vector(int irq) >> @@ -296,25 +301,28 @@ int irq_to_vector(int irq) >> return vector; >> } >> >> -static void __init init_one_irq_desc(struct irq_desc *desc) >> +int arch_init_one_irq_desc(struct irq_desc *desc) >> { >> - desc->status = IRQ_DISABLED; >> - desc->handler = &no_irq_type; >> - desc->action = NULL; >> - desc->msi_desc = NULL; >> - spin_lock_init(&desc->lock); >> - cpumask_setall(&desc->affinity); >> - INIT_LIST_HEAD(&desc->rl_link); >> -} >> + if ( !zalloc_cpumask_var(&desc->arch.cpu_mask) ) >> + return -ENOMEM; >> + >> + if ( !alloc_cpumask_var(&desc->arch.old_cpu_mask) ) >> + { >> + free_cpumask_var(desc->arch.cpu_mask); >> + return -ENOMEM; >> + } >> >> -static void __init init_one_irq_cfg(struct irq_cfg *cfg) >> -{ >> - cfg->vector = IRQ_VECTOR_UNASSIGNED; >> - cfg->old_vector = IRQ_VECTOR_UNASSIGNED; >> - cpumask_clear(&cfg->cpu_mask); >> - cpumask_clear(&cfg->old_cpu_mask); >> - cfg->used_vectors = NULL; >> - cfg->used = IRQ_UNUSED; >> + if ( !alloc_cpumask_var(&desc->arch.pending_mask) ) >> + { >> + free_cpumask_var(desc->arch.old_cpu_mask); >> + free_cpumask_var(desc->arch.cpu_mask); >> + return -ENOMEM; >> + } >> + >> + desc->arch.vector = IRQ_VECTOR_UNASSIGNED; >> + desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; >> + >> + return 0; >> } >> >> int __init init_irq_data(void) >> @@ -331,12 +339,13 @@ int __init init_irq_data(void) >> if ( !irq_desc || !irq_vector ) >> return -ENOMEM; >> >> - for (irq = 0; irq < nr_irqs; irq++) { >> + for (irq = 0; irq < nr_irqs_gsi; irq++) { >> desc = irq_to_desc(irq); >> desc->irq = irq; >> init_one_irq_desc(desc); >> - init_one_irq_cfg(&desc->arch); >> } >> + for (; irq < nr_irqs; irq++) >> + irq_to_desc(irq)->irq = irq; >> >> /* Never allocate the hypercall vector or Linux/BSD fast-trap vector. */ >> set_bit(LEGACY_SYSCALL_VECTOR, used_vectors); >> @@ -403,7 +412,8 @@ static vmask_t *irq_get_used_vector_mask >> return ret; >> } >> >> -int __assign_irq_vector(int irq, struct irq_cfg *cfg, const cpumask_t *mask) >> +static int __assign_irq_vector( >> + int irq, struct irq_desc *desc, const cpumask_t *mask) >> { >> /* >> * NOTE! The local APIC isn''t very good at handling >> @@ -426,13 +436,13 @@ int __assign_irq_vector(int irq, struct >> old_vector = irq_to_vector(irq); >> if (old_vector) { >> cpumask_and(&tmp_mask, mask, &cpu_online_map); >> - if (cpumask_intersects(&tmp_mask, &cfg->cpu_mask)) { >> - cfg->vector = old_vector; >> + if (cpumask_intersects(&tmp_mask, desc->arch.cpu_mask)) { >> + desc->arch.vector = old_vector; >> return 0; >> } >> } >> >> - if ((cfg->move_in_progress) || cfg->move_cleanup_count) >> + if ( desc->arch.move_in_progress || desc->arch.move_cleanup_count ) >> return -EAGAIN; >> >> err = -ENOSPC; >> @@ -440,9 +450,9 @@ int __assign_irq_vector(int irq, struct >> /* This is the only place normal IRQs are ever marked >> * as "in use". If they''re not in use yet, check to see >> * if we need to assign a global vector mask. */ >> - if ( cfg->used == IRQ_USED ) >> + if ( desc->arch.used == IRQ_USED ) >> { >> - irq_used_vectors = cfg->used_vectors; >> + irq_used_vectors = desc->arch.used_vectors; >> } >> else >> irq_used_vectors = irq_get_used_vector_mask(irq); >> @@ -485,29 +495,29 @@ next: >> current_offset = offset; >> local_irq_save(flags); >> if (old_vector) { >> - cfg->move_in_progress = 1; >> - cpumask_copy(&cfg->old_cpu_mask, &cfg->cpu_mask); >> - cfg->old_vector = cfg->vector; >> + desc->arch.move_in_progress = 1; >> + cpumask_copy(desc->arch.old_cpu_mask, desc->arch.cpu_mask); >> + desc->arch.old_vector = desc->arch.vector; >> } >> trace_irq_mask(TRC_HW_IRQ_ASSIGN_VECTOR, irq, vector, &tmp_mask); >> for_each_cpu_mask(new_cpu, tmp_mask) >> per_cpu(vector_irq, new_cpu)[vector] = irq; >> - cfg->vector = vector; >> - cpumask_copy(&cfg->cpu_mask, &tmp_mask); >> + desc->arch.vector = vector; >> + cpumask_copy(desc->arch.cpu_mask, &tmp_mask); >> >> - cfg->used = IRQ_USED; >> - ASSERT((cfg->used_vectors == NULL) >> - || (cfg->used_vectors == irq_used_vectors)); >> - cfg->used_vectors = irq_used_vectors; >> + desc->arch.used = IRQ_USED; >> + ASSERT((desc->arch.used_vectors == NULL) >> + || (desc->arch.used_vectors == irq_used_vectors)); >> + desc->arch.used_vectors = irq_used_vectors; >> >> if (IO_APIC_IRQ(irq)) >> irq_vector[irq] = vector; >> >> - if ( cfg->used_vectors ) >> + if ( desc->arch.used_vectors ) >> { >> - ASSERT(!test_bit(vector, cfg->used_vectors)); >> + ASSERT(!test_bit(vector, desc->arch.used_vectors)); >> >> - set_bit(vector, cfg->used_vectors); >> + set_bit(vector, desc->arch.used_vectors); >> } >> >> err = 0; >> @@ -521,16 +531,15 @@ int assign_irq_vector(int irq) >> { >> int ret; >> unsigned long flags; >> - struct irq_cfg *cfg = irq_cfg(irq); >> struct irq_desc *desc = irq_to_desc(irq); >> >> BUG_ON(irq >= nr_irqs || irq <0); >> >> spin_lock_irqsave(&vector_lock, flags); >> - ret = __assign_irq_vector(irq, cfg, TARGET_CPUS); >> + ret = __assign_irq_vector(irq, desc, TARGET_CPUS); >> if (!ret) { >> - ret = cfg->vector; >> - cpumask_copy(&desc->affinity, &cfg->cpu_mask); >> + ret = desc->arch.vector; >> + cpumask_copy(desc->affinity, desc->arch.cpu_mask); >> } >> spin_unlock_irqrestore(&vector_lock, flags); >> return ret; >> @@ -543,15 +552,16 @@ int assign_irq_vector(int irq) >> void __setup_vector_irq(int cpu) >> { >> int irq, vector; >> - struct irq_cfg *cfg; >> >> /* Clear vector_irq */ >> for (vector = 0; vector < NR_VECTORS; ++vector) >> per_cpu(vector_irq, cpu)[vector] = -1; >> /* Mark the inuse vectors */ >> for (irq = 0; irq < nr_irqs; ++irq) { >> - cfg = irq_cfg(irq); >> - if (!cpu_isset(cpu, cfg->cpu_mask)) >> + struct irq_desc *desc = irq_to_desc(irq); >> + >> + if (!irq_desc_initialized(desc) || >> + !cpumask_test_cpu(cpu, desc->arch.cpu_mask)) >> continue; >> vector = irq_to_vector(irq); >> per_cpu(vector_irq, cpu)[vector] = irq; >> @@ -560,12 +570,14 @@ void __setup_vector_irq(int cpu) >> >> void move_masked_irq(struct irq_desc *desc) >> { >> + cpumask_t *pending_mask = desc->arch.pending_mask; >> + >> if (likely(!(desc->status & IRQ_MOVE_PENDING))) >> return; >> >> desc->status &= ~IRQ_MOVE_PENDING; >> >> - if (unlikely(cpus_empty(desc->pending_mask))) >> + if (unlikely(cpumask_empty(pending_mask))) >> return; >> >> if (!desc->handler->set_affinity) >> @@ -580,10 +592,10 @@ void move_masked_irq(struct irq_desc *de >> * >> * For correct operation this depends on the caller masking the irqs. >> */ >> - if (likely(cpus_intersects(desc->pending_mask, cpu_online_map))) >> - desc->handler->set_affinity(desc, &desc->pending_mask); >> + if ( likely(cpumask_intersects(pending_mask, &cpu_online_map)) ) >> + desc->handler->set_affinity(desc, pending_mask); >> >> - cpumask_clear(&desc->pending_mask); >> + cpumask_clear(pending_mask); >> } >> >> void move_native_irq(struct irq_desc *desc) >> @@ -626,7 +638,8 @@ fastcall void smp_irq_move_cleanup_inter >> if (!desc->arch.move_cleanup_count) >> goto unlock; >> >> - if (vector == desc->arch.vector && cpumask_test_cpu(me, > &desc->arch.cpu_mask)) >> + if ( vector == desc->arch.vector && >> + cpumask_test_cpu(me, desc->arch.cpu_mask) ) >> goto unlock; >> >> irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); >> @@ -653,7 +666,7 @@ fastcall void smp_irq_move_cleanup_inter >> if ( desc->arch.move_cleanup_count == 0 ) >> { >> desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; >> - cpumask_clear(&desc->arch.old_cpu_mask); >> + cpumask_clear(desc->arch.old_cpu_mask); >> >> if ( desc->arch.used_vectors ) >> { >> @@ -673,7 +686,7 @@ static void send_cleanup_vector(struct i >> { >> cpumask_t cleanup_mask; >> >> - cpumask_and(&cleanup_mask, &desc->arch.old_cpu_mask, &cpu_online_map); >> + cpumask_and(&cleanup_mask, desc->arch.old_cpu_mask, &cpu_online_map); >> desc->arch.move_cleanup_count = cpumask_weight(&cleanup_mask); >> genapic->send_IPI_mask(&cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); >> >> @@ -690,7 +703,8 @@ void irq_complete_move(struct irq_desc * >> vector = get_irq_regs()->entry_vector; >> me = smp_processor_id(); >> >> - if (vector == desc->arch.vector && cpumask_test_cpu(me, &desc->arch.cpu_mask)) >> + if ( vector == desc->arch.vector && >> + cpumask_test_cpu(me, desc->arch.cpu_mask) ) >> send_cleanup_vector(desc); >> } >> >> @@ -708,15 +722,15 @@ unsigned int set_desc_affinity(struct ir >> >> local_irq_save(flags); >> lock_vector_lock(); >> - ret = __assign_irq_vector(irq, &desc->arch, mask); >> + ret = __assign_irq_vector(irq, desc, mask); >> unlock_vector_lock(); >> local_irq_restore(flags); >> >> if (ret < 0) >> return BAD_APICID; >> >> - cpumask_copy(&desc->affinity, mask); >> - cpumask_and(&dest_mask, mask, &desc->arch.cpu_mask); >> + cpumask_copy(desc->affinity, mask); >> + cpumask_and(&dest_mask, mask, desc->arch.cpu_mask); >> >> return cpu_mask_to_apicid(&dest_mask); >> } >> @@ -730,7 +744,7 @@ void irq_set_affinity(struct irq_desc *d >> ASSERT(spin_is_locked(&desc->lock)); >> desc->status &= ~IRQ_MOVE_PENDING; >> wmb(); >> - cpumask_copy(&desc->pending_mask, mask); >> + cpumask_copy(desc->arch.pending_mask, mask); >> wmb(); >> desc->status |= IRQ_MOVE_PENDING; >> } >> @@ -1992,13 +2006,13 @@ static void dump_irqs(unsigned char key) >> >> desc = irq_to_desc(irq); >> >> - if ( !desc->handler || desc->handler == &no_irq_type ) >> + if ( !irq_desc_initialized(desc) || desc->handler == &no_irq_type ) >> continue; >> >> spin_lock_irqsave(&desc->lock, flags); >> >> cpumask_scnprintf(keyhandler_scratch, sizeof(keyhandler_scratch), >> - &desc->affinity); >> + desc->affinity); >> printk(" IRQ:%4d affinity:%s vec:%02x type=%-15s" >> " status=%08x ", >> irq, keyhandler_scratch, desc->arch.vector, >> @@ -2073,10 +2087,12 @@ void fixup_irqs(void) >> continue; >> >> desc = irq_to_desc(irq); >> + if ( !irq_desc_initialized(desc) ) >> + continue; >> >> spin_lock(&desc->lock); >> >> - cpumask_copy(&affinity, &desc->affinity); >> + cpumask_copy(&affinity, desc->affinity); >> if ( !desc->action || cpumask_subset(&affinity, &cpu_online_map) ) >> { >> spin_unlock(&desc->lock); >> --- a/xen/arch/x86/msi.c >> +++ b/xen/arch/x86/msi.c >> @@ -125,13 +125,13 @@ void msi_compose_msg(struct irq_desc *de >> unsigned dest; >> int vector = desc->arch.vector; >> >> - if ( cpumask_empty(&desc->arch.cpu_mask) ) { >> + if ( cpumask_empty(desc->arch.cpu_mask) ) { >> dprintk(XENLOG_ERR,"%s, compose msi message error!!\n", __func__); >> return; >> } >> >> if ( vector ) { >> - dest = cpu_mask_to_apicid(&desc->arch.cpu_mask); >> + dest = cpu_mask_to_apicid(desc->arch.cpu_mask); >> >> msg->address_hi = MSI_ADDR_BASE_HI; >> msg->address_lo >> --- a/xen/arch/x86/smpboot.c >> +++ b/xen/arch/x86/smpboot.c >> @@ -1011,7 +1011,7 @@ void __init smp_intr_init(void) >> irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1; >> per_cpu(vector_irq, cpu)[FIRST_HIPRIORITY_VECTOR + seridx + 1] = > irq; >> irq_to_desc(irq)->arch.vector = FIRST_HIPRIORITY_VECTOR + seridx + 1; >> - cpumask_copy(&irq_to_desc(irq)->arch.cpu_mask, &cpu_online_map); >> + cpumask_copy(irq_to_desc(irq)->arch.cpu_mask, &cpu_online_map); >> } >> >> /* IPI for cleanuping vectors after irq move */ >> --- a/xen/common/Makefile >> +++ b/xen/common/Makefile >> @@ -5,6 +5,7 @@ obj-y += domctl.o >> obj-y += domain.o >> obj-y += event_channel.o >> obj-y += grant_table.o >> +obj-y += irq.o >> obj-y += kernel.o >> obj-y += keyhandler.o >> obj-y += kexec.o >> --- /dev/null >> +++ a/xen/common/irq.c >> @@ -0,0 +1,28 @@ >> +#include <xen/config.h> >> +#include <xen/irq.h> >> + >> +int init_one_irq_desc(struct irq_desc *desc) >> +{ >> + int err; >> + >> + if (irq_desc_initialized(desc)) >> + return 0; >> + >> + if ( !alloc_cpumask_var(&desc->affinity) ) >> + return -ENOMEM; >> + >> + desc->status = IRQ_DISABLED; >> + desc->handler = &no_irq_type; >> + spin_lock_init(&desc->lock); >> + cpumask_setall(desc->affinity); >> + INIT_LIST_HEAD(&desc->rl_link); >> + >> + err = arch_init_one_irq_desc(desc); >> + if ( err ) >> + { >> + free_cpumask_var(desc->affinity); >> + desc->handler = NULL; >> + } >> + >> + return err; >> +} >> --- a/xen/drivers/passthrough/vtd/iommu.c >> +++ b/xen/drivers/passthrough/vtd/iommu.c >> @@ -1965,17 +1965,18 @@ static int init_vtd_hw(void) >> struct iommu_flush *flush = NULL; >> int ret; >> unsigned long flags; >> - struct irq_cfg *cfg; >> >> /* >> * Basic VT-d HW init: set VT-d interrupt, clear VT-d faults. >> */ >> for_each_drhd_unit ( drhd ) >> { >> + struct irq_desc *desc; >> + >> iommu = drhd->iommu; >> >> - cfg = irq_cfg(iommu->irq); >> - dma_msi_set_affinity(irq_to_desc(iommu->irq), &cfg->cpu_mask); >> + desc = irq_to_desc(iommu->irq); >> + dma_msi_set_affinity(desc, desc->arch.cpu_mask); >> >> clear_fault_bits(iommu); >> >> --- a/xen/include/asm-ia64/linux-xen/asm/irq.h >> +++ b/xen/include/asm-ia64/linux-xen/asm/irq.h >> @@ -18,8 +18,10 @@ >> struct irq_cfg { >> #define arch_irq_desc irq_cfg >> int vector; >> - cpumask_t cpu_mask; >> + cpumask_var_t cpu_mask; >> }; >> + >> +int init_irq_data(void); >> #endif >> >> static __inline__ int >> --- a/xen/include/asm-x86/irq.h >> +++ b/xen/include/asm-x86/irq.h >> @@ -33,8 +33,9 @@ struct irq_cfg { >> #define arch_irq_desc irq_cfg >> s16 vector; /* vector itself is only 8 bits, */ >> s16 old_vector; /* but we use -1 for unassigned */ >> - cpumask_t cpu_mask; >> - cpumask_t old_cpu_mask; >> + cpumask_var_t cpu_mask; >> + cpumask_var_t old_cpu_mask; >> + cpumask_var_t pending_mask; >> unsigned move_cleanup_count; >> vmask_t *used_vectors; >> u8 move_in_progress : 1; >> @@ -174,8 +175,6 @@ void __setup_vector_irq(int cpu); >> void move_native_irq(struct irq_desc *); >> void move_masked_irq(struct irq_desc *); >> >> -int __assign_irq_vector(int irq, struct irq_cfg *, const cpumask_t *); >> - >> int bind_irq_vector(int irq, int vector, const cpumask_t *); >> >> void irq_set_affinity(struct irq_desc *, const cpumask_t *mask); >> --- a/xen/include/xen/irq.h >> +++ b/xen/include/xen/irq.h >> @@ -76,8 +76,7 @@ typedef struct irq_desc { >> int irq; >> spinlock_t lock; >> struct arch_irq_desc arch; >> - cpumask_t affinity; >> - cpumask_t pending_mask; /* IRQ migration pending mask */ >> + cpumask_var_t affinity; >> >> /* irq ratelimit */ >> s_time_t rl_quantum_start; >> @@ -85,6 +84,11 @@ typedef struct irq_desc { >> struct list_head rl_link; >> } __cacheline_aligned irq_desc_t; >> >> +int init_one_irq_desc(struct irq_desc *); >> +int arch_init_one_irq_desc(struct irq_desc *); >> + >> +#define irq_desc_initialized(desc) ((desc)->handler != NULL) >> + >> #if defined(__ia64__) >> extern irq_desc_t irq_desc[NR_VECTORS]; >> >> @@ -153,7 +157,7 @@ extern irq_desc_t *pirq_spin_lock_irq_de >> >> static inline void set_native_irq_info(unsigned int irq, const cpumask_t > *mask) >> { >> - cpumask_copy(&irq_desc[irq].affinity, mask); >> + cpumask_copy(irq_to_desc(irq)->affinity, mask); >> } >> >> unsigned int set_desc_affinity(struct irq_desc *, const cpumask_t *); >> >>_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Andrew Cooper
2011-Nov-03 15:43 UTC
Re: [Xen-devel] [PATCH 1/2] IRQ: allocate CPU masks dynamically
On 03/11/11 15:17, Jan Beulich wrote:>>>> On 03.11.11 at 15:49, Andrew Cooper <andrew.cooper3@citrix.com> wrote: >> On 03/11/11 14:26, Jan Beulich wrote: >>> IRQ: allocate CPU masks dynamically >>> >>> This includes delaying the initialization of dynamically created IRQs >>> until their actual first use and some further elimination of uses of >>> struct irq_cfg. >>> >>> Signed-off-by: Jan Beulich <jbeulich@suse.com> >> Acked-by: Andrew Cooper <andrew.cooper3@citrix.com> >> >> One query which may or may not affect the patch. Would we get better >> caching characteristics if all cpumasks were allocated in consecutive >> memory, rather than having 3 individual allocs in arch_init_one_irq_desc ? > That was what the first version of the patch did, rejected by Keir > (and not liked too much by me either). > > JanMy understanding of the objection was hiding the variables themselves as an array in the code. An alternative approach such as alloc''ing 3*sizeof(cpu mask) (cache aligned) and assigning the relevant pointers to the current cpumask_var_t''s would be a suitable approach which causes the cpumasks to be in contiguous memory, but not changing how they are referenced in the code. ~Andrew>>> --- a/xen/arch/ia64/linux-xen/irq_ia64.c >>> +++ b/xen/arch/ia64/linux-xen/irq_ia64.c >>> @@ -303,6 +303,9 @@ int __init request_irq_vector(unsigned i >>> void __init >>> init_IRQ (void) >>> { >>> +#ifdef XEN >>> + BUG_ON(init_irq_data()); >>> +#endif >>> register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); >>> #ifdef CONFIG_SMP >>> register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); >>> --- a/xen/arch/ia64/xen/irq.c >>> +++ b/xen/arch/ia64/xen/irq.c >>> @@ -74,17 +74,30 @@ unsigned int __ia64_local_vector_to_irq >>> /* >>> * Controller mappings for all interrupt sources: >>> */ >>> -irq_desc_t irq_desc[NR_IRQS] = { >>> - [0 ... NR_IRQS-1] = { >>> - .status = IRQ_DISABLED, >>> - .handler = &no_irq_type, >>> - .lock = SPIN_LOCK_UNLOCKED >>> - .arch = { >>> - .vector = -1, >>> - .cpu_mask = CPU_MASK_ALL, >>> - } >>> +irq_desc_t irq_desc[NR_IRQS]; >>> + >>> +int __init arch_init_one_irq_desc(struct irq_desc *desc) >>> +{ >>> + if (!alloc_cpumask_var(&desc->arch.cpu_mask)) >>> + return -ENOMEM; >>> + >>> + desc->arch.vector = -1; >>> + cpumask_setall(desc->arch.cpu_mask); >>> + >>> + return 0; >>> +} >>> + >>> +int __init init_irq_data(void) >>> +{ >>> + unsigned int irq; >>> + >>> + for (irq = 0; irq < NR_IRQS; irq++) { >>> + struct irq_desc *desc = irq_to_desc(irq); >>> + >>> + desc->irq = irq; >>> + init_one_irq_desc(desc); >>> } >>> -}; >>> +} >>> >>> void __do_IRQ_guest(int irq); >>> >>> --- a/xen/arch/x86/i8259.c >>> +++ b/xen/arch/x86/i8259.c >>> @@ -398,7 +398,7 @@ void __init init_IRQ(void) >>> >>> desc->handler = &i8259A_irq_type; >>> per_cpu(vector_irq, cpu)[FIRST_LEGACY_VECTOR + irq] = irq; >>> - cpumask_copy(&desc->arch.cpu_mask, cpumask_of(cpu)); >>> + cpumask_copy(desc->arch.cpu_mask, cpumask_of(cpu)); >>> desc->arch.vector = FIRST_LEGACY_VECTOR + irq; >>> } >>> >>> --- a/xen/arch/x86/io_apic.c >>> +++ b/xen/arch/x86/io_apic.c >>> @@ -648,20 +648,21 @@ static int pin_2_irq(int idx, int apic, >>> void /*__init*/ setup_ioapic_dest(void) >>> { >>> int pin, ioapic, irq, irq_entry; >>> - struct irq_cfg *cfg; >>> >>> if (skip_ioapic_setup) >>> return; >>> >>> for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { >>> for (pin = 0; pin < nr_ioapic_entries[ioapic]; pin++) { >>> + struct irq_desc *desc; >>> + >>> irq_entry = find_irq_entry(ioapic, pin, mp_INT); >>> if (irq_entry == -1) >>> continue; >>> irq = pin_2_irq(irq_entry, ioapic, pin); >>> - cfg = irq_cfg(irq); >>> - BUG_ON(cpus_empty(cfg->cpu_mask)); >>> - set_ioapic_affinity_irq(irq_to_desc(irq), &cfg->cpu_mask); >>> + desc = irq_to_desc(irq); >>> + BUG_ON(cpumask_empty(desc->arch.cpu_mask)); >>> + set_ioapic_affinity_irq(desc, desc->arch.cpu_mask); >>> } >>> >>> } >>> @@ -956,12 +957,12 @@ static void __init setup_IO_APIC_irqs(vo >>> struct IO_APIC_route_entry entry; >>> int apic, pin, idx, irq, first_notcon = 1, vector; >>> unsigned long flags; >>> - struct irq_cfg *cfg; >>> >>> apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); >>> >>> for (apic = 0; apic < nr_ioapics; apic++) { >>> for (pin = 0; pin < nr_ioapic_entries[apic]; pin++) { >>> + struct irq_desc *desc; >>> >>> /* >>> * add it to the IO-APIC irq-routing table: >>> @@ -1016,9 +1017,9 @@ static void __init setup_IO_APIC_irqs(vo >>> if (!apic && platform_legacy_irq(irq)) >>> disable_8259A_irq(irq_to_desc(irq)); >>> } >>> - cfg = irq_cfg(irq); >>> + desc = irq_to_desc(irq); >>> SET_DEST(entry.dest.dest32, entry.dest.logical.logical_dest, >>> - cpu_mask_to_apicid(&cfg->cpu_mask)); >>> + cpu_mask_to_apicid(desc->arch.cpu_mask)); >>> spin_lock_irqsave(&ioapic_lock, flags); >>> __ioapic_write_entry(apic, pin, 0, entry); >>> set_native_irq_info(irq, TARGET_CPUS); >>> @@ -2372,7 +2373,7 @@ int ioapic_guest_write(unsigned long phy >>> rte.vector = cfg->vector; >>> >>> SET_DEST(rte.dest.dest32, rte.dest.logical.logical_dest, >>> - cpu_mask_to_apicid(&cfg->cpu_mask)); >>> + cpu_mask_to_apicid(desc->arch.cpu_mask)); >>> >>> io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0)); >>> io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1)); >>> --- a/xen/arch/x86/irq.c >>> +++ b/xen/arch/x86/irq.c >>> @@ -25,6 +25,7 @@ >>> #include <public/physdev.h> >>> >>> static void parse_irq_vector_map_param(char *s); >>> +static int __assign_irq_vector(int irq, struct irq_desc *, const cpumask_t >> *); >>> /* opt_noirqbalance: If true, software IRQ balancing/affinity is disabled. >> */ >>> bool_t __read_mostly opt_noirqbalance = 0; >>> @@ -110,7 +111,7 @@ static int __init __bind_irq_vector(int >>> { >>> cpumask_t online_mask; >>> int cpu; >>> - struct irq_cfg *cfg = irq_cfg(irq); >>> + struct irq_desc *desc = irq_to_desc(irq); >>> >>> BUG_ON((unsigned)irq >= nr_irqs); >>> BUG_ON((unsigned)vector >= NR_VECTORS); >>> @@ -118,21 +119,22 @@ static int __init __bind_irq_vector(int >>> cpumask_and(&online_mask, cpu_mask, &cpu_online_map); >>> if (cpumask_empty(&online_mask)) >>> return -EINVAL; >>> - if ((cfg->vector == vector) && cpumask_equal(&cfg->cpu_mask, &online_mask)) >>> + if ( (desc->arch.vector == vector) && >>> + cpumask_equal(desc->arch.cpu_mask, &online_mask) ) >>> return 0; >>> - if (cfg->vector != IRQ_VECTOR_UNASSIGNED) >>> + if ( desc->arch.vector != IRQ_VECTOR_UNASSIGNED ) >>> return -EBUSY; >>> trace_irq_mask(TRC_HW_IRQ_BIND_VECTOR, irq, vector, &online_mask); >>> for_each_cpu_mask(cpu, online_mask) >>> per_cpu(vector_irq, cpu)[vector] = irq; >>> - cfg->vector = vector; >>> - cpumask_copy(&cfg->cpu_mask, &online_mask); >>> - if ( cfg->used_vectors ) >>> + desc->arch.vector = vector; >>> + cpumask_copy(desc->arch.cpu_mask, &online_mask); >>> + if ( desc->arch.used_vectors ) >>> { >>> - ASSERT(!test_bit(vector, cfg->used_vectors)); >>> - set_bit(vector, cfg->used_vectors); >>> + ASSERT(!test_bit(vector, desc->arch.used_vectors)); >>> + set_bit(vector, desc->arch.used_vectors); >>> } >>> - cfg->used = IRQ_USED; >>> + desc->arch.used = IRQ_USED; >>> if (IO_APIC_IRQ(irq)) >>> irq_vector[irq] = vector; >>> return 0; >>> @@ -166,14 +168,17 @@ int create_irq(void) >>> { >>> unsigned long flags; >>> int irq, ret; >>> - irq = -ENOSPC; >>> + struct irq_desc *desc; >>> >>> spin_lock_irqsave(&vector_lock, flags); >>> >>> irq = find_unassigned_irq(); >>> if (irq < 0) >>> goto out; >>> - ret = __assign_irq_vector(irq, irq_cfg(irq), TARGET_CPUS); >>> + desc = irq_to_desc(irq); >>> + ret = init_one_irq_desc(desc); >>> + if (!ret) >>> + ret = __assign_irq_vector(irq, desc, TARGET_CPUS); >>> if (ret < 0) >>> irq = ret; >>> out: >>> @@ -197,7 +202,7 @@ static void dynamic_irq_cleanup(unsigned >>> desc->msi_desc = NULL; >>> desc->handler = &no_irq_type; >>> desc->arch.used_vectors = NULL; >>> - cpumask_setall(&desc->affinity); >>> + cpumask_setall(desc->affinity); >>> spin_unlock_irqrestore(&desc->lock, flags); >>> >>> /* Wait to make sure it''s not being used on another CPU */ >>> @@ -211,38 +216,38 @@ static void __clear_irq_vector(int irq) >>> { >>> int cpu, vector, old_vector; >>> cpumask_t tmp_mask; >>> - struct irq_cfg *cfg = irq_cfg(irq); >>> + struct irq_desc *desc = irq_to_desc(irq); >>> >>> - BUG_ON(!cfg->vector); >>> + BUG_ON(!desc->arch.vector); >>> >>> - /* Always clear cfg->vector */ >>> - vector = cfg->vector; >>> - cpumask_and(&tmp_mask, &cfg->cpu_mask, &cpu_online_map); >>> + /* Always clear desc->arch.vector */ >>> + vector = desc->arch.vector; >>> + cpumask_and(&tmp_mask, desc->arch.cpu_mask, &cpu_online_map); >>> >>> for_each_cpu_mask(cpu, tmp_mask) { >>> ASSERT( per_cpu(vector_irq, cpu)[vector] == irq ); >>> per_cpu(vector_irq, cpu)[vector] = -1; >>> } >>> >>> - cfg->vector = IRQ_VECTOR_UNASSIGNED; >>> - cpumask_clear(&cfg->cpu_mask); >>> + desc->arch.vector = IRQ_VECTOR_UNASSIGNED; >>> + cpumask_clear(desc->arch.cpu_mask); >>> >>> - if ( cfg->used_vectors ) >>> + if ( desc->arch.used_vectors ) >>> { >>> - ASSERT(test_bit(vector, cfg->used_vectors)); >>> - clear_bit(vector, cfg->used_vectors); >>> + ASSERT(test_bit(vector, desc->arch.used_vectors)); >>> + clear_bit(vector, desc->arch.used_vectors); >>> } >>> >>> - cfg->used = IRQ_UNUSED; >>> + desc->arch.used = IRQ_UNUSED; >>> >>> trace_irq_mask(TRC_HW_IRQ_CLEAR_VECTOR, irq, vector, &tmp_mask); >>> >>> - if (likely(!cfg->move_in_progress)) >>> + if ( likely(!desc->arch.move_in_progress) ) >>> return; >>> >>> - /* If we were in motion, also clear cfg->old_vector */ >>> - old_vector = cfg->old_vector; >>> - cpumask_and(&tmp_mask, &cfg->old_cpu_mask, &cpu_online_map); >>> + /* If we were in motion, also clear desc->arch.old_vector */ >>> + old_vector = desc->arch.old_vector; >>> + cpumask_and(&tmp_mask, desc->arch.old_cpu_mask, &cpu_online_map); >>> >>> for_each_cpu_mask(cpu, tmp_mask) { >>> ASSERT( per_cpu(vector_irq, cpu)[old_vector] == irq ); >>> @@ -250,16 +255,16 @@ static void __clear_irq_vector(int irq) >>> per_cpu(vector_irq, cpu)[old_vector] = -1; >>> } >>> >>> - cfg->old_vector = IRQ_VECTOR_UNASSIGNED; >>> - cpumask_clear(&cfg->old_cpu_mask); >>> + desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; >>> + cpumask_clear(desc->arch.old_cpu_mask); >>> >>> - if ( cfg->used_vectors ) >>> + if ( desc->arch.used_vectors ) >>> { >>> - ASSERT(test_bit(old_vector, cfg->used_vectors)); >>> - clear_bit(old_vector, cfg->used_vectors); >>> + ASSERT(test_bit(old_vector, desc->arch.used_vectors)); >>> + clear_bit(old_vector, desc->arch.used_vectors); >>> } >>> >>> - cfg->move_in_progress = 0; >>> + desc->arch.move_in_progress = 0; >>> } >>> >>> void clear_irq_vector(int irq) >>> @@ -296,25 +301,28 @@ int irq_to_vector(int irq) >>> return vector; >>> } >>> >>> -static void __init init_one_irq_desc(struct irq_desc *desc) >>> +int arch_init_one_irq_desc(struct irq_desc *desc) >>> { >>> - desc->status = IRQ_DISABLED; >>> - desc->handler = &no_irq_type; >>> - desc->action = NULL; >>> - desc->msi_desc = NULL; >>> - spin_lock_init(&desc->lock); >>> - cpumask_setall(&desc->affinity); >>> - INIT_LIST_HEAD(&desc->rl_link); >>> -} >>> + if ( !zalloc_cpumask_var(&desc->arch.cpu_mask) ) >>> + return -ENOMEM; >>> + >>> + if ( !alloc_cpumask_var(&desc->arch.old_cpu_mask) ) >>> + { >>> + free_cpumask_var(desc->arch.cpu_mask); >>> + return -ENOMEM; >>> + } >>> >>> -static void __init init_one_irq_cfg(struct irq_cfg *cfg) >>> -{ >>> - cfg->vector = IRQ_VECTOR_UNASSIGNED; >>> - cfg->old_vector = IRQ_VECTOR_UNASSIGNED; >>> - cpumask_clear(&cfg->cpu_mask); >>> - cpumask_clear(&cfg->old_cpu_mask); >>> - cfg->used_vectors = NULL; >>> - cfg->used = IRQ_UNUSED; >>> + if ( !alloc_cpumask_var(&desc->arch.pending_mask) ) >>> + { >>> + free_cpumask_var(desc->arch.old_cpu_mask); >>> + free_cpumask_var(desc->arch.cpu_mask); >>> + return -ENOMEM; >>> + } >>> + >>> + desc->arch.vector = IRQ_VECTOR_UNASSIGNED; >>> + desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; >>> + >>> + return 0; >>> } >>> >>> int __init init_irq_data(void) >>> @@ -331,12 +339,13 @@ int __init init_irq_data(void) >>> if ( !irq_desc || !irq_vector ) >>> return -ENOMEM; >>> >>> - for (irq = 0; irq < nr_irqs; irq++) { >>> + for (irq = 0; irq < nr_irqs_gsi; irq++) { >>> desc = irq_to_desc(irq); >>> desc->irq = irq; >>> init_one_irq_desc(desc); >>> - init_one_irq_cfg(&desc->arch); >>> } >>> + for (; irq < nr_irqs; irq++) >>> + irq_to_desc(irq)->irq = irq; >>> >>> /* Never allocate the hypercall vector or Linux/BSD fast-trap vector. */ >>> set_bit(LEGACY_SYSCALL_VECTOR, used_vectors); >>> @@ -403,7 +412,8 @@ static vmask_t *irq_get_used_vector_mask >>> return ret; >>> } >>> >>> -int __assign_irq_vector(int irq, struct irq_cfg *cfg, const cpumask_t *mask) >>> +static int __assign_irq_vector( >>> + int irq, struct irq_desc *desc, const cpumask_t *mask) >>> { >>> /* >>> * NOTE! The local APIC isn''t very good at handling >>> @@ -426,13 +436,13 @@ int __assign_irq_vector(int irq, struct >>> old_vector = irq_to_vector(irq); >>> if (old_vector) { >>> cpumask_and(&tmp_mask, mask, &cpu_online_map); >>> - if (cpumask_intersects(&tmp_mask, &cfg->cpu_mask)) { >>> - cfg->vector = old_vector; >>> + if (cpumask_intersects(&tmp_mask, desc->arch.cpu_mask)) { >>> + desc->arch.vector = old_vector; >>> return 0; >>> } >>> } >>> >>> - if ((cfg->move_in_progress) || cfg->move_cleanup_count) >>> + if ( desc->arch.move_in_progress || desc->arch.move_cleanup_count ) >>> return -EAGAIN; >>> >>> err = -ENOSPC; >>> @@ -440,9 +450,9 @@ int __assign_irq_vector(int irq, struct >>> /* This is the only place normal IRQs are ever marked >>> * as "in use". If they''re not in use yet, check to see >>> * if we need to assign a global vector mask. */ >>> - if ( cfg->used == IRQ_USED ) >>> + if ( desc->arch.used == IRQ_USED ) >>> { >>> - irq_used_vectors = cfg->used_vectors; >>> + irq_used_vectors = desc->arch.used_vectors; >>> } >>> else >>> irq_used_vectors = irq_get_used_vector_mask(irq); >>> @@ -485,29 +495,29 @@ next: >>> current_offset = offset; >>> local_irq_save(flags); >>> if (old_vector) { >>> - cfg->move_in_progress = 1; >>> - cpumask_copy(&cfg->old_cpu_mask, &cfg->cpu_mask); >>> - cfg->old_vector = cfg->vector; >>> + desc->arch.move_in_progress = 1; >>> + cpumask_copy(desc->arch.old_cpu_mask, desc->arch.cpu_mask); >>> + desc->arch.old_vector = desc->arch.vector; >>> } >>> trace_irq_mask(TRC_HW_IRQ_ASSIGN_VECTOR, irq, vector, &tmp_mask); >>> for_each_cpu_mask(new_cpu, tmp_mask) >>> per_cpu(vector_irq, new_cpu)[vector] = irq; >>> - cfg->vector = vector; >>> - cpumask_copy(&cfg->cpu_mask, &tmp_mask); >>> + desc->arch.vector = vector; >>> + cpumask_copy(desc->arch.cpu_mask, &tmp_mask); >>> >>> - cfg->used = IRQ_USED; >>> - ASSERT((cfg->used_vectors == NULL) >>> - || (cfg->used_vectors == irq_used_vectors)); >>> - cfg->used_vectors = irq_used_vectors; >>> + desc->arch.used = IRQ_USED; >>> + ASSERT((desc->arch.used_vectors == NULL) >>> + || (desc->arch.used_vectors == irq_used_vectors)); >>> + desc->arch.used_vectors = irq_used_vectors; >>> >>> if (IO_APIC_IRQ(irq)) >>> irq_vector[irq] = vector; >>> >>> - if ( cfg->used_vectors ) >>> + if ( desc->arch.used_vectors ) >>> { >>> - ASSERT(!test_bit(vector, cfg->used_vectors)); >>> + ASSERT(!test_bit(vector, desc->arch.used_vectors)); >>> >>> - set_bit(vector, cfg->used_vectors); >>> + set_bit(vector, desc->arch.used_vectors); >>> } >>> >>> err = 0; >>> @@ -521,16 +531,15 @@ int assign_irq_vector(int irq) >>> { >>> int ret; >>> unsigned long flags; >>> - struct irq_cfg *cfg = irq_cfg(irq); >>> struct irq_desc *desc = irq_to_desc(irq); >>> >>> BUG_ON(irq >= nr_irqs || irq <0); >>> >>> spin_lock_irqsave(&vector_lock, flags); >>> - ret = __assign_irq_vector(irq, cfg, TARGET_CPUS); >>> + ret = __assign_irq_vector(irq, desc, TARGET_CPUS); >>> if (!ret) { >>> - ret = cfg->vector; >>> - cpumask_copy(&desc->affinity, &cfg->cpu_mask); >>> + ret = desc->arch.vector; >>> + cpumask_copy(desc->affinity, desc->arch.cpu_mask); >>> } >>> spin_unlock_irqrestore(&vector_lock, flags); >>> return ret; >>> @@ -543,15 +552,16 @@ int assign_irq_vector(int irq) >>> void __setup_vector_irq(int cpu) >>> { >>> int irq, vector; >>> - struct irq_cfg *cfg; >>> >>> /* Clear vector_irq */ >>> for (vector = 0; vector < NR_VECTORS; ++vector) >>> per_cpu(vector_irq, cpu)[vector] = -1; >>> /* Mark the inuse vectors */ >>> for (irq = 0; irq < nr_irqs; ++irq) { >>> - cfg = irq_cfg(irq); >>> - if (!cpu_isset(cpu, cfg->cpu_mask)) >>> + struct irq_desc *desc = irq_to_desc(irq); >>> + >>> + if (!irq_desc_initialized(desc) || >>> + !cpumask_test_cpu(cpu, desc->arch.cpu_mask)) >>> continue; >>> vector = irq_to_vector(irq); >>> per_cpu(vector_irq, cpu)[vector] = irq; >>> @@ -560,12 +570,14 @@ void __setup_vector_irq(int cpu) >>> >>> void move_masked_irq(struct irq_desc *desc) >>> { >>> + cpumask_t *pending_mask = desc->arch.pending_mask; >>> + >>> if (likely(!(desc->status & IRQ_MOVE_PENDING))) >>> return; >>> >>> desc->status &= ~IRQ_MOVE_PENDING; >>> >>> - if (unlikely(cpus_empty(desc->pending_mask))) >>> + if (unlikely(cpumask_empty(pending_mask))) >>> return; >>> >>> if (!desc->handler->set_affinity) >>> @@ -580,10 +592,10 @@ void move_masked_irq(struct irq_desc *de >>> * >>> * For correct operation this depends on the caller masking the irqs. >>> */ >>> - if (likely(cpus_intersects(desc->pending_mask, cpu_online_map))) >>> - desc->handler->set_affinity(desc, &desc->pending_mask); >>> + if ( likely(cpumask_intersects(pending_mask, &cpu_online_map)) ) >>> + desc->handler->set_affinity(desc, pending_mask); >>> >>> - cpumask_clear(&desc->pending_mask); >>> + cpumask_clear(pending_mask); >>> } >>> >>> void move_native_irq(struct irq_desc *desc) >>> @@ -626,7 +638,8 @@ fastcall void smp_irq_move_cleanup_inter >>> if (!desc->arch.move_cleanup_count) >>> goto unlock; >>> >>> - if (vector == desc->arch.vector && cpumask_test_cpu(me, >> &desc->arch.cpu_mask)) >>> + if ( vector == desc->arch.vector && >>> + cpumask_test_cpu(me, desc->arch.cpu_mask) ) >>> goto unlock; >>> >>> irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); >>> @@ -653,7 +666,7 @@ fastcall void smp_irq_move_cleanup_inter >>> if ( desc->arch.move_cleanup_count == 0 ) >>> { >>> desc->arch.old_vector = IRQ_VECTOR_UNASSIGNED; >>> - cpumask_clear(&desc->arch.old_cpu_mask); >>> + cpumask_clear(desc->arch.old_cpu_mask); >>> >>> if ( desc->arch.used_vectors ) >>> { >>> @@ -673,7 +686,7 @@ static void send_cleanup_vector(struct i >>> { >>> cpumask_t cleanup_mask; >>> >>> - cpumask_and(&cleanup_mask, &desc->arch.old_cpu_mask, &cpu_online_map); >>> + cpumask_and(&cleanup_mask, desc->arch.old_cpu_mask, &cpu_online_map); >>> desc->arch.move_cleanup_count = cpumask_weight(&cleanup_mask); >>> genapic->send_IPI_mask(&cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); >>> >>> @@ -690,7 +703,8 @@ void irq_complete_move(struct irq_desc * >>> vector = get_irq_regs()->entry_vector; >>> me = smp_processor_id(); >>> >>> - if (vector == desc->arch.vector && cpumask_test_cpu(me, &desc->arch.cpu_mask)) >>> + if ( vector == desc->arch.vector && >>> + cpumask_test_cpu(me, desc->arch.cpu_mask) ) >>> send_cleanup_vector(desc); >>> } >>> >>> @@ -708,15 +722,15 @@ unsigned int set_desc_affinity(struct ir >>> >>> local_irq_save(flags); >>> lock_vector_lock(); >>> - ret = __assign_irq_vector(irq, &desc->arch, mask); >>> + ret = __assign_irq_vector(irq, desc, mask); >>> unlock_vector_lock(); >>> local_irq_restore(flags); >>> >>> if (ret < 0) >>> return BAD_APICID; >>> >>> - cpumask_copy(&desc->affinity, mask); >>> - cpumask_and(&dest_mask, mask, &desc->arch.cpu_mask); >>> + cpumask_copy(desc->affinity, mask); >>> + cpumask_and(&dest_mask, mask, desc->arch.cpu_mask); >>> >>> return cpu_mask_to_apicid(&dest_mask); >>> } >>> @@ -730,7 +744,7 @@ void irq_set_affinity(struct irq_desc *d >>> ASSERT(spin_is_locked(&desc->lock)); >>> desc->status &= ~IRQ_MOVE_PENDING; >>> wmb(); >>> - cpumask_copy(&desc->pending_mask, mask); >>> + cpumask_copy(desc->arch.pending_mask, mask); >>> wmb(); >>> desc->status |= IRQ_MOVE_PENDING; >>> } >>> @@ -1992,13 +2006,13 @@ static void dump_irqs(unsigned char key) >>> >>> desc = irq_to_desc(irq); >>> >>> - if ( !desc->handler || desc->handler == &no_irq_type ) >>> + if ( !irq_desc_initialized(desc) || desc->handler == &no_irq_type ) >>> continue; >>> >>> spin_lock_irqsave(&desc->lock, flags); >>> >>> cpumask_scnprintf(keyhandler_scratch, sizeof(keyhandler_scratch), >>> - &desc->affinity); >>> + desc->affinity); >>> printk(" IRQ:%4d affinity:%s vec:%02x type=%-15s" >>> " status=%08x ", >>> irq, keyhandler_scratch, desc->arch.vector, >>> @@ -2073,10 +2087,12 @@ void fixup_irqs(void) >>> continue; >>> >>> desc = irq_to_desc(irq); >>> + if ( !irq_desc_initialized(desc) ) >>> + continue; >>> >>> spin_lock(&desc->lock); >>> >>> - cpumask_copy(&affinity, &desc->affinity); >>> + cpumask_copy(&affinity, desc->affinity); >>> if ( !desc->action || cpumask_subset(&affinity, &cpu_online_map) ) >>> { >>> spin_unlock(&desc->lock); >>> --- a/xen/arch/x86/msi.c >>> +++ b/xen/arch/x86/msi.c >>> @@ -125,13 +125,13 @@ void msi_compose_msg(struct irq_desc *de >>> unsigned dest; >>> int vector = desc->arch.vector; >>> >>> - if ( cpumask_empty(&desc->arch.cpu_mask) ) { >>> + if ( cpumask_empty(desc->arch.cpu_mask) ) { >>> dprintk(XENLOG_ERR,"%s, compose msi message error!!\n", __func__); >>> return; >>> } >>> >>> if ( vector ) { >>> - dest = cpu_mask_to_apicid(&desc->arch.cpu_mask); >>> + dest = cpu_mask_to_apicid(desc->arch.cpu_mask); >>> >>> msg->address_hi = MSI_ADDR_BASE_HI; >>> msg->address_lo >>> --- a/xen/arch/x86/smpboot.c >>> +++ b/xen/arch/x86/smpboot.c >>> @@ -1011,7 +1011,7 @@ void __init smp_intr_init(void) >>> irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1; >>> per_cpu(vector_irq, cpu)[FIRST_HIPRIORITY_VECTOR + seridx + 1] >> irq; >>> irq_to_desc(irq)->arch.vector = FIRST_HIPRIORITY_VECTOR + seridx + 1; >>> - cpumask_copy(&irq_to_desc(irq)->arch.cpu_mask, &cpu_online_map); >>> + cpumask_copy(irq_to_desc(irq)->arch.cpu_mask, &cpu_online_map); >>> } >>> >>> /* IPI for cleanuping vectors after irq move */ >>> --- a/xen/common/Makefile >>> +++ b/xen/common/Makefile >>> @@ -5,6 +5,7 @@ obj-y += domctl.o >>> obj-y += domain.o >>> obj-y += event_channel.o >>> obj-y += grant_table.o >>> +obj-y += irq.o >>> obj-y += kernel.o >>> obj-y += keyhandler.o >>> obj-y += kexec.o >>> --- /dev/null >>> +++ a/xen/common/irq.c >>> @@ -0,0 +1,28 @@ >>> +#include <xen/config.h> >>> +#include <xen/irq.h> >>> + >>> +int init_one_irq_desc(struct irq_desc *desc) >>> +{ >>> + int err; >>> + >>> + if (irq_desc_initialized(desc)) >>> + return 0; >>> + >>> + if ( !alloc_cpumask_var(&desc->affinity) ) >>> + return -ENOMEM; >>> + >>> + desc->status = IRQ_DISABLED; >>> + desc->handler = &no_irq_type; >>> + spin_lock_init(&desc->lock); >>> + cpumask_setall(desc->affinity); >>> + INIT_LIST_HEAD(&desc->rl_link); >>> + >>> + err = arch_init_one_irq_desc(desc); >>> + if ( err ) >>> + { >>> + free_cpumask_var(desc->affinity); >>> + desc->handler = NULL; >>> + } >>> + >>> + return err; >>> +} >>> --- a/xen/drivers/passthrough/vtd/iommu.c >>> +++ b/xen/drivers/passthrough/vtd/iommu.c >>> @@ -1965,17 +1965,18 @@ static int init_vtd_hw(void) >>> struct iommu_flush *flush = NULL; >>> int ret; >>> unsigned long flags; >>> - struct irq_cfg *cfg; >>> >>> /* >>> * Basic VT-d HW init: set VT-d interrupt, clear VT-d faults. >>> */ >>> for_each_drhd_unit ( drhd ) >>> { >>> + struct irq_desc *desc; >>> + >>> iommu = drhd->iommu; >>> >>> - cfg = irq_cfg(iommu->irq); >>> - dma_msi_set_affinity(irq_to_desc(iommu->irq), &cfg->cpu_mask); >>> + desc = irq_to_desc(iommu->irq); >>> + dma_msi_set_affinity(desc, desc->arch.cpu_mask); >>> >>> clear_fault_bits(iommu); >>> >>> --- a/xen/include/asm-ia64/linux-xen/asm/irq.h >>> +++ b/xen/include/asm-ia64/linux-xen/asm/irq.h >>> @@ -18,8 +18,10 @@ >>> struct irq_cfg { >>> #define arch_irq_desc irq_cfg >>> int vector; >>> - cpumask_t cpu_mask; >>> + cpumask_var_t cpu_mask; >>> }; >>> + >>> +int init_irq_data(void); >>> #endif >>> >>> static __inline__ int >>> --- a/xen/include/asm-x86/irq.h >>> +++ b/xen/include/asm-x86/irq.h >>> @@ -33,8 +33,9 @@ struct irq_cfg { >>> #define arch_irq_desc irq_cfg >>> s16 vector; /* vector itself is only 8 bits, */ >>> s16 old_vector; /* but we use -1 for unassigned */ >>> - cpumask_t cpu_mask; >>> - cpumask_t old_cpu_mask; >>> + cpumask_var_t cpu_mask; >>> + cpumask_var_t old_cpu_mask; >>> + cpumask_var_t pending_mask; >>> unsigned move_cleanup_count; >>> vmask_t *used_vectors; >>> u8 move_in_progress : 1; >>> @@ -174,8 +175,6 @@ void __setup_vector_irq(int cpu); >>> void move_native_irq(struct irq_desc *); >>> void move_masked_irq(struct irq_desc *); >>> >>> -int __assign_irq_vector(int irq, struct irq_cfg *, const cpumask_t *); >>> - >>> int bind_irq_vector(int irq, int vector, const cpumask_t *); >>> >>> void irq_set_affinity(struct irq_desc *, const cpumask_t *mask); >>> --- a/xen/include/xen/irq.h >>> +++ b/xen/include/xen/irq.h >>> @@ -76,8 +76,7 @@ typedef struct irq_desc { >>> int irq; >>> spinlock_t lock; >>> struct arch_irq_desc arch; >>> - cpumask_t affinity; >>> - cpumask_t pending_mask; /* IRQ migration pending mask */ >>> + cpumask_var_t affinity; >>> >>> /* irq ratelimit */ >>> s_time_t rl_quantum_start; >>> @@ -85,6 +84,11 @@ typedef struct irq_desc { >>> struct list_head rl_link; >>> } __cacheline_aligned irq_desc_t; >>> >>> +int init_one_irq_desc(struct irq_desc *); >>> +int arch_init_one_irq_desc(struct irq_desc *); >>> + >>> +#define irq_desc_initialized(desc) ((desc)->handler != NULL) >>> + >>> #if defined(__ia64__) >>> extern irq_desc_t irq_desc[NR_VECTORS]; >>> >>> @@ -153,7 +157,7 @@ extern irq_desc_t *pirq_spin_lock_irq_de >>> >>> static inline void set_native_irq_info(unsigned int irq, const cpumask_t >> *mask) >>> { >>> - cpumask_copy(&irq_desc[irq].affinity, mask); >>> + cpumask_copy(irq_to_desc(irq)->affinity, mask); >>> } >>> >>> unsigned int set_desc_affinity(struct irq_desc *, const cpumask_t *); >>> >>> > >-- Andrew Cooper - Dom0 Kernel Engineer, Citrix XenServer T: +44 (0)1223 225 900, http://www.citrix.com _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-03 15:51 UTC
Re: [Xen-devel] [PATCH 1/2] IRQ: allocate CPU masks dynamically
>>> On 03.11.11 at 16:43, Andrew Cooper <andrew.cooper3@citrix.com> wrote: > On 03/11/11 15:17, Jan Beulich wrote: >>>>> On 03.11.11 at 15:49, Andrew Cooper <andrew.cooper3@citrix.com> wrote: >>> On 03/11/11 14:26, Jan Beulich wrote: >>>> IRQ: allocate CPU masks dynamically >>>> >>>> This includes delaying the initialization of dynamically created IRQs >>>> until their actual first use and some further elimination of uses of >>>> struct irq_cfg. >>>> >>>> Signed-off-by: Jan Beulich <jbeulich@suse.com> >>> Acked-by: Andrew Cooper <andrew.cooper3@citrix.com> >>> >>> One query which may or may not affect the patch. Would we get better >>> caching characteristics if all cpumasks were allocated in consecutive >>> memory, rather than having 3 individual allocs in arch_init_one_irq_desc ? >> That was what the first version of the patch did, rejected by Keir >> (and not liked too much by me either). >> >> Jan > > My understanding of the objection was hiding the variables themselves as > an array in the code. > > An alternative approach such as alloc''ing 3*sizeof(cpu mask) (cache > aligned) and assigning the relevant pointers to the current > cpumask_var_t''s would be a suitable approach which causes the cpumasks > to be in contiguous memory, but not changing how they are referenced in > the code.That would mean just open-coding what the former patch did by abstraction. In my opinion that is even worse - either we want a generally usable mechanism to do this, or we don''t do it at all. Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Andrew Cooper
2011-Nov-03 16:02 UTC
Re: [Xen-devel] [PATCH 1/2] IRQ: allocate CPU masks dynamically
On 03/11/11 15:51, Jan Beulich wrote:>>>> On 03.11.11 at 16:43, Andrew Cooper <andrew.cooper3@citrix.com> wrote: >> On 03/11/11 15:17, Jan Beulich wrote: >>>>>> On 03.11.11 at 15:49, Andrew Cooper <andrew.cooper3@citrix.com> wrote: >>>> On 03/11/11 14:26, Jan Beulich wrote: >>>>> IRQ: allocate CPU masks dynamically >>>>> >>>>> This includes delaying the initialization of dynamically created IRQs >>>>> until their actual first use and some further elimination of uses of >>>>> struct irq_cfg. >>>>> >>>>> Signed-off-by: Jan Beulich <jbeulich@suse.com> >>>> Acked-by: Andrew Cooper <andrew.cooper3@citrix.com> >>>> >>>> One query which may or may not affect the patch. Would we get better >>>> caching characteristics if all cpumasks were allocated in consecutive >>>> memory, rather than having 3 individual allocs in arch_init_one_irq_desc ? >>> That was what the first version of the patch did, rejected by Keir >>> (and not liked too much by me either). >>> >>> Jan >> My understanding of the objection was hiding the variables themselves as >> an array in the code. >> >> An alternative approach such as alloc''ing 3*sizeof(cpu mask) (cache >> aligned) and assigning the relevant pointers to the current >> cpumask_var_t''s would be a suitable approach which causes the cpumasks >> to be in contiguous memory, but not changing how they are referenced in >> the code. > That would mean just open-coding what the former patch did by > abstraction. In my opinion that is even worse - either we want a > generally usable mechanism to do this, or we don''t do it at all. > > JanThat is an interesting point, but I dont think it is worse. There are very few cases where we want to be doing this, so open coding is not too bad. With a comment explaining why, I would have thought it would be fine. -- Andrew Cooper - Dom0 Kernel Engineer, Citrix XenServer T: +44 (0)1223 225 900, http://www.citrix.com _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-03 16:13 UTC
Re: [Xen-devel] [PATCH 1/2] IRQ: allocate CPU masks dynamically
>>> On 03.11.11 at 17:02, Andrew Cooper <andrew.cooper3@citrix.com> wrote: > On 03/11/11 15:51, Jan Beulich wrote: >>>>> On 03.11.11 at 16:43, Andrew Cooper <andrew.cooper3@citrix.com> wrote: >>> On 03/11/11 15:17, Jan Beulich wrote: >>>>>>> On 03.11.11 at 15:49, Andrew Cooper <andrew.cooper3@citrix.com> wrote: >>>>> On 03/11/11 14:26, Jan Beulich wrote: >>>>>> IRQ: allocate CPU masks dynamically >>>>>> >>>>>> This includes delaying the initialization of dynamically created IRQs >>>>>> until their actual first use and some further elimination of uses of >>>>>> struct irq_cfg. >>>>>> >>>>>> Signed-off-by: Jan Beulich <jbeulich@suse.com> >>>>> Acked-by: Andrew Cooper <andrew.cooper3@citrix.com> >>>>> >>>>> One query which may or may not affect the patch. Would we get better >>>>> caching characteristics if all cpumasks were allocated in consecutive >>>>> memory, rather than having 3 individual allocs in arch_init_one_irq_desc ? >>>> That was what the first version of the patch did, rejected by Keir >>>> (and not liked too much by me either). >>>> >>>> Jan >>> My understanding of the objection was hiding the variables themselves as >>> an array in the code. >>> >>> An alternative approach such as alloc''ing 3*sizeof(cpu mask) (cache >>> aligned) and assigning the relevant pointers to the current >>> cpumask_var_t''s would be a suitable approach which causes the cpumasks >>> to be in contiguous memory, but not changing how they are referenced in >>> the code. >> That would mean just open-coding what the former patch did by >> abstraction. In my opinion that is even worse - either we want a >> generally usable mechanism to do this, or we don''t do it at all. >> >> Jan > > That is an interesting point, but I dont think it is worse. > > There are very few cases where we want to be doing this, so open coding > is not too bad. With a comment explaining why, I would have thought it > would be fine.This isn''t how I think maintainable code should be written - whenever we''d adjust the CPU mask allocation mechanism in some way, we''d have to touch that code separately. Depending on the nature of the change, it may even get overlooked (i.e. when no build failure results). Just consider how ugly it would be if there were no {,z}alloc_cpumask_var() wrappers (which already did change from their original version in that we''re now able to allocate just the portion that we know will actually get used). Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel