Provide domain info flags which tell the core to allocate simple descriptors or to free descriptors when the interrupts are freed and implement the required functionality.
Unified · Split
| @@ -105,6 +105,8 @@ struct pci_msi_desc { · 104 unmodified lines | |||
| 105 | }; | 105 | }; |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | #define MSI_MAX_INDEX ((unsigned int)USHRT_MAX) | ||
| 109 | |||
| 108 | /** | 110 | /** |
| 109 | * struct msi_desc - Descriptor structure for MSI based interrupts | 111 | * struct msi_desc - Descriptor structure for MSI based interrupts |
| 110 | * @list: List head for management | 112 | * @list: List head for management |
| @@ -248,6 +250,17 @@ static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg) · 137 unmodified lines | |||
| 248 | #endif /* CONFIG_PCI_MSI */ | 250 | #endif /* CONFIG_PCI_MSI */ |
| 249 | 251 | ||
| 250 | int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc); | 252 | int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc); |
| 253 | void msi_free_msi_descs_range(struct device *dev, enum msi_desc_filter filter, | ||
| 254 | unsigned int first_index, unsigned int last_index); | ||
| 255 | |||
| 256 | /** | ||
| 257 | * msi_free_msi_descs - Free MSI descriptors of a device | ||
| 258 | * @dev: Device to free the descriptors | ||
| 259 | */ | ||
| 260 | static inline void msi_free_msi_descs(struct device *dev) | ||
| 261 | { | ||
| 262 | msi_free_msi_descs_range(dev, MSI_DESC_ALL, 0, MSI_MAX_INDEX); | ||
| 263 | } | ||
| 251 | 264 | ||
| 252 | struct msi_desc *alloc_msi_entry(struct device *dev, int nvec, | 265 | struct msi_desc *alloc_msi_entry(struct device *dev, int nvec, |
| 253 | const struct irq_affinity_desc *affinity); | 266 | const struct irq_affinity_desc *affinity); |
| @@ -408,6 +421,10 @@ enum { · 154 unmodified lines | |||
| 408 | MSI_FLAG_DEV_SYSFS = (1 << 7), | 421 | MSI_FLAG_DEV_SYSFS = (1 << 7), |
| 409 | /* MSI-X entries must be contiguous */ | 422 | /* MSI-X entries must be contiguous */ |
| 410 | MSI_FLAG_MSIX_CONTIGUOUS = (1 << 8), | 423 | MSI_FLAG_MSIX_CONTIGUOUS = (1 << 8), |
| 424 | /* Allocate simple MSI descriptors */ | ||
| 425 | MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS = (1 << 9), | ||
| 426 | /* Free MSI descriptors */ | ||
| 427 | MSI_FLAG_FREE_MSI_DESCS = (1 << 10), | ||
| 411 | }; | 428 | }; |
| 412 | 429 | ||
| 413 | int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, | 430 | int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, |
| @@ -119,6 +119,32 @@ fail: · 118 unmodified lines | |||
| 119 | return -ENOMEM; | 119 | return -ENOMEM; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | /** | ||
| 123 | * msi_free_msi_descs_range - Free MSI descriptors of a device | ||
| 124 | * @dev: Device to free the descriptors | ||
| 125 | * @filter: Descriptor state filter | ||
| 126 | * @first_index: Index to start freeing from | ||
| 127 | * @last_index: Last index to be freed | ||
| 128 | */ | ||
| 129 | void msi_free_msi_descs_range(struct device *dev, enum msi_desc_filter filter, | ||
| 130 | unsigned int first_index, unsigned int last_index) | ||
| 131 | { | ||
| 132 | struct msi_desc *desc; | ||
| 133 | |||
| 134 | lockdep_assert_held(&dev->msi.data->mutex); | ||
| 135 | |||
| 136 | msi_for_each_desc(desc, dev, filter) { | ||
| 137 | /* | ||
| 138 | * Stupid for now to handle MSI device domain until the | ||
| 139 | * storage is switched over to an xarray. | ||
| 140 | */ | ||
| 141 | if (desc->msi_index < first_index || desc->msi_index > last_index) | ||
| 142 | continue; | ||
| 143 | list_del(&desc->list); | ||
| 144 | free_msi_entry(desc); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 122 | void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg) | 148 | void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg) |
| 123 | { | 149 | { |
| 124 | *msg = entry->msg; | 150 | *msg = entry->msg; |
| @@ -879,6 +905,16 @@ skip_activate: · 754 unmodified lines | |||
| 879 | return 0; | 905 | return 0; |
| 880 | } | 906 | } |
| 881 | 907 | ||
| 908 | static int msi_domain_add_simple_msi_descs(struct msi_domain_info *info, | ||
| 909 | struct device *dev, | ||
| 910 | unsigned int num_descs) | ||
| 911 | { | ||
| 912 | if (!(info->flags & MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS)) | ||
| 913 | return 0; | ||
| 914 | |||
| 915 | return msi_add_simple_msi_descs(dev, 0, num_descs); | ||
| 916 | } | ||
| 917 | |||
| 882 | /** | 918 | /** |
| 883 | * msi_domain_alloc_irqs_descs_locked - Allocate interrupts from a MSI interrupt domain | 919 | * msi_domain_alloc_irqs_descs_locked - Allocate interrupts from a MSI interrupt domain |
| 884 | * @domain: The domain to allocate from | 920 | * @domain: The domain to allocate from |
| @@ -901,6 +937,10 @@ int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device · 16 unmodified lines | |||
| 901 | 937 | ||
| 902 | lockdep_assert_held(&dev->msi.data->mutex); | 938 | lockdep_assert_held(&dev->msi.data->mutex); |
| 903 | 939 | ||
| 940 | ret = msi_domain_add_simple_msi_descs(info, dev, nvec); | ||
| 941 | if (ret) | ||
| 942 | return ret; | ||
| 943 | |||
| 904 | ret = ops->domain_alloc_irqs(domain, dev, nvec); | 944 | ret = ops->domain_alloc_irqs(domain, dev, nvec); |
| 905 | if (ret) | 945 | if (ret) |
| 906 | goto cleanup; | 946 | goto cleanup; |
| @@ -962,6 +1002,13 @@ void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) · 55 unmodified lines | |||
| 962 | } | 1002 | } |
| 963 | } | 1003 | } |
| 964 | 1004 | ||
| 1005 | static void msi_domain_free_msi_descs(struct msi_domain_info *info, | ||
| 1006 | struct device *dev) | ||
| 1007 | { | ||
| 1008 | if (info->flags & MSI_FLAG_FREE_MSI_DESCS) | ||
| 1009 | msi_free_msi_descs(dev); | ||
| 1010 | } | ||
| 1011 | |||
| 965 | /** | 1012 | /** |
| 966 | * msi_domain_free_irqs_descs_locked - Free interrupts from a MSI interrupt @domain associated to @dev | 1013 | * msi_domain_free_irqs_descs_locked - Free interrupts from a MSI interrupt @domain associated to @dev |
| 967 | * @domain: The domain to managing the interrupts | 1014 | * @domain: The domain to managing the interrupts |
| @@ -982,6 +1029,7 @@ void msi_domain_free_irqs_descs_locked(struct irq_domain *domain, struct device · 14 unmodified lines | |||
| 982 | if (info->flags & MSI_FLAG_DEV_SYSFS) | 1029 | if (info->flags & MSI_FLAG_DEV_SYSFS) |
| 983 | msi_device_destroy_sysfs(dev); | 1030 | msi_device_destroy_sysfs(dev); |
| 984 | ops->domain_free_irqs(domain, dev); | 1031 | ops->domain_free_irqs(domain, dev); |
| 1032 | msi_domain_free_msi_descs(info, dev); | ||
| 985 | } | 1033 | } |
| 986 | 1034 | ||
| 987 | /** | 1035 | /** |