iosapic.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. /*
  2. * I/O SAPIC support.
  3. *
  4. * Copyright (C) 1999 Intel Corp.
  5. * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
  6. * Copyright (C) 2000-2002 J.I. Lee <jung-ik.lee@intel.com>
  7. * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co.
  8. * David Mosberger-Tang <davidm@hpl.hp.com>
  9. * Copyright (C) 1999 VA Linux Systems
  10. * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
  11. *
  12. * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code.
  13. * In particular, we now have separate handlers for edge
  14. * and level triggered interrupts.
  15. * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector allocation
  16. * PCI to vector mapping, shared PCI interrupts.
  17. * 00/10/27 D. Mosberger Document things a bit more to make them more understandable.
  18. * Clean up much of the old IOSAPIC cruft.
  19. * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts and fixes for
  20. * ACPI S5(SoftOff) support.
  21. * 02/01/23 J.I. Lee iosapic pgm fixes for PCI irq routing from _PRT
  22. * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt vectors in
  23. * iosapic_set_affinity(), initializations for
  24. * /proc/irq/#/smp_affinity
  25. * 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing.
  26. * 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq
  27. * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping
  28. * error
  29. * 02/07/29 T. Kochi Allocate interrupt vectors dynamically
  30. * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.)
  31. * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's pci_irq code.
  32. * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC.
  33. * Remove iosapic_address & gsi_base from external interfaces.
  34. * Rationalize __init/__devinit attributes.
  35. * 04/12/04 Ashok Raj <ashok.raj@intel.com> Intel Corporation 2004
  36. * Updated to work with irq migration necessary for CPU Hotplug
  37. */
  38. /*
  39. * Here is what the interrupt logic between a PCI device and the kernel looks like:
  40. *
  41. * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The
  42. * device is uniquely identified by its bus--, and slot-number (the function
  43. * number does not matter here because all functions share the same interrupt
  44. * lines).
  45. *
  46. * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller.
  47. * Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level
  48. * triggered and use the same polarity). Each interrupt line has a unique Global
  49. * System Interrupt (GSI) number which can be calculated as the sum of the controller's
  50. * base GSI number and the IOSAPIC pin number to which the line connects.
  51. *
  52. * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the IOSAPIC pin
  53. * into the IA-64 interrupt vector. This interrupt vector is then sent to the CPU.
  54. *
  55. * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is used as
  56. * architecture-independent interrupt handling mechanism in Linux. As an
  57. * IRQ is a number, we have to have IA-64 interrupt vector number <-> IRQ number
  58. * mapping. On smaller systems, we use one-to-one mapping between IA-64 vector and
  59. * IRQ. A platform can implement platform_irq_to_vector(irq) and
  60. * platform_local_vector_to_irq(vector) APIs to differentiate the mapping.
  61. * Please see also include/asm-ia64/hw_irq.h for those APIs.
  62. *
  63. * To sum up, there are three levels of mappings involved:
  64. *
  65. * PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
  66. *
  67. * Note: The term "IRQ" is loosely used everywhere in Linux kernel to describe interrupts.
  68. * Now we use "IRQ" only for Linux IRQ's. ISA IRQ (isa_irq) is the only exception in this
  69. * source code.
  70. */
  71. #include <linux/config.h>
  72. #include <linux/acpi.h>
  73. #include <linux/init.h>
  74. #include <linux/irq.h>
  75. #include <linux/kernel.h>
  76. #include <linux/list.h>
  77. #include <linux/pci.h>
  78. #include <linux/smp.h>
  79. #include <linux/smp_lock.h>
  80. #include <linux/string.h>
  81. #include <asm/delay.h>
  82. #include <asm/hw_irq.h>
  83. #include <asm/io.h>
  84. #include <asm/iosapic.h>
  85. #include <asm/machvec.h>
  86. #include <asm/processor.h>
  87. #include <asm/ptrace.h>
  88. #include <asm/system.h>
  89. #undef DEBUG_INTERRUPT_ROUTING
  90. #ifdef DEBUG_INTERRUPT_ROUTING
  91. #define DBG(fmt...) printk(fmt)
  92. #else
  93. #define DBG(fmt...)
  94. #endif
  95. static DEFINE_SPINLOCK(iosapic_lock);
  96. /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
  97. static struct iosapic_intr_info {
  98. char __iomem *addr; /* base address of IOSAPIC */
  99. u32 low32; /* current value of low word of Redirection table entry */
  100. unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
  101. char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */
  102. unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
  103. unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */
  104. unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
  105. int refcnt; /* reference counter */
  106. } iosapic_intr_info[IA64_NUM_VECTORS];
  107. static struct iosapic {
  108. char __iomem *addr; /* base address of IOSAPIC */
  109. unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
  110. unsigned short num_rte; /* number of RTE in this IOSAPIC */
  111. #ifdef CONFIG_NUMA
  112. unsigned short node; /* numa node association via pxm */
  113. #endif
  114. } iosapic_lists[NR_IOSAPICS];
  115. static int num_iosapic;
  116. static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */
  117. /*
  118. * Find an IOSAPIC associated with a GSI
  119. */
  120. static inline int
  121. find_iosapic (unsigned int gsi)
  122. {
  123. int i;
  124. for (i = 0; i < num_iosapic; i++) {
  125. if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)
  126. return i;
  127. }
  128. return -1;
  129. }
  130. static inline int
  131. _gsi_to_vector (unsigned int gsi)
  132. {
  133. struct iosapic_intr_info *info;
  134. for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info)
  135. if (info->gsi_base + info->rte_index == gsi)
  136. return info - iosapic_intr_info;
  137. return -1;
  138. }
  139. /*
  140. * Translate GSI number to the corresponding IA-64 interrupt vector. If no
  141. * entry exists, return -1.
  142. */
  143. inline int
  144. gsi_to_vector (unsigned int gsi)
  145. {
  146. return _gsi_to_vector(gsi);
  147. }
  148. int
  149. gsi_to_irq (unsigned int gsi)
  150. {
  151. /*
  152. * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq
  153. * numbers...
  154. */
  155. return _gsi_to_vector(gsi);
  156. }
  157. static void
  158. set_rte (unsigned int vector, unsigned int dest, int mask)
  159. {
  160. unsigned long pol, trigger, dmode;
  161. u32 low32, high32;
  162. char __iomem *addr;
  163. int rte_index;
  164. char redir;
  165. DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
  166. rte_index = iosapic_intr_info[vector].rte_index;
  167. if (rte_index < 0)
  168. return; /* not an IOSAPIC interrupt */
  169. addr = iosapic_intr_info[vector].addr;
  170. pol = iosapic_intr_info[vector].polarity;
  171. trigger = iosapic_intr_info[vector].trigger;
  172. dmode = iosapic_intr_info[vector].dmode;
  173. vector &= (~IA64_IRQ_REDIRECTED);
  174. redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
  175. #ifdef CONFIG_SMP
  176. {
  177. unsigned int irq;
  178. for (irq = 0; irq < NR_IRQS; ++irq)
  179. if (irq_to_vector(irq) == vector) {
  180. set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
  181. break;
  182. }
  183. }
  184. #endif
  185. low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
  186. (trigger << IOSAPIC_TRIGGER_SHIFT) |
  187. (dmode << IOSAPIC_DELIVERY_SHIFT) |
  188. ((mask ? 1 : 0) << IOSAPIC_MASK_SHIFT) |
  189. vector);
  190. /* dest contains both id and eid */
  191. high32 = (dest << IOSAPIC_DEST_SHIFT);
  192. iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
  193. iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
  194. iosapic_intr_info[vector].low32 = low32;
  195. }
  196. static void
  197. nop (unsigned int vector)
  198. {
  199. /* do nothing... */
  200. }
  201. static void
  202. mask_irq (unsigned int irq)
  203. {
  204. unsigned long flags;
  205. char __iomem *addr;
  206. u32 low32;
  207. int rte_index;
  208. ia64_vector vec = irq_to_vector(irq);
  209. addr = iosapic_intr_info[vec].addr;
  210. rte_index = iosapic_intr_info[vec].rte_index;
  211. if (rte_index < 0)
  212. return; /* not an IOSAPIC interrupt! */
  213. spin_lock_irqsave(&iosapic_lock, flags);
  214. {
  215. /* set only the mask bit */
  216. low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
  217. iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
  218. }
  219. spin_unlock_irqrestore(&iosapic_lock, flags);
  220. }
  221. static void
  222. unmask_irq (unsigned int irq)
  223. {
  224. unsigned long flags;
  225. char __iomem *addr;
  226. u32 low32;
  227. int rte_index;
  228. ia64_vector vec = irq_to_vector(irq);
  229. addr = iosapic_intr_info[vec].addr;
  230. rte_index = iosapic_intr_info[vec].rte_index;
  231. if (rte_index < 0)
  232. return; /* not an IOSAPIC interrupt! */
  233. spin_lock_irqsave(&iosapic_lock, flags);
  234. {
  235. low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
  236. iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
  237. }
  238. spin_unlock_irqrestore(&iosapic_lock, flags);
  239. }
  240. static void
  241. iosapic_set_affinity (unsigned int irq, cpumask_t mask)
  242. {
  243. #ifdef CONFIG_SMP
  244. unsigned long flags;
  245. u32 high32, low32;
  246. int dest, rte_index;
  247. char __iomem *addr;
  248. int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
  249. ia64_vector vec;
  250. irq &= (~IA64_IRQ_REDIRECTED);
  251. vec = irq_to_vector(irq);
  252. if (cpus_empty(mask))
  253. return;
  254. dest = cpu_physical_id(first_cpu(mask));
  255. rte_index = iosapic_intr_info[vec].rte_index;
  256. addr = iosapic_intr_info[vec].addr;
  257. if (rte_index < 0)
  258. return; /* not an IOSAPIC interrupt */
  259. set_irq_affinity_info(irq, dest, redir);
  260. /* dest contains both id and eid */
  261. high32 = dest << IOSAPIC_DEST_SHIFT;
  262. spin_lock_irqsave(&iosapic_lock, flags);
  263. {
  264. low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
  265. if (redir)
  266. /* change delivery mode to lowest priority */
  267. low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
  268. else
  269. /* change delivery mode to fixed */
  270. low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
  271. iosapic_intr_info[vec].low32 = low32;
  272. iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
  273. iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
  274. }
  275. spin_unlock_irqrestore(&iosapic_lock, flags);
  276. #endif
  277. }
  278. /*
  279. * Handlers for level-triggered interrupts.
  280. */
  281. static unsigned int
  282. iosapic_startup_level_irq (unsigned int irq)
  283. {
  284. unmask_irq(irq);
  285. return 0;
  286. }
  287. static void
  288. iosapic_end_level_irq (unsigned int irq)
  289. {
  290. ia64_vector vec = irq_to_vector(irq);
  291. move_irq(irq);
  292. iosapic_eoi(iosapic_intr_info[vec].addr, vec);
  293. }
  294. #define iosapic_shutdown_level_irq mask_irq
  295. #define iosapic_enable_level_irq unmask_irq
  296. #define iosapic_disable_level_irq mask_irq
  297. #define iosapic_ack_level_irq nop
  298. struct hw_interrupt_type irq_type_iosapic_level = {
  299. .typename = "IO-SAPIC-level",
  300. .startup = iosapic_startup_level_irq,
  301. .shutdown = iosapic_shutdown_level_irq,
  302. .enable = iosapic_enable_level_irq,
  303. .disable = iosapic_disable_level_irq,
  304. .ack = iosapic_ack_level_irq,
  305. .end = iosapic_end_level_irq,
  306. .set_affinity = iosapic_set_affinity
  307. };
  308. /*
  309. * Handlers for edge-triggered interrupts.
  310. */
  311. static unsigned int
  312. iosapic_startup_edge_irq (unsigned int irq)
  313. {
  314. unmask_irq(irq);
  315. /*
  316. * IOSAPIC simply drops interrupts pended while the
  317. * corresponding pin was masked, so we can't know if an
  318. * interrupt is pending already. Let's hope not...
  319. */
  320. return 0;
  321. }
  322. static void
  323. iosapic_ack_edge_irq (unsigned int irq)
  324. {
  325. irq_desc_t *idesc = irq_descp(irq);
  326. move_irq(irq);
  327. /*
  328. * Once we have recorded IRQ_PENDING already, we can mask the
  329. * interrupt for real. This prevents IRQ storms from unhandled
  330. * devices.
  331. */
  332. if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) == (IRQ_PENDING|IRQ_DISABLED))
  333. mask_irq(irq);
  334. }
  335. #define iosapic_enable_edge_irq unmask_irq
  336. #define iosapic_disable_edge_irq nop
  337. #define iosapic_end_edge_irq nop
  338. struct hw_interrupt_type irq_type_iosapic_edge = {
  339. .typename = "IO-SAPIC-edge",
  340. .startup = iosapic_startup_edge_irq,
  341. .shutdown = iosapic_disable_edge_irq,
  342. .enable = iosapic_enable_edge_irq,
  343. .disable = iosapic_disable_edge_irq,
  344. .ack = iosapic_ack_edge_irq,
  345. .end = iosapic_end_edge_irq,
  346. .set_affinity = iosapic_set_affinity
  347. };
  348. unsigned int
  349. iosapic_version (char __iomem *addr)
  350. {
  351. /*
  352. * IOSAPIC Version Register return 32 bit structure like:
  353. * {
  354. * unsigned int version : 8;
  355. * unsigned int reserved1 : 8;
  356. * unsigned int max_redir : 8;
  357. * unsigned int reserved2 : 8;
  358. * }
  359. */
  360. return iosapic_read(addr, IOSAPIC_VERSION);
  361. }
  362. /*
  363. * if the given vector is already owned by other,
  364. * assign a new vector for the other and make the vector available
  365. */
  366. static void __init
  367. iosapic_reassign_vector (int vector)
  368. {
  369. int new_vector;
  370. if (iosapic_intr_info[vector].rte_index >= 0 || iosapic_intr_info[vector].addr
  371. || iosapic_intr_info[vector].gsi_base || iosapic_intr_info[vector].dmode
  372. || iosapic_intr_info[vector].polarity || iosapic_intr_info[vector].trigger)
  373. {
  374. new_vector = assign_irq_vector(AUTO_ASSIGN);
  375. printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector);
  376. memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
  377. sizeof(struct iosapic_intr_info));
  378. memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
  379. iosapic_intr_info[vector].rte_index = -1;
  380. }
  381. }
  382. static void
  383. register_intr (unsigned int gsi, int vector, unsigned char delivery,
  384. unsigned long polarity, unsigned long trigger)
  385. {
  386. irq_desc_t *idesc;
  387. struct hw_interrupt_type *irq_type;
  388. int rte_index;
  389. int index;
  390. unsigned long gsi_base;
  391. void __iomem *iosapic_address;
  392. index = find_iosapic(gsi);
  393. if (index < 0) {
  394. printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi);
  395. return;
  396. }
  397. iosapic_address = iosapic_lists[index].addr;
  398. gsi_base = iosapic_lists[index].gsi_base;
  399. rte_index = gsi - gsi_base;
  400. iosapic_intr_info[vector].rte_index = rte_index;
  401. iosapic_intr_info[vector].polarity = polarity;
  402. iosapic_intr_info[vector].dmode = delivery;
  403. iosapic_intr_info[vector].addr = iosapic_address;
  404. iosapic_intr_info[vector].gsi_base = gsi_base;
  405. iosapic_intr_info[vector].trigger = trigger;
  406. iosapic_intr_info[vector].refcnt++;
  407. if (trigger == IOSAPIC_EDGE)
  408. irq_type = &irq_type_iosapic_edge;
  409. else
  410. irq_type = &irq_type_iosapic_level;
  411. idesc = irq_descp(vector);
  412. if (idesc->handler != irq_type) {
  413. if (idesc->handler != &no_irq_type)
  414. printk(KERN_WARNING "%s: changing vector %d from %s to %s\n",
  415. __FUNCTION__, vector, idesc->handler->typename, irq_type->typename);
  416. idesc->handler = irq_type;
  417. }
  418. }
  419. static unsigned int
  420. get_target_cpu (unsigned int gsi, int vector)
  421. {
  422. #ifdef CONFIG_SMP
  423. static int cpu = -1;
  424. /*
  425. * If the platform supports redirection via XTP, let it
  426. * distribute interrupts.
  427. */
  428. if (smp_int_redirect & SMP_IRQ_REDIRECTION)
  429. return cpu_physical_id(smp_processor_id());
  430. /*
  431. * Some interrupts (ACPI SCI, for instance) are registered
  432. * before the BSP is marked as online.
  433. */
  434. if (!cpu_online(smp_processor_id()))
  435. return cpu_physical_id(smp_processor_id());
  436. #ifdef CONFIG_NUMA
  437. {
  438. int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
  439. cpumask_t cpu_mask;
  440. iosapic_index = find_iosapic(gsi);
  441. if (iosapic_index < 0 ||
  442. iosapic_lists[iosapic_index].node == MAX_NUMNODES)
  443. goto skip_numa_setup;
  444. cpu_mask = node_to_cpumask(iosapic_lists[iosapic_index].node);
  445. for_each_cpu_mask(numa_cpu, cpu_mask) {
  446. if (!cpu_online(numa_cpu))
  447. cpu_clear(numa_cpu, cpu_mask);
  448. }
  449. num_cpus = cpus_weight(cpu_mask);
  450. if (!num_cpus)
  451. goto skip_numa_setup;
  452. /* Use vector assigment to distribute across cpus in node */
  453. cpu_index = vector % num_cpus;
  454. for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++)
  455. numa_cpu = next_cpu(numa_cpu, cpu_mask);
  456. if (numa_cpu != NR_CPUS)
  457. return cpu_physical_id(numa_cpu);
  458. }
  459. skip_numa_setup:
  460. #endif
  461. /*
  462. * Otherwise, round-robin interrupt vectors across all the
  463. * processors. (It'd be nice if we could be smarter in the
  464. * case of NUMA.)
  465. */
  466. do {
  467. if (++cpu >= NR_CPUS)
  468. cpu = 0;
  469. } while (!cpu_online(cpu));
  470. return cpu_physical_id(cpu);
  471. #else
  472. return cpu_physical_id(smp_processor_id());
  473. #endif
  474. }
  475. /*
  476. * ACPI can describe IOSAPIC interrupts via static tables and namespace
  477. * methods. This provides an interface to register those interrupts and
  478. * program the IOSAPIC RTE.
  479. */
  480. int
  481. iosapic_register_intr (unsigned int gsi,
  482. unsigned long polarity, unsigned long trigger)
  483. {
  484. int vector;
  485. unsigned int dest;
  486. unsigned long flags;
  487. /*
  488. * If this GSI has already been registered (i.e., it's a
  489. * shared interrupt, or we lost a race to register it),
  490. * don't touch the RTE.
  491. */
  492. spin_lock_irqsave(&iosapic_lock, flags);
  493. {
  494. vector = gsi_to_vector(gsi);
  495. if (vector > 0) {
  496. iosapic_intr_info[vector].refcnt++;
  497. spin_unlock_irqrestore(&iosapic_lock, flags);
  498. return vector;
  499. }
  500. vector = assign_irq_vector(AUTO_ASSIGN);
  501. dest = get_target_cpu(gsi, vector);
  502. register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
  503. polarity, trigger);
  504. set_rte(vector, dest, 1);
  505. }
  506. spin_unlock_irqrestore(&iosapic_lock, flags);
  507. printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
  508. gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
  509. (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
  510. cpu_logical_id(dest), dest, vector);
  511. return vector;
  512. }
  513. #ifdef CONFIG_ACPI_DEALLOCATE_IRQ
  514. void
  515. iosapic_unregister_intr (unsigned int gsi)
  516. {
  517. unsigned long flags;
  518. int irq, vector;
  519. irq_desc_t *idesc;
  520. int rte_index;
  521. unsigned long trigger, polarity;
  522. /*
  523. * If the irq associated with the gsi is not found,
  524. * iosapic_unregister_intr() is unbalanced. We need to check
  525. * this again after getting locks.
  526. */
  527. irq = gsi_to_irq(gsi);
  528. if (irq < 0) {
  529. printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);
  530. WARN_ON(1);
  531. return;
  532. }
  533. vector = irq_to_vector(irq);
  534. idesc = irq_descp(irq);
  535. spin_lock_irqsave(&idesc->lock, flags);
  536. spin_lock(&iosapic_lock);
  537. {
  538. rte_index = iosapic_intr_info[vector].rte_index;
  539. if (rte_index < 0) {
  540. spin_unlock(&iosapic_lock);
  541. spin_unlock_irqrestore(&idesc->lock, flags);
  542. printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);
  543. WARN_ON(1);
  544. return;
  545. }
  546. if (--iosapic_intr_info[vector].refcnt > 0) {
  547. spin_unlock(&iosapic_lock);
  548. spin_unlock_irqrestore(&idesc->lock, flags);
  549. return;
  550. }
  551. /*
  552. * If interrupt handlers still exist on the irq
  553. * associated with the gsi, don't unregister the
  554. * interrupt.
  555. */
  556. if (idesc->action) {
  557. iosapic_intr_info[vector].refcnt++;
  558. spin_unlock(&iosapic_lock);
  559. spin_unlock_irqrestore(&idesc->lock, flags);
  560. printk(KERN_WARNING "Cannot unregister GSI. IRQ %u is still in use.\n", irq);
  561. return;
  562. }
  563. /* Clear the interrupt controller descriptor. */
  564. idesc->handler = &no_irq_type;
  565. trigger = iosapic_intr_info[vector].trigger;
  566. polarity = iosapic_intr_info[vector].polarity;
  567. /* Clear the interrupt information. */
  568. memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
  569. iosapic_intr_info[vector].rte_index = -1; /* mark as unused */
  570. }
  571. spin_unlock(&iosapic_lock);
  572. spin_unlock_irqrestore(&idesc->lock, flags);
  573. /* Free the interrupt vector */
  574. free_irq_vector(vector);
  575. printk(KERN_INFO "GSI %u (%s, %s) -> vector %d unregisterd.\n",
  576. gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
  577. (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
  578. vector);
  579. }
  580. #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
  581. /*
  582. * ACPI calls this when it finds an entry for a platform interrupt.
  583. * Note that the irq_base and IOSAPIC address must be set in iosapic_init().
  584. */
  585. int __init
  586. iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
  587. int iosapic_vector, u16 eid, u16 id,
  588. unsigned long polarity, unsigned long trigger)
  589. {
  590. static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"};
  591. unsigned char delivery;
  592. int vector, mask = 0;
  593. unsigned int dest = ((id << 8) | eid) & 0xffff;
  594. switch (int_type) {
  595. case ACPI_INTERRUPT_PMI:
  596. vector = iosapic_vector;
  597. /*
  598. * since PMI vector is alloc'd by FW(ACPI) not by kernel,
  599. * we need to make sure the vector is available
  600. */
  601. iosapic_reassign_vector(vector);
  602. delivery = IOSAPIC_PMI;
  603. break;
  604. case ACPI_INTERRUPT_INIT:
  605. vector = assign_irq_vector(AUTO_ASSIGN);
  606. delivery = IOSAPIC_INIT;
  607. break;
  608. case ACPI_INTERRUPT_CPEI:
  609. vector = IA64_CPE_VECTOR;
  610. delivery = IOSAPIC_LOWEST_PRIORITY;
  611. mask = 1;
  612. break;
  613. default:
  614. printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type);
  615. return -1;
  616. }
  617. register_intr(gsi, vector, delivery, polarity, trigger);
  618. printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
  619. int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",
  620. int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
  621. (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
  622. cpu_logical_id(dest), dest, vector);
  623. set_rte(vector, dest, mask);
  624. return vector;
  625. }
  626. /*
  627. * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
  628. * Note that the gsi_base and IOSAPIC address must be set in iosapic_init().
  629. */
  630. void __init
  631. iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
  632. unsigned long polarity,
  633. unsigned long trigger)
  634. {
  635. int vector;
  636. unsigned int dest = cpu_physical_id(smp_processor_id());
  637. vector = isa_irq_to_vector(isa_irq);
  638. register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
  639. DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
  640. isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",
  641. polarity == IOSAPIC_POL_HIGH ? "high" : "low",
  642. cpu_logical_id(dest), dest, vector);
  643. set_rte(vector, dest, 1);
  644. }
  645. void __init
  646. iosapic_system_init (int system_pcat_compat)
  647. {
  648. int vector;
  649. for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
  650. iosapic_intr_info[vector].rte_index = -1; /* mark as unused */
  651. pcat_compat = system_pcat_compat;
  652. if (pcat_compat) {
  653. /*
  654. * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
  655. * enabled.
  656. */
  657. printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);
  658. outb(0xff, 0xA1);
  659. outb(0xff, 0x21);
  660. }
  661. }
  662. void __init
  663. iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
  664. {
  665. int num_rte;
  666. unsigned int isa_irq, ver;
  667. char __iomem *addr;
  668. addr = ioremap(phys_addr, 0);
  669. ver = iosapic_version(addr);
  670. /*
  671. * The MAX_REDIR register holds the highest input pin
  672. * number (starting from 0).
  673. * We add 1 so that we can use it for number of pins (= RTEs)
  674. */
  675. num_rte = ((ver >> 16) & 0xff) + 1;
  676. iosapic_lists[num_iosapic].addr = addr;
  677. iosapic_lists[num_iosapic].gsi_base = gsi_base;
  678. iosapic_lists[num_iosapic].num_rte = num_rte;
  679. #ifdef CONFIG_NUMA
  680. iosapic_lists[num_iosapic].node = MAX_NUMNODES;
  681. #endif
  682. num_iosapic++;
  683. if ((gsi_base == 0) && pcat_compat) {
  684. /*
  685. * Map the legacy ISA devices into the IOSAPIC data. Some of these may
  686. * get reprogrammed later on with data from the ACPI Interrupt Source
  687. * Override table.
  688. */
  689. for (isa_irq = 0; isa_irq < 16; ++isa_irq)
  690. iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
  691. }
  692. }
  693. #ifdef CONFIG_NUMA
  694. void __init
  695. map_iosapic_to_node(unsigned int gsi_base, int node)
  696. {
  697. int index;
  698. index = find_iosapic(gsi_base);
  699. if (index < 0) {
  700. printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
  701. __FUNCTION__, gsi_base);
  702. return;
  703. }
  704. iosapic_lists[index].node = node;
  705. return;
  706. }
  707. #endif