17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 500d0963fSdilpreet * Common Development and Distribution License (the "License"). 600d0963fSdilpreet * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 2200d0963fSdilpreet * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * PCI PBM implementation: 307c478bd9Sstevel@tonic-gate * initialization 317c478bd9Sstevel@tonic-gate * Bus error interrupt handler 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 367c478bd9Sstevel@tonic-gate #include <sys/spl.h> 377c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 387c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 397c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h> 407c478bd9Sstevel@tonic-gate #include <sys/fm/util.h> 417c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> /* ldphysio() */ 427c478bd9Sstevel@tonic-gate #include <sys/async.h> 437c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 447c478bd9Sstevel@tonic-gate #include <sys/ontrap.h> 457c478bd9Sstevel@tonic-gate #include <sys/pci/pci_obj.h> 467c478bd9Sstevel@tonic-gate #include <sys/membar.h> 477c478bd9Sstevel@tonic-gate #include <sys/ivintr.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static uint_t pbm_error_intr(caddr_t a); 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* The nexus interrupt priority values */ 547c478bd9Sstevel@tonic-gate int pci_pil[] = {14, 14, 14, 14, 14, 14}; 557c478bd9Sstevel@tonic-gate void 567c478bd9Sstevel@tonic-gate pbm_create(pci_t *pci_p) 577c478bd9Sstevel@tonic-gate { 587c478bd9Sstevel@tonic-gate pbm_t *pbm_p; 597c478bd9Sstevel@tonic-gate int i, len; 607c478bd9Sstevel@tonic-gate int nrange = pci_p->pci_ranges_length / sizeof (pci_ranges_t); 617c478bd9Sstevel@tonic-gate dev_info_t *dip = pci_p->pci_dip; 627c478bd9Sstevel@tonic-gate pci_ranges_t *rangep = pci_p->pci_ranges; 637c478bd9Sstevel@tonic-gate uint64_t base_addr, last_addr; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #ifdef lint 667c478bd9Sstevel@tonic-gate dip = dip; 677c478bd9Sstevel@tonic-gate #endif 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * Allocate a state structure for the PBM and cross-link it 717c478bd9Sstevel@tonic-gate * to its per pci node state structure. 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate pbm_p = (pbm_t *)kmem_zalloc(sizeof (pbm_t), KM_SLEEP); 747c478bd9Sstevel@tonic-gate pci_p->pci_pbm_p = pbm_p; 757c478bd9Sstevel@tonic-gate pbm_p->pbm_pci_p = pci_p; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate len = snprintf(pbm_p->pbm_nameinst_str, 787c478bd9Sstevel@tonic-gate sizeof (pbm_p->pbm_nameinst_str), 797c478bd9Sstevel@tonic-gate "%s%d", NAMEINST(dip)); 807c478bd9Sstevel@tonic-gate pbm_p->pbm_nameaddr_str = pbm_p->pbm_nameinst_str + ++len; 817c478bd9Sstevel@tonic-gate (void) snprintf(pbm_p->pbm_nameaddr_str, 827c478bd9Sstevel@tonic-gate sizeof (pbm_p->pbm_nameinst_str) - len, 837c478bd9Sstevel@tonic-gate "%s@%s", NAMEADDR(dip)); 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate pci_pbm_setup(pbm_p); 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * Get this pbm's mem32 and mem64 segments to determine whether 897c478bd9Sstevel@tonic-gate * a dma object originates from ths pbm. i.e. dev to dev dma 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate /* Init all of our boundaries */ 927c478bd9Sstevel@tonic-gate base_addr = -1ull; 937c478bd9Sstevel@tonic-gate last_addr = 0ull; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate for (i = 0; i < nrange; i++, rangep++) { 967c478bd9Sstevel@tonic-gate uint32_t rng_type = rangep->child_high & PCI_ADDR_MASK; 977c478bd9Sstevel@tonic-gate if (rng_type == PCI_ADDR_MEM32 || rng_type == PCI_ADDR_MEM64) { 987c478bd9Sstevel@tonic-gate uint64_t rng_addr, rng_size; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate rng_addr = (uint64_t)rangep->parent_high << 32; 1017c478bd9Sstevel@tonic-gate rng_addr |= (uint64_t)rangep->parent_low; 1027c478bd9Sstevel@tonic-gate rng_size = (uint64_t)rangep->size_high << 32; 1037c478bd9Sstevel@tonic-gate rng_size |= (uint64_t)rangep->size_low; 1047c478bd9Sstevel@tonic-gate base_addr = MIN(rng_addr, base_addr); 1057c478bd9Sstevel@tonic-gate last_addr = MAX(rng_addr + rng_size, last_addr); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate pbm_p->pbm_base_pfn = mmu_btop(base_addr); 1097c478bd9Sstevel@tonic-gate pbm_p->pbm_last_pfn = mmu_btop(last_addr); 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate DEBUG4(DBG_ATTACH, dip, 1127c478bd9Sstevel@tonic-gate "pbm_create: ctrl=%x, afsr=%x, afar=%x, diag=%x\n", 1137c478bd9Sstevel@tonic-gate pbm_p->pbm_ctrl_reg, pbm_p->pbm_async_flt_status_reg, 1147c478bd9Sstevel@tonic-gate pbm_p->pbm_async_flt_addr_reg, pbm_p->pbm_diag_reg); 1157c478bd9Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_create: conf=%x\n", 1167c478bd9Sstevel@tonic-gate pbm_p->pbm_config_header); 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * Register a function to disable pbm error interrupts during a panic. 1207c478bd9Sstevel@tonic-gate */ 1217c478bd9Sstevel@tonic-gate bus_func_register(BF_TYPE_ERRDIS, 1227c478bd9Sstevel@tonic-gate (busfunc_t)pbm_disable_pci_errors, pbm_p); 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * create the interrupt-priorities property if it doesn't 1267c478bd9Sstevel@tonic-gate * already exist to provide a hint as to the PIL level for 1277c478bd9Sstevel@tonic-gate * our interrupt. 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate if (ddi_getproplen(DDI_DEV_T_ANY, dip, 1307c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "interrupt-priorities", 1317c478bd9Sstevel@tonic-gate &len) != DDI_PROP_SUCCESS) { 1327c478bd9Sstevel@tonic-gate /* Create the interrupt-priorities property. */ 1337c478bd9Sstevel@tonic-gate (void) ddi_prop_create(DDI_DEV_T_NONE, dip, 1347c478bd9Sstevel@tonic-gate DDI_PROP_CANSLEEP, "interrupt-priorities", 1357c478bd9Sstevel@tonic-gate (caddr_t)pci_pil, sizeof (pci_pil)); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate pbm_configure(pbm_p); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * Determine if we need to apply the Sun Fire 15k AXQ/PIO 1427c478bd9Sstevel@tonic-gate * workaround. 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate pci_axq_pio_limit(pbm_p); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate int 1487c478bd9Sstevel@tonic-gate pbm_register_intr(pbm_t *pbm_p) 1497c478bd9Sstevel@tonic-gate { 1507c478bd9Sstevel@tonic-gate pci_t *pci_p = pbm_p->pbm_pci_p; 1517c478bd9Sstevel@tonic-gate uint32_t mondo; 1527c478bd9Sstevel@tonic-gate int r = DDI_SUCCESS; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate ib_nintr_clear(pci_p->pci_ib_p, pci_p->pci_inos[CBNINTR_PBM]); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * Install the PCI error interrupt handler. 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate mondo = IB_INO_TO_MONDO(pci_p->pci_ib_p, pci_p->pci_inos[CBNINTR_PBM]); 1607c478bd9Sstevel@tonic-gate mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo); 1617c478bd9Sstevel@tonic-gate 162*b0fc0e77Sgovinda VERIFY(add_ivintr(mondo, pci_pil[CBNINTR_PBM], (intrfunc)pbm_error_intr, 163*b0fc0e77Sgovinda (caddr_t)pci_p, NULL, NULL) == 0); 1647c478bd9Sstevel@tonic-gate 165f47a9c50Smathue pbm_p->pbm_iblock_cookie = (void *)(uintptr_t)pci_pil[CBNINTR_PBM]; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * Create the pokefault mutex at the PIL below the error interrupt. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate mutex_init(&pbm_p->pbm_pokefault_mutex, NULL, MUTEX_DRIVER, 171f47a9c50Smathue (void *)(uintptr_t)ipltospl(spltoipl( 172f47a9c50Smathue (int)(uintptr_t)pbm_p->pbm_iblock_cookie) - 1)); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if (!r) 1757c478bd9Sstevel@tonic-gate r = pci_pbm_add_intr(pci_p); 1767c478bd9Sstevel@tonic-gate return (PCI_ATTACH_RETCODE(PCI_PBM_OBJ, PCI_OBJ_INTR_ADD, r)); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate void 1807c478bd9Sstevel@tonic-gate pbm_destroy(pci_t *pci_p) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p; 1837c478bd9Sstevel@tonic-gate ib_t *ib_p = pci_p->pci_ib_p; 1847c478bd9Sstevel@tonic-gate uint32_t mondo; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate DEBUG0(DBG_DETACH, pci_p->pci_dip, "pbm_destroy:\n"); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate mondo = IB_INO_TO_MONDO(pci_p->pci_ib_p, pci_p->pci_inos[CBNINTR_PBM]); 1897c478bd9Sstevel@tonic-gate mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo); 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * Free the pokefault mutex. 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate mutex_destroy(&pbm_p->pbm_pokefault_mutex); 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* 1977c478bd9Sstevel@tonic-gate * Remove the error interrupt and consistent dma sync handler. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate intr_dist_rem(pbm_intr_dist, pbm_p); 2007c478bd9Sstevel@tonic-gate pci_pbm_rem_intr(pci_p); 2017c478bd9Sstevel@tonic-gate ib_intr_disable(ib_p, pci_p->pci_inos[CBNINTR_PBM], IB_INTR_WAIT); 202*b0fc0e77Sgovinda VERIFY(rem_ivintr(mondo, pci_pil[CBNINTR_PBM]) == 0); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * Remove the error disable function. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate bus_func_unregister(BF_TYPE_ERRDIS, 2087c478bd9Sstevel@tonic-gate (busfunc_t)pbm_disable_pci_errors, pbm_p); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate pci_pbm_teardown(pbm_p); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* 2137c478bd9Sstevel@tonic-gate * Free the pbm state structure. 2147c478bd9Sstevel@tonic-gate */ 2157c478bd9Sstevel@tonic-gate kmem_free(pbm_p, sizeof (pbm_t)); 2167c478bd9Sstevel@tonic-gate pci_p->pci_pbm_p = NULL; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate static uint_t 2207c478bd9Sstevel@tonic-gate pbm_error_intr(caddr_t a) 2217c478bd9Sstevel@tonic-gate { 2227c478bd9Sstevel@tonic-gate pci_t *pci_p = (pci_t *)a; 2237c478bd9Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p; 2247c478bd9Sstevel@tonic-gate ddi_fm_error_t derr; 2257c478bd9Sstevel@tonic-gate int err = DDI_FM_OK; 2267c478bd9Sstevel@tonic-gate on_trap_data_t *otp = pbm_p->pbm_ontrap_data; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate bzero(&derr, sizeof (ddi_fm_error_t)); 2297c478bd9Sstevel@tonic-gate derr.fme_version = DDI_FME_VERSION; 2307c478bd9Sstevel@tonic-gate mutex_enter(&pci_p->pci_common_p->pci_fm_mutex); 2314fd7ecabSdilpreet if (pbm_p->pbm_excl_handle != NULL) { 2324fd7ecabSdilpreet /* 2334fd7ecabSdilpreet * cautious write protection, protected from all errors. 2344fd7ecabSdilpreet */ 2354fd7ecabSdilpreet ASSERT(MUTEX_HELD(&pbm_p->pbm_pokefault_mutex)); 2364fd7ecabSdilpreet ddi_fm_acc_err_get(pbm_p->pbm_excl_handle, &derr, 2374fd7ecabSdilpreet DDI_FME_VERSION); 2384fd7ecabSdilpreet ASSERT(derr.fme_flag == DDI_FM_ERR_EXPECTED); 2394fd7ecabSdilpreet derr.fme_acc_handle = pbm_p->pbm_excl_handle; 2404fd7ecabSdilpreet err = pci_pbm_err_handler(pci_p->pci_dip, &derr, (void *)pci_p, 2414fd7ecabSdilpreet PCI_INTR_CALL); 2424fd7ecabSdilpreet } else if ((otp != NULL) && (otp->ot_prot & OT_DATA_ACCESS)) { 2437c478bd9Sstevel@tonic-gate /* 2447c478bd9Sstevel@tonic-gate * ddi_poke protection, check nexus and children for 2457c478bd9Sstevel@tonic-gate * expected errors. 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate otp->ot_trap |= OT_DATA_ACCESS; 2487c478bd9Sstevel@tonic-gate membar_sync(); 2497c478bd9Sstevel@tonic-gate derr.fme_flag = DDI_FM_ERR_POKE; 2507c478bd9Sstevel@tonic-gate err = pci_pbm_err_handler(pci_p->pci_dip, &derr, (void *)pci_p, 2517c478bd9Sstevel@tonic-gate PCI_INTR_CALL); 2527c478bd9Sstevel@tonic-gate } else if (pci_check_error(pci_p) != 0) { 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * unprotected error, check for all errors. 2557c478bd9Sstevel@tonic-gate */ 2567c478bd9Sstevel@tonic-gate if (pci_errtrig_pa) 2577c478bd9Sstevel@tonic-gate (void) ldphysio(pci_errtrig_pa); 2587c478bd9Sstevel@tonic-gate derr.fme_flag = DDI_FM_ERR_UNEXPECTED; 2597c478bd9Sstevel@tonic-gate err = pci_pbm_err_handler(pci_p->pci_dip, &derr, (void *)pci_p, 2607c478bd9Sstevel@tonic-gate PCI_INTR_CALL); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (err == DDI_FM_FATAL) { 2647c478bd9Sstevel@tonic-gate if (pci_panic_on_fatal_errors) { 2657c478bd9Sstevel@tonic-gate mutex_exit(&pci_p->pci_common_p->pci_fm_mutex); 2667c478bd9Sstevel@tonic-gate fm_panic("%s-%d: Fatal PCI bus error(s)\n", 2677c478bd9Sstevel@tonic-gate ddi_driver_name(pci_p->pci_dip), 2687c478bd9Sstevel@tonic-gate ddi_get_instance(pci_p->pci_dip)); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate mutex_exit(&pci_p->pci_common_p->pci_fm_mutex); 2737c478bd9Sstevel@tonic-gate ib_nintr_clear(pci_p->pci_ib_p, pci_p->pci_inos[CBNINTR_PBM]); 2747c478bd9Sstevel@tonic-gate return (DDI_INTR_CLAIMED); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate void 2787c478bd9Sstevel@tonic-gate pbm_suspend(pbm_t *pbm_p) 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate pci_t *pci_p = pbm_p->pbm_pci_p; 2817c478bd9Sstevel@tonic-gate ib_ino_t ino = pci_p->pci_inos[CBNINTR_PBM]; 2827c478bd9Sstevel@tonic-gate pbm_p->pbm_imr_save = *ib_intr_map_reg_addr(pci_p->pci_ib_p, ino); 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate pci_pbm_suspend(pci_p); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate void 2887c478bd9Sstevel@tonic-gate pbm_resume(pbm_t *pbm_p) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate pci_t *pci_p = pbm_p->pbm_pci_p; 2917c478bd9Sstevel@tonic-gate ib_ino_t ino = pci_p->pci_inos[CBNINTR_PBM]; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate ib_nintr_clear(pci_p->pci_ib_p, ino); 2947c478bd9Sstevel@tonic-gate *ib_intr_map_reg_addr(pci_p->pci_ib_p, ino) = pbm_p->pbm_imr_save; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate pci_pbm_resume(pci_p); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate void 3007c478bd9Sstevel@tonic-gate pbm_intr_dist(void *arg) 3017c478bd9Sstevel@tonic-gate { 3027c478bd9Sstevel@tonic-gate pbm_t *pbm_p = (pbm_t *)arg; 3037c478bd9Sstevel@tonic-gate pci_t *pci_p = pbm_p->pbm_pci_p; 3047c478bd9Sstevel@tonic-gate ib_t *ib_p = pci_p->pci_ib_p; 3057c478bd9Sstevel@tonic-gate ib_ino_t ino = IB_MONDO_TO_INO(pci_p->pci_inos[CBNINTR_PBM]); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate mutex_enter(&ib_p->ib_intr_lock); 3087c478bd9Sstevel@tonic-gate ib_intr_dist_nintr(ib_p, ino, ib_intr_map_reg_addr(ib_p, ino)); 3097c478bd9Sstevel@tonic-gate pci_pbm_intr_dist(pbm_p); 3107c478bd9Sstevel@tonic-gate mutex_exit(&ib_p->ib_intr_lock); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * Function used to log PBM AFSR register bits and to lookup and fault 3157c478bd9Sstevel@tonic-gate * handle associated with PBM AFAR register. Called by pci_pbm_err_handler with 3167c478bd9Sstevel@tonic-gate * pci_fm_mutex held. 3177c478bd9Sstevel@tonic-gate */ 3187c478bd9Sstevel@tonic-gate int 3197c478bd9Sstevel@tonic-gate pbm_afsr_report(dev_info_t *dip, uint64_t fme_ena, pbm_errstate_t *pbm_err_p) 3207c478bd9Sstevel@tonic-gate { 3217c478bd9Sstevel@tonic-gate int fatal = 0; 3227c478bd9Sstevel@tonic-gate int ret = 0; 3237c478bd9Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 3247c478bd9Sstevel@tonic-gate pci_common_t *cmn_p = pci_p->pci_common_p; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cmn_p->pci_fm_mutex)); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate pbm_err_p->pbm_pri = PBM_PRIMARY; 3297c478bd9Sstevel@tonic-gate (void) pci_pbm_classify(pbm_err_p); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate pci_format_addr(dip, &pbm_err_p->pbm_pci.pci_pa, pbm_err_p->pbm_afsr); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate if (pbm_err_p->pbm_log == FM_LOG_PBM) 3347c478bd9Sstevel@tonic-gate pbm_ereport_post(dip, fme_ena, pbm_err_p); 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * Lookup and fault errant handle 3387c478bd9Sstevel@tonic-gate */ 33900d0963fSdilpreet if (((ret = ndi_fmc_error(dip, NULL, ACC_HANDLE, fme_ena, 34000d0963fSdilpreet (void *)&pbm_err_p->pbm_pci.pci_pa)) == DDI_FM_FATAL) || 34100d0963fSdilpreet (ret == DDI_FM_UNKNOWN)) 3427c478bd9Sstevel@tonic-gate fatal++; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * queue target ereport if appropriate 3467c478bd9Sstevel@tonic-gate */ 34700d0963fSdilpreet if (pbm_err_p->pbm_terr_class) 34800d0963fSdilpreet pci_target_enqueue(fme_ena, pbm_err_p->pbm_terr_class, 34900d0963fSdilpreet (pbm_err_p->pbm_log == FM_LOG_PCI) ? "pci" : 35000d0963fSdilpreet pbm_err_p->pbm_bridge_type, pbm_err_p->pbm_pci.pci_pa); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* 3537c478bd9Sstevel@tonic-gate * We are currently not dealing with the multiple error 3547c478bd9Sstevel@tonic-gate * case, for any secondary errors we will panic. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate pbm_err_p->pbm_pri = PBM_SECONDARY; 3577c478bd9Sstevel@tonic-gate if (pci_pbm_classify(pbm_err_p)) { 3587c478bd9Sstevel@tonic-gate fatal++; 3597c478bd9Sstevel@tonic-gate if (pbm_err_p->pbm_log == FM_LOG_PBM) 3607c478bd9Sstevel@tonic-gate pbm_ereport_post(dip, fme_ena, pbm_err_p); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate if (fatal) 3647c478bd9Sstevel@tonic-gate return (DDI_FM_FATAL); 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate return (DDI_FM_NONFATAL); 3677c478bd9Sstevel@tonic-gate } 368