Lines Matching +full:in +full:- +full:flight

1 // SPDX-License-Identifier: GPL-2.0
7 #define pr_fmt(fmt) "riscv-imsic: " fmt
23 #include <linux/irqchip/irq-msi-lib.h>
24 #include "irq-riscv-imsic-state.h"
32 global = &imsic->global; in imsic_cpu_page_phys()
33 local = per_cpu_ptr(global->local, cpu); in imsic_cpu_page_phys()
35 if (BIT(global->guest_index_bits) <= guest_index) in imsic_cpu_page_phys()
39 *out_msi_pa = local->msi_pa + (guest_index * IMSIC_MMIO_PAGE_SZ); in imsic_cpu_page_phys()
60 return -ENOENT; in imsic_irq_retrigger()
62 local = per_cpu_ptr(imsic->global.local, vec->cpu); in imsic_irq_retrigger()
63 writel_relaxed(vec->local_id, local->msi_va); in imsic_irq_retrigger()
79 if (WARN_ON(!imsic_cpu_page_phys(vec->cpu, 0, &msi_addr))) in imsic_irq_compose_vector_msg()
82 msg->address_hi = upper_32_bits(msi_addr); in imsic_irq_compose_vector_msg()
83 msg->address_lo = lower_32_bits(msi_addr); in imsic_irq_compose_vector_msg()
84 msg->data = vec->local_id; in imsic_irq_compose_vector_msg()
98 irq_data_get_irq_chip(d)->irq_write_msi_msg(d, &msg); in imsic_msi_update_msg()
111 * happily do imsic_irq_set_affinity() in the process-context on in imsic_irq_set_affinity()
115 * 2) Downstream irqdomains (or devices) with non-atomic MSI update in imsic_irq_set_affinity()
116 * must use imsic_irq_set_affinity() in nterrupt-context upon in imsic_irq_set_affinity()
123 return -ENOENT; in imsic_irq_set_affinity()
126 if (cpumask_test_cpu(old_vec->cpu, mask_val)) in imsic_irq_set_affinity()
129 /* If move is already in-flight then return failure */ in imsic_irq_set_affinity()
131 return -EBUSY; in imsic_irq_set_affinity()
134 new_vec = imsic_vector_alloc(old_vec->irq, mask_val); in imsic_irq_set_affinity()
136 return -ENOSPC; in imsic_irq_set_affinity()
139 * Device having non-atomic MSI update might see an intermediate in imsic_irq_set_affinity()
155 new_vec->local_id != old_vec->local_id) { in imsic_irq_set_affinity()
157 tmp_vec.cpu = old_vec->cpu; in imsic_irq_set_affinity()
158 tmp_vec.local_id = new_vec->local_id; in imsic_irq_set_affinity()
161 imsic_msi_update_msg(irq_get_irq_data(d->irq), &tmp_vec); in imsic_irq_set_affinity()
165 imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec); in imsic_irq_set_affinity()
168 d->chip_data = new_vec; in imsic_irq_set_affinity()
171 irq_data_update_effective_affinity(d, cpumask_of(new_vec->cpu)); in imsic_irq_set_affinity()
187 /* Do nothing if there is no in-flight move */ in imsic_irq_force_complete_move()
193 if (mvec->cpu != cpu) in imsic_irq_force_complete_move()
200 * refer to the comments in irq_force_complete_move() function in imsic_irq_force_complete_move()
204 /* Force cleanup in-flight move */ in imsic_irq_force_complete_move()
205 pr_info("IRQ fixup: irq %d move in progress, old vector cpu %d local_id %d\n", in imsic_irq_force_complete_move()
206 d->irq, mvec->cpu, mvec->local_id); in imsic_irq_force_complete_move()
230 /* Multi-MSI is not supported yet. */ in imsic_irq_domain_alloc()
232 return -EOPNOTSUPP; in imsic_irq_domain_alloc()
236 return -ENOSPC; in imsic_irq_domain_alloc()
242 irq_data_update_effective_affinity(irq_get_irq_data(virq), cpumask_of(vec->cpu)); in imsic_irq_domain_alloc()
284 switch (info->bus_token) { in imsic_init_dev_msi_info()
287 info->chip->flags |= IRQCHIP_MOVE_DEFERRED; in imsic_init_dev_msi_info()
316 if (!imsic || !imsic->fwnode) { in imsic_irqdomain_init()
318 return -ENODEV; in imsic_irqdomain_init()
321 if (imsic->base_domain) { in imsic_irqdomain_init()
322 pr_err("%pfwP: irq domain already created\n", imsic->fwnode); in imsic_irqdomain_init()
323 return -ENODEV; in imsic_irqdomain_init()
327 info.fwnode = imsic->fwnode, in imsic_irqdomain_init()
328 imsic->base_domain = msi_create_parent_irq_domain(&info, &imsic_msi_parent_ops); in imsic_irqdomain_init()
329 if (!imsic->base_domain) { in imsic_irqdomain_init()
330 pr_err("%pfwP: failed to create IMSIC base domain\n", imsic->fwnode); in imsic_irqdomain_init()
331 return -ENOMEM; in imsic_irqdomain_init()
334 global = &imsic->global; in imsic_irqdomain_init()
335 pr_info("%pfwP: hart-index-bits: %d, guest-index-bits: %d\n", in imsic_irqdomain_init()
336 imsic->fwnode, global->hart_index_bits, global->guest_index_bits); in imsic_irqdomain_init()
337 pr_info("%pfwP: group-index-bits: %d, group-index-shift: %d\n", in imsic_irqdomain_init()
338 imsic->fwnode, global->group_index_bits, global->group_index_shift); in imsic_irqdomain_init()
339 pr_info("%pfwP: per-CPU IDs %d at base address %pa\n", in imsic_irqdomain_init()
340 imsic->fwnode, global->nr_ids, &global->base_addr); in imsic_irqdomain_init()
342 imsic->fwnode, num_possible_cpus() * (global->nr_ids - 1)); in imsic_irqdomain_init()
349 if (imsic && imsic->fwnode != fwnode) { in imsic_platform_probe_common()
351 return -ENODEV; in imsic_platform_probe_common()
359 return imsic_platform_probe_common(pdev->dev.fwnode); in imsic_platform_dt_probe()
365 * On ACPI based systems, PCI enumeration happens early during boot in
367 * it calls pci_set_msi_domain(). Hence, unlike in DT where
368 * imsic-platform drive probe happens late during boot, ACPI based
385 .name = "riscv-imsic",