aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/iosapic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/iosapic.c')
-rw-r--r--arch/ia64/kernel/iosapic.c165
1 files changed, 57 insertions, 108 deletions
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 7ded76658d2d..b0f9afebb146 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -108,10 +108,6 @@
108#define DBG(fmt...) 108#define DBG(fmt...)
109#endif 109#endif
110 110
111#define NR_PREALLOCATE_RTE_ENTRIES \
112 (PAGE_SIZE / sizeof(struct iosapic_rte_info))
113#define RTE_PREALLOCATED (1)
114
115static DEFINE_SPINLOCK(iosapic_lock); 111static DEFINE_SPINLOCK(iosapic_lock);
116 112
117/* 113/*
@@ -136,7 +132,6 @@ struct iosapic_rte_info {
136 struct list_head rte_list; /* RTEs sharing the same vector */ 132 struct list_head rte_list; /* RTEs sharing the same vector */
137 char rte_index; /* IOSAPIC RTE index */ 133 char rte_index; /* IOSAPIC RTE index */
138 int refcnt; /* reference counter */ 134 int refcnt; /* reference counter */
139 unsigned int flags; /* flags */
140 struct iosapic *iosapic; 135 struct iosapic *iosapic;
141} ____cacheline_aligned; 136} ____cacheline_aligned;
142 137
@@ -155,9 +150,6 @@ static struct iosapic_intr_info {
155 150
156static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ 151static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */
157 152
158static int iosapic_kmalloc_ok;
159static LIST_HEAD(free_rte_list);
160
161static inline void 153static inline void
162iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val) 154iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
163{ 155{
@@ -265,7 +257,7 @@ set_rte (unsigned int gsi, unsigned int irq, unsigned int dest, int mask)
265} 257}
266 258
267static void 259static void
268nop (unsigned int irq) 260nop (struct irq_data *data)
269{ 261{
270 /* do nothing... */ 262 /* do nothing... */
271} 263}
@@ -295,8 +287,9 @@ kexec_disable_iosapic(void)
295#endif 287#endif
296 288
297static void 289static void
298mask_irq (unsigned int irq) 290mask_irq (struct irq_data *data)
299{ 291{
292 unsigned int irq = data->irq;
300 u32 low32; 293 u32 low32;
301 int rte_index; 294 int rte_index;
302 struct iosapic_rte_info *rte; 295 struct iosapic_rte_info *rte;
@@ -313,8 +306,9 @@ mask_irq (unsigned int irq)
313} 306}
314 307
315static void 308static void
316unmask_irq (unsigned int irq) 309unmask_irq (struct irq_data *data)
317{ 310{
311 unsigned int irq = data->irq;
318 u32 low32; 312 u32 low32;
319 int rte_index; 313 int rte_index;
320 struct iosapic_rte_info *rte; 314 struct iosapic_rte_info *rte;
@@ -331,9 +325,11 @@ unmask_irq (unsigned int irq)
331 325
332 326
333static int 327static int
334iosapic_set_affinity(unsigned int irq, const struct cpumask *mask) 328iosapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
329 bool force)
335{ 330{
336#ifdef CONFIG_SMP 331#ifdef CONFIG_SMP
332 unsigned int irq = data->irq;
337 u32 high32, low32; 333 u32 high32, low32;
338 int cpu, dest, rte_index; 334 int cpu, dest, rte_index;
339 int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; 335 int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
@@ -387,31 +383,33 @@ iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
387 */ 383 */
388 384
389static unsigned int 385static unsigned int
390iosapic_startup_level_irq (unsigned int irq) 386iosapic_startup_level_irq (struct irq_data *data)
391{ 387{
392 unmask_irq(irq); 388 unmask_irq(data);
393 return 0; 389 return 0;
394} 390}
395 391
396static void 392static void
397iosapic_end_level_irq (unsigned int irq) 393iosapic_unmask_level_irq (struct irq_data *data)
398{ 394{
395 unsigned int irq = data->irq;
399 ia64_vector vec = irq_to_vector(irq); 396 ia64_vector vec = irq_to_vector(irq);
400 struct iosapic_rte_info *rte; 397 struct iosapic_rte_info *rte;
401 int do_unmask_irq = 0; 398 int do_unmask_irq = 0;
402 399
403 irq_complete_move(irq); 400 irq_complete_move(irq);
404 if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) { 401 if (unlikely(irqd_is_setaffinity_pending(data))) {
405 do_unmask_irq = 1; 402 do_unmask_irq = 1;
406 mask_irq(irq); 403 mask_irq(data);
407 } 404 } else
405 unmask_irq(data);
408 406
409 list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) 407 list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
410 iosapic_eoi(rte->iosapic->addr, vec); 408 iosapic_eoi(rte->iosapic->addr, vec);
411 409
412 if (unlikely(do_unmask_irq)) { 410 if (unlikely(do_unmask_irq)) {
413 move_masked_irq(irq); 411 irq_move_masked_irq(data);
414 unmask_irq(irq); 412 unmask_irq(data);
415 } 413 }
416} 414}
417 415
@@ -421,16 +419,15 @@ iosapic_end_level_irq (unsigned int irq)
421#define iosapic_ack_level_irq nop 419#define iosapic_ack_level_irq nop
422 420
423static struct irq_chip irq_type_iosapic_level = { 421static struct irq_chip irq_type_iosapic_level = {
424 .name = "IO-SAPIC-level", 422 .name = "IO-SAPIC-level",
425 .startup = iosapic_startup_level_irq, 423 .irq_startup = iosapic_startup_level_irq,
426 .shutdown = iosapic_shutdown_level_irq, 424 .irq_shutdown = iosapic_shutdown_level_irq,
427 .enable = iosapic_enable_level_irq, 425 .irq_enable = iosapic_enable_level_irq,
428 .disable = iosapic_disable_level_irq, 426 .irq_disable = iosapic_disable_level_irq,
429 .ack = iosapic_ack_level_irq, 427 .irq_ack = iosapic_ack_level_irq,
430 .end = iosapic_end_level_irq, 428 .irq_mask = mask_irq,
431 .mask = mask_irq, 429 .irq_unmask = iosapic_unmask_level_irq,
432 .unmask = unmask_irq, 430 .irq_set_affinity = iosapic_set_affinity
433 .set_affinity = iosapic_set_affinity
434}; 431};
435 432
436/* 433/*
@@ -438,9 +435,9 @@ static struct irq_chip irq_type_iosapic_level = {
438 */ 435 */
439 436
440static unsigned int 437static unsigned int
441iosapic_startup_edge_irq (unsigned int irq) 438iosapic_startup_edge_irq (struct irq_data *data)
442{ 439{
443 unmask_irq(irq); 440 unmask_irq(data);
444 /* 441 /*
445 * IOSAPIC simply drops interrupts pended while the 442 * IOSAPIC simply drops interrupts pended while the
446 * corresponding pin was masked, so we can't know if an 443 * corresponding pin was masked, so we can't know if an
@@ -450,37 +447,25 @@ iosapic_startup_edge_irq (unsigned int irq)
450} 447}
451 448
452static void 449static void
453iosapic_ack_edge_irq (unsigned int irq) 450iosapic_ack_edge_irq (struct irq_data *data)
454{ 451{
455 struct irq_desc *idesc = irq_desc + irq; 452 irq_complete_move(data->irq);
456 453 irq_move_irq(data);
457 irq_complete_move(irq);
458 move_native_irq(irq);
459 /*
460 * Once we have recorded IRQ_PENDING already, we can mask the
461 * interrupt for real. This prevents IRQ storms from unhandled
462 * devices.
463 */
464 if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) ==
465 (IRQ_PENDING|IRQ_DISABLED))
466 mask_irq(irq);
467} 454}
468 455
469#define iosapic_enable_edge_irq unmask_irq 456#define iosapic_enable_edge_irq unmask_irq
470#define iosapic_disable_edge_irq nop 457#define iosapic_disable_edge_irq nop
471#define iosapic_end_edge_irq nop
472 458
473static struct irq_chip irq_type_iosapic_edge = { 459static struct irq_chip irq_type_iosapic_edge = {
474 .name = "IO-SAPIC-edge", 460 .name = "IO-SAPIC-edge",
475 .startup = iosapic_startup_edge_irq, 461 .irq_startup = iosapic_startup_edge_irq,
476 .shutdown = iosapic_disable_edge_irq, 462 .irq_shutdown = iosapic_disable_edge_irq,
477 .enable = iosapic_enable_edge_irq, 463 .irq_enable = iosapic_enable_edge_irq,
478 .disable = iosapic_disable_edge_irq, 464 .irq_disable = iosapic_disable_edge_irq,
479 .ack = iosapic_ack_edge_irq, 465 .irq_ack = iosapic_ack_edge_irq,
480 .end = iosapic_end_edge_irq, 466 .irq_mask = mask_irq,
481 .mask = mask_irq, 467 .irq_unmask = unmask_irq,
482 .unmask = unmask_irq, 468 .irq_set_affinity = iosapic_set_affinity
483 .set_affinity = iosapic_set_affinity
484}; 469};
485 470
486static unsigned int 471static unsigned int
@@ -552,37 +537,6 @@ iosapic_reassign_vector (int irq)
552 } 537 }
553} 538}
554 539
555static struct iosapic_rte_info * __init_refok iosapic_alloc_rte (void)
556{
557 int i;
558 struct iosapic_rte_info *rte;
559 int preallocated = 0;
560
561 if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
562 rte = alloc_bootmem(sizeof(struct iosapic_rte_info) *
563 NR_PREALLOCATE_RTE_ENTRIES);
564 for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
565 list_add(&rte->rte_list, &free_rte_list);
566 }
567
568 if (!list_empty(&free_rte_list)) {
569 rte = list_entry(free_rte_list.next, struct iosapic_rte_info,
570 rte_list);
571 list_del(&rte->rte_list);
572 preallocated++;
573 } else {
574 rte = kmalloc(sizeof(struct iosapic_rte_info), GFP_ATOMIC);
575 if (!rte)
576 return NULL;
577 }
578
579 memset(rte, 0, sizeof(struct iosapic_rte_info));
580 if (preallocated)
581 rte->flags |= RTE_PREALLOCATED;
582
583 return rte;
584}
585
586static inline int irq_is_shared (int irq) 540static inline int irq_is_shared (int irq)
587{ 541{
588 return (iosapic_intr_info[irq].count > 1); 542 return (iosapic_intr_info[irq].count > 1);
@@ -601,8 +555,7 @@ static int
601register_intr (unsigned int gsi, int irq, unsigned char delivery, 555register_intr (unsigned int gsi, int irq, unsigned char delivery,
602 unsigned long polarity, unsigned long trigger) 556 unsigned long polarity, unsigned long trigger)
603{ 557{
604 struct irq_desc *idesc; 558 struct irq_chip *chip, *irq_type;
605 struct irq_chip *irq_type;
606 int index; 559 int index;
607 struct iosapic_rte_info *rte; 560 struct iosapic_rte_info *rte;
608 561
@@ -615,7 +568,7 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
615 568
616 rte = find_rte(irq, gsi); 569 rte = find_rte(irq, gsi);
617 if (!rte) { 570 if (!rte) {
618 rte = iosapic_alloc_rte(); 571 rte = kzalloc(sizeof (*rte), GFP_ATOMIC);
619 if (!rte) { 572 if (!rte) {
620 printk(KERN_WARNING "%s: cannot allocate memory\n", 573 printk(KERN_WARNING "%s: cannot allocate memory\n",
621 __func__); 574 __func__);
@@ -649,15 +602,18 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
649 602
650 irq_type = iosapic_get_irq_chip(trigger); 603 irq_type = iosapic_get_irq_chip(trigger);
651 604
652 idesc = irq_desc + irq; 605 chip = irq_get_chip(irq);
653 if (irq_type != NULL && idesc->chip != irq_type) { 606 if (irq_type != NULL && chip != irq_type) {
654 if (idesc->chip != &no_irq_chip) 607 if (chip != &no_irq_chip)
655 printk(KERN_WARNING 608 printk(KERN_WARNING
656 "%s: changing vector %d from %s to %s\n", 609 "%s: changing vector %d from %s to %s\n",
657 __func__, irq_to_vector(irq), 610 __func__, irq_to_vector(irq),
658 idesc->chip->name, irq_type->name); 611 chip->name, irq_type->name);
659 idesc->chip = irq_type; 612 chip = irq_type;
660 } 613 }
614 __irq_set_chip_handler_name_locked(irq, chip, trigger == IOSAPIC_EDGE ?
615 handle_edge_irq : handle_level_irq,
616 NULL);
661 return 0; 617 return 0;
662} 618}
663 619
@@ -767,6 +723,7 @@ iosapic_register_intr (unsigned int gsi,
767 struct iosapic_rte_info *rte; 723 struct iosapic_rte_info *rte;
768 u32 low32; 724 u32 low32;
769 unsigned char dmode; 725 unsigned char dmode;
726 struct irq_desc *desc;
770 727
771 /* 728 /*
772 * If this GSI has already been registered (i.e., it's a 729 * If this GSI has already been registered (i.e., it's a
@@ -794,12 +751,13 @@ iosapic_register_intr (unsigned int gsi,
794 goto unlock_iosapic_lock; 751 goto unlock_iosapic_lock;
795 } 752 }
796 753
797 raw_spin_lock(&irq_desc[irq].lock); 754 desc = irq_to_desc(irq);
755 raw_spin_lock(&desc->lock);
798 dest = get_target_cpu(gsi, irq); 756 dest = get_target_cpu(gsi, irq);
799 dmode = choose_dmode(); 757 dmode = choose_dmode();
800 err = register_intr(gsi, irq, dmode, polarity, trigger); 758 err = register_intr(gsi, irq, dmode, polarity, trigger);
801 if (err < 0) { 759 if (err < 0) {
802 raw_spin_unlock(&irq_desc[irq].lock); 760 raw_spin_unlock(&desc->lock);
803 irq = err; 761 irq = err;
804 goto unlock_iosapic_lock; 762 goto unlock_iosapic_lock;
805 } 763 }
@@ -818,7 +776,7 @@ iosapic_register_intr (unsigned int gsi,
818 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), 776 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
819 cpu_logical_id(dest), dest, irq_to_vector(irq)); 777 cpu_logical_id(dest), dest, irq_to_vector(irq));
820 778
821 raw_spin_unlock(&irq_desc[irq].lock); 779 raw_spin_unlock(&desc->lock);
822 unlock_iosapic_lock: 780 unlock_iosapic_lock:
823 spin_unlock_irqrestore(&iosapic_lock, flags); 781 spin_unlock_irqrestore(&iosapic_lock, flags);
824 return irq; 782 return irq;
@@ -829,7 +787,6 @@ iosapic_unregister_intr (unsigned int gsi)
829{ 787{
830 unsigned long flags; 788 unsigned long flags;
831 int irq, index; 789 int irq, index;
832 struct irq_desc *idesc;
833 u32 low32; 790 u32 low32;
834 unsigned long trigger, polarity; 791 unsigned long trigger, polarity;
835 unsigned int dest; 792 unsigned int dest;
@@ -859,7 +816,6 @@ iosapic_unregister_intr (unsigned int gsi)
859 if (--rte->refcnt > 0) 816 if (--rte->refcnt > 0)
860 goto out; 817 goto out;
861 818
862 idesc = irq_desc + irq;
863 rte->refcnt = NO_REF_RTE; 819 rte->refcnt = NO_REF_RTE;
864 820
865 /* Mask the interrupt */ 821 /* Mask the interrupt */
@@ -883,7 +839,7 @@ iosapic_unregister_intr (unsigned int gsi)
883 if (iosapic_intr_info[irq].count == 0) { 839 if (iosapic_intr_info[irq].count == 0) {
884#ifdef CONFIG_SMP 840#ifdef CONFIG_SMP
885 /* Clear affinity */ 841 /* Clear affinity */
886 cpumask_setall(idesc->affinity); 842 cpumask_setall(irq_get_irq_data(irq)->affinity);
887#endif 843#endif
888 /* Clear the interrupt information */ 844 /* Clear the interrupt information */
889 iosapic_intr_info[irq].dest = 0; 845 iosapic_intr_info[irq].dest = 0;
@@ -1161,10 +1117,3 @@ map_iosapic_to_node(unsigned int gsi_base, int node)
1161 return; 1117 return;
1162} 1118}
1163#endif 1119#endif
1164
1165static int __init iosapic_enable_kmalloc (void)
1166{
1167 iosapic_kmalloc_ok = 1;
1168 return 0;
1169}
1170core_initcall (iosapic_enable_kmalloc);