aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic_64.c
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel@gmail.com>2008-08-19 23:50:07 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-16 10:52:31 -0400
commite5a53714acfc7b5f868d07d27c5f02cb00b118db (patch)
tree087446051c2af229177c1d2aa079d7255077ebb0 /arch/x86/kernel/io_apic_64.c
parent3ac2de48ed3c998df7f366e039c97eedb27e7c3d (diff)
x86: put irq_2_pin pointer into irq_cfg
preallocate 32 irq_2_pin entries, and use get_one_free_irq_2_pin() to get one more and link to irq_cfg if needed. so don't waste one where no irq is enabled. Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/io_apic_64.c')
-rw-r--r--arch/x86/kernel/io_apic_64.c161
1 files changed, 120 insertions, 41 deletions
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index 858c37a31a2f..51ef7eb75f2e 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -58,10 +58,11 @@
58#define __apicdebuginit(type) static type __init 58#define __apicdebuginit(type) static type __init
59 59
60struct irq_cfg; 60struct irq_cfg;
61 61struct irq_pin_list;
62struct irq_cfg { 62struct irq_cfg {
63 unsigned int irq; 63 unsigned int irq;
64 struct irq_cfg *next; 64 struct irq_cfg *next;
65 struct irq_pin_list *irq_2_pin;
65 cpumask_t domain; 66 cpumask_t domain;
66 cpumask_t old_domain; 67 cpumask_t old_domain;
67 unsigned move_cleanup_count; 68 unsigned move_cleanup_count;
@@ -252,13 +253,66 @@ int pin_map_size;
252 * between pins and IRQs. 253 * between pins and IRQs.
253 */ 254 */
254 255
255static struct irq_pin_list { 256struct irq_pin_list {
256 short apic, pin; 257 int apic, pin;
257 int next; 258 struct irq_pin_list *next;
258} *irq_2_pin; 259};
260
261static struct irq_pin_list *irq_2_pin_head;
262/* fill one page ? */
263static int nr_irq_2_pin = 0x100;
264static struct irq_pin_list *irq_2_pin_ptr;
265static void __init irq_2_pin_init_work(void *data)
266{
267 struct dyn_array *da = data;
268 struct irq_pin_list *pin;
269 int i;
270
271 pin = *da->name;
272
273 for (i = 1; i < *da->nr; i++)
274 pin[i-1].next = &pin[i];
275
276 irq_2_pin_ptr = &pin[0];
277}
278DEFINE_DYN_ARRAY(irq_2_pin_head, sizeof(struct irq_pin_list), nr_irq_2_pin, PAGE_SIZE, irq_2_pin_init_work);
279
280static struct irq_pin_list *get_one_free_irq_2_pin(void)
281{
282 struct irq_pin_list *pin;
283 int i;
284
285 pin = irq_2_pin_ptr;
286
287 if (pin) {
288 irq_2_pin_ptr = pin->next;
289 pin->next = NULL;
290 return pin;
291 }
292
293 /*
294 * we run out of pre-allocate ones, allocate more
295 */
296 printk(KERN_DEBUG "try to get more irq_2_pin %d\n", nr_irq_2_pin);
297
298 if (after_bootmem)
299 pin = kzalloc(sizeof(struct irq_pin_list)*nr_irq_2_pin,
300 GFP_ATOMIC);
301 else
302 pin = __alloc_bootmem_nopanic(sizeof(struct irq_pin_list) *
303 nr_irq_2_pin, PAGE_SIZE, 0);
304
305 if (!pin)
306 panic("can not get more irq_2_pin\n");
259 307
260DEFINE_DYN_ARRAY(irq_2_pin, sizeof(struct irq_pin_list), pin_map_size, sizeof(struct irq_pin_list), NULL); 308 for (i = 1; i < nr_irq_2_pin; i++)
309 pin[i-1].next = &pin[i];
261 310
311 irq_2_pin_ptr = pin->next;
312 pin->next = NULL;
313
314 return pin;
315}
262 316
263struct io_apic { 317struct io_apic {
264 unsigned int index; 318 unsigned int index;
@@ -300,16 +354,17 @@ static bool io_apic_level_ack_pending(unsigned int irq)
300{ 354{
301 struct irq_pin_list *entry; 355 struct irq_pin_list *entry;
302 unsigned long flags; 356 unsigned long flags;
357 struct irq_cfg *cfg = irq_cfg(irq);
303 358
304 spin_lock_irqsave(&ioapic_lock, flags); 359 spin_lock_irqsave(&ioapic_lock, flags);
305 entry = irq_2_pin + irq; 360 entry = cfg->irq_2_pin;
306 for (;;) { 361 for (;;) {
307 unsigned int reg; 362 unsigned int reg;
308 int pin; 363 int pin;
309 364
310 pin = entry->pin; 365 if (!entry)
311 if (pin == -1)
312 break; 366 break;
367 pin = entry->pin;
313 reg = io_apic_read(entry->apic, 0x10 + pin*2); 368 reg = io_apic_read(entry->apic, 0x10 + pin*2);
314 /* Is the remote IRR bit set? */ 369 /* Is the remote IRR bit set? */
315 if (reg & IO_APIC_REDIR_REMOTE_IRR) { 370 if (reg & IO_APIC_REDIR_REMOTE_IRR) {
@@ -318,7 +373,7 @@ static bool io_apic_level_ack_pending(unsigned int irq)
318 } 373 }
319 if (!entry->next) 374 if (!entry->next)
320 break; 375 break;
321 entry = irq_2_pin + entry->next; 376 entry = entry->next;
322 } 377 }
323 spin_unlock_irqrestore(&ioapic_lock, flags); 378 spin_unlock_irqrestore(&ioapic_lock, flags);
324 379
@@ -339,21 +394,24 @@ static inline void io_apic_sync(unsigned int apic)
339 \ 394 \
340{ \ 395{ \
341 int pin; \ 396 int pin; \
342 struct irq_pin_list *entry = irq_2_pin + irq; \ 397 struct irq_cfg *cfg; \
398 struct irq_pin_list *entry; \
343 \ 399 \
344 BUG_ON(irq >= nr_irqs); \ 400 BUG_ON(irq >= nr_irqs); \
401 cfg = irq_cfg(irq); \
402 entry = cfg->irq_2_pin; \
345 for (;;) { \ 403 for (;;) { \
346 unsigned int reg; \ 404 unsigned int reg; \
347 pin = entry->pin; \ 405 if (!entry) \
348 if (pin == -1) \
349 break; \ 406 break; \
407 pin = entry->pin; \
350 reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \ 408 reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
351 reg ACTION; \ 409 reg ACTION; \
352 io_apic_modify(entry->apic, reg); \ 410 io_apic_modify(entry->apic, reg); \
353 FINAL; \ 411 FINAL; \
354 if (!entry->next) \ 412 if (!entry->next) \
355 break; \ 413 break; \
356 entry = irq_2_pin + entry->next; \ 414 entry = entry->next; \
357 } \ 415 } \
358} 416}
359 417
@@ -416,15 +474,20 @@ static void ioapic_mask_entry(int apic, int pin)
416static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) 474static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
417{ 475{
418 int apic, pin; 476 int apic, pin;
419 struct irq_pin_list *entry = irq_2_pin + irq; 477 struct irq_cfg *cfg;
478 struct irq_pin_list *entry;
420 479
421 BUG_ON(irq >= nr_irqs); 480 BUG_ON(irq >= nr_irqs);
481 cfg = irq_cfg(irq);
482 entry = cfg->irq_2_pin;
422 for (;;) { 483 for (;;) {
423 unsigned int reg; 484 unsigned int reg;
485
486 if (!entry)
487 break;
488
424 apic = entry->apic; 489 apic = entry->apic;
425 pin = entry->pin; 490 pin = entry->pin;
426 if (pin == -1)
427 break;
428 /* 491 /*
429 * With interrupt-remapping, destination information comes 492 * With interrupt-remapping, destination information comes
430 * from interrupt-remapping table entry. 493 * from interrupt-remapping table entry.
@@ -437,7 +500,7 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
437 io_apic_modify(apic, reg); 500 io_apic_modify(apic, reg);
438 if (!entry->next) 501 if (!entry->next)
439 break; 502 break;
440 entry = irq_2_pin + entry->next; 503 entry = entry->next;
441 } 504 }
442} 505}
443 506
@@ -480,22 +543,35 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
480int first_free_entry; 543int first_free_entry;
481static void add_pin_to_irq(unsigned int irq, int apic, int pin) 544static void add_pin_to_irq(unsigned int irq, int apic, int pin)
482{ 545{
483 struct irq_pin_list *entry = irq_2_pin + irq; 546 struct irq_cfg *cfg;
547 struct irq_pin_list *entry;
484 548
485 BUG_ON(irq >= nr_irqs); 549 BUG_ON(irq >= nr_irqs);
486 irq_cfg_alloc(irq); 550 /* first time to refer irq_cfg, so with new */
551 cfg = irq_cfg_alloc(irq);
552 entry = cfg->irq_2_pin;
553 if (!entry) {
554 entry = get_one_free_irq_2_pin();
555 cfg->irq_2_pin = entry;
556 entry->apic = apic;
557 entry->pin = pin;
558 printk(KERN_DEBUG " 0 add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
559 return;
560 }
487 561
488 while (entry->next) 562 while (entry->next) {
489 entry = irq_2_pin + entry->next; 563 /* not again, please */
564 if (entry->apic == apic && entry->pin == pin)
565 return;
490 566
491 if (entry->pin != -1) { 567 entry = entry->next;
492 entry->next = first_free_entry;
493 entry = irq_2_pin + entry->next;
494 if (++first_free_entry >= pin_map_size)
495 panic("io_apic.c: ran out of irq_2_pin entries!");
496 } 568 }
569
570 entry->next = get_one_free_irq_2_pin();
571 entry = entry->next;
497 entry->apic = apic; 572 entry->apic = apic;
498 entry->pin = pin; 573 entry->pin = pin;
574 printk(KERN_DEBUG " x add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
499} 575}
500 576
501/* 577/*
@@ -505,17 +581,24 @@ static void __init replace_pin_at_irq(unsigned int irq,
505 int oldapic, int oldpin, 581 int oldapic, int oldpin,
506 int newapic, int newpin) 582 int newapic, int newpin)
507{ 583{
508 struct irq_pin_list *entry = irq_2_pin + irq; 584 struct irq_cfg *cfg = irq_cfg(irq);
585 struct irq_pin_list *entry = cfg->irq_2_pin;
586 int replaced = 0;
509 587
510 while (1) { 588 while (entry) {
511 if (entry->apic == oldapic && entry->pin == oldpin) { 589 if (entry->apic == oldapic && entry->pin == oldpin) {
512 entry->apic = newapic; 590 entry->apic = newapic;
513 entry->pin = newpin; 591 entry->pin = newpin;
514 } 592 replaced = 1;
515 if (!entry->next) 593 /* every one is different, right? */
516 break; 594 break;
517 entry = irq_2_pin + entry->next; 595 }
596 entry = entry->next;
518 } 597 }
598
599 /* why? call replace before add? */
600 if (!replaced)
601 add_pin_to_irq(irq, newapic, newpin);
519} 602}
520 603
521 604
@@ -1326,15 +1409,16 @@ __apicdebuginit(void) print_IO_APIC(void)
1326 } 1409 }
1327 printk(KERN_DEBUG "IRQ to pin mappings:\n"); 1410 printk(KERN_DEBUG "IRQ to pin mappings:\n");
1328 for (i = 0; i < nr_irqs; i++) { 1411 for (i = 0; i < nr_irqs; i++) {
1329 struct irq_pin_list *entry = irq_2_pin + i; 1412 struct irq_cfg *cfg = irq_cfg(i);
1330 if (entry->pin < 0) 1413 struct irq_pin_list *entry = cfg->irq_2_pin;
1414 if (!entry)
1331 continue; 1415 continue;
1332 printk(KERN_DEBUG "IRQ%d ", i); 1416 printk(KERN_DEBUG "IRQ%d ", i);
1333 for (;;) { 1417 for (;;) {
1334 printk("-> %d:%d", entry->apic, entry->pin); 1418 printk("-> %d:%d", entry->apic, entry->pin);
1335 if (!entry->next) 1419 if (!entry->next)
1336 break; 1420 break;
1337 entry = irq_2_pin + entry->next; 1421 entry = entry->next;
1338 } 1422 }
1339 printk("\n"); 1423 printk("\n");
1340 } 1424 }
@@ -1495,14 +1579,9 @@ void __init enable_IO_APIC(void)
1495{ 1579{
1496 union IO_APIC_reg_01 reg_01; 1580 union IO_APIC_reg_01 reg_01;
1497 int i8259_apic, i8259_pin; 1581 int i8259_apic, i8259_pin;
1498 int i, apic; 1582 int apic;
1499 unsigned long flags; 1583 unsigned long flags;
1500 1584
1501 for (i = 0; i < pin_map_size; i++) {
1502 irq_2_pin[i].pin = -1;
1503 irq_2_pin[i].next = 0;
1504 }
1505
1506 /* 1585 /*
1507 * The number of IO-APIC IRQ registers (== #pins): 1586 * The number of IO-APIC IRQ registers (== #pins):
1508 */ 1587 */