diff options
| -rw-r--r-- | arch/Kconfig | 4 | ||||
| -rw-r--r-- | arch/x86/Kconfig | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/io_apic.c | 199 | ||||
| -rw-r--r-- | arch/x86/kernel/setup_percpu.c | 8 | ||||
| -rw-r--r-- | arch/x86/kernel/visws_quirks.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/vmlinux_32.lds.S | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/vmlinux_64.lds.S | 2 | ||||
| -rw-r--r-- | arch/x86/xen/spinlock.c | 2 | ||||
| -rw-r--r-- | drivers/char/random.c | 5 | ||||
| -rw-r--r-- | drivers/pci/intr_remapping.c | 11 | ||||
| -rw-r--r-- | include/asm-generic/vmlinux.lds.h | 13 | ||||
| -rw-r--r-- | include/linux/init.h | 43 | ||||
| -rw-r--r-- | include/linux/irq.h | 15 | ||||
| -rw-r--r-- | include/linux/kernel_stat.h | 16 | ||||
| -rw-r--r-- | init/Makefile | 2 | ||||
| -rw-r--r-- | init/dyn_array.c | 120 | ||||
| -rw-r--r-- | init/main.c | 11 | ||||
| -rw-r--r-- | kernel/irq/chip.c | 30 | ||||
| -rw-r--r-- | kernel/irq/handle.c | 114 |
19 files changed, 103 insertions, 496 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index c8a7c2eb6490..071004d3a1b1 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
| @@ -102,7 +102,3 @@ config HAVE_CLK | |||
| 102 | help | 102 | help |
| 103 | The <linux/clk.h> calls support software clock gating and | 103 | The <linux/clk.h> calls support software clock gating and |
| 104 | thus are a key power management tool on many systems. | 104 | thus are a key power management tool on many systems. |
| 105 | |||
| 106 | config HAVE_DYN_ARRAY | ||
| 107 | def_bool n | ||
| 108 | |||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 8636ddf2f4a4..8da6123a60d0 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -33,7 +33,6 @@ config X86 | |||
| 33 | select HAVE_ARCH_TRACEHOOK | 33 | select HAVE_ARCH_TRACEHOOK |
| 34 | select HAVE_GENERIC_DMA_COHERENT if X86_32 | 34 | select HAVE_GENERIC_DMA_COHERENT if X86_32 |
| 35 | select HAVE_EFFICIENT_UNALIGNED_ACCESS | 35 | select HAVE_EFFICIENT_UNALIGNED_ACCESS |
| 36 | select HAVE_DYN_ARRAY | ||
| 37 | 36 | ||
| 38 | config ARCH_DEFCONFIG | 37 | config ARCH_DEFCONFIG |
| 39 | string | 38 | string |
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index e03bc0f87eef..6f80dc2f137e 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c | |||
| @@ -107,7 +107,6 @@ static int __init parse_noapic(char *str) | |||
| 107 | } | 107 | } |
| 108 | early_param("noapic", parse_noapic); | 108 | early_param("noapic", parse_noapic); |
| 109 | 109 | ||
| 110 | struct irq_cfg; | ||
| 111 | struct irq_pin_list; | 110 | struct irq_pin_list; |
| 112 | struct irq_cfg { | 111 | struct irq_cfg { |
| 113 | unsigned int irq; | 112 | unsigned int irq; |
| @@ -120,7 +119,7 @@ struct irq_cfg { | |||
| 120 | }; | 119 | }; |
| 121 | 120 | ||
| 122 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ | 121 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ |
| 123 | static struct irq_cfg irq_cfg_legacy[] __initdata = { | 122 | static struct irq_cfg irq_cfgx[NR_IRQS] = { |
| 124 | [0] = { .irq = 0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, | 123 | [0] = { .irq = 0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, |
| 125 | [1] = { .irq = 1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, | 124 | [1] = { .irq = 1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, |
| 126 | [2] = { .irq = 2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, | 125 | [2] = { .irq = 2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, |
| @@ -139,49 +138,27 @@ static struct irq_cfg irq_cfg_legacy[] __initdata = { | |||
| 139 | [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, | 138 | [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, |
| 140 | }; | 139 | }; |
| 141 | 140 | ||
| 142 | static struct irq_cfg irq_cfg_init = { .irq = -1U, }; | ||
| 143 | |||
| 144 | static void init_one_irq_cfg(struct irq_cfg *cfg) | ||
| 145 | { | ||
| 146 | memcpy(cfg, &irq_cfg_init, sizeof(struct irq_cfg)); | ||
| 147 | } | ||
| 148 | |||
| 149 | static struct irq_cfg *irq_cfgx; | ||
| 150 | |||
| 151 | static void __init init_work(void *data) | ||
| 152 | { | ||
| 153 | struct dyn_array *da = data; | ||
| 154 | struct irq_cfg *cfg; | ||
| 155 | int legacy_count; | ||
| 156 | int i; | ||
| 157 | |||
| 158 | cfg = *da->name; | ||
| 159 | |||
| 160 | memcpy(cfg, irq_cfg_legacy, sizeof(irq_cfg_legacy)); | ||
| 161 | |||
| 162 | legacy_count = ARRAY_SIZE(irq_cfg_legacy); | ||
| 163 | for (i = legacy_count; i < *da->nr; i++) | ||
| 164 | init_one_irq_cfg(&cfg[i]); | ||
| 165 | } | ||
| 166 | |||
| 167 | #define for_each_irq_cfg(irq, cfg) \ | 141 | #define for_each_irq_cfg(irq, cfg) \ |
| 168 | for (irq = 0, cfg = &irq_cfgx[irq]; irq < nr_irqs; irq++, cfg = &irq_cfgx[irq]) | 142 | for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++) |
| 169 | 143 | ||
| 170 | DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irqs, PAGE_SIZE, init_work); | 144 | static struct irq_cfg *irq_cfg(unsigned int irq) |
| 171 | |||
| 172 | struct irq_cfg *irq_cfg(unsigned int irq) | ||
| 173 | { | 145 | { |
| 174 | if (irq < nr_irqs) | 146 | return irq < nr_irqs ? irq_cfgx + irq : NULL; |
| 175 | return &irq_cfgx[irq]; | ||
| 176 | |||
| 177 | return NULL; | ||
| 178 | } | 147 | } |
| 179 | struct irq_cfg *irq_cfg_alloc(unsigned int irq) | 148 | |
| 149 | static struct irq_cfg *irq_cfg_alloc(unsigned int irq) | ||
| 180 | { | 150 | { |
| 181 | return irq_cfg(irq); | 151 | return irq_cfg(irq); |
| 182 | } | 152 | } |
| 183 | 153 | ||
| 184 | /* | 154 | /* |
| 155 | * Rough estimation of how many shared IRQs there are, can be changed | ||
| 156 | * anytime. | ||
| 157 | */ | ||
| 158 | #define MAX_PLUS_SHARED_IRQS NR_IRQS | ||
| 159 | #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) | ||
| 160 | |||
| 161 | /* | ||
| 185 | * This is performance-critical, we want to do it O(1) | 162 | * This is performance-critical, we want to do it O(1) |
| 186 | * | 163 | * |
| 187 | * the indexing order of this array favors 1:1 mappings | 164 | * the indexing order of this array favors 1:1 mappings |
| @@ -193,59 +170,29 @@ struct irq_pin_list { | |||
| 193 | struct irq_pin_list *next; | 170 | struct irq_pin_list *next; |
| 194 | }; | 171 | }; |
| 195 | 172 | ||
| 196 | static struct irq_pin_list *irq_2_pin_head; | 173 | static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE]; |
| 197 | /* fill one page ? */ | ||
| 198 | static int nr_irq_2_pin = 0x100; | ||
| 199 | static struct irq_pin_list *irq_2_pin_ptr; | 174 | static struct irq_pin_list *irq_2_pin_ptr; |
| 200 | static void __init irq_2_pin_init_work(void *data) | 175 | |
| 176 | static void __init irq_2_pin_init(void) | ||
| 201 | { | 177 | { |
| 202 | struct dyn_array *da = data; | 178 | struct irq_pin_list *pin = irq_2_pin_head; |
| 203 | struct irq_pin_list *pin; | ||
| 204 | int i; | 179 | int i; |
| 205 | 180 | ||
| 206 | pin = *da->name; | 181 | for (i = 1; i < PIN_MAP_SIZE; i++) |
| 207 | |||
| 208 | for (i = 1; i < *da->nr; i++) | ||
| 209 | pin[i-1].next = &pin[i]; | 182 | pin[i-1].next = &pin[i]; |
| 210 | 183 | ||
| 211 | irq_2_pin_ptr = &pin[0]; | 184 | irq_2_pin_ptr = &pin[0]; |
| 212 | } | 185 | } |
| 213 | DEFINE_DYN_ARRAY(irq_2_pin_head, sizeof(struct irq_pin_list), nr_irq_2_pin, PAGE_SIZE, irq_2_pin_init_work); | ||
| 214 | 186 | ||
| 215 | static struct irq_pin_list *get_one_free_irq_2_pin(void) | 187 | static struct irq_pin_list *get_one_free_irq_2_pin(void) |
| 216 | { | 188 | { |
| 217 | struct irq_pin_list *pin; | 189 | struct irq_pin_list *pin = irq_2_pin_ptr; |
| 218 | int i; | ||
| 219 | |||
| 220 | pin = irq_2_pin_ptr; | ||
| 221 | |||
| 222 | if (pin) { | ||
| 223 | irq_2_pin_ptr = pin->next; | ||
| 224 | pin->next = NULL; | ||
| 225 | return pin; | ||
| 226 | } | ||
| 227 | |||
| 228 | /* | ||
| 229 | * we run out of pre-allocate ones, allocate more | ||
| 230 | */ | ||
| 231 | printk(KERN_DEBUG "try to get more irq_2_pin %d\n", nr_irq_2_pin); | ||
| 232 | |||
| 233 | if (after_bootmem) | ||
| 234 | pin = kzalloc(sizeof(struct irq_pin_list)*nr_irq_2_pin, | ||
| 235 | GFP_ATOMIC); | ||
| 236 | else | ||
| 237 | pin = __alloc_bootmem_nopanic(sizeof(struct irq_pin_list) * | ||
| 238 | nr_irq_2_pin, PAGE_SIZE, 0); | ||
| 239 | 190 | ||
| 240 | if (!pin) | 191 | if (!pin) |
| 241 | panic("can not get more irq_2_pin\n"); | 192 | panic("can not get more irq_2_pin\n"); |
| 242 | 193 | ||
| 243 | for (i = 1; i < nr_irq_2_pin; i++) | ||
| 244 | pin[i-1].next = &pin[i]; | ||
| 245 | |||
| 246 | irq_2_pin_ptr = pin->next; | 194 | irq_2_pin_ptr = pin->next; |
| 247 | pin->next = NULL; | 195 | pin->next = NULL; |
| 248 | |||
| 249 | return pin; | 196 | return pin; |
| 250 | } | 197 | } |
| 251 | 198 | ||
| @@ -284,8 +231,9 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i | |||
| 284 | static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) | 231 | static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) |
| 285 | { | 232 | { |
| 286 | struct io_apic __iomem *io_apic = io_apic_base(apic); | 233 | struct io_apic __iomem *io_apic = io_apic_base(apic); |
| 287 | if (sis_apic_bug) | 234 | |
| 288 | writel(reg, &io_apic->index); | 235 | if (sis_apic_bug) |
| 236 | writel(reg, &io_apic->index); | ||
| 289 | writel(value, &io_apic->data); | 237 | writel(value, &io_apic->data); |
| 290 | } | 238 | } |
| 291 | 239 | ||
| @@ -1044,11 +992,11 @@ static int pin_2_irq(int idx, int apic, int pin) | |||
| 1044 | while (i < apic) | 992 | while (i < apic) |
| 1045 | irq += nr_ioapic_registers[i++]; | 993 | irq += nr_ioapic_registers[i++]; |
| 1046 | irq += pin; | 994 | irq += pin; |
| 1047 | /* | 995 | /* |
| 1048 | * For MPS mode, so far only needed by ES7000 platform | 996 | * For MPS mode, so far only needed by ES7000 platform |
| 1049 | */ | 997 | */ |
| 1050 | if (ioapic_renumber_irq) | 998 | if (ioapic_renumber_irq) |
| 1051 | irq = ioapic_renumber_irq(apic, irq); | 999 | irq = ioapic_renumber_irq(apic, irq); |
| 1052 | } | 1000 | } |
| 1053 | 1001 | ||
| 1054 | #ifdef CONFIG_X86_32 | 1002 | #ifdef CONFIG_X86_32 |
| @@ -1232,19 +1180,19 @@ static struct irq_chip ir_ioapic_chip; | |||
| 1232 | #ifdef CONFIG_X86_32 | 1180 | #ifdef CONFIG_X86_32 |
| 1233 | static inline int IO_APIC_irq_trigger(int irq) | 1181 | static inline int IO_APIC_irq_trigger(int irq) |
| 1234 | { | 1182 | { |
| 1235 | int apic, idx, pin; | 1183 | int apic, idx, pin; |
| 1236 | 1184 | ||
| 1237 | for (apic = 0; apic < nr_ioapics; apic++) { | 1185 | for (apic = 0; apic < nr_ioapics; apic++) { |
| 1238 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { | 1186 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { |
| 1239 | idx = find_irq_entry(apic, pin, mp_INT); | 1187 | idx = find_irq_entry(apic, pin, mp_INT); |
| 1240 | if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin))) | 1188 | if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin))) |
| 1241 | return irq_trigger(idx); | 1189 | return irq_trigger(idx); |
| 1242 | } | 1190 | } |
| 1243 | } | 1191 | } |
| 1244 | /* | 1192 | /* |
| 1245 | * nonexistent IRQs are edge default | 1193 | * nonexistent IRQs are edge default |
| 1246 | */ | 1194 | */ |
| 1247 | return 0; | 1195 | return 0; |
| 1248 | } | 1196 | } |
| 1249 | #else | 1197 | #else |
| 1250 | static inline int IO_APIC_irq_trigger(int irq) | 1198 | static inline int IO_APIC_irq_trigger(int irq) |
| @@ -1509,8 +1457,8 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
| 1509 | reg_01.raw = io_apic_read(apic, 1); | 1457 | reg_01.raw = io_apic_read(apic, 1); |
| 1510 | if (reg_01.bits.version >= 0x10) | 1458 | if (reg_01.bits.version >= 0x10) |
| 1511 | reg_02.raw = io_apic_read(apic, 2); | 1459 | reg_02.raw = io_apic_read(apic, 2); |
| 1512 | if (reg_01.bits.version >= 0x20) | 1460 | if (reg_01.bits.version >= 0x20) |
| 1513 | reg_03.raw = io_apic_read(apic, 3); | 1461 | reg_03.raw = io_apic_read(apic, 3); |
| 1514 | spin_unlock_irqrestore(&ioapic_lock, flags); | 1462 | spin_unlock_irqrestore(&ioapic_lock, flags); |
| 1515 | 1463 | ||
| 1516 | printk("\n"); | 1464 | printk("\n"); |
| @@ -2089,9 +2037,9 @@ static int ioapic_retrigger_irq(unsigned int irq) | |||
| 2089 | #else | 2037 | #else |
| 2090 | static int ioapic_retrigger_irq(unsigned int irq) | 2038 | static int ioapic_retrigger_irq(unsigned int irq) |
| 2091 | { | 2039 | { |
| 2092 | send_IPI_self(irq_cfg(irq)->vector); | 2040 | send_IPI_self(irq_cfg(irq)->vector); |
| 2093 | 2041 | ||
| 2094 | return 1; | 2042 | return 1; |
| 2095 | } | 2043 | } |
| 2096 | #endif | 2044 | #endif |
| 2097 | 2045 | ||
| @@ -2189,7 +2137,7 @@ static int migrate_irq_remapped_level(int irq) | |||
| 2189 | 2137 | ||
| 2190 | if (io_apic_level_ack_pending(irq)) { | 2138 | if (io_apic_level_ack_pending(irq)) { |
| 2191 | /* | 2139 | /* |
| 2192 | * Interrupt in progress. Migrating irq now will change the | 2140 | * Interrupt in progress. Migrating irq now will change the |
| 2193 | * vector information in the IO-APIC RTE and that will confuse | 2141 | * vector information in the IO-APIC RTE and that will confuse |
| 2194 | * the EOI broadcast performed by cpu. | 2142 | * the EOI broadcast performed by cpu. |
| 2195 | * So, delay the irq migration to the next instance. | 2143 | * So, delay the irq migration to the next instance. |
| @@ -2426,28 +2374,28 @@ static void ack_apic_level(unsigned int irq) | |||
| 2426 | } | 2374 | } |
| 2427 | 2375 | ||
| 2428 | static struct irq_chip ioapic_chip __read_mostly = { | 2376 | static struct irq_chip ioapic_chip __read_mostly = { |
| 2429 | .name = "IO-APIC", | 2377 | .name = "IO-APIC", |
| 2430 | .startup = startup_ioapic_irq, | 2378 | .startup = startup_ioapic_irq, |
| 2431 | .mask = mask_IO_APIC_irq, | 2379 | .mask = mask_IO_APIC_irq, |
| 2432 | .unmask = unmask_IO_APIC_irq, | 2380 | .unmask = unmask_IO_APIC_irq, |
| 2433 | .ack = ack_apic_edge, | 2381 | .ack = ack_apic_edge, |
| 2434 | .eoi = ack_apic_level, | 2382 | .eoi = ack_apic_level, |
| 2435 | #ifdef CONFIG_SMP | 2383 | #ifdef CONFIG_SMP |
| 2436 | .set_affinity = set_ioapic_affinity_irq, | 2384 | .set_affinity = set_ioapic_affinity_irq, |
| 2437 | #endif | 2385 | #endif |
| 2438 | .retrigger = ioapic_retrigger_irq, | 2386 | .retrigger = ioapic_retrigger_irq, |
| 2439 | }; | 2387 | }; |
| 2440 | 2388 | ||
| 2441 | #ifdef CONFIG_INTR_REMAP | 2389 | #ifdef CONFIG_INTR_REMAP |
| 2442 | static struct irq_chip ir_ioapic_chip __read_mostly = { | 2390 | static struct irq_chip ir_ioapic_chip __read_mostly = { |
| 2443 | .name = "IR-IO-APIC", | 2391 | .name = "IR-IO-APIC", |
| 2444 | .startup = startup_ioapic_irq, | 2392 | .startup = startup_ioapic_irq, |
| 2445 | .mask = mask_IO_APIC_irq, | 2393 | .mask = mask_IO_APIC_irq, |
| 2446 | .unmask = unmask_IO_APIC_irq, | 2394 | .unmask = unmask_IO_APIC_irq, |
| 2447 | .ack = ack_x2apic_edge, | 2395 | .ack = ack_x2apic_edge, |
| 2448 | .eoi = ack_x2apic_level, | 2396 | .eoi = ack_x2apic_level, |
| 2449 | #ifdef CONFIG_SMP | 2397 | #ifdef CONFIG_SMP |
| 2450 | .set_affinity = set_ir_ioapic_affinity_irq, | 2398 | .set_affinity = set_ir_ioapic_affinity_irq, |
| 2451 | #endif | 2399 | #endif |
| 2452 | .retrigger = ioapic_retrigger_irq, | 2400 | .retrigger = ioapic_retrigger_irq, |
| 2453 | }; | 2401 | }; |
| @@ -2636,8 +2584,8 @@ static inline void __init check_timer(void) | |||
| 2636 | 2584 | ||
| 2637 | local_irq_save(flags); | 2585 | local_irq_save(flags); |
| 2638 | 2586 | ||
| 2639 | ver = apic_read(APIC_LVR); | 2587 | ver = apic_read(APIC_LVR); |
| 2640 | ver = GET_APIC_VERSION(ver); | 2588 | ver = GET_APIC_VERSION(ver); |
| 2641 | 2589 | ||
| 2642 | /* | 2590 | /* |
| 2643 | * get/set the timer IRQ vector: | 2591 | * get/set the timer IRQ vector: |
| @@ -2822,12 +2770,12 @@ void __init setup_IO_APIC(void) | |||
| 2822 | io_apic_irqs = ~PIC_IRQS; | 2770 | io_apic_irqs = ~PIC_IRQS; |
| 2823 | 2771 | ||
| 2824 | apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); | 2772 | apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); |
| 2825 | /* | 2773 | /* |
| 2826 | * Set up IO-APIC IRQ routing. | 2774 | * Set up IO-APIC IRQ routing. |
| 2827 | */ | 2775 | */ |
| 2828 | #ifdef CONFIG_X86_32 | 2776 | #ifdef CONFIG_X86_32 |
| 2829 | if (!acpi_ioapic) | 2777 | if (!acpi_ioapic) |
| 2830 | setup_ioapic_ids_from_mpc(); | 2778 | setup_ioapic_ids_from_mpc(); |
| 2831 | #endif | 2779 | #endif |
| 2832 | sync_Arb_IDs(); | 2780 | sync_Arb_IDs(); |
| 2833 | setup_IO_APIC_irqs(); | 2781 | setup_IO_APIC_irqs(); |
| @@ -2842,9 +2790,9 @@ void __init setup_IO_APIC(void) | |||
| 2842 | 2790 | ||
| 2843 | static int __init io_apic_bug_finalize(void) | 2791 | static int __init io_apic_bug_finalize(void) |
| 2844 | { | 2792 | { |
| 2845 | if (sis_apic_bug == -1) | 2793 | if (sis_apic_bug == -1) |
| 2846 | sis_apic_bug = 0; | 2794 | sis_apic_bug = 0; |
| 2847 | return 0; | 2795 | return 0; |
| 2848 | } | 2796 | } |
| 2849 | 2797 | ||
| 2850 | late_initcall(io_apic_bug_finalize); | 2798 | late_initcall(io_apic_bug_finalize); |
| @@ -3199,7 +3147,7 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec) | |||
| 3199 | if (index < 0) { | 3147 | if (index < 0) { |
| 3200 | printk(KERN_ERR | 3148 | printk(KERN_ERR |
| 3201 | "Unable to allocate %d IRTE for PCI %s\n", nvec, | 3149 | "Unable to allocate %d IRTE for PCI %s\n", nvec, |
| 3202 | pci_name(dev)); | 3150 | pci_name(dev)); |
| 3203 | return -ENOSPC; | 3151 | return -ENOSPC; |
| 3204 | } | 3152 | } |
| 3205 | return index; | 3153 | return index; |
| @@ -3885,23 +3833,24 @@ static struct resource * __init ioapic_setup_resources(void) | |||
| 3885 | void __init ioapic_init_mappings(void) | 3833 | void __init ioapic_init_mappings(void) |
| 3886 | { | 3834 | { |
| 3887 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; | 3835 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; |
| 3888 | int i; | ||
| 3889 | struct resource *ioapic_res; | 3836 | struct resource *ioapic_res; |
| 3837 | int i; | ||
| 3890 | 3838 | ||
| 3839 | irq_2_pin_init(); | ||
| 3891 | ioapic_res = ioapic_setup_resources(); | 3840 | ioapic_res = ioapic_setup_resources(); |
| 3892 | for (i = 0; i < nr_ioapics; i++) { | 3841 | for (i = 0; i < nr_ioapics; i++) { |
| 3893 | if (smp_found_config) { | 3842 | if (smp_found_config) { |
| 3894 | ioapic_phys = mp_ioapics[i].mp_apicaddr; | 3843 | ioapic_phys = mp_ioapics[i].mp_apicaddr; |
| 3895 | #ifdef CONFIG_X86_32 | 3844 | #ifdef CONFIG_X86_32 |
| 3896 | if (!ioapic_phys) { | 3845 | if (!ioapic_phys) { |
| 3897 | printk(KERN_ERR | 3846 | printk(KERN_ERR |
| 3898 | "WARNING: bogus zero IO-APIC " | 3847 | "WARNING: bogus zero IO-APIC " |
| 3899 | "address found in MPTABLE, " | 3848 | "address found in MPTABLE, " |
| 3900 | "disabling IO/APIC support!\n"); | 3849 | "disabling IO/APIC support!\n"); |
| 3901 | smp_found_config = 0; | 3850 | smp_found_config = 0; |
| 3902 | skip_ioapic_setup = 1; | 3851 | skip_ioapic_setup = 1; |
| 3903 | goto fake_ioapic_page; | 3852 | goto fake_ioapic_page; |
| 3904 | } | 3853 | } |
| 3905 | #endif | 3854 | #endif |
| 3906 | } else { | 3855 | } else { |
| 3907 | #ifdef CONFIG_X86_32 | 3856 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 2b7dab699e83..410c88f0bfeb 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
| @@ -140,7 +140,7 @@ static void __init setup_cpu_pda_map(void) | |||
| 140 | */ | 140 | */ |
| 141 | void __init setup_per_cpu_areas(void) | 141 | void __init setup_per_cpu_areas(void) |
| 142 | { | 142 | { |
| 143 | ssize_t size, old_size, da_size; | 143 | ssize_t size, old_size; |
| 144 | char *ptr; | 144 | char *ptr; |
| 145 | int cpu; | 145 | int cpu; |
| 146 | unsigned long align = 1; | 146 | unsigned long align = 1; |
| @@ -150,9 +150,8 @@ void __init setup_per_cpu_areas(void) | |||
| 150 | 150 | ||
| 151 | /* Copy section for each CPU (we discard the original) */ | 151 | /* Copy section for each CPU (we discard the original) */ |
| 152 | old_size = PERCPU_ENOUGH_ROOM; | 152 | old_size = PERCPU_ENOUGH_ROOM; |
| 153 | da_size = per_cpu_dyn_array_size(&align); | ||
| 154 | align = max_t(unsigned long, PAGE_SIZE, align); | 153 | align = max_t(unsigned long, PAGE_SIZE, align); |
| 155 | size = roundup(old_size + da_size, align); | 154 | size = roundup(old_size, align); |
| 156 | printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n", | 155 | printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n", |
| 157 | size); | 156 | size); |
| 158 | 157 | ||
| @@ -182,9 +181,6 @@ void __init setup_per_cpu_areas(void) | |||
| 182 | #endif | 181 | #endif |
| 183 | per_cpu_offset(cpu) = ptr - __per_cpu_start; | 182 | per_cpu_offset(cpu) = ptr - __per_cpu_start; |
| 184 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); | 183 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); |
| 185 | |||
| 186 | per_cpu_alloc_dyn_array(cpu, ptr + old_size); | ||
| 187 | |||
| 188 | } | 184 | } |
| 189 | 185 | ||
| 190 | printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d, nr_node_ids %d\n", | 186 | printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d, nr_node_ids %d\n", |
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 817aa55a1209..0c9667f0752a 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c | |||
| @@ -633,7 +633,7 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id) | |||
| 633 | /* | 633 | /* |
| 634 | * handle this 'virtual interrupt' as a Cobalt one now. | 634 | * handle this 'virtual interrupt' as a Cobalt one now. |
| 635 | */ | 635 | */ |
| 636 | kstat_irqs_this_cpu(desc)++; | 636 | kstat_incr_irqs_this_cpu(realirq, desc); |
| 637 | 637 | ||
| 638 | if (likely(desc->action != NULL)) | 638 | if (likely(desc->action != NULL)) |
| 639 | handle_IRQ_event(realirq, desc->action); | 639 | handle_IRQ_event(realirq, desc->action); |
diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S index c36007ab3940..a9b8560adbc2 100644 --- a/arch/x86/kernel/vmlinux_32.lds.S +++ b/arch/x86/kernel/vmlinux_32.lds.S | |||
| @@ -145,7 +145,6 @@ SECTIONS | |||
| 145 | *(.x86_cpu_dev.init) | 145 | *(.x86_cpu_dev.init) |
| 146 | __x86_cpu_dev_end = .; | 146 | __x86_cpu_dev_end = .; |
| 147 | } | 147 | } |
| 148 | DYN_ARRAY_INIT(8) | ||
| 149 | SECURITY_INIT | 148 | SECURITY_INIT |
| 150 | . = ALIGN(4); | 149 | . = ALIGN(4); |
| 151 | .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { | 150 | .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { |
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 30973dbac8c2..3245ad72594a 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S | |||
| @@ -174,8 +174,6 @@ SECTIONS | |||
| 174 | } | 174 | } |
| 175 | __x86_cpu_dev_end = .; | 175 | __x86_cpu_dev_end = .; |
| 176 | 176 | ||
| 177 | DYN_ARRAY_INIT(8) | ||
| 178 | |||
| 179 | SECURITY_INIT | 177 | SECURITY_INIT |
| 180 | 178 | ||
| 181 | . = ALIGN(8); | 179 | . = ALIGN(8); |
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index bb6bc721b13d..5601506f2dd9 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c | |||
| @@ -241,7 +241,7 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enabl | |||
| 241 | ADD_STATS(taken_slow_spurious, !xen_test_irq_pending(irq)); | 241 | ADD_STATS(taken_slow_spurious, !xen_test_irq_pending(irq)); |
| 242 | } while (!xen_test_irq_pending(irq)); /* check for spurious wakeups */ | 242 | } while (!xen_test_irq_pending(irq)); /* check for spurious wakeups */ |
| 243 | 243 | ||
| 244 | kstat_irqs_this_cpu(irq_to_desc(irq))++; | 244 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); |
| 245 | 245 | ||
| 246 | out: | 246 | out: |
| 247 | raw_local_irq_restore(flags); | 247 | raw_local_irq_restore(flags); |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 9ce80213007b..1137d2976043 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -558,12 +558,7 @@ struct timer_rand_state { | |||
| 558 | unsigned dont_count_entropy:1; | 558 | unsigned dont_count_entropy:1; |
| 559 | }; | 559 | }; |
| 560 | 560 | ||
| 561 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 562 | static struct timer_rand_state **irq_timer_state; | ||
| 563 | DEFINE_DYN_ARRAY(irq_timer_state, sizeof(struct timer_rand_state *), nr_irqs, PAGE_SIZE, NULL); | ||
| 564 | #else | ||
| 565 | static struct timer_rand_state *irq_timer_state[NR_IRQS]; | 561 | static struct timer_rand_state *irq_timer_state[NR_IRQS]; |
| 566 | #endif | ||
| 567 | 562 | ||
| 568 | static struct timer_rand_state *get_timer_rand_state(unsigned int irq) | 563 | static struct timer_rand_state *get_timer_rand_state(unsigned int irq) |
| 569 | { | 564 | { |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 0f43b265eee6..950769e87475 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
| @@ -19,20 +19,13 @@ struct irq_2_iommu { | |||
| 19 | u8 irte_mask; | 19 | u8 irte_mask; |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 23 | static struct irq_2_iommu *irq_2_iommuX; | ||
| 24 | DEFINE_DYN_ARRAY(irq_2_iommuX, sizeof(struct irq_2_iommu), nr_irqs, PAGE_SIZE, NULL); | ||
| 25 | #else | ||
| 26 | static struct irq_2_iommu irq_2_iommuX[NR_IRQS]; | 22 | static struct irq_2_iommu irq_2_iommuX[NR_IRQS]; |
| 27 | #endif | ||
| 28 | 23 | ||
| 29 | static struct irq_2_iommu *irq_2_iommu(unsigned int irq) | 24 | static struct irq_2_iommu *irq_2_iommu(unsigned int irq) |
| 30 | { | 25 | { |
| 31 | if (irq < nr_irqs) | 26 | return (irq < nr_irqs) ?: irq_2_iommuX + irq : NULL; |
| 32 | return &irq_2_iommuX[irq]; | ||
| 33 | |||
| 34 | return NULL; | ||
| 35 | } | 27 | } |
| 28 | |||
| 36 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) | 29 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) |
| 37 | { | 30 | { |
| 38 | return irq_2_iommu(irq); | 31 | return irq_2_iommu(irq); |
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c68eda9d9a90..7440a0dceddb 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
| @@ -210,19 +210,6 @@ | |||
| 210 | * All archs are supposed to use RO_DATA() */ | 210 | * All archs are supposed to use RO_DATA() */ |
| 211 | #define RODATA RO_DATA(4096) | 211 | #define RODATA RO_DATA(4096) |
| 212 | 212 | ||
| 213 | #define DYN_ARRAY_INIT(align) \ | ||
| 214 | . = ALIGN((align)); \ | ||
| 215 | .dyn_array.init : AT(ADDR(.dyn_array.init) - LOAD_OFFSET) { \ | ||
| 216 | VMLINUX_SYMBOL(__dyn_array_start) = .; \ | ||
| 217 | *(.dyn_array.init) \ | ||
| 218 | VMLINUX_SYMBOL(__dyn_array_end) = .; \ | ||
| 219 | } \ | ||
| 220 | . = ALIGN((align)); \ | ||
| 221 | .per_cpu_dyn_array.init : AT(ADDR(.per_cpu_dyn_array.init) - LOAD_OFFSET) { \ | ||
| 222 | VMLINUX_SYMBOL(__per_cpu_dyn_array_start) = .; \ | ||
| 223 | *(.per_cpu_dyn_array.init) \ | ||
| 224 | VMLINUX_SYMBOL(__per_cpu_dyn_array_end) = .; \ | ||
| 225 | } | ||
| 226 | #define SECURITY_INIT \ | 213 | #define SECURITY_INIT \ |
| 227 | .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \ | 214 | .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \ |
| 228 | VMLINUX_SYMBOL(__security_initcall_start) = .; \ | 215 | VMLINUX_SYMBOL(__security_initcall_start) = .; \ |
diff --git a/include/linux/init.h b/include/linux/init.h index 59fbb4aaba6a..70ad53e1eab8 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
| @@ -247,49 +247,6 @@ struct obs_kernel_param { | |||
| 247 | /* Relies on boot_command_line being set */ | 247 | /* Relies on boot_command_line being set */ |
| 248 | void __init parse_early_param(void); | 248 | void __init parse_early_param(void); |
| 249 | 249 | ||
| 250 | struct dyn_array { | ||
| 251 | void **name; | ||
| 252 | unsigned long size; | ||
| 253 | unsigned int *nr; | ||
| 254 | unsigned long align; | ||
| 255 | void (*init_work)(void *); | ||
| 256 | }; | ||
| 257 | extern struct dyn_array *__dyn_array_start[], *__dyn_array_end[]; | ||
| 258 | extern struct dyn_array *__per_cpu_dyn_array_start[], *__per_cpu_dyn_array_end[]; | ||
| 259 | |||
| 260 | #define DEFINE_DYN_ARRAY_ADDR(nameX, addrX, sizeX, nrX, alignX, init_workX) \ | ||
| 261 | static struct dyn_array __dyn_array_##nameX __initdata = \ | ||
| 262 | { .name = (void **)&(nameX),\ | ||
| 263 | .size = sizeX,\ | ||
| 264 | .nr = &(nrX),\ | ||
| 265 | .align = alignX,\ | ||
| 266 | .init_work = init_workX,\ | ||
| 267 | }; \ | ||
| 268 | static struct dyn_array *__dyn_array_ptr_##nameX __used \ | ||
| 269 | __attribute__((__section__(".dyn_array.init"))) = \ | ||
| 270 | &__dyn_array_##nameX | ||
| 271 | |||
| 272 | #define DEFINE_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \ | ||
| 273 | DEFINE_DYN_ARRAY_ADDR(nameX, nameX, sizeX, nrX, alignX, init_workX) | ||
| 274 | |||
| 275 | #define DEFINE_PER_CPU_DYN_ARRAY_ADDR(nameX, addrX, sizeX, nrX, alignX, init_workX) \ | ||
| 276 | static struct dyn_array __per_cpu_dyn_array_##nameX __initdata = \ | ||
| 277 | { .name = (void **)&(addrX),\ | ||
| 278 | .size = sizeX,\ | ||
| 279 | .nr = &(nrX),\ | ||
| 280 | .align = alignX,\ | ||
| 281 | .init_work = init_workX,\ | ||
| 282 | }; \ | ||
| 283 | static struct dyn_array *__per_cpu_dyn_array_ptr_##nameX __used \ | ||
| 284 | __attribute__((__section__(".per_cpu_dyn_array.init"))) = \ | ||
| 285 | &__per_cpu_dyn_array_##nameX | ||
| 286 | |||
| 287 | #define DEFINE_PER_CPU_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \ | ||
| 288 | DEFINE_PER_CPU_DYN_ARRAY_ADDR(nameX, nameX, nrX, alignX, init_workX) | ||
| 289 | |||
| 290 | extern void pre_alloc_dyn_array(void); | ||
| 291 | extern unsigned long per_cpu_dyn_array_size(unsigned long *align); | ||
| 292 | extern void per_cpu_alloc_dyn_array(int cpu, char *ptr); | ||
| 293 | #endif /* __ASSEMBLY__ */ | 250 | #endif /* __ASSEMBLY__ */ |
| 294 | 251 | ||
| 295 | /** | 252 | /** |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 3f33c7790300..38bf89f2ade0 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
| @@ -139,8 +139,6 @@ struct irq_chip { | |||
| 139 | const char *typename; | 139 | const char *typename; |
| 140 | }; | 140 | }; |
| 141 | 141 | ||
| 142 | struct timer_rand_state; | ||
| 143 | struct irq_2_iommu; | ||
| 144 | /** | 142 | /** |
| 145 | * struct irq_desc - interrupt descriptor | 143 | * struct irq_desc - interrupt descriptor |
| 146 | * | 144 | * |
| @@ -167,9 +165,6 @@ struct irq_2_iommu; | |||
| 167 | */ | 165 | */ |
| 168 | struct irq_desc { | 166 | struct irq_desc { |
| 169 | unsigned int irq; | 167 | unsigned int irq; |
| 170 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 171 | unsigned int *kstat_irqs; | ||
| 172 | #endif | ||
| 173 | irq_flow_handler_t handle_irq; | 168 | irq_flow_handler_t handle_irq; |
| 174 | struct irq_chip *chip; | 169 | struct irq_chip *chip; |
| 175 | struct msi_desc *msi_desc; | 170 | struct msi_desc *msi_desc; |
| @@ -198,23 +193,13 @@ struct irq_desc { | |||
| 198 | } ____cacheline_internodealigned_in_smp; | 193 | } ____cacheline_internodealigned_in_smp; |
| 199 | 194 | ||
| 200 | 195 | ||
| 201 | #ifndef CONFIG_HAVE_DYN_ARRAY | ||
| 202 | /* could be removed if we get rid of all irq_desc reference */ | ||
| 203 | extern struct irq_desc irq_desc[NR_IRQS]; | 196 | extern struct irq_desc irq_desc[NR_IRQS]; |
| 204 | #else | ||
| 205 | extern struct irq_desc *irq_desc; | ||
| 206 | #endif | ||
| 207 | 197 | ||
| 208 | static inline struct irq_desc *irq_to_desc(unsigned int irq) | 198 | static inline struct irq_desc *irq_to_desc(unsigned int irq) |
| 209 | { | 199 | { |
| 210 | return (irq < nr_irqs) ? irq_desc + irq : NULL; | 200 | return (irq < nr_irqs) ? irq_desc + irq : NULL; |
| 211 | } | 201 | } |
| 212 | 202 | ||
| 213 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 214 | #define kstat_irqs_this_cpu(DESC) \ | ||
| 215 | ((DESC)->kstat_irqs[smp_processor_id()]) | ||
| 216 | #endif | ||
| 217 | |||
| 218 | /* | 203 | /* |
| 219 | * Migration helpers for obsolete names, they will go away: | 204 | * Migration helpers for obsolete names, they will go away: |
| 220 | */ | 205 | */ |
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 21249d8c1293..a9d0d360b776 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h | |||
| @@ -28,9 +28,7 @@ struct cpu_usage_stat { | |||
| 28 | 28 | ||
| 29 | struct kernel_stat { | 29 | struct kernel_stat { |
| 30 | struct cpu_usage_stat cpustat; | 30 | struct cpu_usage_stat cpustat; |
| 31 | #ifndef CONFIG_HAVE_DYN_ARRAY | ||
| 32 | unsigned int irqs[NR_IRQS]; | 31 | unsigned int irqs[NR_IRQS]; |
| 33 | #endif | ||
| 34 | }; | 32 | }; |
| 35 | 33 | ||
| 36 | DECLARE_PER_CPU(struct kernel_stat, kstat); | 34 | DECLARE_PER_CPU(struct kernel_stat, kstat); |
| @@ -41,20 +39,18 @@ DECLARE_PER_CPU(struct kernel_stat, kstat); | |||
| 41 | 39 | ||
| 42 | extern unsigned long long nr_context_switches(void); | 40 | extern unsigned long long nr_context_switches(void); |
| 43 | 41 | ||
| 44 | #ifndef CONFIG_HAVE_DYN_ARRAY | 42 | struct irq_desc; |
| 45 | #define kstat_irqs_this_cpu(irq) \ | ||
| 46 | (kstat_this_cpu.irqs[irq]) | ||
| 47 | #endif | ||
| 48 | 43 | ||
| 44 | static inline void kstat_incr_irqs_this_cpu(unsigned int irq, | ||
| 45 | struct irq_desc *desc) | ||
| 46 | { | ||
| 47 | kstat_this_cpu.irqs[irq]++; | ||
| 48 | } | ||
| 49 | 49 | ||
| 50 | #ifndef CONFIG_HAVE_DYN_ARRAY | ||
| 51 | static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) | 50 | static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) |
| 52 | { | 51 | { |
| 53 | return kstat_cpu(cpu).irqs[irq]; | 52 | return kstat_cpu(cpu).irqs[irq]; |
| 54 | } | 53 | } |
| 55 | #else | ||
| 56 | extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu); | ||
| 57 | #endif | ||
| 58 | 54 | ||
| 59 | /* | 55 | /* |
| 60 | * Number of interrupts per specific IRQ source, since bootup | 56 | * Number of interrupts per specific IRQ source, since bootup |
diff --git a/init/Makefile b/init/Makefile index dc5eeca6eb6d..4a243df426f7 100644 --- a/init/Makefile +++ b/init/Makefile | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y := main.o dyn_array.o version.o mounts.o | 5 | obj-y := main.o version.o mounts.o |
| 6 | ifneq ($(CONFIG_BLK_DEV_INITRD),y) | 6 | ifneq ($(CONFIG_BLK_DEV_INITRD),y) |
| 7 | obj-y += noinitramfs.o | 7 | obj-y += noinitramfs.o |
| 8 | else | 8 | else |
diff --git a/init/dyn_array.c b/init/dyn_array.c deleted file mode 100644 index c8d5e2a18588..000000000000 --- a/init/dyn_array.c +++ /dev/null | |||
| @@ -1,120 +0,0 @@ | |||
| 1 | #include <linux/types.h> | ||
| 2 | #include <linux/kernel.h> | ||
| 3 | #include <linux/kallsyms.h> | ||
| 4 | #include <linux/init.h> | ||
| 5 | #include <linux/bootmem.h> | ||
| 6 | #include <linux/irq.h> | ||
| 7 | |||
| 8 | void __init pre_alloc_dyn_array(void) | ||
| 9 | { | ||
| 10 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 11 | unsigned long total_size = 0, size, phys; | ||
| 12 | unsigned long max_align = 1; | ||
| 13 | struct dyn_array **daa; | ||
| 14 | char *ptr; | ||
| 15 | |||
| 16 | /* get the total size at first */ | ||
| 17 | for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) { | ||
| 18 | struct dyn_array *da = *daa; | ||
| 19 | |||
| 20 | printk(KERN_DEBUG "dyn_array %pF size:%#lx nr:%d align:%#lx\n", | ||
| 21 | da->name, da->size, *da->nr, da->align); | ||
| 22 | size = da->size * (*da->nr); | ||
| 23 | total_size += roundup(size, da->align); | ||
| 24 | if (da->align > max_align) | ||
| 25 | max_align = da->align; | ||
| 26 | } | ||
| 27 | if (total_size) | ||
| 28 | printk(KERN_DEBUG "dyn_array total_size: %#lx\n", | ||
| 29 | total_size); | ||
| 30 | else | ||
| 31 | return; | ||
| 32 | |||
| 33 | /* allocate them all together */ | ||
| 34 | max_align = max_t(unsigned long, max_align, PAGE_SIZE); | ||
| 35 | ptr = __alloc_bootmem(total_size, max_align, 0); | ||
| 36 | phys = virt_to_phys(ptr); | ||
| 37 | |||
| 38 | for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) { | ||
| 39 | struct dyn_array *da = *daa; | ||
| 40 | |||
| 41 | size = da->size * (*da->nr); | ||
| 42 | phys = roundup(phys, da->align); | ||
| 43 | printk(KERN_DEBUG "dyn_array %pF ==> [%#lx - %#lx]\n", | ||
| 44 | da->name, phys, phys + size); | ||
| 45 | *da->name = phys_to_virt(phys); | ||
| 46 | |||
| 47 | phys += size; | ||
| 48 | |||
| 49 | if (da->init_work) | ||
| 50 | da->init_work(da); | ||
| 51 | } | ||
| 52 | #else | ||
| 53 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
| 54 | unsigned int i; | ||
| 55 | |||
| 56 | for (i = 0; i < NR_IRQS; i++) | ||
| 57 | irq_desc[i].irq = i; | ||
| 58 | #endif | ||
| 59 | #endif | ||
| 60 | } | ||
| 61 | |||
| 62 | unsigned long __init per_cpu_dyn_array_size(unsigned long *align) | ||
| 63 | { | ||
| 64 | unsigned long total_size = 0; | ||
| 65 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 66 | unsigned long size; | ||
| 67 | struct dyn_array **daa; | ||
| 68 | unsigned max_align = 1; | ||
| 69 | |||
| 70 | for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) { | ||
| 71 | struct dyn_array *da = *daa; | ||
| 72 | |||
| 73 | printk(KERN_DEBUG "per_cpu_dyn_array %pF size:%#lx nr:%d align:%#lx\n", | ||
| 74 | da->name, da->size, *da->nr, da->align); | ||
| 75 | size = da->size * (*da->nr); | ||
| 76 | total_size += roundup(size, da->align); | ||
| 77 | if (da->align > max_align) | ||
| 78 | max_align = da->align; | ||
| 79 | } | ||
| 80 | if (total_size) { | ||
| 81 | printk(KERN_DEBUG "per_cpu_dyn_array total_size: %#lx\n", | ||
| 82 | total_size); | ||
| 83 | *align = max_align; | ||
| 84 | } | ||
| 85 | #endif | ||
| 86 | return total_size; | ||
| 87 | } | ||
| 88 | |||
| 89 | #ifdef CONFIG_SMP | ||
| 90 | void __init per_cpu_alloc_dyn_array(int cpu, char *ptr) | ||
| 91 | { | ||
| 92 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 93 | unsigned long size, phys; | ||
| 94 | struct dyn_array **daa; | ||
| 95 | unsigned long addr; | ||
| 96 | void **array; | ||
| 97 | |||
| 98 | phys = virt_to_phys(ptr); | ||
| 99 | for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) { | ||
| 100 | struct dyn_array *da = *daa; | ||
| 101 | |||
| 102 | size = da->size * (*da->nr); | ||
| 103 | phys = roundup(phys, da->align); | ||
| 104 | printk(KERN_DEBUG "per_cpu_dyn_array %pF ==> [%#lx - %#lx]\n", | ||
| 105 | da->name, phys, phys + size); | ||
| 106 | |||
| 107 | addr = (unsigned long)da->name; | ||
| 108 | addr += per_cpu_offset(cpu); | ||
| 109 | array = (void **)addr; | ||
| 110 | *array = phys_to_virt(phys); | ||
| 111 | *da->name = *array; /* so init_work could use it directly */ | ||
| 112 | |||
| 113 | phys += size; | ||
| 114 | |||
| 115 | if (da->init_work) | ||
| 116 | da->init_work(da); | ||
| 117 | } | ||
| 118 | #endif | ||
| 119 | } | ||
| 120 | #endif | ||
diff --git a/init/main.c b/init/main.c index e81cf427d9c7..27f6bf6108e9 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -391,23 +391,17 @@ EXPORT_SYMBOL(__per_cpu_offset); | |||
| 391 | 391 | ||
| 392 | static void __init setup_per_cpu_areas(void) | 392 | static void __init setup_per_cpu_areas(void) |
| 393 | { | 393 | { |
| 394 | unsigned long size, i, old_size; | 394 | unsigned long size, i; |
| 395 | char *ptr; | 395 | char *ptr; |
| 396 | unsigned long nr_possible_cpus = num_possible_cpus(); | 396 | unsigned long nr_possible_cpus = num_possible_cpus(); |
| 397 | unsigned long align = 1; | ||
| 398 | unsigned da_size; | ||
| 399 | 397 | ||
| 400 | /* Copy section for each CPU (we discard the original) */ | 398 | /* Copy section for each CPU (we discard the original) */ |
| 401 | old_size = PERCPU_ENOUGH_ROOM; | 399 | size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE); |
| 402 | da_size = per_cpu_dyn_array_size(&align); | ||
| 403 | align = max_t(unsigned long, PAGE_SIZE, align); | ||
| 404 | size = ALIGN(old_size + da_size, align); | ||
| 405 | ptr = alloc_bootmem_pages(size * nr_possible_cpus); | 400 | ptr = alloc_bootmem_pages(size * nr_possible_cpus); |
| 406 | 401 | ||
| 407 | for_each_possible_cpu(i) { | 402 | for_each_possible_cpu(i) { |
| 408 | __per_cpu_offset[i] = ptr - __per_cpu_start; | 403 | __per_cpu_offset[i] = ptr - __per_cpu_start; |
| 409 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); | 404 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); |
| 410 | per_cpu_alloc_dyn_array(i, ptr + old_size); | ||
| 411 | ptr += size; | 405 | ptr += size; |
| 412 | } | 406 | } |
| 413 | } | 407 | } |
| @@ -573,7 +567,6 @@ asmlinkage void __init start_kernel(void) | |||
| 573 | printk(KERN_NOTICE); | 567 | printk(KERN_NOTICE); |
| 574 | printk(linux_banner); | 568 | printk(linux_banner); |
| 575 | setup_arch(&command_line); | 569 | setup_arch(&command_line); |
| 576 | pre_alloc_dyn_array(); | ||
| 577 | mm_init_owner(&init_mm, &init_task); | 570 | mm_init_owner(&init_mm, &init_task); |
| 578 | setup_command_line(command_line); | 571 | setup_command_line(command_line); |
| 579 | unwind_setup(); | 572 | unwind_setup(); |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index e6f73dbfcc3d..d96d6f687c48 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -326,11 +326,7 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) | |||
| 326 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 326 | if (unlikely(desc->status & IRQ_INPROGRESS)) |
| 327 | goto out_unlock; | 327 | goto out_unlock; |
| 328 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 328 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
| 329 | #ifdef CONFIG_HAVE_DYN_ARRAY | 329 | kstat_incr_irqs_this_cpu(irq, desc); |
| 330 | kstat_irqs_this_cpu(desc)++; | ||
| 331 | #else | ||
| 332 | kstat_irqs_this_cpu(irq)++; | ||
| 333 | #endif | ||
| 334 | 330 | ||
| 335 | action = desc->action; | 331 | action = desc->action; |
| 336 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | 332 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) |
| @@ -371,11 +367,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 371 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 367 | if (unlikely(desc->status & IRQ_INPROGRESS)) |
| 372 | goto out_unlock; | 368 | goto out_unlock; |
| 373 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 369 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
| 374 | #ifdef CONFIG_HAVE_DYN_ARRAY | 370 | kstat_incr_irqs_this_cpu(irq, desc); |
| 375 | kstat_irqs_this_cpu(desc)++; | ||
| 376 | #else | ||
| 377 | kstat_irqs_this_cpu(irq)++; | ||
| 378 | #endif | ||
| 379 | 371 | ||
| 380 | /* | 372 | /* |
| 381 | * If its disabled or no action available | 373 | * If its disabled or no action available |
| @@ -422,11 +414,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
| 422 | goto out; | 414 | goto out; |
| 423 | 415 | ||
| 424 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 416 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
| 425 | #ifdef CONFIG_HAVE_DYN_ARRAY | 417 | kstat_incr_irqs_this_cpu(irq, desc); |
| 426 | kstat_irqs_this_cpu(desc)++; | ||
| 427 | #else | ||
| 428 | kstat_irqs_this_cpu(irq)++; | ||
| 429 | #endif | ||
| 430 | 418 | ||
| 431 | /* | 419 | /* |
| 432 | * If its disabled or no action available | 420 | * If its disabled or no action available |
| @@ -490,11 +478,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
| 490 | mask_ack_irq(desc, irq); | 478 | mask_ack_irq(desc, irq); |
| 491 | goto out_unlock; | 479 | goto out_unlock; |
| 492 | } | 480 | } |
| 493 | #ifdef CONFIG_HAVE_DYN_ARRAY | 481 | kstat_incr_irqs_this_cpu(irq, desc); |
| 494 | kstat_irqs_this_cpu(desc)++; | ||
| 495 | #else | ||
| 496 | kstat_irqs_this_cpu(irq)++; | ||
| 497 | #endif | ||
| 498 | 482 | ||
| 499 | /* Start handling the irq */ | 483 | /* Start handling the irq */ |
| 500 | desc->chip->ack(irq); | 484 | desc->chip->ack(irq); |
| @@ -549,11 +533,7 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) | |||
| 549 | { | 533 | { |
| 550 | irqreturn_t action_ret; | 534 | irqreturn_t action_ret; |
| 551 | 535 | ||
| 552 | #ifdef CONFIG_HAVE_DYN_ARRAY | 536 | kstat_incr_irqs_this_cpu(irq, desc); |
| 553 | kstat_irqs_this_cpu(desc)++; | ||
| 554 | #else | ||
| 555 | kstat_irqs_this_cpu(irq)++; | ||
| 556 | #endif | ||
| 557 | 537 | ||
| 558 | if (desc->chip->ack) | 538 | if (desc->chip->ack) |
| 559 | desc->chip->ack(irq); | 539 | desc->chip->ack(irq); |
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index f837133cdfbe..9fe86b3a60a5 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
| @@ -18,11 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | #include "internals.h" | 19 | #include "internals.h" |
| 20 | 20 | ||
| 21 | /* | ||
| 22 | * lockdep: we want to handle all irq_desc locks as a single lock-class: | ||
| 23 | */ | ||
| 24 | static struct lock_class_key irq_desc_lock_class; | ||
| 25 | |||
| 26 | /** | 21 | /** |
| 27 | * handle_bad_irq - handle spurious and unhandled irqs | 22 | * handle_bad_irq - handle spurious and unhandled irqs |
| 28 | * @irq: the interrupt number | 23 | * @irq: the interrupt number |
| @@ -30,15 +25,10 @@ static struct lock_class_key irq_desc_lock_class; | |||
| 30 | * | 25 | * |
| 31 | * Handles spurious and unhandled IRQ's. It also prints a debugmessage. | 26 | * Handles spurious and unhandled IRQ's. It also prints a debugmessage. |
| 32 | */ | 27 | */ |
| 33 | void | 28 | void handle_bad_irq(unsigned int irq, struct irq_desc *desc) |
| 34 | handle_bad_irq(unsigned int irq, struct irq_desc *desc) | ||
| 35 | { | 29 | { |
| 36 | print_irq_desc(irq, desc); | 30 | print_irq_desc(irq, desc); |
| 37 | #ifdef CONFIG_HAVE_DYN_ARRAY | 31 | kstat_incr_irqs_this_cpu(irq, desc); |
| 38 | kstat_irqs_this_cpu(desc)++; | ||
| 39 | #else | ||
| 40 | kstat_irqs_this_cpu(irq)++; | ||
| 41 | #endif | ||
| 42 | ack_bad_irq(irq); | 32 | ack_bad_irq(irq); |
| 43 | } | 33 | } |
| 44 | 34 | ||
| @@ -59,80 +49,6 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc) | |||
| 59 | int nr_irqs = NR_IRQS; | 49 | int nr_irqs = NR_IRQS; |
| 60 | EXPORT_SYMBOL_GPL(nr_irqs); | 50 | EXPORT_SYMBOL_GPL(nr_irqs); |
| 61 | 51 | ||
| 62 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 63 | static struct irq_desc irq_desc_init = { | ||
| 64 | .irq = -1U, | ||
| 65 | .status = IRQ_DISABLED, | ||
| 66 | .chip = &no_irq_chip, | ||
| 67 | .handle_irq = handle_bad_irq, | ||
| 68 | .depth = 1, | ||
| 69 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), | ||
| 70 | #ifdef CONFIG_SMP | ||
| 71 | .affinity = CPU_MASK_ALL | ||
| 72 | #endif | ||
| 73 | }; | ||
| 74 | |||
| 75 | |||
| 76 | static void init_one_irq_desc(struct irq_desc *desc) | ||
| 77 | { | ||
| 78 | memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); | ||
| 79 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); | ||
| 80 | } | ||
| 81 | |||
| 82 | extern int after_bootmem; | ||
| 83 | extern void *__alloc_bootmem_nopanic(unsigned long size, | ||
| 84 | unsigned long align, | ||
| 85 | unsigned long goal); | ||
| 86 | |||
| 87 | static void init_kstat_irqs(struct irq_desc *desc, int nr_desc, int nr) | ||
| 88 | { | ||
| 89 | unsigned long bytes, total_bytes; | ||
| 90 | char *ptr; | ||
| 91 | int i; | ||
| 92 | unsigned long phys; | ||
| 93 | |||
| 94 | /* Compute how many bytes we need per irq and allocate them */ | ||
| 95 | bytes = nr * sizeof(unsigned int); | ||
| 96 | total_bytes = bytes * nr_desc; | ||
| 97 | if (after_bootmem) | ||
| 98 | ptr = kzalloc(total_bytes, GFP_ATOMIC); | ||
| 99 | else | ||
| 100 | ptr = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0); | ||
| 101 | |||
| 102 | if (!ptr) | ||
| 103 | panic(" can not allocate kstat_irqs\n"); | ||
| 104 | |||
| 105 | phys = __pa(ptr); | ||
| 106 | printk(KERN_DEBUG "kstat_irqs ==> [%#lx - %#lx]\n", phys, phys + total_bytes); | ||
| 107 | |||
| 108 | for (i = 0; i < nr_desc; i++) { | ||
| 109 | desc[i].kstat_irqs = (unsigned int *)ptr; | ||
| 110 | ptr += bytes; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | static void __init init_work(void *data) | ||
| 115 | { | ||
| 116 | struct dyn_array *da = data; | ||
| 117 | int i; | ||
| 118 | struct irq_desc *desc; | ||
| 119 | |||
| 120 | desc = *da->name; | ||
| 121 | |||
| 122 | for (i = 0; i < *da->nr; i++) { | ||
| 123 | init_one_irq_desc(&desc[i]); | ||
| 124 | desc[i].irq = i; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* init kstat_irqs, nr_cpu_ids is ready already */ | ||
| 128 | init_kstat_irqs(desc, *da->nr, nr_cpu_ids); | ||
| 129 | } | ||
| 130 | |||
| 131 | struct irq_desc *irq_desc; | ||
| 132 | DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work); | ||
| 133 | |||
| 134 | #else | ||
| 135 | |||
| 136 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | 52 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { |
| 137 | [0 ... NR_IRQS-1] = { | 53 | [0 ... NR_IRQS-1] = { |
| 138 | .status = IRQ_DISABLED, | 54 | .status = IRQ_DISABLED, |
| @@ -146,8 +62,6 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | |||
| 146 | } | 62 | } |
| 147 | }; | 63 | }; |
| 148 | 64 | ||
| 149 | #endif | ||
| 150 | |||
| 151 | /* | 65 | /* |
| 152 | * What should we do if we get a hw irq event on an illegal vector? | 66 | * What should we do if we get a hw irq event on an illegal vector? |
| 153 | * Each architecture has to answer this themself. | 67 | * Each architecture has to answer this themself. |
| @@ -258,11 +172,8 @@ unsigned int __do_IRQ(unsigned int irq) | |||
| 258 | struct irqaction *action; | 172 | struct irqaction *action; |
| 259 | unsigned int status; | 173 | unsigned int status; |
| 260 | 174 | ||
| 261 | #ifdef CONFIG_HAVE_DYN_ARRAY | 175 | kstat_incr_irqs_this_cpu(irq, desc); |
| 262 | kstat_irqs_this_cpu(desc)++; | 176 | |
| 263 | #else | ||
| 264 | kstat_irqs_this_cpu(irq)++; | ||
| 265 | #endif | ||
| 266 | if (CHECK_IRQ_PER_CPU(desc->status)) { | 177 | if (CHECK_IRQ_PER_CPU(desc->status)) { |
| 267 | irqreturn_t action_ret; | 178 | irqreturn_t action_ret; |
| 268 | 179 | ||
| @@ -351,23 +262,16 @@ out: | |||
| 351 | 262 | ||
| 352 | 263 | ||
| 353 | #ifdef CONFIG_TRACE_IRQFLAGS | 264 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 265 | /* | ||
| 266 | * lockdep: we want to handle all irq_desc locks as a single lock-class: | ||
| 267 | */ | ||
| 268 | static struct lock_class_key irq_desc_lock_class; | ||
| 269 | |||
| 354 | void early_init_irq_lock_class(void) | 270 | void early_init_irq_lock_class(void) |
| 355 | { | 271 | { |
| 356 | #ifndef CONFIG_HAVE_DYN_ARRAY | ||
| 357 | int i; | 272 | int i; |
| 358 | 273 | ||
| 359 | for (i = 0; i < nr_irqs; i++) | 274 | for (i = 0; i < nr_irqs; i++) |
| 360 | lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class); | 275 | lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class); |
| 361 | #endif | ||
| 362 | } | 276 | } |
| 363 | #endif | 277 | #endif |
| 364 | |||
| 365 | #ifdef CONFIG_HAVE_DYN_ARRAY | ||
| 366 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) | ||
| 367 | { | ||
| 368 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 369 | return desc->kstat_irqs[cpu]; | ||
| 370 | } | ||
| 371 | #endif | ||
| 372 | EXPORT_SYMBOL(kstat_irqs_cpu); | ||
| 373 | |||
