1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #include <sys/types.h> 27 #include <px_err.h> 28 29 #include "fabric-xlate.h" 30 31 #define EPKT_DESC(b, o, p, c, d) (BLOCK_##b << 16 | OP_##o << 12 | \ 32 PH_##p << 8 | CND_##c << 4 | DIR_##d) 33 34 /* EPKT Table used only for RC/RP errors */ 35 typedef struct fab_epkt_tbl { 36 uint32_t epkt_desc; 37 uint32_t pcie_ue_sts; /* Equivalent PCIe UE Status */ 38 uint16_t pci_err_sts; /* Equivalent PCI Error Status */ 39 uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */ 40 const char *tgt_class; /* Target Ereport Class */ 41 } fab_epkt_tbl_t; 42 43 static fab_epkt_tbl_t fab_epkt_tbl[] = { 44 EPKT_DESC(MMU, XLAT, DATA, INV, RDWR), 45 PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0, 46 EPKT_DESC(MMU, XLAT, ADDR, UNMAP, RDWR), 47 PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0, 48 EPKT_DESC(MMU, XLAT, DATA, PROT, RDWR), 49 PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0, 50 51 EPKT_DESC(INTR, MSI32, DATA, ILL, IRR), 52 PCIE_AER_UCE_MTLP, PCI_STAT_S_SYSERR, 0, 0, 53 54 EPKT_DESC(PORT, PIO, IRR, RCA, WRITE), 55 PCIE_AER_UCE_CA, PCI_STAT_S_SYSERR, PCI_STAT_S_TARG_AB, 0, 56 57 EPKT_DESC(PORT, PIO, IRR, RUR, WRITE), 58 PCIE_AER_UCE_UR, PCI_STAT_S_SYSERR, 0, 0, 59 60 EPKT_DESC(PORT, PIO, IRR, INV, RDWR), 61 PCIE_AER_UCE_MTLP, PCI_STAT_S_SYSERR, 0, 0, 62 63 EPKT_DESC(PORT, PIO, IRR, TO, READ), 64 PCIE_AER_UCE_TO, PCI_STAT_S_SYSERR, 0, PCI_TARG_MA, 65 EPKT_DESC(PORT, PIO, IRR, TO, WRITE), 66 PCIE_AER_UCE_TO, PCI_STAT_S_SYSERR, 0, PCI_TARG_MA, 67 68 EPKT_DESC(PORT, PIO, IRR, UC, IRR), 69 PCIE_AER_UCE_UC, PCI_STAT_S_SYSERR, 0, 0, 70 71 EPKT_DESC(PORT, LINK, FC, TO, IRR), 72 PCIE_AER_UCE_FCP, PCI_STAT_S_SYSERR, 0, 0, 73 74 0, 0, 0, 0, 0 75 }; 76 77 /* ARGSUSED */ 78 void 79 fab_epkt_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) 80 { 81 data->nvl = nvl; 82 83 /* Always Root Complex */ 84 data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT; 85 86 data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD | 87 PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP); 88 } 89 90 static int 91 fab_xlate_epkt(fmd_hdl_t *hdl, fab_data_t *data, px_rc_err_t *epktp) 92 { 93 fab_epkt_tbl_t *entry; 94 uint32_t temp; 95 96 for (entry = fab_epkt_tbl; entry->epkt_desc != 0; entry++) { 97 temp = *(uint32_t *)&epktp->rc_descr >> 12; 98 if (entry->epkt_desc == temp) 99 goto send; 100 } 101 102 return (0); 103 104 send: 105 fmd_hdl_debug(hdl, "Translate epkt DESC = %#x\n", temp); 106 107 /* Fill in PCI Status Register */ 108 data->pci_err_status = entry->pci_err_sts; 109 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 110 111 /* Fill in the device status register */ 112 if (epktp->rc_descr.STOP) 113 data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; 114 else if (epktp->rc_descr.C) 115 data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED; 116 else 117 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 118 119 /* Fill in the AER UE register */ 120 data->pcie_ue_status = entry->pcie_ue_sts; 121 122 /* Fill in the AER Control register */ 123 temp = entry->pcie_ue_sts; 124 for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++) 125 temp = temp >> 1; 126 127 /* Send target ereports */ 128 data->pcie_ue_no_tgt_erpt = B_TRUE; 129 if (entry->tgt_class && !epktp->rc_descr.STOP) { 130 if (epktp->rc_descr.D) { 131 data->pcie_ue_tgt_trans = PF_ADDR_DMA; 132 data->pcie_ue_tgt_addr = epktp->addr; 133 } else if (epktp->rc_descr.M) { 134 data->pcie_ue_tgt_trans = PF_ADDR_PIO; 135 data->pcie_ue_tgt_addr = epktp->addr; 136 } 137 138 if (data->pcie_ue_tgt_trans) 139 fab_send_tgt_erpt(hdl, data, entry->tgt_class, 140 B_TRUE); 141 } 142 return (1); 143 } 144 145 void 146 fab_xlate_epkt_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class) 147 { 148 fab_data_t data = {0}; 149 px_rc_err_t epkt = {0}; 150 pcie_tlp_hdr_t *tlp_hdr; 151 void *ptr; 152 uint8_t ver; 153 int err; 154 char *rppath = NULL; 155 nvlist_t *detector; 156 157 fmd_hdl_debug(hdl, "epkt ereport received: %s\n", class); 158 fab_epkt_to_data(hdl, nvl, &data); 159 160 err = nvlist_lookup_uint8(nvl, "epkt_ver", &ver); 161 err |= nvlist_lookup_uint32(nvl, "desc", (uint32_t *)&epkt.rc_descr); 162 err |= nvlist_lookup_uint32(nvl, "size", &epkt.size); 163 err |= nvlist_lookup_uint64(nvl, "addr", &epkt.addr); 164 err |= nvlist_lookup_uint64(nvl, "hdr1", &epkt.hdr[0]); 165 err |= nvlist_lookup_uint64(nvl, "hdr2", &epkt.hdr[1]); 166 err |= nvlist_lookup_uint64(nvl, "reserved", &epkt.reserved); 167 168 if (err != 0) { 169 fmd_hdl_debug(hdl, "Failed to retrieve all epkt payloads"); 170 return; 171 } 172 173 fmd_hdl_debug(hdl, "epkt flags: %c%c%c%c%c%c%c%c%c %s", 174 epkt.rc_descr.S ? 'S' : '-', epkt.rc_descr.M ? 'M' : '-', 175 epkt.rc_descr.S ? 'Q' : '-', epkt.rc_descr.D ? 'D' : '-', 176 epkt.rc_descr.R ? 'R' : '-', epkt.rc_descr.H ? 'H' : '-', 177 epkt.rc_descr.C ? 'C' : '-', epkt.rc_descr.I ? 'I' : '-', 178 epkt.rc_descr.B ? 'B' : '-', epkt.rc_descr.STOP ? "STOP" : ""); 179 180 /* 181 * If the least byte of the 'reserved' is non zero, it is device 182 * and function of the port 183 */ 184 if (epkt.reserved && 0xff) 185 rppath = fab_find_rppath_by_df(hdl, nvl, epkt.reserved & 0xff); 186 187 if (epkt.rc_descr.H) { 188 data.pcie_ue_hdr[0] = (uint32_t)(epkt.hdr[0] >> 32); 189 data.pcie_ue_hdr[1] = (uint32_t)epkt.hdr[0]; 190 data.pcie_ue_hdr[2] = (uint32_t)(epkt.hdr[1] >> 32); 191 data.pcie_ue_hdr[3] = (uint32_t)(epkt.hdr[1]); 192 193 tlp_hdr = (pcie_tlp_hdr_t *)&data.pcie_ue_hdr[0]; 194 ptr = &data.pcie_ue_hdr[1]; 195 switch (tlp_hdr->type) { 196 case PCIE_TLP_TYPE_IO: 197 case PCIE_TLP_TYPE_MEM: 198 case PCIE_TLP_TYPE_MEMLK: 199 { 200 pcie_mem64_t *pmp = ptr; 201 data.pcie_ue_tgt_trans = PF_ADDR_PIO; 202 data.pcie_ue_tgt_bdf = pmp->rid; 203 if (tlp_hdr->fmt & 0x1) 204 data.pcie_ue_tgt_addr = 205 ((uint64_t)pmp->addr1 << 32) | pmp->addr0; 206 else 207 data.pcie_ue_tgt_addr = 208 ((pcie_memio32_t *)ptr)->addr0; 209 210 break; 211 } 212 213 case PCIE_TLP_TYPE_CFG0: 214 case PCIE_TLP_TYPE_CFG1: 215 { 216 pcie_cfg_t *pcp = ptr; 217 218 data.pcie_ue_tgt_trans = PF_ADDR_CFG; 219 data.pcie_ue_tgt_bdf = 220 (pcp->bus << 8) | (pcp->dev << 3) | pcp->func; 221 break; 222 } 223 224 case PCIE_TLP_TYPE_CPL: 225 case PCIE_TLP_TYPE_CPLLK: 226 data.pcie_ue_tgt_bdf = ((pcie_cpl_t *)ptr)->rid; 227 break; 228 } 229 230 fmd_hdl_debug(hdl, "HEADER 0 0x%x", data.pcie_ue_hdr[0]); 231 fmd_hdl_debug(hdl, "HEADER 1 0x%x", data.pcie_ue_hdr[1]); 232 fmd_hdl_debug(hdl, "HEADER 2 0x%x", data.pcie_ue_hdr[2]); 233 fmd_hdl_debug(hdl, "HEADER 3 0x%x", data.pcie_ue_hdr[3]); 234 fmd_hdl_debug(hdl, "In header bdf = %#hx addr = %#llx", 235 data.pcie_ue_tgt_bdf, 236 (uint64_t)data.pcie_ue_tgt_addr); 237 238 /* find the root port to which this error is related */ 239 if (data.pcie_ue_tgt_bdf) 240 rppath = fab_find_rppath_by_devbdf(hdl, nvl, 241 data.pcie_ue_tgt_bdf); 242 } 243 244 /* 245 * reset the detector in the original ereport to the root port 246 */ 247 if (rppath && nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) == 0) { 248 (void) nvlist_add_string(detector, FM_VERSION, 249 FM_DEV_SCHEME_VERSION); 250 (void) nvlist_add_string(detector, FM_FMRI_SCHEME, 251 FM_FMRI_SCHEME_DEV); 252 (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, rppath); 253 (void) nvlist_remove_all(nvl, FM_EREPORT_DETECTOR); 254 (void) nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR, detector); 255 nvlist_free(detector); 256 } 257 258 fmd_hdl_strfree(hdl, rppath); 259 260 (void) fab_xlate_epkt(hdl, &data, &epkt); 261 fab_xlate_pcie_erpts(hdl, &data); 262 } 263