^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Support of MSI, HPET and DMAR interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Moved from arch/x86/kernel/apic/io_apic.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Jiang Liu <jiang.liu@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Convert to hierarchical irqdomain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/dmar.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/hpet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/msi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/msidef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/hpet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/hw_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/apic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/irq_remapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct irq_domain *x86_pci_msi_default_domain __ro_after_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static void __irq_msi_compose_msg(struct irq_cfg *cfg, struct msi_msg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) msg->address_hi = MSI_ADDR_BASE_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (x2apic_enabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) msg->address_hi |= MSI_ADDR_EXT_DEST_ID(cfg->dest_apicid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) msg->address_lo =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MSI_ADDR_BASE_LO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ((apic->irq_dest_mode == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) MSI_ADDR_DEST_MODE_PHYSICAL :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MSI_ADDR_DEST_MODE_LOGICAL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) MSI_ADDR_REDIRECTION_CPU |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) MSI_ADDR_DEST_ID(cfg->dest_apicid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) msg->data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MSI_DATA_TRIGGER_EDGE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MSI_DATA_LEVEL_ASSERT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MSI_DATA_DELIVERY_FIXED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MSI_DATA_VECTOR(cfg->vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) void x86_vector_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) __irq_msi_compose_msg(irqd_cfg(data), msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void irq_msi_update_msg(struct irq_data *irqd, struct irq_cfg *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct msi_msg msg[2] = { [1] = { }, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) __irq_msi_compose_msg(cfg, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) irq_data_get_irq_chip(irqd)->irq_write_msi_msg(irqd, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) msi_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct irq_cfg old_cfg, *cfg = irqd_cfg(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct irq_data *parent = irqd->parent_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Save the current configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) cpu = cpumask_first(irq_data_get_effective_affinity_mask(irqd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) old_cfg = *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Allocate a new target vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ret = parent->chip->irq_set_affinity(parent, mask, force);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * For non-maskable and non-remapped MSI interrupts the migration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * to a different destination CPU and a different vector has to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * done careful to handle the possible stray interrupt which can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * caused by the non-atomic update of the address/data pair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Direct update is possible when:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * - The MSI is maskable (remapped MSI does not use this code path)).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * The quirk bit is not set in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * - The new vector is the same as the old vector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * - The old vector is MANAGED_IRQ_SHUTDOWN_VECTOR (interrupt starts up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * - The interrupt is not yet started up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * - The new destination CPU is the same as the old destination CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!irqd_msi_nomask_quirk(irqd) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) cfg->vector == old_cfg.vector ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) old_cfg.vector == MANAGED_IRQ_SHUTDOWN_VECTOR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) !irqd_is_started(irqd) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) cfg->dest_apicid == old_cfg.dest_apicid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) irq_msi_update_msg(irqd, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * Paranoia: Validate that the interrupt target is the local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (WARN_ON_ONCE(cpu != smp_processor_id())) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) irq_msi_update_msg(irqd, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * Redirect the interrupt to the new vector on the current CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * first. This might cause a spurious interrupt on this vector if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * the device raises an interrupt right between this update and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * update to the final destination CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * If the vector is in use then the installed device handler will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * denote it as spurious which is no harm as this is a rare event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * and interrupt handlers have to cope with spurious interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * anyway. If the vector is unused, then it is marked so it won't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * trigger the 'No irq handler for vector' warning in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * common_interrupt().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * This requires to hold vector lock to prevent concurrent updates to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * the affected vector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) lock_vector_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * Mark the new target vector on the local CPU if it is currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * unused. Reuse the VECTOR_RETRIGGERED state which is also used in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * the CPU hotplug path for a similar purpose. This cannot be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * undone here as the current CPU has interrupts disabled and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * cannot handle the interrupt before the whole set_affinity()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * section is done. In the CPU unplug case, the current CPU is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * about to vanish and will not handle any interrupts anymore. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * vector is cleaned up when the CPU comes online again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (IS_ERR_OR_NULL(this_cpu_read(vector_irq[cfg->vector])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) this_cpu_write(vector_irq[cfg->vector], VECTOR_RETRIGGERED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* Redirect it to the new vector on the local CPU temporarily */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) old_cfg.vector = cfg->vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) irq_msi_update_msg(irqd, &old_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* Now transition it to the target CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) irq_msi_update_msg(irqd, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * All interrupts after this point are now targeted at the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * vector/CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * Drop vector lock before testing whether the temporary assignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * to the local CPU was hit by an interrupt raised in the device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * because the retrigger function acquires vector lock again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) unlock_vector_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Check whether the transition raced with a device interrupt and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * is pending in the local APICs IRR. It is safe to do this outside
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * of vector lock as the irq_desc::lock of this interrupt is still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * held and interrupts are disabled: The check is not accessing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * underlying vector store. It's just checking the local APIC's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * IRR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (lapic_vector_set_in_irr(cfg->vector))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) irq_data_get_irq_chip(irqd)->irq_retrigger(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * which implement the MSI or MSI-X Capability Structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct irq_chip pci_msi_controller = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .name = "PCI-MSI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .irq_unmask = pci_msi_unmask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .irq_mask = pci_msi_mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .irq_ack = irq_chip_ack_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .irq_retrigger = irq_chip_retrigger_hierarchy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .irq_set_affinity = msi_set_affinity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .flags = IRQCHIP_SKIP_SET_WAKE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) IRQCHIP_AFFINITY_PRE_STARTUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) msi_alloc_info_t *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct pci_dev *pdev = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct msi_desc *desc = first_pci_msi_entry(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) init_irq_alloc_info(arg, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (desc->msi_attrib.is_msix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) arg->flags |= X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) EXPORT_SYMBOL_GPL(pci_msi_prepare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static struct msi_domain_ops pci_msi_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .msi_prepare = pci_msi_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static struct msi_domain_info pci_msi_domain_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) MSI_FLAG_PCI_MSIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .ops = &pci_msi_domain_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .chip = &pci_msi_controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .handler = handle_edge_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .handler_name = "edge",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct irq_domain * __init native_create_pci_msi_domain(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct fwnode_handle *fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct irq_domain *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (disable_apic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) fn = irq_domain_alloc_named_fwnode("PCI-MSI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) d = pci_msi_create_irq_domain(fn, &pci_msi_domain_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) x86_vector_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) irq_domain_free_fwnode(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pr_warn("Failed to initialize PCI-MSI irqdomain.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) d->flags |= IRQ_DOMAIN_MSI_NOMASK_QUIRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) void __init x86_create_pci_msi_domain(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) x86_pci_msi_default_domain = x86_init.irqs.create_pci_msi_domain();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #ifdef CONFIG_IRQ_REMAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static struct irq_chip pci_msi_ir_controller = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .name = "IR-PCI-MSI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .irq_unmask = pci_msi_unmask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .irq_mask = pci_msi_mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .irq_ack = irq_chip_ack_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .irq_retrigger = irq_chip_retrigger_hierarchy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .flags = IRQCHIP_SKIP_SET_WAKE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) IRQCHIP_AFFINITY_PRE_STARTUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static struct msi_domain_info pci_msi_ir_domain_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .ops = &pci_msi_domain_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .chip = &pci_msi_ir_controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .handler = handle_edge_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .handler_name = "edge",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct irq_domain *arch_create_remap_msi_irq_domain(struct irq_domain *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) const char *name, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct fwnode_handle *fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct irq_domain *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) fn = irq_domain_alloc_named_id_fwnode(name, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (!fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) d = pci_msi_create_irq_domain(fn, &pci_msi_ir_domain_info, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (!d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) irq_domain_free_fwnode(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #ifdef CONFIG_DMAR_TABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static void dmar_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dmar_msi_write(data->irq, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static struct irq_chip dmar_msi_controller = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .name = "DMAR-MSI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .irq_unmask = dmar_msi_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .irq_mask = dmar_msi_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .irq_ack = irq_chip_ack_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .irq_set_affinity = msi_domain_set_affinity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .irq_retrigger = irq_chip_retrigger_hierarchy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .irq_write_msi_msg = dmar_msi_write_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .flags = IRQCHIP_SKIP_SET_WAKE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) IRQCHIP_AFFINITY_PRE_STARTUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int dmar_msi_init(struct irq_domain *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct msi_domain_info *info, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) irq_hw_number_t hwirq, msi_alloc_info_t *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) irq_domain_set_info(domain, virq, arg->devid, info->chip, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) handle_edge_irq, arg->data, "edge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static struct msi_domain_ops dmar_msi_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .msi_init = dmar_msi_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static struct msi_domain_info dmar_msi_domain_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) .ops = &dmar_msi_domain_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) .chip = &dmar_msi_controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .flags = MSI_FLAG_USE_DEF_DOM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static struct irq_domain *dmar_get_irq_domain(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static struct irq_domain *dmar_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static DEFINE_MUTEX(dmar_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct fwnode_handle *fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) mutex_lock(&dmar_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (dmar_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) fn = irq_domain_alloc_named_fwnode("DMAR-MSI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (fn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dmar_domain = msi_create_irq_domain(fn, &dmar_msi_domain_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) x86_vector_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (!dmar_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) irq_domain_free_fwnode(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) mutex_unlock(&dmar_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return dmar_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) int dmar_alloc_hwirq(int id, int node, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct irq_domain *domain = dmar_get_irq_domain();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct irq_alloc_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (!domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) init_irq_alloc_info(&info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) info.type = X86_IRQ_ALLOC_TYPE_DMAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) info.devid = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) info.hwirq = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) info.data = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return irq_domain_alloc_irqs(domain, 1, node, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) void dmar_free_hwirq(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) irq_domain_free_irqs(irq, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * MSI message composition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) #ifdef CONFIG_HPET_TIMER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static inline int hpet_dev_id(struct irq_domain *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct msi_domain_info *info = msi_get_domain_info(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return (int)(long)info->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static void hpet_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) hpet_msi_write(irq_data_get_irq_handler_data(data), msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static struct irq_chip hpet_msi_controller __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .name = "HPET-MSI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .irq_unmask = hpet_msi_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .irq_mask = hpet_msi_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) .irq_ack = irq_chip_ack_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .irq_set_affinity = msi_domain_set_affinity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .irq_retrigger = irq_chip_retrigger_hierarchy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .irq_write_msi_msg = hpet_msi_write_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_AFFINITY_PRE_STARTUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int hpet_msi_init(struct irq_domain *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct msi_domain_info *info, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) irq_hw_number_t hwirq, msi_alloc_info_t *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) irq_domain_set_info(domain, virq, arg->hwirq, info->chip, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) handle_edge_irq, arg->data, "edge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static void hpet_msi_free(struct irq_domain *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct msi_domain_info *info, unsigned int virq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static struct msi_domain_ops hpet_msi_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .msi_init = hpet_msi_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .msi_free = hpet_msi_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static struct msi_domain_info hpet_msi_domain_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .ops = &hpet_msi_domain_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) .chip = &hpet_msi_controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .flags = MSI_FLAG_USE_DEF_DOM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct irq_domain *hpet_create_irq_domain(int hpet_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) struct msi_domain_info *domain_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct irq_domain *parent, *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct irq_alloc_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct fwnode_handle *fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (x86_vector_domain == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) domain_info = kzalloc(sizeof(*domain_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!domain_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) *domain_info = hpet_msi_domain_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) domain_info->data = (void *)(long)hpet_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) init_irq_alloc_info(&info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) info.type = X86_IRQ_ALLOC_TYPE_HPET_GET_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) info.devid = hpet_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) parent = irq_remapping_get_irq_domain(&info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (parent == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) parent = x86_vector_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) hpet_msi_controller.name = "IR-HPET-MSI";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) fn = irq_domain_alloc_named_id_fwnode(hpet_msi_controller.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) hpet_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!fn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) kfree(domain_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) d = msi_create_irq_domain(fn, domain_info, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (!d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) irq_domain_free_fwnode(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) kfree(domain_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int hpet_assign_irq(struct irq_domain *domain, struct hpet_channel *hc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int dev_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct irq_alloc_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) init_irq_alloc_info(&info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) info.type = X86_IRQ_ALLOC_TYPE_HPET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) info.data = hc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) info.devid = hpet_dev_id(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) info.hwirq = dev_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) #endif