summaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2022-11-25 00:24:30 +0100
committerThomas Gleixner <tglx@linutronix.de>2022-12-05 19:20:59 +0100
commit377712c5a45f6de40bffef5ddc31b39cd86cf23f (patch)
treeae980b6e81e9a5f3427615da6bd9a7fd2c352d2c /kernel/irq
parentfc8ab388325ddfd848d00f3a3383b4304594546a (diff)
downloadlinux-377712c5a45f6de40bffef5ddc31b39cd86cf23f.tar.bz2
genirq/msi: Make descriptor freeing domain aware
Change the descriptor free functions to take a domain id to prepare for the upcoming multi MSI domain per device support. To avoid changing and extending the interfaces over and over use an core internal control struct and hand the pointer through the various functions. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Acked-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20221124230314.220788011@linutronix.de
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/msi.c58
1 files changed, 48 insertions, 10 deletions
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index e75b07fffbcd..33ababf8645d 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -19,6 +19,18 @@
#include "internals.h"
+/**
+ * struct msi_ctrl - MSI internal management control structure
+ * @domid: ID of the domain on which management operations should be done
+ * @first: First (hardware) slot index to operate on
+ * @last: Last (hardware) slot index to operate on
+ */
+struct msi_ctrl {
+ unsigned int domid;
+ unsigned int first;
+ unsigned int last;
+};
+
/* Invalid Xarray index which is outside of any searchable range */
#define MSI_XA_MAX_INDEX (ULONG_MAX - 1)
/* The maximum domain size */
@@ -151,22 +163,29 @@ static bool msi_desc_match(struct msi_desc *desc, enum msi_desc_filter filter)
return false;
}
-/**
- * msi_free_msi_descs_range - Free MSI descriptors of a device
- * @dev: Device to free the descriptors
- * @first_index: Index to start freeing from
- * @last_index: Last index to be freed
- */
-void msi_free_msi_descs_range(struct device *dev, unsigned int first_index,
- unsigned int last_index)
+static bool msi_ctrl_valid(struct device *dev, struct msi_ctrl *ctrl)
+{
+ if (WARN_ON_ONCE(ctrl->domid >= MSI_MAX_DEVICE_IRQDOMAINS ||
+ ctrl->first > ctrl->last ||
+ ctrl->first > MSI_MAX_INDEX ||
+ ctrl->last > MSI_MAX_INDEX))
+ return false;
+ return true;
+}
+
+static void msi_domain_free_descs(struct device *dev, struct msi_ctrl *ctrl)
{
- struct xarray *xa = &dev->msi.data->__domains[MSI_DEFAULT_DOMAIN].store;
struct msi_desc *desc;
+ struct xarray *xa;
unsigned long idx;
lockdep_assert_held(&dev->msi.data->mutex);
- xa_for_each_range(xa, idx, desc, first_index, last_index) {
+ if (!msi_ctrl_valid(dev, ctrl))
+ return;
+
+ xa = &dev->msi.data->__domains[ctrl->domid].store;
+ xa_for_each_range(xa, idx, desc, ctrl->first, ctrl->last) {
xa_erase(xa, idx);
/* Leak the descriptor when it is still referenced */
@@ -176,6 +195,25 @@ void msi_free_msi_descs_range(struct device *dev, unsigned int first_index,
}
}
+/**
+ * msi_domain_free_msi_descs_range - Free a range of MSI descriptors of a device in an irqdomain
+ * @dev: Device for which to free the descriptors
+ * @domid: Id of the domain to operate on
+ * @first: Index to start freeing from (inclusive)
+ * @last: Last index to be freed (inclusive)
+ */
+void msi_domain_free_msi_descs_range(struct device *dev, unsigned int domid,
+ unsigned int first, unsigned int last)
+{
+ struct msi_ctrl ctrl = {
+ .domid = domid,
+ .first = first,
+ .last = last,
+ };
+
+ msi_domain_free_descs(dev, &ctrl);
+}
+
void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
*msg = entry->msg;