1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
88f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
98f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
238f23e9faSHans Rosenfeld  * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25*a3170057SPaul Winder  * Copyright 2020 RackTop Systems, Inc.
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_FCP_C);
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte #define	EMLXS_GET_VADDR(hba, rp, icmd) emlxs_mem_get_vaddr(hba, rp, \
3482527734SSukumar Swaminathan 	PADDR(icmd->un.cont64[i].addrHigh, icmd->un.cont64[i].addrLow));
35fcf3ce44SJohn Forte 
36291a2b48SSukumar Swaminathan static void	emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp,
37291a2b48SSukumar Swaminathan     Q *abort, uint8_t *flag, emlxs_buf_t *fpkt);
38fcf3ce44SJohn Forte 
39fcf3ce44SJohn Forte #define	SCSI3_PERSISTENT_RESERVE_IN	0x5e
40291a2b48SSukumar Swaminathan #define	SCSI_INQUIRY			0x12
41291a2b48SSukumar Swaminathan #define	SCSI_RX_DIAG    		0x1C
42fcf3ce44SJohn Forte 
43fcf3ce44SJohn Forte 
44fcf3ce44SJohn Forte /*
45fcf3ce44SJohn Forte  *  emlxs_handle_fcp_event
46fcf3ce44SJohn Forte  *
47fcf3ce44SJohn Forte  *  Description: Process an FCP Rsp Ring completion
48fcf3ce44SJohn Forte  *
49fcf3ce44SJohn Forte  */
50fcf3ce44SJohn Forte /* ARGSUSED */
51fcf3ce44SJohn Forte extern void
emlxs_handle_fcp_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)5282527734SSukumar Swaminathan emlxs_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
53fcf3ce44SJohn Forte {
54fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5582527734SSukumar Swaminathan 	emlxs_config_t	*cfg = &CFG;
56fcf3ce44SJohn Forte 	IOCB *cmd;
57fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
58fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
59291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
60291a2b48SSukumar Swaminathan 	NODELIST *ndlp;
61291a2b48SSukumar Swaminathan #endif
62fcf3ce44SJohn Forte 	uint32_t iostat;
63fcf3ce44SJohn Forte 	uint8_t localstat;
64fcf3ce44SJohn Forte 	fcp_rsp_t *rsp;
65fcf3ce44SJohn Forte 	uint32_t rsp_data_resid;
66fcf3ce44SJohn Forte 	uint32_t check_underrun;
67fcf3ce44SJohn Forte 	uint8_t asc;
68fcf3ce44SJohn Forte 	uint8_t ascq;
69fcf3ce44SJohn Forte 	uint8_t scsi_status;
70fcf3ce44SJohn Forte 	uint8_t sense;
71fcf3ce44SJohn Forte 	uint32_t did;
72fcf3ce44SJohn Forte 	uint32_t fix_it;
73fcf3ce44SJohn Forte 	uint8_t *scsi_cmd;
74fcf3ce44SJohn Forte 	uint8_t scsi_opcode;
75fcf3ce44SJohn Forte 	uint16_t scsi_dl;
76fcf3ce44SJohn Forte 	uint32_t data_rx;
778f23e9faSHans Rosenfeld 	uint32_t length;
78fcf3ce44SJohn Forte 
79fcf3ce44SJohn Forte 	cmd = &iocbq->iocb;
80fcf3ce44SJohn Forte 
81fcf3ce44SJohn Forte 	/* Initialize the status */
8282527734SSukumar Swaminathan 	iostat = cmd->ULPSTATUS;
83fcf3ce44SJohn Forte 	localstat = 0;
84fcf3ce44SJohn Forte 	scsi_status = 0;
85fcf3ce44SJohn Forte 	asc = 0;
86fcf3ce44SJohn Forte 	ascq = 0;
87fcf3ce44SJohn Forte 	sense = 0;
88fcf3ce44SJohn Forte 	check_underrun = 0;
89fcf3ce44SJohn Forte 	fix_it = 0;
90fcf3ce44SJohn Forte 
91fcf3ce44SJohn Forte 	HBASTATS.FcpEvent++;
92fcf3ce44SJohn Forte 
93fcf3ce44SJohn Forte 	sbp = (emlxs_buf_t *)iocbq->sbp;
94fcf3ce44SJohn Forte 
95fcf3ce44SJohn Forte 	if (!sbp) {
96fcf3ce44SJohn Forte 		/* completion with missing xmit command */
97fcf3ce44SJohn Forte 		HBASTATS.FcpStray++;
98fcf3ce44SJohn Forte 
99fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_fcp_completion_msg,
1008f23e9faSHans Rosenfeld 		    "cmd=%x iotag=%d", cmd->ULPCOMMAND, cmd->ULPIOTAG);
101fcf3ce44SJohn Forte 
102fcf3ce44SJohn Forte 		return;
103fcf3ce44SJohn Forte 	}
104291a2b48SSukumar Swaminathan 
105fcf3ce44SJohn Forte 	HBASTATS.FcpCompleted++;
106fcf3ce44SJohn Forte 
107291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
108291a2b48SSukumar Swaminathan 	emlxs_update_sd_bucket(sbp);
109291a2b48SSukumar Swaminathan #endif /* SAN_DIAG_SUPPORT */
110291a2b48SSukumar Swaminathan 
111fcf3ce44SJohn Forte 	pkt = PRIV2PKT(sbp);
112fcf3ce44SJohn Forte 
11382527734SSukumar Swaminathan 	did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
114fcf3ce44SJohn Forte 	scsi_cmd = (uint8_t *)pkt->pkt_cmd;
115fcf3ce44SJohn Forte 	scsi_opcode = scsi_cmd[12];
116fcf3ce44SJohn Forte 	data_rx = 0;
117fcf3ce44SJohn Forte 
118fcf3ce44SJohn Forte 	/* Sync data in data buffer only on FC_PKT_FCP_READ */
119fcf3ce44SJohn Forte 	if (pkt->pkt_datalen && (pkt->pkt_tran_type == FC_PKT_FCP_READ)) {
12082527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen,
121fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORKERNEL);
122fcf3ce44SJohn Forte 
123fcf3ce44SJohn Forte #ifdef TEST_SUPPORT
124fcf3ce44SJohn Forte 		if (hba->underrun_counter && (iostat == IOSTAT_SUCCESS) &&
125fcf3ce44SJohn Forte 		    (pkt->pkt_datalen >= 512)) {
126fcf3ce44SJohn Forte 			hba->underrun_counter--;
127fcf3ce44SJohn Forte 			iostat = IOSTAT_FCP_RSP_ERROR;
128fcf3ce44SJohn Forte 
129fcf3ce44SJohn Forte 			/* Report 512 bytes missing by adapter */
130fcf3ce44SJohn Forte 			cmd->un.fcpi.fcpi_parm = pkt->pkt_datalen - 512;
131fcf3ce44SJohn Forte 
132fcf3ce44SJohn Forte 			/* Corrupt 512 bytes of Data buffer */
133fcf3ce44SJohn Forte 			bzero((uint8_t *)pkt->pkt_data, 512);
134fcf3ce44SJohn Forte 
135fcf3ce44SJohn Forte 			/* Set FCP response to STATUS_GOOD */
136fcf3ce44SJohn Forte 			bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen);
137fcf3ce44SJohn Forte 		}
138291a2b48SSukumar Swaminathan #endif /* TEST_SUPPORT */
139fcf3ce44SJohn Forte 	}
140291a2b48SSukumar Swaminathan 
141fcf3ce44SJohn Forte 	/* Process the pkt */
142fcf3ce44SJohn Forte 	mutex_enter(&sbp->mtx);
143fcf3ce44SJohn Forte 
144fcf3ce44SJohn Forte 	/* Check for immediate return */
145fcf3ce44SJohn Forte 	if ((iostat == IOSTAT_SUCCESS) &&
146fcf3ce44SJohn Forte 	    (pkt->pkt_comp) &&
147291a2b48SSukumar Swaminathan 	    !(sbp->pkt_flags &
14882527734SSukumar Swaminathan 	    (PACKET_ULP_OWNED | PACKET_COMPLETED |
149fcf3ce44SJohn Forte 	    PACKET_IN_COMPLETION | PACKET_IN_TXQ | PACKET_IN_CHIPQ |
150fcf3ce44SJohn Forte 	    PACKET_IN_DONEQ | PACKET_IN_TIMEOUT | PACKET_IN_FLUSH |
151fcf3ce44SJohn Forte 	    PACKET_IN_ABORT | PACKET_POLLED))) {
152fcf3ce44SJohn Forte 		HBASTATS.FcpGood++;
153fcf3ce44SJohn Forte 
154291a2b48SSukumar Swaminathan 		sbp->pkt_flags |=
155291a2b48SSukumar Swaminathan 		    (PACKET_STATE_VALID | PACKET_IN_COMPLETION |
15682527734SSukumar Swaminathan 		    PACKET_COMPLETED | PACKET_ULP_OWNED);
157fcf3ce44SJohn Forte 		mutex_exit(&sbp->mtx);
158fcf3ce44SJohn Forte 
159fcf3ce44SJohn Forte #if (EMLXS_MODREVX == EMLXS_MODREV2X)
160fcf3ce44SJohn Forte 		emlxs_unswap_pkt(sbp);
161291a2b48SSukumar Swaminathan #endif /* EMLXS_MODREV2X */
162b3660a96SSukumar Swaminathan 
163b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
164b3660a96SSukumar Swaminathan 		emlxs_check_dma(hba, sbp);
165b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
166b3660a96SSukumar Swaminathan 
16782527734SSukumar Swaminathan 		cp->ulpCmplCmd++;
168fcf3ce44SJohn Forte 		(*pkt->pkt_comp) (pkt);
169fcf3ce44SJohn Forte 
170b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
171b3660a96SSukumar Swaminathan 		if (hba->flag & FC_DMA_CHECK_ERROR) {
172b3660a96SSukumar Swaminathan 			emlxs_thread_spawn(hba, emlxs_restart_thread,
173b3660a96SSukumar Swaminathan 			    NULL, NULL);
174b3660a96SSukumar Swaminathan 		}
175b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
176b3660a96SSukumar Swaminathan 
177fcf3ce44SJohn Forte 		return;
178fcf3ce44SJohn Forte 	}
179291a2b48SSukumar Swaminathan 
180fcf3ce44SJohn Forte 	/*
181291a2b48SSukumar Swaminathan 	 * A response is only placed in the resp buffer if IOSTAT_FCP_RSP_ERROR
182291a2b48SSukumar Swaminathan 	 * is reported.
183fcf3ce44SJohn Forte 	 */
184fcf3ce44SJohn Forte 
1858f23e9faSHans Rosenfeld 	/* Check if a response buffer was not provided */
1868f23e9faSHans Rosenfeld 	if ((iostat != IOSTAT_FCP_RSP_ERROR) || (pkt->pkt_rsplen == 0)) {
1878f23e9faSHans Rosenfeld 		goto done;
1888f23e9faSHans Rosenfeld 	}
1898f23e9faSHans Rosenfeld 
1908f23e9faSHans Rosenfeld 	EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen,
1918f23e9faSHans Rosenfeld 	    DDI_DMA_SYNC_FORKERNEL);
1928f23e9faSHans Rosenfeld 
1938f23e9faSHans Rosenfeld 	/* Get the response buffer pointer */
1948f23e9faSHans Rosenfeld 	rsp = (fcp_rsp_t *)pkt->pkt_resp;
1958f23e9faSHans Rosenfeld 
1968f23e9faSHans Rosenfeld 	/* Validate the response payload */
1978f23e9faSHans Rosenfeld 	if (!rsp->fcp_u.fcp_status.resid_under &&
1988f23e9faSHans Rosenfeld 	    !rsp->fcp_u.fcp_status.resid_over) {
1998f23e9faSHans Rosenfeld 		rsp->fcp_resid = 0;
2008f23e9faSHans Rosenfeld 	}
2018f23e9faSHans Rosenfeld 
2028f23e9faSHans Rosenfeld 	if (!rsp->fcp_u.fcp_status.rsp_len_set) {
2038f23e9faSHans Rosenfeld 		rsp->fcp_response_len = 0;
2048f23e9faSHans Rosenfeld 	}
205fcf3ce44SJohn Forte 
2068f23e9faSHans Rosenfeld 	if (!rsp->fcp_u.fcp_status.sense_len_set) {
2078f23e9faSHans Rosenfeld 		rsp->fcp_sense_len = 0;
2088f23e9faSHans Rosenfeld 	}
2098f23e9faSHans Rosenfeld 
2108f23e9faSHans Rosenfeld 	length = sizeof (fcp_rsp_t) + LE_SWAP32(rsp->fcp_response_len) +
2118f23e9faSHans Rosenfeld 	    LE_SWAP32(rsp->fcp_sense_len);
2128f23e9faSHans Rosenfeld 
2138f23e9faSHans Rosenfeld 	if (length > pkt->pkt_rsplen) {
2148f23e9faSHans Rosenfeld 		iostat = IOSTAT_RSP_INVALID;
2158f23e9faSHans Rosenfeld 		pkt->pkt_data_resid = pkt->pkt_datalen;
2168f23e9faSHans Rosenfeld 		goto done;
2178f23e9faSHans Rosenfeld 	}
218fcf3ce44SJohn Forte 
2198f23e9faSHans Rosenfeld 	/* Set the valid response flag */
2208f23e9faSHans Rosenfeld 	sbp->pkt_flags |= PACKET_FCP_RSP_VALID;
221fcf3ce44SJohn Forte 
2228f23e9faSHans Rosenfeld 	scsi_status = rsp->fcp_u.fcp_status.scsi_status;
223fcf3ce44SJohn Forte 
224291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
2258f23e9faSHans Rosenfeld 	ndlp = (NODELIST *)iocbq->node;
2268f23e9faSHans Rosenfeld 	if (scsi_status == SCSI_STAT_QUE_FULL) {
2278f23e9faSHans Rosenfeld 		emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_QFULL,
2288f23e9faSHans Rosenfeld 		    (HBA_WWN *)&ndlp->nlp_portname, sbp->lun);
2298f23e9faSHans Rosenfeld 	} else if (scsi_status == SCSI_STAT_BUSY) {
2308f23e9faSHans Rosenfeld 		emlxs_log_sd_scsi_event(port,
2318f23e9faSHans Rosenfeld 		    SD_SCSI_SUBCATEGORY_DEVBSY,
2328f23e9faSHans Rosenfeld 		    (HBA_WWN *)&ndlp->nlp_portname, sbp->lun);
2338f23e9faSHans Rosenfeld 	}
234291a2b48SSukumar Swaminathan #endif
235291a2b48SSukumar Swaminathan 
2368f23e9faSHans Rosenfeld 	/*
2378f23e9faSHans Rosenfeld 	 * Convert a task abort to a check condition with no data
2388f23e9faSHans Rosenfeld 	 * transferred. We saw a data corruption when Solaris received
2398f23e9faSHans Rosenfeld 	 * a Task Abort from a tape.
2408f23e9faSHans Rosenfeld 	 */
241a9800bebSGarrett D'Amore 
2428f23e9faSHans Rosenfeld 	if (scsi_status == SCSI_STAT_TASK_ABORT) {
2438f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT,
2448f23e9faSHans Rosenfeld 		    &emlxs_fcp_completion_error_msg,
2458f23e9faSHans Rosenfeld 		    "Task Abort. "
2468f23e9faSHans Rosenfeld 		    "Fixed. did=0x%06x sbp=%p cmd=%02x dl=%d",
2478f23e9faSHans Rosenfeld 		    did, sbp, scsi_opcode, pkt->pkt_datalen);
2488f23e9faSHans Rosenfeld 
2498f23e9faSHans Rosenfeld 		rsp->fcp_u.fcp_status.scsi_status =
2508f23e9faSHans Rosenfeld 		    SCSI_STAT_CHECK_COND;
2518f23e9faSHans Rosenfeld 		rsp->fcp_u.fcp_status.rsp_len_set = 0;
2528f23e9faSHans Rosenfeld 		rsp->fcp_u.fcp_status.sense_len_set = 0;
2538f23e9faSHans Rosenfeld 		rsp->fcp_u.fcp_status.resid_over = 0;
2548f23e9faSHans Rosenfeld 
2558f23e9faSHans Rosenfeld 		if (pkt->pkt_datalen) {
2568f23e9faSHans Rosenfeld 			rsp->fcp_u.fcp_status.resid_under = 1;
2578f23e9faSHans Rosenfeld 			rsp->fcp_resid =
2588f23e9faSHans Rosenfeld 			    LE_SWAP32(pkt->pkt_datalen);
2598f23e9faSHans Rosenfeld 		} else {
2608f23e9faSHans Rosenfeld 			rsp->fcp_u.fcp_status.resid_under = 0;
2618f23e9faSHans Rosenfeld 			rsp->fcp_resid = 0;
2628f23e9faSHans Rosenfeld 		}
263fcf3ce44SJohn Forte 
2648f23e9faSHans Rosenfeld 		scsi_status = SCSI_STAT_CHECK_COND;
2658f23e9faSHans Rosenfeld 	}
266fcf3ce44SJohn Forte 
2678f23e9faSHans Rosenfeld 	/*
2688f23e9faSHans Rosenfeld 	 * We only need to check underrun if data could
2698f23e9faSHans Rosenfeld 	 * have been sent
2708f23e9faSHans Rosenfeld 	 */
271fcf3ce44SJohn Forte 
2728f23e9faSHans Rosenfeld 	/* Always check underrun if status is good */
2738f23e9faSHans Rosenfeld 	if (scsi_status == SCSI_STAT_GOOD) {
2748f23e9faSHans Rosenfeld 		check_underrun = 1;
2758f23e9faSHans Rosenfeld 	}
2768f23e9faSHans Rosenfeld 	/* Check the sense codes if this is a check condition */
2778f23e9faSHans Rosenfeld 	else if (scsi_status == SCSI_STAT_CHECK_COND) {
2788f23e9faSHans Rosenfeld 		check_underrun = 1;
2798f23e9faSHans Rosenfeld 
2808f23e9faSHans Rosenfeld 		/* Check if sense data was provided */
2818f23e9faSHans Rosenfeld 		if (LE_SWAP32(rsp->fcp_sense_len) >= 14) {
2828f23e9faSHans Rosenfeld 			sense = *((uint8_t *)rsp + 32 + 2);
2838f23e9faSHans Rosenfeld 			asc = *((uint8_t *)rsp + 32 + 12);
2848f23e9faSHans Rosenfeld 			ascq = *((uint8_t *)rsp + 32 + 13);
285fcf3ce44SJohn Forte 		}
286291a2b48SSukumar Swaminathan 
2878f23e9faSHans Rosenfeld #ifdef SAN_DIAG_SUPPORT
2888f23e9faSHans Rosenfeld 		emlxs_log_sd_scsi_check_event(port,
2898f23e9faSHans Rosenfeld 		    (HBA_WWN *)&ndlp->nlp_portname, sbp->lun,
2908f23e9faSHans Rosenfeld 		    scsi_opcode, sense, asc, ascq);
2918f23e9faSHans Rosenfeld #endif
2928f23e9faSHans Rosenfeld 	}
2938f23e9faSHans Rosenfeld 	/* Status is not good and this is not a check condition */
2948f23e9faSHans Rosenfeld 	/* No data should have been sent */
2958f23e9faSHans Rosenfeld 	else {
2968f23e9faSHans Rosenfeld 		check_underrun = 0;
2978f23e9faSHans Rosenfeld 	}
2988f23e9faSHans Rosenfeld 
2998f23e9faSHans Rosenfeld 	/* Initialize the resids */
3008f23e9faSHans Rosenfeld 	pkt->pkt_resp_resid = 0;
3018f23e9faSHans Rosenfeld 	pkt->pkt_data_resid = 0;
3028f23e9faSHans Rosenfeld 
3038f23e9faSHans Rosenfeld 	/* Check if no data was to be transferred */
3048f23e9faSHans Rosenfeld 	if (pkt->pkt_datalen == 0) {
3058f23e9faSHans Rosenfeld 		goto done;
3068f23e9faSHans Rosenfeld 	}
3078f23e9faSHans Rosenfeld 
3088f23e9faSHans Rosenfeld 	/* Get the residual underrun count reported by the SCSI reply */
3098f23e9faSHans Rosenfeld 	rsp_data_resid = (rsp->fcp_u.fcp_status.resid_under) ?
3108f23e9faSHans Rosenfeld 	    LE_SWAP32(rsp->fcp_resid) : 0;
3118f23e9faSHans Rosenfeld 
3128f23e9faSHans Rosenfeld 	/* Set the pkt_data_resid to what the scsi response resid */
3138f23e9faSHans Rosenfeld 	pkt->pkt_data_resid = rsp_data_resid;
3148f23e9faSHans Rosenfeld 
3158f23e9faSHans Rosenfeld 	/* Adjust the pkt_data_resid field if needed */
3168f23e9faSHans Rosenfeld 	if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
317fcf3ce44SJohn Forte 		/*
3188f23e9faSHans Rosenfeld 		 * Get the residual underrun count reported by
3198f23e9faSHans Rosenfeld 		 * our adapter
320fcf3ce44SJohn Forte 		 */
3218f23e9faSHans Rosenfeld 		pkt->pkt_data_resid = cmd->un.fcpi.fcpi_parm;
322291a2b48SSukumar Swaminathan 
323291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
3248f23e9faSHans Rosenfeld 		if ((rsp_data_resid == 0) && (pkt->pkt_data_resid)) {
3258f23e9faSHans Rosenfeld 			emlxs_log_sd_fc_rdchk_event(port,
326291a2b48SSukumar Swaminathan 			    (HBA_WWN *)&ndlp->nlp_portname, sbp->lun,
3278f23e9faSHans Rosenfeld 			    scsi_opcode, pkt->pkt_data_resid);
328fcf3ce44SJohn Forte 		}
3298f23e9faSHans Rosenfeld #endif
3308f23e9faSHans Rosenfeld 
3318f23e9faSHans Rosenfeld 		/* Get the actual amount of data transferred */
3328f23e9faSHans Rosenfeld 		data_rx = pkt->pkt_datalen - pkt->pkt_data_resid;
333fcf3ce44SJohn Forte 
3348f23e9faSHans Rosenfeld 		/*
3358f23e9faSHans Rosenfeld 		 * If the residual being reported by the adapter is
3368f23e9faSHans Rosenfeld 		 * greater than the residual being reported in the
3378f23e9faSHans Rosenfeld 		 * reply, then we have a true underrun.
3388f23e9faSHans Rosenfeld 		 */
3398f23e9faSHans Rosenfeld 		if (check_underrun && (pkt->pkt_data_resid > rsp_data_resid)) {
3408f23e9faSHans Rosenfeld 			switch (scsi_opcode) {
3418f23e9faSHans Rosenfeld 			case SCSI_INQUIRY:
3428f23e9faSHans Rosenfeld 				scsi_dl = scsi_cmd[16];
3438f23e9faSHans Rosenfeld 				break;
3448f23e9faSHans Rosenfeld 
3458f23e9faSHans Rosenfeld 			case SCSI_RX_DIAG:
3468f23e9faSHans Rosenfeld 				scsi_dl =
3478f23e9faSHans Rosenfeld 				    (scsi_cmd[15] * 0x100) +
3488f23e9faSHans Rosenfeld 				    scsi_cmd[16];
3498f23e9faSHans Rosenfeld 				break;
350fcf3ce44SJohn Forte 
3518f23e9faSHans Rosenfeld 			default:
3528f23e9faSHans Rosenfeld 				scsi_dl = pkt->pkt_datalen;
3538f23e9faSHans Rosenfeld 			}
354fcf3ce44SJohn Forte 
3558f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH1
3568f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH1) {
357fcf3ce44SJohn Forte 			/*
3588f23e9faSHans Rosenfeld 			 * If status is not good and no data was
3598f23e9faSHans Rosenfeld 			 * actually transferred, then we must fix
3608f23e9faSHans Rosenfeld 			 * the issue
361fcf3ce44SJohn Forte 			 */
3628f23e9faSHans Rosenfeld 			if ((scsi_status != SCSI_STAT_GOOD) && (data_rx == 0)) {
3638f23e9faSHans Rosenfeld 				fix_it = 1;
3648f23e9faSHans Rosenfeld 
3658f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
3668f23e9faSHans Rosenfeld 				    &emlxs_fcp_completion_error_msg,
3678f23e9faSHans Rosenfeld 				    "Underrun(1). Fixed. "
3688f23e9faSHans Rosenfeld 				    "did=0x%06x sbp=%p cmd=%02x "
3698f23e9faSHans Rosenfeld 				    "dl=%d,%d rx=%d rsp=%d",
3708f23e9faSHans Rosenfeld 				    did, sbp, scsi_opcode,
3718f23e9faSHans Rosenfeld 				    pkt->pkt_datalen, scsi_dl,
3728f23e9faSHans Rosenfeld 				    (pkt->pkt_datalen -
3738f23e9faSHans Rosenfeld 				    pkt->pkt_data_resid),
3748f23e9faSHans Rosenfeld 				    rsp_data_resid);
375fcf3ce44SJohn Forte 
376291a2b48SSukumar Swaminathan 			}
3778f23e9faSHans Rosenfeld }
3788f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH1 */
379291a2b48SSukumar Swaminathan 
380fcf3ce44SJohn Forte 
3818f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH2
3828f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH2) {
3838f23e9faSHans Rosenfeld 			if (scsi_status == SCSI_STAT_GOOD) {
3848f23e9faSHans Rosenfeld 				emlxs_msg_t	*msg;
385fcf3ce44SJohn Forte 
3868f23e9faSHans Rosenfeld 				msg = &emlxs_fcp_completion_error_msg;
3878f23e9faSHans Rosenfeld 				/*
3888f23e9faSHans Rosenfeld 				 * If status is good and this is an
3898f23e9faSHans Rosenfeld 				 * inquiry request and the amount of
3908f23e9faSHans Rosenfeld 				 * data
3918f23e9faSHans Rosenfeld 				 */
3928f23e9faSHans Rosenfeld 				/*
3938f23e9faSHans Rosenfeld 				 * requested <= data received, then we
3948f23e9faSHans Rosenfeld 				 * must fix the issue.
3958f23e9faSHans Rosenfeld 				 */
3968f23e9faSHans Rosenfeld 
3978f23e9faSHans Rosenfeld 				if ((scsi_opcode == SCSI_INQUIRY) &&
3988f23e9faSHans Rosenfeld 				    (pkt->pkt_datalen >= data_rx) &&
3998f23e9faSHans Rosenfeld 				    (scsi_dl <= data_rx)) {
4008f23e9faSHans Rosenfeld 					fix_it = 1;
4018f23e9faSHans Rosenfeld 
4028f23e9faSHans Rosenfeld 					EMLXS_MSGF(EMLXS_CONTEXT, msg,
4038f23e9faSHans Rosenfeld 					    "Underrun(2). Fixed. "
4048f23e9faSHans Rosenfeld 					    "did=0x%06x sbp=%p "
4058f23e9faSHans Rosenfeld 					    "cmd=%02x dl=%d,%d "
4068f23e9faSHans Rosenfeld 					    "rx=%d rsp=%d",
4078f23e9faSHans Rosenfeld 					    did, sbp, scsi_opcode,
4088f23e9faSHans Rosenfeld 					    pkt->pkt_datalen, scsi_dl,
4098f23e9faSHans Rosenfeld 					    data_rx, rsp_data_resid);
410fcf3ce44SJohn Forte 
411fcf3ce44SJohn Forte 				}
412fcf3ce44SJohn Forte 
413fcf3ce44SJohn Forte 				/*
4148f23e9faSHans Rosenfeld 				 * If status is good and this is an
4158f23e9faSHans Rosenfeld 				 * inquiry request and the amount of
4168f23e9faSHans Rosenfeld 				 * data requested >= 128 bytes, but
4178f23e9faSHans Rosenfeld 				 * only 128 bytes were received,
4188f23e9faSHans Rosenfeld 				 * then we must fix the issue.
419fcf3ce44SJohn Forte 				 */
4208f23e9faSHans Rosenfeld 				else if ((scsi_opcode == SCSI_INQUIRY) &&
4218f23e9faSHans Rosenfeld 				    (pkt->pkt_datalen >= 128) &&
4228f23e9faSHans Rosenfeld 				    (scsi_dl >= 128) && (data_rx == 128)) {
423fcf3ce44SJohn Forte 					fix_it = 1;
424fcf3ce44SJohn Forte 
4258f23e9faSHans Rosenfeld 					EMLXS_MSGF(EMLXS_CONTEXT, msg,
4268f23e9faSHans Rosenfeld 					    "Underrun(3). Fixed. "
4278f23e9faSHans Rosenfeld 					    "did=0x%06x sbp=%p "
4288f23e9faSHans Rosenfeld 					    "cmd=%02x dl=%d,%d "
4298f23e9faSHans Rosenfeld 					    "rx=%d rsp=%d",
430fcf3ce44SJohn Forte 					    did, sbp, scsi_opcode,
431fcf3ce44SJohn Forte 					    pkt->pkt_datalen, scsi_dl,
4328f23e9faSHans Rosenfeld 					    data_rx, rsp_data_resid);
433fcf3ce44SJohn Forte 
434fcf3ce44SJohn Forte 				}
4358f23e9faSHans Rosenfeld 			}
43682527734SSukumar Swaminathan }
4378f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH2 */
438fcf3ce44SJohn Forte 
4398f23e9faSHans Rosenfeld 			/*
4408f23e9faSHans Rosenfeld 			 * Check if SCSI response payload should be
4418f23e9faSHans Rosenfeld 			 * fixed or if a DATA_UNDERRUN should be
4428f23e9faSHans Rosenfeld 			 * reported
4438f23e9faSHans Rosenfeld 			 */
4448f23e9faSHans Rosenfeld 			if (fix_it) {
4458f23e9faSHans Rosenfeld 				/*
4468f23e9faSHans Rosenfeld 				 * Fix the SCSI response payload itself
4478f23e9faSHans Rosenfeld 				 */
4488f23e9faSHans Rosenfeld 				rsp->fcp_u.fcp_status.resid_under = 1;
4498f23e9faSHans Rosenfeld 				rsp->fcp_resid =
4508f23e9faSHans Rosenfeld 				    LE_SWAP32(pkt->pkt_data_resid);
4518f23e9faSHans Rosenfeld 			} else {
4528f23e9faSHans Rosenfeld 				/*
4538f23e9faSHans Rosenfeld 				 * Change the status from
4548f23e9faSHans Rosenfeld 				 * IOSTAT_FCP_RSP_ERROR to
4558f23e9faSHans Rosenfeld 				 * IOSTAT_DATA_UNDERRUN
4568f23e9faSHans Rosenfeld 				 */
4578f23e9faSHans Rosenfeld 				iostat = IOSTAT_DATA_UNDERRUN;
4588f23e9faSHans Rosenfeld 				pkt->pkt_data_resid =
4598f23e9faSHans Rosenfeld 				    pkt->pkt_datalen;
4608f23e9faSHans Rosenfeld 			}
4618f23e9faSHans Rosenfeld 		}
462fcf3ce44SJohn Forte 
4638f23e9faSHans Rosenfeld 		/*
4648f23e9faSHans Rosenfeld 		 * If the residual being reported by the adapter is
4658f23e9faSHans Rosenfeld 		 * less than the residual being reported in the reply,
4668f23e9faSHans Rosenfeld 		 * then we have a true overrun. Since we don't know
4678f23e9faSHans Rosenfeld 		 * where the extra data came from or went to then we
4688f23e9faSHans Rosenfeld 		 * cannot trust anything we received
4698f23e9faSHans Rosenfeld 		 */
4708f23e9faSHans Rosenfeld 		else if (rsp_data_resid > pkt->pkt_data_resid) {
4718f23e9faSHans Rosenfeld 			/*
4728f23e9faSHans Rosenfeld 			 * Change the status from
4738f23e9faSHans Rosenfeld 			 * IOSTAT_FCP_RSP_ERROR to
4748f23e9faSHans Rosenfeld 			 * IOSTAT_DATA_OVERRUN
4758f23e9faSHans Rosenfeld 			 */
4768f23e9faSHans Rosenfeld 			iostat = IOSTAT_DATA_OVERRUN;
4778f23e9faSHans Rosenfeld 			pkt->pkt_data_resid = pkt->pkt_datalen;
4788f23e9faSHans Rosenfeld 		}
479fcf3ce44SJohn Forte 
4808f23e9faSHans Rosenfeld 	} else if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
4818f23e9faSHans Rosenfeld 	    (pkt->pkt_tran_type == FC_PKT_FCP_WRITE)) {
4828f23e9faSHans Rosenfeld 		/*
4838f23e9faSHans Rosenfeld 		 * Get the residual underrun count reported by
4848f23e9faSHans Rosenfeld 		 * our adapter
4858f23e9faSHans Rosenfeld 		 */
4868f23e9faSHans Rosenfeld 		pkt->pkt_data_resid = cmd->un.fcpi.fcpi_parm;
487fcf3ce44SJohn Forte 
4888f23e9faSHans Rosenfeld #ifdef SAN_DIAG_SUPPORT
4898f23e9faSHans Rosenfeld 		if ((rsp_data_resid == 0) && (pkt->pkt_data_resid)) {
4908f23e9faSHans Rosenfeld 			emlxs_log_sd_fc_rdchk_event(port,
4918f23e9faSHans Rosenfeld 			    (HBA_WWN *)&ndlp->nlp_portname, sbp->lun,
4928f23e9faSHans Rosenfeld 			    scsi_opcode, pkt->pkt_data_resid);
4938f23e9faSHans Rosenfeld 		}
4948f23e9faSHans Rosenfeld #endif /* SAN_DIAG_SUPPORT */
495fcf3ce44SJohn Forte 
4968f23e9faSHans Rosenfeld 		/* Get the actual amount of data transferred */
4978f23e9faSHans Rosenfeld 		data_rx = pkt->pkt_datalen - pkt->pkt_data_resid;
498fcf3ce44SJohn Forte 
4998f23e9faSHans Rosenfeld 		/*
5008f23e9faSHans Rosenfeld 		 * If the residual being reported by the adapter is
5018f23e9faSHans Rosenfeld 		 * greater than the residual being reported in the
5028f23e9faSHans Rosenfeld 		 * reply, then we have a true underrun.
5038f23e9faSHans Rosenfeld 		 */
5048f23e9faSHans Rosenfeld 		if (check_underrun && (pkt->pkt_data_resid > rsp_data_resid)) {
505291a2b48SSukumar Swaminathan 
5068f23e9faSHans Rosenfeld 			scsi_dl = pkt->pkt_datalen;
507fcf3ce44SJohn Forte 
5088f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH1
5098f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH1) {
5108f23e9faSHans Rosenfeld 			/*
5118f23e9faSHans Rosenfeld 			 * If status is not good and no data was
5128f23e9faSHans Rosenfeld 			 * actually transferred, then we must fix
5138f23e9faSHans Rosenfeld 			 * the issue
5148f23e9faSHans Rosenfeld 			 */
5158f23e9faSHans Rosenfeld 			if ((scsi_status != SCSI_STAT_GOOD) && (data_rx == 0)) {
5168f23e9faSHans Rosenfeld 				fix_it = 1;
517291a2b48SSukumar Swaminathan 
5188f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
5198f23e9faSHans Rosenfeld 				    &emlxs_fcp_completion_error_msg,
5208f23e9faSHans Rosenfeld 				    "Underrun(1). Fixed. "
5218f23e9faSHans Rosenfeld 				    "did=0x%06x sbp=%p cmd=%02x "
5228f23e9faSHans Rosenfeld 				    "dl=%d,%d rx=%d rsp=%d",
5238f23e9faSHans Rosenfeld 				    did, sbp, scsi_opcode,
5248f23e9faSHans Rosenfeld 				    pkt->pkt_datalen, scsi_dl,
5258f23e9faSHans Rosenfeld 				    (pkt->pkt_datalen -
5268f23e9faSHans Rosenfeld 				    pkt->pkt_data_resid),
5278f23e9faSHans Rosenfeld 				    rsp_data_resid);
528fcf3ce44SJohn Forte 
529fcf3ce44SJohn Forte 			}
5308f23e9faSHans Rosenfeld }
5318f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH1 */
532291a2b48SSukumar Swaminathan 
533fcf3ce44SJohn Forte 			/*
5348f23e9faSHans Rosenfeld 			 * Check if SCSI response payload should be
5358f23e9faSHans Rosenfeld 			 * fixed or if a DATA_UNDERRUN should be
5368f23e9faSHans Rosenfeld 			 * reported
537fcf3ce44SJohn Forte 			 */
5388f23e9faSHans Rosenfeld 			if (fix_it) {
5398f23e9faSHans Rosenfeld 				/*
5408f23e9faSHans Rosenfeld 				 * Fix the SCSI response payload itself
5418f23e9faSHans Rosenfeld 				 */
5428f23e9faSHans Rosenfeld 				rsp->fcp_u.fcp_status.resid_under = 1;
5438f23e9faSHans Rosenfeld 				rsp->fcp_resid =
5448f23e9faSHans Rosenfeld 				    LE_SWAP32(pkt->pkt_data_resid);
5458f23e9faSHans Rosenfeld 			} else {
546fcf3ce44SJohn Forte 				/*
547fcf3ce44SJohn Forte 				 * Change the status from
548fcf3ce44SJohn Forte 				 * IOSTAT_FCP_RSP_ERROR to
5498f23e9faSHans Rosenfeld 				 * IOSTAT_DATA_UNDERRUN
550fcf3ce44SJohn Forte 				 */
5518f23e9faSHans Rosenfeld 				iostat = IOSTAT_DATA_UNDERRUN;
5528f23e9faSHans Rosenfeld 				pkt->pkt_data_resid =
5538f23e9faSHans Rosenfeld 				    pkt->pkt_datalen;
554fcf3ce44SJohn Forte 			}
5558f23e9faSHans Rosenfeld 		}
556291a2b48SSukumar Swaminathan 
5578f23e9faSHans Rosenfeld 		/*
5588f23e9faSHans Rosenfeld 		 * If the residual being reported by the adapter is
5598f23e9faSHans Rosenfeld 		 * less than the residual being reported in the reply,
5608f23e9faSHans Rosenfeld 		 * then we have a true overrun. Since we don't know
5618f23e9faSHans Rosenfeld 		 * where the extra data came from or went to then we
5628f23e9faSHans Rosenfeld 		 * cannot trust anything we received
5638f23e9faSHans Rosenfeld 		 */
5648f23e9faSHans Rosenfeld 		else if (rsp_data_resid > pkt->pkt_data_resid) {
5658f23e9faSHans Rosenfeld 			/*
5668f23e9faSHans Rosenfeld 			 * Change the status from
5678f23e9faSHans Rosenfeld 			 * IOSTAT_FCP_RSP_ERROR to
5688f23e9faSHans Rosenfeld 			 * IOSTAT_DATA_OVERRUN
5698f23e9faSHans Rosenfeld 			 */
5708f23e9faSHans Rosenfeld 			iostat = IOSTAT_DATA_OVERRUN;
5718f23e9faSHans Rosenfeld 			pkt->pkt_data_resid = pkt->pkt_datalen;
572fcf3ce44SJohn Forte 		}
573fcf3ce44SJohn Forte 	}
574291a2b48SSukumar Swaminathan 
5758f23e9faSHans Rosenfeld done:
5768f23e9faSHans Rosenfeld 
577fcf3ce44SJohn Forte 	/* Print completion message */
578fcf3ce44SJohn Forte 	switch (iostat) {
579fcf3ce44SJohn Forte 	case IOSTAT_SUCCESS:
580fcf3ce44SJohn Forte 		/* Build SCSI GOOD status */
581fcf3ce44SJohn Forte 		if (pkt->pkt_rsplen) {
582fcf3ce44SJohn Forte 			bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen);
583fcf3ce44SJohn Forte 		}
584fcf3ce44SJohn Forte 		break;
585fcf3ce44SJohn Forte 
586fcf3ce44SJohn Forte 	case IOSTAT_FCP_RSP_ERROR:
587fcf3ce44SJohn Forte 		break;
588fcf3ce44SJohn Forte 
589fcf3ce44SJohn Forte 	case IOSTAT_REMOTE_STOP:
590fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
591291a2b48SSukumar Swaminathan 		    "Remote Stop. did=0x%06x sbp=%p cmd=%02x", did, sbp,
592291a2b48SSukumar Swaminathan 		    scsi_opcode);
593fcf3ce44SJohn Forte 		break;
594fcf3ce44SJohn Forte 
595fcf3ce44SJohn Forte 	case IOSTAT_LOCAL_REJECT:
596fcf3ce44SJohn Forte 		localstat = cmd->un.grsp.perr.statLocalError;
597fcf3ce44SJohn Forte 
598fcf3ce44SJohn Forte 		switch (localstat) {
599fcf3ce44SJohn Forte 		case IOERR_SEQUENCE_TIMEOUT:
600fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT,
601fcf3ce44SJohn Forte 			    &emlxs_fcp_completion_error_msg,
602291a2b48SSukumar Swaminathan 			    "Local reject. "
603291a2b48SSukumar Swaminathan 			    "%s did=0x%06x sbp=%p cmd=%02x tmo=%d ",
604fcf3ce44SJohn Forte 			    emlxs_error_xlate(localstat), did, sbp,
605fcf3ce44SJohn Forte 			    scsi_opcode, pkt->pkt_timeout);
606fcf3ce44SJohn Forte 			break;
607fcf3ce44SJohn Forte 
608fcf3ce44SJohn Forte 		default:
609fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT,
610fcf3ce44SJohn Forte 			    &emlxs_fcp_completion_error_msg,
611a9800bebSGarrett D'Amore 			    "Local reject. %s 0x%06x %p %02x (%x)(%x)",
612291a2b48SSukumar Swaminathan 			    emlxs_error_xlate(localstat), did, sbp,
613a9800bebSGarrett D'Amore 			    scsi_opcode, (uint16_t)cmd->ULPIOTAG,
614a9800bebSGarrett D'Amore 			    (uint16_t)cmd->ULPCONTEXT);
615fcf3ce44SJohn Forte 		}
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 		break;
618fcf3ce44SJohn Forte 
619fcf3ce44SJohn Forte 	case IOSTAT_NPORT_RJT:
620fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
621291a2b48SSukumar Swaminathan 		    "Nport reject. did=0x%06x sbp=%p cmd=%02x", did, sbp,
622291a2b48SSukumar Swaminathan 		    scsi_opcode);
623fcf3ce44SJohn Forte 		break;
624fcf3ce44SJohn Forte 
625fcf3ce44SJohn Forte 	case IOSTAT_FABRIC_RJT:
626fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
627291a2b48SSukumar Swaminathan 		    "Fabric reject. did=0x%06x sbp=%p cmd=%02x", did, sbp,
628291a2b48SSukumar Swaminathan 		    scsi_opcode);
629fcf3ce44SJohn Forte 		break;
630fcf3ce44SJohn Forte 
631fcf3ce44SJohn Forte 	case IOSTAT_NPORT_BSY:
632291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
633291a2b48SSukumar Swaminathan 		ndlp = (NODELIST *)iocbq->node;
634291a2b48SSukumar Swaminathan 		emlxs_log_sd_fc_bsy_event(port, (HBA_WWN *)&ndlp->nlp_portname);
635291a2b48SSukumar Swaminathan #endif
636291a2b48SSukumar Swaminathan 
637fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
638291a2b48SSukumar Swaminathan 		    "Nport busy. did=0x%06x sbp=%p cmd=%02x", did, sbp,
639291a2b48SSukumar Swaminathan 		    scsi_opcode);
640fcf3ce44SJohn Forte 		break;
641fcf3ce44SJohn Forte 
642fcf3ce44SJohn Forte 	case IOSTAT_FABRIC_BSY:
643291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT
644291a2b48SSukumar Swaminathan 		ndlp = (NODELIST *)iocbq->node;
645291a2b48SSukumar Swaminathan 		emlxs_log_sd_fc_bsy_event(port, NULL);
646291a2b48SSukumar Swaminathan #endif
647291a2b48SSukumar Swaminathan 
648fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
649291a2b48SSukumar Swaminathan 		    "Fabric busy. did=0x%06x sbp=%p cmd=%02x", did, sbp,
650291a2b48SSukumar Swaminathan 		    scsi_opcode);
651fcf3ce44SJohn Forte 		break;
652fcf3ce44SJohn Forte 
653fcf3ce44SJohn Forte 	case IOSTAT_INTERMED_RSP:
654fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
655291a2b48SSukumar Swaminathan 		    "Intermediate response. did=0x%06x sbp=%p cmd=%02x", did,
656291a2b48SSukumar Swaminathan 		    sbp, scsi_opcode);
657fcf3ce44SJohn Forte 		break;
658fcf3ce44SJohn Forte 
659fcf3ce44SJohn Forte 	case IOSTAT_LS_RJT:
660fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
661291a2b48SSukumar Swaminathan 		    "LS Reject. did=0x%06x sbp=%p cmd=%02x", did, sbp,
662291a2b48SSukumar Swaminathan 		    scsi_opcode);
663fcf3ce44SJohn Forte 		break;
664fcf3ce44SJohn Forte 
665fcf3ce44SJohn Forte 	case IOSTAT_DATA_UNDERRUN:
666fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
667291a2b48SSukumar Swaminathan 		    "Underrun. did=0x%06x sbp=%p cmd=%02x "
668291a2b48SSukumar Swaminathan 		    "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)",
669291a2b48SSukumar Swaminathan 		    did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx,
670291a2b48SSukumar Swaminathan 		    rsp_data_resid, scsi_status, sense, asc, ascq);
671fcf3ce44SJohn Forte 		break;
672fcf3ce44SJohn Forte 
673fcf3ce44SJohn Forte 	case IOSTAT_DATA_OVERRUN:
674fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
675291a2b48SSukumar Swaminathan 		    "Overrun. did=0x%06x sbp=%p cmd=%02x "
676291a2b48SSukumar Swaminathan 		    "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)",
677291a2b48SSukumar Swaminathan 		    did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx,
678291a2b48SSukumar Swaminathan 		    rsp_data_resid, scsi_status, sense, asc, ascq);
679fcf3ce44SJohn Forte 		break;
680fcf3ce44SJohn Forte 
6818f23e9faSHans Rosenfeld 	case IOSTAT_RSP_INVALID:
6828f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
6838f23e9faSHans Rosenfeld 		    "Rsp Invalid. did=0x%06x sbp=%p cmd=%02x dl=%d rl=%d"
6848f23e9faSHans Rosenfeld 		    "(%d, %d, %d)",
6858f23e9faSHans Rosenfeld 		    did, sbp, scsi_opcode, pkt->pkt_datalen, pkt->pkt_rsplen,
6868f23e9faSHans Rosenfeld 		    LE_SWAP32(rsp->fcp_resid),
6878f23e9faSHans Rosenfeld 		    LE_SWAP32(rsp->fcp_sense_len),
6888f23e9faSHans Rosenfeld 		    LE_SWAP32(rsp->fcp_response_len));
6898f23e9faSHans Rosenfeld 		break;
6908f23e9faSHans Rosenfeld 
691fcf3ce44SJohn Forte 	default:
692fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg,
693fcf3ce44SJohn Forte 		    "Unknown status=%x reason=%x did=0x%06x sbp=%p cmd=%02x",
694291a2b48SSukumar Swaminathan 		    iostat, cmd->un.grsp.perr.statLocalError, did, sbp,
695291a2b48SSukumar Swaminathan 		    scsi_opcode);
696fcf3ce44SJohn Forte 		break;
697fcf3ce44SJohn Forte 	}
698fcf3ce44SJohn Forte 
699fcf3ce44SJohn Forte 	if (iostat == IOSTAT_SUCCESS) {
700fcf3ce44SJohn Forte 		HBASTATS.FcpGood++;
701fcf3ce44SJohn Forte 	} else {
702fcf3ce44SJohn Forte 		HBASTATS.FcpError++;
703fcf3ce44SJohn Forte 	}
704fcf3ce44SJohn Forte 
705fcf3ce44SJohn Forte 	mutex_exit(&sbp->mtx);
706fcf3ce44SJohn Forte 
707fcf3ce44SJohn Forte 	emlxs_pkt_complete(sbp, iostat, localstat, 0);
708fcf3ce44SJohn Forte 
709fcf3ce44SJohn Forte 	return;
710fcf3ce44SJohn Forte 
71182527734SSukumar Swaminathan } /* emlxs_handle_fcp_event() */
712fcf3ce44SJohn Forte 
713fcf3ce44SJohn Forte 
714fcf3ce44SJohn Forte /*
715fcf3ce44SJohn Forte  *  emlxs_post_buffer
716fcf3ce44SJohn Forte  *
717fcf3ce44SJohn Forte  *  This routine will post count buffers to the
718fcf3ce44SJohn Forte  *  ring with the QUE_RING_BUF_CN command. This
719fcf3ce44SJohn Forte  *  allows 2 buffers / command to be posted.
720fcf3ce44SJohn Forte  *  Returns the number of buffers NOT posted.
721fcf3ce44SJohn Forte  */
72282527734SSukumar Swaminathan /* SLI3 */
723fcf3ce44SJohn Forte extern int
emlxs_post_buffer(emlxs_hba_t * hba,RING * rp,int16_t cnt)724fcf3ce44SJohn Forte emlxs_post_buffer(emlxs_hba_t *hba, RING *rp, int16_t cnt)
725fcf3ce44SJohn Forte {
726fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
727fcf3ce44SJohn Forte 	IOCB *icmd;
728fcf3ce44SJohn Forte 	IOCBQ *iocbq;
729fcf3ce44SJohn Forte 	MATCHMAP *mp;
730fcf3ce44SJohn Forte 	uint16_t tag;
731fcf3ce44SJohn Forte 	uint32_t maxqbuf;
732fcf3ce44SJohn Forte 	int32_t i;
733fcf3ce44SJohn Forte 	int32_t j;
734fcf3ce44SJohn Forte 	uint32_t seg;
735fcf3ce44SJohn Forte 	uint32_t size;
736fcf3ce44SJohn Forte 
737fcf3ce44SJohn Forte 	mp = 0;
738fcf3ce44SJohn Forte 	maxqbuf = 2;
739fcf3ce44SJohn Forte 	tag = (uint16_t)cnt;
740fcf3ce44SJohn Forte 	cnt += rp->fc_missbufcnt;
741fcf3ce44SJohn Forte 
74282527734SSukumar Swaminathan 	if (rp->ringno == hba->channel_els) {
743fcf3ce44SJohn Forte 		seg = MEM_BUF;
744fcf3ce44