From 163982253f22d4c123044b3cf6e4f71427d98b8f Mon Sep 17 00:00:00 2001 From: Guixin Liu Date: Tue, 17 Mar 2026 15:28:26 +0800 Subject: [PATCH] anolis: PCI/MSI: Update msix domain hwsize ANBZ: #32236 After the upper-layer driver is removed, the hardware firmware may modify the hwsize during the period before the next probe. The irq_domain still retains the old hwsize value, so the hwsize should be checked and updated when setting up the MSI-X device domain. Signed-off-by: Guixin Liu --- drivers/pci/msi/irqdomain.c | 5 ++++- include/linux/msi.h | 3 +++ kernel/irq/msi.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/pci/msi/irqdomain.c b/drivers/pci/msi/irqdomain.c index f569d575fa72..2bad86354b2a 100644 --- a/drivers/pci/msi/irqdomain.c +++ b/drivers/pci/msi/irqdomain.c @@ -325,8 +325,11 @@ bool pci_setup_msix_device_domain(struct pci_dev *pdev, unsigned int hwsize) if (WARN_ON_ONCE(pdev->msi_enabled)) return false; - if (pci_match_device_domain(pdev, DOMAIN_BUS_PCI_DEVICE_MSIX)) + if (pci_match_device_domain(pdev, DOMAIN_BUS_PCI_DEVICE_MSIX)) { + if (msi_domain_update_hwsize(&pdev->dev, MSI_DEFAULT_DOMAIN, hwsize)) + pr_warn("too big MSI-X hwsize:%u\n", hwsize); return true; + } if (pci_match_device_domain(pdev, DOMAIN_BUS_PCI_DEVICE_MSI)) msi_remove_device_irq_domain(&pdev->dev, MSI_DEFAULT_DOMAIN); diff --git a/include/linux/msi.h b/include/linux/msi.h index 78046c06a0a1..de51fc3c9f82 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -622,6 +622,9 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid, void *chip_data); void msi_remove_device_irq_domain(struct device *dev, unsigned int domid); +int msi_domain_update_hwsize(struct device *dev, unsigned int domid, + unsigned int hwsize_new); + bool msi_match_device_irq_domain(struct device *dev, unsigned int domid, enum irq_domain_bus_token bus_token); diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index ac3361da4fe1..cb5bcfbab43a 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -1079,6 +1079,34 @@ void msi_remove_device_irq_domain(struct device *dev, unsigned int domid) msi_unlock_descs(dev); } +int msi_domain_update_hwsize(struct device *dev, unsigned int domid, + unsigned int hwsize_new) +{ + struct msi_domain_info *info; + struct irq_domain *domain; + int ret = 0; + + if (hwsize_new > MSI_XA_DOMAIN_SIZE) + return -EINVAL; + if (!hwsize_new) + hwsize_new = MSI_XA_DOMAIN_SIZE; + + msi_lock_descs(dev); + + domain = msi_get_device_domain(dev, domid); + if (!domain) { + ret = -ENODEV; + goto out; + } + + info = domain->host_data; + if (hwsize_new != info->hwsize) + info->hwsize = hwsize_new; +out: + msi_unlock_descs(dev); + return ret; +} + /** * msi_match_device_irq_domain - Match a device irq domain against a bus token * @dev: Pointer to the device -- Gitee