0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 #include <linux/pci.h>
0127
0128 #include <asm/pdc.h>
0129 #include <asm/pdcpat.h>
0130 #ifdef CONFIG_SUPERIO
0131 #include <asm/superio.h>
0132 #endif
0133
0134 #include <asm/ropes.h>
0135 #include "iosapic_private.h"
0136
0137 #define MODULE_NAME "iosapic"
0138
0139
0140 #undef PCI_BRIDGE_FUNCS
0141 #undef DEBUG_IOSAPIC
0142 #undef DEBUG_IOSAPIC_IRT
0143
0144
0145 #ifdef DEBUG_IOSAPIC
0146 #define DBG(x...) printk(x)
0147 #else
0148 #define DBG(x...)
0149 #endif
0150
0151 #ifdef DEBUG_IOSAPIC_IRT
0152 #define DBG_IRT(x...) printk(x)
0153 #else
0154 #define DBG_IRT(x...)
0155 #endif
0156
0157 #ifdef CONFIG_64BIT
0158 #define COMPARE_IRTE_ADDR(irte, hpa) ((irte)->dest_iosapic_addr == (hpa))
0159 #else
0160 #define COMPARE_IRTE_ADDR(irte, hpa) \
0161 ((irte)->dest_iosapic_addr == ((hpa) | 0xffffffff00000000ULL))
0162 #endif
0163
0164 #define IOSAPIC_REG_SELECT 0x00
0165 #define IOSAPIC_REG_WINDOW 0x10
0166 #define IOSAPIC_REG_EOI 0x40
0167
0168 #define IOSAPIC_REG_VERSION 0x1
0169
0170 #define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2)
0171 #define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2)
0172
0173 static inline unsigned int iosapic_read(void __iomem *iosapic, unsigned int reg)
0174 {
0175 writel(reg, iosapic + IOSAPIC_REG_SELECT);
0176 return readl(iosapic + IOSAPIC_REG_WINDOW);
0177 }
0178
0179 static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 val)
0180 {
0181 writel(reg, iosapic + IOSAPIC_REG_SELECT);
0182 writel(val, iosapic + IOSAPIC_REG_WINDOW);
0183 }
0184
0185 #define IOSAPIC_VERSION_MASK 0x000000ff
0186 #define IOSAPIC_VERSION(ver) ((int) (ver & IOSAPIC_VERSION_MASK))
0187
0188 #define IOSAPIC_MAX_ENTRY_MASK 0x00ff0000
0189 #define IOSAPIC_MAX_ENTRY_SHIFT 0x10
0190 #define IOSAPIC_IRDT_MAX_ENTRY(ver) \
0191 (int) (((ver) & IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
0192
0193
0194 #define IOSAPIC_IRDT_ENABLE 0x10000
0195 #define IOSAPIC_IRDT_PO_LOW 0x02000
0196 #define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
0197 #define IOSAPIC_IRDT_MODE_LPRI 0x00100
0198
0199
0200 #define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
0201
0202
0203 static DEFINE_SPINLOCK(iosapic_lock);
0204
0205 static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
0206 {
0207 __raw_writel(data, addr);
0208 }
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 static struct irt_entry *irt_cell;
0220 static size_t irt_num_entry;
0221
0222 static struct irt_entry *iosapic_alloc_irt(int num_entries)
0223 {
0224 return kcalloc(num_entries, sizeof(struct irt_entry), GFP_KERNEL);
0225 }
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254 static int __init
0255 iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
0256 {
0257 long status;
0258 struct irt_entry *table;
0259 unsigned long num_entries = 0UL;
0260
0261 BUG_ON(!irt);
0262
0263 if (is_pdc_pat()) {
0264
0265 DBG("calling get_irt_size (cell %ld)\n", cell_num);
0266 status = pdc_pat_get_irt_size(&num_entries, cell_num);
0267 DBG("get_irt_size: %ld\n", status);
0268
0269 BUG_ON(status != PDC_OK);
0270 BUG_ON(num_entries == 0);
0271
0272
0273
0274
0275
0276
0277
0278 table = iosapic_alloc_irt(num_entries);
0279 if (table == NULL) {
0280 printk(KERN_WARNING MODULE_NAME ": read_irt : can "
0281 "not alloc mem for IRT\n");
0282 return 0;
0283 }
0284
0285
0286 status = pdc_pat_get_irt(table, cell_num);
0287 DBG("pdc_pat_get_irt: %ld\n", status);
0288 WARN_ON(status != PDC_OK);
0289 } else {
0290
0291
0292
0293
0294
0295 if (irt_cell)
0296 return 0;
0297
0298
0299 status = pdc_pci_irt_size(&num_entries, 0);
0300 DBG("pdc_pci_irt_size: %ld\n", status);
0301
0302 if (status != PDC_OK) {
0303
0304 return 0;
0305 }
0306
0307 BUG_ON(num_entries == 0);
0308
0309 table = iosapic_alloc_irt(num_entries);
0310 if (!table) {
0311 printk(KERN_WARNING MODULE_NAME ": read_irt : can "
0312 "not alloc mem for IRT\n");
0313 return 0;
0314 }
0315
0316
0317 status = pdc_pci_irt(num_entries, 0, table);
0318 BUG_ON(status != PDC_OK);
0319 }
0320
0321
0322 *irt = table;
0323
0324 #ifdef DEBUG_IOSAPIC_IRT
0325 {
0326 struct irt_entry *p = table;
0327 int i;
0328
0329 printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
0330 printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
0331 table,
0332 num_entries,
0333 (int) sizeof(struct irt_entry));
0334
0335 for (i = 0 ; i < num_entries ; i++, p++) {
0336 printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
0337 p->entry_type, p->entry_length, p->interrupt_type,
0338 p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
0339 p->src_seg_id, p->dest_iosapic_intin,
0340 ((u32 *) p)[2],
0341 ((u32 *) p)[3]
0342 );
0343 }
0344 }
0345 #endif
0346
0347 return num_entries;
0348 }
0349
0350
0351
0352 void __init iosapic_init(void)
0353 {
0354 unsigned long cell = 0;
0355
0356 DBG("iosapic_init()\n");
0357
0358 #ifdef __LP64__
0359 if (is_pdc_pat()) {
0360 int status;
0361 struct pdc_pat_cell_num cell_info;
0362
0363 status = pdc_pat_cell_get_number(&cell_info);
0364 if (status == PDC_OK) {
0365 cell = cell_info.cell_num;
0366 }
0367 }
0368 #endif
0369
0370
0371 irt_num_entry = iosapic_load_irt(cell, &irt_cell);
0372 if (irt_num_entry == 0)
0373 irt_cell = NULL;
0374 }
0375
0376
0377
0378
0379
0380 static struct irt_entry *
0381 irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
0382 {
0383 struct irt_entry *i = irt_cell;
0384 int cnt;
0385 u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1);
0386
0387 DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin);
0388
0389 for (cnt=0; cnt < irt_num_entry; cnt++, i++) {
0390
0391
0392
0393
0394
0395
0396
0397
0398 if (i->entry_type != IRT_IOSAPIC_TYPE) {
0399 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type);
0400 continue;
0401 }
0402
0403 if (i->entry_length != IRT_IOSAPIC_LENGTH) {
0404 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length);
0405 continue;
0406 }
0407
0408 if (i->interrupt_type != IRT_VECTORED_INTR) {
0409 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type);
0410 continue;
0411 }
0412
0413 if (!COMPARE_IRTE_ADDR(i, isi->isi_hpa))
0414 continue;
0415
0416 if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
0417 continue;
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 return i;
0428 }
0429
0430 printk(KERN_WARNING MODULE_NAME ": 0x%lx : no IRT entry for slot %d, pin %d\n",
0431 isi->isi_hpa, slot, intr_pin);
0432 return NULL;
0433 }
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450 static struct irt_entry *
0451 iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
0452 {
0453 u8 intr_pin, intr_slot;
0454
0455 pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
0456
0457 DBG_IRT("iosapic_xlate_pin(%s) SLOT %d pin %d\n",
0458 pcidev->slot_name, PCI_SLOT(pcidev->devfn), intr_pin);
0459
0460 if (intr_pin == 0) {
0461
0462 return NULL;
0463 }
0464
0465
0466 if (pcidev->bus->parent) {
0467
0468
0469
0470 #ifdef PCI_BRIDGE_FUNCS
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480 if (pci_bridge_funcs->xlate_intr_line) {
0481 intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev);
0482 }
0483 #else
0484 struct pci_bus *p = pcidev->bus;
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498 intr_pin = pci_swizzle_interrupt_pin(pcidev, intr_pin);
0499 #endif
0500
0501
0502
0503
0504 while (p->parent->parent)
0505 p = p->parent;
0506
0507 intr_slot = PCI_SLOT(p->self->devfn);
0508 } else {
0509 intr_slot = PCI_SLOT(pcidev->devfn);
0510 }
0511 DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n",
0512 pcidev->bus->busn_res.start, intr_slot, intr_pin);
0513
0514 return irt_find_irqline(isi, intr_slot, intr_pin);
0515 }
0516
0517 static void iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)
0518 {
0519 struct iosapic_info *isp = vi->iosapic;
0520 u8 idx = vi->irqline;
0521
0522 *dp0 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY(idx));
0523 *dp1 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY_HI(idx));
0524 }
0525
0526
0527 static void iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1)
0528 {
0529 struct iosapic_info *isp = vi->iosapic;
0530
0531 DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %lx 0x%x 0x%x\n",
0532 vi->irqline, isp->isi_hpa, dp0, dp1);
0533
0534 iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY(vi->irqline), dp0);
0535
0536
0537 dp0 = readl(isp->addr+IOSAPIC_REG_WINDOW);
0538
0539 iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY_HI(vi->irqline), dp1);
0540
0541
0542 dp1 = readl(isp->addr+IOSAPIC_REG_WINDOW);
0543 }
0544
0545
0546
0547
0548
0549
0550 static void
0551 iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
0552 {
0553 u32 mode = 0;
0554 struct irt_entry *p = vi->irte;
0555
0556 if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
0557 mode |= IOSAPIC_IRDT_PO_LOW;
0558
0559 if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG)
0560 mode |= IOSAPIC_IRDT_LEVEL_TRIG;
0561
0562
0563
0564
0565
0566
0567 *dp0 = mode | (u32) vi->txn_data;
0568
0569
0570
0571
0572
0573 if (is_pdc_pat()) {
0574
0575
0576
0577
0578 *dp1 = (u32) (vi->txn_addr);
0579 } else {
0580
0581
0582
0583
0584
0585
0586
0587 *dp1 = (((u32)vi->txn_addr & 0x0ff00000) >> 4) |
0588 (((u32)vi->txn_addr & 0x000ff000) << 12);
0589 }
0590 DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1);
0591 }
0592
0593
0594 static void iosapic_mask_irq(struct irq_data *d)
0595 {
0596 unsigned long flags;
0597 struct vector_info *vi = irq_data_get_irq_chip_data(d);
0598 u32 d0, d1;
0599
0600 spin_lock_irqsave(&iosapic_lock, flags);
0601 iosapic_rd_irt_entry(vi, &d0, &d1);
0602 d0 |= IOSAPIC_IRDT_ENABLE;
0603 iosapic_wr_irt_entry(vi, d0, d1);
0604 spin_unlock_irqrestore(&iosapic_lock, flags);
0605 }
0606
0607 static void iosapic_unmask_irq(struct irq_data *d)
0608 {
0609 struct vector_info *vi = irq_data_get_irq_chip_data(d);
0610 u32 d0, d1;
0611
0612
0613 WARN_ON(vi->txn_irq == 0);
0614
0615 iosapic_set_irt_data(vi, &d0, &d1);
0616 iosapic_wr_irt_entry(vi, d0, d1);
0617
0618 #ifdef DEBUG_IOSAPIC_IRT
0619 {
0620 u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL);
0621 printk("iosapic_enable_irq(): regs %p", vi->eoi_addr);
0622 for ( ; t < vi->eoi_addr; t++)
0623 printk(" %x", readl(t));
0624 printk("\n");
0625 }
0626
0627 printk("iosapic_enable_irq(): sel ");
0628 {
0629 struct iosapic_info *isp = vi->iosapic;
0630
0631 for (d0=0x10; d0<0x1e; d0++) {
0632 d1 = iosapic_read(isp->addr, d0);
0633 printk(" %x", d1);
0634 }
0635 }
0636 printk("\n");
0637 #endif
0638
0639
0640
0641
0642
0643
0644
0645 DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq,
0646 vi->eoi_addr, vi->eoi_data);
0647 iosapic_eoi(vi->eoi_addr, vi->eoi_data);
0648 }
0649
0650 static void iosapic_eoi_irq(struct irq_data *d)
0651 {
0652 struct vector_info *vi = irq_data_get_irq_chip_data(d);
0653
0654 iosapic_eoi(vi->eoi_addr, vi->eoi_data);
0655 cpu_eoi_irq(d);
0656 }
0657
0658 #ifdef CONFIG_SMP
0659 static int iosapic_set_affinity_irq(struct irq_data *d,
0660 const struct cpumask *dest, bool force)
0661 {
0662 struct vector_info *vi = irq_data_get_irq_chip_data(d);
0663 u32 d0, d1, dummy_d0;
0664 unsigned long flags;
0665 int dest_cpu;
0666
0667 dest_cpu = cpu_check_affinity(d, dest);
0668 if (dest_cpu < 0)
0669 return -1;
0670
0671 irq_data_update_affinity(d, cpumask_of(dest_cpu));
0672 vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu);
0673
0674 spin_lock_irqsave(&iosapic_lock, flags);
0675
0676
0677 iosapic_rd_irt_entry(vi, &d0, &d1);
0678 iosapic_set_irt_data(vi, &dummy_d0, &d1);
0679 iosapic_wr_irt_entry(vi, d0, d1);
0680 spin_unlock_irqrestore(&iosapic_lock, flags);
0681
0682 return 0;
0683 }
0684 #endif
0685
0686 static struct irq_chip iosapic_interrupt_type = {
0687 .name = "IO-SAPIC-level",
0688 .irq_unmask = iosapic_unmask_irq,
0689 .irq_mask = iosapic_mask_irq,
0690 .irq_ack = cpu_ack_irq,
0691 .irq_eoi = iosapic_eoi_irq,
0692 #ifdef CONFIG_SMP
0693 .irq_set_affinity = iosapic_set_affinity_irq,
0694 #endif
0695 };
0696
0697 int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
0698 {
0699 struct iosapic_info *isi = isi_obj;
0700 struct irt_entry *irte = NULL;
0701 struct vector_info *vi;
0702 int isi_line;
0703
0704 if (!isi) {
0705 printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
0706 pci_name(pcidev));
0707 return -1;
0708 }
0709
0710 #ifdef CONFIG_SUPERIO
0711
0712
0713
0714
0715
0716
0717
0718
0719 if (is_superio_device(pcidev)) {
0720
0721 pcidev->irq = superio_fixup_irq(pcidev);
0722
0723
0724 if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN)
0725 return pcidev->irq;
0726 }
0727 #endif
0728
0729
0730 irte = iosapic_xlate_pin(isi, pcidev);
0731 if (!irte) {
0732 printk("iosapic: no IRTE for %s (IRQ not connected?)\n",
0733 pci_name(pcidev));
0734 return -1;
0735 }
0736 DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
0737 irte,
0738 irte->entry_type,
0739 irte->entry_length,
0740 irte->polarity_trigger,
0741 irte->src_bus_irq_devno,
0742 irte->src_bus_id,
0743 irte->src_seg_id,
0744 irte->dest_iosapic_intin,
0745 (u32) irte->dest_iosapic_addr);
0746 isi_line = irte->dest_iosapic_intin;
0747
0748
0749 vi = isi->isi_vector + isi_line;
0750 DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi);
0751
0752
0753 if (vi->irte)
0754 goto out;
0755
0756 vi->irte = irte;
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767 vi->txn_irq = txn_alloc_irq(8);
0768
0769 if (vi->txn_irq < 0)
0770 panic("I/O sapic: couldn't get TXN IRQ\n");
0771
0772
0773 vi->txn_addr = txn_alloc_addr(vi->txn_irq);
0774 vi->txn_data = txn_alloc_data(vi->txn_irq);
0775
0776 vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI;
0777 vi->eoi_data = cpu_to_le32(vi->txn_data);
0778
0779 cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi);
0780
0781 out:
0782 pcidev->irq = vi->txn_irq;
0783
0784 DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
0785 PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn),
0786 pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
0787
0788 return pcidev->irq;
0789 }
0790
0791 static struct iosapic_info *iosapic_list;
0792
0793 #ifdef CONFIG_64BIT
0794 int iosapic_serial_irq(struct parisc_device *dev)
0795 {
0796 struct iosapic_info *isi;
0797 struct irt_entry *irte;
0798 struct vector_info *vi;
0799 int cnt;
0800 int intin;
0801
0802 intin = (dev->mod_info >> 24) & 15;
0803
0804
0805 for (cnt = 0; cnt < irt_num_entry; cnt++) {
0806 irte = &irt_cell[cnt];
0807 if (COMPARE_IRTE_ADDR(irte, dev->mod0) &&
0808 irte->dest_iosapic_intin == intin)
0809 break;
0810 }
0811 if (cnt >= irt_num_entry)
0812 return 0;
0813
0814 DBG_IRT("iosapic_serial_irq(): irte %p %x %x %x %x %x %x %x %x\n",
0815 irte,
0816 irte->entry_type,
0817 irte->entry_length,
0818 irte->polarity_trigger,
0819 irte->src_bus_irq_devno,
0820 irte->src_bus_id,
0821 irte->src_seg_id,
0822 irte->dest_iosapic_intin,
0823 (u32) irte->dest_iosapic_addr);
0824
0825
0826 for (isi = iosapic_list; isi; isi = isi->isi_next)
0827 if (isi->isi_hpa == dev->mod0)
0828 break;
0829 if (!isi)
0830 return 0;
0831
0832
0833 vi = isi->isi_vector + intin;
0834 DBG_IRT("iosapic_serial_irq: line %d vi 0x%p\n", iosapic_intin, vi);
0835
0836
0837 if (vi->irte)
0838 goto out;
0839
0840 vi->irte = irte;
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851 vi->txn_irq = txn_alloc_irq(8);
0852
0853 if (vi->txn_irq < 0)
0854 panic("I/O sapic: couldn't get TXN IRQ\n");
0855
0856
0857 vi->txn_addr = txn_alloc_addr(vi->txn_irq);
0858 vi->txn_data = txn_alloc_data(vi->txn_irq);
0859
0860 vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI;
0861 vi->eoi_data = cpu_to_le32(vi->txn_data);
0862
0863 cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi);
0864
0865 out:
0866
0867 return vi->txn_irq;
0868 }
0869 #endif
0870
0871
0872
0873
0874
0875 static unsigned int
0876 iosapic_rd_version(struct iosapic_info *isi)
0877 {
0878 return iosapic_read(isi->addr, IOSAPIC_REG_VERSION);
0879 }
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892 void *iosapic_register(unsigned long hpa)
0893 {
0894 struct iosapic_info *isi = NULL;
0895 struct irt_entry *irte = irt_cell;
0896 struct vector_info *vip;
0897 int cnt;
0898
0899
0900
0901
0902
0903
0904 for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
0905 WARN_ON(IRT_IOSAPIC_TYPE != irte->entry_type);
0906 if (COMPARE_IRTE_ADDR(irte, hpa))
0907 break;
0908 }
0909
0910 if (cnt >= irt_num_entry) {
0911 DBG("iosapic_register() ignoring 0x%lx (NOT FOUND)\n", hpa);
0912 return NULL;
0913 }
0914
0915 isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
0916 if (!isi) {
0917 BUG();
0918 return NULL;
0919 }
0920
0921 isi->addr = ioremap(hpa, 4096);
0922 isi->isi_hpa = hpa;
0923 isi->isi_version = iosapic_rd_version(isi);
0924 isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
0925
0926 vip = isi->isi_vector = kcalloc(isi->isi_num_vectors,
0927 sizeof(struct vector_info), GFP_KERNEL);
0928 if (vip == NULL) {
0929 kfree(isi);
0930 return NULL;
0931 }
0932
0933 for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
0934 vip->irqline = (unsigned char) cnt;
0935 vip->iosapic = isi;
0936 }
0937 isi->isi_next = iosapic_list;
0938 iosapic_list = isi;
0939 return isi;
0940 }
0941
0942
0943 #ifdef DEBUG_IOSAPIC
0944
0945 static void
0946 iosapic_prt_irt(void *irt, long num_entry)
0947 {
0948 unsigned int i, *irp = (unsigned int *) irt;
0949
0950
0951 printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
0952
0953 for (i=0; i<num_entry; i++, irp += 4) {
0954 printk(KERN_DEBUG "%p : %2d %.8x %.8x %.8x %.8x\n",
0955 irp, i, irp[0], irp[1], irp[2], irp[3]);
0956 }
0957 }
0958
0959
0960 static void
0961 iosapic_prt_vi(struct vector_info *vi)
0962 {
0963 printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi);
0964 printk(KERN_DEBUG "\t\tstatus: %.4x\n", vi->status);
0965 printk(KERN_DEBUG "\t\ttxn_irq: %d\n", vi->txn_irq);
0966 printk(KERN_DEBUG "\t\ttxn_addr: %lx\n", vi->txn_addr);
0967 printk(KERN_DEBUG "\t\ttxn_data: %lx\n", vi->txn_data);
0968 printk(KERN_DEBUG "\t\teoi_addr: %p\n", vi->eoi_addr);
0969 printk(KERN_DEBUG "\t\teoi_data: %x\n", vi->eoi_data);
0970 }
0971
0972
0973 static void
0974 iosapic_prt_isi(struct iosapic_info *isi)
0975 {
0976 printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
0977 printk(KERN_DEBUG "\t\tisi_hpa: %lx\n", isi->isi_hpa);
0978 printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status);
0979 printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version);
0980 printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector);
0981 }
0982 #endif