Commit 60290525 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

genirq/msi: Provide msi_alloc_msi_desc() and a simple allocator



Provide msi_alloc_msi_desc() which takes a template MSI descriptor for
initializing a newly allocated descriptor. This allows to simplify various
usage sites of alloc_msi_entry() and moves the storage handling into the
core code.

For simple cases where only a linear vector space is required provide
msi_add_simple_msi_descs() which just allocates a linear range of MSI
descriptors and fills msi_desc::msi_index accordingly.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarMichael Kelley <mikelley@microsoft.com>
Tested-by: default avatarNishanth Menon <nm@ti.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/20211206210747.873833567@linutronix.de
parent 1046f71d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -247,6 +247,8 @@ static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg)
}
#endif /* CONFIG_PCI_MSI */

int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc);

struct msi_desc *alloc_msi_entry(struct device *dev, int nvec,
				 const struct irq_affinity_desc *affinity);
void free_msi_entry(struct msi_desc *entry);
+59 −0
Original line number Diff line number Diff line
@@ -60,6 +60,65 @@ void free_msi_entry(struct msi_desc *entry)
	kfree(entry);
}

/**
 * msi_add_msi_desc - Allocate and initialize a MSI descriptor
 * @dev:	Pointer to the device for which the descriptor is allocated
 * @init_desc:	Pointer to an MSI descriptor to initialize the new descriptor
 *
 * Return: 0 on success or an appropriate failure code.
 */
int msi_add_msi_desc(struct device *dev, struct msi_desc *init_desc)
{
	struct msi_desc *desc;

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

	desc = alloc_msi_entry(dev, init_desc->nvec_used, init_desc->affinity);
	if (!desc)
		return -ENOMEM;

	/* Copy the MSI index and type specific data to the new descriptor. */
	desc->msi_index = init_desc->msi_index;
	desc->pci = init_desc->pci;

	list_add_tail(&desc->list, &dev->msi.data->list);
	return 0;
}

/**
 * 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)
{
	struct msi_desc *desc, *tmp;
	LIST_HEAD(list);
	unsigned int i;

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

	for (i = 0; i < ndesc; i++) {
		desc = alloc_msi_entry(dev, 1, NULL);
		if (!desc)
			goto fail;
		desc->msi_index = index + i;
		list_add_tail(&desc->list, &list);
	}
	list_splice_tail(&list, &dev->msi.data->list);
	return 0;

fail:
	list_for_each_entry_safe(desc, tmp, &list, list) {
		list_del(&desc->list);
		free_msi_entry(desc);
	}
	return -ENOMEM;
}

void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
	*msg = entry->msg;