Lines Matching +full:hart +full:- +full:index +full:- +full:bits

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