···102102 help103103 The <linux/clk.h> calls support software clock gating and104104 thus are a key power management tool on many systems.105105-106106-config HAVE_DYN_ARRAY107107- def_bool n108108-
···107107}108108early_param("noapic", parse_noapic);109109110110-struct irq_cfg;111110struct irq_pin_list;112111struct irq_cfg {113112 unsigned int irq;···119120};120121121122/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */122122-static struct irq_cfg irq_cfg_legacy[] __initdata = {123123+static struct irq_cfg irq_cfgx[NR_IRQS] = {123124 [0] = { .irq = 0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, },124125 [1] = { .irq = 1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, },125126 [2] = { .irq = 2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, },···138139 [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },139140};140141141141-static struct irq_cfg irq_cfg_init = { .irq = -1U, };142142-143143-static void init_one_irq_cfg(struct irq_cfg *cfg)144144-{145145- memcpy(cfg, &irq_cfg_init, sizeof(struct irq_cfg));146146-}147147-148148-static struct irq_cfg *irq_cfgx;149149-150150-static void __init init_work(void *data)151151-{152152- struct dyn_array *da = data;153153- struct irq_cfg *cfg;154154- int legacy_count;155155- int i;156156-157157- cfg = *da->name;158158-159159- memcpy(cfg, irq_cfg_legacy, sizeof(irq_cfg_legacy));160160-161161- legacy_count = ARRAY_SIZE(irq_cfg_legacy);162162- for (i = legacy_count; i < *da->nr; i++)163163- init_one_irq_cfg(&cfg[i]);164164-}165165-166142#define for_each_irq_cfg(irq, cfg) \167167- for (irq = 0, cfg = &irq_cfgx[irq]; irq < nr_irqs; irq++, cfg = &irq_cfgx[irq])143143+ for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++)168144169169-DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irqs, PAGE_SIZE, init_work);170170-171171-struct irq_cfg *irq_cfg(unsigned int irq)145145+static struct irq_cfg *irq_cfg(unsigned int irq)172146{173173- if (irq < nr_irqs)174174- return &irq_cfgx[irq];175175-176176- return NULL;147147+ return irq < nr_irqs ? irq_cfgx + irq : NULL;177148}178178-struct irq_cfg *irq_cfg_alloc(unsigned int irq)149149+150150+static struct irq_cfg *irq_cfg_alloc(unsigned int irq)179151{180152 return irq_cfg(irq);181153}154154+155155+/*156156+ * Rough estimation of how many shared IRQs there are, can be changed157157+ * anytime.158158+ */159159+#define MAX_PLUS_SHARED_IRQS NR_IRQS160160+#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)182161183162/*184163 * This is performance-critical, we want to do it O(1)···170193 struct irq_pin_list *next;171194};172195173173-static struct irq_pin_list *irq_2_pin_head;174174-/* fill one page ? */175175-static int nr_irq_2_pin = 0x100;196196+static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE];176197static struct irq_pin_list *irq_2_pin_ptr;177177-static void __init irq_2_pin_init_work(void *data)198198+199199+static void __init irq_2_pin_init(void)178200{179179- struct dyn_array *da = data;180180- struct irq_pin_list *pin;201201+ struct irq_pin_list *pin = irq_2_pin_head;181202 int i;182203183183- pin = *da->name;184184-185185- for (i = 1; i < *da->nr; i++)204204+ for (i = 1; i < PIN_MAP_SIZE; i++)186205 pin[i-1].next = &pin[i];187206188207 irq_2_pin_ptr = &pin[0];189208}190190-DEFINE_DYN_ARRAY(irq_2_pin_head, sizeof(struct irq_pin_list), nr_irq_2_pin, PAGE_SIZE, irq_2_pin_init_work);191209192210static struct irq_pin_list *get_one_free_irq_2_pin(void)193211{194194- struct irq_pin_list *pin;195195- int i;196196-197197- pin = irq_2_pin_ptr;198198-199199- if (pin) {200200- irq_2_pin_ptr = pin->next;201201- pin->next = NULL;202202- return pin;203203- }204204-205205- /*206206- * we run out of pre-allocate ones, allocate more207207- */208208- printk(KERN_DEBUG "try to get more irq_2_pin %d\n", nr_irq_2_pin);209209-210210- if (after_bootmem)211211- pin = kzalloc(sizeof(struct irq_pin_list)*nr_irq_2_pin,212212- GFP_ATOMIC);213213- else214214- pin = __alloc_bootmem_nopanic(sizeof(struct irq_pin_list) *215215- nr_irq_2_pin, PAGE_SIZE, 0);212212+ struct irq_pin_list *pin = irq_2_pin_ptr;216213217214 if (!pin)218215 panic("can not get more irq_2_pin\n");219216220220- for (i = 1; i < nr_irq_2_pin; i++)221221- pin[i-1].next = &pin[i];222222-223217 irq_2_pin_ptr = pin->next;224218 pin->next = NULL;225225-226219 return pin;227220}228221···231284static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)232285{233286 struct io_apic __iomem *io_apic = io_apic_base(apic);234234- if (sis_apic_bug)235235- writel(reg, &io_apic->index);287287+288288+ if (sis_apic_bug)289289+ writel(reg, &io_apic->index);236290 writel(value, &io_apic->data);237291}238292···9921044 while (i < apic)9931045 irq += nr_ioapic_registers[i++];9941046 irq += pin;995995- /*10471047+ /*9961048 * For MPS mode, so far only needed by ES7000 platform9971049 */998998- if (ioapic_renumber_irq)999999- irq = ioapic_renumber_irq(apic, irq);10501050+ if (ioapic_renumber_irq)10511051+ irq = ioapic_renumber_irq(apic, irq);10001052 }1001105310021054#ifdef CONFIG_X86_32···11801232#ifdef CONFIG_X86_3211811233static inline int IO_APIC_irq_trigger(int irq)11821234{11831183- int apic, idx, pin;12351235+ int apic, idx, pin;1184123611851185- for (apic = 0; apic < nr_ioapics; apic++) {11861186- for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {11871187- idx = find_irq_entry(apic, pin, mp_INT);11881188- if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))11891189- return irq_trigger(idx);11901190- }11911191- }11921192- /*12371237+ for (apic = 0; apic < nr_ioapics; apic++) {12381238+ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {12391239+ idx = find_irq_entry(apic, pin, mp_INT);12401240+ if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))12411241+ return irq_trigger(idx);12421242+ }12431243+ }12441244+ /*11931245 * nonexistent IRQs are edge default11941246 */11951195- return 0;12471247+ return 0;11961248}11971249#else11981250static inline int IO_APIC_irq_trigger(int irq)···14571509 reg_01.raw = io_apic_read(apic, 1);14581510 if (reg_01.bits.version >= 0x10)14591511 reg_02.raw = io_apic_read(apic, 2);14601460- if (reg_01.bits.version >= 0x20)14611461- reg_03.raw = io_apic_read(apic, 3);15121512+ if (reg_01.bits.version >= 0x20)15131513+ reg_03.raw = io_apic_read(apic, 3);14621514 spin_unlock_irqrestore(&ioapic_lock, flags);1463151514641516 printk("\n");···20372089#else20382090static int ioapic_retrigger_irq(unsigned int irq)20392091{20402040- send_IPI_self(irq_cfg(irq)->vector);20922092+ send_IPI_self(irq_cfg(irq)->vector);2041209320422042- return 1;20942094+ return 1;20432095}20442096#endif20452097···2137218921382190 if (io_apic_level_ack_pending(irq)) {21392191 /*21402140- * Interrupt in progress. Migrating irq now will change the21922192+ * Interrupt in progress. Migrating irq now will change the21412193 * vector information in the IO-APIC RTE and that will confuse21422194 * the EOI broadcast performed by cpu.21432195 * So, delay the irq migration to the next instance.···23742426}2375242723762428static struct irq_chip ioapic_chip __read_mostly = {23772377- .name = "IO-APIC",23782378- .startup = startup_ioapic_irq,23792379- .mask = mask_IO_APIC_irq,23802380- .unmask = unmask_IO_APIC_irq,23812381- .ack = ack_apic_edge,23822382- .eoi = ack_apic_level,24292429+ .name = "IO-APIC",24302430+ .startup = startup_ioapic_irq,24312431+ .mask = mask_IO_APIC_irq,24322432+ .unmask = unmask_IO_APIC_irq,24332433+ .ack = ack_apic_edge,24342434+ .eoi = ack_apic_level,23832435#ifdef CONFIG_SMP23842384- .set_affinity = set_ioapic_affinity_irq,24362436+ .set_affinity = set_ioapic_affinity_irq,23852437#endif23862438 .retrigger = ioapic_retrigger_irq,23872439};2388244023892441#ifdef CONFIG_INTR_REMAP23902442static struct irq_chip ir_ioapic_chip __read_mostly = {23912391- .name = "IR-IO-APIC",23922392- .startup = startup_ioapic_irq,23932393- .mask = mask_IO_APIC_irq,23942394- .unmask = unmask_IO_APIC_irq,23952395- .ack = ack_x2apic_edge,23962396- .eoi = ack_x2apic_level,24432443+ .name = "IR-IO-APIC",24442444+ .startup = startup_ioapic_irq,24452445+ .mask = mask_IO_APIC_irq,24462446+ .unmask = unmask_IO_APIC_irq,24472447+ .ack = ack_x2apic_edge,24482448+ .eoi = ack_x2apic_level,23972449#ifdef CONFIG_SMP23982398- .set_affinity = set_ir_ioapic_affinity_irq,24502450+ .set_affinity = set_ir_ioapic_affinity_irq,23992451#endif24002452 .retrigger = ioapic_retrigger_irq,24012453};···2584263625852637 local_irq_save(flags);2586263825872587- ver = apic_read(APIC_LVR);25882588- ver = GET_APIC_VERSION(ver);26392639+ ver = apic_read(APIC_LVR);26402640+ ver = GET_APIC_VERSION(ver);2589264125902642 /*25912643 * get/set the timer IRQ vector:···27702822 io_apic_irqs = ~PIC_IRQS;2771282327722824 apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");27732773- /*28252825+ /*27742826 * Set up IO-APIC IRQ routing.27752827 */27762828#ifdef CONFIG_X86_3227772777- if (!acpi_ioapic)27782778- setup_ioapic_ids_from_mpc();28292829+ if (!acpi_ioapic)28302830+ setup_ioapic_ids_from_mpc();27792831#endif27802832 sync_Arb_IDs();27812833 setup_IO_APIC_irqs();···2790284227912843static int __init io_apic_bug_finalize(void)27922844{27932793- if (sis_apic_bug == -1)27942794- sis_apic_bug = 0;27952795- return 0;28452845+ if (sis_apic_bug == -1)28462846+ sis_apic_bug = 0;28472847+ return 0;27962848}2797284927982850late_initcall(io_apic_bug_finalize);···31473199 if (index < 0) {31483200 printk(KERN_ERR31493201 "Unable to allocate %d IRTE for PCI %s\n", nvec,31503150- pci_name(dev));32023202+ pci_name(dev));31513203 return -ENOSPC;31523204 }31533205 return index;···38333885void __init ioapic_init_mappings(void)38343886{38353887 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;38363836- int i;38373888 struct resource *ioapic_res;38893889+ int i;3838389038913891+ irq_2_pin_init();38393892 ioapic_res = ioapic_setup_resources();38403893 for (i = 0; i < nr_ioapics; i++) {38413894 if (smp_found_config) {38423895 ioapic_phys = mp_ioapics[i].mp_apicaddr;38433896#ifdef CONFIG_X86_3238443844- if (!ioapic_phys) {38453845- printk(KERN_ERR38463846- "WARNING: bogus zero IO-APIC "38473847- "address found in MPTABLE, "38483848- "disabling IO/APIC support!\n");38493849- smp_found_config = 0;38503850- skip_ioapic_setup = 1;38513851- goto fake_ioapic_page;38523852- }38973897+ if (!ioapic_phys) {38983898+ printk(KERN_ERR38993899+ "WARNING: bogus zero IO-APIC "39003900+ "address found in MPTABLE, "39013901+ "disabling IO/APIC support!\n");39023902+ smp_found_config = 0;39033903+ skip_ioapic_setup = 1;39043904+ goto fake_ioapic_page;39053905+ }38533906#endif38543907 } else {38553908#ifdef CONFIG_X86_32
+2-6
arch/x86/kernel/setup_percpu.c
···140140 */141141void __init setup_per_cpu_areas(void)142142{143143- ssize_t size, old_size, da_size;143143+ ssize_t size, old_size;144144 char *ptr;145145 int cpu;146146 unsigned long align = 1;···150150151151 /* Copy section for each CPU (we discard the original) */152152 old_size = PERCPU_ENOUGH_ROOM;153153- da_size = per_cpu_dyn_array_size(&align);154153 align = max_t(unsigned long, PAGE_SIZE, align);155155- size = roundup(old_size + da_size, align);154154+ size = roundup(old_size, align);156155 printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n",157156 size);158157···181182#endif182183 per_cpu_offset(cpu) = ptr - __per_cpu_start;183184 memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);184184-185185- per_cpu_alloc_dyn_array(cpu, ptr + old_size);186186-187185 }188186189187 printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d, nr_node_ids %d\n",
+1-1
arch/x86/kernel/visws_quirks.c
···633633 /*634634 * handle this 'virtual interrupt' as a Cobalt one now.635635 */636636- kstat_irqs_this_cpu(desc)++;636636+ kstat_incr_irqs_this_cpu(realirq, desc);637637638638 if (likely(desc->action != NULL))639639 handle_IRQ_event(realirq, desc->action);
···139139 const char *typename;140140};141141142142-struct timer_rand_state;143143-struct irq_2_iommu;144142/**145143 * struct irq_desc - interrupt descriptor146144 *···165167 */166168struct irq_desc {167169 unsigned int irq;168168-#ifdef CONFIG_HAVE_DYN_ARRAY169169- unsigned int *kstat_irqs;170170-#endif171170 irq_flow_handler_t handle_irq;172171 struct irq_chip *chip;173172 struct msi_desc *msi_desc;···193198} ____cacheline_internodealigned_in_smp;194199195200196196-#ifndef CONFIG_HAVE_DYN_ARRAY197197-/* could be removed if we get rid of all irq_desc reference */198201extern struct irq_desc irq_desc[NR_IRQS];199199-#else200200-extern struct irq_desc *irq_desc;201201-#endif202202203203static inline struct irq_desc *irq_to_desc(unsigned int irq)204204{205205 return (irq < nr_irqs) ? irq_desc + irq : NULL;206206}207207-208208-#ifdef CONFIG_HAVE_DYN_ARRAY209209-#define kstat_irqs_this_cpu(DESC) \210210- ((DESC)->kstat_irqs[smp_processor_id()])211211-#endif212207213208/*214209 * Migration helpers for obsolete names, they will go away:
+6-10
include/linux/kernel_stat.h
···28282929struct kernel_stat {3030 struct cpu_usage_stat cpustat;3131-#ifndef CONFIG_HAVE_DYN_ARRAY3231 unsigned int irqs[NR_IRQS];3333-#endif3432};35333634DECLARE_PER_CPU(struct kernel_stat, kstat);···39414042extern unsigned long long nr_context_switches(void);41434242-#ifndef CONFIG_HAVE_DYN_ARRAY4343-#define kstat_irqs_this_cpu(irq) \4444- (kstat_this_cpu.irqs[irq])4545-#endif4444+struct irq_desc;46454646+static inline void kstat_incr_irqs_this_cpu(unsigned int irq,4747+ struct irq_desc *desc)4848+{4949+ kstat_this_cpu.irqs[irq]++;5050+}47514848-#ifndef CONFIG_HAVE_DYN_ARRAY4952static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)5053{5154 return kstat_cpu(cpu).irqs[irq];5255}5353-#else5454-extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu);5555-#endif56565757/*5858 * Number of interrupts per specific IRQ source, since bootup
+1-1
init/Makefile
···22# Makefile for the linux kernel.33#4455-obj-y := main.o dyn_array.o version.o mounts.o55+obj-y := main.o version.o mounts.o66ifneq ($(CONFIG_BLK_DEV_INITRD),y)77obj-y += noinitramfs.o88else
-120
init/dyn_array.c
···11-#include <linux/types.h>22-#include <linux/kernel.h>33-#include <linux/kallsyms.h>44-#include <linux/init.h>55-#include <linux/bootmem.h>66-#include <linux/irq.h>77-88-void __init pre_alloc_dyn_array(void)99-{1010-#ifdef CONFIG_HAVE_DYN_ARRAY1111- unsigned long total_size = 0, size, phys;1212- unsigned long max_align = 1;1313- struct dyn_array **daa;1414- char *ptr;1515-1616- /* get the total size at first */1717- for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {1818- struct dyn_array *da = *daa;1919-2020- printk(KERN_DEBUG "dyn_array %pF size:%#lx nr:%d align:%#lx\n",2121- da->name, da->size, *da->nr, da->align);2222- size = da->size * (*da->nr);2323- total_size += roundup(size, da->align);2424- if (da->align > max_align)2525- max_align = da->align;2626- }2727- if (total_size)2828- printk(KERN_DEBUG "dyn_array total_size: %#lx\n",2929- total_size);3030- else3131- return;3232-3333- /* allocate them all together */3434- max_align = max_t(unsigned long, max_align, PAGE_SIZE);3535- ptr = __alloc_bootmem(total_size, max_align, 0);3636- phys = virt_to_phys(ptr);3737-3838- for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {3939- struct dyn_array *da = *daa;4040-4141- size = da->size * (*da->nr);4242- phys = roundup(phys, da->align);4343- printk(KERN_DEBUG "dyn_array %pF ==> [%#lx - %#lx]\n",4444- da->name, phys, phys + size);4545- *da->name = phys_to_virt(phys);4646-4747- phys += size;4848-4949- if (da->init_work)5050- da->init_work(da);5151- }5252-#else5353-#ifdef CONFIG_GENERIC_HARDIRQS5454- unsigned int i;5555-5656- for (i = 0; i < NR_IRQS; i++)5757- irq_desc[i].irq = i;5858-#endif5959-#endif6060-}6161-6262-unsigned long __init per_cpu_dyn_array_size(unsigned long *align)6363-{6464- unsigned long total_size = 0;6565-#ifdef CONFIG_HAVE_DYN_ARRAY6666- unsigned long size;6767- struct dyn_array **daa;6868- unsigned max_align = 1;6969-7070- for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {7171- struct dyn_array *da = *daa;7272-7373- printk(KERN_DEBUG "per_cpu_dyn_array %pF size:%#lx nr:%d align:%#lx\n",7474- da->name, da->size, *da->nr, da->align);7575- size = da->size * (*da->nr);7676- total_size += roundup(size, da->align);7777- if (da->align > max_align)7878- max_align = da->align;7979- }8080- if (total_size) {8181- printk(KERN_DEBUG "per_cpu_dyn_array total_size: %#lx\n",8282- total_size);8383- *align = max_align;8484- }8585-#endif8686- return total_size;8787-}8888-8989-#ifdef CONFIG_SMP9090-void __init per_cpu_alloc_dyn_array(int cpu, char *ptr)9191-{9292-#ifdef CONFIG_HAVE_DYN_ARRAY9393- unsigned long size, phys;9494- struct dyn_array **daa;9595- unsigned long addr;9696- void **array;9797-9898- phys = virt_to_phys(ptr);9999- for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {100100- struct dyn_array *da = *daa;101101-102102- size = da->size * (*da->nr);103103- phys = roundup(phys, da->align);104104- printk(KERN_DEBUG "per_cpu_dyn_array %pF ==> [%#lx - %#lx]\n",105105- da->name, phys, phys + size);106106-107107- addr = (unsigned long)da->name;108108- addr += per_cpu_offset(cpu);109109- array = (void **)addr;110110- *array = phys_to_virt(phys);111111- *da->name = *array; /* so init_work could use it directly */112112-113113- phys += size;114114-115115- if (da->init_work)116116- da->init_work(da);117117- }118118-#endif119119-}120120-#endif