diff options
author | Ian Campbell <ian.campbell@citrix.com> | 2011-02-18 11:43:32 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-03-10 14:44:40 -0500 |
commit | bf480d952bcf25e8ff7e95d2a23964107513ac51 (patch) | |
tree | b2d1a75e39bfdf82021ccdefb5f9613a17087040 /drivers | |
parent | 5cad61a6ba6f4956a218ffbb64cafcc1daefaca0 (diff) |
xen: events: separate MSI PIRQ allocation from PIRQ binding to IRQ
Split the binding aspect of xen_allocate_pirq_msi out into a new
xen_bind_pirq_to_irq function.
In xen_hvm_setup_msi_irq when allocating a pirq write the MSI message
to signal the PIRQ as soon as the pirq is obtained. There is no way to
free the pirq back so if the subsequent binding to an IRQ fails we
want to ensure that we will reuse the PIRQ next time rather than leak
it.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/xen/events.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index c21066fc30be..1033f6284f31 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -647,12 +647,12 @@ out: | |||
647 | #include <linux/msi.h> | 647 | #include <linux/msi.h> |
648 | #include "../pci/msi.h" | 648 | #include "../pci/msi.h" |
649 | 649 | ||
650 | static int find_unbound_pirq(int type) | 650 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) |
651 | { | 651 | { |
652 | int rc; | 652 | int rc; |
653 | struct physdev_get_free_pirq op_get_free_pirq; | 653 | struct physdev_get_free_pirq op_get_free_pirq; |
654 | 654 | ||
655 | op_get_free_pirq.type = type; | 655 | op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI; |
656 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); | 656 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); |
657 | 657 | ||
658 | WARN_ONCE(rc == -ENOSYS, | 658 | WARN_ONCE(rc == -ENOSYS, |
@@ -661,9 +661,10 @@ static int find_unbound_pirq(int type) | |||
661 | return rc ? -1 : op_get_free_pirq.pirq; | 661 | return rc ? -1 : op_get_free_pirq.pirq; |
662 | } | 662 | } |
663 | 663 | ||
664 | int xen_allocate_pirq_msi(char *name, int *pirq, int alloc_pirq) | 664 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
665 | int pirq, const char *name) | ||
665 | { | 666 | { |
666 | int irq; | 667 | int irq, ret; |
667 | 668 | ||
668 | spin_lock(&irq_mapping_update_lock); | 669 | spin_lock(&irq_mapping_update_lock); |
669 | 670 | ||
@@ -671,24 +672,21 @@ int xen_allocate_pirq_msi(char *name, int *pirq, int alloc_pirq) | |||
671 | if (irq == -1) | 672 | if (irq == -1) |
672 | goto out; | 673 | goto out; |
673 | 674 | ||
674 | if (alloc_pirq) { | ||
675 | *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI); | ||
676 | if (*pirq == -1) { | ||
677 | xen_free_irq(irq); | ||
678 | irq = -1; | ||
679 | goto out; | ||
680 | } | ||
681 | } | ||
682 | |||
683 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, | 675 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, |
684 | handle_level_irq, name); | 676 | handle_level_irq, name); |
685 | 677 | ||
686 | irq_info[irq] = mk_pirq_info(0, *pirq, 0, 0); | 678 | irq_info[irq] = mk_pirq_info(0, pirq, 0, 0); |
687 | pirq_to_irq[*pirq] = irq; | 679 | pirq_to_irq[pirq] = irq; |
688 | 680 | ret = set_irq_msi(irq, msidesc); | |
681 | if (ret < 0) | ||
682 | goto error_irq; | ||
689 | out: | 683 | out: |
690 | spin_unlock(&irq_mapping_update_lock); | 684 | spin_unlock(&irq_mapping_update_lock); |
691 | return irq; | 685 | return irq; |
686 | error_irq: | ||
687 | spin_unlock(&irq_mapping_update_lock); | ||
688 | xen_free_irq(irq); | ||
689 | return -1; | ||
692 | } | 690 | } |
693 | 691 | ||
694 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) | 692 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) |