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-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) ** I/O Sapic Driver - PCI interrupt line support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) **      (c) Copyright 1999 Grant Grundler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) **      (c) Copyright 1999 Hewlett-Packard Company
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) ** The I/O sapic driver manages the Interrupt Redirection Table which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) ** the control logic to convert PCI line based interrupts into a Message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) ** Signaled Interrupt (aka Transaction Based Interrupt, TBI).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) ** Acronyms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) ** --------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) ** HPA  Hard Physical Address (aka MMIO address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) ** IRQ  Interrupt ReQuest. Implies Line based interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) ** IRT	Interrupt Routing Table (provided by PAT firmware)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) ** IRdT Interrupt Redirection Table. IRQ line to TXN ADDR/DATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) **      table which is implemented in I/O SAPIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) ** ISR  Interrupt Service Routine. aka Interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) ** MSI	Message Signaled Interrupt. PCI 2.2 functionality.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) **      aka Transaction Based Interrupt (or TBI).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) ** PA   Precision Architecture. HP's RISC architecture.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) ** RISC Reduced Instruction Set Computer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) ** What's a Message Signalled Interrupt?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) ** -------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) ** MSI is a write transaction which targets a processor and is similar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) ** to a processor write to memory or MMIO. MSIs can be generated by I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) ** devices as well as processors and require *architecture* to work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) ** PA only supports MSI. So I/O subsystems must either natively generate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) ** MSIs (e.g. GSC or HP-PB) or convert line based interrupts into MSIs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) ** (e.g. PCI and EISA).  IA64 supports MSIs via a "local SAPIC" which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) ** acts on behalf of a processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) ** MSI allows any I/O device to interrupt any processor. This makes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) ** load balancing of the interrupt processing possible on an SMP platform.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) ** Interrupts are also ordered WRT to DMA data.  It's possible on I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) ** coherent systems to completely eliminate PIO reads from the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) ** path. The device and driver must be designed and implemented to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) ** guarantee all DMA has been issued (issues about atomicity here)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) ** before the MSI is issued. I/O status can then safely be read from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) ** DMA'd data by the ISR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) ** PA Firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) ** -----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) ** PA-RISC platforms have two fundamentally different types of firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) ** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) ** and BARs similar to a traditional PC BIOS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) ** The newer "PAT" firmware supports PDC calls which return tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) ** PAT firmware only initializes the PCI Console and Boot interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) ** With these tables, the OS can program all other PCI devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) ** One such PAT PDC call returns the "Interrupt Routing Table" (IRT).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) ** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) ** input line.  If the IRT is not available, this driver assumes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) ** INTERRUPT_LINE register has been programmed by firmware. The latter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) ** case also means online addition of PCI cards can NOT be supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) ** even if HW support is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) ** All platforms with PAT firmware to date (Oct 1999) use one Interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) ** Routing Table for the entire platform.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) ** Where's the iosapic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) ** --------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) ** I/O sapic is part of the "Core Electronics Complex". And on HP platforms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) ** it's integrated as part of the PCI bus adapter, "lba".  So no bus walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) ** will discover I/O Sapic. I/O Sapic driver learns about each device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) ** when lba driver advertises the presence of the I/O sapic by calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) ** iosapic_register().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) ** IRQ handling notes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) ** ------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) ** The IO-SAPIC can indicate to the CPU which interrupt was asserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) ** So, unlike the GSC-ASIC and Dino, we allocate one CPU interrupt per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) ** IO-SAPIC interrupt and call the device driver's handler directly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) ** The IO-SAPIC driver hijacks the CPU interrupt handler so it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) ** issue the End Of Interrupt command to the IO-SAPIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) ** Overview of exported iosapic functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) ** --------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) ** (caveat: code isn't finished yet - this is just the plan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) ** iosapic_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) **   o initialize globals (lock, etc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) **   o try to read IRT. Presence of IRT determines if this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) **     a PAT platform or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) ** iosapic_register():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) **   o create iosapic_info instance data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) **   o allocate vector_info array for this iosapic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) **   o initialize vector_info - read corresponding IRdT?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) ** iosapic_xlate_pin: (only called by fixup_irq for PAT platform)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) **   o intr_pin = read cfg (INTERRUPT_PIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) **   o if (device under PCI-PCI bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) **               translate slot/pin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ** iosapic_fixup_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) **   o if PAT platform (IRT present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) **	   intr_pin = iosapic_xlate_pin(isi,pcidev):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) **         intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) **         save IRT entry into vector_info later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) **         write cfg INTERRUPT_LINE (with intr_line)?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) **     else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) **         intr_line = pcidev->irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) **         IRT pointer = NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) **     endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) **   o locate vector_info (needs: isi, intr_line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) **   o allocate processor "irq" and get txn_addr/data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) **   o request_irq(processor_irq,  iosapic_interrupt, vector_info,...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ** iosapic_enable_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) **   o clear any pending IRQ on that line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) **   o enable IRdT - call enable_irq(vector[line]->processor_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) **   o write EOI in case line is already asserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ** iosapic_disable_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) **   o disable IRdT - call disable_irq(vector[line]->processor_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #include <asm/pdc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #include <asm/pdcpat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #ifdef CONFIG_SUPERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #include <asm/superio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #include <asm/ropes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #include "iosapic_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define MODULE_NAME "iosapic"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* "local" compile flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #undef PCI_BRIDGE_FUNCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #undef DEBUG_IOSAPIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #undef DEBUG_IOSAPIC_IRT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #ifdef DEBUG_IOSAPIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define DBG(x...) printk(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #else /* DEBUG_IOSAPIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define DBG(x...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #endif /* DEBUG_IOSAPIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #ifdef DEBUG_IOSAPIC_IRT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define DBG_IRT(x...) printk(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define DBG_IRT(x...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define COMPARE_IRTE_ADDR(irte, hpa)	((irte)->dest_iosapic_addr == (hpa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define COMPARE_IRTE_ADDR(irte, hpa)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		((irte)->dest_iosapic_addr == ((hpa) | 0xffffffff00000000ULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define IOSAPIC_REG_SELECT              0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define IOSAPIC_REG_WINDOW              0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define IOSAPIC_REG_EOI                 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define IOSAPIC_REG_VERSION		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define IOSAPIC_IRDT_ENTRY(idx)		(0x10+(idx)*2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define IOSAPIC_IRDT_ENTRY_HI(idx)	(0x11+(idx)*2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static inline unsigned int iosapic_read(void __iomem *iosapic, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	return readl(iosapic + IOSAPIC_REG_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	writel(val, iosapic + IOSAPIC_REG_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define IOSAPIC_VERSION_MASK	0x000000ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define	IOSAPIC_VERSION(ver)	((int) (ver & IOSAPIC_VERSION_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define IOSAPIC_MAX_ENTRY_MASK          0x00ff0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define IOSAPIC_MAX_ENTRY_SHIFT         0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define	IOSAPIC_IRDT_MAX_ENTRY(ver)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	(int) (((ver) & IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* bits in the "low" I/O Sapic IRdT entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define IOSAPIC_IRDT_ENABLE       0x10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define IOSAPIC_IRDT_PO_LOW       0x02000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define IOSAPIC_IRDT_LEVEL_TRIG   0x08000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define IOSAPIC_IRDT_MODE_LPRI    0x00100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* bits in the "high" I/O Sapic IRdT entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #define IOSAPIC_IRDT_ID_EID_SHIFT              0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static DEFINE_SPINLOCK(iosapic_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	__raw_writel(data, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ** REVISIT: future platforms may have more than one IRT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ** If so, the following three fields form a structure which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ** then be linked into a list. Names are chosen to make searching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ** for them easy - not necessarily accurate (eg "cell").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ** Alternative: iosapic_info could point to the IRT it's in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ** iosapic_register() could search a list of IRT's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static struct irt_entry *irt_cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static size_t irt_num_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static struct irt_entry *iosapic_alloc_irt(int num_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	unsigned long a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	/* The IRT needs to be 8-byte aligned for the PDC call. 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	 * Normally kmalloc would guarantee larger alignment, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	 * if CONFIG_DEBUG_SLAB is enabled, then we can get only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	 * 4-byte alignment on 32-bit kernels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	a = (a + 7UL) & ~7UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	return (struct irt_entry *)a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  * iosapic_load_irt - Fill in the interrupt routing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  * @cell_num: The cell number of the CPU we're currently executing on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  * @irt: The address to place the new IRT at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  * @return The number of entries found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  * The "Get PCI INT Routing Table Size" option returns the number of 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  * entries in the PCI interrupt routing table for the cell specified 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  * in the cell_number argument.  The cell number must be for a cell 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)  * within the caller's protection domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)  * The "Get PCI INT Routing Table" option returns, for the cell 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)  * specified in the cell_number argument, the PCI interrupt routing 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)  * table in the caller allocated memory pointed to by mem_addr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)  * We assume the IRT only contains entries for I/O SAPIC and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  * calculate the size based on the size of I/O sapic entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)  * The PCI interrupt routing table entry format is derived from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  * IA64 SAL Specification 2.4.   The PCI interrupt routing table defines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  * the routing of PCI interrupt signals between the PCI device output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  * "pins" and the IO SAPICs' input "lines" (including core I/O PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  * devices).  This table does NOT include information for devices/slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  * behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)  * for the architected method of routing of IRQ's behind PPB's.
^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) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	long status;              /* PDC return value status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	struct irt_entry *table;  /* start of interrupt routing tbl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	unsigned long num_entries = 0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	BUG_ON(!irt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	if (is_pdc_pat()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		/* Use pat pdc routine to get interrupt routing table size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		DBG("calling get_irt_size (cell %ld)\n", cell_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		status = pdc_pat_get_irt_size(&num_entries, cell_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		DBG("get_irt_size: %ld\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		BUG_ON(status != PDC_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		BUG_ON(num_entries == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		** allocate memory for interrupt routing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		** This interface isn't really right. We are assuming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		** the contents of the table are exclusively
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		** for I/O sapic devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		table = iosapic_alloc_irt(num_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		if (table == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 			printk(KERN_WARNING MODULE_NAME ": read_irt : can "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 					"not alloc mem for IRT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		/* get PCI INT routing table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		status = pdc_pat_get_irt(table, cell_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		DBG("pdc_pat_get_irt: %ld\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		WARN_ON(status != PDC_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		** C3000/J5000 (and similar) platforms with Sprockets PDC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		** will return exactly one IRT for all iosapics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		** So if we have one, don't need to get it again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		if (irt_cell)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		/* Should be using the Elroy's HPA, but it's ignored anyway */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		status = pdc_pci_irt_size(&num_entries, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		DBG("pdc_pci_irt_size: %ld\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		if (status != PDC_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			/* Not a "legacy" system with I/O SAPIC either */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		BUG_ON(num_entries == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		table = iosapic_alloc_irt(num_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		if (!table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			printk(KERN_WARNING MODULE_NAME ": read_irt : can "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 					"not alloc mem for IRT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		/* HPA ignored by this call too. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		status = pdc_pci_irt(num_entries, 0, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		BUG_ON(status != PDC_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	/* return interrupt table address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	*irt = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) #ifdef DEBUG_IOSAPIC_IRT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	struct irt_entry *p = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		num_entries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		(int) sizeof(struct irt_entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	for (i = 0 ; i < num_entries ; i++, p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		p->entry_type, p->entry_length, p->interrupt_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		p->src_seg_id, p->dest_iosapic_intin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		((u32 *) p)[2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		((u32 *) p)[3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) #endif /* DEBUG_IOSAPIC_IRT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	return num_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) void __init iosapic_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	unsigned long cell = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	DBG("iosapic_init()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) #ifdef __LP64__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	if (is_pdc_pat()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		struct pdc_pat_cell_num cell_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		status = pdc_pat_cell_get_number(&cell_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		if (status == PDC_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			cell = cell_info.cell_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	/* get interrupt routing table for this cell */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	irt_num_entry = iosapic_load_irt(cell, &irt_cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	if (irt_num_entry == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		irt_cell = NULL;	/* old PDC w/o iosapic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) ** Return the IRT entry in case we need to look something else up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static struct irt_entry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	struct irt_entry *i = irt_cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	int cnt;	/* track how many entries we've looked at */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	for (cnt=0; cnt < irt_num_entry; cnt++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		** Validate: entry_type, entry_length, interrupt_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		** Difference between validate vs compare is the former
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		** should print debug info and is not expected to "fail"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		** on current platforms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		if (i->entry_type != IRT_IOSAPIC_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 			DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 			continue;
^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) 		if (i->entry_length != IRT_IOSAPIC_LENGTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d  length %d\n", i, cnt, i->entry_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		if (i->interrupt_type != IRT_VECTORED_INTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 			DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry  %d interrupt_type %d\n", i, cnt, i->interrupt_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		if (!COMPARE_IRTE_ADDR(i, isi->isi_hpa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		** Ignore: src_bus_id and rc_seg_id correlate with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		**         iosapic_info->isi_hpa on HP platforms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		**         If needed, pass in "PFA" (aka config space addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		**         instead of slot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		/* Found it! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	printk(KERN_WARNING MODULE_NAME ": 0x%lx : no IRT entry for slot %d, pin %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 			isi->isi_hpa, slot, intr_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^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) ** xlate_pin() supports the skewing of IRQ lines done by subsidiary bridges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ** Legacy PDC already does this translation for us and stores it in INTR_LINE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ** PAT PDC needs to basically do what legacy PDC does:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ** o read PIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ** o adjust PIN in case device is "behind" a PPB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) **     (eg 4-port 100BT and SCSI/LAN "Combo Card")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ** o convert slot/pin to I/O SAPIC input line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ** HP platforms only support:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ** o one level of skewing for any number of PPBs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) ** o only support PCI-PCI Bridges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static struct irt_entry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	u8 intr_pin, intr_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	DBG_IRT("iosapic_xlate_pin(%s) SLOT %d pin %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		pcidev->slot_name, PCI_SLOT(pcidev->devfn), intr_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	if (intr_pin == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		/* The device does NOT support/use IRQ lines.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	/* Check if pcidev behind a PPB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	if (pcidev->bus->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		/* Convert pcidev INTR_PIN into something we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		** can lookup in the IRT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) #ifdef PCI_BRIDGE_FUNCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		** Proposal #1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		** call implementation specific translation function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		** This is architecturally "cleaner". HP-UX doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		** support other secondary bus types (eg. E/ISA) directly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		** May be needed for other processor (eg IA64) architectures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		** or by some ambitous soul who wants to watch TV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		if (pci_bridge_funcs->xlate_intr_line) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 			intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) #else	/* PCI_BRIDGE_FUNCS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		struct pci_bus *p = pcidev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		** Proposal #2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		** The "pin" is skewed ((pin + dev - 1) % 4).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		** This isn't very clean since I/O SAPIC must assume:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		**   - all platforms only have PCI busses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		**   - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		**   - IRQ routing is only skewed once regardless of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		**     the number of PPB's between iosapic and device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		**     (Bit3 expansion chassis follows this rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		** Advantage is it's really easy to implement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		intr_pin = pci_swizzle_interrupt_pin(pcidev, intr_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) #endif /* PCI_BRIDGE_FUNCS */
^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) 		 * Locate the host slot of the PPB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		while (p->parent->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 			p = p->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		intr_slot = PCI_SLOT(p->self->devfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		intr_slot = PCI_SLOT(pcidev->devfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	DBG_IRT("iosapic_xlate_pin:  bus %d slot %d pin %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 			pcidev->bus->busn_res.start, intr_slot, intr_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	return irt_find_irqline(isi, intr_slot, intr_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static void iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	struct iosapic_info *isp = vi->iosapic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	u8 idx = vi->irqline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	*dp0 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY(idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	*dp1 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY_HI(idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^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) static void iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	struct iosapic_info *isp = vi->iosapic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %lx 0x%x 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		vi->irqline, isp->isi_hpa, dp0, dp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY(vi->irqline), dp0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	/* Read the window register to flush the writes down to HW  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	dp0 = readl(isp->addr+IOSAPIC_REG_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY_HI(vi->irqline), dp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	/* Read the window register to flush the writes down to HW  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	dp1 = readl(isp->addr+IOSAPIC_REG_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ** set_irt prepares the data (dp0, dp1) according to the vector_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) ** and target cpu (id_eid).  dp0/dp1 are then used to program I/O SAPIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) ** IRdT for the given "vector" (aka IRQ line).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	u32 mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	struct irt_entry *p = vi->irte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		mode |= IOSAPIC_IRDT_PO_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		mode |= IOSAPIC_IRDT_LEVEL_TRIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	** IA64 REVISIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	** PA doesn't support EXTINT or LPRIO bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	*dp0 = mode | (u32) vi->txn_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	** Extracting id_eid isn't a real clean way of getting it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	** But the encoding is the same for both PA and IA64 platforms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	if (is_pdc_pat()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		** PAT PDC just hands it to us "right".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 		** txn_addr comes from cpu_data[x].txn_addr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		*dp1 = (u32) (vi->txn_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		/* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		** eg if base_addr == 0xfffa0000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		**    we want to get 0xa0ff0000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		** eid	0x0ff00000 -> 0x00ff0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 		** id	0x000ff000 -> 0xff000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		*dp1 = (((u32)vi->txn_addr & 0x0ff00000) >> 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 			(((u32)vi->txn_addr & 0x000ff000) << 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static void iosapic_mask_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	struct vector_info *vi = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	u32 d0, d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	spin_lock_irqsave(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	iosapic_rd_irt_entry(vi, &d0, &d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	d0 |= IOSAPIC_IRDT_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	iosapic_wr_irt_entry(vi, d0, d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static void iosapic_unmask_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	struct vector_info *vi = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	u32 d0, d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	/* data is initialized by fixup_irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	WARN_ON(vi->txn_irq  == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	iosapic_set_irt_data(vi, &d0, &d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	iosapic_wr_irt_entry(vi, d0, d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) #ifdef DEBUG_IOSAPIC_IRT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	printk("iosapic_enable_irq(): regs %p", vi->eoi_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	for ( ; t < vi->eoi_addr; t++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		printk(" %x", readl(t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) printk("iosapic_enable_irq(): sel ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	struct iosapic_info *isp = vi->iosapic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	for (d0=0x10; d0<0x1e; d0++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 		d1 = iosapic_read(isp->addr, d0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		printk(" %x", d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	 * Issuing I/O SAPIC an EOI causes an interrupt IFF IRQ line is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	 * asserted.  IRQ generally should not be asserted when a driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	 * enables their IRQ. It can lead to "interesting" race conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	 * in the driver initialization sequence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 			vi->eoi_addr, vi->eoi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	iosapic_eoi(vi->eoi_addr, vi->eoi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static void iosapic_eoi_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	struct vector_info *vi = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	iosapic_eoi(vi->eoi_addr, vi->eoi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	cpu_eoi_irq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static int iosapic_set_affinity_irq(struct irq_data *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 				    const struct cpumask *dest, bool force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	struct vector_info *vi = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	u32 d0, d1, dummy_d0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	int dest_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	dest_cpu = cpu_check_affinity(d, dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	if (dest_cpu < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	cpumask_copy(irq_data_get_affinity_mask(d), cpumask_of(dest_cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	spin_lock_irqsave(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	/* d1 contains the destination CPU, so only want to set that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	 * entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	iosapic_rd_irt_entry(vi, &d0, &d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	iosapic_set_irt_data(vi, &dummy_d0, &d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	iosapic_wr_irt_entry(vi, d0, d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	spin_unlock_irqrestore(&iosapic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static struct irq_chip iosapic_interrupt_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	.name		=	"IO-SAPIC-level",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	.irq_unmask	=	iosapic_unmask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	.irq_mask	=	iosapic_mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	.irq_ack	=	cpu_ack_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	.irq_eoi	=	iosapic_eoi_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	.irq_set_affinity =	iosapic_set_affinity_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) #endif
^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) int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	struct iosapic_info *isi = isi_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	struct irt_entry *irte = NULL;  /* only used if PAT PDC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	struct vector_info *vi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	int isi_line;	/* line used by device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	if (!isi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 		printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 			pci_name(pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) #ifdef CONFIG_SUPERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	 * HACK ALERT! (non-compliant PCI device support)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	 * All SuckyIO interrupts are routed through the PIC's on function 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	 * But SuckyIO OHCI USB controller gets an IRT entry anyway because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	 * it advertises INT D for INT_PIN.  Use that IRT entry to get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	 * SuckyIO interrupt routing for PICs on function 1 (*BLEECCHH*).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	if (is_superio_device(pcidev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		/* We must call superio_fixup_irq() to register the pdev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 		pcidev->irq = superio_fixup_irq(pcidev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 		/* Don't return if need to program the IOSAPIC's IRT... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 		if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 			return pcidev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) #endif /* CONFIG_SUPERIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	/* lookup IRT entry for isi/slot/pin set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	irte = iosapic_xlate_pin(isi, pcidev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	if (!irte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 		printk("iosapic: no IRTE for %s (IRQ not connected?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 				pci_name(pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 		irte,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 		irte->entry_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 		irte->entry_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 		irte->polarity_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		irte->src_bus_irq_devno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 		irte->src_bus_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 		irte->src_seg_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 		irte->dest_iosapic_intin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 		(u32) irte->dest_iosapic_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	isi_line = irte->dest_iosapic_intin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	/* get vector info for this input line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 	vi = isi->isi_vector + isi_line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	DBG_IRT("iosapic_fixup_irq:  line %d vi 0x%p\n", isi_line, vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	/* If this IRQ line has already been setup, skip it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	if (vi->irte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	vi->irte = irte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 	 * Allocate processor IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	 * XXX/FIXME The txn_alloc_irq() code and related code should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	 * moved to enable_irq(). That way we only allocate processor IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	 * bits for devices that actually have drivers claiming them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	 * Right now we assign an IRQ to every PCI device present,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	 * regardless of whether it's used or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 	vi->txn_irq = txn_alloc_irq(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 	if (vi->txn_irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 		panic("I/O sapic: couldn't get TXN IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 	/* enable_irq() will use txn_* to program IRdT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	vi->txn_addr = txn_alloc_addr(vi->txn_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 	vi->txn_data = txn_alloc_data(vi->txn_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	vi->eoi_data = cpu_to_le32(vi->txn_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 	cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 	pcidev->irq = vi->txn_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 		PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 		pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	return pcidev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static struct iosapic_info *iosapic_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int iosapic_serial_irq(struct parisc_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	struct iosapic_info *isi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	struct irt_entry *irte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	struct vector_info *vi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 	int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 	int intin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 	intin = (dev->mod_info >> 24) & 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 	/* lookup IRT entry for isi/slot/pin set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	for (cnt = 0; cnt < irt_num_entry; cnt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 		irte = &irt_cell[cnt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 		if (COMPARE_IRTE_ADDR(irte, dev->mod0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 		    irte->dest_iosapic_intin == intin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	if (cnt >= irt_num_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 		return 0; /* no irq found, force polling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	DBG_IRT("iosapic_serial_irq(): irte %p %x %x %x %x %x %x %x %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 		irte,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 		irte->entry_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 		irte->entry_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 		irte->polarity_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 		irte->src_bus_irq_devno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 		irte->src_bus_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 		irte->src_seg_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 		irte->dest_iosapic_intin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 		(u32) irte->dest_iosapic_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	/* search for iosapic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	for (isi = iosapic_list; isi; isi = isi->isi_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 		if (isi->isi_hpa == dev->mod0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 	if (!isi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 		return 0; /* no iosapic found, force polling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	/* get vector info for this input line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 	vi = isi->isi_vector + intin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 	DBG_IRT("iosapic_serial_irq:  line %d vi 0x%p\n", iosapic_intin, vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	/* If this IRQ line has already been setup, skip it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 	if (vi->irte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	vi->irte = irte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 	 * Allocate processor IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 	 * XXX/FIXME The txn_alloc_irq() code and related code should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	 * moved to enable_irq(). That way we only allocate processor IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 	 * bits for devices that actually have drivers claiming them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 	 * Right now we assign an IRQ to every PCI device present,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 	 * regardless of whether it's used or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 	vi->txn_irq = txn_alloc_irq(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 	if (vi->txn_irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 		panic("I/O sapic: couldn't get TXN IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 	/* enable_irq() will use txn_* to program IRdT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 	vi->txn_addr = txn_alloc_addr(vi->txn_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 	vi->txn_data = txn_alloc_data(vi->txn_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 	vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	vi->eoi_data = cpu_to_le32(vi->txn_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 	cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	return vi->txn_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) ** squirrel away the I/O Sapic Version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) iosapic_rd_version(struct iosapic_info *isi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 	return iosapic_read(isi->addr, IOSAPIC_REG_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ** iosapic_register() is called by "drivers" with an integrated I/O SAPIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) ** Caller must be certain they have an I/O SAPIC and know its MMIO address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) **	o allocate iosapic_info and add it to the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) **	o read iosapic version and squirrel that away
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) **	o read size of IRdT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) **	o allocate and initialize isi_vector[]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) **	o allocate irq region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) void *iosapic_register(unsigned long hpa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 	struct iosapic_info *isi = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 	struct irt_entry *irte = irt_cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 	struct vector_info *vip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 	int cnt;	/* track how many entries we've looked at */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 	 * Astro based platforms can only support PCI OLARD if they implement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 	 * PAT PDC.  Legacy PDC omits LBAs with no PCI devices from the IRT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 	 * Search the IRT and ignore iosapic's which aren't in the IRT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 	for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 		WARN_ON(IRT_IOSAPIC_TYPE != irte->entry_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 		if (COMPARE_IRTE_ADDR(irte, hpa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 	if (cnt >= irt_num_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 		DBG("iosapic_register() ignoring 0x%lx (NOT FOUND)\n", hpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 	isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 	if (!isi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 		BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 	isi->addr = ioremap(hpa, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 	isi->isi_hpa = hpa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 	isi->isi_version = iosapic_rd_version(isi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 	isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 	vip = isi->isi_vector = kcalloc(isi->isi_num_vectors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) 					sizeof(struct vector_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 	if (vip == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 		kfree(isi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 	for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) 		vip->irqline = (unsigned char) cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) 		vip->iosapic = isi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 	isi->isi_next = iosapic_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) 	iosapic_list = isi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) 	return isi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) #ifdef DEBUG_IOSAPIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) iosapic_prt_irt(void *irt, long num_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) 	unsigned int i, *irp = (unsigned int *) irt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) 	printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) 	for (i=0; i<num_entry; i++, irp += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) 		printk(KERN_DEBUG "%p : %2d %.8x %.8x %.8x %.8x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) 					irp, i, irp[0], irp[1], irp[2], irp[3]);
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) iosapic_prt_vi(struct vector_info *vi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) 	printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) 	printk(KERN_DEBUG "\t\tstatus:	 %.4x\n", vi->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) 	printk(KERN_DEBUG "\t\ttxn_irq:  %d\n",  vi->txn_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) 	printk(KERN_DEBUG "\t\ttxn_addr: %lx\n", vi->txn_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) 	printk(KERN_DEBUG "\t\ttxn_data: %lx\n", vi->txn_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) 	printk(KERN_DEBUG "\t\teoi_addr: %p\n",  vi->eoi_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) 	printk(KERN_DEBUG "\t\teoi_data: %x\n",  vi->eoi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) iosapic_prt_isi(struct iosapic_info *isi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) 	printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) 	printk(KERN_DEBUG "\t\tisi_hpa:       %lx\n", isi->isi_hpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) 	printk(KERN_DEBUG "\t\tisi_status:    %x\n", isi->isi_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) 	printk(KERN_DEBUG "\t\tisi_version:   %x\n", isi->isi_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) 	printk(KERN_DEBUG "\t\tisi_vector:    %p\n", isi->isi_vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) #endif /* DEBUG_IOSAPIC */