Commit 386ced19 authored by Vivian Wang's avatar Vivian Wang Committed by Thomas Gleixner
Browse files

PCI/MSI: Convert the boolean no_64bit_msi flag to a DMA address mask



Some PCI devices have PCI_MSI_FLAGS_64BIT in the MSI capability, but
implement less than 64 address bits. This breaks on platforms where such
a device is assigned an MSI address higher than what's supported.

Currently, no_64bit_msi bit is set for these devices, meaning that only
32-bit MSI addresses are allowed for them. However, on some platforms the
MSI doorbell address is above the 32-bit limit but within the addressable
range of the device.

As a first step to enable MSI on those combinations of devices and
platforms, convert the boolean no_64bit_msi flag to a DMA mask and fixup
the affected usage sites:

  - no_64bit_msi = 1    ->    msi_addr_mask = DMA_BIT_MASK(32)
  - no_64bit_msi = 0    ->    msi_addr_mask = DMA_BIT_MASK(64)
  - if (no_64bit_msi)   ->    if (msi_addr_mask < DMA_BIT_MASK(64))

Since no values other than DMA_BIT_MASK(32) and DMA_BIT_MASK(64) are used,
this is functionally equivalent.

This prepares for changing the binary decision between 32 and 64 bit to a
DMA mask based decision which allows to support systems which have a DMA
address space less than 64bit but a MSI doorbell address above the 32-bit
limit.

[ tglx: Massaged changelog ]

Signed-off-by: default avatarVivian Wang <wangruikang@iscas.ac.cn>
Signed-off-by: default avatarThomas Gleixner <tglx@kernel.org>
Reviewed-by: Brett Creeley <brett.creeley@amd.com> # ionic
Reviewed-by: default avatarThomas Gleixner <tglx@kernel.org>
Acked-by: Takashi Iwai <tiwai@suse.de> # sound
Link: https://patch.msgid.link/20260129-pci-msi-addr-mask-v4-1-70da998f2750@iscas.ac.cn
parent 37f9d502
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1666,7 +1666,7 @@ static int __pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
		return -ENXIO;

	/* Force 32-bit MSI on some broken devices */
	if (dev->no_64bit_msi)
	if (dev->msi_addr_mask < DMA_BIT_MASK(64))
		is_64 = 0;

	/* Assign XIVE to PE */
+2 −2
Original line number Diff line number Diff line
@@ -383,7 +383,7 @@ static int rtas_prepare_msi_irqs(struct pci_dev *pdev, int nvec_in, int type,
	 */
again:
	if (type == PCI_CAP_ID_MSI) {
		if (pdev->no_64bit_msi) {
		if (pdev->msi_addr_mask < DMA_BIT_MASK(64)) {
			rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
			if (rc < 0) {
				/*
@@ -409,7 +409,7 @@ static int rtas_prepare_msi_irqs(struct pci_dev *pdev, int nvec_in, int type,
		if (use_32bit_msi_hack && rc > 0)
			rtas_hack_32bit_msi_gen2(pdev);
	} else {
		if (pdev->no_64bit_msi)
		if (pdev->msi_addr_mask < DMA_BIT_MASK(64))
			rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSIX_FN, nvec);
		else
			rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
+1 −1
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
	 */
	if (rdev->family < CHIP_BONAIRE) {
		dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n");
		rdev->pdev->no_64bit_msi = 1;
		rdev->pdev->msi_addr_mask = DMA_BIT_MASK(32);
	}

	/* force MSI on */
+1 −1
Original line number Diff line number Diff line
@@ -331,7 +331,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

#ifdef CONFIG_PPC64
	/* Ensure MSI/MSI-X interrupts lie within addressable physical memory */
	pdev->no_64bit_msi = 1;
	pdev->msi_addr_mask = DMA_BIT_MASK(32);
#endif

	err = ionic_setup_one(ionic);
+1 −1
Original line number Diff line number Diff line
@@ -322,7 +322,7 @@ static int msi_verify_entries(struct pci_dev *dev)
{
	struct msi_desc *entry;

	if (!dev->no_64bit_msi)
	if (dev->msi_addr_mask == DMA_BIT_MASK(64))
		return 0;

	msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) {
Loading