Skip to content

Commit 386ced1

Browse files
dramforeverThomas Gleixner
authored andcommitted
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: Vivian Wang <wangruikang@iscas.ac.cn> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Reviewed-by: Brett Creeley <brett.creeley@amd.com> # ionic Reviewed-by: Thomas 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
1 parent 37f9d50 commit 386ced1

9 files changed

Lines changed: 22 additions & 9 deletions

File tree

arch/powerpc/platforms/powernv/pci-ioda.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1666,7 +1666,7 @@ static int __pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
16661666
return -ENXIO;
16671667

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

16721672
/* Assign XIVE to PE */

arch/powerpc/platforms/pseries/msi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ static int rtas_prepare_msi_irqs(struct pci_dev *pdev, int nvec_in, int type,
383383
*/
384384
again:
385385
if (type == PCI_CAP_ID_MSI) {
386-
if (pdev->no_64bit_msi) {
386+
if (pdev->msi_addr_mask < DMA_BIT_MASK(64)) {
387387
rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
388388
if (rc < 0) {
389389
/*
@@ -409,7 +409,7 @@ static int rtas_prepare_msi_irqs(struct pci_dev *pdev, int nvec_in, int type,
409409
if (use_32bit_msi_hack && rc > 0)
410410
rtas_hack_32bit_msi_gen2(pdev);
411411
} else {
412-
if (pdev->no_64bit_msi)
412+
if (pdev->msi_addr_mask < DMA_BIT_MASK(64))
413413
rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSIX_FN, nvec);
414414
else
415415
rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);

drivers/gpu/drm/radeon/radeon_irq_kms.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
252252
*/
253253
if (rdev->family < CHIP_BONAIRE) {
254254
dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n");
255-
rdev->pdev->no_64bit_msi = 1;
255+
rdev->pdev->msi_addr_mask = DMA_BIT_MASK(32);
256256
}
257257

258258
/* force MSI on */

drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
331331

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

337337
err = ionic_setup_one(ionic);

drivers/pci/msi/msi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static int msi_verify_entries(struct pci_dev *dev)
322322
{
323323
struct msi_desc *entry;
324324

325-
if (!dev->no_64bit_msi)
325+
if (dev->msi_addr_mask == DMA_BIT_MASK(64))
326326
return 0;
327327

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

drivers/pci/msi/pcidev_msi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ void pci_msi_init(struct pci_dev *dev)
2424
}
2525

2626
if (!(ctrl & PCI_MSI_FLAGS_64BIT))
27-
dev->no_64bit_msi = 1;
27+
dev->msi_addr_mask = DMA_BIT_MASK(32);
2828
}
2929

3030
void pci_msix_init(struct pci_dev *dev)

drivers/pci/probe.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,6 +2047,13 @@ int pci_setup_device(struct pci_dev *dev)
20472047
*/
20482048
dev->dma_mask = 0xffffffff;
20492049

2050+
/*
2051+
* Assume 64-bit addresses for MSI initially. Will be changed to 32-bit
2052+
* if MSI (rather than MSI-X) capability does not have
2053+
* PCI_MSI_FLAGS_64BIT. Can also be overridden by driver.
2054+
*/
2055+
dev->msi_addr_mask = DMA_BIT_MASK(64);
2056+
20502057
dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus),
20512058
dev->bus->number, PCI_SLOT(dev->devfn),
20522059
PCI_FUNC(dev->devfn));

include/linux/pci.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,13 @@ struct pci_dev {
377377
0xffffffff. You only need to change
378378
this if your device has broken DMA
379379
or supports 64-bit transfers. */
380+
u64 msi_addr_mask; /* Mask of the bits of bus address for
381+
MSI that this device implements.
382+
Normally set based on device
383+
capabilities. You only need to
384+
change this if your device claims
385+
to support 64-bit MSI but implements
386+
fewer than 64 address bits. */
380387

381388
struct device_dma_parameters dma_parms;
382389

@@ -441,7 +448,6 @@ struct pci_dev {
441448

442449
unsigned int is_busmaster:1; /* Is busmaster */
443450
unsigned int no_msi:1; /* May not use MSI */
444-
unsigned int no_64bit_msi:1; /* May only use 32-bit MSIs */
445451
unsigned int block_cfg_access:1; /* Config space access blocked */
446452
unsigned int broken_parity_status:1; /* Generates false positive parity */
447453
unsigned int irq_reroute_variant:2; /* Needs IRQ rerouting variant */

sound/hda/controllers/intel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1905,7 +1905,7 @@ static int azx_first_init(struct azx *chip)
19051905

19061906
if (chip->msi && chip->driver_caps & AZX_DCAPS_NO_MSI64) {
19071907
dev_dbg(card->dev, "Disabling 64bit MSI\n");
1908-
pci->no_64bit_msi = true;
1908+
pci->msi_addr_mask = DMA_BIT_MASK(32);
19091909
}
19101910

19111911
pci_set_master(pci);

0 commit comments

Comments
 (0)