void __init init_nlm_common_irqs(void) { int i, irq, irt; for (i = 0; i < PIC_IRT_FIRST_IRQ; i++) irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq); for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ ; i++) irq_set_chip_and_handler(i, &xlp_pic, handle_level_irq); #ifdef CONFIG_SMP irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr, nlm_smp_function_ipi_handler); irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr, nlm_smp_resched_ipi_handler); nlm_irq_mask |= ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE)); #endif for (irq = PIC_IRT_FIRST_IRQ; irq <= PIC_IRT_LAST_IRQ; irq++) { irt = nlm_irq_to_irt(irq); if (irt == -1) continue; nlm_irq_mask |= (1ULL << irq); nlm_pic_init_irt(nlm_pic_base, irt, irq, 0); } nlm_irq_mask |= (1ULL << IRQ_TIMER); }
/* * Allocate a MSI vector on a link */ static int xlp_setup_msi(uint64_t lnkbase, int node, int link, struct msi_desc *desc) { struct xlp_msi_data *md; struct msi_msg msg; unsigned long flags; int msivec, irt, lirq, xirq, ret; uint64_t msiaddr; /* Get MSI data for the link */ lirq = PIC_PCIE_LINK_MSI_IRQ(link); xirq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); md = irq_get_handler_data(xirq); msiaddr = MSI_LINK_ADDR(node, link); spin_lock_irqsave(&md->msi_lock, flags); if (md->msi_alloc_mask == 0) { xlp_config_link_msi(lnkbase, lirq, msiaddr); /* switch the link IRQ to MSI range */ if (cpu_is_xlp9xx()) irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link); else irt = PIC_IRT_PCIE_LINK_INDEX(link); nlm_setup_pic_irq(node, lirq, lirq, irt); nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, node * nlm_threads_per_node(), 1 /*en */); } /* allocate a MSI vec, and tell the bridge about it */ msivec = fls(md->msi_alloc_mask); if (msivec == XLP_MSIVEC_PER_LINK) { spin_unlock_irqrestore(&md->msi_lock, flags); return -ENOMEM; } md->msi_alloc_mask |= (1u << msivec); spin_unlock_irqrestore(&md->msi_lock, flags); msg.address_hi = msiaddr >> 32; msg.address_lo = msiaddr & 0xffffffff; msg.data = 0xc00 | msivec; xirq = xirq + msivec; /* msi mapped to global irq space */ ret = irq_set_msi_desc(xirq, desc); if (ret < 0) return ret; write_msi_msg(xirq, &msg); return 0; }