| @@ -828,23 +828,74 @@ static int msi_handle_pci_fail(struct irq_domain *domain, struct msi_desc *desc, · 827 unmodified lines |
| 828 | return allocated ? allocated : -ENOSPC; | 828 | return allocated ? allocated : -ENOSPC; |
| 829 | } | 829 | } |
| 830 | | 830 | |
| | 831 | #define VIRQ_CAN_RESERVE 0x01 |
| | 832 | #define VIRQ_ACTIVATE 0x02 |
| | 833 | #define VIRQ_NOMASK_QUIRK 0x04 |
| | 834 | |
| | 835 | static int msi_init_virq(struct irq_domain *domain, int virq, unsigned int vflags) |
| | 836 | { |
| | 837 | struct irq_data *irqd = irq_domain_get_irq_data(domain, virq); |
| | 838 | int ret; |
| | 839 | |
| | 840 | if (!(vflags & VIRQ_CAN_RESERVE)) { |
| | 841 | irqd_clr_can_reserve(irqd); |
| | 842 | if (vflags & VIRQ_NOMASK_QUIRK) |
| | 843 | irqd_set_msi_nomask_quirk(irqd); |
| | 844 | } |
| | 845 | |
| | 846 | if (!(vflags & VIRQ_ACTIVATE)) |
| | 847 | return 0; |
| | 848 | |
| | 849 | ret = irq_domain_activate_irq(irqd, vflags & VIRQ_CAN_RESERVE); |
| | 850 | if (ret) |
| | 851 | return ret; |
| | 852 | /* |
| | 853 | * If the interrupt uses reservation mode, clear the activated bit |
| | 854 | * so request_irq() will assign the final vector. |
| | 855 | */ |
| | 856 | if (vflags & VIRQ_CAN_RESERVE) |
| | 857 | irqd_clr_activated(irqd); |
| | 858 | return 0; |
| | 859 | } |
| | 860 | |
| 831 | int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, | 861 | int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, |
| 832 | int nvec) | 862 | int nvec) |
| 833 | { | 863 | { |
| 834 | struct msi_domain_info *info = domain->host_data; | 864 | struct msi_domain_info *info = domain->host_data; |
| 835 | struct msi_domain_ops *ops = info->ops; | 865 | struct msi_domain_ops *ops = info->ops; |
| 836 | struct irq_data *irq_data; | | |
| 837 | struct msi_desc *desc; | | |
| 838 | msi_alloc_info_t arg = { }; | 866 | msi_alloc_info_t arg = { }; |
| | 867 | unsigned int vflags = 0; |
| | 868 | struct msi_desc *desc; |
| 839 | int allocated = 0; | 869 | int allocated = 0; |
| 840 | int i, ret, virq; | 870 | int i, ret, virq; |
| 841 | bool can_reserve; | | |
| 842 | | 871 | |
| 843 | ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg); | 872 | ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg); |
| 844 | if (ret) | 873 | if (ret) |
| 845 | return ret; | 874 | return ret; |
| 846 | | 875 | |
| 847 | for_each_msi_entry(desc, dev) { | 876 | /* |
| | 877 | * This flag is set by the PCI layer as we need to activate |
| | 878 | * the MSI entries before the PCI layer enables MSI in the |
| | 879 | * card. Otherwise the card latches a random msi message. |
| | 880 | */ |
| | 881 | if (info->flags & MSI_FLAG_ACTIVATE_EARLY) |
| | 882 | vflags |= VIRQ_ACTIVATE; |
| | 883 | |
| | 884 | /* |
| | 885 | * Interrupt can use a reserved vector and will not occupy |
| | 886 | * a real device vector until the interrupt is requested. |
| | 887 | */ |
| | 888 | if (msi_check_reservation_mode(domain, info, dev)) { |
| | 889 | vflags |= VIRQ_CAN_RESERVE; |
| | 890 | /* |
| | 891 | * MSI affinity setting requires a special quirk (X86) when |
| | 892 | * reservation mode is active. |
| | 893 | */ |
| | 894 | if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) |
| | 895 | vflags |= VIRQ_NOMASK_QUIRK; |
| | 896 | } |
| | 897 | |
| | 898 | msi_for_each_desc(desc, dev, MSI_DESC_NOTASSOCIATED) { |
| 848 | ops->set_desc(&arg, desc); | 899 | ops->set_desc(&arg, desc); |
| 849 | | 900 | |
| 850 | virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used, | 901 | virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used, |
| @@ -856,49 +907,12 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, · 5 unmodified lines |
| 856 | for (i = 0; i < desc->nvec_used; i++) { | 907 | for (i = 0; i < desc->nvec_used; i++) { |
| 857 | irq_set_msi_desc_off(virq, i, desc); | 908 | irq_set_msi_desc_off(virq, i, desc); |
| 858 | irq_debugfs_copy_devname(virq + i, dev); | 909 | irq_debugfs_copy_devname(virq + i, dev); |
| | 910 | ret = msi_init_virq(domain, virq + i, vflags); |
| | 911 | if (ret) |
| | 912 | return ret; |
| 859 | } | 913 | } |
| 860 | allocated++; | 914 | allocated++; |
| 861 | } | 915 | } |
| 862 | | | |
| 863 | can_reserve = msi_check_reservation_mode(domain, info, dev); | | |
| 864 | | | |
| 865 | /* | | |
| 866 | * This flag is set by the PCI layer as we need to activate | | |
| 867 | * the MSI entries before the PCI layer enables MSI in the | | |
| 868 | * card. Otherwise the card latches a random msi message. | | |
| 869 | */ | | |
| 870 | if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY)) | | |
| 871 | goto skip_activate; | | |
| 872 | | | |
| 873 | for_each_msi_vector(desc, i, dev) { | | |
| 874 | if (desc->irq == i) { | | |
| 875 | virq = desc->irq; | | |
| 876 | dev_dbg(dev, "irq [%d-%d] for MSI\n", | | |
| 877 | virq, virq + desc->nvec_used - 1); | | |
| 878 | } | | |
| 879 | | | |
| 880 | irq_data = irq_domain_get_irq_data(domain, i); | | |
| 881 | if (!can_reserve) { | | |
| 882 | irqd_clr_can_reserve(irq_data); | | |
| 883 | if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) | | |
| 884 | irqd_set_msi_nomask_quirk(irq_data); | | |
| 885 | } | | |
| 886 | ret = irq_domain_activate_irq(irq_data, can_reserve); | | |
| 887 | if (ret) | | |
| 888 | return ret; | | |
| 889 | } | | |
| 890 | | | |
| 891 | skip_activate: | | |
| 892 | /* | | |
| 893 | * If these interrupts use reservation mode, clear the activated bit | | |
| 894 | * so request_irq() will assign the final vector. | | |
| 895 | */ | | |
| 896 | if (can_reserve) { | | |
| 897 | for_each_msi_vector(desc, i, dev) { | | |
| 898 | irq_data = irq_domain_get_irq_data(domain, i); | | |
| 899 | irqd_clr_activated(irq_data); | | |
| 900 | } | | |
| 901 | } | | |
| 902 | return 0; | 916 | return 0; |
| 903 | } | 917 | } |
| 904 | | 918 | |
| @@ -976,26 +990,21 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nve · 71 unmodified lines |
| 976 | | 990 | |
| 977 | void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) | 991 | void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) |
| 978 | { | 992 | { |
| 979 | struct irq_data *irq_data; | 993 | struct irq_data *irqd; |
| 980 | struct msi_desc *desc; | 994 | struct msi_desc *desc; |
| 981 | int i; | 995 | int i; |
| 982 | | 996 | |
| 983 | for_each_msi_vector(desc, i, dev) { | 997 | /* Only handle MSI entries which have an interrupt associated */ |
| 984 | irq_data = irq_domain_get_irq_data(domain, i); | 998 | msi_for_each_desc(desc, dev, MSI_DESC_ASSOCIATED) { |
| 985 | if (irqd_is_activated(irq_data)) | 999 | /* Make sure all interrupts are deactivated */ |
| 986 | irq_domain_deactivate_irq(irq_data); | 1000 | for (i = 0; i < desc->nvec_used; i++) { |
| 987 | } | 1001 | irqd = irq_domain_get_irq_data(domain, desc->irq + i); |
| 988 | | 1002 | if (irqd && irqd_is_activated(irqd)) |
| 989 | for_each_msi_entry(desc, dev) { | 1003 | irq_domain_deactivate_irq(irqd); |
| 990 | /* | | |
| 991 | * We might have failed to allocate an MSI early | | |
| 992 | * enough that there is no IRQ associated to this | | |
| 993 | * entry. If that's the case, don't do anything. | | |
| 994 | */ | | |
| 995 | if (desc->irq) { | | |
| 996 | irq_domain_free_irqs(desc->irq, desc->nvec_used); | | |
| 997 | desc->irq = 0; | | |
| 998 | } | 1004 | } |
| | 1005 | |
| | 1006 | irq_domain_free_irqs(desc->irq, desc->nvec_used); |
| | 1007 | desc->irq = 0; |
| 999 | } | 1008 | } |
| 1000 | } | 1009 | } |
| 1001 | | 1010 | |