xref: /illumos-gate/usr/src/uts/common/os/pcifm.c (revision 3fe80ca4)
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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * Copyright 2023 Oxide Computer Company
28  */
29 
30 #include <sys/types.h>
31 #include <sys/sunndi.h>
32 #include <sys/sysmacros.h>
33 #include <sys/ddifm_impl.h>
34 #include <sys/fm/util.h>
35 #include <sys/fm/protocol.h>
36 #include <sys/fm/io/pci.h>
37 #include <sys/fm/io/ddi.h>
38 #include <sys/pci.h>
39 #include <sys/pci_cap.h>
40 #include <sys/pci_impl.h>
41 #include <sys/epm.h>
42 #include <sys/pcifm.h>
43 
44 #define	PCIX_ECC_VER_CHECK(x)	(((x) == PCI_PCIX_VER_1) ||\
45 				((x) == PCI_PCIX_VER_2))
46 
47 errorq_t *pci_target_queue = NULL;
48 
49 pci_fm_err_t pci_err_tbl[] = {
50 	PCI_DET_PERR,	PCI_STAT_PERROR,	NULL,		DDI_FM_UNKNOWN,
51 	PCI_MDPE,	PCI_STAT_S_PERROR,	PCI_TARG_MDPE,	DDI_FM_UNKNOWN,
52 	PCI_SIG_SERR,	PCI_STAT_S_SYSERR,	NULL,		DDI_FM_FATAL,
53 	PCI_MA,		PCI_STAT_R_MAST_AB,	PCI_TARG_MA,	DDI_FM_UNKNOWN,
54 	PCI_REC_TA,	PCI_STAT_R_TARG_AB,	PCI_TARG_REC_TA, DDI_FM_UNKNOWN,
55 	PCI_SIG_TA,	PCI_STAT_S_TARG_AB,	NULL,		DDI_FM_UNKNOWN,
56 	NULL, 0, NULL, DDI_FM_OK,
57 };
58 
59 pci_fm_err_t pci_bdg_err_tbl[] = {
60 	PCI_DET_PERR,	PCI_STAT_PERROR,	NULL,		DDI_FM_UNKNOWN,
61 	PCI_MDPE,	PCI_STAT_S_PERROR,	PCI_TARG_MDPE,	DDI_FM_UNKNOWN,
62 	PCI_REC_SERR,	PCI_STAT_S_SYSERR,	NULL,		DDI_FM_UNKNOWN,
63 #if defined(__sparc)
64 	PCI_MA,		PCI_STAT_R_MAST_AB,	PCI_TARG_MA,	DDI_FM_UNKNOWN,
65 #endif
66 	PCI_REC_TA,	PCI_STAT_R_TARG_AB,	PCI_TARG_REC_TA, DDI_FM_UNKNOWN,
67 	PCI_SIG_TA,	PCI_STAT_S_TARG_AB,	NULL,		DDI_FM_UNKNOWN,
68 	NULL, 0, NULL, DDI_FM_OK,
69 };
70 
71 static pci_fm_err_t pcix_err_tbl[] = {
72 	PCIX_SPL_DIS,		PCI_PCIX_SPL_DSCD,	NULL,	DDI_FM_UNKNOWN,
73 	PCIX_UNEX_SPL,		PCI_PCIX_UNEX_SPL,	NULL,	DDI_FM_UNKNOWN,
74 	PCIX_RX_SPL_MSG,	PCI_PCIX_RX_SPL_MSG,	NULL,   DDI_FM_UNKNOWN,
75 	NULL, 0, NULL, DDI_FM_OK,
76 };
77 
78 static pci_fm_err_t pcix_sec_err_tbl[] = {
79 	PCIX_SPL_DIS,		PCI_PCIX_BSS_SPL_DSCD,	NULL,	DDI_FM_UNKNOWN,
80 	PCIX_UNEX_SPL,		PCI_PCIX_BSS_UNEX_SPL,	NULL,	DDI_FM_UNKNOWN,
81 	PCIX_BSS_SPL_OR,	PCI_PCIX_BSS_SPL_OR,	NULL,	DDI_FM_OK,
82 	PCIX_BSS_SPL_DLY,	PCI_PCIX_BSS_SPL_DLY,	NULL,	DDI_FM_OK,
83 	NULL, 0, NULL, DDI_FM_OK,
84 };
85 
86 static int
pci_config_check(ddi_acc_handle_t handle,int fme_flag)87 pci_config_check(ddi_acc_handle_t handle, int fme_flag)
88 {
89 	ddi_acc_hdl_t *hp = impl_acc_hdl_get(handle);
90 	ddi_fm_error_t de;
91 
92 	if (!(DDI_FM_ACC_ERR_CAP(ddi_fm_capable(hp->ah_dip))))
93 		return (DDI_FM_OK);
94 
95 	de.fme_version = DDI_FME_VERSION;
96 
97 	ddi_fm_acc_err_get(handle, &de, de.fme_version);
98 	if (de.fme_status != DDI_FM_OK) {
99 		if (fme_flag == DDI_FM_ERR_UNEXPECTED) {
100 			char buf[FM_MAX_CLASS];
101 
102 			(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
103 			    PCI_ERROR_SUBCLASS, PCI_NR);
104 			ddi_fm_ereport_post(hp->ah_dip, buf, de.fme_ena,
105 			    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, NULL);
106 		}
107 		ddi_fm_acc_err_clear(handle, de.fme_version);
108 	}
109 	return (de.fme_status);
110 }
111 
112 static void
pcix_ecc_regs_gather(pci_erpt_t * erpt_p,pcix_ecc_regs_t * pcix_ecc_regs,uint8_t pcix_cap_ptr,int fme_flag)113 pcix_ecc_regs_gather(pci_erpt_t *erpt_p, pcix_ecc_regs_t *pcix_ecc_regs,
114     uint8_t pcix_cap_ptr, int fme_flag)
115 {
116 	int bdg = erpt_p->pe_dflags & PCI_BRIDGE_DEV;
117 
118 	pcix_ecc_regs->pcix_ecc_ctlstat = pci_config_get32(erpt_p->pe_hdl,
119 	    (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_STATUS :
120 	    PCI_PCIX_ECC_STATUS)));
121 	if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
122 		pcix_ecc_regs->pcix_ecc_vflags |= PCIX_ERR_ECC_STS_VALID;
123 	else
124 		return;
125 	pcix_ecc_regs->pcix_ecc_fstaddr = pci_config_get32(erpt_p->pe_hdl,
126 	    (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_FST_AD :
127 	    PCI_PCIX_ECC_FST_AD)));
128 	pcix_ecc_regs->pcix_ecc_secaddr = pci_config_get32(erpt_p->pe_hdl,
129 	    (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_SEC_AD :
130 	    PCI_PCIX_ECC_SEC_AD)));
131 	pcix_ecc_regs->pcix_ecc_attr = pci_config_get32((
132 	    ddi_acc_handle_t)erpt_p->pe_hdl,
133 	    (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_ATTR : PCI_PCIX_ECC_ATTR)));
134 }
135 
136 static void
pcix_regs_gather(pci_erpt_t * erpt_p,void * pe_regs,int fme_flag)137 pcix_regs_gather(pci_erpt_t *erpt_p, void *pe_regs, int fme_flag)
138 {
139 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
140 		pcix_bdg_error_regs_t *pcix_bdg_regs =
141 		    (pcix_bdg_error_regs_t *)pe_regs;
142 		uint8_t pcix_bdg_cap_ptr;
143 		int i;
144 
145 		pcix_bdg_cap_ptr = pcix_bdg_regs->pcix_bdg_cap_ptr;
146 		pcix_bdg_regs->pcix_bdg_sec_stat = pci_config_get16(
147 		    erpt_p->pe_hdl, (pcix_bdg_cap_ptr + PCI_PCIX_SEC_STATUS));
148 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
149 			pcix_bdg_regs->pcix_bdg_vflags |=
150 			    PCIX_BDG_SEC_STATUS_VALID;
151 		else
152 			return;
153 		pcix_bdg_regs->pcix_bdg_stat = pci_config_get32(erpt_p->pe_hdl,
154 		    (pcix_bdg_cap_ptr + PCI_PCIX_BDG_STATUS));
155 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
156 			pcix_bdg_regs->pcix_bdg_vflags |= PCIX_BDG_STATUS_VALID;
157 		else
158 			return;
159 		if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
160 			pcix_ecc_regs_t *pcix_bdg_ecc_regs;
161 
162 			for (i = 0; i < 2; i++) {
163 				pcix_bdg_ecc_regs =
164 				    pcix_bdg_regs->pcix_bdg_ecc_regs[i];
165 				pci_config_put32(erpt_p->pe_hdl,
166 				    (pcix_bdg_cap_ptr +
167 				    PCI_PCIX_BDG_ECC_STATUS), i);
168 				pcix_ecc_regs_gather(erpt_p,
169 				    pcix_bdg_ecc_regs,
170 				    pcix_bdg_cap_ptr, fme_flag);
171 			}
172 		}
173 	} else {
174 		pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)pe_regs;
175 		uint8_t pcix_cap_ptr;
176 
177 		pcix_cap_ptr = pcix_regs->pcix_cap_ptr;
178 
179 		pcix_regs->pcix_command = pci_config_get16(erpt_p->pe_hdl,
180 		    (pcix_cap_ptr + PCI_PCIX_COMMAND));
181 		pcix_regs->pcix_status = pci_config_get32(erpt_p->pe_hdl,
182 		    (pcix_cap_ptr + PCI_PCIX_STATUS));
183 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
184 			pcix_regs->pcix_vflags |= PCIX_ERR_STATUS_VALID;
185 		else
186 			return;
187 		if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
188 			pcix_ecc_regs_t *pcix_ecc_regs =
189 			    pcix_regs->pcix_ecc_regs;
190 
191 			pcix_ecc_regs_gather(erpt_p, pcix_ecc_regs,
192 			    pcix_cap_ptr, fme_flag);
193 		}
194 	}
195 }
196 
197 /*ARGSUSED*/
198 static void
pci_regs_gather(dev_info_t * dip,pci_erpt_t * erpt_p,int fme_flag)199 pci_regs_gather(dev_info_t *dip, pci_erpt_t *erpt_p, int fme_flag)
200 {
201 	pci_error_regs_t *pci_regs = erpt_p->pe_pci_regs;
202 
203 	/*
204 	 * Start by reading all the error registers that are available for
205 	 * pci and pci express and for leaf devices and bridges/switches
206 	 */
207 	pci_regs->pci_err_status = pci_config_get16(erpt_p->pe_hdl,
208 	    PCI_CONF_STAT);
209 	if (pci_config_check(erpt_p->pe_hdl, fme_flag) != DDI_FM_OK)
210 		return;
211 	pci_regs->pci_vflags |= PCI_ERR_STATUS_VALID;
212 	pci_regs->pci_cfg_comm = pci_config_get16(erpt_p->pe_hdl,
213 	    PCI_CONF_COMM);
214 	if (pci_config_check(erpt_p->pe_hdl, fme_flag) != DDI_FM_OK)
215 		return;
216 
217 	/*
218 	 * If pci-pci bridge grab PCI bridge specific error registers.
219 	 */
220 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
221 		pci_regs->pci_bdg_regs->pci_bdg_sec_stat =
222 		    pci_config_get16(erpt_p->pe_hdl, PCI_BCNF_SEC_STATUS);
223 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
224 			pci_regs->pci_bdg_regs->pci_bdg_vflags |=
225 			    PCI_BDG_SEC_STAT_VALID;
226 		pci_regs->pci_bdg_regs->pci_bdg_ctrl =
227 		    pci_config_get16(erpt_p->pe_hdl, PCI_BCNF_BCNTRL);
228 		if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK)
229 			pci_regs->pci_bdg_regs->pci_bdg_vflags |=
230 			    PCI_BDG_CTRL_VALID;
231 	}
232 
233 	/* If pci-x device grab error registers */
234 	if (erpt_p->pe_dflags & PCIX_DEV)
235 		pcix_regs_gather(erpt_p, erpt_p->pe_regs, fme_flag);
236 
237 }
238 
239 static void
pcix_regs_clear(pci_erpt_t * erpt_p,void * pe_regs)240 pcix_regs_clear(pci_erpt_t *erpt_p, void *pe_regs)
241 {
242 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
243 		pcix_bdg_error_regs_t *pcix_bdg_regs =
244 		    (pcix_bdg_error_regs_t *)pe_regs;
245 		uint8_t pcix_bdg_cap_ptr;
246 		int i;
247 
248 		pcix_bdg_cap_ptr = pcix_bdg_regs->pcix_bdg_cap_ptr;
249 
250 		if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_SEC_STATUS_VALID)
251 			pci_config_put16(erpt_p->pe_hdl,
252 			    (pcix_bdg_cap_ptr + PCI_PCIX_SEC_STATUS),
253 			    pcix_bdg_regs->pcix_bdg_sec_stat);
254 
255 		if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_STATUS_VALID)
256 			pci_config_put32(erpt_p->pe_hdl,
257 			    (pcix_bdg_cap_ptr + PCI_PCIX_BDG_STATUS),
258 			    pcix_bdg_regs->pcix_bdg_stat);
259 
260 		pcix_bdg_regs->pcix_bdg_vflags = 0x0;
261 
262 		if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
263 			pcix_ecc_regs_t *pcix_bdg_ecc_regs;
264 			for (i = 0; i < 2; i++) {
265 				pcix_bdg_ecc_regs =
266 				    pcix_bdg_regs->pcix_bdg_ecc_regs[i];
267 
268 				if (pcix_bdg_ecc_regs->pcix_ecc_vflags &
269 				    PCIX_ERR_ECC_STS_VALID) {
270 					pci_config_put32(erpt_p->pe_hdl,
271 					    (pcix_bdg_cap_ptr +
272 					    PCI_PCIX_BDG_ECC_STATUS),
273 					    i);
274 
275 					pci_config_put32(erpt_p->pe_hdl,
276 					    (pcix_bdg_cap_ptr +
277 					    PCI_PCIX_BDG_ECC_STATUS),
278 					    pcix_bdg_ecc_regs->
279 					    pcix_ecc_ctlstat);
280 				}
281 				pcix_bdg_ecc_regs->pcix_ecc_vflags =
282 				    0x0;
283 			}
284 		}
285 	} else {
286 		pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)pe_regs;
287 		uint8_t pcix_cap_ptr;
288 
289 		pcix_cap_ptr = pcix_regs->pcix_cap_ptr;
290 
291 		if (pcix_regs->pcix_vflags & PCIX_ERR_STATUS_VALID)
292 			pci_config_put32(erpt_p->pe_hdl,
293 			    (pcix_cap_ptr + PCI_PCIX_STATUS),
294 			    pcix_regs->pcix_status);
295 
296 		pcix_regs->pcix_vflags = 0x0;
297 
298 		if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
299 			pcix_ecc_regs_t *pcix_ecc_regs =
300 			    pcix_regs->pcix_ecc_regs;
301 
302 			if (pcix_ecc_regs->pcix_ecc_vflags &
303 			    PCIX_ERR_ECC_STS_VALID)
304 				pci_config_put32(erpt_p->pe_hdl,
305 				    (pcix_cap_ptr + PCI_PCIX_ECC_STATUS),
306 				    pcix_ecc_regs->pcix_ecc_ctlstat);
307 
308 			pcix_ecc_regs->pcix_ecc_vflags = 0x0;
309 		}
310 	}
311 }
312 
313 static void
pci_regs_clear(pci_erpt_t * erpt_p)314 pci_regs_clear(pci_erpt_t *erpt_p)
315 {
316 	/*
317 	 * Finally clear the error bits
318 	 */
319 	if (erpt_p->pe_dflags & PCIX_DEV)
320 		pcix_regs_clear(erpt_p, erpt_p->pe_regs);
321 
322 	if (erpt_p->pe_pci_regs->pci_vflags & PCI_ERR_STATUS_VALID)
323 		pci_config_put16(erpt_p->pe_hdl, PCI_CONF_STAT,
324 		    erpt_p->pe_pci_regs->pci_err_status);
325 
326 	erpt_p->pe_pci_regs->pci_vflags = 0x0;
327 
328 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
329 		if (erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags &
330 		    PCI_BDG_SEC_STAT_VALID)
331 			pci_config_put16(erpt_p->pe_hdl, PCI_BCNF_SEC_STATUS,
332 			    erpt_p->pe_pci_regs->pci_bdg_regs->
333 			    pci_bdg_sec_stat);
334 		if (erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags &
335 		    PCI_BDG_CTRL_VALID)
336 			pci_config_put16(erpt_p->pe_hdl, PCI_BCNF_BCNTRL,
337 			    erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_ctrl);
338 
339 		erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags = 0x0;
340 	}
341 }
342 
343 /*
344  * pcix_ereport_setup: Allocate structures for PCI-X error handling and ereport
345  * generation.
346  */
347 /* ARGSUSED */
348 static void
pcix_ereport_setup(dev_info_t * dip,pci_erpt_t * erpt_p)349 pcix_ereport_setup(dev_info_t *dip, pci_erpt_t *erpt_p)
350 {
351 	uint16_t pcix_cap_ptr = PCI_CAP_NEXT_PTR_NULL;
352 	ddi_acc_handle_t eh;
353 	int i;
354 
355 	if (pci_config_setup(dip, &eh) == DDI_SUCCESS) {
356 		(void) PCI_CAP_LOCATE(eh, PCI_CAP_ID_PCIX, &pcix_cap_ptr);
357 		pci_config_teardown(&eh);
358 	}
359 
360 	if (pcix_cap_ptr != PCI_CAP_NEXT_PTR_NULL)
361 		erpt_p->pe_dflags |= PCIX_DEV;
362 	else
363 		return;
364 
365 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
366 		pcix_bdg_error_regs_t *pcix_bdg_regs;
367 
368 		erpt_p->pe_regs = kmem_zalloc(sizeof (pcix_bdg_error_regs_t),
369 		    KM_SLEEP);
370 		pcix_bdg_regs = (pcix_bdg_error_regs_t *)erpt_p->pe_regs;
371 		pcix_bdg_regs->pcix_bdg_cap_ptr = pcix_cap_ptr;
372 		pcix_bdg_regs->pcix_bdg_ver = pci_config_get16(erpt_p->pe_hdl,
373 		    pcix_cap_ptr + PCI_PCIX_SEC_STATUS) & PCI_PCIX_VER_MASK;
374 		if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
375 			for (i = 0; i < 2; i++) {
376 				pcix_bdg_regs->pcix_bdg_ecc_regs[i] =
377 				    kmem_zalloc(sizeof (pcix_ecc_regs_t),
378 				    KM_SLEEP);
379 			}
380 		}
381 	} else {
382 		pcix_error_regs_t *pcix_regs;
383 
384 		erpt_p->pe_regs = kmem_zalloc(sizeof (pcix_error_regs_t),
385 		    KM_SLEEP);
386 		pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
387 		pcix_regs->pcix_cap_ptr = pcix_cap_ptr;
388 		pcix_regs->pcix_ver = pci_config_get16(erpt_p->pe_hdl,
389 		    pcix_cap_ptr + PCI_PCIX_COMMAND) & PCI_PCIX_VER_MASK;
390 		if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
391 			pcix_regs->pcix_ecc_regs = kmem_zalloc(
392 			    sizeof (pcix_ecc_regs_t), KM_SLEEP);
393 		}
394 	}
395 }
396 
397 /*
398  * pci_ereport_setup: Detect PCI device type and initialize structures to be
399  * used to generate ereports based on detected generic device errors.
400  */
401 void
pci_ereport_setup(dev_info_t * dip)402 pci_ereport_setup(dev_info_t *dip)
403 {
404 	struct dev_info *devi = DEVI(dip);
405 	struct i_ddi_fmhdl *fmhdl = devi->devi_fmhdl;
406 	pci_erpt_t *erpt_p;
407 	uint8_t pci_hdr_type;
408 	uint16_t pci_status;
409 	pci_regspec_t *pci_rp;
410 	int32_t len;
411 	uint32_t phys_hi;
412 
413 	/*
414 	 * If device is not ereport capbable then report an error against the
415 	 * driver for using this interface,
416 	 */
417 	if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
418 	    !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
419 		i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_SLEEP);
420 		return;
421 	}
422 
423 	/*
424 	 * ASSERT fmhdl exists and fh_bus_specific is NULL.
425 	 */
426 	ASSERT(fmhdl && (fmhdl->fh_bus_specific == NULL));
427 
428 	erpt_p = kmem_zalloc(sizeof (pci_erpt_t), KM_SLEEP);
429 
430 	if (pci_config_setup(dip, &erpt_p->pe_hdl) != DDI_SUCCESS)
431 		goto error;
432 
433 	erpt_p->pe_pci_regs = kmem_zalloc(sizeof (pci_error_regs_t), KM_SLEEP);
434 
435 	pci_status = pci_config_get16(erpt_p->pe_hdl, PCI_CONF_STAT);
436 	if (pci_config_check(erpt_p->pe_hdl, DDI_FM_ERR_UNEXPECTED) !=
437 	    DDI_FM_OK)
438 		goto error;
439 
440 	/*
441 	 * Get header type and record if device is a bridge.
442 	 */
443 	pci_hdr_type = pci_config_get8(erpt_p->pe_hdl, PCI_CONF_HEADER);
444 	if (pci_config_check(erpt_p->pe_hdl, DDI_FM_ERR_UNEXPECTED) !=
445 	    DDI_FM_OK)
446 		goto error;
447 
448 	/*
449 	 * Check to see if PCI device is a bridge, if so allocate pci bridge
450 	 * error register structure.
451 	 */
452 	if ((pci_hdr_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
453 		erpt_p->pe_dflags |= PCI_BRIDGE_DEV;
454 		erpt_p->pe_pci_regs->pci_bdg_regs = kmem_zalloc(
455 		    sizeof (pci_bdg_error_regs_t), KM_SLEEP);
456 	}
457 
458 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
459 	    (caddr_t)&pci_rp, &len) == DDI_SUCCESS) {
460 		phys_hi = pci_rp->pci_phys_hi;
461 		kmem_free(pci_rp, len);
462 
463 		erpt_p->pe_bdf = (uint16_t)(PCI_REG_BDFR_G(phys_hi) >>
464 		    PCI_REG_FUNC_SHIFT);
465 	}
466 
467 	if (!(pci_status & PCI_STAT_CAP)) {
468 		goto done;
469 	}
470 
471 	/* Initialize structures for PCI-X devices. */
472 	pcix_ereport_setup(dip, erpt_p);
473 
474 done:
475 	pci_regs_gather(dip, erpt_p, DDI_FM_ERR_UNEXPECTED);
476 	pci_regs_clear(erpt_p);
477 
478 	/*
479 	 * Before returning set fh_bus_specific to completed pci_erpt_t
480 	 * structure
481 	 */
482 	fmhdl->fh_bus_specific = (void *)erpt_p;
483 
484 	return;
485 error:
486 	if (erpt_p->pe_pci_regs)
487 		kmem_free(erpt_p->pe_pci_regs, sizeof (pci_error_regs_t));
488 	kmem_free(erpt_p, sizeof (pci_erpt_t));
489 	erpt_p = NULL;
490 }
491 
492 static void
pcix_ereport_teardown(pci_erpt_t * erpt_p)493 pcix_ereport_teardown(pci_erpt_t *erpt_p)
494 {
495 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
496 		pcix_bdg_error_regs_t *pcix_bdg_regs;
497 		uint16_t pcix_ver;
498 
499 		pcix_bdg_regs = (pcix_bdg_error_regs_t *)erpt_p->pe_regs;
500 		pcix_ver = pcix_bdg_regs->pcix_bdg_ver;
501 		if (PCIX_ECC_VER_CHECK(pcix_ver)) {
502 			int i;
503 			for (i = 0; i < 2; i++)
504 				kmem_free(pcix_bdg_regs->pcix_bdg_ecc_regs[i],
505 				    sizeof (pcix_ecc_regs_t));
506 		}
507 		kmem_free(erpt_p->pe_regs, sizeof (pcix_bdg_error_regs_t));
508 	} else {
509 		pcix_error_regs_t *pcix_regs;
510 		uint16_t pcix_ver;
511 
512 		pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
513 		pcix_ver = pcix_regs->pcix_ver;
514 		if (PCIX_ECC_VER_CHECK(pcix_ver)) {
515 			kmem_free(pcix_regs->pcix_ecc_regs,
516 			    sizeof (pcix_ecc_regs_t));
517 		}
518 		kmem_free(erpt_p->pe_regs, sizeof (pcix_error_regs_t));
519 	}
520 }
521 
522 void
pci_ereport_teardown(dev_info_t * dip)523 pci_ereport_teardown(dev_info_t *dip)
524 {
525 	struct i_ddi_fmhdl *fmhdl = DEVI(dip)->devi_fmhdl;
526 	pci_erpt_t *erpt_p;
527 
528 	if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
529 	    !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
530 		i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_SLEEP);
531 	}
532 
533 	ASSERT(fmhdl);
534 
535 	erpt_p = (pci_erpt_t *)fmhdl->fh_bus_specific;
536 	if (erpt_p == NULL)
537 		return;
538 
539 	if (erpt_p->pe_dflags & PCIX_DEV)
540 		pcix_ereport_teardown(erpt_p);
541 	pci_config_teardown((ddi_acc_handle_t *)&erpt_p->pe_hdl);
542 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV)
543 		kmem_free(erpt_p->pe_pci_regs->pci_bdg_regs,
544 		    sizeof (pci_bdg_error_regs_t));
545 	kmem_free(erpt_p->pe_pci_regs, sizeof (pci_error_regs_t));
546 	kmem_free(erpt_p, sizeof (pci_erpt_t));
547 	fmhdl->fh_bus_specific = NULL;
548 
549 	/*
550 	 * The following sparc specific code should be removed once the pci_cap
551 	 * interfaces create the necessary properties for us.
552 	 */
553 }
554 
555 /*ARGSUSED*/
556 static int
pcix_check_addr(dev_info_t * dip,ddi_fm_error_t * derr,pcix_ecc_regs_t * pcix_ecc_regs,int type)557 pcix_check_addr(dev_info_t *dip, ddi_fm_error_t *derr,
558     pcix_ecc_regs_t *pcix_ecc_regs, int type)
559 {
560 	int cmd = (pcix_ecc_regs->pcix_ecc_ctlstat >> 16) & 0xf;
561 	uint64_t addr;
562 	pci_fme_bus_specific_t *pci_fme_bsp =
563 	    (pci_fme_bus_specific_t *)derr->fme_bus_specific;
564 
565 	addr = pcix_ecc_regs->pcix_ecc_secaddr;
566 	addr = addr << 32;
567 	addr |= pcix_ecc_regs->pcix_ecc_fstaddr;
568 
569 	switch (cmd) {
570 	case PCI_PCIX_CMD_INTR:
571 	case PCI_PCIX_CMD_SPEC:
572 		return (DDI_FM_FATAL);
573 	case PCI_PCIX_CMD_IORD:
574 	case PCI_PCIX_CMD_IOWR:
575 		pci_fme_bsp->pci_bs_addr = addr;
576 		pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
577 		pci_fme_bsp->pci_bs_type = type;
578 		return (DDI_FM_UNKNOWN);
579 	case PCI_PCIX_CMD_DEVID:
580 		return (DDI_FM_FATAL);
581 	case PCI_PCIX_CMD_MEMRD_DW:
582 	case PCI_PCIX_CMD_MEMWR:
583 	case PCI_PCIX_CMD_MEMRD_BL:
584 	case PCI_PCIX_CMD_MEMWR_BL:
585 		pci_fme_bsp->pci_bs_addr = addr;
586 		pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
587 		pci_fme_bsp->pci_bs_type = type;
588 		return (DDI_FM_UNKNOWN);
589 	case PCI_PCIX_CMD_CFRD:
590 	case PCI_PCIX_CMD_CFWR:
591 		/*
592 		 * for type 1 config transaction we can find bdf from address
593 		 */
594 		if ((addr & 3) == 1) {
595 			pci_fme_bsp->pci_bs_bdf = (addr >> 8) & 0xffffffff;
596 			pci_fme_bsp->pci_bs_flags |= PCI_BS_BDF_VALID;
597 			pci_fme_bsp->pci_bs_type = type;
598 		}
599 		return (DDI_FM_UNKNOWN);
600 	case PCI_PCIX_CMD_SPL:
601 	case PCI_PCIX_CMD_DADR:
602 		return (DDI_FM_UNKNOWN);
603 	case PCI_PCIX_CMD_MEMRDBL:
604 	case PCI_PCIX_CMD_MEMWRBL:
605 		pci_fme_bsp->pci_bs_addr = addr;
606 		pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID;
607 		pci_fme_bsp->pci_bs_type = type;
608 		return (DDI_FM_UNKNOWN);
609 	default:
610 		return (DDI_FM_FATAL);
611 	}
612 }
613 
614 /*ARGSUSED*/
615 static int
pci_bdg_error_report(dev_info_t * dip,ddi_fm_error_t * derr,pci_erpt_t * erpt_p)616 pci_bdg_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
617 {
618 	pci_bdg_error_regs_t *pci_bdg_regs = erpt_p->pe_pci_regs->pci_bdg_regs;
619 	int fatal = 0;
620 	int nonfatal = 0;
621 	int unknown = 0;
622 	int ok = 0;
623 	int ret = DDI_FM_OK;
624 	char buf[FM_MAX_CLASS];
625 	int i;
626 	pci_fme_bus_specific_t *pci_fme_bsp =
627 	    (pci_fme_bus_specific_t *)derr->fme_bus_specific;
628 
629 	if (derr->fme_flag != DDI_FM_ERR_UNEXPECTED)
630 		goto done;
631 
632 	if ((pci_bdg_regs->pci_bdg_vflags & PCI_BDG_CTRL_VALID) &&
633 	    (pci_bdg_regs->pci_bdg_ctrl & PCI_BCNF_BCNTRL_DTO_STAT)) {
634 		(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
635 		    PCI_ERROR_SUBCLASS, PCI_DTO);
636 		ddi_fm_ereport_post(dip, buf, derr->fme_ena,
637 		    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
638 		    PCI_SEC_CONFIG_STATUS, DATA_TYPE_UINT16,
639 		    pci_bdg_regs->pci_bdg_sec_stat, PCI_BCNTRL,
640 		    DATA_TYPE_UINT16, pci_bdg_regs->pci_bdg_ctrl, NULL);
641 		unknown++;
642 	}
643 
644 	if (pci_bdg_regs->pci_bdg_vflags & PCI_BDG_SEC_STAT_VALID) {
645 		for (i = 0; pci_bdg_err_tbl[i].err_class != NULL; i++) {
646 			if (pci_bdg_regs->pci_bdg_sec_stat &
647 			    pci_bdg_err_tbl[i].reg_bit) {
648 				(void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s",
649 				    PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS,
650 				    pci_bdg_err_tbl[i].err_class);
651 				ddi_fm_ereport_post(dip, buf, derr->fme_ena,
652 				    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
653 				    PCI_SEC_CONFIG_STATUS, DATA_TYPE_UINT16,
654 				    pci_bdg_regs->pci_bdg_sec_stat, PCI_BCNTRL,
655 				    DATA_TYPE_UINT16,
656 				    pci_bdg_regs->pci_bdg_ctrl, NULL);
657 				PCI_FM_SEV_INC(pci_bdg_err_tbl[i].flags);
658 				if (pci_fme_bsp && (pci_fme_bsp->pci_bs_flags &
659 				    PCI_BS_ADDR_VALID) &&
660 				    pci_fme_bsp->pci_bs_type == ACC_HANDLE &&
661 				    pci_bdg_err_tbl[i].terr_class)
662 					pci_target_enqueue(derr->fme_ena,
663 					    pci_bdg_err_tbl[i].terr_class,
664 					    PCI_ERROR_SUBCLASS,
665 					    pci_fme_bsp->pci_bs_addr);
666 			}
667 		}
668 	}
669 
670 done:
671 	/*
672 	 * Need to check for poke and cautious put. We already know peek
673 	 * and cautious get errors occurred (as we got a trap) and we know
674 	 * they are nonfatal.
675 	 */
676 	if (derr->fme_flag == DDI_FM_ERR_EXPECTED) {
677 		/*
678 		 * for cautious puts we treat all errors as nonfatal. Actually
679 		 * we set nonfatal for cautious gets as well - doesn't do any
680 		 * harm
681 		 */
682 		if (pci_bdg_regs->pci_bdg_sec_stat & (PCI_STAT_R_TARG_AB |
683 		    PCI_STAT_R_MAST_AB | PCI_STAT_S_PERROR | PCI_STAT_S_SYSERR))
684 			nonfatal++;
685 	}
686 	if (derr->fme_flag == DDI_FM_ERR_POKE) {
687 		/*
688 		 * special case for pokes - we only consider master abort
689 		 * and target abort as nonfatal. Sserr with no master abort is
690 		 * fatal, but master/target abort can come in on separate
691 		 * instance, so return unknown and parent will determine if
692 		 * nonfatal (if another child returned nonfatal - ie master
693 		 * or target abort) or fatal otherwise
694 		 */
695 		if (pci_bdg_regs->pci_bdg_sec_stat & (PCI_STAT_R_TARG_AB |
696 		    PCI_STAT_R_MAST_AB))
697 			nonfatal++;
698 		if (erpt_p->pe_pci_regs->pci_err_status & PCI_STAT_S_SYSERR)
699 			unknown++;
700 	}
701 
702 	/*
703 	 * now check children below the bridge
704 	 */
705 	ret = ndi_fm_handler_dispatch(dip, NULL, derr);
706 	PCI_FM_SEV_INC(ret);
707 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
708 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
709 }
710 
711 static int
pcix_ecc_error_report(dev_info_t * dip,ddi_fm_error_t * derr,pci_erpt_t * erpt_p,void * pe_regs)712 pcix_ecc_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p,
713     void *pe_regs)
714 {
715 	pcix_error_regs_t *pcix_regs;
716 	pcix_bdg_error_regs_t *pcix_bdg_regs;
717 	pcix_ecc_regs_t *pcix_ecc_regs;
718 	int bridge;
719 	int i;
720 	int ecc_phase;
721 	int ecc_corr;
722 	int sec_ue;
723 	int sec_ce;
724 	int fatal = 0;
725 	int nonfatal = 0;
726 	int unknown = 0;
727 	int ok = 0;
728 	char buf[FM_MAX_CLASS];
729 
730 	if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
731 		pcix_bdg_regs = (pcix_bdg_error_regs_t *)pe_regs;
732 		bridge = 1;
733 	} else {
734 		pcix_regs = (pcix_error_regs_t *)pe_regs;
735 		bridge = 0;
736 	}
737 
738 	for (i = 0; i < (bridge ? 2 : 1); i++) {
739 		int ret = DDI_FM_OK;
740 		pcix_ecc_regs = bridge ? pcix_bdg_regs->pcix_bdg_ecc_regs[i] :
741 		    pcix_regs->pcix_ecc_regs;
742 		if (pcix_ecc_regs->pcix_ecc_vflags & PCIX_ERR_ECC_STS_VALID) {
743 			ecc_phase = (pcix_ecc_regs->pcix_ecc_ctlstat &
744 			    PCI_PCIX_ECC_PHASE) >> 0x4;
745 			ecc_corr = (pcix_ecc_regs->pcix_ecc_ctlstat &
746 			    PCI_PCIX_ECC_CORR);
747 			sec_ue = (pcix_ecc_regs->pcix_ecc_ctlstat &
748 			    PCI_PCIX_ECC_S_UE);
749 			sec_ce = (pcix_ecc_regs->pcix_ecc_ctlstat &
750 			    PCI_PCIX_ECC_S_CE);
751 
752 			switch (ecc_phase) {
753 			case PCI_PCIX_ECC_PHASE_NOERR:
754 				break;
755 			case PCI_PCIX_ECC_PHASE_FADDR:
756 			case PCI_PCIX_ECC_PHASE_SADDR:
757 				PCI_FM_SEV_INC(ecc_corr ?  DDI_FM_OK :
758 				    DDI_FM_FATAL);
759 				(void) snprintf(buf, FM_MAX_CLASS,
760 				    "%s.%s%s", PCIX_ERROR_SUBCLASS,
761 				    i ? PCIX_SEC_ERROR_SUBCLASS : "",
762 				    ecc_corr ? PCIX_ECC_CE_ADDR :
763 				    PCIX_ECC_UE_ADDR);
764 				break;
765 			case PCI_PCIX_ECC_PHASE_ATTR:
766 				PCI_FM_SEV_INC(ecc_corr ?
767 				    DDI_FM_OK : DDI_FM_FATAL);
768 				(void) snprintf(buf, FM_MAX_CLASS,
769 				    "%s.%s%s", PCIX_ERROR_SUBCLASS,
770 				    i ? PCIX_SEC_ERROR_SUBCLASS : "",
771 				    ecc_corr ? PCIX_ECC_CE_ATTR :
772 				    PCIX_ECC_UE_ATTR);
773 				break;
774 			case PCI_PCIX_ECC_PHASE_DATA32:
775 			case PCI_PCIX_ECC_PHASE_DATA64:
776 				if (ecc_corr)
777 					ret = DDI_FM_OK;
778 				else {
779 					int type;
780 					pci_error_regs_t *pci_regs =
781 					    erpt_p->pe_pci_regs;
782 
783 					if (i) {
784 						if (pci_regs->pci_bdg_regs->
785 						    pci_bdg_sec_stat &
786 						    PCI_STAT_S_PERROR)
787 							type = ACC_HANDLE;
788 						else
789 							type = DMA_HANDLE;
790 					} else {
791 						if (pci_regs->pci_err_status &
792 						    PCI_STAT_S_PERROR)
793 							type = DMA_HANDLE;
794 						else
795 							type = ACC_HANDLE;
796 					}
797 					ret = pcix_check_addr(dip, derr,
798 					    pcix_ecc_regs, type);
799 				}
800 				PCI_FM_SEV_INC(ret);
801 
802 				(void) snprintf(buf, FM_MAX_CLASS,
803 				    "%s.%s%s", PCIX_ERROR_SUBCLASS,
804 				    i ? PCIX_SEC_ERROR_SUBCLASS : "",
805 				    ecc_corr ? PCIX_ECC_CE_DATA :
806 				    PCIX_ECC_UE_DATA);
807 				break;
808 			}
809 			if (ecc_phase)
810 				if (bridge)
811 					ddi_fm_ereport_post(dip, buf,
812 					    derr->fme_ena,
813 					    DDI_NOSLEEP, FM_VERSION,
814 					    DATA_TYPE_UINT8, 0,
815 					    PCIX_SEC_STATUS, DATA_TYPE_UINT16,
816 					    pcix_bdg_regs->pcix_bdg_sec_stat,
817 					    PCIX_BDG_STAT, DATA_TYPE_UINT32,
818 					    pcix_bdg_regs->pcix_bdg_stat,
819 					    PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
820 					    pcix_ecc_regs->pcix_ecc_ctlstat,
821 					    PCIX_ECC_ATTR, DATA_TYPE_UINT32,
822 					    pcix_ecc_regs->pcix_ecc_attr, NULL);
823 				else
824 					ddi_fm_ereport_post(dip, buf,
825 					    derr->fme_ena,
826 					    DDI_NOSLEEP, FM_VERSION,
827 					    DATA_TYPE_UINT8, 0,
828 					    PCIX_COMMAND, DATA_TYPE_UINT16,
829 					    pcix_regs->pcix_command,
830 					    PCIX_STATUS, DATA_TYPE_UINT32,
831 					    pcix_regs->pcix_status,
832 					    PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
833 					    pcix_ecc_regs->pcix_ecc_ctlstat,
834 					    PCIX_ECC_ATTR, DATA_TYPE_UINT32,
835 					    pcix_ecc_regs->pcix_ecc_attr, NULL);
836 			if (sec_ce || sec_ue) {
837 				(void) snprintf(buf, FM_MAX_CLASS,
838 				    "%s.%s%s", PCIX_ERROR_SUBCLASS,
839 				    i ? PCIX_SEC_ERROR_SUBCLASS : "",
840 				    sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
841 				if (bridge)
842 					ddi_fm_ereport_post(dip, buf,
843 					    derr->fme_ena,
844 					    DDI_NOSLEEP, FM_VERSION,
845 					    DATA_TYPE_UINT8, 0,
846 					    PCIX_SEC_STATUS, DATA_TYPE_UINT16,
847 					    pcix_bdg_regs->pcix_bdg_sec_stat,
848 					    PCIX_BDG_STAT, DATA_TYPE_UINT32,
849 					    pcix_bdg_regs->pcix_bdg_stat,
850 					    PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
851 					    pcix_ecc_regs->pcix_ecc_ctlstat,
852 					    PCIX_ECC_ATTR, DATA_TYPE_UINT32,
853 					    pcix_ecc_regs->pcix_ecc_attr, NULL);
854 				else
855 					ddi_fm_ereport_post(dip, buf,
856 					    derr->fme_ena,
857 					    DDI_NOSLEEP, FM_VERSION,
858 					    DATA_TYPE_UINT8, 0,
859 					    PCIX_COMMAND, DATA_TYPE_UINT16,
860 					    pcix_regs->pcix_command,
861 					    PCIX_STATUS, DATA_TYPE_UINT32,
862 					    pcix_regs->pcix_status,
863 					    PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32,
864 					    pcix_ecc_regs->pcix_ecc_ctlstat,
865 					    PCIX_ECC_ATTR, DATA_TYPE_UINT32,
866 					    pcix_ecc_regs->pcix_ecc_attr, NULL);
867 				PCI_FM_SEV_INC(sec_ue ? DDI_FM_FATAL :
868 				    DDI_FM_OK);
869 			}
870 		}
871 	}
872 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
873 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
874 }
875 
876 static int
pcix_bdg_error_report(dev_info_t * dip,ddi_fm_error_t * derr,pci_erpt_t * erpt_p,void * pe_regs)877 pcix_bdg_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p,
878     void *pe_regs)
879 {
880 	pcix_bdg_error_regs_t *pcix_bdg_regs = (pcix_bdg_error_regs_t *)pe_regs;
881 	int fatal = 0;
882 	int nonfatal = 0;
883 	int unknown = 0;
884 	int ok = 0;
885 	char buf[FM_MAX_CLASS];
886 	int i;
887 
888 	if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_STATUS_VALID) {
889 		for (i = 0; pcix_err_tbl[i].err_class != NULL; i++) {
890 			if ((pcix_bdg_regs->pcix_bdg_stat &
891 			    pcix_err_tbl[i].reg_bit)) {
892 				(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
893 				    PCIX_ERROR_SUBCLASS,
894 				    pcix_err_tbl[i].err_class);
895 				ddi_fm_ereport_post(dip, buf, derr->fme_ena,
896 				    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
897 				    PCIX_SEC_STATUS, DATA_TYPE_UINT16,
898 				    pcix_bdg_regs->pcix_bdg_sec_stat,
899 				    PCIX_BDG_STAT, DATA_TYPE_UINT32,
900 				    pcix_bdg_regs->pcix_bdg_stat, NULL);
901 				PCI_FM_SEV_INC(pcix_err_tbl[i].flags);
902 			}
903 		}
904 	}
905 
906 	if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_SEC_STATUS_VALID) {
907 		for (i = 0; pcix_sec_err_tbl[i].err_class != NULL; i++) {
908 			if ((pcix_bdg_regs->pcix_bdg_sec_stat &
909 			    pcix_sec_err_tbl[i].reg_bit)) {
910 				(void) snprintf(buf, FM_MAX_CLASS, "%s.%s%s",
911 				    PCIX_ERROR_SUBCLASS,
912 				    PCIX_SEC_ERROR_SUBCLASS,
913 				    pcix_sec_err_tbl[i].err_class);
914 				ddi_fm_ereport_post(dip, buf, derr->fme_ena,
915 				    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
916 				    PCIX_SEC_STATUS, DATA_TYPE_UINT16,
917 				    pcix_bdg_regs->pcix_bdg_sec_stat,
918 				    PCIX_BDG_STAT, DATA_TYPE_UINT32,
919 				    pcix_bdg_regs->pcix_bdg_stat, NULL);
920 				PCI_FM_SEV_INC(pcix_sec_err_tbl[i].flags);
921 			}
922 		}
923 	}
924 
925 	/* Log/Handle ECC errors */
926 	if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) {
927 		int ret;
928 
929 		ret = pcix_ecc_error_report(dip, derr, erpt_p,
930 		    (void *)pcix_bdg_regs);
931 		PCI_FM_SEV_INC(ret);
932 	}
933 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
934 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
935 }
936 
937 static int
pcix_error_report(dev_info_t * dip,ddi_fm_error_t * derr,pci_erpt_t * erpt_p)938 pcix_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
939 {
940 	pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs;
941 	int fatal = 0;
942 	int nonfatal = 0;
943 	int unknown = 0;
944 	int ok = 0;
945 	char buf[FM_MAX_CLASS];
946 	int i;
947 
948 	if (pcix_regs->pcix_vflags & PCIX_ERR_STATUS_VALID) {
949 		for (i = 0; pcix_err_tbl[i].err_class != NULL; i++) {
950 			if (!(pcix_regs->pcix_status & pcix_err_tbl[i].reg_bit))
951 				continue;
952 
953 			(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
954 			    PCIX_ERROR_SUBCLASS, pcix_err_tbl[i].err_class);
955 			ddi_fm_ereport_post(dip, buf, derr->fme_ena,
956 			    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
957 			    PCIX_COMMAND, DATA_TYPE_UINT16,
958 			    pcix_regs->pcix_command, PCIX_STATUS,
959 			    DATA_TYPE_UINT32, pcix_regs->pcix_status,
960 			    NULL);
961 			PCI_FM_SEV_INC(pcix_err_tbl[i].flags);
962 		}
963 	}
964 	/* Log/Handle ECC errors */
965 	if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) {
966 		int ret = pcix_ecc_error_report(dip, derr, erpt_p,
967 		    (void *)pcix_regs);
968 		PCI_FM_SEV_INC(ret);
969 	}
970 
971 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
972 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
973 }
974 
975 static void
pci_error_report(dev_info_t * dip,ddi_fm_error_t * derr,pci_erpt_t * erpt_p)976 pci_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p)
977 {
978 	int fatal = 0;
979 	int nonfatal = 0;
980 	int unknown = 0;
981 	int ok = 0;
982 	char buf[FM_MAX_CLASS];
983 	int i;
984 
985 	if (derr->fme_flag == DDI_FM_ERR_UNEXPECTED) {
986 		/*
987 		 * Log generic PCI errors.
988 		 */
989 		for (i = 0; pci_err_tbl[i].err_class != NULL; i++) {
990 			if (!(erpt_p->pe_pci_regs->pci_err_status &
991 			    pci_err_tbl[i].reg_bit) ||
992 			    !(erpt_p->pe_pci_regs->pci_vflags &
993 			    PCI_ERR_STATUS_VALID))
994 				continue;
995 			/*
996 			 * Generate an ereport for this error bit.
997 			 */
998 			(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
999 			    PCI_ERROR_SUBCLASS, pci_err_tbl[i].err_class);
1000 			ddi_fm_ereport_post(dip, buf, derr->fme_ena,
1001 			    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1002 			    PCI_CONFIG_STATUS, DATA_TYPE_UINT16,
1003 			    erpt_p->pe_pci_regs->pci_err_status,
1004 			    PCI_CONFIG_COMMAND, DATA_TYPE_UINT16,
1005 			    erpt_p->pe_pci_regs->pci_cfg_comm, NULL);
1006 
1007 			PCI_FM_SEV_INC(pci_err_tbl[i].flags);
1008 		}
1009 		if (erpt_p->pe_dflags & PCIX_DEV) {
1010 			if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) {
1011 				int ret = pcix_bdg_error_report(dip, derr,
1012 				    erpt_p, erpt_p->pe_regs);
1013 				PCI_FM_SEV_INC(ret);
1014 			} else {
1015 				int ret = pcix_error_report(dip, derr, erpt_p);
1016 				PCI_FM_SEV_INC(ret);
1017 			}
1018 		}
1019 	}
1020 
1021 	if ((erpt_p->pe_dflags & PCI_BRIDGE_DEV)) {
1022 		int ret = pci_bdg_error_report(dip, derr, erpt_p);
1023 		PCI_FM_SEV_INC(ret);
1024 	}
1025 
1026 	if (derr->fme_flag == DDI_FM_ERR_UNEXPECTED) {
1027 		pci_fme_bus_specific_t *pci_fme_bsp;
1028 		int ret = DDI_FM_UNKNOWN;
1029 
1030 		pci_fme_bsp = (pci_fme_bus_specific_t *)derr->fme_bus_specific;
1031 		if (pci_fme_bsp->pci_bs_flags & PCI_BS_ADDR_VALID) {
1032 			ret = ndi_fmc_entry_error(dip,
1033 			    pci_fme_bsp->pci_bs_type, derr,
1034 			    (void *)&pci_fme_bsp->pci_bs_addr);
1035 			PCI_FM_SEV_INC(ret);
1036 		}
1037 		/*
1038 		 * If we didn't find the handle using an addr, try using bdf.
1039 		 * Note we don't do this where the bdf is for a
1040 		 * device behind a pciex/pci bridge as the bridge may have
1041 		 * fabricated the bdf.
1042 		 */
1043 		if (ret == DDI_FM_UNKNOWN &&
1044 		    (pci_fme_bsp->pci_bs_flags & PCI_BS_BDF_VALID) &&
1045 		    pci_fme_bsp->pci_bs_bdf == erpt_p->pe_bdf) {
1046 			ret = ndi_fmc_entry_error_all(dip,
1047 			    pci_fme_bsp->pci_bs_type, derr);
1048 			PCI_FM_SEV_INC(ret);
1049 		}
1050 	}
1051 
1052 	derr->fme_status = (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
1053 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
1054 }
1055 
1056 void
pci_ereport_post(dev_info_t * dip,ddi_fm_error_t * derr,uint16_t * xx_status)1057 pci_ereport_post(dev_info_t *dip, ddi_fm_error_t *derr, uint16_t *xx_status)
1058 {
1059 	struct i_ddi_fmhdl *fmhdl;
1060 	pci_erpt_t *erpt_p;
1061 	ddi_fm_error_t de;
1062 	pci_fme_bus_specific_t pci_fme_bs;
1063 
1064 	/*
1065 	 * On PCI Express systems, all error handling and ereport are done via
1066 	 * the PCIe misc module.  This function is a no-op for PCIe Systems.  In
1067 	 * order to tell if a system is a PCI or PCIe system, check that the
1068 	 * bus_private_data exists.  If it exists, this is a PCIe system.
1069 	 */
1070 	if (ndi_get_bus_private(dip, B_TRUE)) {
1071 		derr->fme_status = DDI_FM_OK;
1072 		if (xx_status != NULL)
1073 			*xx_status = 0x0;
1074 
1075 		return;
1076 	}
1077 
1078 	fmhdl = DEVI(dip)->devi_fmhdl;
1079 	if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) &&
1080 	    !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) {
1081 		i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_NOSLEEP);
1082 		return;
1083 	}
1084 
1085 	/*
1086 	 * copy in the ddi_fm_error_t structure in case it's VER0
1087 	 */
1088 	de.fme_version = derr->fme_version;
1089 	de.fme_status = derr->fme_status;
1090 	de.fme_flag = derr->fme_flag;
1091 	de.fme_ena = derr->fme_ena;
1092 	de.fme_acc_handle = derr->fme_acc_handle;
1093 	de.fme_dma_handle = derr->fme_dma_handle;
1094 	de.fme_bus_specific = derr->fme_bus_specific;
1095 	if (derr->fme_version >= DDI_FME_VER1)
1096 		de.fme_bus_type = derr->fme_bus_type;
1097 	else
1098 		de.fme_bus_type = DDI_FME_BUS_TYPE_DFLT;
1099 	if (de.fme_bus_type == DDI_FME_BUS_TYPE_DFLT) {
1100 		/*
1101 		 * if this is the first pci device we've found convert
1102 		 * fme_bus_specific to DDI_FME_BUS_TYPE_PCI
1103 		 */
1104 		bzero(&pci_fme_bs, sizeof (pci_fme_bs));
1105 		if (de.fme_bus_specific) {
1106 			/*
1107 			 * the cpu passed us an addr - this can be used to look
1108 			 * up an access handle
1109 			 */
1110 			pci_fme_bs.pci_bs_addr = (uintptr_t)de.fme_bus_specific;
1111 			pci_fme_bs.pci_bs_type = ACC_HANDLE;
1112 			pci_fme_bs.pci_bs_flags |= PCI_BS_ADDR_VALID;
1113 		}
1114 		de.fme_bus_specific = (void *)&pci_fme_bs;
1115 		de.fme_bus_type = DDI_FME_BUS_TYPE_PCI;
1116 	}
1117 
1118 	ASSERT(fmhdl);
1119 
1120 	if (de.fme_ena == 0)
1121 		de.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
1122 
1123 	erpt_p = (pci_erpt_t *)fmhdl->fh_bus_specific;
1124 	if (erpt_p == NULL)
1125 		return;
1126 
1127 	pci_regs_gather(dip, erpt_p, de.fme_flag);
1128 	pci_error_report(dip, &de, erpt_p);
1129 	pci_regs_clear(erpt_p);
1130 
1131 	derr->fme_status = de.fme_status;
1132 	derr->fme_ena = de.fme_ena;
1133 	derr->fme_acc_handle = de.fme_acc_handle;
1134 	derr->fme_dma_handle = de.fme_dma_handle;
1135 	if (xx_status != NULL)
1136 		*xx_status = erpt_p->pe_pci_regs->pci_err_status;
1137 }
1138 
1139 /*
1140  * private version of walk_devs() that can be used during panic. No
1141  * sleeping or locking required.
1142  */
1143 static int
pci_fm_walk_devs(dev_info_t * dip,int (* f)(dev_info_t *,void *),void * arg)1144 pci_fm_walk_devs(dev_info_t *dip, int (*f)(dev_info_t *, void *), void *arg)
1145 {
1146 	while (dip) {
1147 		switch ((*f)(dip, arg)) {
1148 		case DDI_WALK_TERMINATE:
1149 			return (DDI_WALK_TERMINATE);
1150 		case DDI_WALK_CONTINUE:
1151 			if (pci_fm_walk_devs(ddi_get_child(dip), f,
1152 			    arg) == DDI_WALK_TERMINATE)
1153 				return (DDI_WALK_TERMINATE);
1154 			break;
1155 		case DDI_WALK_PRUNECHILD:
1156 			break;
1157 		}
1158 		dip = ddi_get_next_sibling(dip);
1159 	}
1160 	return (DDI_WALK_CONTINUE);
1161 }
1162 
1163 /*
1164  * need special version of ddi_fm_ereport_post() as the leaf driver may
1165  * not be hardened.
1166  */
1167 static void
pci_fm_ereport_post(dev_info_t * dip,const char * error_class,uint64_t ena,uint8_t version,...)1168 pci_fm_ereport_post(dev_info_t *dip, const char *error_class, uint64_t ena,
1169     uint8_t version, ...)
1170 {
1171 	char *name;
1172 	char device_path[MAXPATHLEN];
1173 	char ddi_error_class[FM_MAX_CLASS];
1174 	nvlist_t *ereport, *detector;
1175 	nv_alloc_t *nva;
1176 	errorq_elem_t *eqep;
1177 	va_list ap;
1178 
1179 	eqep = NULL;
1180 	if (panicstr) {
1181 		eqep = errorq_reserve(ereport_errorq);
1182 		if (eqep == NULL)
1183 			return;
1184 		ereport = errorq_elem_nvl(ereport_errorq, eqep);
1185 		nva = errorq_elem_nva(ereport_errorq, eqep);
1186 		detector = fm_nvlist_create(nva);
1187 	} else {
1188 		ereport = fm_nvlist_create(NULL);
1189 		detector = fm_nvlist_create(NULL);
1190 	}
1191 
1192 	(void) ddi_pathname(dip, device_path);
1193 	fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
1194 	    device_path, NULL, NULL);
1195 	(void) snprintf(ddi_error_class, FM_MAX_CLASS, "%s.%s",
1196 	    DDI_IO_CLASS, error_class);
1197 	fm_ereport_set(ereport, version, ddi_error_class, ena, detector, NULL);
1198 
1199 	va_start(ap, version);
1200 	name = va_arg(ap, char *);
1201 	(void) i_fm_payload_set(ereport, name, ap);
1202 	va_end(ap);
1203 
1204 	if (panicstr) {
1205 		errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
1206 	} else {
1207 		(void) fm_ereport_post(ereport, EVCH_TRYHARD);
1208 		fm_nvlist_destroy(ereport, FM_NVA_FREE);
1209 		fm_nvlist_destroy(detector, FM_NVA_FREE);
1210 	}
1211 }
1212 
1213 static int
pci_check_regs(dev_info_t * dip,void * arg)1214 pci_check_regs(dev_info_t *dip, void *arg)
1215 {
1216 	int reglen;
1217 	int rn;
1218 	int totreg;
1219 	pci_regspec_t *drv_regp;
1220 	pci_target_err_t *tgt_err = (pci_target_err_t *)arg;
1221 
1222 	if (tgt_err->tgt_pci_space == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) {
1223 		/*
1224 		 * for config space, we need to check if the given address
1225 		 * is a valid config space address for this device - based
1226 		 * on pci_phys_hi of the config space entry in reg property.
1227 		 */
1228 		if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
1229 		    "reg", (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
1230 			return (DDI_WALK_CONTINUE);
1231 
1232 		totreg = reglen / sizeof (pci_regspec_t);
1233 		for (rn = 0; rn < totreg; rn++) {
1234 			if (tgt_err->tgt_pci_space ==
1235 			    PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi) &&
1236 			    (tgt_err->tgt_pci_addr & (PCI_REG_BUS_M |
1237 			    PCI_REG_DEV_M | PCI_REG_FUNC_M)) ==
1238 			    (drv_regp[rn].pci_phys_hi & (PCI_REG_BUS_M |
1239 			    PCI_REG_DEV_M | PCI_REG_FUNC_M))) {
1240 				tgt_err->tgt_dip = dip;
1241 				kmem_free(drv_regp, reglen);
1242 				return (DDI_WALK_TERMINATE);
1243 			}
1244 		}
1245 		kmem_free(drv_regp, reglen);
1246 	} else {
1247 		/*
1248 		 * for non config space, need to check reg to look
1249 		 * for any non-relocable mapping, otherwise check
1250 		 * assigned-addresses.
1251 		 */
1252 		if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
1253 		    "reg", (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
1254 			return (DDI_WALK_CONTINUE);
1255 
1256 		totreg = reglen / sizeof (pci_regspec_t);
1257 		for (rn = 0; rn < totreg; rn++) {
1258 			if ((drv_regp[rn].pci_phys_hi & PCI_RELOCAT_B) &&
1259 			    (tgt_err->tgt_pci_space == TGT_PCI_SPACE_UNKNOWN ||
1260 			    tgt_err->tgt_pci_space ==
1261 			    PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi)) &&
1262 			    (tgt_err->tgt_pci_addr >=
1263 			    (uint64_t)drv_regp[rn].pci_phys_low +
1264 			    ((uint64_t)drv_regp[rn].pci_phys_mid << 32)) &&
1265 			    (tgt_err->tgt_pci_addr <
1266 			    (uint64_t)drv_regp[rn].pci_phys_low +
1267 			    ((uint64_t)drv_regp[rn].pci_phys_mid << 32) +
1268 			    (uint64_t)drv_regp[rn].pci_size_low +
1269 			    ((uint64_t)drv_regp[rn].pci_size_hi << 32))) {
1270 				tgt_err->tgt_dip = dip;
1271 				kmem_free(drv_regp, reglen);
1272 				return (DDI_WALK_TERMINATE);
1273 			}
1274 		}
1275 		kmem_free(drv_regp, reglen);
1276 
1277 		if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
1278 		    "assigned-addresses", (caddr_t)&drv_regp, &reglen) !=
1279 		    DDI_SUCCESS)
1280 			return (DDI_WALK_CONTINUE);
1281 
1282 		totreg = reglen / sizeof (pci_regspec_t);
1283 		for (rn = 0; rn < totreg; rn++) {
1284 			if ((tgt_err->tgt_pci_space == TGT_PCI_SPACE_UNKNOWN ||
1285 			    tgt_err->tgt_pci_space ==
1286 			    PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi)) &&
1287 			    (tgt_err->tgt_pci_addr >=
1288 			    (uint64_t)drv_regp[rn].pci_phys_low +
1289 			    ((uint64_t)drv_regp[rn].pci_phys_mid << 32)) &&
1290 			    (tgt_err->tgt_pci_addr <
1291 			    (uint64_t)drv_regp[rn].pci_phys_low +
1292 			    ((uint64_t)drv_regp[rn].pci_phys_mid << 32) +
1293 			    (uint64_t)drv_regp[rn].pci_size_low +
1294 			    ((uint64_t)drv_regp[rn].pci_size_hi << 32))) {
1295 				tgt_err->tgt_dip = dip;
1296 				kmem_free(drv_regp, reglen);
1297 				return (DDI_WALK_TERMINATE);
1298 			}
1299 		}
1300 		kmem_free(drv_regp, reglen);
1301 	}
1302 	return (DDI_WALK_CONTINUE);
1303 }
1304 
1305 /*
1306  * impl_fix_ranges - fixes the config space entry of the "ranges"
1307  * property on psycho+ platforms.  (if changing this function please make sure
1308  * to change the pci_fix_ranges function in pcipsy.c)
1309  */
1310 /*ARGSUSED*/
1311 static void
pci_fix_ranges(dev_info_t * dip,pci_ranges_t * pci_ranges,int nrange)1312 pci_fix_ranges(dev_info_t *dip, pci_ranges_t *pci_ranges, int nrange)
1313 {
1314 #if defined(__sparc)
1315 	char *name = ddi_binding_name(dip);
1316 
1317 	if ((strcmp(name, "pci108e,8000") == 0) ||
1318 	    (strcmp(name, "pci108e,a000") == 0) ||
1319 	    (strcmp(name, "pci108e,a001") == 0)) {
1320 		int i;
1321 		for (i = 0; i < nrange; i++, pci_ranges++)
1322 			if ((pci_ranges->child_high & PCI_REG_ADDR_M) ==
1323 			    PCI_ADDR_CONFIG)
1324 				pci_ranges->parent_low |=
1325 				    pci_ranges->child_high;
1326 	}
1327 #endif
1328 }
1329 
1330 static int
pci_check_ranges(dev_info_t * dip,void * arg)1331 pci_check_ranges(dev_info_t *dip, void *arg)
1332 {
1333 	uint64_t range_parent_begin;
1334 	uint64_t range_parent_size;
1335 	uint64_t range_parent_end;
1336 	uint32_t space_type;
1337 	uint32_t bus_num;
1338 	uint32_t range_offset;
1339 	pci_ranges_t *pci_ranges, *rangep;
1340 	pci_bus_range_t *pci_bus_rangep;
1341 	int pci_ranges_length;
1342 	int nrange;
1343 	pci_target_err_t *tgt_err = (pci_target_err_t *)arg;
1344 	int i, size;
1345 	if (strcmp(ddi_node_name(dip), "pci") != 0 &&
1346 	    strcmp(ddi_node_name(dip), "pciex") != 0)
1347 		return (DDI_WALK_CONTINUE);
1348 
1349 	/*
1350 	 * Get the ranges property. Note we only look at the top level pci
1351 	 * node (hostbridge) which has a ranges property of type pci_ranges_t
1352 	 * not at pci-pci bridges.
1353 	 */
1354 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
1355 	    (caddr_t)&pci_ranges, &pci_ranges_length) != DDI_SUCCESS) {
1356 		/*
1357 		 * no ranges property - no translation needed
1358 		 */
1359 		tgt_err->tgt_pci_addr = tgt_err->tgt_err_addr;
1360 		tgt_err->tgt_pci_space = TGT_PCI_SPACE_UNKNOWN;
1361 		if (panicstr)
1362 			(void) pci_fm_walk_devs(ddi_get_child(dip),
1363 			    pci_check_regs, (void *)tgt_err);
1364 		else {
1365 			ndi_devi_enter(dip);
1366 			ddi_walk_devs(ddi_get_child(dip), pci_check_regs,
1367 			    (void *)tgt_err);
1368 			ndi_devi_exit(dip);
1369 		}
1370 		if (tgt_err->tgt_dip != NULL)
1371 			return (DDI_WALK_TERMINATE);
1372 		return (DDI_WALK_PRUNECHILD);
1373 	}
1374 	nrange = pci_ranges_length / sizeof (pci_ranges_t);
1375 	rangep = pci_ranges;
1376 
1377 	/* Need to fix the pci ranges property for psycho based systems */
1378 	pci_fix_ranges(dip, pci_ranges, nrange);
1379 
1380 	for (i = 0; i < nrange; i++, rangep++) {
1381 		range_parent_begin = ((uint64_t)rangep->parent_high << 32) +
1382 		    rangep->parent_low;
1383 		range_parent_size = ((uint64_t)rangep->size_high << 32) +
1384 		    rangep->size_low;
1385 		range_parent_end = range_parent_begin + range_parent_size - 1;
1386 
1387 		if ((tgt_err->tgt_err_addr < range_parent_begin) ||
1388 		    (tgt_err->tgt_err_addr > range_parent_end)) {
1389 			/* Not in range */
1390 			continue;
1391 		}
1392 		space_type = PCI_REG_ADDR_G(rangep->child_high);
1393 		if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) {
1394 			/* Config space address - check bus range */
1395 			range_offset = tgt_err->tgt_err_addr -
1396 			    range_parent_begin;
1397 			bus_num = PCI_REG_BUS_G(range_offset);
1398 			if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
1399 			    DDI_PROP_DONTPASS, "bus-range",
1400 			    (caddr_t)&pci_bus_rangep, &size) != DDI_SUCCESS) {
1401 				continue;
1402 			}
1403 			if ((bus_num < pci_bus_rangep->lo) ||
1404 			    (bus_num > pci_bus_rangep->hi)) {
1405 				/*
1406 				 * Bus number not appropriate for this
1407 				 * pci nexus.
1408 				 */
1409 				kmem_free(pci_bus_rangep, size);
1410 				continue;
1411 			}
1412 			kmem_free(pci_bus_rangep, size);
1413 		}
1414 
1415 		/* We have a match if we get here - compute pci address */
1416 		tgt_err->tgt_pci_addr = tgt_err->tgt_err_addr -
1417 		    range_parent_begin;
1418 		tgt_err->tgt_pci_addr += (((uint64_t)rangep->child_mid << 32) +
1419 		    rangep->child_low);
1420 		tgt_err->tgt_pci_space = space_type;
1421 		if (panicstr)
1422 			(void) pci_fm_walk_devs(ddi_get_child(dip),
1423 			    pci_check_regs, (void *)tgt_err);
1424 		else {
1425 			ndi_devi_enter(dip);
1426 			ddi_walk_devs(ddi_get_child(dip), pci_check_regs,
1427 			    (void *)tgt_err);
1428 			ndi_devi_exit(dip);
1429 		}
1430 		if (tgt_err->tgt_dip != NULL) {
1431 			kmem_free(pci_ranges, pci_ranges_length);
1432 			return (DDI_WALK_TERMINATE);
1433 		}
1434 	}
1435 	kmem_free(pci_ranges, pci_ranges_length);
1436 	return (DDI_WALK_PRUNECHILD);
1437 }
1438 
1439 /*
1440  * Function used to drain pci_target_queue, either during panic or after softint
1441  * is generated, to generate target device ereports based on captured physical
1442  * addresses
1443  */
1444 /*ARGSUSED*/
1445 static void
pci_target_drain(void * private_p,const void * err,const errorq_elem_t * arg __unused)1446 pci_target_drain(void *private_p, const void *err,
1447     const errorq_elem_t *arg __unused)
1448 {
1449 	pci_target_err_t *tgt_err = (pci_target_err_t *)err;
1450 	char buf[FM_MAX_CLASS];
1451 
1452 	/*
1453 	 * The following assumes that all pci_pci bridge devices
1454 	 * are configured as transparant. Find the top-level pci
1455 	 * nexus which has tgt_err_addr in one of its ranges, converting this
1456 	 * to a pci address in the process. Then starting at this node do
1457 	 * another tree walk to find a device with the pci address we've
1458 	 * found within range of one of it's assigned-addresses properties.
1459 	 */
1460 	tgt_err->tgt_dip = NULL;
1461 	if (panicstr)
1462 		(void) pci_fm_walk_devs(ddi_root_node(), pci_check_ranges,
1463 		    (void *)tgt_err);
1464 	else
1465 		ddi_walk_devs(ddi_root_node(), pci_check_ranges,
1466 		    (void *)tgt_err);
1467 	if (tgt_err->tgt_dip == NULL)
1468 		return;
1469 
1470 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s", tgt_err->tgt_bridge_type,
1471 	    tgt_err->tgt_err_class);
1472 	pci_fm_ereport_post(tgt_err->tgt_dip, buf, tgt_err->tgt_err_ena, 0,
1473 	    PCI_PA, DATA_TYPE_UINT64, tgt_err->tgt_err_addr, NULL);
1474 }
1475 
1476 void
pci_target_enqueue(uint64_t ena,char * class,char * bridge_type,uint64_t addr)1477 pci_target_enqueue(uint64_t ena, char *class, char *bridge_type, uint64_t addr)
1478 {
1479 	pci_target_err_t tgt_err;
1480 
1481 	tgt_err.tgt_err_ena = ena;
1482 	tgt_err.tgt_err_class = class;
1483 	tgt_err.tgt_bridge_type = bridge_type;
1484 	tgt_err.tgt_err_addr = addr;
1485 	errorq_dispatch(pci_target_queue, (void *)&tgt_err,
1486 	    sizeof (pci_target_err_t), ERRORQ_ASYNC);
1487 }
1488 
1489 void
pci_targetq_init(void)1490 pci_targetq_init(void)
1491 {
1492 	/*
1493 	 * PCI target errorq, to schedule async handling of generation of
1494 	 * target device ereports based on captured physical address.
1495 	 * The errorq is created here but destroyed when _fini is called
1496 	 * for the pci module.
1497 	 */
1498 	if (pci_target_queue == NULL) {
1499 		pci_target_queue = errorq_create("pci_target_queue",
1500 		    pci_target_drain, (void *)NULL,
1501 		    TARGET_MAX_ERRS, sizeof (pci_target_err_t), FM_ERR_PIL,
1502 		    ERRORQ_VITAL);
1503 		if (pci_target_queue == NULL)
1504 			panic("failed to create required system error queue");
1505 	}
1506 }
1507