static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger, int polarity) { #ifdef CONFIG_X86_MPPARSE struct mpc_intsrc mp_irq; struct pci_dev *pdev; unsigned char number; unsigned int devfn; int ioapic; u8 pin; if (!acpi_ioapic) return 0; if (!dev || !dev_is_pci(dev)) return 0; pdev = to_pci_dev(dev); number = pdev->bus->number; devfn = pdev->devfn; pin = pdev->pin; /* print the entry should happen on mptable identically */ mp_irq.type = MP_INTSRC; mp_irq.irqtype = mp_INT; mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) | (polarity == ACPI_ACTIVE_HIGH ? 1 : 3); mp_irq.srcbus = number; mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); ioapic = mp_find_ioapic(gsi); mp_irq.dstapic = mpc_ioapic_id(ioapic); mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); mp_save_irq(&mp_irq); #endif return 0; }
/* Propagate PCI IRQ# */ static int vlv2_pci_enable_irq(struct pci_dev *pdev) { u8 ir_val, dev; void __iomem *ilb_mem; struct io_apic_irq_attr irq_attr; ilb_mem = ioremap_nocache(ILB_BASE, ILB_SIZE); if (ilb_mem == NULL) { pr_err("%s(): can't map ILB_BASE(0x%x)\n", __func__, ILB_BASE); return -EIO; } dev = PCI_DEV_NUM(pdev->devfn); ir_val = ioread8(ilb_mem + ILB_IR + PCI_DEV_NUM(pdev->devfn) * 2); iounmap(ilb_mem); /* map INTA# only */ pdev->irq = PIRQ2IRQ(IR_INTA(ir_val)); pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq); irq_attr.ioapic = mp_find_ioapic(pdev->irq); irq_attr.ioapic_pin = pdev->irq; irq_attr.trigger = 1; /* level */ irq_attr.polarity = 1; /* active low */ io_apic_set_pci_routing(&pdev->dev, pdev->irq, &irq_attr); return 0; }
static int __init mp_register_ioapic_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) { struct mpc_intsrc mp_irq; int ioapic, pin; /* Convert 'gsi' to 'ioapic.pin'(INTIN#) */ ioapic = mp_find_ioapic(gsi); if (ioapic < 0) { pr_warn("Failed to find ioapic for gsi : %u\n", gsi); return ioapic; } pin = mp_find_ioapic_pin(ioapic, gsi); mp_irq.type = MP_INTSRC; mp_irq.irqtype = mp_INT; mp_irq.irqflag = (trigger << 2) | polarity; mp_irq.srcbus = MP_ISA_BUS; mp_irq.srcbusirq = bus_irq; mp_irq.dstapic = mpc_ioapic_id(ioapic); mp_irq.dstirq = pin; mp_save_irq(&mp_irq); return 0; }
static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) { int ioapic; int pin; struct mpc_intsrc mp_irq; /* * Check bus_irq boundary. */ if (bus_irq >= NR_IRQS_LEGACY) { pr_warn("Invalid bus_irq %u for legacy override\n", bus_irq); return; } /* * Convert 'gsi' to 'ioapic.pin'. */ ioapic = mp_find_ioapic(gsi); if (ioapic < 0) return; pin = mp_find_ioapic_pin(ioapic, gsi); /* * TBD: This check is for faulty timer entries, where the override * erroneously sets the trigger to level, resulting in a HUGE * increase of timer interrupts! */ if ((bus_irq == 0) && (trigger == 3)) trigger = 1; mp_irq.type = MP_INTSRC; mp_irq.irqtype = mp_INT; mp_irq.irqflag = (trigger << 2) | polarity; mp_irq.srcbus = MP_ISA_BUS; mp_irq.srcbusirq = bus_irq; /* IRQ */ mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */ mp_irq.dstirq = pin; /* INTIN# */ mp_save_irq(&mp_irq); /* * Reset default identity mapping if gsi is also an legacy IRQ, * otherwise there will be more than one entry with the same GSI * and acpi_isa_irq_to_gsi() may give wrong result. */ if (gsi < nr_legacy_irqs() && isa_irq_to_gsi[gsi] == gsi) isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI; isa_irq_to_gsi[bus_irq] = gsi; }
static inline int byt_program_ioapic(int irq, int trigger, int polarity) { struct io_apic_irq_attr irq_attr; int ioapic; ioapic = mp_find_ioapic(irq); if (ioapic < 0) return -EINVAL; irq_attr.ioapic = ioapic; irq_attr.ioapic_pin = irq; irq_attr.trigger = trigger; irq_attr.polarity = polarity; return io_apic_set_pci_routing(NULL, irq, &irq_attr); }
static int handle_mrfl_dev_ioapic(int irq) { int ret = 0; int ioapic; struct io_apic_irq_attr irq_attr; ioapic = mp_find_ioapic(irq); if (ioapic >= 0) { irq_attr.ioapic = ioapic; irq_attr.ioapic_pin = irq; irq_attr.trigger = 1; irq_attr.polarity = 0; /* Active high */ io_apic_set_pci_routing(NULL, irq, &irq_attr); } else { pr_warn("can not find interrupt %d in ioapic\n", irq); ret = -EINVAL; } return ret; }