static int px_enable_err_intr(px_t *px_p) { /* Add FMA Callback handler for failed PIO Loads */ px_fm_cb_enable(px_p); /* Add Common Block mondo handler */ if (px_cb_add_intr(&px_p->px_cb_fault) != DDI_SUCCESS) goto cb_bad; /* Add PEU Block Mondo Handler */ if (px_err_add_intr(&px_p->px_fault) != DDI_SUCCESS) goto peu_bad; /* Enable interrupt handler for PCIE Fabric Error Messages */ if (px_pec_msg_add_intr(px_p) != DDI_SUCCESS) goto msg_bad; return (DDI_SUCCESS); msg_bad: px_err_rem_intr(&px_p->px_fault); peu_bad: px_cb_rem_intr(&px_p->px_cb_fault); cb_bad: px_fm_cb_disable(px_p); return (DDI_FAILURE); }
int px_pec_attach(px_t *px_p) { px_pec_t *pec_p; int i, len; int nrange = px_p->px_ranges_length / sizeof (px_ranges_t); dev_info_t *dip = px_p->px_dip; px_ranges_t *rangep = px_p->px_ranges_p; int ret; /* * Allocate a state structure for the PEC and cross-link it * to its per px node state structure. */ pec_p = kmem_zalloc(sizeof (px_pec_t), KM_SLEEP); px_p->px_pec_p = pec_p; pec_p->pec_px_p = px_p; len = snprintf(pec_p->pec_nameinst_str, sizeof (pec_p->pec_nameinst_str), "%s%d", NAMEINST(dip)); pec_p->pec_nameaddr_str = pec_p->pec_nameinst_str + ++len; (void) snprintf(pec_p->pec_nameaddr_str, sizeof (pec_p->pec_nameinst_str) - len, "%s@%s", NAMEADDR(dip)); /* * Add interrupt handlers to process correctable/fatal/non fatal * PCIE messages. */ if ((ret = px_pec_msg_add_intr(px_p)) != DDI_SUCCESS) { px_pec_msg_rem_intr(px_p); return (ret); } /* * Get this pec's mem32 and mem64 segments to determine whether * a dma object originates from ths pec. i.e. dev to dev dma */ for (i = 0; i < nrange; i++, rangep++) { uint64_t rng_addr, rng_size, *pfnbp, *pfnlp; uint32_t rng_type = rangep->child_high & PCI_ADDR_MASK; switch (rng_type) { case PCI_ADDR_MEM32: pfnbp = &pec_p->pec_base32_pfn; pfnlp = &pec_p->pec_last32_pfn; break; case PCI_ADDR_MEM64: pfnbp = &pec_p->pec_base64_pfn; pfnlp = &pec_p->pec_last64_pfn; break; case PCI_ADDR_CONFIG: case PCI_ADDR_IO: default: continue; } rng_addr = (uint64_t)(rangep->parent_high & px_ranges_phi_mask) << 32; rng_addr |= (uint64_t)rangep->parent_low; rng_size = (uint64_t)rangep->size_high << 32; rng_size |= (uint64_t)rangep->size_low; *pfnbp = mmu_btop(rng_addr); *pfnlp = mmu_btop(rng_addr + rng_size); } mutex_init(&pec_p->pec_pokefault_mutex, NULL, MUTEX_DRIVER, (void *)px_p->px_fm_ibc); return (DDI_SUCCESS); }