1/* 2 * This module supports the iSeries PCI bus interrupt handling 3 * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp> 4 * Copyright (C) 2004-2005 IBM Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the: 18 * Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, 20 * Boston, MA 02111-1307 USA 21 * 22 * Change Activity: 23 * Created, December 13, 2000 by Wayne Holm 24 * End Change Activity 25 */ 26#include <linux/pci.h> 27#include <linux/init.h> 28#include <linux/threads.h> 29#include <linux/smp.h> 30#include <linux/param.h> 31#include <linux/string.h> 32#include <linux/bootmem.h> 33#include <linux/irq.h> 34#include <linux/spinlock.h> 35 36#include <asm/paca.h> 37#include <asm/iseries/hv_types.h> 38#include <asm/iseries/hv_lp_event.h> 39#include <asm/iseries/hv_call_xm.h> 40#include <asm/iseries/it_lp_queue.h> 41 42#include "irq.h" 43#include "pci.h" 44#include "call_pci.h" 45#include "smp.h" 46 47#ifdef CONFIG_PCI 48 49enum pci_event_type { 50 pe_bus_created = 0, /* PHB has been created */ 51 pe_bus_error = 1, /* PHB has failed */ 52 pe_bus_failed = 2, /* Msg to Secondary, Primary failed bus */ 53 pe_node_failed = 4, /* Multi-adapter bridge has failed */ 54 pe_node_recovered = 5, /* Multi-adapter bridge has recovered */ 55 pe_bus_recovered = 12, /* PHB has been recovered */ 56 pe_unquiese_bus = 18, /* Secondary bus unqiescing */ 57 pe_bridge_error = 21, /* Bridge Error */ 58 pe_slot_interrupt = 22 /* Slot interrupt */ 59}; 60 61struct pci_event { 62 struct HvLpEvent event; 63 union { 64 u64 __align; /* Align on an 8-byte boundary */ 65 struct { 66 u32 fisr; 67 HvBusNumber bus_number; 68 HvSubBusNumber sub_bus_number; 69 HvAgentId dev_id; 70 } slot; 71 struct { 72 HvBusNumber bus_number; 73 HvSubBusNumber sub_bus_number; 74 } bus; 75 struct { 76 HvBusNumber bus_number; 77 HvSubBusNumber sub_bus_number; 78 HvAgentId dev_id; 79 } node; 80 } data; 81}; 82 83static DEFINE_SPINLOCK(pending_irqs_lock); 84static int num_pending_irqs; 85static int pending_irqs[NR_IRQS]; 86 87static void int_received(struct pci_event *event) 88{ 89 int irq; 90 91 switch (event->event.xSubtype) { 92 case pe_slot_interrupt: 93 irq = event->event.xCorrelationToken; 94 if (irq < NR_IRQS) { 95 spin_lock(&pending_irqs_lock); 96 pending_irqs[irq]++; 97 num_pending_irqs++; 98 spin_unlock(&pending_irqs_lock); 99 } else { 100 printk(KERN_WARNING "int_received: bad irq number %d\n", 101 irq); 102 HvCallPci_eoi(event->data.slot.bus_number, 103 event->data.slot.sub_bus_number, 104 event->data.slot.dev_id); 105 } 106 break; 107 /* Ignore error recovery events for now */ 108 case pe_bus_created: 109 printk(KERN_INFO "int_received: system bus %d created\n", 110 event->data.bus.bus_number); 111 break; 112 case pe_bus_error: 113 case pe_bus_failed: 114 printk(KERN_INFO "int_received: system bus %d failed\n", 115 event->data.bus.bus_number); 116 break; 117 case pe_bus_recovered: 118 case pe_unquiese_bus: 119 printk(KERN_INFO "int_received: system bus %d recovered\n", 120 event->data.bus.bus_number); 121 break; 122 case pe_node_failed: 123 case pe_bridge_error: 124 printk(KERN_INFO 125 "int_received: multi-adapter bridge %d/%d/%d failed\n", 126 event->data.node.bus_number, 127 event->data.node.sub_bus_number, 128 event->data.node.dev_id); 129 break; 130 case pe_node_recovered: 131 printk(KERN_INFO 132 "int_received: multi-adapter bridge %d/%d/%d recovered\n", 133 event->data.node.bus_number, 134 event->data.node.sub_bus_number, 135 event->data.node.dev_id); 136 break; 137 default: 138 printk(KERN_ERR 139 "int_received: unrecognized event subtype 0x%x\n", 140 event->event.xSubtype); 141 break; 142 } 143} 144 145static void pci_event_handler(struct HvLpEvent *event) 146{ 147 if (event && (event->xType == HvLpEvent_Type_PciIo)) { 148 if (hvlpevent_is_int(event)) 149 int_received((struct pci_event *)event); 150 else 151 printk(KERN_ERR 152 "pci_event_handler: unexpected ack received\n"); 153 } else if (event) 154 printk(KERN_ERR 155 "pci_event_handler: Unrecognized PCI event type 0x%x\n", 156 (int)event->xType); 157 else 158 printk(KERN_ERR "pci_event_handler: NULL event received\n"); 159} 160 161#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff) 162#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) 163#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) 164#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7) 165 166/* 167 * This will be called by device drivers (via enable_IRQ) 168 * to enable INTA in the bridge interrupt status register. 169 */ 170static void iseries_enable_IRQ(unsigned int irq) 171{ 172 u32 bus, dev_id, function, mask; 173 const u32 sub_bus = 0; 174 unsigned int rirq = (unsigned int)irq_map[irq].hwirq; 175 176 /* The IRQ has already been locked by the caller */ 177 bus = REAL_IRQ_TO_BUS(rirq); 178 function = REAL_IRQ_TO_FUNC(rirq); 179 dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; 180 181 /* Unmask secondary INTA */ 182 mask = 0x80000000; 183 HvCallPci_unmaskInterrupts(bus, sub_bus, dev_id, mask); 184} 185 186/* This is called by iseries_activate_IRQs */ 187static unsigned int iseries_startup_IRQ(unsigned int irq) 188{ 189 u32 bus, dev_id, function, mask; 190 const u32 sub_bus = 0; 191 unsigned int rirq = (unsigned int)irq_map[irq].hwirq; 192 193 bus = REAL_IRQ_TO_BUS(rirq); 194 function = REAL_IRQ_TO_FUNC(rirq); 195 dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; 196 197 /* Link the IRQ number to the bridge */ 198 HvCallXm_connectBusUnit(bus, sub_bus, dev_id, irq); 199 200 /* Unmask bridge interrupts in the FISR */ 201 mask = 0x01010000 << function; 202 HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask); 203 iseries_enable_IRQ(irq); 204 return 0; 205} 206 207/* 208 * This is called out of iSeries_fixup to activate interrupt 209 * generation for usable slots 210 */ 211void __init iSeries_activate_IRQs() 212{ 213 int irq; 214 unsigned long flags; 215 216 for_each_irq (irq) { 217 struct irq_desc *desc = irq_to_desc(irq); 218 219 if (desc && desc->chip && desc->chip->startup) { 220 raw_spin_lock_irqsave(&desc->lock, flags); 221 desc->chip->startup(irq); 222 raw_spin_unlock_irqrestore(&desc->lock, flags); 223 } 224 } 225} 226 227/* this is not called anywhere currently */ 228static void iseries_shutdown_IRQ(unsigned int irq) 229{ 230 u32 bus, dev_id, function, mask; 231 const u32 sub_bus = 0; 232 unsigned int rirq = (unsigned int)irq_map[irq].hwirq; 233 234 /* irq should be locked by the caller */ 235 bus = REAL_IRQ_TO_BUS(rirq); 236 function = REAL_IRQ_TO_FUNC(rirq); 237 dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; 238 239 /* Invalidate the IRQ number in the bridge */ 240 HvCallXm_connectBusUnit(bus, sub_bus, dev_id, 0); 241 242 /* Mask bridge interrupts in the FISR */ 243 mask = 0x01010000 << function; 244 HvCallPci_maskFisr(bus, sub_bus, dev_id, mask); 245} 246 247/* 248 * This will be called by device drivers (via disable_IRQ) 249 * to disable INTA in the bridge interrupt status register. 250 */ 251static void iseries_disable_IRQ(unsigned int irq) 252{ 253 u32 bus, dev_id, function, mask; 254 const u32 sub_bus = 0; 255 unsigned int rirq = (unsigned int)irq_map[irq].hwirq; 256 257 /* The IRQ has already been locked by the caller */ 258 bus = REAL_IRQ_TO_BUS(rirq); 259 function = REAL_IRQ_TO_FUNC(rirq); 260 dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; 261 262 /* Mask secondary INTA */ 263 mask = 0x80000000; 264 HvCallPci_maskInterrupts(bus, sub_bus, dev_id, mask); 265} 266 267static void iseries_end_IRQ(unsigned int irq) 268{ 269 unsigned int rirq = (unsigned int)irq_map[irq].hwirq; 270 271 HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq), 272 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq)); 273} 274 275static struct irq_chip iseries_pic = { 276 .name = "iSeries", 277 .startup = iseries_startup_IRQ, 278 .shutdown = iseries_shutdown_IRQ, 279 .unmask = iseries_enable_IRQ, 280 .mask = iseries_disable_IRQ, 281 .eoi = iseries_end_IRQ 282}; 283 284/* 285 * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot 286 * It calculates the irq value for the slot. 287 * Note that sub_bus is always 0 (at the moment at least). 288 */ 289int __init iSeries_allocate_IRQ(HvBusNumber bus, 290 HvSubBusNumber sub_bus, u32 bsubbus) 291{ 292 unsigned int realirq; 293 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); 294 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); 295 296 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) 297 + function; 298 299 return irq_create_mapping(NULL, realirq); 300} 301 302#endif /* CONFIG_PCI */ 303 304/* 305 * Get the next pending IRQ. 306 */ 307unsigned int iSeries_get_irq(void) 308{ 309 int irq = NO_IRQ_IGNORE; 310 311#ifdef CONFIG_SMP 312 if (get_lppaca()->int_dword.fields.ipi_cnt) { 313 get_lppaca()->int_dword.fields.ipi_cnt = 0; 314 iSeries_smp_message_recv(); 315 } 316#endif /* CONFIG_SMP */ 317 if (hvlpevent_is_pending()) 318 process_hvlpevents(); 319 320#ifdef CONFIG_PCI 321 if (num_pending_irqs) { 322 spin_lock(&pending_irqs_lock); 323 for (irq = 0; irq < NR_IRQS; irq++) { 324 if (pending_irqs[irq]) { 325 pending_irqs[irq]--; 326 num_pending_irqs--; 327 break; 328 } 329 } 330 spin_unlock(&pending_irqs_lock); 331 if (irq >= NR_IRQS) 332 irq = NO_IRQ_IGNORE; 333 } 334#endif 335 336 return irq; 337} 338 339#ifdef CONFIG_PCI 340 341static int iseries_irq_host_map(struct irq_host *h, unsigned int virq, 342 irq_hw_number_t hw) 343{ 344 set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq); 345 346 return 0; 347} 348 349static int iseries_irq_host_match(struct irq_host *h, struct device_node *np) 350{ 351 /* Match all */ 352 return 1; 353} 354 355static struct irq_host_ops iseries_irq_host_ops = { 356 .map = iseries_irq_host_map, 357 .match = iseries_irq_host_match, 358}; 359 360/* 361 * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c 362 * It must be called before the bus walk. 363 */ 364void __init iSeries_init_IRQ(void) 365{ 366 /* Register PCI event handler and open an event path */ 367 struct irq_host *host; 368 int ret; 369 370 /* 371 * The Hypervisor only allows us up to 256 interrupt 372 * sources (the irq number is passed in a u8). 373 */ 374 irq_set_virq_count(256); 375 376 /* Create irq host. No need for a revmap since HV will give us 377 * back our virtual irq number 378 */ 379 host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, 380 &iseries_irq_host_ops, 0); 381 BUG_ON(host == NULL); 382 irq_set_default_host(host); 383 384 ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, 385 &pci_event_handler); 386 if (ret == 0) { 387 ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); 388 if (ret != 0) 389 printk(KERN_ERR "iseries_init_IRQ: open event path " 390 "failed with rc 0x%x\n", ret); 391 } else 392 printk(KERN_ERR "iseries_init_IRQ: register handler " 393 "failed with rc 0x%x\n", ret); 394} 395 396#endif /* CONFIG_PCI */ 397