Skip to content

Commit 0fb7fb7

Browse files
committed
genirq/msi, platform-msi: Ensure that MSI descriptors are unreferenced
Miquel reported a warning in the MSI core which is triggered when interrupts are freed via platform_msi_device_domain_free(). This code got reworked to use core functions for freeing the MSI descriptors, but nothing took care to clear the msi_desc->irq entry, which then triggers the warning in msi_free_msi_desc() which uses desc->irq to validate that the descriptor has been torn down. The same issue exists in msi_domain_populate_irqs(). Up to the point that msi_free_msi_descs() grew a warning for this case, this went un-noticed. Provide the counterpart of msi_domain_populate_irqs() and invoke it in platform_msi_device_domain_free() before freeing the interrupts and MSI descriptors and also in the error path of msi_domain_populate_irqs(). Fixes: 2f2940d ("genirq/msi: Remove filter from msi_free_descs_free_range()") Reported-by: Miquel Raynal <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Miquel Raynal <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/87mt4wkwnv.ffs@tglx
1 parent ea9a78c commit 0fb7fb7

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

drivers/base/platform-msi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int vir
324324
struct platform_msi_priv_data *data = domain->host_data;
325325

326326
msi_lock_descs(data->dev);
327+
msi_domain_depopulate_descs(data->dev, virq, nr_irqs);
327328
irq_domain_free_irqs_common(domain, virq, nr_irqs);
328329
msi_free_msi_descs_range(data->dev, virq, virq + nr_irqs - 1);
329330
msi_unlock_descs(data->dev);

include/linux/msi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,8 @@ int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
631631
int nvec, msi_alloc_info_t *args);
632632
int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
633633
int virq, int nvec, msi_alloc_info_t *args);
634+
void msi_domain_depopulate_descs(struct device *dev, int virq, int nvec);
635+
634636
struct irq_domain *
635637
__platform_msi_create_device_domain(struct device *dev,
636638
unsigned int nvec,

kernel/irq/msi.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1109,14 +1109,35 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
11091109
return 0;
11101110

11111111
fail:
1112-
for (--virq; virq >= virq_base; virq--)
1112+
for (--virq; virq >= virq_base; virq--) {
1113+
msi_domain_depopulate_descs(dev, virq, 1);
11131114
irq_domain_free_irqs_common(domain, virq, 1);
1115+
}
11141116
msi_domain_free_descs(dev, &ctrl);
11151117
unlock:
11161118
msi_unlock_descs(dev);
11171119
return ret;
11181120
}
11191121

1122+
void msi_domain_depopulate_descs(struct device *dev, int virq_base, int nvec)
1123+
{
1124+
struct msi_ctrl ctrl = {
1125+
.domid = MSI_DEFAULT_DOMAIN,
1126+
.first = virq_base,
1127+
.last = virq_base + nvec - 1,
1128+
};
1129+
struct msi_desc *desc;
1130+
struct xarray *xa;
1131+
unsigned long idx;
1132+
1133+
if (!msi_ctrl_valid(dev, &ctrl))
1134+
return;
1135+
1136+
xa = &dev->msi.data->__domains[ctrl.domid].store;
1137+
xa_for_each_range(xa, idx, desc, ctrl.first, ctrl.last)
1138+
desc->irq = 0;
1139+
}
1140+
11201141
/*
11211142
* Carefully check whether the device can use reservation mode. If
11221143
* reservation mode is enabled then the early activation will assign a

0 commit comments

Comments
 (0)