1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131#include <linux/types.h>
132#include <linux/kernel.h>
133#include <linux/spinlock.h>
134#include <linux/pci.h>
135#include <linux/init.h>
136#include <linux/slab.h>
137#include <linux/interrupt.h>
138
139#include <asm/byteorder.h>
140#include <asm/pdc.h>
141#include <asm/pdcpat.h>
142#include <asm/page.h>
143#include <asm/system.h>
144#include <asm/io.h>
145#ifdef CONFIG_SUPERIO
146#include <asm/superio.h>
147#endif
148
149#include <asm/ropes.h>
150#include "./iosapic_private.h"
151
152#define MODULE_NAME "iosapic"
153
154
155#undef PCI_BRIDGE_FUNCS
156#undef DEBUG_IOSAPIC
157#undef DEBUG_IOSAPIC_IRT
158
159
160#ifdef DEBUG_IOSAPIC
161#define DBG(x...) printk(x)
162#else
163#define DBG(x...)
164#endif
165
166#ifdef DEBUG_IOSAPIC_IRT
167#define DBG_IRT(x...) printk(x)
168#else
169#define DBG_IRT(x...)
170#endif
171
172#ifdef CONFIG_64BIT
173#define COMPARE_IRTE_ADDR(irte, hpa) ((irte)->dest_iosapic_addr == (hpa))
174#else
175#define COMPARE_IRTE_ADDR(irte, hpa) \
176 ((irte)->dest_iosapic_addr == ((hpa) | 0xffffffff00000000ULL))
177#endif
178
179#define IOSAPIC_REG_SELECT 0x00
180#define IOSAPIC_REG_WINDOW 0x10
181#define IOSAPIC_REG_EOI 0x40
182
183#define IOSAPIC_REG_VERSION 0x1
184
185#define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2)
186#define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2)
187
188static inline unsigned int iosapic_read(void __iomem *iosapic, unsigned int reg)
189{
190 writel(reg, iosapic + IOSAPIC_REG_SELECT);
191 return readl(iosapic + IOSAPIC_REG_WINDOW);
192}
193
194static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 val)
195{
196 writel(reg, iosapic + IOSAPIC_REG_SELECT);
197 writel(val, iosapic + IOSAPIC_REG_WINDOW);
198}
199
200#define IOSAPIC_VERSION_MASK 0x000000ff
201#define IOSAPIC_VERSION(ver) ((int) (ver & IOSAPIC_VERSION_MASK))
202
203#define IOSAPIC_MAX_ENTRY_MASK 0x00ff0000
204#define IOSAPIC_MAX_ENTRY_SHIFT 0x10
205#define IOSAPIC_IRDT_MAX_ENTRY(ver) \
206 (int) (((ver) & IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
207
208
209#define IOSAPIC_IRDT_ENABLE 0x10000
210#define IOSAPIC_IRDT_PO_LOW 0x02000
211#define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
212#define IOSAPIC_IRDT_MODE_LPRI 0x00100
213
214
215#define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
216
217
218static DEFINE_SPINLOCK(iosapic_lock);
219
220static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
221{
222 __raw_writel(data, addr);
223}
224
225
226
227
228
229
230
231
232
233
234static struct irt_entry *irt_cell;
235static size_t irt_num_entry;
236
237static struct irt_entry *iosapic_alloc_irt(int num_entries)
238{
239 unsigned long a;
240
241
242
243
244
245
246 a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
247 a = (a + 7UL) & ~7UL;
248 return (struct irt_entry *)a;
249}
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278static int __init
279iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
280{
281 long status;
282 struct irt_entry *table;
283 unsigned long num_entries = 0UL;
284
285 BUG_ON(!irt);
286
287 if (is_pdc_pat()) {
288
289 DBG("calling get_irt_size (cell %ld)\n", cell_num);
290 status = pdc_pat_get_irt_size(&num_entries, cell_num);
291 DBG("get_irt_size: %ld\n", status);
292
293 BUG_ON(status != PDC_OK);
294 BUG_ON(num_entries == 0);
295
296
297
298
299
300
301
302 table = iosapic_alloc_irt(num_entries);
303 if (table == NULL) {
304 printk(KERN_WARNING MODULE_NAME ": read_irt : can "
305 "not alloc mem for IRT\n");
306 return 0;
307 }
308
309
310 status = pdc_pat_get_irt(table, cell_num);
311 DBG("pdc_pat_get_irt: %ld\n", status);
312 WARN_ON(status != PDC_OK);
313 } else {
314
315
316
317
318
319 if (irt_cell)
320 return 0;
321
322
323 status = pdc_pci_irt_size(&num_entries, 0);
324 DBG("pdc_pci_irt_size: %ld\n", status);
325
326 if (status != PDC_OK) {
327
328 return 0;
329 }
330
331 BUG_ON(num_entries == 0);
332
333 table = iosapic_alloc_irt(num_entries);
334 if (!table) {
335 printk(KERN_WARNING MODULE_NAME ": read_irt : can "
336 "not alloc mem for IRT\n");
337 return 0;
338 }
339
340
341 status = pdc_pci_irt(num_entries, 0, table);
342 BUG_ON(status != PDC_OK);
343 }
344
345
346 *irt = table;
347
348#ifdef DEBUG_IOSAPIC_IRT
349{
350 struct irt_entry *p = table;
351 int i;
352
353 printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
354 printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
355 table,
356 num_entries,
357 (int) sizeof(struct irt_entry));
358
359 for (i = 0 ; i < num_entries ; i++, p++) {
360 printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
361 p->entry_type, p->entry_length, p->interrupt_type,
362 p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
363 p->src_seg_id, p->dest_iosapic_intin,
364 ((u32 *) p)[2],
365 ((u32 *) p)[3]
366 );
367 }
368}
369#endif
370
371 return num_entries;
372}
373
374
375
376void __init iosapic_init(void)
377{
378 unsigned long cell = 0;
379
380 DBG("iosapic_init()\n");
381
382#ifdef __LP64__
383 if (is_pdc_pat()) {
384 int status;
385 struct pdc_pat_cell_num cell_info;
386
387 status = pdc_pat_cell_get_number(&cell_info);
388 if (status == PDC_OK) {
389 cell = cell_info.cell_num;
390 }
391 }
392#endif
393
394
395 irt_num_entry = iosapic_load_irt(cell, &irt_cell);
396 if (irt_num_entry == 0)
397 irt_cell = NULL;
398}
399
400
401
402
403
404static struct irt_entry *
405irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
406{
407 struct irt_entry *i = irt_cell;
408 int cnt;
409 u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1);
410
411 DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin);
412
413 for (cnt=0; cnt < irt_num_entry; cnt++, i++) {
414
415
416
417
418
419
420
421
422 if (i->entry_type != IRT_IOSAPIC_TYPE) {
423 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type);
424 continue;
425 }
426
427 if (i->entry_length != IRT_IOSAPIC_LENGTH) {
428 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length);
429 continue;
430 }
431
432 if (i->interrupt_type != IRT_VECTORED_INTR) {
433 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type);
434 continue;
435 }
436
437 if (!COMPARE_IRTE_ADDR(i, isi->isi_hpa))
438 continue;
439
440 if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
441 continue;
442
443
444
445
446
447
448
449
450
451 return i;
452 }
453
454 printk(KERN_WARNING MODULE_NAME ": 0x%lx : no IRT entry for slot %d, pin %d\n",
455 isi->isi_hpa, slot, intr_pin);
456 return NULL;
457}
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474static struct irt_entry *
475iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
476{
477 u8 intr_pin, intr_slot;
478
479 pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
480
481 DBG_IRT("iosapic_xlate_pin(%s) SLOT %d pin %d\n",
482 pcidev->slot_name, PCI_SLOT(pcidev->devfn), intr_pin);
483
484 if (intr_pin == 0) {
485
486 return NULL;
487 }
488
489
490 if (pcidev->bus->parent) {
491
492
493
494#ifdef PCI_BRIDGE_FUNCS
495
496
497
498
499
500
501
502
503
504 if (pci_bridge_funcs->xlate_intr_line) {
505 intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev);
506 }
507#else
508 struct pci_bus *p = pcidev->bus;
509
510
511
512
513
514
515
516
517
518
519
520
521
522 intr_pin = pci_swizzle_interrupt_pin(pcidev, intr_pin);
523#endif
524
525
526
527
528 while (p->parent->parent)
529 p = p->parent;
530
531 intr_slot = PCI_SLOT(p->self->devfn);
532 } else {
533 intr_slot = PCI_SLOT(pcidev->devfn);
534 }
535 DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n",
536 pcidev->bus->secondary, intr_slot, intr_pin);
537
538 return irt_find_irqline(isi, intr_slot, intr_pin);
539}
540
541static void iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)
542{
543 struct iosapic_info *isp = vi->iosapic;
544 u8 idx = vi->irqline;
545
546 *dp0 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY(idx));
547 *dp1 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY_HI(idx));
548}
549
550
551static void iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1)
552{
553 struct iosapic_info *isp = vi->iosapic;
554
555 DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %lx 0x%x 0x%x\n",
556 vi->irqline, isp->isi_hpa, dp0, dp1);
557
558 iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY(vi->irqline), dp0);
559
560
561 dp0 = readl(isp->addr+IOSAPIC_REG_WINDOW);
562
563 iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY_HI(vi->irqline), dp1);
564
565
566 dp1 = readl(isp->addr+IOSAPIC_REG_WINDOW);
567}
568
569
570
571
572
573
574static void
575iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
576{
577 u32 mode = 0;
578 struct irt_entry *p = vi->irte;
579
580 if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
581 mode |= IOSAPIC_IRDT_PO_LOW;
582
583 if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG)
584 mode |= IOSAPIC_IRDT_LEVEL_TRIG;
585
586
587
588
589
590
591 *dp0 = mode | (u32) vi->txn_data;
592
593
594
595
596
597 if (is_pdc_pat()) {
598
599
600
601
602 *dp1 = (u32) (vi->txn_addr);
603 } else {
604
605
606
607
608
609
610
611 *dp1 = (((u32)vi->txn_addr & 0x0ff00000) >> 4) |
612 (((u32)vi->txn_addr & 0x000ff000) << 12);
613 }
614 DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1);
615}
616
617
618static struct vector_info *iosapic_get_vector(unsigned int irq)
619{
620 struct irq_desc *desc = irq_to_desc(irq);
621
622 return desc->chip_data;
623}
624
625static void iosapic_disable_irq(unsigned int irq)
626{
627 unsigned long flags;
628 struct vector_info *vi = iosapic_get_vector(irq);
629 u32 d0, d1;
630
631 spin_lock_irqsave(&iosapic_lock, flags);
632 iosapic_rd_irt_entry(vi, &d0, &d1);
633 d0 |= IOSAPIC_IRDT_ENABLE;
634 iosapic_wr_irt_entry(vi, d0, d1);
635 spin_unlock_irqrestore(&iosapic_lock, flags);
636}
637
638static void iosapic_enable_irq(unsigned int irq)
639{
640 struct vector_info *vi = iosapic_get_vector(irq);
641 u32 d0, d1;
642
643
644 WARN_ON(vi->txn_irq == 0);
645
646 iosapic_set_irt_data(vi, &d0, &d1);
647 iosapic_wr_irt_entry(vi, d0, d1);
648
649#ifdef DEBUG_IOSAPIC_IRT
650{
651 u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL);
652 printk("iosapic_enable_irq(): regs %p", vi->eoi_addr);
653 for ( ; t < vi->eoi_addr; t++)
654 printk(" %x", readl(t));
655 printk("\n");
656}
657
658printk("iosapic_enable_irq(): sel ");
659{
660 struct iosapic_info *isp = vi->iosapic;
661
662 for (d0=0x10; d0<0x1e; d0++) {
663 d1 = iosapic_read(isp->addr, d0);
664 printk(" %x", d1);
665 }
666}
667printk("\n");
668#endif
669
670
671
672
673
674
675
676 DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", irq,
677 vi->eoi_addr, vi->eoi_data);
678 iosapic_eoi(vi->eoi_addr, vi->eoi_data);
679}
680
681
682
683
684
685
686
687
688
689static void iosapic_end_irq(unsigned int irq)
690{
691 struct vector_info *vi = iosapic_get_vector(irq);
692 DBG(KERN_DEBUG "end_irq(%d): eoi(%p, 0x%x)\n", irq,
693 vi->eoi_addr, vi->eoi_data);
694 iosapic_eoi(vi->eoi_addr, vi->eoi_data);
695 cpu_end_irq(irq);
696}
697
698static unsigned int iosapic_startup_irq(unsigned int irq)
699{
700 iosapic_enable_irq(irq);
701 return 0;
702}
703
704#ifdef CONFIG_SMP
705static void iosapic_set_affinity_irq(unsigned int irq,
706 const struct cpumask *dest)
707{
708 struct vector_info *vi = iosapic_get_vector(irq);
709 u32 d0, d1, dummy_d0;
710 unsigned long flags;
711 int dest_cpu;
712
713 dest_cpu = cpu_check_affinity(irq, dest);
714 if (dest_cpu < 0)
715 return;
716
717 cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
718 vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
719
720 spin_lock_irqsave(&iosapic_lock, flags);
721
722
723 iosapic_rd_irt_entry(vi, &d0, &d1);
724 iosapic_set_irt_data(vi, &dummy_d0, &d1);
725 iosapic_wr_irt_entry(vi, d0, d1);
726 spin_unlock_irqrestore(&iosapic_lock, flags);
727}
728#endif
729
730static struct hw_interrupt_type iosapic_interrupt_type = {
731 .typename = "IO-SAPIC-level",
732 .startup = iosapic_startup_irq,
733 .shutdown = iosapic_disable_irq,
734 .enable = iosapic_enable_irq,
735 .disable = iosapic_disable_irq,
736 .ack = cpu_ack_irq,
737 .end = iosapic_end_irq,
738#ifdef CONFIG_SMP
739 .set_affinity = iosapic_set_affinity_irq,
740#endif
741};
742
743int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
744{
745 struct iosapic_info *isi = isi_obj;
746 struct irt_entry *irte = NULL;
747 struct vector_info *vi;
748 int isi_line;
749
750 if (!isi) {
751 printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
752 pci_name(pcidev));
753 return -1;
754 }
755
756#ifdef CONFIG_SUPERIO
757
758
759
760
761
762
763
764
765 if (is_superio_device(pcidev)) {
766
767 pcidev->irq = superio_fixup_irq(pcidev);
768
769
770 if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN)
771 return pcidev->irq;
772 }
773#endif
774
775
776 irte = iosapic_xlate_pin(isi, pcidev);
777 if (!irte) {
778 printk("iosapic: no IRTE for %s (IRQ not connected?)\n",
779 pci_name(pcidev));
780 return -1;
781 }
782 DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
783 irte,
784 irte->entry_type,
785 irte->entry_length,
786 irte->polarity_trigger,
787 irte->src_bus_irq_devno,
788 irte->src_bus_id,
789 irte->src_seg_id,
790 irte->dest_iosapic_intin,
791 (u32) irte->dest_iosapic_addr);
792 isi_line = irte->dest_iosapic_intin;
793
794
795 vi = isi->isi_vector + isi_line;
796 DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi);
797
798
799 if (vi->irte)
800 goto out;
801
802 vi->irte = irte;
803
804
805
806
807
808
809
810
811
812
813 vi->txn_irq = txn_alloc_irq(8);
814
815 if (vi->txn_irq < 0)
816 panic("I/O sapic: couldn't get TXN IRQ\n");
817
818
819 vi->txn_addr = txn_alloc_addr(vi->txn_irq);
820 vi->txn_data = txn_alloc_data(vi->txn_irq);
821
822 vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI;
823 vi->eoi_data = cpu_to_le32(vi->txn_data);
824
825 cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi);
826
827 out:
828 pcidev->irq = vi->txn_irq;
829
830 DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
831 PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn),
832 pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
833
834 return pcidev->irq;
835}
836
837
838
839
840
841static unsigned int
842iosapic_rd_version(struct iosapic_info *isi)
843{
844 return iosapic_read(isi->addr, IOSAPIC_REG_VERSION);
845}
846
847
848
849
850
851
852
853
854
855
856
857
858void *iosapic_register(unsigned long hpa)
859{
860 struct iosapic_info *isi = NULL;
861 struct irt_entry *irte = irt_cell;
862 struct vector_info *vip;
863 int cnt;
864
865
866
867
868
869
870 for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
871 WARN_ON(IRT_IOSAPIC_TYPE != irte->entry_type);
872 if (COMPARE_IRTE_ADDR(irte, hpa))
873 break;
874 }
875
876 if (cnt >= irt_num_entry) {
877 DBG("iosapic_register() ignoring 0x%lx (NOT FOUND)\n", hpa);
878 return NULL;
879 }
880
881 isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
882 if (!isi) {
883 BUG();
884 return NULL;
885 }
886
887 isi->addr = ioremap_nocache(hpa, 4096);
888 isi->isi_hpa = hpa;
889 isi->isi_version = iosapic_rd_version(isi);
890 isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
891
892 vip = isi->isi_vector = (struct vector_info *)
893 kzalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
894 if (vip == NULL) {
895 kfree(isi);
896 return NULL;
897 }
898
899 for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
900 vip->irqline = (unsigned char) cnt;
901 vip->iosapic = isi;
902 }
903 return isi;
904}
905
906
907#ifdef DEBUG_IOSAPIC
908
909static void
910iosapic_prt_irt(void *irt, long num_entry)
911{
912 unsigned int i, *irp = (unsigned int *) irt;
913
914
915 printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
916
917 for (i=0; i<num_entry; i++, irp += 4) {
918 printk(KERN_DEBUG "%p : %2d %.8x %.8x %.8x %.8x\n",
919 irp, i, irp[0], irp[1], irp[2], irp[3]);
920 }
921}
922
923
924static void
925iosapic_prt_vi(struct vector_info *vi)
926{
927 printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi);
928 printk(KERN_DEBUG "\t\tstatus: %.4x\n", vi->status);
929 printk(KERN_DEBUG "\t\ttxn_irq: %d\n", vi->txn_irq);
930 printk(KERN_DEBUG "\t\ttxn_addr: %lx\n", vi->txn_addr);
931 printk(KERN_DEBUG "\t\ttxn_data: %lx\n", vi->txn_data);
932 printk(KERN_DEBUG "\t\teoi_addr: %p\n", vi->eoi_addr);
933 printk(KERN_DEBUG "\t\teoi_data: %x\n", vi->eoi_data);
934}
935
936
937static void
938iosapic_prt_isi(struct iosapic_info *isi)
939{
940 printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
941 printk(KERN_DEBUG "\t\tisi_hpa: %lx\n", isi->isi_hpa);
942 printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status);
943 printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version);
944 printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector);
945}
946#endif
947