1*4c3888b8SHans Rosenfeld /*
2*4c3888b8SHans Rosenfeld  * CDDL HEADER START
3*4c3888b8SHans Rosenfeld  *
4*4c3888b8SHans Rosenfeld  * The contents of this file are subject to the terms of the
5*4c3888b8SHans Rosenfeld  * Common Development and Distribution License (the "License").
6*4c3888b8SHans Rosenfeld  * You may not use this file except in compliance with the License.
7*4c3888b8SHans Rosenfeld  *
8*4c3888b8SHans Rosenfeld  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4c3888b8SHans Rosenfeld  * or http://www.opensolaris.org/os/licensing.
10*4c3888b8SHans Rosenfeld  * See the License for the specific language governing permissions
11*4c3888b8SHans Rosenfeld  * and limitations under the License.
12*4c3888b8SHans Rosenfeld  *
13*4c3888b8SHans Rosenfeld  * When distributing Covered Code, include this CDDL HEADER in each
14*4c3888b8SHans Rosenfeld  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4c3888b8SHans Rosenfeld  * If applicable, add the following below this CDDL HEADER, with the
16*4c3888b8SHans Rosenfeld  * fields enclosed by brackets "[]" replaced with your own identifying
17*4c3888b8SHans Rosenfeld  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4c3888b8SHans Rosenfeld  *
19*4c3888b8SHans Rosenfeld  * CDDL HEADER END
20*4c3888b8SHans Rosenfeld  */
21*4c3888b8SHans Rosenfeld 
22*4c3888b8SHans Rosenfeld /*
23*4c3888b8SHans Rosenfeld  * ***********************************************************************
24*4c3888b8SHans Rosenfeld  * *                                                                    **
25*4c3888b8SHans Rosenfeld  * *                            NOTICE                                  **
26*4c3888b8SHans Rosenfeld  * *            COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION              **
27*4c3888b8SHans Rosenfeld  * *                    ALL RIGHTS RESERVED                             **
28*4c3888b8SHans Rosenfeld  * *                                                                    **
29*4c3888b8SHans Rosenfeld  * ***********************************************************************
30*4c3888b8SHans Rosenfeld  *
31*4c3888b8SHans Rosenfeld  */
32*4c3888b8SHans Rosenfeld 
33*4c3888b8SHans Rosenfeld #include <ql_apps.h>
34*4c3888b8SHans Rosenfeld #include <ql_api.h>
35*4c3888b8SHans Rosenfeld #include <ql_fm.h>
36*4c3888b8SHans Rosenfeld 
37*4c3888b8SHans Rosenfeld /* Define default impact code */
38*4c3888b8SHans Rosenfeld qlc_fm_ereport_t qlc_fm_ereport_tbl[] = {
39*4c3888b8SHans Rosenfeld 
40*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_DMA_ERR,
41*4c3888b8SHans Rosenfeld 	"A DMA direction error",
42*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_DMA_ERR,
43*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INTERN_CORR,
44*4c3888b8SHans Rosenfeld 	DDI_SERVICE_UNAFFECTED},
45*4c3888b8SHans Rosenfeld 
46*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_BAD_PAYLOAD,
47*4c3888b8SHans Rosenfeld 	"A bad payload detected",
48*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_BAD_PAYLOAD,
49*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INTERN_CORR,
50*4c3888b8SHans Rosenfeld 	DDI_SERVICE_UNAFFECTED},
51*4c3888b8SHans Rosenfeld 
52*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_CMD_FAILED,
53*4c3888b8SHans Rosenfeld 	"A command failed",
54*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_CMD_FAILED,
55*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INTERN_CORR,
56*4c3888b8SHans Rosenfeld 	DDI_SERVICE_UNAFFECTED},
57*4c3888b8SHans Rosenfeld 
58*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_CHIP_HANG,
59*4c3888b8SHans Rosenfeld 	"fw is not responding",
60*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_CHIP_HANG,
61*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INTERN_CORR,
62*4c3888b8SHans Rosenfeld 	DDI_SERVICE_UNAFFECTED},
63*4c3888b8SHans Rosenfeld 
64*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_UNKNOWN,
65*4c3888b8SHans Rosenfeld 	"Unknown error reported",
66*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_UNKNOWN,
67*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INTERN_CORR,
68*4c3888b8SHans Rosenfeld 	DDI_SERVICE_UNAFFECTED},
69*4c3888b8SHans Rosenfeld 
70*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_MBA_REQ_TRANSFER_ERR,
71*4c3888b8SHans Rosenfeld 	"Async event request transfer error",
72*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_MBA_REQ_TRANSFER_ERR,
73*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INVAL_STATE,
74*4c3888b8SHans Rosenfeld 	DDI_SERVICE_LOST},
75*4c3888b8SHans Rosenfeld 
76*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_MBA_RSP_TRANSFER_ERR,
77*4c3888b8SHans Rosenfeld 	"Async event response transfer error",
78*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_MBA_RSP_TRANSFER_ERR,
79*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INVAL_STATE,
80*4c3888b8SHans Rosenfeld 	DDI_SERVICE_LOST},
81*4c3888b8SHans Rosenfeld 
82*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_ACC_HANDLE_CHECK,
83*4c3888b8SHans Rosenfeld 	"ACC handle check return failed",
84*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_ACC_HANDLE_ERR,
85*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INTERN_UNCORR,
86*4c3888b8SHans Rosenfeld 	DDI_SERVICE_LOST},
87*4c3888b8SHans Rosenfeld 
88*4c3888b8SHans Rosenfeld 	{QL_FM_EREPORT_DMA_HANDLE_CHECK,
89*4c3888b8SHans Rosenfeld 	"DMA handle check return failed",
90*4c3888b8SHans Rosenfeld 	QL_FM_DEVICE_DMA_HANDLE_ERR,
91*4c3888b8SHans Rosenfeld 	DDI_FM_DEVICE_INTERN_CORR,
92*4c3888b8SHans Rosenfeld 	DDI_SERVICE_UNAFFECTED},
93*4c3888b8SHans Rosenfeld 
94*4c3888b8SHans Rosenfeld 	/* Reporting Standard I/O controller Errors */
95*4c3888b8SHans Rosenfeld 
96*4c3888b8SHans Rosenfeld 	/* End of table */
97*4c3888b8SHans Rosenfeld 	{0, NULL, NULL, NULL, 0},
98*4c3888b8SHans Rosenfeld };
99*4c3888b8SHans Rosenfeld 
100*4c3888b8SHans Rosenfeld 
101*4c3888b8SHans Rosenfeld int
qlc_fm_check_acc_handle(ql_adapter_state_t * ha,ddi_acc_handle_t handle)102*4c3888b8SHans Rosenfeld qlc_fm_check_acc_handle(ql_adapter_state_t *ha, ddi_acc_handle_t handle)
103*4c3888b8SHans Rosenfeld {
104*4c3888b8SHans Rosenfeld 
105*4c3888b8SHans Rosenfeld 	ddi_fm_error_t err;
106*4c3888b8SHans Rosenfeld 
107*4c3888b8SHans Rosenfeld 	if (!DDI_FM_ACC_ERR_CAP(ha->fm_capabilities)) {
108*4c3888b8SHans Rosenfeld 		return (DDI_FM_OK);
109*4c3888b8SHans Rosenfeld 	}
110*4c3888b8SHans Rosenfeld 	err.fme_status = DDI_FM_OK;
111*4c3888b8SHans Rosenfeld 
112*4c3888b8SHans Rosenfeld 	ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION);
113*4c3888b8SHans Rosenfeld 
114*4c3888b8SHans Rosenfeld 	if ((void *)&ddi_fm_acc_err_clear != NULL)
115*4c3888b8SHans Rosenfeld 		(void) ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
116*4c3888b8SHans Rosenfeld 
117*4c3888b8SHans Rosenfeld 	return (err.fme_status);
118*4c3888b8SHans Rosenfeld }
119*4c3888b8SHans Rosenfeld 
120*4c3888b8SHans Rosenfeld /*ARGSUSED*/
121*4c3888b8SHans Rosenfeld int
qlc_fm_check_dma_handle(ql_adapter_state_t * ha,ddi_dma_handle_t handle)122*4c3888b8SHans Rosenfeld qlc_fm_check_dma_handle(ql_adapter_state_t *ha, ddi_dma_handle_t handle)
123*4c3888b8SHans Rosenfeld {
124*4c3888b8SHans Rosenfeld 	ddi_fm_error_t err;
125*4c3888b8SHans Rosenfeld 
126*4c3888b8SHans Rosenfeld 	if (!DDI_FM_DMA_ERR_CAP(ha->fm_capabilities)) {
127*4c3888b8SHans Rosenfeld 		return (DDI_FM_OK);
128*4c3888b8SHans Rosenfeld 	}
129*4c3888b8SHans Rosenfeld 
130*4c3888b8SHans Rosenfeld 	err.fme_status = DDI_FM_OK;
131*4c3888b8SHans Rosenfeld 
132*4c3888b8SHans Rosenfeld 	ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION);
133*4c3888b8SHans Rosenfeld 
134*4c3888b8SHans Rosenfeld 	return (err.fme_status);
135*4c3888b8SHans Rosenfeld 
136*4c3888b8SHans Rosenfeld }
137*4c3888b8SHans Rosenfeld 
138*4c3888b8SHans Rosenfeld 
139*4c3888b8SHans Rosenfeld void
qlc_fm_check_pkt_dma_handle(ql_adapter_state_t * ha,ql_srb_t * sb)140*4c3888b8SHans Rosenfeld qlc_fm_check_pkt_dma_handle(ql_adapter_state_t *ha, ql_srb_t *sb)
141*4c3888b8SHans Rosenfeld {
142*4c3888b8SHans Rosenfeld 	fc_packet_t	*pkt = sb->pkt;
143*4c3888b8SHans Rosenfeld 	int		rval = DDI_FM_OK;
144*4c3888b8SHans Rosenfeld 
145*4c3888b8SHans Rosenfeld 
146*4c3888b8SHans Rosenfeld 	if (!DDI_FM_DMA_ERR_CAP(ha->fm_capabilities)) {
147*4c3888b8SHans Rosenfeld 		return;
148*4c3888b8SHans Rosenfeld 	}
149*4c3888b8SHans Rosenfeld 
150*4c3888b8SHans Rosenfeld 	if (pkt->pkt_cmd_acc != NULL && pkt->pkt_cmdlen) {
151*4c3888b8SHans Rosenfeld 		rval = qlc_fm_check_dma_handle(ha, pkt->pkt_cmd_dma);
152*4c3888b8SHans Rosenfeld 	}
153*4c3888b8SHans Rosenfeld 
154*4c3888b8SHans Rosenfeld 	if (pkt->pkt_resp_acc != NULL && rval == DDI_FM_OK &&
155*4c3888b8SHans Rosenfeld 	    pkt->pkt_rsplen != 0) {
156*4c3888b8SHans Rosenfeld 		rval = qlc_fm_check_dma_handle(ha, pkt->pkt_resp_dma);
157*4c3888b8SHans Rosenfeld 	}
158*4c3888b8SHans Rosenfeld 
159*4c3888b8SHans Rosenfeld 	if (((pkt->pkt_data_acc != NULL) & (rval == DDI_FM_OK) &
160*4c3888b8SHans Rosenfeld 	    (pkt->pkt_datalen != 0)) != 0) {
161*4c3888b8SHans Rosenfeld 		rval = qlc_fm_check_dma_handle(ha, pkt->pkt_data_dma);
162*4c3888b8SHans Rosenfeld 	}
163*4c3888b8SHans Rosenfeld 
164*4c3888b8SHans Rosenfeld 	if (rval != DDI_FM_OK) {
165*4c3888b8SHans Rosenfeld 		pkt->pkt_state = FC_PKT_TRAN_ERROR;
166*4c3888b8SHans Rosenfeld 		pkt->pkt_reason = FC_REASON_DMA_ERROR;
167*4c3888b8SHans Rosenfeld 		pkt->pkt_expln = FC_EXPLN_NONE;
168*4c3888b8SHans Rosenfeld 		pkt->pkt_action = FC_ACTION_RETRYABLE;
169*4c3888b8SHans Rosenfeld 
170*4c3888b8SHans Rosenfeld 		(void) qlc_fm_report_err_impact(ha,
171*4c3888b8SHans Rosenfeld 		    QL_FM_EREPORT_DMA_HANDLE_CHECK);
172*4c3888b8SHans Rosenfeld 	}
173*4c3888b8SHans Rosenfeld 
174*4c3888b8SHans Rosenfeld }
175*4c3888b8SHans Rosenfeld 
176*4c3888b8SHans Rosenfeld /*
177*4c3888b8SHans Rosenfeld  * The IO fault service error handling callback function
178*4c3888b8SHans Rosenfeld  */
179*4c3888b8SHans Rosenfeld 
180*4c3888b8SHans Rosenfeld /*ARGSUSED*/
181*4c3888b8SHans Rosenfeld int
qlc_fm_error_cb(dev_info_t * dip,ddi_fm_error_t * err,const void * impl_data)182*4c3888b8SHans Rosenfeld qlc_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
183*4c3888b8SHans Rosenfeld {
184*4c3888b8SHans Rosenfeld 	pci_ereport_post(dip, err, NULL);
185*4c3888b8SHans Rosenfeld 
186*4c3888b8SHans Rosenfeld 	return (err->fme_status);
187*4c3888b8SHans Rosenfeld 
188*4c3888b8SHans Rosenfeld }
189*4c3888b8SHans Rosenfeld 
190*4c3888b8SHans Rosenfeld /*ARGSUSED*/
191*4c3888b8SHans Rosenfeld void
qlc_fm_service_impact(ql_adapter_state_t * ha,int impact)192*4c3888b8SHans Rosenfeld qlc_fm_service_impact(ql_adapter_state_t *ha, int impact)
193*4c3888b8SHans Rosenfeld {
194*4c3888b8SHans Rosenfeld 	if (!DDI_FM_EREPORT_CAP(ha->fm_capabilities)) {
195*4c3888b8SHans Rosenfeld 		return;
196*4c3888b8SHans Rosenfeld 	}
197*4c3888b8SHans Rosenfeld 
198*4c3888b8SHans Rosenfeld 	ddi_fm_service_impact(ha->dip, impact);
199*4c3888b8SHans Rosenfeld }
200*4c3888b8SHans Rosenfeld 
201*4c3888b8SHans Rosenfeld 
202*4c3888b8SHans Rosenfeld /*ARGSUSED*/
203*4c3888b8SHans Rosenfeld void
qlc_fm_init(ql_adapter_state_t * ha)204*4c3888b8SHans Rosenfeld qlc_fm_init(ql_adapter_state_t *ha)
205*4c3888b8SHans Rosenfeld {
206*4c3888b8SHans Rosenfeld 	ddi_iblock_cookie_t iblk;
207*4c3888b8SHans Rosenfeld 
208*4c3888b8SHans Rosenfeld 	if (ha->fm_capabilities == DDI_FM_NOT_CAPABLE) {
209*4c3888b8SHans Rosenfeld 		return;
210*4c3888b8SHans Rosenfeld 	}
211*4c3888b8SHans Rosenfeld 
212*4c3888b8SHans Rosenfeld 	/*
213*4c3888b8SHans Rosenfeld 	 * Register capabilities with IO Fault Services.
214*4c3888b8SHans Rosenfeld 	 */
215*4c3888b8SHans Rosenfeld 	if (ha->fm_capabilities) {
216*4c3888b8SHans Rosenfeld 		ddi_fm_init(ha->dip, (int *)&ha->fm_capabilities, &iblk);
217*4c3888b8SHans Rosenfeld 	}
218*4c3888b8SHans Rosenfeld 
219*4c3888b8SHans Rosenfeld 	/*
220*4c3888b8SHans Rosenfeld 	 * Initialize pci ereport capabilities if ereport capable
221*4c3888b8SHans Rosenfeld 	 * PCI-related errors are automatically detected and reported
222*4c3888b8SHans Rosenfeld 	 */
223*4c3888b8SHans Rosenfeld 	if (DDI_FM_EREPORT_CAP(ha->fm_capabilities) ||
224*4c3888b8SHans Rosenfeld 	    DDI_FM_ERRCB_CAP(ha->fm_capabilities)) {
225*4c3888b8SHans Rosenfeld 		pci_ereport_setup(ha->dip);
226*4c3888b8SHans Rosenfeld 	}
227*4c3888b8SHans Rosenfeld 
228*4c3888b8SHans Rosenfeld 	/*
229*4c3888b8SHans Rosenfeld 	 * Register error callback if error callback capable.
230*4c3888b8SHans Rosenfeld 	 */
231*4c3888b8SHans Rosenfeld 	if (DDI_FM_ERRCB_CAP(ha->fm_capabilities)) {
232*4c3888b8SHans Rosenfeld 		ddi_fm_handler_register(ha->dip,
233*4c3888b8SHans Rosenfeld 		    qlc_fm_error_cb, (void*)ha);
234*4c3888b8SHans Rosenfeld 	}
235*4c3888b8SHans Rosenfeld 
236*4c3888b8SHans Rosenfeld 	/*
237*4c3888b8SHans Rosenfeld 	 * DDI_FLAGERR_ACC indicates:
238*4c3888b8SHans Rosenfeld 	 * 1. Driver will check its access handle(s) for faults on
239*4c3888b8SHans Rosenfeld 	 *    a regular basis by calling ddi_fm_acc_err_get
240*4c3888b8SHans Rosenfeld 	 * 2. Driver is able to cope with incorrect results of I/O
241*4c3888b8SHans Rosenfeld 	 *    operations resulted from an I/O fault.
242*4c3888b8SHans Rosenfeld 	 */
243*4c3888b8SHans Rosenfeld 	if (DDI_FM_ACC_ERR_CAP(ha->fm_capabilities)) {
244*4c3888b8SHans Rosenfeld 		ql_dev_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
245*4c3888b8SHans Rosenfeld 	} else {
246*4c3888b8SHans Rosenfeld 		ql_dev_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
247*4c3888b8SHans Rosenfeld 	}
248*4c3888b8SHans Rosenfeld 
249*4c3888b8SHans Rosenfeld 	/*
250*4c3888b8SHans Rosenfeld 	 * per instance based setup only
251*4c3888b8SHans Rosenfeld 	 */
252*4c3888b8SHans Rosenfeld 	if (DDI_FM_DMA_ERR_CAP(ha->fm_capabilities)) {
253*4c3888b8SHans Rosenfeld 		ha->bit32_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
254*4c3888b8SHans Rosenfeld 		ha->bit64_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
255*4c3888b8SHans Rosenfeld 
256*4c3888b8SHans Rosenfeld 	} else {
257*4c3888b8SHans Rosenfeld 		ha->bit32_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
258*4c3888b8SHans Rosenfeld 		ha->bit64_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
259*4c3888b8SHans Rosenfeld 	}
260*4c3888b8SHans Rosenfeld 
261*4c3888b8SHans Rosenfeld }
262*4c3888b8SHans Rosenfeld 
263*4c3888b8SHans Rosenfeld 
264*4c3888b8SHans Rosenfeld void
qlc_fm_fini(ql_adapter_state_t * ha)265*4c3888b8SHans Rosenfeld qlc_fm_fini(ql_adapter_state_t *ha)
266*4c3888b8SHans Rosenfeld {
267*4c3888b8SHans Rosenfeld 	if (ha->fm_capabilities) {
268*4c3888b8SHans Rosenfeld 		/*
269*4c3888b8SHans Rosenfeld 		 * Release any resources allocated by pci_ereport_setup()
270*4c3888b8SHans Rosenfeld 		 */
271*4c3888b8SHans Rosenfeld 		if (DDI_FM_EREPORT_CAP(ha->fm_capabilities) ||
272*4c3888b8SHans Rosenfeld 		    DDI_FM_ERRCB_CAP(ha->fm_capabilities)) {
273*4c3888b8SHans Rosenfeld 			pci_ereport_teardown(ha->dip);
274*4c3888b8SHans Rosenfeld 		}
275*4c3888b8SHans Rosenfeld 
276*4c3888b8SHans Rosenfeld 		if (DDI_FM_ERRCB_CAP(ha->fm_capabilities)) {
277*4c3888b8SHans Rosenfeld 			ddi_fm_handler_unregister(ha->dip);
278*4c3888b8SHans Rosenfeld 		}
279*4c3888b8SHans Rosenfeld 
280*4c3888b8SHans Rosenfeld 		/* Unregister from IO Fault Services */
281*4c3888b8SHans Rosenfeld 		ddi_fm_fini(ha->dip);
282*4c3888b8SHans Rosenfeld 	}
283*4c3888b8SHans Rosenfeld 
284*4c3888b8SHans Rosenfeld }
285*4c3888b8SHans Rosenfeld 
286*4c3888b8SHans Rosenfeld 
287*4c3888b8SHans Rosenfeld void
qlc_fm_report_err_impact(ql_adapter_state_t * ha,uint32_t fid)288*4c3888b8SHans Rosenfeld qlc_fm_report_err_impact(ql_adapter_state_t *ha, uint32_t fid)
289*4c3888b8SHans Rosenfeld {
290*4c3888b8SHans Rosenfeld 	uint64_t ena;
291*4c3888b8SHans Rosenfeld 	char eclass[QL_FM_MAX_CLASS];
292*4c3888b8SHans Rosenfeld 	qlc_fm_ereport_t *ereport = NULL;
293*4c3888b8SHans Rosenfeld 
294*4c3888b8SHans Rosenfeld 	if (!DDI_FM_EREPORT_CAP(ha->fm_capabilities)) {
295*4c3888b8SHans Rosenfeld 		return;
296*4c3888b8SHans Rosenfeld 	}
297*4c3888b8SHans Rosenfeld 
298*4c3888b8SHans Rosenfeld 	if (fid > QL_FM_EREPORT_NONE) {
299*4c3888b8SHans Rosenfeld 		cmn_err(CE_NOTE, "Not reported yet");
300*4c3888b8SHans Rosenfeld 		return;
301*4c3888b8SHans Rosenfeld 	}
302*4c3888b8SHans Rosenfeld 
303*4c3888b8SHans Rosenfeld 	ereport = &qlc_fm_ereport_tbl[fid];
304*4c3888b8SHans Rosenfeld 
305*4c3888b8SHans Rosenfeld 	/* We already have everything we need in ereport */
306*4c3888b8SHans Rosenfeld 	(void) snprintf(eclass, QL_FM_MAX_CLASS, "%s.%s",
307*4c3888b8SHans Rosenfeld 	    DDI_FM_DEVICE,
308*4c3888b8SHans Rosenfeld 	    ereport->gen_eclass);
309*4c3888b8SHans Rosenfeld 
310*4c3888b8SHans Rosenfeld 	ena = fm_ena_generate(0, FM_ENA_FMT1);
311*4c3888b8SHans Rosenfeld 
312*4c3888b8SHans Rosenfeld 	switch (ereport->fid) {
313*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_DMA_ERR:
314*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_BAD_PAYLOAD:
315*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_CMD_FAILED:
316*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_CHIP_HANG:
317*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_UNKNOWN:
318*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_MBA_REQ_TRANSFER_ERR:
319*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_MBA_RSP_TRANSFER_ERR:
320*4c3888b8SHans Rosenfeld 
321*4c3888b8SHans Rosenfeld 		ddi_fm_ereport_post(ha->dip, eclass, ena,
322*4c3888b8SHans Rosenfeld 		    DDI_NOSLEEP,
323*4c3888b8SHans Rosenfeld 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
324*4c3888b8SHans Rosenfeld 		    "Detailed error desc", DATA_TYPE_STRING, ereport->desc,
325*4c3888b8SHans Rosenfeld 		    "Instance number", DATA_TYPE_UINT8, ha->instance,
326*4c3888b8SHans Rosenfeld 		    NULL);
327*4c3888b8SHans Rosenfeld 
328*4c3888b8SHans Rosenfeld 		break;
329*4c3888b8SHans Rosenfeld 
330*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_ACC_HANDLE_CHECK:
331*4c3888b8SHans Rosenfeld 	case QL_FM_EREPORT_DMA_HANDLE_CHECK:
332*4c3888b8SHans Rosenfeld 	/*
333*4c3888b8SHans Rosenfeld 	 * Adjust the impact code based on the state
334*4c3888b8SHans Rosenfeld 	 * of the device: For example, if check failed
335*4c3888b8SHans Rosenfeld 	 * during attach, then impact is DDI_SERVICE_LOST.
336*4c3888b8SHans Rosenfeld 	 *
337*4c3888b8SHans Rosenfeld 	 * driver's callback qlc_fm_error_cb() registerd will report error.
338*4c3888b8SHans Rosenfeld 	 * We only need to report service impact here.
339*4c3888b8SHans Rosenfeld 	 */
340*4c3888b8SHans Rosenfeld 		ddi_fm_ereport_post(ha->dip, eclass, ena,
341*4c3888b8SHans Rosenfeld 		    DDI_NOSLEEP,
342*4c3888b8SHans Rosenfeld 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
343*4c3888b8SHans Rosenfeld 		    "Detailed error desc", DATA_TYPE_STRING, ereport->desc,
344*4c3888b8SHans Rosenfeld 		    "Instance number", DATA_TYPE_UINT8, ha->instance,
345*4c3888b8SHans Rosenfeld 		    NULL);
346*4c3888b8SHans Rosenfeld 
347*4c3888b8SHans Rosenfeld 		break;
348*4c3888b8SHans Rosenfeld 
349*4c3888b8SHans Rosenfeld 	default:
350*4c3888b8SHans Rosenfeld 		ddi_fm_ereport_post(ha->dip, eclass, ena,
351*4c3888b8SHans Rosenfeld 		    DDI_NOSLEEP,
352*4c3888b8SHans Rosenfeld 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
353*4c3888b8SHans Rosenfeld 
354*4c3888b8SHans Rosenfeld 		break;
355*4c3888b8SHans Rosenfeld 	}
356*4c3888b8SHans Rosenfeld 
357*4c3888b8SHans Rosenfeld 	qlc_fm_service_impact(ha, ereport->impact_code);
358*4c3888b8SHans Rosenfeld }
359