On 1/6/26 02:05, Creeley, Brett wrote:
> On 12/23/2025 7:10 PM, Vivian Wang wrote:
>> Caution: This message originated from an External Source. Use proper caution 
>> when opening attachments, clicking links, or responding.
>>
>>
>> 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 reachable.
>>
>> Currently, we deal with this with a single no_64bit_msi flag, and
>> (notably on powerpc) use 32-bit MSI address for these devices. However,
>> on some platforms the MSI doorbell address is above 32-bit but within
>> device ability.
>>
>> As a first step, conservatively generalize the single-bit flag
>> no_64bit_msi into msi_addr_mask. (The name msi_addr_mask is chosen to
>> avoid confusion with msi_mask.)
>>
>> The translation is essentially:
>>
>> - 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) is
>> used, no functional change is intended. Future patches that make use of
>> intermediate values of msi_addr_mask will follow, allowing devices that
>> cannot use full 64-bit addresses for MSI to work on platforms with MSI
>> doorbell above 32-bit address space.
>>
>> Signed-off-by: Vivian Wang <[email protected]>
>>
>> ---
>>
>> checkpatch complains about the comment include/linux/pci.h, which I have
>> formatted similarly with other comments in the vicinity.
>> ---
>>   arch/powerpc/platforms/powernv/pci-ioda.c           | 2 +-
>>   arch/powerpc/platforms/pseries/msi.c                | 4 ++--
>>   drivers/gpu/drm/radeon/radeon_irq_kms.c             | 2 +-
>>   drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c | 2 +-
>>   drivers/pci/msi/msi.c                               | 2 +-
>>   drivers/pci/msi/pcidev_msi.c                        | 2 +-
>>   drivers/pci/probe.c                                 | 7 +++++++
>>   include/linux/pci.h                                 | 8 +++++++-
>>   sound/hda/controllers/intel.c                       | 2 +-
>>   9 files changed, 22 insertions(+), 9 deletions(-)
>>
>> diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
>> b/arch/powerpc/platforms/powernv/pci-ioda.c
>> index b0c1d9d16fb5..1c78fdfb7b03 100644
>> --- a/arch/powerpc/platforms/powernv/pci-ioda.c
>> +++ b/arch/powerpc/platforms/powernv/pci-ioda.c
>> @@ -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 */
>> diff --git a/arch/powerpc/platforms/pseries/msi.c 
>> b/arch/powerpc/platforms/pseries/msi.c
>> index a82aaa786e9e..7473c7ca1db0 100644
>> --- a/arch/powerpc/platforms/pseries/msi.c
>> +++ b/arch/powerpc/platforms/pseries/msi.c
>> @@ -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);
>> diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c 
>> b/drivers/gpu/drm/radeon/radeon_irq_kms.c
>> index 9961251b44ba..d550554a6f3f 100644
>> --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
>> +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
>> @@ -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 */
>> diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c 
>> b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
>> index 70d86c5f52fb..0671deae9a28 100644
>> --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
>> +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
>> @@ -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);
> I know this is just an intermediate commit in the series, but does this
> retain the original intent?
I do believe so, yes. The no_64bit_msi bit's meaning is the negation of
this bit found in the MSI capability:

    #define  PCI_MSI_FLAGS_64BIT    0x0080    /* 64-bit addresses allowed */

PCI_MSI_FLAGS_64BIT is set if this function handles PCI_MSI_ADDRESS_HI
and cleared if doesn't handle PCI_MSI_ADDRESS_HI. So with "no 64bit",
only PCI_MSI_ADDRESS_LO is usable, and MSI is limited to 32 bits. See
also old handling here:

>> diff --git a/drivers/pci/msi/pcidev_msi.c b/drivers/pci/msi/pcidev_msi.c
>> index 5520aff53b56..0b0346813092 100644
>> --- a/drivers/pci/msi/pcidev_msi.c
>> +++ b/drivers/pci/msi/pcidev_msi.c
>> @@ -24,7 +24,7 @@ void pci_msi_init(struct pci_dev *dev)
>>          }
>>
>>          if (!(ctrl & PCI_MSI_FLAGS_64BIT))
>> -               dev->no_64bit_msi = 1;
>> +               dev->msi_addr_mask = DMA_BIT_MASK(32);
>>   }
>>
>>   void pci_msix_init(struct pci_dev *dev)
... and the old definition of the flag here, where the comment
explicitly says no_64bit_msi means 32-bit:
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index 41183aed8f5d..a2bff57176a3 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>>
>> [...]
>>
>> @@ -441,7 +448,6 @@ struct pci_dev {
>>
>>          unsigned int    is_busmaster:1;         /* Is busmaster */
>>          unsigned int    no_msi:1;               /* May not use MSI */
>> -       unsigned int    no_64bit_msi:1;         /* May only use 32-bit MSIs 
>> */
>>          unsigned int    block_cfg_access:1;     /* Config space access 
>> blocked */
>>          unsigned int    broken_parity_status:1; /* Generates false positive 
>> parity */
>>          unsigned int    irq_reroute_variant:2;  /* Needs IRQ rerouting 
>> variant */
Vivian "dramforever" Wang

Reply via email to