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
105105 };
106106 };
107107
108+#define MSI_MAX_INDEX ((unsigned int)USHRT_MAX)
109+
108110 /**
109111 * struct msi_desc - Descriptor structure for MSI based interrupts
110112 * @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
248250 #endif /* CONFIG_PCI_MSI */
249251
250252 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+}
251264
252265 struct msi_desc *alloc_msi_entry(struct device *dev, int nvec,
253266 const struct irq_affinity_desc *affinity);
@@ -408,6 +421,10 @@ enum { · 154 unmodified lines
408421 MSI_FLAG_DEV_SYSFS = (1 << 7),
409422 /* MSI-X entries must be contiguous */
410423 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),
411428 };
412429
413430 int 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
119119 return -ENOMEM;
120120 }
121121
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+
122148 void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
123149 {
124150 *msg = entry->msg;
@@ -879,6 +905,16 @@ skip_activate: · 754 unmodified lines
879905 return 0;
880906 }
881907
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+
882918 /**
883919 * msi_domain_alloc_irqs_descs_locked - Allocate interrupts from a MSI interrupt domain
884920 * @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
901937
902938 lockdep_assert_held(&dev->msi.data->mutex);
903939
940+ ret = msi_domain_add_simple_msi_descs(info, dev, nvec);
941+ if (ret)
942+ return ret;
943+
904944 ret = ops->domain_alloc_irqs(domain, dev, nvec);
905945 if (ret)
906946 goto cleanup;
@@ -962,6 +1002,13 @@ void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) · 55 unmodified lines
9621002 }
9631003 }
9641004
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+
9651012 /**
9661013 * msi_domain_free_irqs_descs_locked - Free interrupts from a MSI interrupt @domain associated to @dev
9671014 * @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
9821029 if (info->flags & MSI_FLAG_DEV_SYSFS)
9831030 msi_device_destroy_sysfs(dev);
9841031 ops->domain_free_irqs(domain, dev);
1032+ msi_domain_free_msi_descs(info, dev);
9851033 }
9861034
9871035 /**