Skip to content

Commit

Permalink
genirq/msi: Make msi_add_simple_msi_descs() device domain aware
Browse files Browse the repository at this point in the history
Allocating simple interrupt descriptors in the core code has to be multi
device irqdomain aware for the upcoming PCI/IMS support.

Change the interfaces to take a domain id into account. Use the internal
control struct for transport of arguments.

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.279112474@linutronix.de
  • Loading branch information
Thomas Gleixner committed Dec 5, 2022
1 parent 377712c commit 4074271
Showing 1 changed file with 57 additions and 41 deletions.
98 changes: 57 additions & 41 deletions kernel/irq/msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,39 +116,6 @@ int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid,
return msi_insert_desc(dev->msi.data, desc, domid, init_desc->msi_index);
}

/**
* msi_add_simple_msi_descs - Allocate and initialize MSI descriptors
* @dev: Pointer to the device for which the descriptors are allocated
* @index: Index for the first MSI descriptor
* @ndesc: Number of descriptors to allocate
*
* Return: 0 on success or an appropriate failure code.
*/
static int msi_add_simple_msi_descs(struct device *dev, unsigned int index, unsigned int ndesc)
{
unsigned int idx, last = index + ndesc - 1;
struct msi_desc *desc;
int ret;

lockdep_assert_held(&dev->msi.data->mutex);

for (idx = index; idx <= last; idx++) {
desc = msi_alloc_desc(dev, 1, NULL);
if (!desc)
goto fail_mem;
ret = msi_insert_desc(dev->msi.data, desc, MSI_DEFAULT_DOMAIN, idx);
if (ret)
goto fail;
}
return 0;

fail_mem:
ret = -ENOMEM;
fail:
msi_free_msi_descs_range(dev, index, last);
return ret;
}

static bool msi_desc_match(struct msi_desc *desc, enum msi_desc_filter filter)
{
switch (filter) {
Expand All @@ -166,6 +133,7 @@ static bool msi_desc_match(struct msi_desc *desc, enum msi_desc_filter filter)
static bool msi_ctrl_valid(struct device *dev, struct msi_ctrl *ctrl)
{
if (WARN_ON_ONCE(ctrl->domid >= MSI_MAX_DEVICE_IRQDOMAINS ||
!dev->msi.data->__domains[ctrl->domid].domain ||
ctrl->first > ctrl->last ||
ctrl->first > MSI_MAX_INDEX ||
ctrl->last > MSI_MAX_INDEX))
Expand Down Expand Up @@ -214,6 +182,41 @@ void msi_domain_free_msi_descs_range(struct device *dev, unsigned int domid,
msi_domain_free_descs(dev, &ctrl);
}

/**
* msi_domain_add_simple_msi_descs - Allocate and initialize MSI descriptors
* @dev: Pointer to the device for which the descriptors are allocated
* @ctrl: Allocation control struct
*
* Return: 0 on success or an appropriate failure code.
*/
static int msi_domain_add_simple_msi_descs(struct device *dev, struct msi_ctrl *ctrl)
{
struct msi_desc *desc;
unsigned int idx;
int ret;

lockdep_assert_held(&dev->msi.data->mutex);

if (!msi_ctrl_valid(dev, ctrl))
return -EINVAL;

for (idx = ctrl->first; idx <= ctrl->last; idx++) {
desc = msi_alloc_desc(dev, 1, NULL);
if (!desc)
goto fail_mem;
ret = msi_insert_desc(dev->msi.data, desc, ctrl->domid, idx);
if (ret)
goto fail;
}
return 0;

fail_mem:
ret = -ENOMEM;
fail:
msi_domain_free_descs(dev, ctrl);
return ret;
}

void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
*msg = entry->msg;
Expand Down Expand Up @@ -786,16 +789,24 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
{
struct msi_domain_info *info = domain->host_data;
struct msi_domain_ops *ops = info->ops;
struct msi_ctrl ctrl = {
.domid = MSI_DEFAULT_DOMAIN,
.first = virq_base,
.last = virq_base + nvec - 1,
};
struct msi_desc *desc;
struct xarray *xa;
int ret, virq;

if (!msi_ctrl_valid(dev, &ctrl))
return -EINVAL;

msi_lock_descs(dev);
ret = msi_add_simple_msi_descs(dev, virq_base, nvec);
ret = msi_domain_add_simple_msi_descs(dev, &ctrl);
if (ret)
goto unlock;

xa = &dev->msi.data->__domains[MSI_DEFAULT_DOMAIN].store;
xa = &dev->msi.data->__domains[ctrl.domid].store;

for (virq = virq_base; virq < virq_base + nvec; virq++) {
desc = xa_load(xa, virq);
Expand All @@ -814,7 +825,7 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
fail:
for (--virq; virq >= virq_base; virq--)
irq_domain_free_irqs_common(domain, virq, 1);
msi_free_msi_descs_range(dev, virq_base, virq_base + nvec - 1);
msi_domain_free_descs(dev, &ctrl);
unlock:
msi_unlock_descs(dev);
return ret;
Expand Down Expand Up @@ -988,14 +999,19 @@ static int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev
return 0;
}

static int msi_domain_add_simple_msi_descs(struct msi_domain_info *info,
struct device *dev,
unsigned int num_descs)
static int msi_domain_alloc_simple_msi_descs(struct device *dev,
struct msi_domain_info *info,
unsigned int num_descs)
{
struct msi_ctrl ctrl = {
.domid = MSI_DEFAULT_DOMAIN,
.last = num_descs - 1,
};

if (!(info->flags & MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS))
return 0;

return msi_add_simple_msi_descs(dev, 0, num_descs);
return msi_domain_add_simple_msi_descs(dev, &ctrl);
}

/**
Expand Down Expand Up @@ -1026,7 +1042,7 @@ int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device
}

/* Frees allocated descriptors in case of failure. */
ret = msi_domain_add_simple_msi_descs(info, dev, nvec);
ret = msi_domain_alloc_simple_msi_descs(dev, info, nvec);
if (ret)
goto free;

Expand Down

0 comments on commit 4074271

Please sign in to comment.