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 | 111 | * struct msi_desc - Descriptor structure for MSI based interrupts |
| 110 | 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 | 250 | #endif /* CONFIG_PCI_MSI */ |
| 249 | 251 | |
| 250 | 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 | 265 | struct msi_desc *alloc_msi_entry(struct device *dev, int nvec, |
| 253 | 266 | const struct irq_affinity_desc *affinity); |
| @@ -408,6 +421,10 @@ enum { · 154 unmodified lines | ||
| 408 | 421 | MSI_FLAG_DEV_SYSFS = (1 << 7), |
| 409 | 422 | /* MSI-X entries must be contiguous */ |
| 410 | 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 | 430 | int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, |
| @@ -119,6 +119,32 @@ fail: · 118 unmodified lines | ||
| 119 | 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 | 148 | void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg) |
| 123 | 149 | { |
| 124 | 150 | *msg = entry->msg; |
| @@ -879,6 +905,16 @@ skip_activate: · 754 unmodified lines | ||
| 879 | 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 | 919 | * msi_domain_alloc_irqs_descs_locked - Allocate interrupts from a MSI interrupt domain |
| 884 | 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 | 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 | 944 | ret = ops->domain_alloc_irqs(domain, dev, nvec); |
| 905 | 945 | if (ret) |
| 906 | 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 | 1013 | * msi_domain_free_irqs_descs_locked - Free interrupts from a MSI interrupt @domain associated to @dev |
| 967 | 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 | 1029 | if (info->flags & MSI_FLAG_DEV_SYSFS) |
| 983 | 1030 | msi_device_destroy_sysfs(dev); |
| 984 | 1031 | ops->domain_free_irqs(domain, dev); |
| 1032 | + msi_domain_free_msi_descs(info, dev); | |
| 985 | 1033 | } |
| 986 | 1034 | |
| 987 | 1035 | /** |