History

genirq/msi: Provide domain flags to allocate/free MSI descriptors automatically

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.

Thomas Gleixner committed 4 years ago

Commit 645474e1 parent 60290522 files · +65 −0Browse files

Unified · Split

2 files
  1. include/linux/msi.h +17 −0
  2. kernel/irq/msi.c +48 −0
include/linux/msi.h+17−0
@@ -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 interrupts111 * struct msi_desc - Descriptor structure for MSI based interrupts
110 * @list: List head for management112 * @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
250int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc);252int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc);
253void 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 */
260static 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
252struct msi_desc *alloc_msi_entry(struct device *dev, int nvec,265struct 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
413int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,430int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
kernel/irq/msi.c+48−0
@@ -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 */
129void 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
122void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)148void __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
908static 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 domain919 * msi_domain_alloc_irqs_descs_locked - Allocate interrupts from a MSI interrupt domain
884 * @domain: The domain to allocate from920 * @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
1005static 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 @dev1013 * msi_domain_free_irqs_descs_locked - Free interrupts from a MSI interrupt @domain associated to @dev
967 * @domain: The domain to managing the interrupts1014 * @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/**