^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * I/O SAPIC support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1999 Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2000-2002 J.I. Lee <jung-ik.lee@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * David Mosberger-Tang <davidm@hpl.hp.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 1999 VA Linux Systems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * APIC code. In particular, we now have separate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * handlers for edge and level triggered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * allocation PCI to vector mapping, shared PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * 00/10/27 D. Mosberger Document things a bit more to make them more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * understandable. Clean up much of the old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * IOSAPIC cruft.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * and fixes for ACPI S5(SoftOff) support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 02/01/23 J.I. Lee iosapic pgm fixes for PCI irq routing from _PRT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * vectors in iosapic_set_affinity(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * initializations for /proc/irq/#/smp_affinity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * IOSAPIC mapping error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * 02/07/29 T. Kochi Allocate interrupt vectors dynamically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * 02/08/04 T. Kochi Cleaned up terminology (irq, global system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * interrupt, vector, etc.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * pci_irq code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Remove iosapic_address & gsi_base from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * external interfaces. Rationalize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * __init/__devinit attributes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * 04/12/04 Ashok Raj <ashok.raj@intel.com> Intel Corporation 2004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Updated to work with irq migration necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * for CPU Hotplug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Here is what the interrupt logic between a PCI device and the kernel looks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * like:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * INTD). The device is uniquely identified by its bus-, and slot-number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * (the function number does not matter here because all functions share
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * the same interrupt lines).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * controller. Multiple interrupt lines may have to share the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * IOSAPIC pin (if they're level triggered and use the same polarity).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Each interrupt line has a unique Global System Interrupt (GSI) number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * which can be calculated as the sum of the controller's base GSI number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * and the IOSAPIC pin number to which the line connects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * IOSAPIC pin into the IA-64 interrupt vector. This interrupt vector is then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * sent to the CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * used as architecture-independent interrupt handling mechanism in Linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * As an IRQ is a number, we have to have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * IA-64 interrupt vector number <-> IRQ number mapping. On smaller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * systems, we use one-to-one mapping between IA-64 vector and IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * To sum up, there are three levels of mappings involved:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * Note: The term "IRQ" is loosely used everywhere in Linux kernel to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * describe interrupts. Now we use "IRQ" only for Linux IRQ's. ISA IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * (isa_irq) is the only exception in this source code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #include <asm/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #include <asm/hw_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #include <asm/iosapic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #include <asm/xtp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #undef DEBUG_INTERRUPT_ROUTING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #ifdef DEBUG_INTERRUPT_ROUTING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define DBG(fmt...) printk(fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define DBG(fmt...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static DEFINE_SPINLOCK(iosapic_lock);
^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) * These tables map IA-64 vectors to the IOSAPIC pin that generates this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * vector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define NO_REF_RTE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct iosapic {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) char __iomem *addr; /* base address of IOSAPIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned int gsi_base; /* GSI base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned short num_rte; /* # of RTEs on this IOSAPIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int rtes_inuse; /* # of RTEs in use on this IOSAPIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #ifdef CONFIG_NUMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned short node; /* numa node association via pxm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) spinlock_t lock; /* lock for indirect reg access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } iosapic_lists[NR_IOSAPICS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct iosapic_rte_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct list_head rte_list; /* RTEs sharing the same vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) char rte_index; /* IOSAPIC RTE index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int refcnt; /* reference counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct iosapic *iosapic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) } ____cacheline_aligned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static struct iosapic_intr_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct list_head rtes; /* RTEs using this vector (empty =>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * not an IOSAPIC interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int count; /* # of registered RTEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) u32 low32; /* current value of low word of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Redirection table entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int dest; /* destination CPU physical ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) unsigned char polarity: 1; /* interrupt polarity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * (see iosapic.h) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) } iosapic_intr_info[NR_IRQS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static unsigned char pcat_compat; /* 8259 compatibility flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) spin_lock_irqsave(&iosapic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) __iosapic_write(iosapic->addr, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) spin_unlock_irqrestore(&iosapic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * Find an IOSAPIC associated with a GSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) find_iosapic (unsigned int gsi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) for (i = 0; i < NR_IOSAPICS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if ((unsigned) (gsi - iosapic_lists[i].gsi_base) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) iosapic_lists[i].num_rte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static inline int __gsi_to_irq(unsigned int gsi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct iosapic_intr_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) for (irq = 0; irq < NR_IRQS; irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) info = &iosapic_intr_info[irq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) list_for_each_entry(rte, &info->rtes, rte_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (rte->iosapic->gsi_base + rte->rte_index == gsi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) gsi_to_irq (unsigned int gsi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) spin_lock_irqsave(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) irq = __gsi_to_irq(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static struct iosapic_rte_info *find_rte(unsigned int irq, unsigned int gsi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (rte->iosapic->gsi_base + rte->rte_index == gsi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) set_rte (unsigned int gsi, unsigned int irq, unsigned int dest, int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) unsigned long pol, trigger, dmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) u32 low32, high32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int rte_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) char redir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ia64_vector vector = irq_to_vector(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) rte = find_rte(irq, gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!rte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return; /* not an IOSAPIC interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) rte_index = rte->rte_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) pol = iosapic_intr_info[irq].polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) trigger = iosapic_intr_info[irq].trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) dmode = iosapic_intr_info[irq].dmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) (trigger << IOSAPIC_TRIGGER_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) (dmode << IOSAPIC_DELIVERY_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ((mask ? 1 : 0) << IOSAPIC_MASK_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* dest contains both id and eid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) high32 = (dest << IOSAPIC_DEST_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) iosapic_intr_info[irq].low32 = low32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) iosapic_intr_info[irq].dest = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) iosapic_nop (struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* do nothing... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #ifdef CONFIG_KEXEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) kexec_disable_iosapic(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct iosapic_intr_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ia64_vector vec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) for (irq = 0; irq < NR_IRQS; irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) info = &iosapic_intr_info[irq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) vec = irq_to_vector(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) list_for_each_entry(rte, &info->rtes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) rte_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) iosapic_write(rte->iosapic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) IOSAPIC_RTE_LOW(rte->rte_index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) IOSAPIC_MASK|vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) iosapic_eoi(rte->iosapic->addr, vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) mask_irq (struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) u32 low32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int rte_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (!iosapic_intr_info[irq].count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return; /* not an IOSAPIC interrupt! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /* set only the mask bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) low32 = iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) rte_index = rte->rte_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unmask_irq (struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u32 low32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int rte_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (!iosapic_intr_info[irq].count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return; /* not an IOSAPIC interrupt! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) low32 = iosapic_intr_info[irq].low32 &= ~IOSAPIC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) rte_index = rte->rte_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) iosapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) bool force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u32 high32, low32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int cpu, dest, rte_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct iosapic *iosapic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) irq &= (~IA64_IRQ_REDIRECTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) cpu = cpumask_first_and(cpu_online_mask, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (cpu >= nr_cpu_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (irq_prepare_move(irq, cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dest = cpu_physical_id(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (!iosapic_intr_info[irq].count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return -1; /* not an IOSAPIC interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) set_irq_affinity_info(irq, dest, redir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* dest contains both id and eid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) high32 = dest << IOSAPIC_DEST_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) low32 = iosapic_intr_info[irq].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (redir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* change delivery mode to lowest priority */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /* change delivery mode to fixed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) low32 &= IOSAPIC_VECTOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) low32 |= irq_to_vector(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) iosapic_intr_info[irq].low32 = low32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) iosapic_intr_info[irq].dest = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) iosapic = rte->iosapic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) rte_index = rte->rte_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * Handlers for level-triggered interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) iosapic_startup_level_irq (struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) unmask_irq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) iosapic_unmask_level_irq (struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) ia64_vector vec = irq_to_vector(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int do_unmask_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) irq_complete_move(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (unlikely(irqd_is_setaffinity_pending(data))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) do_unmask_irq = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) mask_irq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) unmask_irq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) iosapic_eoi(rte->iosapic->addr, vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (unlikely(do_unmask_irq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) irq_move_masked_irq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) unmask_irq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) #define iosapic_shutdown_level_irq mask_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) #define iosapic_enable_level_irq unmask_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) #define iosapic_disable_level_irq mask_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) #define iosapic_ack_level_irq iosapic_nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static struct irq_chip irq_type_iosapic_level = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .name = "IO-SAPIC-level",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .irq_startup = iosapic_startup_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .irq_shutdown = iosapic_shutdown_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .irq_enable = iosapic_enable_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .irq_disable = iosapic_disable_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .irq_ack = iosapic_ack_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .irq_mask = mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .irq_unmask = iosapic_unmask_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .irq_set_affinity = iosapic_set_affinity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * Handlers for edge-triggered interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) iosapic_startup_edge_irq (struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) unmask_irq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * IOSAPIC simply drops interrupts pended while the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * corresponding pin was masked, so we can't know if an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * interrupt is pending already. Let's hope not...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) iosapic_ack_edge_irq (struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) irq_complete_move(data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) irq_move_irq(data);
^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) #define iosapic_enable_edge_irq unmask_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) #define iosapic_disable_edge_irq iosapic_nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static struct irq_chip irq_type_iosapic_edge = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .name = "IO-SAPIC-edge",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) .irq_startup = iosapic_startup_edge_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .irq_shutdown = iosapic_disable_edge_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .irq_enable = iosapic_enable_edge_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .irq_disable = iosapic_disable_edge_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .irq_ack = iosapic_ack_edge_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .irq_mask = mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .irq_unmask = unmask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .irq_set_affinity = iosapic_set_affinity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) iosapic_version (char __iomem *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * IOSAPIC Version Register return 32 bit structure like:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * unsigned int version : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * unsigned int reserved1 : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * unsigned int max_redir : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * unsigned int reserved2 : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return __iosapic_read(addr, IOSAPIC_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static int iosapic_find_sharable_irq(unsigned long trigger, unsigned long pol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int i, irq = -ENOSPC, min_count = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct iosapic_intr_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * shared vectors for edge-triggered interrupts are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * supported yet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (trigger == IOSAPIC_EDGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) for (i = 0; i < NR_IRQS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) info = &iosapic_intr_info[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (info->trigger == trigger && info->polarity == pol &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) (info->dmode == IOSAPIC_FIXED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) info->dmode == IOSAPIC_LOWEST_PRIORITY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) can_request_irq(i, IRQF_SHARED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (min_count == -1 || info->count < min_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) irq = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) min_count = info->count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * if the given vector is already owned by other,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * assign a new vector for the other and make the vector available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) iosapic_reassign_vector (int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int new_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (iosapic_intr_info[irq].count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) new_irq = create_irq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (new_irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) panic("%s: out of interrupt vectors!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) printk(KERN_INFO "Reassigning vector %d to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) irq_to_vector(irq), irq_to_vector(new_irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) memcpy(&iosapic_intr_info[new_irq], &iosapic_intr_info[irq],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) sizeof(struct iosapic_intr_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) INIT_LIST_HEAD(&iosapic_intr_info[new_irq].rtes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) list_move(iosapic_intr_info[irq].rtes.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) &iosapic_intr_info[new_irq].rtes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) memset(&iosapic_intr_info[irq], 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) sizeof(struct iosapic_intr_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static inline int irq_is_shared (int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return (iosapic_intr_info[irq].count > 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct irq_chip*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ia64_native_iosapic_get_irq_chip(unsigned long trigger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (trigger == IOSAPIC_EDGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return &irq_type_iosapic_edge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return &irq_type_iosapic_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) register_intr (unsigned int gsi, int irq, unsigned char delivery,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) unsigned long polarity, unsigned long trigger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct irq_chip *chip, *irq_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) index = find_iosapic(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (index < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) __func__, gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) rte = find_rte(irq, gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (!rte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) rte = kzalloc(sizeof (*rte), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (!rte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) printk(KERN_WARNING "%s: cannot allocate memory\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) rte->iosapic = &iosapic_lists[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) rte->rte_index = gsi - rte->iosapic->gsi_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) rte->refcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) list_add_tail(&rte->rte_list, &iosapic_intr_info[irq].rtes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) iosapic_intr_info[irq].count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) iosapic_lists[index].rtes_inuse++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) else if (rte->refcnt == NO_REF_RTE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct iosapic_intr_info *info = &iosapic_intr_info[irq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (info->count > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) (info->trigger != trigger || info->polarity != polarity)){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) printk (KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) "%s: cannot override the interrupt\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) rte->refcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) iosapic_intr_info[irq].count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) iosapic_lists[index].rtes_inuse++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) iosapic_intr_info[irq].polarity = polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) iosapic_intr_info[irq].dmode = delivery;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) iosapic_intr_info[irq].trigger = trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) irq_type = iosapic_get_irq_chip(trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) chip = irq_get_chip(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (irq_type != NULL && chip != irq_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (chip != &no_irq_chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) "%s: changing vector %d from %s to %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) __func__, irq_to_vector(irq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) chip->name, irq_type->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) chip = irq_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) irq_set_chip_handler_name_locked(irq_get_irq_data(irq), chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) trigger == IOSAPIC_EDGE ? handle_edge_irq : handle_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) get_target_cpu (unsigned int gsi, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static int cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) extern int cpe_vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) cpumask_t domain = irq_to_domain(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * In case of vector shared by multiple RTEs, all RTEs that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * share the vector need to use the same destination CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (iosapic_intr_info[irq].count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return iosapic_intr_info[irq].dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * If the platform supports redirection via XTP, let it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * distribute interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (smp_int_redirect & SMP_IRQ_REDIRECTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return cpu_physical_id(smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * Some interrupts (ACPI SCI, for instance) are registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * before the BSP is marked as online.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!cpu_online(smp_processor_id()))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return cpu_physical_id(smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (cpe_vector > 0 && irq_to_vector(irq) == IA64_CPEP_VECTOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return get_cpei_target_cpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) #ifdef CONFIG_NUMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) const struct cpumask *cpu_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) iosapic_index = find_iosapic(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (iosapic_index < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) iosapic_lists[iosapic_index].node == MAX_NUMNODES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) goto skip_numa_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) cpu_mask = cpumask_of_node(iosapic_lists[iosapic_index].node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) num_cpus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) for_each_cpu_and(numa_cpu, cpu_mask, &domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (cpu_online(numa_cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) num_cpus++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (!num_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) goto skip_numa_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /* Use irq assignment to distribute across cpus in node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) cpu_index = irq % num_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) for_each_cpu_and(numa_cpu, cpu_mask, &domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (cpu_online(numa_cpu) && i++ >= cpu_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (numa_cpu < nr_cpu_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return cpu_physical_id(numa_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) skip_numa_setup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * Otherwise, round-robin interrupt vectors across all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * processors. (It'd be nice if we could be smarter in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * case of NUMA.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (++cpu >= nr_cpu_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) cpu = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) } while (!cpu_online(cpu) || !cpumask_test_cpu(cpu, &domain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return cpu_physical_id(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) #else /* CONFIG_SMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return cpu_physical_id(smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) static inline unsigned char choose_dmode(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (smp_int_redirect & SMP_IRQ_REDIRECTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return IOSAPIC_LOWEST_PRIORITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return IOSAPIC_FIXED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * ACPI can describe IOSAPIC interrupts via static tables and namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * methods. This provides an interface to register those interrupts and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * program the IOSAPIC RTE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) iosapic_register_intr (unsigned int gsi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) unsigned long polarity, unsigned long trigger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) int irq, mask = 1, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) unsigned int dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) u32 low32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) unsigned char dmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct irq_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * If this GSI has already been registered (i.e., it's a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * shared interrupt, or we lost a race to register it),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * don't touch the RTE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) spin_lock_irqsave(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) irq = __gsi_to_irq(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) rte = find_rte(irq, gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if(iosapic_intr_info[irq].count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) assign_irq_vector(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) irq_init_desc(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) } else if (rte->refcnt != NO_REF_RTE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) rte->refcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) goto unlock_iosapic_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) irq = create_irq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* If vector is running out, we try to find a sharable vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) irq = iosapic_find_sharable_irq(trigger, polarity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) goto unlock_iosapic_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) desc = irq_to_desc(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) raw_spin_lock(&desc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) dest = get_target_cpu(gsi, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) dmode = choose_dmode();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) err = register_intr(gsi, irq, dmode, polarity, trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) raw_spin_unlock(&desc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) irq = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) goto unlock_iosapic_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * If the vector is shared and already unmasked for other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * interrupt sources, don't mask it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) low32 = iosapic_intr_info[irq].low32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (irq_is_shared(irq) && !(low32 & IOSAPIC_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) set_rte(gsi, irq, dest, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) cpu_logical_id(dest), dest, irq_to_vector(irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) raw_spin_unlock(&desc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) unlock_iosapic_lock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) iosapic_unregister_intr (unsigned int gsi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) int irq, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) u32 low32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) unsigned long trigger, polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) unsigned int dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct iosapic_rte_info *rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * If the irq associated with the gsi is not found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * iosapic_unregister_intr() is unbalanced. We need to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * this again after getting locks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) irq = gsi_to_irq(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) spin_lock_irqsave(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if ((rte = find_rte(irq, gsi)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (--rte->refcnt > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) rte->refcnt = NO_REF_RTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* Mask the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) iosapic_intr_info[irq].count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) index = find_iosapic(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) iosapic_lists[index].rtes_inuse--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) WARN_ON(iosapic_lists[index].rtes_inuse < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) trigger = iosapic_intr_info[irq].trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) polarity = iosapic_intr_info[irq].polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dest = iosapic_intr_info[irq].dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) cpu_logical_id(dest), dest, irq_to_vector(irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (iosapic_intr_info[irq].count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) /* Clear affinity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) cpumask_setall(irq_get_affinity_mask(irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* Clear the interrupt information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) iosapic_intr_info[irq].dest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) iosapic_intr_info[irq].dmode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) iosapic_intr_info[irq].polarity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) iosapic_intr_info[irq].trigger = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /* Destroy and reserve IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) destroy_and_reserve_irq(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * ACPI calls this when it finds an entry for a platform interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) int iosapic_vector, u16 eid, u16 id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) unsigned long polarity, unsigned long trigger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) unsigned char delivery;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) int irq, vector, mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) unsigned int dest = ((id << 8) | eid) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) switch (int_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) case ACPI_INTERRUPT_PMI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) irq = vector = iosapic_vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) bind_irq_vector(irq, vector, CPU_MASK_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * since PMI vector is alloc'd by FW(ACPI) not by kernel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) * we need to make sure the vector is available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) iosapic_reassign_vector(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) delivery = IOSAPIC_PMI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) case ACPI_INTERRUPT_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) irq = create_irq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) panic("%s: out of interrupt vectors!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) vector = irq_to_vector(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) delivery = IOSAPIC_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) case ACPI_INTERRUPT_CPEI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) irq = vector = IA64_CPE_VECTOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) delivery = IOSAPIC_FIXED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) mask = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) printk(KERN_ERR "%s: invalid int type 0x%x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) register_intr(gsi, irq, delivery, polarity, trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) " vector %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) cpu_logical_id(dest), dest, vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) set_rte(gsi, irq, dest, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) void iosapic_override_isa_irq(unsigned int isa_irq, unsigned int gsi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) unsigned long polarity, unsigned long trigger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) int vector, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) unsigned int dest = cpu_physical_id(smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) unsigned char dmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) irq = vector = isa_irq_to_vector(isa_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) dmode = choose_dmode();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) register_intr(gsi, irq, dmode, polarity, trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) polarity == IOSAPIC_POL_HIGH ? "high" : "low",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) cpu_logical_id(dest), dest, vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) set_rte(gsi, irq, dest, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ia64_native_iosapic_pcat_compat_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (pcat_compat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * Disable the compatibility mode interrupts (8259 style),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * needs IN/OUT support enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) "%s: Disabling PC-AT compatible 8259 interrupts\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) outb(0xff, 0xA1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) outb(0xff, 0x21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) iosapic_system_init (int system_pcat_compat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) for (irq = 0; irq < NR_IRQS; ++irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) /* mark as unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) iosapic_intr_info[irq].count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) pcat_compat = system_pcat_compat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (pcat_compat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) iosapic_pcat_compat_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) iosapic_alloc (void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) for (index = 0; index < NR_IOSAPICS; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (!iosapic_lists[index].addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) printk(KERN_WARNING "%s: failed to allocate iosapic\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) iosapic_free (int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) unsigned int gsi_end, base, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* check gsi range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) gsi_end = gsi_base + ((ver >> 16) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) for (index = 0; index < NR_IOSAPICS; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (!iosapic_lists[index].addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) base = iosapic_lists[index].gsi_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) end = base + iosapic_lists[index].num_rte - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (gsi_end < base || end < gsi_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) continue; /* OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) iosapic_delete_rte(unsigned int irq, unsigned int gsi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct iosapic_rte_info *rte, *temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) list_for_each_entry_safe(rte, temp, &iosapic_intr_info[irq].rtes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) rte_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (rte->iosapic->gsi_base + rte->rte_index == gsi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (rte->refcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) list_del(&rte->rte_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) kfree(rte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int num_rte, err, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) unsigned int isa_irq, ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) char __iomem *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) spin_lock_irqsave(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) index = find_iosapic(gsi_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (index >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) addr = ioremap(phys_addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (addr == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ver = iosapic_version(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) iounmap(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * The MAX_REDIR register holds the highest input pin number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * (starting from 0). We add 1 so that we can use it for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * number of pins (= RTEs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) num_rte = ((ver >> 16) & 0xff) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) index = iosapic_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) iosapic_lists[index].addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) iosapic_lists[index].gsi_base = gsi_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) iosapic_lists[index].num_rte = num_rte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) #ifdef CONFIG_NUMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) iosapic_lists[index].node = MAX_NUMNODES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) spin_lock_init(&iosapic_lists[index].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if ((gsi_base == 0) && pcat_compat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * Map the legacy ISA devices into the IOSAPIC data. Some of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * these may get reprogrammed later on with data from the ACPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * Interrupt Source Override table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) for (isa_irq = 0; isa_irq < 16; ++isa_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) iosapic_override_isa_irq(isa_irq, isa_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) IOSAPIC_POL_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) IOSAPIC_EDGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) int iosapic_remove(unsigned int gsi_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) int i, irq, index, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) spin_lock_irqsave(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) index = find_iosapic(gsi_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (index < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) __func__, gsi_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (iosapic_lists[index].rtes_inuse) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) __func__, gsi_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) for (i = gsi_base; i < gsi_base + iosapic_lists[index].num_rte; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) irq = __gsi_to_irq(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) err = iosapic_delete_rte(irq, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) iounmap(iosapic_lists[index].addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) iosapic_free(index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) #ifdef CONFIG_NUMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) void map_iosapic_to_node(unsigned int gsi_base, int node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) index = find_iosapic(gsi_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (index < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) __func__, gsi_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) iosapic_lists[index].node = node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) #endif