[PATCH v4 07/21] irqchip/riscv-imsic: Compose MSI updates through the hierarchy
Andrew Jones <[email protected]>
| Newsgroups | org.infradead.lists.linux-riscv,dev.linux.lists.iommu,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
imsic_irq_set_affinity() currently writes a newly composed MSI message directly to the device. This bypasses intermediate irqdomains, so an IOMMU remapping domain cannot translate the target after an affinity change. Compose affinity updates from the top of the hierarchy instead. This allows each intermediate domain to update the message and any descriptor state before the device is programmed. Non-atomic moves temporarily use the old address with the new interrupt ID before switching to the new vector. Preserve that transition by composing the temporary message before publishing the new vector, then compose the final message after publishing it, but before the old vector is retired. Signed-off-by: Andrew Jones <[email protected]> --- drivers/irqchip/irq-riscv-imsic-platform.c | 27 ++++++++-------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c index 643c8e459611..5634641dc223 100644 --- a/drivers/irqchip/irq-riscv-imsic-platform.c +++ b/drivers/irqchip/irq-riscv-imsic-platform.c @@ -90,19 +90,12 @@ static void imsic_irq_compose_msg(struct irq_data *d, struct msi_msg *msg) } #ifdef CONFIG_SMP -static void imsic_msi_update_msg(struct irq_data *d, struct imsic_vector *vec) -{ - struct msi_msg msg = { }; - - imsic_irq_compose_vector_msg(vec, &msg); - irq_data_get_irq_chip(d)->irq_write_msi_msg(d, &msg); -} - static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { + struct irq_data *top = irq_get_irq_data(d->irq); struct imsic_vector *old_vec, *new_vec; - struct imsic_vector tmp_vec; + struct msi_msg msg = { }; /* * Requirements for the downstream irqdomains (or devices): @@ -153,20 +146,20 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask */ if (!irq_can_move_in_process_context(d) && new_vec->local_id != old_vec->local_id) { - /* Setup temporary vector */ - tmp_vec.cpu = old_vec->cpu; - tmp_vec.local_id = new_vec->local_id; - /* Point device to the temporary vector */ - imsic_msi_update_msg(irq_get_irq_data(d->irq), &tmp_vec); + BUG_ON(irq_chip_compose_msi_msg(top, &msg)); + msg.data = new_vec->local_id; + irq_data_get_irq_chip(top)->irq_write_msi_msg(top, &msg); } - /* Point device to the new vector */ - imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec); - /* Update irq descriptors with the new vector */ d->chip_data = new_vec; + /* Point device to the new vector */ + memset(&msg, 0, sizeof(msg)); + BUG_ON(irq_chip_compose_msi_msg(top, &msg)); + irq_data_get_irq_chip(top)->irq_write_msi_msg(top, &msg); + /* Update effective affinity */ irq_data_update_effective_affinity(d, cpumask_of(new_vec->cpu)); -- 2.43.0 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv