Commit 9cc82d99 authored by Marc Zyngier's avatar Marc Zyngier Committed by Thomas Gleixner
Browse files

PCI/MSI: Size device MSI domain with the maximum number of vectors



Zenghui reports that since 1396e89e ("genirq/msi: Move prepare() call
to per-device allocation"), his Multi-MSI capable device isn't working
anymore.

This is a consequence of 15c72f82 ("PCI/MSI: Add support for per device
MSI[X] domains"), which always creates a MSI domain of size 1, even in the
presence of Multi-MSI.

While this was somehow working until then, moving the .prepare() call ends
up sizing the ITS table with a tiny value for this device, and making the
endpoint driver unhappy.

Instead, always create the domain and call the .prepare() helper with the
maximum expected size.

Fixes: 1396e89e ("genirq/msi: Move prepare() call to per-device allocation")
Fixes: 15c72f82 ("PCI/MSI: Add support for per device MSI[X] domains")
Reported-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Reviewed-by: default avatarLorenzo Pieralisi <lpieralisi@kernel.org>
Link: https://lore.kernel.org/all/20250603141801.915305-1-maz@kernel.org
Closes: https://lore.kernel.org/r/0b1d7aec-1eac-a9cd-502a-339e216e08a1@huawei.com
parent 5abc7438
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -271,6 +271,7 @@ static bool pci_create_device_domain(struct pci_dev *pdev, const struct msi_doma
/**
 * pci_setup_msi_device_domain - Setup a device MSI interrupt domain
 * @pdev:	The PCI device to create the domain on
 * @hwsize:	The maximum number of MSI vectors
 *
 * Return:
 *  True when:
@@ -287,7 +288,7 @@ static bool pci_create_device_domain(struct pci_dev *pdev, const struct msi_doma
 *	- The device is removed
 *	- MSI is disabled and a MSI-X domain is created
 */
bool pci_setup_msi_device_domain(struct pci_dev *pdev)
bool pci_setup_msi_device_domain(struct pci_dev *pdev, unsigned int hwsize)
{
	if (WARN_ON_ONCE(pdev->msix_enabled))
		return false;
@@ -297,7 +298,7 @@ bool pci_setup_msi_device_domain(struct pci_dev *pdev)
	if (pci_match_device_domain(pdev, DOMAIN_BUS_PCI_DEVICE_MSIX))
		msi_remove_device_irq_domain(&pdev->dev, MSI_DEFAULT_DOMAIN);

	return pci_create_device_domain(pdev, &pci_msi_template, 1);
	return pci_create_device_domain(pdev, &pci_msi_template, hwsize);
}

/**
+4 −4
Original line number Diff line number Diff line
@@ -439,16 +439,16 @@ int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
	if (nvec < minvec)
		return -ENOSPC;

	if (nvec > maxvec)
		nvec = maxvec;

	rc = pci_setup_msi_context(dev);
	if (rc)
		return rc;

	if (!pci_setup_msi_device_domain(dev))
	if (!pci_setup_msi_device_domain(dev, nvec))
		return -ENODEV;

	if (nvec > maxvec)
		nvec = maxvec;

	for (;;) {
		if (affd) {
			nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
+1 −1
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ enum support_mode {
};

bool pci_msi_domain_supports(struct pci_dev *dev, unsigned int feature_mask, enum support_mode mode);
bool pci_setup_msi_device_domain(struct pci_dev *pdev);
bool pci_setup_msi_device_domain(struct pci_dev *pdev, unsigned int hwsize);
bool pci_setup_msix_device_domain(struct pci_dev *pdev, unsigned int hwsize);

/* Legacy (!IRQDOMAIN) fallbacks */