Skip to content

Commit 3381d7b

Browse files
committed
Merge tag 'irq-msi-2026-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull MSI updates from Thomas Gleixner: "Updates for the [PCI] MSI subsystem: - Add interrupt redirection infrastructure Some PCI controllers use a single demultiplexing interrupt for the MSI interrupts of subordinate devices. This prevents setting the interrupt affinity of device interrupts, which causes device interrupts to be delivered to a single CPU. That obviously is counterproductive for multi-queue devices and interrupt balancing. To work around this limitation the new infrastructure installs a dummy irq_set_affinity() callback which captures the affinity mask and picks a redirection target CPU out of the mask. When the PCI controller demultiplexes the interrupts it invokes a new handling function in the core, which either runs the interrupt handler in the context of the target CPU or delegates it to irq_work on the target CPU. - Utilize the interrupt redirection mechanism in the PCI DWC host controller driver. This allows affinity control for the subordinate device MSI interrupts instead of being randomly executed on the CPU which runs the demultiplex handler. - Replace the binary 64-bit MSI flag with a DMA 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. With the binary 64-bit flag there is no other choice than disabling 64-bit MSI support which leaves the device disfunctional. By using a DMA mask the address limit of a device can be described correctly which provides support for the above scenario. - Make use of the DMA mask based address limit in the hda/intel and radeon drivers to enable them on affected platforms - The usual small cleanups and improvements" * tag 'irq-msi-2026-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: ALSA: hda/intel: Make MSI address limit based on the device DMA limit drm/radeon: Make MSI address limit based on the device DMA limit PCI/MSI: Check the device specific address mask in msi_verify_entries() PCI/MSI: Convert the boolean no_64bit_msi flag to a DMA address mask genirq/redirect: Prevent writing MSI message on affinity change PCI/MSI: Unmap MSI-X region on error genirq: Update effective affinity for redirected interrupts PCI: dwc: Enable MSI affinity support PCI: dwc: Code cleanup genirq: Add interrupt redirection infrastructure genirq/msi: Correct kernel-doc in <linux/msi.h>
2 parents dc855b7 + cb9b6f9 commit 3381d7b

18 files changed

Lines changed: 247 additions & 112 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_device.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,7 @@ int radeon_device_init(struct radeon_device *rdev,
13741374
pr_warn("radeon: No suitable DMA available\n");
13751375
return r;
13761376
}
1377+
rdev->pdev->msi_addr_mask = DMA_BIT_MASK(dma_bits);
13771378
rdev->need_swiotlb = drm_need_swiotlb(dma_bits);
13781379

13791380
/* Registers mapping */

drivers/gpu/drm/radeon/radeon_irq_kms.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -245,16 +245,6 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
245245
if (rdev->flags & RADEON_IS_AGP)
246246
return false;
247247

248-
/*
249-
* Older chips have a HW limitation, they can only generate 40 bits
250-
* of address for "64-bit" MSIs which breaks on some platforms, notably
251-
* IBM POWER servers, so we limit them
252-
*/
253-
if (rdev->family < CHIP_BONAIRE) {
254-
dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n");
255-
rdev->pdev->no_64bit_msi = 1;
256-
}
257-
258248
/* force MSI on */
259249
if (radeon_msi == 1)
260250
return true;

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/controller/dwc/pcie-designware-host.c

Lines changed: 58 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,27 @@ static struct pci_ops dw_pcie_ops;
2626
static struct pci_ops dw_pcie_ecam_ops;
2727
static struct pci_ops dw_child_pcie_ops;
2828

29+
#ifdef CONFIG_SMP
30+
static void dw_irq_noop(struct irq_data *d) { }
31+
#endif
32+
33+
static bool dw_pcie_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
34+
struct irq_domain *real_parent, struct msi_domain_info *info)
35+
{
36+
if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
37+
return false;
38+
39+
#ifdef CONFIG_SMP
40+
info->chip->irq_ack = dw_irq_noop;
41+
info->chip->irq_pre_redirect = irq_chip_pre_redirect_parent;
42+
#else
43+
info->chip->irq_ack = irq_chip_ack_parent;
44+
#endif
45+
return true;
46+
}
47+
2948
#define DW_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
3049
MSI_FLAG_USE_DEF_CHIP_OPS | \
31-
MSI_FLAG_NO_AFFINITY | \
3250
MSI_FLAG_PCI_MSI_MASK_PARENT)
3351
#define DW_PCIE_MSI_FLAGS_SUPPORTED (MSI_FLAG_MULTI_PCI_MSI | \
3452
MSI_FLAG_PCI_MSIX | \
@@ -40,41 +58,30 @@ static const struct msi_parent_ops dw_pcie_msi_parent_ops = {
4058
.required_flags = DW_PCIE_MSI_FLAGS_REQUIRED,
4159
.supported_flags = DW_PCIE_MSI_FLAGS_SUPPORTED,
4260
.bus_select_token = DOMAIN_BUS_PCI_MSI,
43-
.chip_flags = MSI_CHIP_FLAG_SET_ACK,
4461
.prefix = "DW-",
45-
.init_dev_msi_info = msi_lib_init_dev_msi_info,
62+
.init_dev_msi_info = dw_pcie_init_dev_msi_info,
4663
};
4764

4865
/* MSI int handler */
49-
irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp)
66+
void dw_handle_msi_irq(struct dw_pcie_rp *pp)
5067
{
51-
int i, pos;
52-
unsigned long val;
53-
u32 status, num_ctrls;
54-
irqreturn_t ret = IRQ_NONE;
5568
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
69+
unsigned int i, num_ctrls;
5670

5771
num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
5872

5973
for (i = 0; i < num_ctrls; i++) {
60-
status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS +
61-
(i * MSI_REG_CTRL_BLOCK_SIZE));
74+
unsigned int reg_off = i * MSI_REG_CTRL_BLOCK_SIZE;
75+
unsigned int irq_off = i * MAX_MSI_IRQS_PER_CTRL;
76+
unsigned long status, pos;
77+
78+
status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS + reg_off);
6279
if (!status)
6380
continue;
6481

65-
ret = IRQ_HANDLED;
66-
val = status;
67-
pos = 0;
68-
while ((pos = find_next_bit(&val, MAX_MSI_IRQS_PER_CTRL,
69-
pos)) != MAX_MSI_IRQS_PER_CTRL) {
70-
generic_handle_domain_irq(pp->irq_domain,
71-
(i * MAX_MSI_IRQS_PER_CTRL) +
72-
pos);
73-
pos++;
74-
}
82+
for_each_set_bit(pos, &status, MAX_MSI_IRQS_PER_CTRL)
83+
generic_handle_demux_domain_irq(pp->irq_domain, irq_off + pos);
7584
}
76-
77-
return ret;
7885
}
7986

8087
/* Chained MSI interrupt service routine */
@@ -95,13 +102,10 @@ static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)
95102
{
96103
struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
97104
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
98-
u64 msi_target;
99-
100-
msi_target = (u64)pp->msi_data;
105+
u64 msi_target = (u64)pp->msi_data;
101106

102107
msg->address_lo = lower_32_bits(msi_target);
103108
msg->address_hi = upper_32_bits(msi_target);
104-
105109
msg->data = d->hwirq;
106110

107111
dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",
@@ -113,37 +117,29 @@ static void dw_pci_bottom_mask(struct irq_data *d)
113117
struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
114118
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
115119
unsigned int res, bit, ctrl;
116-
unsigned long flags;
117-
118-
raw_spin_lock_irqsave(&pp->lock, flags);
119120

121+
guard(raw_spinlock)(&pp->lock);
120122
ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
121123
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
122124
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
123125

124126
pp->irq_mask[ctrl] |= BIT(bit);
125127
dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);
126-
127-
raw_spin_unlock_irqrestore(&pp->lock, flags);
128128
}
129129

130130
static void dw_pci_bottom_unmask(struct irq_data *d)
131131
{
132132
struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
133133
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
134134
unsigned int res, bit, ctrl;
135-
unsigned long flags;
136-
137-
raw_spin_lock_irqsave(&pp->lock, flags);
138135

136+
guard(raw_spinlock)(&pp->lock);
139137
ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
140138
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
141139
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
142140

143141
pp->irq_mask[ctrl] &= ~BIT(bit);
144142
dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);
145-
146-
raw_spin_unlock_irqrestore(&pp->lock, flags);
147143
}
148144

149145
static void dw_pci_bottom_ack(struct irq_data *d)
@@ -160,54 +156,48 @@ static void dw_pci_bottom_ack(struct irq_data *d)
160156
}
161157

162158
static struct irq_chip dw_pci_msi_bottom_irq_chip = {
163-
.name = "DWPCI-MSI",
164-
.irq_ack = dw_pci_bottom_ack,
165-
.irq_compose_msi_msg = dw_pci_setup_msi_msg,
166-
.irq_mask = dw_pci_bottom_mask,
167-
.irq_unmask = dw_pci_bottom_unmask,
159+
.name = "DWPCI-MSI",
160+
.irq_compose_msi_msg = dw_pci_setup_msi_msg,
161+
.irq_mask = dw_pci_bottom_mask,
162+
.irq_unmask = dw_pci_bottom_unmask,
163+
#ifdef CONFIG_SMP
164+
.irq_ack = dw_irq_noop,
165+
.irq_pre_redirect = dw_pci_bottom_ack,
166+
.irq_set_affinity = irq_chip_redirect_set_affinity,
167+
#else
168+
.irq_ack = dw_pci_bottom_ack,
169+
#endif
168170
};
169171

170-
static int dw_pcie_irq_domain_alloc(struct irq_domain *domain,
171-
unsigned int virq, unsigned int nr_irqs,
172-
void *args)
172+
static int dw_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
173+
unsigned int nr_irqs, void *args)
173174
{
174175
struct dw_pcie_rp *pp = domain->host_data;
175-
unsigned long flags;
176-
u32 i;
177176
int bit;
178177

179-
raw_spin_lock_irqsave(&pp->lock, flags);
180-
181-
bit = bitmap_find_free_region(pp->msi_irq_in_use, pp->num_vectors,
182-
order_base_2(nr_irqs));
183-
184-
raw_spin_unlock_irqrestore(&pp->lock, flags);
178+
scoped_guard (raw_spinlock_irq, &pp->lock) {
179+
bit = bitmap_find_free_region(pp->msi_irq_in_use, pp->num_vectors,
180+
order_base_2(nr_irqs));
181+
}
185182

186183
if (bit < 0)
187184
return -ENOSPC;
188185

189-
for (i = 0; i < nr_irqs; i++)
190-
irq_domain_set_info(domain, virq + i, bit + i,
191-
pp->msi_irq_chip,
192-
pp, handle_edge_irq,
193-
NULL, NULL);
194-
186+
for (unsigned int i = 0; i < nr_irqs; i++) {
187+
irq_domain_set_info(domain, virq + i, bit + i, pp->msi_irq_chip,
188+
pp, handle_edge_irq, NULL, NULL);
189+
}
195190
return 0;
196191
}
197192

198-
static void dw_pcie_irq_domain_free(struct irq_domain *domain,
199-
unsigned int virq, unsigned int nr_irqs)
193+
static void dw_pcie_irq_domain_free(struct irq_domain *domain, unsigned int virq,
194+
unsigned int nr_irqs)
200195
{
201196
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
202197
struct dw_pcie_rp *pp = domain->host_data;
203-
unsigned long flags;
204198

205-
raw_spin_lock_irqsave(&pp->lock, flags);
206-
207-
bitmap_release_region(pp->msi_irq_in_use, d->hwirq,
208-
order_base_2(nr_irqs));
209-
210-
raw_spin_unlock_irqrestore(&pp->lock, flags);
199+
guard(raw_spinlock_irq)(&pp->lock);
200+
bitmap_release_region(pp->msi_irq_in_use, d->hwirq, order_base_2(nr_irqs));
211201
}
212202

213203
static const struct irq_domain_ops dw_pcie_msi_domain_ops = {
@@ -241,8 +231,7 @@ void dw_pcie_free_msi(struct dw_pcie_rp *pp)
241231

242232
for (ctrl = 0; ctrl < MAX_MSI_CTRLS; ctrl++) {
243233
if (pp->msi_irq[ctrl] > 0)
244-
irq_set_chained_handler_and_data(pp->msi_irq[ctrl],
245-
NULL, NULL);
234+
irq_set_chained_handler_and_data(pp->msi_irq[ctrl], NULL, NULL);
246235
}
247236

248237
irq_domain_remove(pp->irq_domain);

drivers/pci/controller/dwc/pcie-designware.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ static inline enum dw_pcie_ltssm dw_pcie_get_ltssm(struct dw_pcie *pci)
821821
#ifdef CONFIG_PCIE_DW_HOST
822822
int dw_pcie_suspend_noirq(struct dw_pcie *pci);
823823
int dw_pcie_resume_noirq(struct dw_pcie *pci);
824-
irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp);
824+
void dw_handle_msi_irq(struct dw_pcie_rp *pp);
825825
void dw_pcie_msi_init(struct dw_pcie_rp *pp);
826826
int dw_pcie_msi_host_init(struct dw_pcie_rp *pp);
827827
void dw_pcie_free_msi(struct dw_pcie_rp *pp);
@@ -842,10 +842,7 @@ static inline int dw_pcie_resume_noirq(struct dw_pcie *pci)
842842
return 0;
843843
}
844844

845-
static inline irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp)
846-
{
847-
return IRQ_NONE;
848-
}
845+
static inline void dw_handle_msi_irq(struct dw_pcie_rp *pp) { }
849846

850847
static inline void dw_pcie_msi_init(struct dw_pcie_rp *pp)
851848
{ }

drivers/pci/msi/msi.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,16 @@ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
321321
static int msi_verify_entries(struct pci_dev *dev)
322322
{
323323
struct msi_desc *entry;
324+
u64 address;
324325

325-
if (!dev->no_64bit_msi)
326+
if (dev->msi_addr_mask == DMA_BIT_MASK(64))
326327
return 0;
327328

328329
msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) {
329-
if (entry->msg.address_hi) {
330-
pci_err(dev, "arch assigned 64-bit MSI address %#x%08x but device only supports 32 bits\n",
331-
entry->msg.address_hi, entry->msg.address_lo);
330+
address = (u64)entry->msg.address_hi << 32 | entry->msg.address_lo;
331+
if (address & ~dev->msi_addr_mask) {
332+
pci_err(dev, "arch assigned 64-bit MSI address %#llx above device MSI address mask %#llx\n",
333+
address, dev->msi_addr_mask);
332334
break;
333335
}
334336
}
@@ -737,7 +739,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
737739

738740
ret = msix_setup_interrupts(dev, entries, nvec, affd);
739741
if (ret)
740-
goto out_disable;
742+
goto out_unmap;
741743

742744
/* Disable INTX */
743745
pci_intx_for_msi(dev, 0);
@@ -758,6 +760,8 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
758760
pcibios_free_irq(dev);
759761
return 0;
760762

763+
out_unmap:
764+
iounmap(dev->msix_base);
761765
out_disable:
762766
dev->msix_enabled = 0;
763767
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0);

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));

0 commit comments

Comments
 (0)