static void xlp_post_ithread(void *source) { struct xlp_intrsrc *src = source; nlm_pic_ack(xlp_pic_base, xlp_irq_to_irt(src->irq)); }
/* * XLP8XX/4XX/3XX/2XX: * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X * interrupts generated by the PIC and each of these correspond to a MSI-X * vector (0-31) that can be assigned. * * We divide the MSI-X vectors to 8 per link and do a per-link allocation * * XLP9XX: * 32 MSI-X vectors are available per link, and the interrupts are not routed * thru the PIC. PIC ack not needed. * * Enable and disable done using standard MSI functions. */ static void xlp_msix_mask_ack(struct irq_data *d) { struct xlp_msi_data *md; int link, msixvec; uint32_t status_reg, bit; msixvec = nlm_irq_msixvec(d->irq); link = nlm_irq_msixlink(msixvec); mask_msi_irq(d); md = irq_data_get_irq_handler_data(d); /* Ack MSI on bridge */ if (cpu_is_xlp9xx()) { status_reg = PCIE_9XX_MSIX_STATUSX(link); bit = msixvec % XLP_MSIXVEC_PER_LINK; } else { status_reg = PCIE_MSIX_STATUS; bit = msixvec; } nlm_write_reg(md->lnkbase, status_reg, 1u << bit); /* Ack at eirr and PIC */ ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); if (!cpu_is_xlp9xx()) nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec)); }
static void xlp_post_filter(void *source) { struct xlp_intrsrc *src = source; if (src->busack) src->busack(src->irq); nlm_pic_ack(xlp_pic_base, xlp_irq_to_irt(src->irq)); }
static void xlp_msi_mask_ack(struct irq_data *d) { struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); int link, vec; link = nlm_irq_msilink(d->irq); vec = nlm_irq_msivec(d->irq); xlp_msi_disable(d); /* Ack MSI on bridge */ if (cpu_is_xlp9xx()) nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec); else nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); /* Ack at eirr and PIC */ ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); if (cpu_is_xlp9xx()) nlm_pic_ack(md->node->picbase, PIC_9XX_IRT_PCIE_LINK_INDEX(link)); else nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); }
static void xlp_pic_unmask(struct irq_data *d) { void *hd = irq_data_get_irq_handler_data(d); int irt; irt = nlm_irq_to_irt(d->irq); if (irt == -1) return; if (hd) { void (*extra_ack)(void *) = hd; extra_ack(d); } /* Ack is a single write, no need to lock */ nlm_pic_ack(nlm_pic_base, irt); }