Commit 653b50c5 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

platform-msi: Let core code handle MSI descriptors



Use the core functionality for platform MSI interrupt domains. The platform
device MSI interrupt domains will be converted in a later step.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarNishanth Menon <nm@ti.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/20211206210748.903173257@linutronix.de
parent e8604b14
Loading
Loading
Loading
Loading
+48 −64
Original line number Diff line number Diff line
@@ -107,57 +107,6 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info)
		info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
}

static void platform_msi_free_descs(struct device *dev, int base, int nvec)
{
	struct msi_desc *desc, *tmp;

	list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
		if (desc->msi_index >= base &&
		    desc->msi_index < (base + nvec)) {
			list_del(&desc->list);
			free_msi_entry(desc);
		}
	}
}

static int platform_msi_alloc_descs_with_irq(struct device *dev, int virq,
					     int nvec)
{
	struct msi_desc *desc;
	int i, base = 0;

	if (!list_empty(dev_to_msi_list(dev))) {
		desc = list_last_entry(dev_to_msi_list(dev),
				       struct msi_desc, list);
		base = desc->msi_index + 1;
	}

	for (i = 0; i < nvec; i++) {
		desc = alloc_msi_entry(dev, 1, NULL);
		if (!desc)
			break;

		desc->msi_index = base + i;
		desc->irq = virq ? virq + i : 0;

		list_add_tail(&desc->list, dev_to_msi_list(dev));
	}

	if (i != nvec) {
		/* Clean up the mess */
		platform_msi_free_descs(dev, base, nvec);

		return -ENOMEM;
	}

	return 0;
}

static int platform_msi_alloc_descs(struct device *dev, int nvec)
{
	return platform_msi_alloc_descs_with_irq(dev, 0, nvec);
}

/**
 * platform_msi_create_irq_domain - Create a platform MSI interrupt domain
 * @fwnode:		Optional fwnode of the interrupt controller
@@ -180,7 +129,8 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
		platform_msi_update_dom_ops(info);
	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
		platform_msi_update_chip_ops(info);
	info->flags |= MSI_FLAG_DEV_SYSFS;
	info->flags |= MSI_FLAG_DEV_SYSFS | MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS |
		       MSI_FLAG_FREE_MSI_DESCS;

	domain = msi_create_irq_domain(fwnode, info, parent);
	if (domain)
@@ -262,20 +212,10 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
	if (err)
		return err;

	err = platform_msi_alloc_descs(dev, nvec);
	if (err)
		goto out_free_priv_data;

	err = msi_domain_alloc_irqs(dev->msi.domain, dev, nvec);
	if (err)
		goto out_free_desc;

	return 0;

out_free_desc:
	platform_msi_free_descs(dev, 0, nvec);
out_free_priv_data:
		platform_msi_free_priv_data(dev);

	return err;
}
EXPORT_SYMBOL_GPL(platform_msi_domain_alloc_irqs);
@@ -287,7 +227,6 @@ EXPORT_SYMBOL_GPL(platform_msi_domain_alloc_irqs);
void platform_msi_domain_free_irqs(struct device *dev)
{
	msi_domain_free_irqs(dev->msi.domain, dev);
	platform_msi_free_descs(dev, 0, MAX_DEV_MSIS);
	platform_msi_free_priv_data(dev);
}
EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs);
@@ -361,6 +300,51 @@ __platform_msi_create_device_domain(struct device *dev,
	return NULL;
}

static void platform_msi_free_descs(struct device *dev, int base, int nvec)
{
	struct msi_desc *desc, *tmp;

	list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
		if (desc->msi_index >= base &&
		    desc->msi_index < (base + nvec)) {
			list_del(&desc->list);
			free_msi_entry(desc);
		}
	}
}

static int platform_msi_alloc_descs_with_irq(struct device *dev, int virq,
					     int nvec)
{
	struct msi_desc *desc;
	int i, base = 0;

	if (!list_empty(dev_to_msi_list(dev))) {
		desc = list_last_entry(dev_to_msi_list(dev),
				       struct msi_desc, list);
		base = desc->msi_index + 1;
	}

	for (i = 0; i < nvec; i++) {
		desc = alloc_msi_entry(dev, 1, NULL);
		if (!desc)
			break;

		desc->msi_index = base + i;
		desc->irq = virq + i;

		list_add_tail(&desc->list, dev_to_msi_list(dev));
	}

	if (i != nvec) {
		/* Clean up the mess */
		platform_msi_free_descs(dev, base, nvec);
		return -ENOMEM;
	}

	return 0;
}

/**
 * platform_msi_device_domain_free - Free interrupts associated with a platform-msi
 *				     device domain