Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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