diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-10-22 05:16:45 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-22 05:16:45 -0400 |
commit | 8d57d3ad0c4641bc6b720160215c907a3d1004a0 (patch) | |
tree | a2ea60d7d49344c74c41dde69ad07be5752dba55 /arch/sparc64/kernel/irq.c | |
parent | 3d0a721f04fe9321ca360fbab144ea10682d458a (diff) |
[SPARC64]: Stop using __do_IRQ().
Invoke the desc->handle_irq directly in the top-level dispatch,
just like other sophisticated ports.
This will allow us to decrease the cost of the MSI queue dispatch.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r-- | arch/sparc64/kernel/irq.c | 85 |
1 files changed, 38 insertions, 47 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 2c3bea228159..30431bd24e1e 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
@@ -257,8 +257,8 @@ struct irq_handler_data { | |||
257 | unsigned long imap; | 257 | unsigned long imap; |
258 | 258 | ||
259 | void (*pre_handler)(unsigned int, void *, void *); | 259 | void (*pre_handler)(unsigned int, void *, void *); |
260 | void *pre_handler_arg1; | 260 | void *arg1; |
261 | void *pre_handler_arg2; | 261 | void *arg2; |
262 | }; | 262 | }; |
263 | 263 | ||
264 | #ifdef CONFIG_SMP | 264 | #ifdef CONFIG_SMP |
@@ -346,7 +346,7 @@ static void sun4u_irq_disable(unsigned int virt_irq) | |||
346 | } | 346 | } |
347 | } | 347 | } |
348 | 348 | ||
349 | static void sun4u_irq_end(unsigned int virt_irq) | 349 | static void sun4u_irq_eoi(unsigned int virt_irq) |
350 | { | 350 | { |
351 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 351 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); |
352 | struct irq_desc *desc = irq_desc + virt_irq; | 352 | struct irq_desc *desc = irq_desc + virt_irq; |
@@ -401,7 +401,7 @@ static void sun4v_irq_disable(unsigned int virt_irq) | |||
401 | "err(%d)\n", ino, err); | 401 | "err(%d)\n", ino, err); |
402 | } | 402 | } |
403 | 403 | ||
404 | static void sun4v_irq_end(unsigned int virt_irq) | 404 | static void sun4v_irq_eoi(unsigned int virt_irq) |
405 | { | 405 | { |
406 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 406 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; |
407 | struct irq_desc *desc = irq_desc + virt_irq; | 407 | struct irq_desc *desc = irq_desc + virt_irq; |
@@ -478,7 +478,7 @@ static void sun4v_virq_disable(unsigned int virt_irq) | |||
478 | dev_handle, dev_ino, err); | 478 | dev_handle, dev_ino, err); |
479 | } | 479 | } |
480 | 480 | ||
481 | static void sun4v_virq_end(unsigned int virt_irq) | 481 | static void sun4v_virq_eoi(unsigned int virt_irq) |
482 | { | 482 | { |
483 | struct irq_desc *desc = irq_desc + virt_irq; | 483 | struct irq_desc *desc = irq_desc + virt_irq; |
484 | unsigned long dev_handle, dev_ino; | 484 | unsigned long dev_handle, dev_ino; |
@@ -498,33 +498,11 @@ static void sun4v_virq_end(unsigned int virt_irq) | |||
498 | dev_handle, dev_ino, err); | 498 | dev_handle, dev_ino, err); |
499 | } | 499 | } |
500 | 500 | ||
501 | static void run_pre_handler(unsigned int virt_irq) | ||
502 | { | ||
503 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | ||
504 | unsigned int ino; | ||
505 | |||
506 | ino = virt_irq_table[virt_irq].dev_ino; | ||
507 | if (likely(data->pre_handler)) { | ||
508 | data->pre_handler(ino, | ||
509 | data->pre_handler_arg1, | ||
510 | data->pre_handler_arg2); | ||
511 | } | ||
512 | } | ||
513 | |||
514 | static struct irq_chip sun4u_irq = { | 501 | static struct irq_chip sun4u_irq = { |
515 | .typename = "sun4u", | 502 | .typename = "sun4u", |
516 | .enable = sun4u_irq_enable, | 503 | .enable = sun4u_irq_enable, |
517 | .disable = sun4u_irq_disable, | 504 | .disable = sun4u_irq_disable, |
518 | .end = sun4u_irq_end, | 505 | .eoi = sun4u_irq_eoi, |
519 | .set_affinity = sun4u_set_affinity, | ||
520 | }; | ||
521 | |||
522 | static struct irq_chip sun4u_irq_ack = { | ||
523 | .typename = "sun4u+ack", | ||
524 | .enable = sun4u_irq_enable, | ||
525 | .disable = sun4u_irq_disable, | ||
526 | .ack = run_pre_handler, | ||
527 | .end = sun4u_irq_end, | ||
528 | .set_affinity = sun4u_set_affinity, | 506 | .set_affinity = sun4u_set_affinity, |
529 | }; | 507 | }; |
530 | 508 | ||
@@ -532,7 +510,7 @@ static struct irq_chip sun4v_irq = { | |||
532 | .typename = "sun4v", | 510 | .typename = "sun4v", |
533 | .enable = sun4v_irq_enable, | 511 | .enable = sun4v_irq_enable, |
534 | .disable = sun4v_irq_disable, | 512 | .disable = sun4v_irq_disable, |
535 | .end = sun4v_irq_end, | 513 | .eoi = sun4v_irq_eoi, |
536 | .set_affinity = sun4v_set_affinity, | 514 | .set_affinity = sun4v_set_affinity, |
537 | }; | 515 | }; |
538 | 516 | ||
@@ -540,31 +518,33 @@ static struct irq_chip sun4v_virq = { | |||
540 | .typename = "vsun4v", | 518 | .typename = "vsun4v", |
541 | .enable = sun4v_virq_enable, | 519 | .enable = sun4v_virq_enable, |
542 | .disable = sun4v_virq_disable, | 520 | .disable = sun4v_virq_disable, |
543 | .end = sun4v_virq_end, | 521 | .eoi = sun4v_virq_eoi, |
544 | .set_affinity = sun4v_virt_set_affinity, | 522 | .set_affinity = sun4v_virt_set_affinity, |
545 | }; | 523 | }; |
546 | 524 | ||
525 | static void fastcall pre_flow_handler(unsigned int virt_irq, | ||
526 | struct irq_desc *desc) | ||
527 | { | ||
528 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | ||
529 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | ||
530 | |||
531 | data->pre_handler(ino, data->arg1, data->arg2); | ||
532 | |||
533 | handle_fasteoi_irq(virt_irq, desc); | ||
534 | } | ||
535 | |||
547 | void irq_install_pre_handler(int virt_irq, | 536 | void irq_install_pre_handler(int virt_irq, |
548 | void (*func)(unsigned int, void *, void *), | 537 | void (*func)(unsigned int, void *, void *), |
549 | void *arg1, void *arg2) | 538 | void *arg1, void *arg2) |
550 | { | 539 | { |
551 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 540 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); |
552 | struct irq_chip *chip = get_irq_chip(virt_irq); | 541 | struct irq_desc *desc = irq_desc + virt_irq; |
553 | |||
554 | if (WARN_ON(chip == &sun4v_irq || chip == &sun4v_virq)) { | ||
555 | printk(KERN_ERR "IRQ: Trying to install pre-handler on " | ||
556 | "sun4v irq %u\n", virt_irq); | ||
557 | return; | ||
558 | } | ||
559 | 542 | ||
560 | data->pre_handler = func; | 543 | data->pre_handler = func; |
561 | data->pre_handler_arg1 = arg1; | 544 | data->arg1 = arg1; |
562 | data->pre_handler_arg2 = arg2; | 545 | data->arg2 = arg2; |
563 | |||
564 | if (chip == &sun4u_irq_ack) | ||
565 | return; | ||
566 | 546 | ||
567 | set_irq_chip(virt_irq, &sun4u_irq_ack); | 547 | desc->handle_irq = pre_flow_handler; |
568 | } | 548 | } |
569 | 549 | ||
570 | unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) | 550 | unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) |
@@ -582,7 +562,10 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) | |||
582 | if (!virt_irq) { | 562 | if (!virt_irq) { |
583 | virt_irq = virt_irq_alloc(0, ino); | 563 | virt_irq = virt_irq_alloc(0, ino); |
584 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 564 | bucket_set_virt_irq(__pa(bucket), virt_irq); |
585 | set_irq_chip(virt_irq, &sun4u_irq); | 565 | set_irq_chip_and_handler_name(virt_irq, |
566 | &sun4u_irq, | ||
567 | handle_fasteoi_irq, | ||
568 | "IVEC"); | ||
586 | } | 569 | } |
587 | 570 | ||
588 | data = get_irq_chip_data(virt_irq); | 571 | data = get_irq_chip_data(virt_irq); |
@@ -617,7 +600,9 @@ static unsigned int sun4v_build_common(unsigned long sysino, | |||
617 | if (!virt_irq) { | 600 | if (!virt_irq) { |
618 | virt_irq = virt_irq_alloc(0, sysino); | 601 | virt_irq = virt_irq_alloc(0, sysino); |
619 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 602 | bucket_set_virt_irq(__pa(bucket), virt_irq); |
620 | set_irq_chip(virt_irq, chip); | 603 | set_irq_chip_and_handler_name(virt_irq, chip, |
604 | handle_fasteoi_irq, | ||
605 | "IVEC"); | ||
621 | } | 606 | } |
622 | 607 | ||
623 | data = get_irq_chip_data(virt_irq); | 608 | data = get_irq_chip_data(virt_irq); |
@@ -665,7 +650,10 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
665 | 650 | ||
666 | virt_irq = virt_irq_alloc(devhandle, devino); | 651 | virt_irq = virt_irq_alloc(devhandle, devino); |
667 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 652 | bucket_set_virt_irq(__pa(bucket), virt_irq); |
668 | set_irq_chip(virt_irq, &sun4v_virq); | 653 | |
654 | set_irq_chip_and_handler_name(virt_irq, &sun4v_virq, | ||
655 | handle_fasteoi_irq, | ||
656 | "IVEC"); | ||
669 | 657 | ||
670 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); | 658 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
671 | if (unlikely(!data)) | 659 | if (unlikely(!data)) |
@@ -724,6 +712,7 @@ void handler_irq(int irq, struct pt_regs *regs) | |||
724 | : "memory"); | 712 | : "memory"); |
725 | 713 | ||
726 | while (bucket_pa) { | 714 | while (bucket_pa) { |
715 | struct irq_desc *desc; | ||
727 | unsigned long next_pa; | 716 | unsigned long next_pa; |
728 | unsigned int virt_irq; | 717 | unsigned int virt_irq; |
729 | 718 | ||
@@ -731,7 +720,9 @@ void handler_irq(int irq, struct pt_regs *regs) | |||
731 | virt_irq = bucket_get_virt_irq(bucket_pa); | 720 | virt_irq = bucket_get_virt_irq(bucket_pa); |
732 | bucket_clear_chain_pa(bucket_pa); | 721 | bucket_clear_chain_pa(bucket_pa); |
733 | 722 | ||
734 | __do_IRQ(virt_irq); | 723 | desc = irq_desc + virt_irq; |
724 | |||
725 | desc->handle_irq(virt_irq, desc); | ||
735 | 726 | ||
736 | bucket_pa = next_pa; | 727 | bucket_pa = next_pa; |
737 | } | 728 | } |