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
9  * http://www.opensource.org/licenses/cddl1.txt.
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) 2004-2012 Emulex. All rights reserved.
24  * Use is subject to license terms.
25  * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
26  * Copyright 2020 RackTop Systems, Inc.
27  */
28 
29 #include <emlxs.h>
30 
31 #ifdef SFCT_SUPPORT
32 
33 
34 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
35 EMLXS_MSG_DEF(EMLXS_FCT_C);
36 
37 static void emlxs_fct_memseg_init(emlxs_hba_t *hba);
38 
39 static fct_status_t emlxs_fct_cmd_acquire(emlxs_port_t *port,
40 	fct_cmd_t *fct_cmd, uint16_t fct_state);
41 static fct_status_t emlxs_fct_cmd_accept(emlxs_port_t *port,
42 	fct_cmd_t *fct_cmd, uint16_t fct_state);
43 static void emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd,
44 	uint16_t fct_state);
45 
46 static emlxs_buf_t *emlxs_fct_cmd_init(emlxs_port_t *port,
47     fct_cmd_t *fct_cmd, uint16_t fct_state);
48 static void emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd,
49 	uint16_t fct_state);
50 static void emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd,
51 	uint16_t fct_state);
52 
53 static fct_status_t emlxs_fct_flogi_xchg(struct fct_local_port *fct_port,
54     struct fct_flogi_xchg *fx);
55 static fct_status_t emlxs_fct_get_link_info(fct_local_port_t *fct_port,
56     fct_link_info_t *link);
57 static fct_status_t emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
58     fct_remote_port_t *port_handle);
59 static fct_status_t emlxs_fct_send_cmd(fct_cmd_t *fct_cmd);
60 static fct_status_t emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd,
61     stmf_data_buf_t *dbuf, uint32_t ioflags);
62 static fct_status_t emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t flags);
63 static fct_status_t emlxs_fct_abort(fct_local_port_t *fct_port,
64     fct_cmd_t *cmd, uint32_t flags);
65 static void emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg);
66 static fct_status_t emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
67     fct_remote_port_t *port_handle, fct_cmd_t *plogi);
68 static fct_status_t emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd);
69 static fct_status_t emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd);
70 static fct_status_t emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd);
71 static fct_status_t emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd);
72 static void emlxs_fct_pkt_comp(fc_packet_t *pkt);
73 static void emlxs_fct_populate_hba_details(fct_local_port_t *fct_port,
74     fct_port_attrs_t *port_attrs);
75 static fct_status_t emlxs_fct_port_info(uint32_t cmd,
76     fct_local_port_t *fct_port, void *arg, uint8_t *buffer, uint32_t *size);
77 
78 static fct_status_t emlxs_fct_dmem_init(emlxs_port_t *port);
79 static void emlxs_fct_dmem_fini(emlxs_port_t *port);
80 
81 static stmf_data_buf_t *emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port,
82     uint32_t size, uint32_t *pminsize, uint32_t flags);
83 static void emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf);
84 
85 static int emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf,
86     uint_t sync_type);
87 static emlxs_buf_t *emlxs_fct_pkt_init(emlxs_port_t *port,
88     fct_cmd_t *fct_cmd, fc_packet_t *pkt);
89 
90 static void emlxs_fct_unsol_flush_thread(emlxs_hba_t *hba, void *arg1,
91     void *arg2);
92 static void emlxs_fct_unsol_flush(emlxs_port_t *port);
93 static uint32_t emlxs_fct_process_unsol_flogi(emlxs_port_t *port,
94     CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
95 static uint32_t emlxs_fct_process_unsol_plogi(emlxs_port_t *port,
96     CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size);
97 static uint32_t emlxs_fct_pkt_abort_txq(emlxs_port_t *port,
98     emlxs_buf_t *cmd_sbp);
99 static fct_status_t emlxs_fct_send_qfull_reply(emlxs_port_t *port,
100     emlxs_node_t *ndlp, uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd);
101 
102 #ifdef FCT_IO_TRACE
103 uint8_t *emlxs_iotrace = 0;	/* global for mdb */
104 int emlxs_iotrace_cnt = 0;
105 
106 /*
107  *
108  * FCT_CMD  (cmd_sbp->fct_state)
109  *
110  * STATE				LOCK STATUS			OWNER
111  * -----------------------------------------------------------------------------
112  * EMLXS_FCT_ABORT_DONE			Lock Destroyed			COMSTAR
113  * EMLXS_FCT_IO_DONE			Lock Destroyed			COMSTAR
114  *
115  * EMLXS_FCT_CMD_POSTED			Lock Released			COMSTAR
116  * EMLXS_FCT_OWNED			Lock Released			COMSTAR
117  *
118  * EMLXS_FCT_CMD_WAITQ			Lock Released			DRIVER
119  * EMLXS_FCT_RSP_PENDING		Lock Released			DRIVER
120  * EMLXS_FCT_REQ_PENDING		Lock Released			DRIVER
121  * EMLXS_FCT_REG_PENDING		Lock Released			DRIVER
122  * EMLXS_FCT_DATA_PENDING		Lock Released			DRIVER
123  * EMLXS_FCT_STATUS_PENDING		Lock Released			DRIVER
124  * EMLXS_FCT_CLOSE_PENDING		Lock Released			DRIVER
125  * EMLXS_FCT_ABORT_PENDING		Lock Released			DRIVER
126  *
127  * EMLXS_FCT_FCP_CMD_RECEIVED		Transistional, lock held	DRIVER
128  * EMLXS_FCT_ELS_CMD_RECEIVED		Transistional, lock held	DRIVER
129  * EMLXS_FCT_SEND_CMD_RSP		Transistional, lock held	DRIVER
130  * EMLXS_FCT_SEND_ELS_RSP		Transistional, lock held	DRIVER
131  * EMLXS_FCT_SEND_ELS_REQ		Transistional, lock held	DRIVER
132  * EMLXS_FCT_SEND_CT_REQ		Transistional, lock held	DRIVER
133  * EMLXS_FCT_REG_COMPLETE		Transistional, lock held	DRIVER
134  * EMLXS_FCT_SEND_FCP_DATA		Transistional, lock held	DRIVER
135  * EMLXS_FCT_SEND_FCP_STATUS		Transistional, lock held	DRIVER
136  * EMLXS_FCT_PKT_COMPLETE		Transistional, lock held	DRIVER
137  * EMLXS_FCT_PKT_FCPRSP_COMPLETE	Transistional, lock held	DRIVER
138  * EMLXS_FCT_PKT_ELSRSP_COMPLETE	Transistional, lock held	DRIVER
139  * EMLXS_FCT_PKT_ELSCMD_COMPLETE	Transistional, lock held	DRIVER
140  * EMLXS_FCT_PKT_CTCMD_COMPLETE		Transistional, lock held	DRIVER
141  * EMLXS_FCT_REQ_COMPLETE		Transistional, lock held	DRIVER
142  *
143  *
144  * 	COMSTAR OWNED	DRIVER OWNED
145  * 	-------------	---------------------------------------------------
146  * 	------- >	@	   Accept---- >Release  @   Acquire--- >+
147  *									|
148  *	< -------	@	Post/Done< ----Acquire  @   Release< ---+
149  *
150  * 	@  :Indicates COMSTAR use of emlxs_fct_abort()
151  *	    Abort requests set the EMLXS_FCT_ABORT_INP flag.
152  *
153  * 	Accept		:Indicates use of emlxs_fct_cmd_accept()
154  * 	Acquire		:Indicates use of emlxs_fct_cmd_acquire()
155  * 	Post		:Indicates use of emlxs_fct_cmd_post()
156  * 	Done		:Indicates use of emlxs_fct_cmd_done()
157  */
158 
159 void
emlxs_fct_io_trace(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint32_t data)160 emlxs_fct_io_trace(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint32_t data)
161 {
162 	emlxs_iotrace_t *iop = port->iotrace;
163 	uint16_t iotrace_cnt;
164 	uint16_t iotrace_index;
165 	int i;
166 
167 	if (!iop) {
168 		return;
169 	}
170 
171 	mutex_enter(&port->iotrace_mtx);
172 	iotrace_cnt = port->iotrace_cnt;
173 	iotrace_index = port->iotrace_index;
174 
175 	switch (data) {
176 
177 		/* New entry */
178 	case EMLXS_FCT_ELS_CMD_RECEIVED:
179 	case EMLXS_FCT_FCP_CMD_RECEIVED:
180 	case EMLXS_FCT_SEND_ELS_REQ:
181 	case EMLXS_FCT_SEND_CT_REQ:
182 		for (i = 0; i < iotrace_cnt; i++) {
183 			if ((iop->fct_cmd == fct_cmd) &&
184 			    (iop->trc[0] != (uint8_t)(0)))
185 				break;
186 			iop++;
187 		}
188 		if (i < iotrace_cnt) {
189 			/* New entry already exists */
190 			mutex_exit(&port->iotrace_mtx);
191 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
192 			    "IOTRACE: New entry already exists: fct_cmd: %p",
193 			    fct_cmd);
194 			return;
195 		}
196 		iop = port->iotrace + iotrace_index;
197 		for (i = 0; i < iotrace_cnt; i++) {
198 			if (iop->trc[0] == (uint8_t)(0))
199 				break;
200 
201 			iop++;
202 			if (iop == (port->iotrace + iotrace_cnt))
203 				iop = port->iotrace;
204 		}
205 		if (i >= iotrace_cnt) {
206 			/* No new slots available */
207 			mutex_exit(&port->iotrace_mtx);
208 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
209 			    "IOTRACE: No new slots: fct_cmd: %p data: %d",
210 			    fct_cmd, data);
211 			return;
212 		}
213 		port->iotrace_index++;
214 		if (port->iotrace_index >= iotrace_cnt)
215 			port->iotrace_index = 0;
216 
217 		bzero((uint8_t *)iop, sizeof (emlxs_iotrace_t));
218 		iop->fct_cmd = fct_cmd;
219 		iop->xri = fct_cmd->cmd_rxid;
220 		iop->marker = 0xff;
221 		iop->trc[0] = 2;
222 		iop->trc[1] = data;
223 		mutex_exit(&port->iotrace_mtx);
224 		return;
225 	}
226 
227 	for (i = 0; i < iotrace_cnt; i++) {
228 		if ((iop->fct_cmd == fct_cmd) &&
229 		    (iop->trc[0] != (uint8_t)(0)))
230 			break;
231 		iop++;
232 	}
233 	if (i >= iotrace_cnt) {
234 		/* Cannot find existing slot for fct_cmd */
235 		mutex_exit(&port->iotrace_mtx);
236 
237 		if ((data != EMLXS_FCT_REG_PENDING) &&
238 		    (data != EMLXS_FCT_REG_COMPLETE)) {
239 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
240 			    "IOTRACE: Missing slot: fct_cmd: %p data: %d",
241 			    fct_cmd, data);
242 		}
243 		return;
244 	}
245 
246 	if (iop->trc[0] >= MAX_IO_TRACE) {
247 		/* trc overrun for fct_cmd */
248 		mutex_exit(&port->iotrace_mtx);
249 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
250 		    "IOTRACE: trc overrun slot: fct_cmd: %p data: %d",
251 		    fct_cmd, data);
252 		return;
253 	}
254 
255 	if (iop->xri != fct_cmd->cmd_rxid) {
256 		/* xri mismatch for fct_cmd */
257 		mutex_exit(&port->iotrace_mtx);
258 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
259 		    "IOTRACE: xri mismatch %x != %x: fct_cmd: %p data: %d",
260 		    iop->xri, fct_cmd->cmd_rxid, fct_cmd, data);
261 		return;
262 	}
263 
264 	iop->trc[iop->trc[0]] = data;
265 	if ((data == EMLXS_FCT_IO_DONE) || (data == EMLXS_FCT_ABORT_DONE)) {
266 		/* IOCB ULPCOMMAND is saved after EMLXS_FCT_IOCB_ISSUED */
267 		if (iop->trc[iop->trc[0]-1] == EMLXS_FCT_IOCB_ISSUED) {
268 			iop->trc[0]++;
269 		} else {
270 			iop->trc[0] = 0;
271 		}
272 	} else {
273 		iop->trc[0]++;
274 	}
275 	mutex_exit(&port->iotrace_mtx);
276 
277 	return;
278 
279 } /* emlxs_fct_io_trace() */
280 #endif /* FCT_IO_TRACE */
281 
282 #ifdef MODSYM_SUPPORT
283 
284 extern int
emlxs_fct_modopen()285 emlxs_fct_modopen()
286 {
287 	int err;
288 
289 	mutex_enter(&emlxs_device.lock);
290 
291 	if (emlxs_modsym.fct_modopen) {
292 		mutex_exit(&emlxs_device.lock);
293 		return (0);
294 	}
295 
296 	emlxs_modsym.fct_modopen++;
297 
298 	/* Comstar (fct) */
299 	err = 0;
300 	emlxs_modsym.mod_fct = ddi_modopen("drv/fct", KRTLD_MODE_FIRST, &err);
301 	if (!emlxs_modsym.mod_fct) {
302 
303 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/fct failed: err %d",
304 		    DRIVER_NAME, err);
305 		goto failed;
306 	}
307 
308 	/* Comstar (stmf) */
309 	err = 0;
310 	emlxs_modsym.mod_stmf =
311 	    ddi_modopen("drv/stmf", KRTLD_MODE_FIRST, &err);
312 	if (!emlxs_modsym.mod_stmf) {
313 
314 		cmn_err(CE_WARN, "?%s: ddi_modopen drv/stmf failed: err %d",
315 		    DRIVER_NAME, err);
316 		goto failed;
317 	}
318 
319 	err = 0;
320 	/* Check if the fct fct_alloc is present */
321 	emlxs_modsym.fct_alloc = (void *(*)())ddi_modsym(emlxs_modsym.mod_fct,
322 	    "fct_alloc", &err);
323 	if ((void *)emlxs_modsym.fct_alloc == NULL) {
324 		cmn_err(CE_WARN,
325 		    "?%s: drv/fct: fct_alloc not present", DRIVER_NAME);
326 		goto failed;
327 	}
328 
329 	err = 0;
330 	/* Check if the fct fct_free is present */
331 	emlxs_modsym.fct_free = (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
332 	    "fct_free", &err);
333 	if ((void *)emlxs_modsym.fct_free == NULL) {
334 		cmn_err(CE_WARN,
335 		    "?%s: drv/fct: fct_free not present", DRIVER_NAME);
336 		goto failed;
337 	}
338 
339 	err = 0;
340 	/* Check if the fct fct_scsi_task_alloc is present */
341 	emlxs_modsym.fct_scsi_task_alloc =
342 	    (void *(*)(void *, uint16_t, uint32_t, uint8_t *,
343 	    uint16_t, uint16_t))ddi_modsym(emlxs_modsym.mod_fct,
344 	    "fct_scsi_task_alloc", &err);
345 	if ((void *)emlxs_modsym.fct_scsi_task_alloc == NULL) {
346 		cmn_err(CE_WARN,
347 		    "?%s: drv/fct: fct_scsi_task_alloc not present",
348 		    DRIVER_NAME);
349 		goto failed;
350 	}
351 
352 	err = 0;
353 	/* Check if the fct fct_register_local_port is present */
354 	emlxs_modsym.fct_register_local_port =
355 	    (int (*)())ddi_modsym(emlxs_modsym.mod_fct,
356 	    "fct_register_local_port", &err);
357 	if ((void *)emlxs_modsym.fct_register_local_port == NULL) {
358 		cmn_err(CE_WARN,
359 		    "?%s: drv/fct: fct_register_local_port not present",
360 		    DRIVER_NAME);
361 		goto failed;
362 	}
363 
364 	err = 0;
365 	/* Check if the fct fct_deregister_local_port is present */
366 	emlxs_modsym.fct_deregister_local_port =
367 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
368 	    "fct_deregister_local_port", &err);
369 	if ((void *)emlxs_modsym.fct_deregister_local_port == NULL) {
370 		cmn_err(CE_WARN,
371 		    "?%s: drv/fct: fct_deregister_local_port not present",
372 		    DRIVER_NAME);
373 		goto failed;
374 	}
375 
376 	err = 0;
377 	/* Check if the fct fct_handle_event is present */
378 	emlxs_modsym.fct_handle_event =
379 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_handle_event",
380 	    &err);
381 	if ((void *)emlxs_modsym.fct_handle_event == NULL) {
382 		cmn_err(CE_WARN,
383 		    "?%s: drv/fct: fct_handle_event not present",
384 		    DRIVER_NAME);
385 		goto failed;
386 	}
387 
388 	err = 0;
389 	/* Check if the fct fct_post_rcvd_cmd is present */
390 	emlxs_modsym.fct_post_rcvd_cmd =
391 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_post_rcvd_cmd",
392 	    &err);
393 	if ((void *)emlxs_modsym.fct_post_rcvd_cmd == NULL) {
394 		cmn_err(CE_WARN,
395 		    "?%s: drv/fct: fct_post_rcvd_cmd not present",
396 		    DRIVER_NAME);
397 		goto failed;
398 	}
399 	err = 0;
400 	/* Check if the fct fct_alloc is present */
401 	emlxs_modsym.fct_ctl = (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
402 	    "fct_ctl", &err);
403 	if ((void *)emlxs_modsym.fct_ctl == NULL) {
404 		cmn_err(CE_WARN,
405 		    "?%s: drv/fct: fct_ctl not present", DRIVER_NAME);
406 		goto failed;
407 	}
408 	err = 0;
409 	/* Check if the fct fct_queue_cmd_for_termination is present */
410 	emlxs_modsym.fct_queue_cmd_for_termination =
411 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
412 	    "fct_queue_cmd_for_termination", &err);
413 	if ((void *)emlxs_modsym.fct_queue_cmd_for_termination == NULL) {
414 		cmn_err(CE_WARN,
415 		    "?%s: drv/fct: fct_queue_cmd_for_termination not present",
416 		    DRIVER_NAME);
417 		goto failed;
418 	}
419 	err = 0;
420 	/* Check if the fct fct_send_response_done is present */
421 	emlxs_modsym.fct_send_response_done =
422 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
423 	    "fct_send_response_done", &err);
424 	if ((void *)emlxs_modsym.fct_send_response_done == NULL) {
425 		cmn_err(CE_WARN,
426 		    "?%s: drv/fct: fct_send_response_done not present",
427 		    DRIVER_NAME);
428 		goto failed;
429 	}
430 	err = 0;
431 	/* Check if the fct fct_send_cmd_done is present */
432 	emlxs_modsym.fct_send_cmd_done =
433 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_send_cmd_done",
434 	    &err);
435 	if ((void *)emlxs_modsym.fct_send_cmd_done == NULL) {
436 		cmn_err(CE_WARN,
437 		    "?%s: drv/fct: fct_send_cmd_done not present",
438 		    DRIVER_NAME);
439 		goto failed;
440 	}
441 	err = 0;
442 	/* Check if the fct fct_scsi_xfer_data_done is present */
443 	emlxs_modsym.fct_scsi_data_xfer_done =
444 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
445 	    "fct_scsi_data_xfer_done", &err);
446 	if ((void *)emlxs_modsym.fct_scsi_data_xfer_done == NULL) {
447 		cmn_err(CE_WARN,
448 		    "?%s: drv/fct: fct_scsi_data_xfer_done not present",
449 		    DRIVER_NAME);
450 		goto failed;
451 	}
452 	err = 0;
453 	/* Check if the fct fct_port_shutdown is present */
454 	emlxs_modsym.fct_port_shutdown =
455 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
456 	    "fct_port_shutdown", &err);
457 	if ((void *)emlxs_modsym.fct_port_shutdown == NULL) {
458 		cmn_err(CE_WARN,
459 		    "?%s: drv/fct: fct_port_shutdown not present",
460 		    DRIVER_NAME);
461 		goto failed;
462 	}
463 
464 	err = 0;
465 	/* Check if the fct fct_port_initialize is present */
466 	emlxs_modsym.fct_port_initialize =
467 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
468 	    "fct_port_initialize", &err);
469 	if ((void *)emlxs_modsym.fct_port_initialize == NULL) {
470 		cmn_err(CE_WARN,
471 		    "?%s: drv/fct: fct_port_initialize not present",
472 		    DRIVER_NAME);
473 		goto failed;
474 	}
475 
476 	err = 0;
477 	/* Check if the fct fct_cmd_fca_aborted is present */
478 	emlxs_modsym.fct_cmd_fca_aborted =
479 	    (void (*)())ddi_modsym(emlxs_modsym.mod_fct,
480 	    "fct_cmd_fca_aborted", &err);
481 	if ((void *)emlxs_modsym.fct_cmd_fca_aborted == NULL) {
482 		cmn_err(CE_WARN,
483 		    "?%s: drv/fct: fct_cmd_fca_aborted not present",
484 		    DRIVER_NAME);
485 		goto failed;
486 	}
487 
488 	err = 0;
489 	/* Check if the fct fct_handle_rcvd_flogi is present */
490 	emlxs_modsym.fct_handle_rcvd_flogi =
491 	    (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct,
492 	    "fct_handle_rcvd_flogi", &err);
493 	if ((void *)emlxs_modsym.fct_handle_rcvd_flogi == NULL) {
494 		cmn_err(CE_WARN,
495 		    "?%s: drv/fct: fct_handle_rcvd_flogi not present",
496 		    DRIVER_NAME);
497 		goto failed;
498 	}
499 
500 	/* Comstar (stmf) */
501 	err = 0;
502 	/* Check if the stmf stmf_alloc is present */
503 	emlxs_modsym.stmf_alloc =
504 	    (void *(*)())ddi_modsym(emlxs_modsym.mod_stmf, "stmf_alloc",
505 	    &err);
506 	if ((void *)emlxs_modsym.stmf_alloc == NULL) {
507 		cmn_err(CE_WARN,
508 		    "?%s: drv/stmf: stmf_alloc not present", DRIVER_NAME);
509 		goto failed;
510 	}
511 
512 	err = 0;
513 	/* Check if the stmf stmf_free is present */
514 	emlxs_modsym.stmf_free = (void (*)())ddi_modsym(emlxs_modsym.mod_stmf,
515 	    "stmf_free", &err);
516 	if ((void *)emlxs_modsym.stmf_free == NULL) {
517 		cmn_err(CE_WARN,
518 		    "?%s: drv/stmf: stmf_free not present", DRIVER_NAME);
519 		goto failed;
520 	}
521 
522 	err = 0;
523 	/* Check if the stmf stmf_deregister_port_provider is present */
524 	emlxs_modsym.stmf_deregister_port_provider =
525 	    (void (*)())ddi_modsym(emlxs_modsym.mod_stmf,
526 	    "stmf_deregister_port_provider", &err);
527 	if ((void *)emlxs_modsym.stmf_deregister_port_provider == NULL) {
528 		cmn_err(CE_WARN,
529 		    "?%s: drv/stmf: stmf_deregister_port_provider not present",
530 		    DRIVER_NAME);
531 		goto failed;
532 	}
533 
534 	err = 0;
535 	/* Check if the stmf stmf_register_port_provider is present */
536 	emlxs_modsym.stmf_register_port_provider =
537 	    (int (*)())ddi_modsym(emlxs_modsym.mod_stmf,
538 	    "stmf_register_port_provider", &err);
539 	if ((void *)emlxs_modsym.stmf_register_port_provider == NULL) {
540 		cmn_err(CE_WARN,
541 		    "?%s: drv/stmf: stmf_register_port_provider not present",
542 		    DRIVER_NAME);
543 		goto failed;
544 	}
545 
546 	mutex_exit(&emlxs_device.lock);
547 	return (0);
548 
549 failed:
550 
551 	mutex_exit(&emlxs_device.lock);
552 	emlxs_fct_modclose();
553 	return (1);
554 
555 } /* emlxs_fct_modopen() */
556 
557 
558 extern void
emlxs_fct_modclose()559 emlxs_fct_modclose()
560 {
561 	mutex_enter(&emlxs_device.lock);
562 
563 	if (emlxs_modsym.fct_modopen == 0) {
564 		mutex_exit(&emlxs_device.lock);
565 		return;
566 	}
567 
568 	emlxs_modsym.fct_modopen--;
569 
570 	if (emlxs_modsym.fct_modopen) {
571 		mutex_exit(&emlxs_device.lock);
572 		return;
573 	}
574 
575 	if (emlxs_modsym.mod_fct) {
576 		(void) ddi_modclose(emlxs_modsym.mod_fct);
577 		emlxs_modsym.mod_fct = 0;
578 	}
579 
580 	if (emlxs_modsym.mod_stmf) {
581 		(void) ddi_modclose(emlxs_modsym.mod_stmf);
582 		emlxs_modsym.mod_stmf = 0;
583 	}
584 
585 	emlxs_modsym.fct_alloc = NULL;
586 	emlxs_modsym.fct_free = NULL;
587 	emlxs_modsym.fct_scsi_task_alloc = NULL;
588 	emlxs_modsym.fct_register_local_port = NULL;
589 	emlxs_modsym.fct_deregister_local_port = NULL;
590 	emlxs_modsym.fct_handle_event = NULL;
591 	emlxs_modsym.fct_ctl = NULL;
592 	emlxs_modsym.fct_queue_cmd_for_termination = NULL;
593 	emlxs_modsym.fct_send_response_done = NULL;
594 	emlxs_modsym.fct_send_cmd_done = NULL;
595 	emlxs_modsym.fct_scsi_data_xfer_done = NULL;
596 	emlxs_modsym.fct_port_shutdown = NULL;
597 	emlxs_modsym.fct_port_initialize = NULL;
598 	emlxs_modsym.fct_cmd_fca_aborted = NULL;
599 	emlxs_modsym.fct_handle_rcvd_flogi = NULL;
600 
601 	emlxs_modsym.stmf_alloc = NULL;
602 	emlxs_modsym.stmf_free = NULL;
603 	emlxs_modsym.stmf_deregister_port_provider = NULL;
604 	emlxs_modsym.stmf_register_port_provider = NULL;
605 
606 	mutex_exit(&emlxs_device.lock);
607 
608 } /* emlxs_fct_modclose() */
609 
610 #endif /* MODSYM_SUPPORT */
611 
612 /*
613  * This routine is called to handle an unsol FLOGI exchange
614  *	fx	save
615  *	0	1	Process or save port->fx
616  *	0	0	Process or reject port->fx
617  *	1	1	Process port->fx, Process or save fx
618  *	1	0	Process or reject port->fx, Process or reject fx
619  */
620 static void
emlxs_fct_handle_unsol_flogi(emlxs_port_t * port,fct_flogi_xchg_t * fx,uint32_t save)621 emlxs_fct_handle_unsol_flogi(emlxs_port_t *port, fct_flogi_xchg_t *fx,
622     uint32_t save)
623 {
624 	emlxs_hba_t *hba = HBA;
625 	fct_status_t status;
626 	IOCBQ iocbq;
627 	fct_flogi_xchg_t fxchg;
628 
629 begin:
630 	mutex_enter(&EMLXS_PORT_LOCK);
631 
632 	/* Check if there is an old saved FLOGI */
633 	if (port->fx.fx_op) {
634 		/* Get it now */
635 		bcopy(&port->fx, &fxchg, sizeof (fct_flogi_xchg_t));
636 
637 		if (fx) {
638 			/* Save new FLOGI */
639 			bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t));
640 
641 			/* Reject old stale FLOGI */
642 			fx = &fxchg;
643 			goto reject_it;
644 
645 		} else {
646 			bzero(&port->fx, sizeof (fct_flogi_xchg_t));
647 			fx = &fxchg;
648 		}
649 
650 	} else if (!fx) {
651 		/* Nothing to do, just return */
652 		mutex_exit(&EMLXS_PORT_LOCK);
653 		return;
654 	}
655 
656 	/* We have a valid FLOGI here */
657 	/* There is no saved FLOGI at this point either */
658 
659 	/* Check if COMSTAR is ready to accept it */
660 	if (port->fct_flags & FCT_STATE_LINK_UP_ACKED) {
661 		mutex_exit(&EMLXS_PORT_LOCK);
662 
663 		bzero((uint8_t *)&iocbq, sizeof (IOCBQ));
664 		iocbq.iocb.un.elsreq.remoteID = fx->fx_sid;
665 		iocbq.iocb.un.elsreq.myID = fx->fx_did;
666 		iocbq.iocb.ULPCONTEXT = (uint16_t)fx->rsvd2;
667 		fx->rsvd2 = 0; /* Clear the reserved field now */
668 
669 		status = MODSYM(fct_handle_rcvd_flogi) (port->fct_port, fx);
670 
671 #ifdef FCT_API_TRACE
672 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
673 		    "fct_handle_rcvd_flogi %p: status=%x",
674 		    port->fct_port, status);
675 #endif /* FCT_API_TRACE */
676 
677 		if (status == FCT_SUCCESS) {
678 			if (fx->fx_op == ELS_OP_ACC) {
679 				(void) emlxs_els_reply(port, &iocbq,
680 				    ELS_CMD_ACC, ELS_CMD_FLOGI, 0, 0);
681 
682 			} else {	/* ELS_OP_LSRJT */
683 				(void) emlxs_els_reply(port, &iocbq,
684 				    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
685 				    fx->fx_rjt_reason, fx->fx_rjt_expl);
686 			}
687 		} else {
688 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
689 			    "FLOGI: sid=%x xid=%x. "
690 			    "fct_handle_rcvd_flogi failed. Rejecting.",
691 			    fx->fx_sid, iocbq.iocb.ULPCONTEXT);
692 
693 			(void) emlxs_els_reply(port, &iocbq,
694 			    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
695 			    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
696 		}
697 
698 		return;
699 	}
700 
701 	if (save) {
702 		/* Save FLOGI for later */
703 		bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t));
704 		mutex_exit(&EMLXS_PORT_LOCK);
705 		return;
706 	}
707 
708 reject_it:
709 
710 	mutex_exit(&EMLXS_PORT_LOCK);
711 
712 	if (port->fct_flags & FCT_STATE_LINK_UP) {
713 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
714 		    "FLOGI: sid=%x xid=%x. Stale. Rejecting.",
715 		    fx->fx_sid, fx->rsvd2);
716 
717 		bzero((uint8_t *)&iocbq, sizeof (IOCBQ));
718 		iocbq.iocb.un.elsreq.remoteID = fx->fx_sid;
719 		iocbq.iocb.un.elsreq.myID = fx->fx_did;
720 		iocbq.iocb.ULPCONTEXT = fx->rsvd2;
721 
722 		(void) emlxs_els_reply(port, &iocbq,
723 		    ELS_CMD_LS_RJT, ELS_CMD_FLOGI,
724 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
725 
726 		/* If we have an FLOGI saved, try sending it now */
727 		if (port->fx.fx_op) {
728 			fx = NULL;
729 			goto begin;
730 		}
731 
732 	} else {
733 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
734 		    "FLOGI: sid=%x xid=%x. Link down. "
735 		    "Dropping.",
736 		    fx->fx_sid, fx->rsvd2);
737 	}
738 
739 	return;
740 
741 } /* emlxs_fct_handle_unsol_flogi() */
742 
743 
744 /* ARGSUSED */
745 static void
emlxs_fct_unsol_flush_thread(emlxs_hba_t * hba,void * arg1,void * arg2)746 emlxs_fct_unsol_flush_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
747 {
748 	emlxs_port_t *port = (emlxs_port_t *)arg1;
749 
750 	emlxs_fct_unsol_flush(port);
751 	return;
752 
753 } /* emlxs_fct_unsol_flush_thread() */
754 
755 
756 /* This is called at port online and offline */
757 static void
emlxs_fct_unsol_flush(emlxs_port_t * port)758 emlxs_fct_unsol_flush(emlxs_port_t *port)
759 {
760 	emlxs_hba_t *hba = HBA;
761 	emlxs_buf_t *cmd_sbp;
762 	emlxs_buf_t *next;
763 	fct_cmd_t *fct_cmd;
764 	fct_status_t rval;
765 	uint32_t cmd_code;
766 
767 	if (!port->fct_port) {
768 		return;
769 	}
770 
771 	/* First handle any pending FLOGI */
772 	emlxs_fct_handle_unsol_flogi(port, NULL, 0);
773 
774 	if ((port->fct_flags & FCT_STATE_LINK_UP_ACKED) &&
775 	    !(port->fct_flags & FCT_STATE_FLOGI_CMPL)) {
776 		return;
777 	}
778 
779 	/* Wait queue */
780 	mutex_enter(&EMLXS_PORT_LOCK);
781 	cmd_sbp = port->fct_wait_head;
782 	port->fct_wait_head = NULL;
783 	port->fct_wait_tail = NULL;
784 	mutex_exit(&EMLXS_PORT_LOCK);
785 
786 	/*
787 	 * Next process any outstanding ELS commands. It doesn't
788 	 * matter if the Link is up or not, always post them to FCT.
789 	 */
790 	while (cmd_sbp) {
791 		next = cmd_sbp->next;
792 		fct_cmd = cmd_sbp->fct_cmd;
793 
794 		cmd_code = (fct_cmd->cmd_oxid << ELS_CMD_SHIFT);
795 
796 		/* Reacquire ownership of the fct_cmd */
797 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
798 		if (rval) {
799 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
800 			    "fct_unsol_flush: %s: sid=%x xid=%x "
801 			    "Unable to reacquire fct_cmd.",
802 			    emlxs_elscmd_xlate(cmd_code),
803 			    fct_cmd->cmd_rxid, fct_cmd->cmd_rportid);
804 
805 			cmd_sbp = next;
806 			continue;
807 		}
808 		/* mutex_enter(&cmd_sbp->fct_mtx); */
809 
810 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
811 		    "Posting %s: sid=%x xid=%x %p",
812 		    emlxs_elscmd_xlate(cmd_code),
813 		    fct_cmd->cmd_rportid, fct_cmd->cmd_rxid,
814 		    fct_cmd);
815 
816 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
817 		/* mutex_exit(&cmd_sbp->fct_mtx); */
818 
819 #ifdef FCT_API_TRACE
820 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
821 		    "fct_post_rcvd_cmd:2 %p:%p portid x%x", fct_cmd, cmd_sbp,
822 		    fct_cmd->cmd_lportid);
823 #endif /* FCT_API_TRACE */
824 
825 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
826 
827 		cmd_sbp = next;
828 
829 	}	/* while () */
830 
831 	return;
832 
833 } /* emlxs_fct_unsol_flush() */
834 
835 
836 int
emlxs_is_digit(uint8_t chr)837 emlxs_is_digit(uint8_t chr)
838 {
839 	if ((chr >= '0') && (chr <= '9')) {
840 		return (1);
841 	}
842 
843 	return (0);
844 
845 } /* emlxs_is_digit */
846 
847 
848 /*
849  *   Convert an ASCII decimal numeric string to integer.
850  *   Negation character '-' is not handled.
851  */
852 static uint32_t
emlxs_str_atoi(uint8_t * string)853 emlxs_str_atoi(uint8_t *string)
854 {
855 	uint32_t num = 0;
856 	int i = 0;
857 
858 	while (string[i]) {
859 		if (!emlxs_is_digit(string[i])) {
860 			return (num);
861 		}
862 
863 		num = num * 10 + (string[i++] - '0');
864 	}
865 
866 	return (num);
867 
868 } /* emlxs_str_atoi() */
869 
870 
871 extern uint32_t
emlxs_fct_init(emlxs_hba_t * hba)872 emlxs_fct_init(emlxs_hba_t *hba)
873 {
874 	emlxs_port_t *port = &PPORT;
875 
876 	/* Check if COMSTAR is present */
877 	if (((void *)MODSYM(stmf_alloc) == NULL) ||
878 	    ((void *)MODSYM(fct_alloc) == NULL)) {
879 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg,
880 		    "Comstar not present.");
881 		return (1);
882 	}
883 
884 	return (0);
885 
886 } /* emlxs_fct_init() */
887 
888 
889 extern void
emlxs_fct_attach(emlxs_hba_t * hba)890 emlxs_fct_attach(emlxs_hba_t *hba)
891 {
892 	emlxs_port_t *port = &PPORT;
893 	uint32_t vpi;
894 
895 	if (!(port->flag & EMLXS_TGT_ENABLED)) {
896 		return;
897 	}
898 
899 	/* Bind the physical port */
900 	emlxs_fct_bind_port(port);
901 
902 	/* Bind virtual ports */
903 	if (hba->flag & FC_NPIV_ENABLED) {
904 		for (vpi = 1; vpi <= hba->vpi_high; vpi++) {
905 			port = &VPORT(vpi);
906 
907 			if (!(port->flag & EMLXS_PORT_ENABLED)) {
908 				continue;
909 			}
910 
911 			emlxs_fct_bind_port(port);
912 		}
913 	}
914 
915 	return;
916 
917 } /* emlxs_fct_attach() */
918 
919 
920 extern void
emlxs_fct_detach(emlxs_hba_t * hba)921 emlxs_fct_detach(emlxs_hba_t *hba)
922 {
923 	uint32_t i;
924 	emlxs_port_t *vport;
925 
926 	for (i = 0; i < MAX_VPORTS; i++) {
927 		vport = &VPORT(i);
928 
929 		if (!(vport->flag & EMLXS_PORT_ENABLED)) {
930 			continue;
931 		}
932 
933 		emlxs_fct_unbind_port(vport);
934 	}
935 
936 #ifdef FCT_IO_TRACE
937 {
938 	emlxs_port_t *port = &PPORT;
939 
940 	mutex_destroy(&port->iotrace_mtx);
941 	if (port->iotrace) {
942 		kmem_free(port->iotrace,
943 		    (port->iotrace_cnt * sizeof (emlxs_iotrace_t)));
944 	}
945 	port->iotrace = NULL;
946 }
947 #endif /* FCT_IO_TRACE */
948 
949 	return;
950 
951 } /* emlxs_fct_detach() */
952 
953 
954 extern void
emlxs_fct_unbind_port(emlxs_port_t * port)955 emlxs_fct_unbind_port(emlxs_port_t *port)
956 {
957 	emlxs_hba_t *hba = HBA;
958 	char node_name[32];
959 
960 	mutex_enter(&EMLXS_PORT_LOCK);
961 
962 	if (!(port->flag & EMLXS_TGT_BOUND)) {
963 		mutex_exit(&EMLXS_PORT_LOCK);
964 		return;
965 	}
966 
967 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
968 	    "fct_unbind_port: port=%d", port->vpi);
969 
970 	/* Destroy & flush all port nodes, if they exist */
971 	if (port->node_count) {
972 		(void) EMLXS_SLI_UNREG_NODE(port, NULL, NULL, NULL, NULL);
973 	}
974 
975 	port->flag &= ~EMLXS_TGT_BOUND;
976 	port->flag &= ~EMLXS_TGT_ENABLED;
977 	hba->num_of_ports--;
978 	mutex_exit(&EMLXS_PORT_LOCK);
979 
980 	if (port->fct_port) {
981 		emlxs_fct_link_down(port);
982 		emlxs_fct_unsol_flush(port);
983 
984 #ifdef FCT_API_TRACE
985 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
986 		    "fct_deregister_local_port %p", port->fct_port);
987 #endif /* FCT_API_TRACE */
988 		MODSYM(fct_deregister_local_port) (port->fct_port);
989 
990 		if (port->fct_port->port_fds) {
991 #ifdef FCT_API_TRACE
992 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
993 			    "fct_free:3 %p", port->fct_port->port_fds);
994 #endif /* FCT_API_TRACE */
995 			MODSYM(fct_free) (port->fct_port->port_fds);
996 			port->fct_port->port_fds = NULL;
997 		}
998 #ifdef FCT_API_TRACE
999 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1000 		    "fct_free:4 %p", port->fct_port);
1001 #endif /* FCT_API_TRACE */
1002 		MODSYM(fct_free) (port->fct_port);
1003 		port->fct_port = NULL;
1004 		port->fct_flags = 0;
1005 	}
1006 
1007 	if (port->port_provider) {
1008 #ifdef FCT_API_TRACE
1009 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1010 		    "stmf_deregister_port_provider:1 %p",
1011 		    port->port_provider);
1012 #endif /* FCT_API_TRACE */
1013 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
1014 
1015 #ifdef FCT_API_TRACE
1016 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1017 		    "stmf_free:1 %p", port->port_provider);
1018 #endif /* FCT_API_TRACE */
1019 		MODSYM(stmf_free) (port->port_provider);
1020 		port->port_provider = NULL;
1021 	}
1022 
1023 	if (port->fct_memseg) {
1024 		emlxs_fct_dmem_fini(port);
1025 	}
1026 
1027 	(void) snprintf(node_name, sizeof (node_name), "%d,%d:SFCT",
1028 	    hba->ddiinst, port->vpi);
1029 	(void) ddi_remove_minor_node(hba->dip, node_name);
1030 
1031 	return;
1032 
1033 } /* emlxs_fct_unbind_port() */
1034 
1035 
1036 extern void
emlxs_fct_bind_port(emlxs_port_t * port)1037 emlxs_fct_bind_port(emlxs_port_t *port)
1038 {
1039 	emlxs_hba_t *hba = HBA;
1040 	fct_local_port_t *fct_port;
1041 	uint32_t flag = 0;
1042 	emlxs_config_t *cfg = &CFG;
1043 	fct_dbuf_store_t *fds;
1044 	char node_name[32];
1045 	uint8_t *bptr;
1046 
1047 	if (!(port->flag & EMLXS_TGT_ENABLED)) {
1048 		return;
1049 	}
1050 
1051 	mutex_enter(&EMLXS_PORT_LOCK);
1052 
1053 	if (port->flag & EMLXS_TGT_BOUND) {
1054 		mutex_exit(&EMLXS_PORT_LOCK);
1055 		return;
1056 	}
1057 
1058 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1059 	    "fct_bind_port: port=%d", port->vpi);
1060 
1061 	/* Perform generic port initialization */
1062 	emlxs_port_init(port);
1063 
1064 	if (port->vpi == 0) {
1065 		(void) snprintf(port->cfd_name, sizeof (port->cfd_name),
1066 		    "%s%d", DRIVER_NAME, hba->ddiinst);
1067 	} else {
1068 		(void) snprintf(port->cfd_name, sizeof (port->cfd_name),
1069 		    "%s%d.%d", DRIVER_NAME, hba->ddiinst, port->vpi);
1070 	}
1071 
1072 	if (emlxs_fct_dmem_init(port) != FCT_SUCCESS) {
1073 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1074 		    "fct_bind_port: Unable to allocate fct memory.");
1075 		goto failed;
1076 	}
1077 	flag |= 0x00000001;
1078 
1079 	port->port_provider =
1080 	    (stmf_port_provider_t *)
1081 	    MODSYM(stmf_alloc) (STMF_STRUCT_PORT_PROVIDER, 0, 0);
1082 #ifdef FCT_API_TRACE
1083 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1084 	    "stmf_alloc port_provider %p", port->port_provider);
1085 #endif /* FCT_API_TRACE */
1086 
1087 	if (port->port_provider == NULL) {
1088 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1089 		    "fct_bind_port: Unable to allocate port provider.");
1090 		goto failed;
1091 	}
1092 	flag |= 0x00000002;
1093 
1094 	port->port_provider->pp_portif_rev = PORTIF_REV_1;
1095 	port->port_provider->pp_name = port->cfd_name;
1096 	port->port_provider->pp_provider_private = port;
1097 
1098 #ifdef FCT_API_TRACE
1099 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1100 	    "stmf_register_port_provider %p", port->port_provider);
1101 #endif /* FCT_API_TRACE */
1102 	/* register port provider with framework */
1103 	if (MODSYM(stmf_register_port_provider) (port->port_provider) !=
1104 	    STMF_SUCCESS) {
1105 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1106 		    "fct_bind_port: Unable to register port provider.");
1107 		goto failed;
1108 	}
1109 	flag |= 0x00000004;
1110 
1111 	port->fct_port =
1112 	    (fct_local_port_t *)MODSYM(fct_alloc) (FCT_STRUCT_LOCAL_PORT, 0,
1113 	    0);
1114 #ifdef FCT_API_TRACE
1115 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1116 	    "fct_alloc fct_port %p", port->fct_port);
1117 #endif /* FCT_API_TRACE */
1118 
1119 	if (port->fct_port == NULL) {
1120 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1121 		    "fct_bind_port: Unable to allocate fct port.");
1122 		goto failed;
1123 	}
1124 	flag |= 0x00000008;
1125 
1126 	port->fct_port->port_fds =
1127 	    (fct_dbuf_store_t *)MODSYM(fct_alloc) (FCT_STRUCT_DBUF_STORE, 0,
1128 	    0);
1129 #ifdef FCT_API_TRACE
1130 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1131 	    "fct_alloc port_fds %p", port->fct_port->port_fds);
1132 #endif /* FCT_API_TRACE */
1133 
1134 	if (port->fct_port->port_fds == NULL) {
1135 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1136 		    "fct_bind_port: Unable to allocate dbuf store.");
1137 		goto failed;
1138 	}
1139 	flag |= 0x00000010;
1140 
1141 	(void) snprintf(node_name, sizeof (node_name), "%d,%d:SFCT",
1142 	    hba->ddiinst, port->vpi);
1143 	if (ddi_create_minor_node(hba->dip, node_name, S_IFCHR, hba->ddiinst,
1144 	    NULL, 0) == DDI_FAILURE) {
1145 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1146 		    "Unable to create SFCT device node.");
1147 		goto failed;
1148 	}
1149 	flag |= 0x00000020;
1150 
1151 	/* Intialize */
1152 	fct_port = port->fct_port;
1153 	fct_port->port_fca_version = FCT_FCA_MODREV_1;
1154 	fct_port->port_fca_private = port;
1155 	fct_port->port_fca_abort_timeout = 30 * 1000;	/* 30 seconds */
1156 
1157 	bcopy((uint8_t *)&port->wwpn, (uint8_t *)fct_port->port_pwwn, 8);
1158 	bcopy((uint8_t *)&port->wwnn, (uint8_t *)fct_port->port_nwwn, 8);
1159 
1160 	bptr = (uint8_t *)&port->wwnn;
1161 	(void) snprintf(fct_port->port_nwwn_str, FC_WWN_BUFLEN,
1162 	    "%02x%02x%02x%02x%02x%02x%02x%02x",
1163 	    bptr[0], bptr[1], bptr[2], bptr[3],
1164 	    bptr[4], bptr[5], bptr[6], bptr[7]);
1165 
1166 	bptr = (uint8_t *)&port->wwpn;
1167 	(void) snprintf(fct_port->port_pwwn_str, FC_WWN_BUFLEN,
1168 	    "%02x%02x%02x%02x%02x%02x%02x%02x",
1169 	    bptr[0], bptr[1], bptr[2], bptr[3],
1170 	    bptr[4], bptr[5], bptr[6], bptr[7]);
1171 
1172 	fct_port->port_sym_node_name = port->snn;
1173 	fct_port->port_sym_port_name = port->spn;
1174 	fct_port->port_hard_address = cfg[CFG_ASSIGN_ALPA].current;
1175 	fct_port->port_default_alias = port->cfd_name;
1176 	fct_port->port_pp = port->port_provider;
1177 	fct_port->port_max_logins = hba->max_nodes + EMLXS_FCT_NUM_ELS_ONLY;
1178 
1179 	if (cfg[CFG_FCT_QDEPTH].current &&
1180 	    (cfg[CFG_FCT_QDEPTH].current < hba->io_throttle)) {
1181 		fct_port->port_max_xchges = cfg[CFG_FCT_QDEPTH].current;
1182 	} else {
1183 		fct_port->port_max_xchges = hba->io_throttle;
1184 	}
1185 
1186 	fct_port->port_fca_fcp_cmd_size = sizeof (emlxs_buf_t);
1187 	fct_port->port_fca_rp_private_size = sizeof (uintptr_t);
1188 	fct_port->port_fca_sol_els_private_size = sizeof (emlxs_buf_t);
1189 	fct_port->port_fca_sol_ct_private_size = sizeof (emlxs_buf_t);
1190 	fct_port->port_get_link_info = emlxs_fct_get_link_info;
1191 	fct_port->port_register_remote_port = emlxs_fct_register_remote_port;
1192 	fct_port->port_deregister_remote_port =
1193 	    emlxs_fct_deregister_remote_port;
1194 	fct_port->port_send_cmd = emlxs_fct_send_cmd;
1195 	fct_port->port_xfer_scsi_data = emlxs_fct_send_fcp_data;
1196 	fct_port->port_send_cmd_response = emlxs_fct_send_cmd_rsp;
1197 	fct_port->port_abort_cmd = emlxs_fct_abort;
1198 	fct_port->port_ctl = emlxs_fct_ctl;
1199 	fct_port->port_flogi_xchg = emlxs_fct_flogi_xchg;
1200 	fct_port->port_populate_hba_details = emlxs_fct_populate_hba_details;
1201 	fct_port->port_info = emlxs_fct_port_info;
1202 
1203 	fds = port->fct_port->port_fds;
1204 	fds->fds_fca_private = port;
1205 	fds->fds_alloc_data_buf = emlxs_fct_dbuf_alloc;
1206 	fds->fds_free_data_buf = emlxs_fct_dbuf_free;
1207 
1208 	/* Scatter gather list support */
1209 /*	fds->fds_setup_dbuf = ; */
1210 /*	fds->fds_teardown_dbuf = ; */
1211 /*	fds->fds_max_sgl_xfer_len = ; */
1212 /*	fds->fds_copy_threshold = ; */
1213 
1214 #ifdef FCT_API_TRACE
1215 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1216 	    "fct_register_local_port %p", fct_port);
1217 #endif /* FCT_API_TRACE */
1218 	/* register this local port with the fct module */
1219 	if (MODSYM(fct_register_local_port) (fct_port) != FCT_SUCCESS) {
1220 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1221 		    "fct_bind_port: Unable to register fct port.");
1222 		goto failed;
1223 	}
1224 
1225 	/* Set the bound flag */
1226 	port->flag |= EMLXS_TGT_BOUND;
1227 	hba->num_of_ports++;
1228 
1229 	mutex_exit(&EMLXS_PORT_LOCK);
1230 
1231 	return;
1232 
1233 failed:
1234 
1235 	if (flag & 0x20) {
1236 		(void) ddi_remove_minor_node(hba->dip, node_name);
1237 	}
1238 
1239 	if (flag & 0x10) {
1240 #ifdef FCT_API_TRACE
1241 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1242 		    "fct_free:5 %p", port->fct_port->port_fds);
1243 #endif /* FCT_API_TRACE */
1244 		MODSYM(fct_free) (port->fct_port->port_fds);
1245 		port->fct_port->port_fds = NULL;
1246 	}
1247 
1248 	if (flag & 0x8) {
1249 #ifdef FCT_API_TRACE
1250 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1251 		    "fct_free:6 %p", port->fct_port);
1252 #endif /* FCT_API_TRACE */
1253 		MODSYM(fct_free) (port->fct_port);
1254 		port->fct_port = NULL;
1255 		port->fct_flags = 0;
1256 	}
1257 
1258 	if (flag & 0x4) {
1259 #ifdef FCT_API_TRACE
1260 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1261 		    "stmf_deregister_port_provider:2 %p",
1262 		    port->port_provider);
1263 #endif /* FCT_API_TRACE */
1264 		MODSYM(stmf_deregister_port_provider) (port->port_provider);
1265 	}
1266 
1267 	if (flag & 0x2) {
1268 #ifdef FCT_API_TRACE
1269 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1270 		    "stmf_free:2 %p", port->port_provider);
1271 #endif /* FCT_API_TRACE */
1272 		MODSYM(stmf_free) (port->port_provider);
1273 		port->port_provider = NULL;
1274 	}
1275 
1276 	if (flag & 0x1) {
1277 		emlxs_fct_dmem_fini(port);
1278 	}
1279 
1280 	port->flag &= ~EMLXS_TGT_ENABLED;
1281 
1282 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1283 	    "Target mode disabled.");
1284 
1285 	mutex_exit(&EMLXS_PORT_LOCK);
1286 
1287 	return;
1288 
1289 } /* emlxs_fct_bind_port() */
1290 
1291 
1292 /* COMSTAR ENTER POINT */
1293 /*ARGSUSED*/
1294 static fct_status_t
emlxs_fct_port_info(uint32_t cmd,fct_local_port_t * fct_port,void * arg,uint8_t * buffer,uint32_t * size)1295 emlxs_fct_port_info(uint32_t cmd, fct_local_port_t *fct_port, void *arg,
1296     uint8_t *buffer, uint32_t *size)
1297 {
1298 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1299 	emlxs_hba_t *hba = HBA;
1300 	fct_status_t rval = FCT_SUCCESS;
1301 	fct_port_link_status_t *link_status;
1302 	MAILBOX *mb;
1303 	MAILBOXQ *mbq;
1304 
1305 	switch (cmd) {
1306 	case FC_TGT_PORT_RLS:
1307 		bzero(buffer, *size);
1308 
1309 		if ((*size) < sizeof (fct_port_link_status_t)) {
1310 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1311 			    "FC_TGT_PORT_RLS: Buffer too small. %d < %d",
1312 			    *size, sizeof (fct_port_link_status_t));
1313 
1314 			rval = FCT_FAILURE;
1315 			break;
1316 		}
1317 
1318 		if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == 0) {
1319 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1320 			    "FC_TGT_PORT_RLS: Unable to allocate mailbox.");
1321 
1322 			rval = FCT_ALLOC_FAILURE;
1323 			break;
1324 		}
1325 		mb = (MAILBOX *)mbq;
1326 
1327 		emlxs_mb_read_lnk_stat(hba, mbq);
1328 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0)
1329 		    != MBX_SUCCESS) {
1330 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1331 			    "FC_TGT_PORT_RLS: Unable to send request.");
1332 
1333 			rval = FCT_BUSY;
1334 		} else {
1335 			link_status = (fct_port_link_status_t *)buffer;
1336 			link_status->LinkFailureCount =
1337 			    mb->un.varRdLnk.linkFailureCnt;
1338 			link_status->LossOfSyncCount =
1339 			    mb->un.varRdLnk.lossSyncCnt;
1340 			link_status->LossOfSignalsCount =
1341 			    mb->un.varRdLnk.lossSignalCnt;
1342 			link_status->PrimitiveSeqProtocolErrorCount =
1343 			    mb->un.varRdLnk.primSeqErrCnt;
1344 			link_status->InvalidTransmissionWordCount =
1345 			    mb->un.varRdLnk.invalidXmitWord;
1346 			link_status->InvalidCRCCount =
1347 			    mb->un.varRdLnk.crcCnt;
1348 		}
1349 
1350 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
1351 		break;
1352 
1353 	default:
1354 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
1355 		    "fct_port_info: Invalid request. cmd=%x",
1356 		    cmd);
1357 
1358 		rval = FCT_FAILURE;
1359 		break;
1360 
1361 	}
1362 
1363 	return (rval);
1364 
1365 } /* emlxs_fct_port_info() */
1366 
1367 
1368 /* COMSTAR ENTER POINT */
1369 static void
emlxs_fct_populate_hba_details(fct_local_port_t * fct_port,fct_port_attrs_t * port_attrs)1370 emlxs_fct_populate_hba_details(fct_local_port_t *fct_port,
1371     fct_port_attrs_t *port_attrs)
1372 {
1373 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1374 	emlxs_hba_t *hba = HBA;
1375 	emlxs_vpd_t *vpd = &VPD;
1376 
1377 	(void) strncpy(port_attrs->manufacturer,
1378 	    hba->model_info.manufacturer,
1379 	    (sizeof (port_attrs->manufacturer)-1));
1380 	(void) strncpy(port_attrs->serial_number, vpd->serial_num,
1381 	    (sizeof (port_attrs->serial_number)-1));
1382 	(void) strncpy(port_attrs->model, hba->model_info.model,
1383 	    (sizeof (port_attrs->model)-1));
1384 	(void) strncpy(port_attrs->model_description,
1385 	    hba->model_info.model_desc,
1386 	    (sizeof (port_attrs->model_description)-1));
1387 	(void) snprintf(port_attrs->hardware_version,
1388 	    (sizeof (port_attrs->hardware_version)-1),
1389 	    "%x", vpd->biuRev);
1390 	(void) snprintf(port_attrs->driver_version,
1391 	    (sizeof (port_attrs->driver_version)-1),
1392 	    "%s (%s)", emlxs_version,
1393 	    emlxs_revision);
1394 	(void) strncpy(port_attrs->option_rom_version, vpd->fcode_version,
1395 	    (sizeof (port_attrs->option_rom_version)-1));
1396 	(void) snprintf(port_attrs->firmware_version,
1397 	    (sizeof (port_attrs->firmware_version)-1),
1398 	    "%s (%s)", vpd->fw_version,
1399 	    vpd->fw_label);
1400 	(void) strncpy(port_attrs->driver_name, DRIVER_NAME,
1401 	    (sizeof (port_attrs->driver_name)-1));
1402 	port_attrs->vendor_specific_id = (hba->model_info.device_id << 16) |
1403 	    hba->model_info.vendor_id;
1404 	port_attrs->supported_cos = LE_SWAP32(FC_NS_CLASS3);
1405 
1406 	port_attrs->max_frame_size = FF_FRAME_SIZE;
1407 
1408 	if (vpd->link_speed & LMT_32GB_CAPABLE) {
1409 		port_attrs->supported_speed |= PORT_SPEED_32G;
1410 	}
1411 	if (vpd->link_speed & LMT_16GB_CAPABLE) {
1412 		port_attrs->supported_speed |= PORT_SPEED_16G;
1413 	}
1414 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
1415 		port_attrs->supported_speed |= PORT_SPEED_10G;
1416 	}
1417 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
1418 		port_attrs->supported_speed |= PORT_SPEED_8G;
1419 	}
1420 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
1421 		port_attrs->supported_speed |= PORT_SPEED_4G;
1422 	}
1423 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
1424 		port_attrs->supported_speed |= PORT_SPEED_2G;
1425 	}
1426 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
1427 		port_attrs->supported_speed |= PORT_SPEED_1G;
1428 	}
1429 
1430 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1431 	    "Port attr: manufacturer       = %s", port_attrs->manufacturer);
1432 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1433 	    "Port attr: serial_num         = %s", port_attrs->serial_number);
1434 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1435 	    "Port attr: model              = %s", port_attrs->model);
1436 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1437 	    "Port attr: model_description  = %s",
1438 	    port_attrs->model_description);
1439 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1440 	    "Port attr: hardware_version   = %s",
1441 	    port_attrs->hardware_version);
1442 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1443 	    "Port attr: driver_version     = %s", port_attrs->driver_version);
1444 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1445 	    "Port attr: option_rom_version = %s",
1446 	    port_attrs->option_rom_version);
1447 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1448 	    "Port attr: firmware_version   = %s",
1449 	    port_attrs->firmware_version);
1450 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1451 	    "Port attr: driver_name        = %s", port_attrs->driver_name);
1452 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1453 	    "Port attr: vendor_specific_id = 0x%x",
1454 	    port_attrs->vendor_specific_id);
1455 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1456 	    "Port attr: supported_cos      = 0x%x",
1457 	    port_attrs->supported_cos);
1458 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1459 	    "Port attr: supported_speed    = 0x%x",
1460 	    port_attrs->supported_speed);
1461 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1462 	    "Port attr: max_frame_size     = 0x%x",
1463 	    port_attrs->max_frame_size);
1464 
1465 	return;
1466 
1467 } /* emlxs_fct_populate_hba_details() */
1468 
1469 
1470 /* COMSTAR ENTER POINT */
1471 /* ARGSUSED */
1472 static void
emlxs_fct_ctl(fct_local_port_t * fct_port,int cmd,void * arg)1473 emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg)
1474 {
1475 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1476 	emlxs_hba_t *hba = HBA;
1477 	stmf_change_status_t st;
1478 	int32_t rval;
1479 
1480 	st.st_completion_status = FCT_SUCCESS;
1481 	st.st_additional_info = NULL;
1482 
1483 	switch (cmd) {
1484 	case FCT_CMD_PORT_ONLINE:
1485 		/* If the HBA is offline, we cannot bring the tgtport online */
1486 		if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
1487 			st.st_completion_status = FCT_FAILURE;
1488 			MODSYM(fct_ctl) (fct_port->port_lport,
1489 			    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1490 			break;
1491 		}
1492 
1493 		if (port->fct_flags & FCT_STATE_PORT_ONLINE) {
1494 			st.st_completion_status = STMF_ALREADY;
1495 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1496 			    "STATE: ONLINE chk");
1497 		} else {
1498 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1499 			    "STATE: OFFLINE --> ONLINE");
1500 
1501 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1502 			port->fct_flags |= FCT_STATE_PORT_ONLINE;
1503 
1504 			if ((port->vpi == 0) &&
1505 			    (port->mode == MODE_TARGET) &&
1506 			    (hba->state <= FC_LINK_DOWN)) {
1507 				/* Try to bring the link up */
1508 				(void) emlxs_reset_link(hba, 1, 1);
1509 			}
1510 
1511 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1512 			    "STATE: ONLINE");
1513 		}
1514 
1515 		MODSYM(fct_ctl) (fct_port->port_lport,
1516 		    FCT_CMD_PORT_ONLINE_COMPLETE, &st);
1517 		break;
1518 
1519 	case FCT_CMD_PORT_OFFLINE:
1520 		if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1521 			st.st_completion_status = STMF_ALREADY;
1522 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1523 			    "STATE: OFFLINE chk");
1524 
1525 		} else {
1526 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1527 			    "STATE: ONLINE --> OFFLINE");
1528 
1529 			/* Take link down and flush */
1530 			emlxs_fct_link_down(port);
1531 			emlxs_fct_unsol_flush(port);
1532 
1533 			/* Declare this port offline now */
1534 			port->fct_flags |= FCT_STATE_NOT_ACKED;
1535 			port->fct_flags &= ~FCT_STATE_PORT_ONLINE;
1536 
1537 			if ((port->vpi == 0) &&
1538 			    (port->mode == MODE_TARGET) &&
1539 			    !(port->flag & EMLXS_INI_ENABLED)) {
1540 				/* Take link down and hold it down */
1541 				(void) emlxs_reset_link(hba, 0, 1);
1542 			}
1543 
1544 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1545 			    "STATE: OFFLINE");
1546 		}
1547 
1548 		MODSYM(fct_ctl) (fct_port->port_lport,
1549 		    FCT_CMD_PORT_OFFLINE_COMPLETE, &st);
1550 
1551 		break;
1552 
1553 	case FCT_ACK_PORT_OFFLINE_COMPLETE:
1554 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1555 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1556 		    "STATE: OFFLINE ack");
1557 		break;
1558 
1559 	case FCT_ACK_PORT_ONLINE_COMPLETE:
1560 		port->fct_flags &= ~FCT_STATE_NOT_ACKED;
1561 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1562 		    "STATE: ONLINE ack");
1563 		break;
1564 
1565 	case FCT_CMD_FORCE_LIP:
1566 		if (port->mode == MODE_INITIATOR) {
1567 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1568 			    "fct_ctl: FCT_CMD_FORCE_LIP.");
1569 			*((fct_status_t *)arg) = FCT_FAILURE;
1570 			break;
1571 		}
1572 
1573 		if (hba->fw_flag & FW_UPDATE_NEEDED) {
1574 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1575 			    "fct_ctl: FCT_CMD_FORCE_LIP -> "
1576 			    "FCT_CMD_RESET");
1577 
1578 			hba->fw_flag |= FW_UPDATE_KERNEL;
1579 
1580 			/* Reset the adapter */
1581 			rval = emlxs_reset(port, FC_FCA_RESET);
1582 		} else {
1583 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1584 			    "fct_ctl: FCT_CMD_FORCE_LIP");
1585 
1586 			/* Reset the link */
1587 			rval = emlxs_reset(port, FC_FCA_LINK_RESET);
1588 		}
1589 		*((fct_status_t *)arg) = (rval == FC_SUCCESS) ? FCT_SUCCESS:
1590 		    FCT_FAILURE;
1591 		break;
1592 	}
1593 
1594 	return;
1595 
1596 } /* emlxs_fct_ctl() */
1597 
1598 
1599 extern int
emlxs_fct_port_shutdown(emlxs_port_t * port)1600 emlxs_fct_port_shutdown(emlxs_port_t *port)
1601 {
1602 	fct_local_port_t *fct_port;
1603 	int i;
1604 
1605 	fct_port = port->fct_port;
1606 	if (!fct_port) {
1607 		return (0);
1608 	}
1609 
1610 	port->fct_flags |= FCT_STATE_NOT_ACKED;
1611 
1612 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, "fct_port_shutdown");
1613 	MODSYM(fct_port_shutdown) (fct_port, STMF_RFLAG_STAY_OFFLINED,
1614 	    DRIVER_NAME" shutdown");
1615 
1616 	i = 0;
1617 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1618 		i++;
1619 		if (i > 300) {	/* 30 seconds */
1620 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1621 			    "fct_port_shutdown failed to ACK");
1622 			break;
1623 		}
1624 		delay(drv_usectohz(100000));	/* 100 msec */
1625 	}
1626 	return (1);
1627 }
1628 
1629 
1630 extern int
emlxs_fct_port_initialize(emlxs_port_t * port)1631 emlxs_fct_port_initialize(emlxs_port_t *port)
1632 {
1633 	fct_local_port_t *fct_port;
1634 	int i;
1635 
1636 	fct_port = port->fct_port;
1637 	if (!fct_port) {
1638 		return (0);
1639 	}
1640 
1641 	port->fct_flags |= FCT_STATE_NOT_ACKED;
1642 
1643 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1644 	    "fct_port_initialize");
1645 	MODSYM(fct_port_initialize) (fct_port, STMF_RFLAG_STAY_OFFLINED,
1646 	    DRIVER_NAME" initialize");
1647 
1648 	i = 0;
1649 	while (port->fct_flags & FCT_STATE_NOT_ACKED) {
1650 		i++;
1651 		if (i > 300) {	/* 30 seconds */
1652 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1653 			    "fct_port_initialize failed to ACK");
1654 			break;
1655 		}
1656 		delay(drv_usectohz(100000));	/* 100 msec */
1657 	}
1658 	return (1);
1659 }
1660 
1661 
1662 /* COMSTAR ENTER POINT */
1663 static fct_status_t
emlxs_fct_send_cmd(fct_cmd_t * fct_cmd)1664 emlxs_fct_send_cmd(fct_cmd_t *fct_cmd)
1665 {
1666 	emlxs_port_t *port;
1667 
1668 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1669 
1670 #ifdef FCT_API_TRACE
1671 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1672 	    "fct_send_cmd %p:%p  x%x", fct_cmd,
1673 	    fct_cmd->cmd_fca_private, fct_cmd->cmd_type);
1674 #endif /* FCT_API_TRACE */
1675 
1676 	switch (fct_cmd->cmd_type) {
1677 	case FCT_CMD_SOL_ELS:
1678 
1679 		return (emlxs_fct_send_els_cmd(fct_cmd));
1680 
1681 	case FCT_CMD_SOL_CT:
1682 
1683 		return (emlxs_fct_send_ct_cmd(fct_cmd));
1684 
1685 	default:
1686 
1687 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1688 		    "fct_send_cmd: Invalid cmd type found. type=%x",
1689 		    fct_cmd->cmd_type);
1690 
1691 		return (FCT_FAILURE);
1692 	}
1693 
1694 } /* emlxs_fct_send_cmd() */
1695 
1696 
1697 /* COMSTAR ENTER POINT */
1698 static fct_status_t
emlxs_fct_send_cmd_rsp(fct_cmd_t * fct_cmd,uint32_t ioflags)1699 emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t ioflags)
1700 {
1701 	emlxs_port_t *port;
1702 	emlxs_buf_t *cmd_sbp;
1703 	fct_status_t rval;
1704 	IOCBQ *iocbq;
1705 	IOCB *iocb;
1706 	uint32_t status;
1707 
1708 	port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
1709 
1710 	rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_CMD_RSP);
1711 	if (rval) {
1712 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1713 		    "fct_send_cmd_rsp: "
1714 		    "Unable to accept fct_cmd. type=%x",
1715 		    fct_cmd->cmd_type);
1716 
1717 		return (rval);
1718 	}
1719 	/* mutex_enter(&cmd_sbp->fct_mtx); */
1720 
1721 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
1722 	iocbq = &cmd_sbp->iocbq;
1723 	iocbq->sbp = cmd_sbp;
1724 	iocb = &iocbq->iocb;
1725 	status = iocb->ULPSTATUS;
1726 
1727 #ifdef FCT_API_TRACE
1728 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1729 	    "fct_send_cmd_rsp %p:%p x%x, %x, %x",
1730 	    fct_cmd, cmd_sbp, fct_cmd->cmd_type, iocb->ULPCT, status);
1731 #endif /* FCT_API_TRACE */
1732 
1733 	switch (fct_cmd->cmd_type) {
1734 	case FCT_CMD_FCP_XCHG:
1735 
1736 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1737 			goto failure;
1738 		}
1739 
1740 		if ((iocb->ULPCT == 0x1) && (status == 0)) {
1741 
1742 			/* Firmware already sent out resp */
1743 			cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
1744 
1745 			TGTPORTSTAT.FctOutstandingIO--;
1746 
1747 			emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
1748 			/* mutex_exit(&cmd_sbp->fct_mtx); */
1749 
1750 #ifdef FCT_API_TRACE
1751 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1752 			    "fct_send_response_done:4 %p: x%x",
1753 			    fct_cmd, fct_cmd->cmd_comp_status);
1754 
1755 #endif /* FCT_API_TRACE */
1756 
1757 			MODSYM(fct_send_response_done) (fct_cmd,
1758 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
1759 
1760 			return (FCT_SUCCESS);
1761 		}
1762 
1763 		rval =  emlxs_fct_send_fcp_status(fct_cmd);
1764 		if (rval == FCT_NOT_FOUND) {
1765 			goto failure;
1766 		}
1767 		/* mutex_exit(&cmd_sbp->fct_mtx); */
1768 
1769 		return (rval);
1770 
1771 	case FCT_CMD_RCVD_ELS:
1772 
1773 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1774 			goto failure;
1775 		}
1776 
1777 		rval =  emlxs_fct_send_els_rsp(fct_cmd);
1778 		/* mutex_exit(&cmd_sbp->fct_mtx); */
1779 
1780 		return (rval);
1781 
1782 	default:
1783 
1784 		if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
1785 			fct_cmd->cmd_handle = 0;
1786 		}
1787 
1788 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1789 		    "fct_send_cmd_rsp: Invalid cmd type found. type=%x",
1790 		    fct_cmd->cmd_type);
1791 
1792 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
1793 		/* mutex_exit(&cmd_sbp->fct_mtx); */
1794 
1795 		return (FCT_FAILURE);
1796 	}
1797 
1798 failure:
1799 
1800 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1801 	    "fct_send_cmd_rsp: "
1802 	    "Unable to handle FCT_IOF_FORCE_FCA_DONE. type=%x",
1803 	    fct_cmd->cmd_type);
1804 
1805 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
1806 	/* mutex_exit(&cmd_sbp->fct_mtx); */
1807 
1808 	return (FCT_FAILURE);
1809 
1810 } /* emlxs_fct_send_cmd_rsp() */
1811 
1812 
1813 /* COMSTAR ENTER POINT */
1814 static fct_status_t
emlxs_fct_flogi_xchg(struct fct_local_port * fct_port,struct fct_flogi_xchg * fx)1815 emlxs_fct_flogi_xchg(struct fct_local_port *fct_port, struct fct_flogi_xchg *fx)
1816 {
1817 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1818 	emlxs_hba_t *hba = HBA;
1819 	uint32_t size;
1820 	fc_packet_t *pkt = NULL;
1821 	ELS_PKT *els;
1822 	fct_status_t rval = FCT_SUCCESS;
1823 
1824 #ifdef FCT_API_TRACE
1825 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1826 	    "fct_flogi_xchg: Sending FLOGI: %p", fct_port);
1827 #else
1828 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1829 	    "fct_flogi_xchg: Sending FLOGI.");
1830 #endif /* FCT_API_TRACE */
1831 
1832 	if (hba->state <= FC_LINK_DOWN) {
1833 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1834 		    "fct_flogi_xchg: FLOGI failed. Link down.");
1835 		rval = FCT_FAILURE;
1836 		goto done;
1837 	}
1838 
1839 	/* Use this entry point as the link up acknowledgment */
1840 	mutex_enter(&EMLXS_PORT_LOCK);
1841 	port->fct_flags |= FCT_STATE_LINK_UP_ACKED;
1842 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1843 	    "fct_link_up acked.");
1844 	mutex_exit(&EMLXS_PORT_LOCK);
1845 
1846 	/* First handle any pending FLOGI's */
1847 	emlxs_fct_handle_unsol_flogi(port, NULL, 0);
1848 
1849 	size = sizeof (SERV_PARM) + 4;
1850 
1851 	if (!(pkt = emlxs_pkt_alloc(port, size, size, 0, KM_NOSLEEP))) {
1852 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1853 		    "fct_flogi_xchg: FLOGI failed. "
1854 		    "Unable allocate packet.");
1855 		rval = FCT_FAILURE;
1856 		goto done;
1857 	}
1858 
1859 	/* Make this a polled IO */
1860 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
1861 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
1862 	pkt->pkt_comp = NULL;
1863 
1864 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
1865 	pkt->pkt_timeout = fx->fx_sec_timeout;
1866 
1867 	/* Build the fc header */
1868 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fx->fx_did);
1869 	pkt->pkt_cmd_fhdr.r_ctl =
1870 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
1871 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(fx->fx_sid);
1872 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
1873 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
1874 	pkt->pkt_cmd_fhdr.seq_id = 0;
1875 	pkt->pkt_cmd_fhdr.df_ctl = 0;
1876 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
1877 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
1878 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
1879 	pkt->pkt_cmd_fhdr.ro = 0;
1880 
1881 	/* Build the command */
1882 	/* Service paramters will be added automatically later by the driver */
1883 	els = (ELS_PKT *)pkt->pkt_cmd;
1884 	els->elsCode = 0x04;	/* FLOGI */
1885 
1886 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
1887 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1888 		    "fct_flogi_xchg: FLOGI failed. "
1889 		    "Unable to send packet.");
1890 
1891 		rval = FCT_FAILURE;
1892 		goto done;
1893 	}
1894 
1895 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
1896 	    (pkt->pkt_state != FC_PKT_LS_RJT)) {
1897 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
1898 			rval = FCT_TIMEOUT;
1899 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
1900 		    (pkt->pkt_reason == FC_REASON_FCAL_OPN_FAIL)) {
1901 			rval = FCT_NOT_FOUND;
1902 		} else {
1903 			rval = FCT_FAILURE;
1904 		}
1905 
1906 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1907 		    "fct_flogi_xchg: FLOGI failed. state=%x reason=%x "
1908 		    "rval=%llx", pkt->pkt_state, pkt->pkt_reason, rval);
1909 
1910 		goto done;
1911 	}
1912 
1913 	if (pkt->pkt_state == FC_PKT_LS_RJT) {
1914 		fx->fx_op = ELS_OP_LSRJT;
1915 		fx->fx_rjt_reason = pkt->pkt_reason;
1916 		fx->fx_rjt_expl = pkt->pkt_expln;
1917 	} else {	/* FC_PKT_SUCCESS */
1918 
1919 		fx->fx_op = ELS_OP_ACC;
1920 		fx->fx_sid = FABRIC_DID;
1921 		fx->fx_did = port->did;
1922 
1923 		els = (ELS_PKT *)pkt->pkt_resp;
1924 		bcopy((caddr_t)&els->un.logi.nodeName,
1925 		    (caddr_t)fx->fx_nwwn, 8);
1926 		bcopy((caddr_t)&els->un.logi.portName,
1927 		    (caddr_t)fx->fx_pwwn, 8);
1928 		fx->fx_fport = els->un.logi.cmn.fPort;
1929 	}
1930 
1931 done:
1932 	if (pkt) {
1933 		emlxs_pkt_free(pkt);
1934 	}
1935 
1936 	if ((rval == FCT_SUCCESS) || (rval == FCT_NOT_FOUND)) {
1937 
1938 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
1939 		    "fct_flogi_xchg: FCT_STATE_FLOGI_CMPL.  rval=%s",
1940 		    ((rval == FCT_SUCCESS)? "FCT_SUCCESS":"FCT_NOT_FOUND"));
1941 
1942 		mutex_enter(&EMLXS_PORT_LOCK);
1943 		port->fct_flags |= FCT_STATE_FLOGI_CMPL;
1944 		mutex_exit(&EMLXS_PORT_LOCK);
1945 
1946 		/*
1947 		 * Flush all unsolicited commands
1948 		 * Must use separate thread since
1949 		 * this thread must complete first
1950 		 */
1951 		emlxs_thread_spawn(hba, emlxs_fct_unsol_flush_thread,
1952 		    (void *)port, 0);
1953 	}
1954 
1955 	return (rval);
1956 
1957 } /* emlxs_fct_flogi_xchg() */
1958 
1959 
1960 /* COMSTAR ENTER POINT */
1961 /* This is called right after we report that link has come online */
1962 static fct_status_t
emlxs_fct_get_link_info(fct_local_port_t * fct_port,fct_link_info_t * link)1963 emlxs_fct_get_link_info(fct_local_port_t *fct_port, fct_link_info_t *link)
1964 {
1965 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
1966 	emlxs_hba_t *hba = HBA;
1967 
1968 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
1969 	    "fct_get_link_info %p: FCT: flg x%x  HBA: ste x%x flg x%x topo x%x",
1970 	    fct_port, port->fct_flags, hba->state, hba->flag, hba->topology);
1971 
1972 	mutex_enter(&EMLXS_PORT_LOCK);
1973 
1974 	if (port->mode == MODE_INITIATOR) {
1975 		link->port_topology = PORT_TOPOLOGY_UNKNOWN;
1976 		link->port_speed = PORT_SPEED_UNKNOWN;
1977 		link->portid = 0;
1978 
1979 		mutex_exit(&EMLXS_PORT_LOCK);
1980 
1981 		return (FCT_SUCCESS);
1982 	}
1983 
1984 	if (!(port->fct_flags & FCT_STATE_LINK_UP) ||
1985 	    (hba->state < FC_LINK_UP) || (hba->flag & FC_LOOPBACK_MODE)) {
1986 		link->port_topology = PORT_TOPOLOGY_UNKNOWN;
1987 		link->port_speed = PORT_SPEED_UNKNOWN;
1988 		link->portid = 0;
1989 
1990 		mutex_exit(&EMLXS_PORT_LOCK);
1991 
1992 		return (FCT_SUCCESS);
1993 	}
1994 
1995 	if (hba->topology == TOPOLOGY_LOOP) {
1996 		link->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP;
1997 	} else {
1998 		link->port_topology = PORT_TOPOLOGY_PT_TO_PT;
1999 	}
2000 
2001 	switch (hba->linkspeed) {
2002 	case LA_1GHZ_LINK:
2003 		link->port_speed = PORT_SPEED_1G;
2004 		break;
2005 	case LA_2GHZ_LINK:
2006 		link->port_speed = PORT_SPEED_2G;
2007 		break;
2008 	case LA_4GHZ_LINK:
2009 		link->port_speed = PORT_SPEED_4G;
2010 		break;
2011 	case LA_8GHZ_LINK:
2012 		link->port_speed = PORT_SPEED_8G;
2013 		break;
2014 	case LA_10GHZ_LINK:
2015 		link->port_speed = PORT_SPEED_10G;
2016 		break;
2017 	case LA_16GHZ_LINK:
2018 		link->port_speed = PORT_SPEED_16G;
2019 		break;
2020 	case LA_32GHZ_LINK:
2021 		link->port_speed = PORT_SPEED_32G;
2022 		break;
2023 	default:
2024 		link->port_speed = PORT_SPEED_UNKNOWN;
2025 		break;
2026 	}
2027 
2028 	link->portid = port->did;
2029 	link->port_no_fct_flogi = 0;
2030 	link->port_fca_flogi_done = 0;
2031 	link->port_fct_flogi_done = 0;
2032 
2033 	mutex_exit(&EMLXS_PORT_LOCK);
2034 
2035 	return (FCT_SUCCESS);
2036 
2037 } /* emlxs_fct_get_link_info() */
2038 
2039 
2040 /* COMSTAR ENTER POINT */
2041 static fct_status_t
emlxs_fct_register_remote_port(fct_local_port_t * fct_port,fct_remote_port_t * remote_port,fct_cmd_t * fct_cmd)2042 emlxs_fct_register_remote_port(fct_local_port_t *fct_port,
2043     fct_remote_port_t *remote_port, fct_cmd_t *fct_cmd)
2044 {
2045 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2046 	emlxs_hba_t *hba = HBA;
2047 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2048 	clock_t timeout;
2049 	int32_t pkt_ret;
2050 	fct_els_t *els;
2051 	SERV_PARM *sp;
2052 	emlxs_node_t *ndlp;
2053 	SERV_PARM sparam;
2054 	uint32_t *iptr;
2055 	uint16_t hdl;
2056 	uint64_t addr;
2057 	fct_status_t rval;
2058 	fct_status_t rval2;
2059 	uint32_t i;
2060 
2061 #ifdef FCT_API_TRACE
2062 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2063 	    "fct_register_remote_port %p", fct_port);
2064 #endif /* FCT_API_TRACE */
2065 
2066 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
2067 
2068 		cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd,
2069 		    EMLXS_FCT_REG_PENDING);
2070 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2071 
2072 		cmd_sbp->channel = &hba->chan[hba->channel_els];
2073 		cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
2074 
2075 	} else {
2076 
2077 		rval = emlxs_fct_cmd_accept(port, fct_cmd,
2078 		    EMLXS_FCT_REG_PENDING);
2079 		if (rval) {
2080 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2081 			    "fct_register_remote_port: "
2082 			    "Unable to accept fct_cmd. lid=%x rid=%x",
2083 			    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid);
2084 
2085 			return (rval);
2086 		}
2087 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2088 	}
2089 
2090 	cmd_sbp->fct_flags &= ~EMLXS_FCT_REGISTERED;
2091 	cmd_sbp->node = emlxs_node_find_did(port, fct_cmd->cmd_rportid, 1);
2092 
2093 	/* Check for unsolicited PLOGI */
2094 	if (cmd_sbp->fct_flags & EMLXS_FCT_PLOGI_RECEIVED) {
2095 		els = (fct_els_t *)fct_cmd->cmd_specific;
2096 		sp = (SERV_PARM *)((caddr_t)els->els_req_payload +
2097 		    sizeof (uint32_t));
2098 
2099 	} else {	/* Solicited PLOGI */
2100 
2101 		sp = &sparam;
2102 		bcopy((caddr_t)&port->sparam, (caddr_t)sp,
2103 		    sizeof (SERV_PARM));
2104 
2105 		/*
2106 		 * Create temporary WWN's from fct_cmd address
2107 		 * This simply allows us to get an RPI from the
2108 		 * adapter until we get real service params.
2109 		 * The PLOGI ACC reply will trigger a REG_LOGIN
2110 		 * update later
2111 		 */
2112 		addr = (uint64_t)((unsigned long)fct_cmd);
2113 
2114 		iptr = (uint32_t *)&sp->portName;
2115 		iptr[0] = PADDR_HI(addr);
2116 		iptr[1] = PADDR_LO(addr);
2117 
2118 		iptr = (uint32_t *)&sp->nodeName;
2119 		iptr[0] = PADDR_HI(addr);
2120 		iptr[1] = PADDR_LO(addr);
2121 	}
2122 
2123 	if (hba->flag & FC_PT_TO_PT) {
2124 		mutex_enter(&EMLXS_PORT_LOCK);
2125 		port->did = fct_cmd->cmd_lportid;
2126 		port->rdid = fct_cmd->cmd_rportid;
2127 		mutex_exit(&EMLXS_PORT_LOCK);
2128 
2129 		/*
2130 		 * We already received the remote port's
2131 		 * parameters in the FLOGI exchange
2132 		 */
2133 		if (!(cmd_sbp->fct_flags & EMLXS_FCT_PLOGI_RECEIVED)) {
2134 			sp = &sparam;
2135 			bcopy((caddr_t)&port->fabric_sparam, (caddr_t)sp,
2136 			    sizeof (SERV_PARM));
2137 
2138 			/*
2139 			 * Since this is a PLOGI, not a FLOGI, we need
2140 			 * to fix up word2 of the CSP accordingly.
2141 			 */
2142 			sp->cmn.w2.r_a_tov = port->sparam.cmn.w2.r_a_tov;
2143 		}
2144 	}
2145 
2146 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
2147 	    "fct_register_remote_port: Register lid=%x rid=%x. (%x,%x,%p)",
2148 	    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid, cmd_sbp->fct_state,
2149 	    hba->flag, fct_cmd);
2150 
2151 	emlxs_fct_cmd_release(port, fct_cmd, 0);
2152 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2153 
2154 	/* Create a new node */
2155 	if (EMLXS_SLI_REG_DID(port, fct_cmd->cmd_rportid, sp, cmd_sbp,
2156 	    NULL, NULL) != 0) {
2157 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2158 		    "fct_register_remote_port: "
2159 		    "Reg login failed. lid=%x rid=%x",
2160 		    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid);
2161 	} else {
2162 
2163 		/* Wait for completion */
2164 		mutex_enter(&EMLXS_PKT_LOCK);
2165 		timeout = emlxs_timeout(hba, 30);
2166 		pkt_ret = 0;
2167 		while ((pkt_ret != -1) &&
2168 		    (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) &&
2169 		    !(cmd_sbp->fct_flags & EMLXS_FCT_REGISTERED)) {
2170 			pkt_ret = cv_timedwait(&EMLXS_PKT_CV,
2171 			    &EMLXS_PKT_LOCK, timeout);
2172 		}
2173 		mutex_exit(&EMLXS_PKT_LOCK);
2174 	}
2175 
2176 	/* Reacquire ownership of the fct_cmd */
2177 	rval2 = emlxs_fct_cmd_acquire(port, fct_cmd,
2178 	    EMLXS_FCT_REG_COMPLETE);
2179 	if (rval2) {
2180 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2181 		    "fct_register_remote_port: "
2182 		    "Unable to reacquire fct_cmd. lid=%x rid=%x",
2183 		    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid);
2184 
2185 		return (rval2);
2186 	}
2187 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2188 
2189 	/* Prepare response */
2190 
2191 	ndlp = (emlxs_node_t *)cmd_sbp->node;
2192 
2193 	if (ndlp) {
2194 		cmd_sbp->fct_flags |= EMLXS_FCT_REGISTERED;
2195 
2196 		*((emlxs_node_t **)remote_port->rp_fca_private) =
2197 		    cmd_sbp->node;
2198 
2199 		hdl = ndlp->nlp_Rpi;
2200 		if (hdl == FABRIC_RPI) {
2201 			if (fct_cmd->cmd_rportid == SCR_DID) {
2202 				/* The SCR handle is hardcoded */
2203 				remote_port->rp_handle = hba->max_nodes;
2204 				port->fct_els_only_bmap |= 1;
2205 
2206 			} else {
2207 				for (i = 1; i < EMLXS_FCT_NUM_ELS_ONLY; i++) {
2208 					if (port->fct_els_only_bmap & (1 << i))
2209 						continue;
2210 					/*
2211 					 * Bit is not set, so use this
2212 					 * for the handle
2213 					 */
2214 					remote_port->rp_handle =
2215 					    hba->max_nodes + i;
2216 					port->fct_els_only_bmap |= (1 << i);
2217 					break;
2218 				}
2219 				if (i >= EMLXS_FCT_NUM_ELS_ONLY) {
2220 					remote_port->rp_handle =
2221 					    FCT_HANDLE_NONE;
2222 				}
2223 			}
2224 		} else {
2225 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2226 				hdl = emlxs_sli4_rpi_to_index(hba, hdl);
2227 			}
2228 			remote_port->rp_handle = hdl;
2229 		}
2230 
2231 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2232 		    "fct_register_remote_port: lid=%x rid=%x hdl=%x",
2233 		    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid,
2234 		    remote_port->rp_handle);
2235 
2236 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2237 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2238 
2239 		TGTPORTSTAT.FctPortRegister++;
2240 		return (FCT_SUCCESS);
2241 	} else {
2242 		*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
2243 
2244 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2245 		    "fct_register_remote_port: failed. lid=%x rid=%x hdl=%x",
2246 		    fct_cmd->cmd_lportid, fct_cmd->cmd_rportid,
2247 		    remote_port->rp_handle);
2248 
2249 		remote_port->rp_handle = FCT_HANDLE_NONE;
2250 
2251 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2252 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2253 
2254 		TGTPORTSTAT.FctFailedPortRegister++;
2255 		return (FCT_FAILURE);
2256 	}
2257 
2258 } /* emlxs_fct_register_remote_port() */
2259 
2260 
2261 /* COMSTAR ENTER POINT */
2262 static fct_status_t
emlxs_fct_deregister_remote_port(fct_local_port_t * fct_port,fct_remote_port_t * remote_port)2263 emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port,
2264     fct_remote_port_t *remote_port)
2265 {
2266 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
2267 	emlxs_hba_t *hba = HBA;
2268 	emlxs_node_t *ndlp;
2269 	uint32_t i;
2270 
2271 #ifdef FCT_API_TRACE
2272 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2273 	    "fct_deregister_remote_port: did=%x hdl=%x",
2274 	    remote_port->rp_id, remote_port->rp_handle);
2275 #else
2276 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2277 	    "fct_deregister_remote_port: did=%x hdl=%x",
2278 	    remote_port->rp_id, remote_port->rp_handle);
2279 #endif /* FCT_API_TRACE */
2280 
2281 	if (remote_port->rp_handle >= hba->max_nodes) {
2282 		i = remote_port->rp_handle - hba->max_nodes;
2283 		if ((i < EMLXS_FCT_NUM_ELS_ONLY) &&
2284 		    (port->fct_els_only_bmap & (1 << i))) {
2285 			port->fct_els_only_bmap &= ~(1 << i);
2286 		}
2287 	}
2288 
2289 	ndlp = *((emlxs_node_t **)remote_port->rp_fca_private);
2290 	*((emlxs_node_t **)remote_port->rp_fca_private) = NULL;
2291 
2292 	if (ndlp) {
2293 		(void) EMLXS_SLI_UNREG_NODE(port, ndlp, NULL,
2294 		    NULL, NULL);
2295 	}
2296 
2297 	TGTPORTSTAT.FctPortDeregister++;
2298 	return (FCT_SUCCESS);
2299 
2300 } /* emlxs_fct_deregister_remote_port() */
2301 
2302 
2303 /* ARGSUSED */
2304 extern int
emlxs_fct_handle_unsol_req(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)2305 emlxs_fct_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
2306     MATCHMAP *mp, uint32_t size)
2307 {
2308 	emlxs_hba_t *hba = HBA;
2309 	IOCB *iocb;
2310 	fct_cmd_t *fct_cmd;
2311 	emlxs_buf_t *cmd_sbp;
2312 	emlxs_fcp_cmd_t *fcp_cmd;
2313 	emlxs_node_t *ndlp;
2314 	uint32_t cnt;
2315 	uint32_t tm;
2316 	uint16_t hdl;
2317 	scsi_task_t *fct_task;
2318 	uint8_t lun[8];
2319 	uint32_t sid = 0;
2320 
2321 	iocb = &iocbq->iocb;
2322 	ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG);
2323 	if (!ndlp) {
2324 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2325 		    "FCP rcvd: Unknown RPI. rpi=%d rxid=%x. Dropping...",
2326 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2327 
2328 		goto dropped;
2329 	}
2330 	sid = ndlp->nlp_DID;
2331 
2332 	fcp_cmd = (emlxs_fcp_cmd_t *)mp->virt;
2333 
2334 	if (!port->fct_port) {
2335 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2336 		    "FCP rcvd: Target unbound. rpi=%d rxid=%x. Dropping...",
2337 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2338 
2339 		emlxs_send_logo(port, sid);
2340 
2341 		goto dropped;
2342 	}
2343 
2344 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
2345 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2346 		    "FCP rcvd: Target offline. rpi=%d rxid=%x. Dropping...",
2347 		    iocb->ULPIOTAG, iocb->ULPCONTEXT);
2348 
2349 		emlxs_send_logo(port, sid);
2350 
2351 		goto dropped;
2352 	}
2353 
2354 	/* Get lun id */
2355 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2356 
2357 	if (TGTPORTSTAT.FctOutstandingIO >= port->fct_port->port_max_xchges) {
2358 		TGTPORTSTAT.FctOverQDepth++;
2359 	}
2360 
2361 	hdl = ndlp->nlp_Rpi;
2362 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2363 		hdl = emlxs_sli4_rpi_to_index(hba, hdl);
2364 	}
2365 	fct_cmd =
2366 	    MODSYM(fct_scsi_task_alloc) (port->fct_port, hdl, sid, lun, 16, 0);
2367 
2368 	if (fct_cmd == NULL) {
2369 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2370 		    "FCP rcvd: sid=%x xid=%x. "
2371 		    "Unable to allocate scsi task. Returning QFULL.",
2372 		    sid, iocb->ULPCONTEXT);
2373 
2374 		(void) emlxs_fct_send_qfull_reply(port, ndlp, iocb->ULPCONTEXT,
2375 		    iocb->ULPCLASS, fcp_cmd);
2376 
2377 		goto dropped;
2378 	}
2379 
2380 	/* Initialize fct_cmd */
2381 	fct_cmd->cmd_rportid = sid;
2382 	fct_cmd->cmd_lportid = port->did;
2383 	fct_cmd->cmd_rp_handle = hdl;
2384 	fct_cmd->cmd_port = port->fct_port;
2385 
2386 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_FCP_CMD_RECEIVED);
2387 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2388 
2389 #ifdef FCT_API_TRACE
2390 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2391 	    "fct_scsi_task_alloc %p:%p FCP rcvd: "
2392 	    "cmd=%x sid=%x rxid=%x oxid=%x lun=%02x%02x dl=%d",
2393 	    fct_cmd, cmd_sbp, fcp_cmd->fcpCdb[0], sid, iocb->ULPCONTEXT,
2394 	    iocb->unsli3.ext_rcv.oxid, lun[0], lun[1],
2395 	    LE_SWAP32(fcp_cmd->fcpDl));
2396 #endif /* FCT_API_TRACE */
2397 
2398 	/* Initialize cmd_sbp */
2399 	cmd_sbp->channel = cp;
2400 	cmd_sbp->class = iocb->ULPCLASS;
2401 	cmd_sbp->lun = (lun[0] << 8) | lun[1];
2402 	cmd_sbp->fct_type = EMLXS_FCT_FCP_CMD;
2403 	cmd_sbp->ticks = hba->timer_tics + (2 * hba->fc_ratov);
2404 
2405 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2406 		/* xrip was setup / passed in from the SLI layer */
2407 		cmd_sbp->xrip = iocbq->sbp;
2408 		cmd_sbp->node = iocbq->node;
2409 		iocbq->sbp = 0;
2410 
2411 		fct_cmd->cmd_oxid = cmd_sbp->xrip->rx_id;
2412 		fct_cmd->cmd_rxid = cmd_sbp->xrip->XRI;
2413 
2414 #ifdef FCT_API_TRACE
2415 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2416 		    "FCP rcvd: oxid=%x rxid=%x iotag=%d %p ",
2417 		    fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp->xrip->iotag,
2418 		    hba->fc_table[cmd_sbp->xrip->iotag]);
2419 #endif /* FCT_API_TRACE */
2420 
2421 	} else {
2422 		fct_cmd->cmd_oxid = iocb->unsli3.ext_rcv.oxid;
2423 		if (!fct_cmd->cmd_oxid) {
2424 			fct_cmd->cmd_oxid = 0xFFFF;
2425 		}
2426 		fct_cmd->cmd_rxid = iocb->ULPCONTEXT;
2427 	}
2428 
2429 
2430 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2431 
2432 	/* Set task_flags */
2433 	switch (fcp_cmd->fcpCntl1) {
2434 	case SIMPLE_Q:
2435 		fct_task->task_flags = TF_ATTR_SIMPLE_QUEUE;
2436 		break;
2437 
2438 	case HEAD_OF_Q:
2439 		fct_task->task_flags = TF_ATTR_HEAD_OF_QUEUE;
2440 		break;
2441 
2442 	case ORDERED_Q:
2443 		fct_task->task_flags = TF_ATTR_ORDERED_QUEUE;
2444 		break;
2445 
2446 	case ACA_Q:
2447 		fct_task->task_flags = TF_ATTR_ACA;
2448 		break;
2449 
2450 	case UNTAGGED:
2451 		fct_task->task_flags = TF_ATTR_UNTAGGED;
2452 		break;
2453 	}
2454 
2455 	cnt = LE_SWAP32(fcp_cmd->fcpDl);
2456 	switch (fcp_cmd->fcpCntl3) {
2457 	case 0:
2458 		TGTPORTSTAT.FctIOCmdCnt++;
2459 		break;
2460 	case 1:
2461 		EMLXS_BUMP_WRIOCTR(port, cnt);
2462 		TGTPORTSTAT.FctWriteBytes += cnt;
2463 		fct_task->task_flags |= TF_WRITE_DATA;
2464 		break;
2465 
2466 	case 2:
2467 		EMLXS_BUMP_RDIOCTR(port, cnt);
2468 		TGTPORTSTAT.FctReadBytes += cnt;
2469 		fct_task->task_flags |= TF_READ_DATA;
2470 		break;
2471 	}
2472 
2473 	fct_task->task_priority = 0;
2474 
2475 	/* task_mgmt_function */
2476 	tm = fcp_cmd->fcpCntl2;
2477 	if (tm) {
2478 		if (tm & BIT_1) {
2479 			fct_task->task_mgmt_function = TM_ABORT_TASK_SET;
2480 		} else if (tm & BIT_2) {
2481 			fct_task->task_mgmt_function = TM_CLEAR_TASK_SET;
2482 		} else if (tm & BIT_4) {
2483 			fct_task->task_mgmt_function = TM_LUN_RESET;
2484 		} else if (tm & BIT_5) {
2485 			fct_task->task_mgmt_function = TM_TARGET_COLD_RESET;
2486 		} else if (tm & BIT_6) {
2487 			fct_task->task_mgmt_function = TM_CLEAR_ACA;
2488 		} else {
2489 			fct_task->task_mgmt_function = TM_ABORT_TASK;
2490 		}
2491 	}
2492 
2493 	/* Parallel buffers support - future */
2494 	fct_task->task_max_nbufs = 1;
2495 
2496 	fct_task->task_additional_flags = 0;
2497 	fct_task->task_cur_nbufs = 0;
2498 	fct_task->task_csn_size = 8;
2499 	fct_task->task_cmd_seq_no = 0;
2500 	fct_task->task_expected_xfer_length = cnt;
2501 	bcopy((void *)&fcp_cmd->fcpCdb, fct_task->task_cdb, 16);
2502 
2503 	TGTPORTSTAT.FctCmdReceived++;
2504 	TGTPORTSTAT.FctOutstandingIO++;
2505 
2506 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2507 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2508 
2509 #ifdef FCT_API_TRACE
2510 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2511 	    "fct_post_rcvd_cmd:3 %p:%p portid x%x, %d outio %d",
2512 	    fct_cmd, cmd_sbp, fct_cmd->cmd_lportid,
2513 	    fct_task->task_expected_xfer_length,
2514 	    TGTPORTSTAT.FctOutstandingIO);
2515 #endif /* FCT_API_TRACE */
2516 
2517 	MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
2518 
2519 	return (0);
2520 
2521 dropped:
2522 
2523 	TGTPORTSTAT.FctRcvDropped++;
2524 	return (1);
2525 
2526 } /* emlxs_fct_handle_unsol_req() */
2527 
2528 
2529 /* COMSTAR ENTER POINT */
2530 /* ARGSUSED */
2531 static fct_status_t
emlxs_fct_send_fcp_data(fct_cmd_t * fct_cmd,stmf_data_buf_t * dbuf,uint32_t ioflags)2532 emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, stmf_data_buf_t *dbuf,
2533     uint32_t ioflags)
2534 {
2535 	emlxs_port_t *port =
2536 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2537 	emlxs_hba_t *hba = HBA;
2538 	emlxs_buf_t *cmd_sbp;
2539 #ifdef FCT_API_TRACE
2540 	scsi_task_t *fct_task;
2541 #endif /* FCT_API_TRACE */
2542 	IOCBQ *iocbq;
2543 	emlxs_node_t *ndlp;
2544 
2545 	int	channel;
2546 	int	channelno;
2547 	fct_status_t rval = 0;
2548 
2549 	rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_FCP_DATA);
2550 	if (rval) {
2551 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2552 		    "fct_send_fcp_data: "
2553 		    "Unable to accept fct_cmd. did=%x",
2554 		    fct_cmd->cmd_rportid);
2555 
2556 		return (rval);
2557 	}
2558 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2559 
2560 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2561 #ifdef FCT_API_TRACE
2562 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2563 #endif /* FCT_API_TRACE */
2564 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
2565 
2566 	cmd_sbp->node = ndlp;
2567 	cmd_sbp->fct_buf = dbuf;
2568 
2569 	channelno = ((CHANNEL *)cmd_sbp->channel)->channelno;
2570 
2571 	channel = channelno;
2572 
2573 
2574 
2575 	iocbq = &cmd_sbp->iocbq;
2576 	iocbq->sbp = cmd_sbp;
2577 
2578 #ifdef FCT_API_TRACE
2579 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2580 	    "fct_send_fcp_data %p:%p flgs=%x ioflags=%x dl=%d,%d,%d,%d",
2581 	    fct_cmd, cmd_sbp, dbuf->db_flags, ioflags,
2582 	    fct_task->task_cmd_xfer_length,
2583 	    fct_task->task_nbytes_transferred, dbuf->db_data_size,
2584 	    fct_task->task_expected_xfer_length);
2585 #endif /* FCT_API_TRACE */
2586 
2587 	/* Setup for I/O prep routine */
2588 	iocbq->iocb.ULPCOMMAND = 0;
2589 
2590 	if (EMLXS_SLI_PREP_FCT_IOCB(port, cmd_sbp, channel) != IOERR_SUCCESS) {
2591 
2592 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2593 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2594 
2595 		return (FCT_BUSY);
2596 	}
2597 
2598 	cmd_sbp->fct_type = EMLXS_FCT_FCP_DATA;
2599 
2600 	if (dbuf->db_flags & DB_SEND_STATUS_GOOD) {
2601 		cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
2602 	}
2603 
2604 	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
2605 		if (emlxs_fct_dbuf_dma_sync(hba, dbuf, DDI_DMA_SYNC_FORDEV)) {
2606 			emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2607 			/* mutex_exit(&cmd_sbp->fct_mtx); */
2608 
2609 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2610 				emlxs_sli4_free_xri(port, cmd_sbp, 0, 0);
2611 			}
2612 			return (FCT_BUSY);
2613 		}
2614 	}
2615 
2616 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
2617 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_DATA_PENDING);
2618 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2619 
2620 	EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, iocbq);
2621 
2622 	return (FCT_SUCCESS);
2623 
2624 } /* emlxs_fct_send_fcp_data() */
2625 
2626 
2627 /* cmd_sbp->fct_mtx must be held to enter */
2628 /* cmd_sbp->fct_mtx must be released before exiting */
2629 static fct_status_t
emlxs_fct_send_fcp_status(fct_cmd_t * fct_cmd)2630 emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd)
2631 {
2632 	emlxs_port_t *port =
2633 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
2634 	emlxs_hba_t *hba = HBA;
2635 	emlxs_buf_t *cmd_sbp;
2636 	scsi_task_t *fct_task;
2637 	fc_packet_t *pkt;
2638 	emlxs_buf_t *sbp = NULL;
2639 	emlxs_fcp_rsp *fcp_rsp;
2640 	emlxs_node_t *ndlp;
2641 	fct_status_t rval;
2642 	uint32_t did;
2643 	uint32_t size;
2644 
2645 	fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
2646 	ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
2647 	did = fct_cmd->cmd_rportid;
2648 
2649 	/* Initialize cmd_sbp */
2650 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2651 
2652 	EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_FCP_STATUS);
2653 
2654 	cmd_sbp->node = ndlp;
2655 
2656 	size = 24;
2657 	if (fct_task->task_sense_length) {
2658 		size += fct_task->task_sense_length;
2659 	}
2660 #ifdef FCT_API_TRACE
2661 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2662 	    "fct_send_fcp_status %p:%p stat=%d resid=%d size=%d rx=%x ox=%x",
2663 	    fct_cmd, cmd_sbp, fct_task->task_scsi_status,
2664 	    fct_task->task_resid, size, fct_cmd->cmd_rxid, fct_cmd->cmd_oxid);
2665 #endif /* FCT_API_TRACE */
2666 
2667 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2668 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2669 		    "fct_send_fcp_status: Unable to allocate packet.");
2670 
2671 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2672 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2673 
2674 		return (FCT_BUSY);
2675 	}
2676 
2677 	cmd_sbp->fct_type = EMLXS_FCT_FCP_STATUS;
2678 
2679 	sbp =  emlxs_fct_pkt_init(port, fct_cmd, pkt);
2680 	cmd_sbp->fct_pkt = pkt;
2681 
2682 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2683 	pkt->pkt_timeout =
2684 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2685 	pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout;
2686 	pkt->pkt_comp = emlxs_fct_pkt_comp;
2687 
2688 	/* Build the fc header */
2689 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
2690 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
2691 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
2692 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2693 	pkt->pkt_cmd_fhdr.f_ctl =
2694 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2695 	pkt->pkt_cmd_fhdr.seq_id = 0;
2696 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2697 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2698 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
2699 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
2700 	pkt->pkt_cmd_fhdr.ro = 0;
2701 
2702 	/* Build the status payload */
2703 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2704 
2705 	if (fct_task->task_resid) {
2706 		if (fct_task->task_status_ctrl & TASK_SCTRL_OVER) {
2707 			TGTPORTSTAT.FctScsiResidOver++;
2708 			fcp_rsp->rspStatus2 |= RESID_OVER;
2709 			fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid);
2710 
2711 		} else if (fct_task->task_status_ctrl & TASK_SCTRL_UNDER) {
2712 			TGTPORTSTAT.FctScsiResidUnder++;
2713 			fcp_rsp->rspStatus2 |= RESID_UNDER;
2714 			fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid);
2715 
2716 		}
2717 	}
2718 
2719 	if (fct_task->task_scsi_status) {
2720 		if (fct_task->task_scsi_status == SCSI_STAT_QUE_FULL) {
2721 			TGTPORTSTAT.FctScsiQfullErr++;
2722 		} else {
2723 			TGTPORTSTAT.FctScsiStatusErr++;
2724 		}
2725 
2726 		/* Make sure residual reported on non-SCSI_GOOD READ status */
2727 		if ((fct_task->task_flags & TF_READ_DATA) &&
2728 		    (fcp_rsp->rspResId == 0)) {
2729 			fcp_rsp->rspStatus2 |= RESID_UNDER;
2730 			fcp_rsp->rspResId =
2731 			    fct_task->task_expected_xfer_length;
2732 		}
2733 	}
2734 
2735 
2736 	if (fct_task->task_sense_length) {
2737 		TGTPORTSTAT.FctScsiSenseErr++;
2738 		fcp_rsp->rspStatus2 |= SNS_LEN_VALID;
2739 		fcp_rsp->rspSnsLen = LE_SWAP32(fct_task->task_sense_length);
2740 
2741 		bcopy((uint8_t *)fct_task->task_sense_data,
2742 		    (uint8_t *)&fcp_rsp->rspInfo0,
2743 		    fct_task->task_sense_length);
2744 	}
2745 
2746 	fcp_rsp->rspStatus3 = fct_task->task_scsi_status;
2747 	fcp_rsp->rspRspLen = 0;
2748 
2749 #ifdef FCT_API_TRACE
2750 	emlxs_data_dump(port, "RESP", (uint32_t *)fcp_rsp, 36, 0);
2751 #endif /* FCT_API_TRACE */
2752 
2753 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
2754 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_STATUS_PENDING);
2755 	/* mutex_exit(&cmd_sbp->fct_mtx); */
2756 
2757 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2758 
2759 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2760 		    "fct_send_fcp_status: Unable to send packet.");
2761 
2762 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2763 			emlxs_sli4_free_xri(port, sbp, 0, 0);
2764 		}
2765 
2766 		/* Reacquire ownership of the fct_cmd */
2767 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
2768 		if (rval) {
2769 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2770 			    "fct_send_fcp_status: "
2771 			    "Unable to acquire fct_cmd.");
2772 			return (rval);
2773 		}
2774 		/* mutex_enter(&cmd_sbp->fct_mtx); */
2775 
2776 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
2777 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2778 
2779 		return (FCT_BUSY);
2780 	}
2781 
2782 	return (FCT_SUCCESS);
2783 
2784 } /* emlxs_fct_send_fcp_status() */
2785 
2786 
2787 static fct_status_t
emlxs_fct_send_qfull_reply(emlxs_port_t * port,emlxs_node_t * ndlp,uint16_t xid,uint32_t class,emlxs_fcp_cmd_t * fcp_cmd)2788 emlxs_fct_send_qfull_reply(emlxs_port_t *port, emlxs_node_t *ndlp,
2789     uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd)
2790 {
2791 	emlxs_hba_t *hba = HBA;
2792 	emlxs_buf_t *sbp;
2793 	fc_packet_t *pkt;
2794 	emlxs_fcp_rsp *fcp_rsp;
2795 	uint32_t size;
2796 	CHANNEL *cp = &hba->chan[hba->CHANNEL_FCT];
2797 	uint8_t lun[8];
2798 
2799 	bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8);
2800 	size = 24;
2801 
2802 	if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) {
2803 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2804 		    "fct_send_qfull_reply: Unable to allocate packet.");
2805 		return (FCT_FAILURE);
2806 	}
2807 
2808 	sbp = PKT2PRIV(pkt);
2809 	sbp->node = ndlp;
2810 	sbp->channel = cp;
2811 	sbp->did = ndlp->nlp_DID;
2812 	sbp->lun = (lun[0] << 8) | lun[1];
2813 	sbp->class = class;
2814 
2815 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
2816 	pkt->pkt_timeout =
2817 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
2818 
2819 	/* Build the fc header */
2820 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID);
2821 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
2822 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
2823 	pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
2824 	pkt->pkt_cmd_fhdr.f_ctl =
2825 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
2826 	pkt->pkt_cmd_fhdr.seq_id = 0;
2827 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2828 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2829 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2830 	pkt->pkt_cmd_fhdr.rx_id = xid;
2831 	pkt->pkt_cmd_fhdr.ro = 0;
2832 
2833 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2834 	    "fct_send_qfull_reply: Sending QFULL: x%x lun x%x: %d %d",
2835 	    xid, sbp->lun, TGTPORTSTAT.FctOutstandingIO,
2836 	    port->fct_port->port_max_xchges);
2837 
2838 	/* Build the status payload */
2839 	fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd;
2840 
2841 	TGTPORTSTAT.FctScsiQfullErr++;
2842 	fcp_rsp->rspStatus3 = SCSI_STAT_QUE_FULL;
2843 	fcp_rsp->rspStatus2 |= RESID_UNDER;
2844 	fcp_rsp->rspResId = LE_SWAP32(fcp_cmd->fcpDl);
2845 
2846 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2847 
2848 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2849 			emlxs_sli4_free_xri(port, sbp, 0, 0);
2850 		}
2851 
2852 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2853 		    "fct_send_qfull_reply: Unable to send packet.");
2854 		emlxs_pkt_free(pkt);
2855 		return (FCT_FAILURE);
2856 	}
2857 
2858 	return (FCT_SUCCESS);
2859 
2860 } /* emlxs_fct_send_qfull_reply() */
2861 
2862 
2863 /* ARGSUSED */
2864 extern int
emlxs_fct_handle_fcp_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)2865 emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2866 {
2867 	emlxs_port_t *port = &PPORT;
2868 	IOCB *iocb;
2869 	emlxs_buf_t *sbp;
2870 	emlxs_buf_t *cmd_sbp;
2871 	uint32_t status;
2872 	fct_cmd_t *fct_cmd;
2873 	stmf_data_buf_t *dbuf;
2874 	scsi_task_t *fct_task;
2875 	fc_packet_t *pkt;
2876 	uint32_t fct_flags;
2877 	stmf_data_buf_t *fct_buf;
2878 	fct_status_t rval;
2879 
2880 	iocb = &iocbq->iocb;
2881 	sbp = (emlxs_buf_t *)iocbq->sbp;
2882 
2883 	TGTPORTSTAT.FctEvent++;
2884 
2885 	if (!sbp) {
2886 		/* completion with missing xmit command */
2887 		TGTPORTSTAT.FctStray++;
2888 
2889 		/* emlxs_stray_fcp_completion_msg */
2890 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2891 		    "FCP event cmd=%x status=%x error=%x iotag=%d",
2892 		    iocb->ULPCOMMAND, iocb->ULPSTATUS,
2893 		    iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG);
2894 
2895 		return (1);
2896 	}
2897 
2898 	TGTPORTSTAT.FctCompleted++;
2899 
2900 	port = sbp->iocbq.port;
2901 	fct_cmd = sbp->fct_cmd;
2902 	status = iocb->ULPSTATUS;
2903 
2904 #ifdef FCT_API_TRACE
2905 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2906 	    "fct_handle_fcp_event: %p:%p cmd=%x status=%x, %x",
2907 	    fct_cmd, sbp, iocb->ULPCOMMAND, status, iocb->ULPCT);
2908 #endif /* FCT_API_TRACE */
2909 
2910 	if (fct_cmd == NULL) {
2911 		/* For driver generated QFULL response */
2912 		if (((iocb->ULPCOMMAND == CMD_FCP_TRSP_CX) ||
2913 		    (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX)) && sbp->pkt) {
2914 			emlxs_pkt_free(sbp->pkt);
2915 		}
2916 		return (0);
2917 	}
2918 
2919 	rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_REQ_COMPLETE);
2920 	if (rval) {
2921 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
2922 		    "fct_handle_fcp_event: "
2923 		    "Unable to reacquire fct_cmd. type=%x",
2924 		    fct_cmd->cmd_type);
2925 
2926 		return (1);
2927 	}
2928 	/* mutex_enter(&cmd_sbp->fct_mtx); */
2929 
2930 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
2931 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
2932 
2933 	pkt = cmd_sbp->fct_pkt;
2934 	cmd_sbp->fct_pkt = NULL;
2935 
2936 	dbuf = sbp->fct_buf;
2937 
2938 	fct_cmd->cmd_comp_status = FCT_SUCCESS;
2939 
2940 	if (status) {
2941 emlxs_dma_error:
2942 		/*
2943 		 * The error indicates this IO should be terminated
2944 		 * immediately.
2945 		 */
2946 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
2947 		fct_cmd->cmd_comp_status = FCT_FAILURE;
2948 
2949 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
2950 		/* mutex_exit(&cmd_sbp->fct_mtx); */
2951 
2952 #ifdef FCT_API_TRACE
2953 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
2954 		    "fct_queue_cmd_for_termination:1 %p: x%x",
2955 		    fct_cmd, fct_cmd->cmd_comp_status);
2956 #endif /* FCT_API_TRACE */
2957 
2958 		MODSYM(fct_queue_cmd_for_termination) (fct_cmd,
2959 		    FCT_ABTS_RECEIVED);
2960 
2961 		goto done;
2962 	}
2963 
2964 	switch (iocb->ULPCOMMAND) {
2965 
2966 	/*
2967 	 *  FCP Data completion
2968 	 */
2969 	case CMD_FCP_TSEND_CX:
2970 	case CMD_FCP_TSEND64_CX:
2971 	case CMD_FCP_TRECEIVE_CX:
2972 	case CMD_FCP_TRECEIVE64_CX:
2973 
2974 		if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) {
2975 			if (emlxs_fct_dbuf_dma_sync(hba, dbuf,
2976 			    DDI_DMA_SYNC_FORCPU)) {
2977 				goto emlxs_dma_error;
2978 			}
2979 		}
2980 
2981 		if ((cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) &&
2982 		    (iocb->ULPCT != 1)) {
2983 
2984 			dbuf->db_flags |= DB_STATUS_GOOD_SENT;
2985 
2986 			fct_task =
2987 			    (scsi_task_t *)fct_cmd->cmd_specific;
2988 			fct_task->task_scsi_status = 0;
2989 
2990 			(void) emlxs_fct_send_fcp_status(fct_cmd);
2991 			/* mutex_exit(&cmd_sbp->fct_mtx); */
2992 
2993 			break;
2994 
2995 		} else if ((cmd_sbp->fct_flags &
2996 		    EMLXS_FCT_SEND_STATUS) &&
2997 		    (iocb->ULPCT == 1)) {
2998 			/* Auto-resp has been sent out by firmware */
2999 			/* We can assume this is really a FC_TRSP_CX */
3000 
3001 			dbuf->db_flags |= DB_STATUS_GOOD_SENT;
3002 			fct_task =
3003 			    (scsi_task_t *)fct_cmd->cmd_specific;
3004 			fct_task->task_scsi_status = 0;
3005 
3006 			cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS;
3007 
3008 			goto auto_resp;
3009 		}
3010 
3011 		cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
3012 
3013 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
3014 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3015 
3016 #ifdef FCT_API_TRACE
3017 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3018 		    "fct_scsi_data_xfer_done:1 %p %p", fct_cmd, dbuf);
3019 #endif /* FCT_API_TRACE */
3020 
3021 		MODSYM(fct_scsi_data_xfer_done) (fct_cmd, dbuf, 0);
3022 
3023 		break;
3024 
3025 		/* FCP Status completion */
3026 	case CMD_FCP_TRSP_CX:
3027 	case CMD_FCP_TRSP64_CX:
3028 
3029 auto_resp:
3030 		/* Copy these before calling emlxs_fct_cmd_done */
3031 		fct_flags = cmd_sbp->fct_flags;
3032 		fct_buf = cmd_sbp->fct_buf;
3033 
3034 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3035 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3036 
3037 		TGTPORTSTAT.FctOutstandingIO--;
3038 
3039 		if (fct_flags & EMLXS_FCT_SEND_STATUS) {
3040 #ifdef FCT_API_TRACE
3041 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3042 			    "fct_scsi_data_xfer_done:2 %p %p outio %d",
3043 			    fct_cmd, fct_buf, TGTPORTSTAT.FctOutstandingIO);
3044 #endif /* FCT_API_TRACE */
3045 
3046 			MODSYM(fct_scsi_data_xfer_done) (fct_cmd,
3047 			    fct_buf, FCT_IOF_FCA_DONE);
3048 		} else {
3049 #ifdef FCT_API_TRACE
3050 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3051 			    "fct_send_response_done:1 %p: x%x outio %d",
3052 			    fct_cmd, fct_cmd->cmd_comp_status,
3053 			    TGTPORTSTAT.FctOutstandingIO);
3054 #endif /* FCT_API_TRACE */
3055 
3056 			MODSYM(fct_send_response_done) (fct_cmd,
3057 			    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3058 		}
3059 		break;
3060 
3061 	default:
3062 		emlxs_fct_cmd_release(port, fct_cmd, 0);
3063 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3064 
3065 		TGTPORTSTAT.FctStray++;
3066 		TGTPORTSTAT.FctCompleted--;
3067 
3068 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3069 		    "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND);
3070 
3071 		if (pkt) {
3072 			emlxs_pkt_complete(sbp, status,
3073 			    iocb->un.grsp.perr.statLocalError, 1);
3074 		}
3075 
3076 	}	/* switch(iocb->ULPCOMMAND) */
3077 
3078 
3079 done:
3080 	if (pkt) {
3081 		emlxs_pkt_free(pkt);
3082 	}
3083 
3084 	if (status == IOSTAT_SUCCESS) {
3085 		TGTPORTSTAT.FctCmplGood++;
3086 	} else {
3087 		TGTPORTSTAT.FctCmplError++;
3088 	}
3089 
3090 	return (0);
3091 
3092 } /* emlxs_fct_handle_fcp_event() */
3093 
3094 
3095 /* ARGSUSED */
3096 extern int
emlxs_fct_handle_abort(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)3097 emlxs_fct_handle_abort(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
3098 {
3099 	emlxs_port_t *port = &PPORT;
3100 	IOCB *iocb;
3101 	emlxs_buf_t *sbp;
3102 	fc_packet_t *pkt;
3103 
3104 	iocb = &iocbq->iocb;
3105 	sbp = (emlxs_buf_t *)iocbq->sbp;
3106 
3107 	TGTPORTSTAT.FctEvent++;
3108 
3109 	if (!sbp) {
3110 		/* completion with missing xmit command */
3111 		TGTPORTSTAT.FctStray++;
3112 
3113 		/* emlxs_stray_fcp_completion_msg */
3114 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3115 		    "ABORT event cmd=%x status=%x error=%x iotag=%d",
3116 		    iocb->ULPCOMMAND, iocb->ULPSTATUS,
3117 		    iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG);
3118 
3119 		return (1);
3120 	}
3121 
3122 	pkt = PRIV2PKT(sbp);
3123 
3124 #ifdef FCT_API_TRACE
3125 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3126 	    "fct_handle_abort: %p:%p xri=%d cmd=%x status=%x",
3127 	    sbp->fct_cmd, sbp,
3128 	    iocb->ULPCONTEXT, iocb->ULPCOMMAND, iocb->ULPSTATUS);
3129 #endif /* FCT_API_TRACE */
3130 
3131 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3132 		XRIobj_t	*xrip;
3133 
3134 		emlxs_sli4_free_xri(port, NULL, sbp->xrip, 1);
3135 		xrip = emlxs_sli4_find_xri(port, iocb->ULPCONTEXT);
3136 		if (!xrip || xrip->state == XRI_STATE_FREE) {
3137 			goto exit;
3138 		}
3139 
3140 		if ((hba->fc_table[xrip->iotag]) &&
3141 		    (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
3142 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
3143 			    "Cmd not aborted, retrying: xri=%d iotag=%d sbp=%p",
3144 			    xrip->XRI, xrip->iotag, hba->fc_table[xrip->iotag]);
3145 
3146 			/* Abort retry */
3147 			if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
3148 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg,
3149 				    "Abort retry failed xri=%x", xrip->XRI);
3150 			} else {
3151 				return (0);
3152 			}
3153 		}
3154 	}
3155 
3156 exit:
3157 	if (pkt) {
3158 		emlxs_pkt_free(pkt);
3159 	}
3160 	return (0);
3161 
3162 } /* emlxs_fct_handle_abort() */
3163 
3164 
3165 extern int
emlxs_fct_handle_unsol_els(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)3166 emlxs_fct_handle_unsol_els(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3167     MATCHMAP *mp, uint32_t size)
3168 {
3169 	emlxs_hba_t *hba = HBA;
3170 	IOCB *iocb;
3171 	uint32_t cmd_code;
3172 	fct_cmd_t *fct_cmd;
3173 	fct_els_t *els;
3174 	uint32_t sid;
3175 	uint32_t padding;
3176 	uint8_t *bp;
3177 	emlxs_buf_t *cmd_sbp;
3178 	uint32_t rval;
3179 
3180 	HBASTATS.ElsCmdReceived++;
3181 
3182 	bp = mp->virt;
3183 	cmd_code = (*(uint32_t *)bp) & ELS_CMD_MASK;
3184 	iocb = &iocbq->iocb;
3185 	sid = iocb->un.elsreq.remoteID;
3186 
3187 	if (!port->fct_port) {
3188 		if (!(hba->flag & FC_ONLINE_MODE)) {
3189 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3190 			    "%s: sid=%x. Adapter offline. Dropping...",
3191 			    emlxs_elscmd_xlate(cmd_code), sid);
3192 			goto done;
3193 		}
3194 
3195 		switch (cmd_code) {
3196 		case ELS_CMD_LOGO:
3197 		case ELS_CMD_PRLO:
3198 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3199 			    "%s: sid=%x. Target unbound. Accepting...",
3200 			    emlxs_elscmd_xlate(cmd_code), sid);
3201 			(void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC,
3202 			    ELS_CMD_LOGO, 0, 0);
3203 			break;
3204 		default:
3205 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3206 			    "%s: sid=%x. Target unbound. Rejecting...",
3207 			    emlxs_elscmd_xlate(cmd_code), sid);
3208 			(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT,
3209 			    cmd_code, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
3210 			break;
3211 		}
3212 		goto done;
3213 	}
3214 
3215 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3216 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3217 		    "%s: sid=%x. Target offline. Rejecting...",
3218 		    emlxs_elscmd_xlate(cmd_code), sid);
3219 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3220 		    LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE);
3221 
3222 		goto done;
3223 	}
3224 
3225 #ifdef FCT_API_TRACE
3226 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3227 	    "%s: sid=%x cnt=%d. Target rcv. ",
3228 	    emlxs_elscmd_xlate(cmd_code), sid, size);
3229 #endif /* FCT_API_TRACE */
3230 
3231 	/* Process the request */
3232 	switch (cmd_code) {
3233 	case ELS_CMD_FLOGI:
3234 		rval = emlxs_fct_process_unsol_flogi(port, cp, iocbq, mp, size);
3235 
3236 		if (!rval) {
3237 			ELS_PKT *els_pkt = (ELS_PKT *)bp;
3238 			fct_flogi_xchg_t fx;
3239 
3240 			bzero((uint8_t *)&fx, sizeof (fct_flogi_xchg_t));
3241 
3242 			/* Save the FLOGI exchange information */
3243 			fx.rsvd2 = iocb->ULPCONTEXT;
3244 			bcopy((caddr_t)&els_pkt->un.logi.nodeName,
3245 			    (caddr_t)fx.fx_nwwn, 8);
3246 			bcopy((caddr_t)&els_pkt->un.logi.portName,
3247 			    (caddr_t)fx.fx_pwwn, 8);
3248 			fx.fx_sid = sid;
3249 			fx.fx_did = iocb->un.elsreq.myID;
3250 			fx.fx_fport = els_pkt->un.logi.cmn.fPort;
3251 			fx.fx_op = ELS_OP_FLOGI;
3252 
3253 			emlxs_fct_handle_unsol_flogi(port, &fx, 1);
3254 		}
3255 
3256 		goto done;
3257 
3258 	case ELS_CMD_PLOGI:
3259 		rval =
3260 		    emlxs_fct_process_unsol_plogi(port, cp, iocbq, mp, size);
3261 		break;
3262 
3263 	default:
3264 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3265 		    "%s: sid=0x%x", emlxs_elscmd_xlate(cmd_code), sid);
3266 		rval = 0;
3267 		break;
3268 	}
3269 
3270 	if (rval) {
3271 		goto done;
3272 	}
3273 
3274 	padding = (8 - (size & 7)) & 7;
3275 
3276 	fct_cmd = (fct_cmd_t *)MODSYM(fct_alloc) (FCT_STRUCT_CMD_RCVD_ELS,
3277 	    (size + padding + GET_STRUCT_SIZE(emlxs_buf_t)),
3278 	    AF_FORCE_NOSLEEP);
3279 
3280 #ifdef FCT_API_TRACE
3281 	{
3282 		uint32_t *ptr = (uint32_t *)bp;
3283 
3284 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3285 		    "fct_alloc %p: ELS rcvd: rxid=%x payload: x%x x%x",
3286 		    fct_cmd, iocb->ULPCONTEXT, *ptr, *(ptr + 1));
3287 	}
3288 #endif /* FCT_API_TRACE */
3289 
3290 	if (fct_cmd == NULL) {
3291 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3292 		    "%s: sid=%x. Out of memory. Rejecting...",
3293 		    emlxs_elscmd_xlate(cmd_code), sid);
3294 
3295 		(void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code,
3296 		    LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE);
3297 		goto done;
3298 	}
3299 
3300 	/* Initialize fct_cmd */
3301 	fct_cmd->cmd_oxid = (cmd_code >> ELS_CMD_SHIFT) & 0xff;
3302 	fct_cmd->cmd_rxid = iocb->ULPCONTEXT;
3303 	fct_cmd->cmd_rportid = sid;
3304 	fct_cmd->cmd_lportid = port->did;
3305 	fct_cmd->cmd_rp_handle = FCT_HANDLE_NONE;
3306 	fct_cmd->cmd_port = port->fct_port;
3307 
3308 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_ELS_CMD_RECEIVED);
3309 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3310 
3311 	/* Initialize cmd_sbp */
3312 	cmd_sbp->channel = cp;
3313 	cmd_sbp->class = iocb->ULPCLASS;
3314 	cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD;
3315 	cmd_sbp->fct_flags |= EMLXS_FCT_PLOGI_RECEIVED;
3316 
3317 	bcopy((uint8_t *)iocb, (uint8_t *)&cmd_sbp->iocbq,
3318 	    sizeof (emlxs_iocb_t));
3319 
3320 	els = (fct_els_t *)fct_cmd->cmd_specific;
3321 	els->els_req_size = (uint16_t)size;
3322 	els->els_req_payload =
3323 	    GET_BYTE_OFFSET(fct_cmd->cmd_fca_private,
3324 	    GET_STRUCT_SIZE(emlxs_buf_t));
3325 	bcopy(bp, els->els_req_payload, size);
3326 
3327 
3328 	/* Check if Offline */
3329 	if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
3330 
3331 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
3332 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3333 
3334 #ifdef FCT_API_TRACE
3335 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3336 		    "fct_post_rcvd_cmd:4 %p: portid x%x", fct_cmd,
3337 		    fct_cmd->cmd_lportid);
3338 #endif /* FCT_API_TRACE */
3339 
3340 		MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
3341 
3342 		goto done;
3343 	}
3344 
3345 	/* Online */
3346 
3347 	/* Check if Link up is acked */
3348 	if (!(port->fct_flags & FCT_STATE_LINK_UP_ACKED)) {
3349 		goto defer;
3350 	}
3351 
3352 	if ((cmd_code != ELS_CMD_FLOGI) &&
3353 	    !(port->fct_flags & FCT_STATE_FLOGI_CMPL)) {
3354 		goto defer;
3355 	}
3356 
3357 	/* Post it to COMSTAR */
3358 	emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
3359 	/* mutex_exit(&cmd_sbp->fct_mtx); */
3360 
3361 #ifdef FCT_API_TRACE
3362 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3363 	    "fct_post_rcvd_cmd:1 %p: portid x%x", fct_cmd,
3364 	    fct_cmd->cmd_lportid);
3365 #endif /* FCT_API_TRACE */
3366 
3367 	MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0);
3368 
3369 	goto done;
3370 
3371 defer:
3372 	/* Defer processing of fct_cmd till later (after link up ack). */
3373 
3374 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3375 	    "%s: sid=%x. Defer Processing x%x.",
3376 	    emlxs_elscmd_xlate(cmd_code), sid, port->fct_flags);
3377 
3378 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_CMD_WAITQ);
3379 	/* mutex_exit(&cmd_sbp->fct_mtx); */
3380 
3381 	/* Add cmd_sbp to queue tail */
3382 	mutex_enter(&EMLXS_PORT_LOCK);
3383 
3384 	if (port->fct_wait_tail) {
3385 		port->fct_wait_tail->next = cmd_sbp;
3386 	}
3387 	port->fct_wait_tail = cmd_sbp;
3388 
3389 	if (!port->fct_wait_head) {
3390 		port->fct_wait_head = cmd_sbp;
3391 	}
3392 
3393 	mutex_exit(&EMLXS_PORT_LOCK);
3394 
3395 done:
3396 
3397 	return (0);
3398 
3399 } /* emlxs_fct_handle_unsol_els() */
3400 
3401 
3402 /* ARGSUSED */
3403 static uint32_t
emlxs_fct_process_unsol_flogi(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)3404 emlxs_fct_process_unsol_flogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3405     MATCHMAP *mp, uint32_t size)
3406 {
3407 	IOCB *iocb;
3408 	char buffer[64];
3409 
3410 	buffer[0] = 0;
3411 
3412 	iocb = &iocbq->iocb;
3413 
3414 	/* Perform processing of FLOGI payload */
3415 	if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer,
3416 	    sizeof (buffer))) {
3417 		return (1);
3418 	}
3419 
3420 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3421 	    "FLOGI: sid=0x%x xid=%x %s",
3422 	    iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer);
3423 
3424 	return (0);
3425 
3426 } /* emlxs_fct_process_unsol_flogi() */
3427 
3428 
3429 /* ARGSUSED */
3430 static uint32_t
emlxs_fct_process_unsol_plogi(emlxs_port_t * port,CHANNEL * cp,IOCBQ * iocbq,MATCHMAP * mp,uint32_t size)3431 emlxs_fct_process_unsol_plogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
3432     MATCHMAP *mp, uint32_t size)
3433 {
3434 	IOCB *iocb;
3435 	char buffer[64];
3436 
3437 	buffer[0] = 0;
3438 
3439 	iocb = &iocbq->iocb;
3440 
3441 	/* Perform processing of PLOGI payload */
3442 	if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer,
3443 	    sizeof (buffer))) {
3444 		return (1);
3445 	}
3446 
3447 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg,
3448 	    "PLOGI: sid=0x%x xid=%x %s",
3449 	    iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer);
3450 
3451 	return (0);
3452 
3453 } /* emlxs_fct_process_unsol_plogi() */
3454 
3455 
3456 /* ARGSUSED */
3457 static emlxs_buf_t *
emlxs_fct_pkt_init(emlxs_port_t * port,fct_cmd_t * fct_cmd,fc_packet_t * pkt)3458 emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd,
3459     fc_packet_t *pkt)
3460 {
3461 	emlxs_buf_t *cmd_sbp;
3462 	emlxs_buf_t *sbp;
3463 
3464 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3465 
3466 	sbp = PKT2PRIV(pkt);
3467 	sbp->fct_cmd = cmd_sbp->fct_cmd;
3468 	sbp->node = cmd_sbp->node;
3469 	sbp->channel = cmd_sbp->channel;
3470 	sbp->did = cmd_sbp->did;
3471 	sbp->lun = cmd_sbp->lun;
3472 	sbp->class = cmd_sbp->class;
3473 	sbp->fct_type = cmd_sbp->fct_type;
3474 	sbp->fct_state = cmd_sbp->fct_state;
3475 	sbp->xrip = cmd_sbp->xrip;
3476 	sbp->iotag = cmd_sbp->iotag;
3477 
3478 	return (sbp);
3479 
3480 } /* emlxs_fct_pkt_init() */
3481 
3482 
3483 /* Mutex will be acquired */
3484 static emlxs_buf_t *
emlxs_fct_cmd_init(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)3485 emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
3486 {
3487 	emlxs_hba_t *hba = HBA;
3488 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3489 
3490 	bzero((void *)cmd_sbp, sizeof (emlxs_buf_t));
3491 	mutex_init(&cmd_sbp->fct_mtx, NULL, MUTEX_DRIVER,
3492 	    DDI_INTR_PRI(hba->intr_arg));
3493 	mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER,
3494 	    DDI_INTR_PRI(hba->intr_arg));
3495 
3496 	mutex_enter(&cmd_sbp->fct_mtx);
3497 	cmd_sbp->pkt_flags = PACKET_VALID;
3498 	cmd_sbp->port = port;
3499 	cmd_sbp->fct_cmd = fct_cmd;
3500 	cmd_sbp->node = (fct_cmd->cmd_rp) ?
3501 	    *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private : NULL;
3502 	cmd_sbp->iocbq.sbp = cmd_sbp;
3503 	cmd_sbp->iocbq.port = port;
3504 	cmd_sbp->did = fct_cmd->cmd_rportid;
3505 
3506 	/* Flags fct_cmd as inuse */
3507 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
3508 		fct_cmd->cmd_oxid = 0xffff;
3509 		fct_cmd->cmd_rxid = 0xffff;
3510 	}
3511 
3512 	if (fct_state) {
3513 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3514 	}
3515 
3516 	return (cmd_sbp);
3517 
3518 } /* emlxs_fct_cmd_init() */
3519 
3520 
3521 /* Called after receiving fct_cmd from COMSTAR */
3522 static fct_status_t
emlxs_fct_cmd_accept(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)3523 emlxs_fct_cmd_accept(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
3524 {
3525 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3526 
3527 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
3528 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3529 		    "fct_cmd_accept: "
3530 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
3531 		    fct_cmd, fct_state);
3532 
3533 		return (FCT_NOT_FOUND);
3534 	}
3535 
3536 	mutex_enter(&cmd_sbp->fct_mtx);
3537 
3538 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
3539 		mutex_exit(&cmd_sbp->fct_mtx);
3540 
3541 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3542 		    "fct_cmd_accept:2 "
3543 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
3544 		    fct_cmd, fct_state);
3545 
3546 		return (FCT_NOT_FOUND);
3547 	}
3548 
3549 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
3550 
3551 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3552 		    "fct_cmd_accept: "
3553 		    "Aborted fct_cmd found! fct_cmd=%p state=%x",
3554 		    fct_cmd, fct_state);
3555 
3556 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE);
3557 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3558 
3559 		MODSYM(fct_cmd_fca_aborted) (fct_cmd,
3560 		    FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
3561 
3562 		return (FCT_NOT_FOUND);
3563 	}
3564 
3565 	mutex_enter(&cmd_sbp->mtx);
3566 	if (!(cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
3567 		mutex_exit(&cmd_sbp->mtx);
3568 		mutex_exit(&cmd_sbp->fct_mtx);
3569 
3570 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3571 		    "fct_cmd_accept: "
3572 		    "Busy fct_cmd found! fct_cmd=%p state=%x",
3573 		    fct_cmd, fct_state);
3574 
3575 		return (FCT_BUSY);
3576 	}
3577 	cmd_sbp->pkt_flags &= ~PACKET_ULP_OWNED;
3578 	mutex_exit(&cmd_sbp->mtx);
3579 
3580 	if (fct_state) {
3581 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3582 	}
3583 
3584 	return (FCT_SUCCESS);
3585 
3586 } /* emlxs_fct_cmd_accept() */
3587 
3588 
3589 /* Called after receiving fct_cmd from driver */
3590 static fct_status_t
emlxs_fct_cmd_acquire(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)3591 emlxs_fct_cmd_acquire(emlxs_port_t *port, fct_cmd_t *fct_cmd,
3592     uint16_t fct_state)
3593 {
3594 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3595 
3596 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
3597 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3598 		    "fct_cmd_acquire: "
3599 		    "Bad fct_cmd found! fct_cmd=%p state=%x",
3600 		    fct_cmd, fct_state);
3601 
3602 		return (FCT_NOT_FOUND);
3603 	}
3604 
3605 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
3606 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3607 		    "fct_cmd_acquire: "
3608 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
3609 		    fct_cmd, fct_state);
3610 
3611 		return (FCT_NOT_FOUND);
3612 	}
3613 
3614 	if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
3615 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3616 		    "fct_cmd_acquire: "
3617 		    "Returned fct_cmd found! fct_cmd=%p state=%x",
3618 		    fct_cmd, fct_state);
3619 
3620 		return (FCT_NOT_FOUND);
3621 	}
3622 
3623 	mutex_enter(&cmd_sbp->fct_mtx);
3624 
3625 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
3626 		mutex_exit(&cmd_sbp->fct_mtx);
3627 
3628 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3629 		    "fct_cmd_acquire:2 "
3630 		    "Bad fct_cmd found! fct_cmd=%p state=%x",
3631 		    fct_cmd, fct_state);
3632 
3633 		return (FCT_NOT_FOUND);
3634 	}
3635 
3636 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
3637 		mutex_exit(&cmd_sbp->fct_mtx);
3638 
3639 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3640 		    "fct_cmd_acquire:2 "
3641 		    "Invalid fct_cmd found! fct_cmd=%p state=%x",
3642 		    fct_cmd, fct_state);
3643 
3644 		return (FCT_NOT_FOUND);
3645 	}
3646 
3647 	if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) {
3648 		mutex_exit(&cmd_sbp->fct_mtx);
3649 
3650 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3651 		    "fct_cmd_acquire:2 "
3652 		    "Returned fct_cmd found! fct_cmd=%p state=%x",
3653 		    fct_cmd, fct_state);
3654 
3655 		return (FCT_NOT_FOUND);
3656 	}
3657 
3658 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
3659 
3660 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3661 		    "fct_cmd_acquire: "
3662 		    "Aborting cmd. fct_cmd=%p state=%x",
3663 		    fct_cmd, fct_state);
3664 
3665 		if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) {
3666 			TGTPORTSTAT.FctOutstandingIO--;
3667 		}
3668 
3669 		fct_cmd->cmd_comp_status = FCT_FAILURE;
3670 
3671 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE);
3672 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3673 
3674 		MODSYM(fct_cmd_fca_aborted) (fct_cmd,
3675 		    FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
3676 
3677 		return (FCT_NOT_FOUND);
3678 	}
3679 
3680 	if (fct_state) {
3681 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3682 	}
3683 
3684 	return (FCT_SUCCESS);
3685 
3686 } /* emlxs_fct_cmd_acquire() */
3687 
3688 
3689 /* cmd_sbp->fct_mtx must be held to enter */
3690 /* cmd_sbp->fct_mtx must be released before exiting */
3691 /* Called before transitionally sending fct_cmd to driver */
3692 /*ARGSUSED*/
3693 static void
emlxs_fct_cmd_release(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)3694 emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd,
3695     uint16_t fct_state)
3696 {
3697 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3698 
3699 	if (fct_state) {
3700 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3701 	}
3702 
3703 	mutex_exit(&cmd_sbp->fct_mtx);
3704 
3705 	return;
3706 
3707 } /* emlxs_fct_cmd_release() */
3708 
3709 
3710 /* cmd_sbp->fct_mtx must be held to enter */
3711 /* cmd_sbp->fct_mtx must be released before exiting */
3712 /* Called before posting fct_cmd back to COMSTAR */
3713 /*ARGSUSED*/
3714 static void
emlxs_fct_cmd_post(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)3715 emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd,
3716     uint16_t fct_state)
3717 {
3718 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3719 	fc_packet_t *pkt;
3720 
3721 	pkt = cmd_sbp->fct_pkt;
3722 	cmd_sbp->fct_pkt = NULL;
3723 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
3724 
3725 	mutex_enter(&cmd_sbp->mtx);
3726 	cmd_sbp->pkt_flags |= PACKET_ULP_OWNED;
3727 	mutex_exit(&cmd_sbp->mtx);
3728 
3729 	if (fct_state) {
3730 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3731 	}
3732 
3733 	mutex_exit(&cmd_sbp->fct_mtx);
3734 
3735 	if (pkt) {
3736 		emlxs_pkt_free(pkt);
3737 	}
3738 
3739 	return;
3740 
3741 } /* emlxs_fct_cmd_post() */
3742 
3743 
3744 /* cmd_sbp->fct_mtx must be held to enter */
3745 /* Called before completing fct_cmd back to COMSTAR */
3746 static void
emlxs_fct_cmd_done(emlxs_port_t * port,fct_cmd_t * fct_cmd,uint16_t fct_state)3747 emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state)
3748 {
3749 	emlxs_hba_t *hba = HBA;
3750 	emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3751 	fc_packet_t *pkt;
3752 
3753 	/* Flags fct_cmd is no longer used */
3754 	fct_cmd->cmd_oxid = 0;
3755 	fct_cmd->cmd_rxid = 0;
3756 
3757 	if (cmd_sbp->iotag != 0) {
3758 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3759 		    "Pkt still registered! channel=%p iotag=%d sbp=%p",
3760 		    cmd_sbp->channel, cmd_sbp->iotag, cmd_sbp);
3761 
3762 		if (cmd_sbp->channel) {
3763 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3764 				emlxs_sli4_free_xri(port, cmd_sbp,
3765 				    cmd_sbp->xrip, 1);
3766 			} else {
3767 				(void) emlxs_unregister_pkt(cmd_sbp->channel,
3768 				    cmd_sbp->iotag, 0);
3769 			}
3770 
3771 		}
3772 	}
3773 
3774 	pkt = cmd_sbp->fct_pkt;
3775 	cmd_sbp->fct_pkt = NULL;
3776 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
3777 
3778 	if (fct_state) {
3779 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state);
3780 	}
3781 
3782 	mutex_enter(&cmd_sbp->mtx);
3783 	cmd_sbp->pkt_flags |= PACKET_ULP_OWNED;
3784 	cmd_sbp->pkt_flags &= ~PACKET_VALID;
3785 	mutex_exit(&cmd_sbp->mtx);
3786 	mutex_exit(&cmd_sbp->fct_mtx);
3787 
3788 
3789 	mutex_destroy(&cmd_sbp->fct_mtx);
3790 	mutex_destroy(&cmd_sbp->mtx);
3791 
3792 	if (pkt) {
3793 		emlxs_pkt_free(pkt);
3794 	}
3795 
3796 	return;
3797 
3798 } /* emlxs_fct_cmd_done() */
3799 
3800 
3801 static void
emlxs_fct_pkt_comp(fc_packet_t * pkt)3802 emlxs_fct_pkt_comp(fc_packet_t *pkt)
3803 {
3804 	emlxs_port_t *port;
3805 #ifdef FMA_SUPPORT
3806 	emlxs_hba_t *hba;
3807 #endif	/* FMA_SUPPORT */
3808 	emlxs_buf_t *sbp;
3809 	emlxs_buf_t *cmd_sbp;
3810 	fct_cmd_t *fct_cmd;
3811 	fct_els_t *fct_els;
3812 	fct_sol_ct_t *fct_ct;
3813 	fct_status_t rval;
3814 
3815 	sbp = PKT2PRIV(pkt);
3816 	port = sbp->port;
3817 #ifdef FMA_SUPPORT
3818 	hba = HBA;
3819 #endif	/* FMA_SUPPORT */
3820 	fct_cmd = sbp->fct_cmd;
3821 
3822 	rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_PKT_COMPLETE);
3823 	if (rval) {
3824 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3825 		    "fct_pkt_comp: "
3826 		    "Unable to reacquire fct_cmd.");
3827 		return;
3828 	}
3829 	/* mutex_enter(&cmd_sbp->fct_mtx); */
3830 
3831 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
3832 	cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP;
3833 	cmd_sbp->fct_pkt = NULL;
3834 
3835 	switch (fct_cmd->cmd_type) {
3836 	case FCT_CMD_FCP_XCHG:
3837 		if ((pkt->pkt_reason == FC_REASON_ABORTED) ||
3838 		    (pkt->pkt_reason == FC_REASON_XCHG_DROPPED) ||
3839 		    (pkt->pkt_reason == FC_REASON_OFFLINE)) {
3840 			/*
3841 			 * The error indicates this IO should be terminated
3842 			 * immediately.
3843 			 */
3844 			cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS;
3845 
3846 			emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
3847 			/* mutex_exit(&cmd_sbp->fct_mtx); */
3848 
3849 #ifdef FCT_API_TRACE
3850 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3851 			    "fct_queue_cmd_for_termination:2 %p:%p x%x",
3852 			    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status);
3853 #endif /* FCT_API_TRACE */
3854 
3855 			MODSYM(fct_queue_cmd_for_termination) (fct_cmd,
3856 			    FCT_ABTS_RECEIVED);
3857 
3858 			break;
3859 		}
3860 
3861 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3862 		    EMLXS_FCT_PKT_FCPRSP_COMPLETE);
3863 
3864 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3865 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3866 
3867 #ifdef FCT_API_TRACE
3868 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3869 		    "fct_send_response_done:2 %p:%p x%x outio %d",
3870 		    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status,
3871 		    TGTPORTSTAT.FctOutstandingIO);
3872 #else
3873 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3874 		    "fct_pkt_comp: fct_send_response_done. dbuf=%p",
3875 		    sbp->fct_buf);
3876 #endif /* FCT_API_TRACE */
3877 
3878 		TGTPORTSTAT.FctOutstandingIO--;
3879 
3880 		MODSYM(fct_send_response_done) (fct_cmd,
3881 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3882 
3883 		break;
3884 
3885 	case FCT_CMD_RCVD_ELS:
3886 
3887 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3888 		    EMLXS_FCT_PKT_ELSRSP_COMPLETE);
3889 
3890 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3891 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3892 
3893 #ifdef FCT_API_TRACE
3894 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3895 		    "fct_send_response_done:3 %p:%p x%x",
3896 		    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status);
3897 #endif /* FCT_API_TRACE */
3898 
3899 		MODSYM(fct_send_response_done) (fct_cmd,
3900 		    fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE);
3901 
3902 		break;
3903 
3904 	case FCT_CMD_SOL_ELS:
3905 
3906 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3907 		    EMLXS_FCT_PKT_ELSCMD_COMPLETE);
3908 
3909 		fct_els = (fct_els_t *)fct_cmd->cmd_specific;
3910 
3911 		if (fct_els->els_resp_payload) {
3912 			EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0,
3913 			    pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL);
3914 
3915 			bcopy((uint8_t *)pkt->pkt_resp,
3916 			    (uint8_t *)fct_els->els_resp_payload,
3917 			    fct_els->els_resp_size);
3918 		}
3919 
3920 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3921 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3922 
3923 #ifdef FCT_API_TRACE
3924 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3925 		    "fct_send_cmd_done:1 %p:%p x%x",
3926 		    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status);
3927 #endif /* FCT_API_TRACE */
3928 
3929 #ifdef FMA_SUPPORT
3930 		if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
3931 		    != DDI_FM_OK) {
3932 			EMLXS_MSGF(EMLXS_CONTEXT,
3933 			    &emlxs_invalid_dma_handle_msg,
3934 			    "fct_pkt_comp: hdl=%p",
3935 			    pkt->pkt_resp_dma);
3936 			MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE,
3937 			    FCT_IOF_FCA_DONE);
3938 
3939 			break;
3940 		}
3941 #endif /* FMA_SUPPORT */
3942 
3943 		MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS,
3944 		    FCT_IOF_FCA_DONE);
3945 
3946 		break;
3947 
3948 	case FCT_CMD_SOL_CT:
3949 
3950 		EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
3951 		    EMLXS_FCT_PKT_CTCMD_COMPLETE);
3952 
3953 		fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
3954 
3955 		if (fct_ct->ct_resp_payload) {
3956 			EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0,
3957 			    pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL);
3958 
3959 			bcopy((uint8_t *)pkt->pkt_resp,
3960 			    (uint8_t *)fct_ct->ct_resp_payload,
3961 			    fct_ct->ct_resp_size);
3962 		}
3963 
3964 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3965 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3966 
3967 #ifdef FCT_API_TRACE
3968 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
3969 		    "fct_send_cmd_done:2 %p:%p x%x",
3970 		    fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status);
3971 #endif /* FCT_API_TRACE */
3972 
3973 #ifdef FMA_SUPPORT
3974 		if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma)
3975 		    != DDI_FM_OK) {
3976 			EMLXS_MSGF(EMLXS_CONTEXT,
3977 			    &emlxs_invalid_dma_handle_msg,
3978 			    "fct_pkt_comp: hdl=%p",
3979 			    pkt->pkt_resp_dma);
3980 			MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE,
3981 			    FCT_IOF_FCA_DONE);
3982 
3983 			break;
3984 		}
3985 #endif /* FMA_SUPPORT */
3986 		MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS,
3987 		    FCT_IOF_FCA_DONE);
3988 
3989 		break;
3990 
3991 	default:
3992 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3993 		    "fct_pkt_comp: Invalid cmd type found. type=%x",
3994 		    fct_cmd->cmd_type);
3995 
3996 		emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE);
3997 		/* mutex_exit(&cmd_sbp->fct_mtx); */
3998 
3999 		break;
4000 	}
4001 
4002 	emlxs_pkt_free(pkt);
4003 	return;
4004 
4005 } /* emlxs_fct_pkt_comp() */
4006 
4007 
4008 static void
emlxs_fct_abort_pkt_comp(fc_packet_t * pkt)4009 emlxs_fct_abort_pkt_comp(fc_packet_t *pkt)
4010 {
4011 #ifdef FCT_API_TRACE
4012 	emlxs_buf_t *sbp;
4013 	IOCBQ *iocbq;
4014 	IOCB *iocb;
4015 	emlxs_port_t *port;
4016 
4017 	sbp = PKT2PRIV(pkt);
4018 	port = sbp->port;
4019 	iocbq = &sbp->iocbq;
4020 	iocb = &iocbq->iocb;
4021 
4022 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4023 	    "fct_abort_pkt_comp: %p: xri=%d cmd=%x status=%x",
4024 	    sbp->fct_cmd, sbp,
4025 	    iocb->ULPCONTEXT, iocb->ULPCOMMAND, iocb->ULPSTATUS);
4026 #endif /* FCT_API_TRACE */
4027 
4028 	emlxs_pkt_free(pkt);
4029 	return;
4030 
4031 } /* emlxs_fct_abort_pkt_comp() */
4032 
4033 
4034 /* COMSTAR ENTER POINT (INDIRECT) */
4035 static fct_status_t
emlxs_fct_send_els_cmd(fct_cmd_t * fct_cmd)4036 emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd)
4037 {
4038 	emlxs_port_t *port =
4039 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4040 	emlxs_hba_t *hba = HBA;
4041 	uint32_t did;
4042 	uint32_t sid;
4043 	fct_els_t *fct_els;
4044 	fc_packet_t *pkt;
4045 	emlxs_buf_t *cmd_sbp;
4046 	fct_status_t rval;
4047 
4048 	did = fct_cmd->cmd_rportid;
4049 	sid = fct_cmd->cmd_lportid;
4050 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
4051 
4052 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_req_size,
4053 	    fct_els->els_resp_size, 0, KM_NOSLEEP))) {
4054 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4055 		    "fct_send_els_cmd: Unable to allocate packet.");
4056 
4057 		return (FCT_BUSY);
4058 	}
4059 
4060 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_ELS_REQ);
4061 	/* mutex_enter(&cmd_sbp->fct_mtx); */
4062 
4063 	cmd_sbp->channel = &hba->chan[hba->channel_els];
4064 	cmd_sbp->fct_type = EMLXS_FCT_ELS_REQ;
4065 
4066 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4067 	cmd_sbp->fct_pkt = pkt;
4068 
4069 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
4070 	pkt->pkt_timeout =
4071 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4072 	pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout;
4073 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4074 
4075 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4076 	    "fct_send_els_cmd: pkt_timeout=%d ratov=%d",
4077 	    pkt->pkt_timeout, hba->fc_ratov);
4078 
4079 	/* Build the fc header */
4080 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4081 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
4082 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid);
4083 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
4084 	pkt->pkt_cmd_fhdr.f_ctl =
4085 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
4086 	pkt->pkt_cmd_fhdr.seq_id = 0;
4087 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4088 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4089 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
4090 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
4091 	pkt->pkt_cmd_fhdr.ro = 0;
4092 
4093 	/* Copy the cmd payload */
4094 	bcopy((uint8_t *)fct_els->els_req_payload, (uint8_t *)pkt->pkt_cmd,
4095 	    fct_els->els_req_size);
4096 
4097 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
4098 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING);
4099 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4100 
4101 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4102 
4103 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4104 		    "fct_send_els_cmd: Unable to send packet.");
4105 
4106 		/* Reacquire ownership of the fct_cmd */
4107 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
4108 		if (rval) {
4109 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4110 			    "fct_send_els_cmd: "
4111 			    "Unable to reacquire fct_cmd.");
4112 			return (rval);
4113 		}
4114 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4115 
4116 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
4117 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4118 
4119 		return (FCT_BUSY);
4120 	}
4121 
4122 	return (FCT_SUCCESS);
4123 
4124 } /* emlxs_fct_send_els_cmd() */
4125 
4126 
4127 /* cmd_sbp->fct_mtx must be held to enter */
4128 /* cmd_sbp->fct_mtx must be released before exiting */
4129 static fct_status_t
emlxs_fct_send_els_rsp(fct_cmd_t * fct_cmd)4130 emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd)
4131 {
4132 	emlxs_port_t *port =
4133 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4134 	emlxs_hba_t *hba = HBA;
4135 	uint32_t did;
4136 	uint32_t sid;
4137 	fct_els_t *fct_els;
4138 	fc_packet_t *pkt;
4139 	emlxs_buf_t *cmd_sbp;
4140 	fct_status_t rval;
4141 
4142 	fct_els = (fct_els_t *)fct_cmd->cmd_specific;
4143 	did = fct_cmd->cmd_rportid;
4144 	sid = fct_cmd->cmd_lportid;
4145 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4146 
4147 	if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_resp_size, 0, 0,
4148 	    KM_NOSLEEP))) {
4149 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4150 		    "fct_send_els_rsp: Unable to allocate packet.");
4151 
4152 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
4153 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4154 
4155 		return (FCT_FAILURE);
4156 	}
4157 
4158 	EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_ELS_RSP);
4159 
4160 	cmd_sbp->fct_type = EMLXS_FCT_ELS_RSP;
4161 
4162 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4163 	cmd_sbp->fct_pkt = pkt;
4164 
4165 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4166 	pkt->pkt_timeout =
4167 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4168 	pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout;
4169 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4170 
4171 	/* Build the fc header */
4172 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4173 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP;
4174 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid);
4175 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
4176 	pkt->pkt_cmd_fhdr.f_ctl =
4177 	    F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
4178 	pkt->pkt_cmd_fhdr.seq_id = 0;
4179 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4180 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4181 	pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
4182 	pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
4183 	pkt->pkt_cmd_fhdr.ro = 0;
4184 
4185 	/* Copy the resp payload to pkt_cmd buffer */
4186 	bcopy((uint8_t *)fct_els->els_resp_payload, (uint8_t *)pkt->pkt_cmd,
4187 	    fct_els->els_resp_size);
4188 
4189 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
4190 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_RSP_PENDING);
4191 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4192 
4193 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4194 
4195 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4196 		    "fct_send_els_rsp: Unable to send packet.");
4197 
4198 		/* Reacquire ownership of the fct_cmd */
4199 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
4200 		if (rval) {
4201 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4202 			    "fct_send_els_rsp: "
4203 			    "Unable to reacquire fct_cmd.");
4204 			return (rval);
4205 		}
4206 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4207 
4208 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED);
4209 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4210 
4211 		return (FCT_FAILURE);
4212 	}
4213 
4214 	return (FCT_SUCCESS);
4215 
4216 } /* emlxs_fct_send_els_rsp() */
4217 
4218 
4219 /* COMSTAR ENTER POINT (INDIRECT) */
4220 static fct_status_t
emlxs_fct_send_ct_cmd(fct_cmd_t * fct_cmd)4221 emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd)
4222 {
4223 	emlxs_port_t *port =
4224 	    (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private;
4225 	emlxs_hba_t *hba = HBA;
4226 	uint32_t did;
4227 	fct_sol_ct_t *fct_ct;
4228 	fc_packet_t *pkt;
4229 	emlxs_buf_t *cmd_sbp;
4230 	fct_status_t rval;
4231 
4232 	did = fct_cmd->cmd_rportid;
4233 	fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific;
4234 
4235 	if (!(pkt = emlxs_pkt_alloc(port, fct_ct->ct_req_size,
4236 	    fct_ct->ct_resp_size, 0, KM_NOSLEEP))) {
4237 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4238 		    "fct_send_ct_cmd: Unable to allocate packet.");
4239 		return (FCT_BUSY);
4240 	}
4241 
4242 	cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_CT_REQ);
4243 	/* mutex_enter(&cmd_sbp->fct_mtx); */
4244 
4245 	cmd_sbp->channel = &hba->chan[hba->channel_ct];
4246 	cmd_sbp->fct_type = EMLXS_FCT_CT_REQ;
4247 
4248 	(void) emlxs_fct_pkt_init(port, fct_cmd, pkt);
4249 	cmd_sbp->fct_pkt = pkt;
4250 
4251 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
4252 	pkt->pkt_timeout =
4253 	    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4254 	pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout;
4255 	pkt->pkt_comp = emlxs_fct_pkt_comp;
4256 
4257 	/* Build the fc header */
4258 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
4259 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
4260 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4261 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
4262 	pkt->pkt_cmd_fhdr.f_ctl =
4263 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
4264 	pkt->pkt_cmd_fhdr.seq_id = 0;
4265 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4266 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4267 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
4268 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
4269 	pkt->pkt_cmd_fhdr.ro = 0;
4270 
4271 	/* Copy the cmd payload */
4272 	bcopy((uint8_t *)fct_ct->ct_req_payload, (uint8_t *)pkt->pkt_cmd,
4273 	    fct_ct->ct_req_size);
4274 
4275 	cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP;
4276 	emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING);
4277 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4278 
4279 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4280 
4281 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4282 		    "fct_send_ct_cmd: Unable to send packet.");
4283 
4284 		/* Reacquire ownership of the fct_cmd */
4285 		rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0);
4286 		if (rval) {
4287 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4288 			    "fct_send_ct_cmd: "
4289 			    "Unable to reacquire fct_cmd.");
4290 
4291 			return (rval);
4292 		}
4293 		/* mutex_enter(&cmd_sbp->fct_mtx); */
4294 
4295 		emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED);
4296 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4297 
4298 		return (FCT_BUSY);
4299 	}
4300 
4301 	return (FCT_SUCCESS);
4302 
4303 } /* emlxs_fct_send_ct_cmd() */
4304 
4305 
4306 /* cmd_sbp->fct_mtx must be held to enter */
4307 static uint32_t
emlxs_fct_pkt_abort_txq(emlxs_port_t * port,emlxs_buf_t * cmd_sbp)4308 emlxs_fct_pkt_abort_txq(emlxs_port_t *port, emlxs_buf_t *cmd_sbp)
4309 {
4310 	emlxs_hba_t *hba = HBA;
4311 	NODELIST *nlp;
4312 	fc_packet_t *pkt;
4313 	emlxs_buf_t *sbp;
4314 	emlxs_buf_t *iocb_sbp;
4315 	uint8_t channelno;
4316 	CHANNEL *cp;
4317 	IOCBQ *iocbq;
4318 	IOCBQ *next;
4319 	IOCBQ *prev;
4320 	uint32_t found;
4321 	uint32_t pkt_flags;
4322 
4323 	/* Check the transmit queue */
4324 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
4325 
4326 	/* The IOCB could point to a cmd_sbp (no packet) or a sbp (packet) */
4327 	pkt = cmd_sbp->fct_pkt;
4328 	if (pkt) {
4329 		sbp = PKT2PRIV(pkt);
4330 		if (sbp == NULL) {
4331 			goto done;
4332 		}
4333 		iocb_sbp = sbp;
4334 		iocbq = &sbp->iocbq;
4335 		pkt_flags = sbp->pkt_flags;
4336 	} else {
4337 		sbp = NULL;
4338 		iocb_sbp = cmd_sbp;
4339 		iocbq = &cmd_sbp->iocbq;
4340 		pkt_flags = cmd_sbp->pkt_flags;
4341 	}
4342 
4343 	nlp = (NODELIST *)cmd_sbp->node;
4344 	cp = (CHANNEL *)cmd_sbp->channel;
4345 	channelno = (cp) ? cp->channelno : 0;
4346 
4347 	if (pkt_flags & PACKET_IN_TXQ) {
4348 		/* Find it on the queue */
4349 		found = 0;
4350 		if (iocbq->flag & IOCB_PRIORITY) {
4351 			/* Search the priority queue */
4352 			prev = NULL;
4353 			next = (IOCBQ *)nlp->nlp_ptx[channelno].q_first;
4354 
4355 			while (next) {
4356 				if (next == iocbq) {
4357 					/* Remove it */
4358 					if (prev) {
4359 						prev->next = iocbq->next;
4360 					}
4361 
4362 					if (nlp->nlp_ptx[channelno].q_last ==
4363 					    (void *)iocbq) {
4364 						nlp->nlp_ptx[channelno].q_last =
4365 						    (void *)prev;
4366 					}
4367 
4368 					if (nlp->nlp_ptx[channelno].q_first ==
4369 					    (void *)iocbq) {
4370 						nlp->nlp_ptx[channelno].
4371 						    q_first =
4372 						    (void *)iocbq->next;
4373 					}
4374 
4375 					nlp->nlp_ptx[channelno].q_cnt--;
4376 					iocbq->next = NULL;
4377 					found = 1;
4378 					break;
4379 				}
4380 
4381 				prev = next;
4382 				next = next->next;
4383 			}
4384 		} else {
4385 			/* Search the normal queue */
4386 			prev = NULL;
4387 			next = (IOCBQ *)nlp->nlp_tx[channelno].q_first;
4388 
4389 			while (next) {
4390 				if (next == iocbq) {
4391 					/* Remove it */
4392 					if (prev) {
4393 						prev->next = iocbq->next;
4394 					}
4395 
4396 					if (nlp->nlp_tx[channelno].q_last ==
4397 					    (void *)iocbq) {
4398 						nlp->nlp_tx[channelno].q_last =
4399 						    (void *)prev;
4400 					}
4401 
4402 					if (nlp->nlp_tx[channelno].q_first ==
4403 					    (void *)iocbq) {
4404 						nlp->nlp_tx[channelno].q_first =
4405 						    (void *)iocbq->next;
4406 					}
4407 
4408 					nlp->nlp_tx[channelno].q_cnt--;
4409 					iocbq->next = NULL;
4410 					found = 1;
4411 					break;
4412 				}
4413 
4414 				prev = next;
4415 				next = (IOCBQ *)next->next;
4416 			}
4417 		}
4418 
4419 		if (!found) {
4420 			goto done;
4421 		}
4422 
4423 		/* Check if node still needs servicing */
4424 		if ((nlp->nlp_ptx[channelno].q_first) ||
4425 		    (nlp->nlp_tx[channelno].q_first &&
4426 		    !(nlp->nlp_flag[channelno] & NLP_CLOSED))) {
4427 
4428 			/*
4429 			 * If this is the base node, don't shift the pointers
4430 			 */
4431 			/* We want to drain the base node before moving on */
4432 			if (!nlp->nlp_base) {
4433 				/* Shift channel queue pointers to next node */
4434 				cp->nodeq.q_last = (void *)nlp;
4435 				cp->nodeq.q_first = nlp->nlp_next[channelno];
4436 			}
4437 		} else {
4438 			/* Remove node from channel queue */
4439 
4440 			/* If this is the last node on list */
4441 			if (cp->nodeq.q_last == (void *)nlp) {
4442 				cp->nodeq.q_last = NULL;
4443 				cp->nodeq.q_first = NULL;
4444 				cp->nodeq.q_cnt = 0;
4445 			} else {
4446 				/* Remove node from head */
4447 				cp->nodeq.q_first = nlp->nlp_next[channelno];
4448 				((NODELIST *)cp->nodeq.q_last)->
4449 				    nlp_next[channelno] = cp->nodeq.q_first;
4450 				cp->nodeq.q_cnt--;
4451 			}
4452 
4453 			/* Clear node */
4454 			nlp->nlp_next[channelno] = NULL;
4455 		}
4456 
4457 		/* The IOCB points to iocb_sbp (no packet) or a sbp (packet) */
4458 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4459 			emlxs_sli4_free_xri(port, iocb_sbp, iocb_sbp->xrip, 1);
4460 		} else {
4461 			(void) emlxs_unregister_pkt(cp, iocb_sbp->iotag, 0);
4462 		}
4463 
4464 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
4465 
4466 		if (pkt) {
4467 			emlxs_pkt_free(pkt);
4468 			cmd_sbp->fct_pkt = NULL;
4469 		}
4470 		return (1);
4471 	}
4472 done:
4473 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
4474 	return (0);
4475 
4476 } /* emlxs_fct_pkt_abort_txq() */
4477 
4478 
4479 /* COMSTAR ENTER POINT */
4480 /* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */
4481 /* FCT_SUCCESS indicates abort will occur asyncronously */
4482 static fct_status_t
emlxs_fct_abort(fct_local_port_t * fct_port,fct_cmd_t * fct_cmd,uint32_t flags)4483 emlxs_fct_abort(fct_local_port_t *fct_port, fct_cmd_t *fct_cmd,
4484     uint32_t flags)
4485 {
4486 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
4487 	emlxs_hba_t *hba = HBA;
4488 	emlxs_buf_t *cmd_sbp;
4489 	emlxs_buf_t *cmd_sbp2;
4490 	emlxs_buf_t *prev;
4491 	fc_packet_t *pkt;
4492 	emlxs_buf_t *sbp = NULL;
4493 	kmutex_t *fct_mtx;
4494 	uint32_t fct_state;
4495 
4496 	cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4497 	fct_mtx = &cmd_sbp->fct_mtx;
4498 
4499 top:
4500 
4501 	/* Sanity check */
4502 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
4503 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4504 		    "fct_abort: Bad fct_cmd=%p.", fct_cmd);
4505 
4506 		return (FCT_NOT_FOUND);
4507 	}
4508 
4509 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
4510 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4511 		    "fct_abort: Pkt invalid. cmd_sbp=%p",
4512 		    cmd_sbp);
4513 
4514 		return (FCT_NOT_FOUND);
4515 	}
4516 
4517 	if (mutex_tryenter(fct_mtx) == 0) {
4518 		/*
4519 		 * This code path handles a race condition if
4520 		 * an IO completes, in emlxs_fct_handle_fcp_event(),
4521 		 * and we get an abort at the same time.
4522 		 */
4523 		delay(drv_usectohz(100000));	/* 100 msec */
4524 		goto top;
4525 	}
4526 	/* At this point, we have entered the mutex */
4527 
4528 	/* Sanity check */
4529 	if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) {
4530 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4531 		    "fct_abort: Bad fct_cmd=%p.", fct_cmd);
4532 
4533 		mutex_exit(fct_mtx);
4534 		return (FCT_NOT_FOUND);
4535 	}
4536 
4537 	if (!(cmd_sbp->pkt_flags & PACKET_VALID)) {
4538 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4539 		    "fct_abort: Pkt invalid. cmd_sbp=%p",
4540 		    cmd_sbp);
4541 
4542 		mutex_exit(fct_mtx);
4543 		return (FCT_NOT_FOUND);
4544 	}
4545 
4546 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4547 	    "fct_abort: hbastate=%x. "
4548 	    "xid=%x,%x cmd_sbp=%p fctstate=%d flags=%x,%x,%x",
4549 	    hba->state, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp,
4550 	    cmd_sbp->fct_state, flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags);
4551 
4552 	if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) {
4553 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, 0);
4554 
4555 		/* If Abort is already in progress */
4556 		mutex_exit(fct_mtx);
4557 		return (FCT_SUCCESS);
4558 	}
4559 	cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_INP;
4560 
4561 	if (flags & FCT_IOF_FORCE_FCA_DONE) {
4562 		fct_cmd->cmd_handle = 0;
4563 	}
4564 
4565 	TGTPORTSTAT.FctAbortSent++;
4566 
4567 	switch (cmd_sbp->fct_state) {
4568 	/* These are currently owned by COMSTAR. */
4569 	/* They were last processed by emlxs_fct_cmd_post() */
4570 	/* We have NO exchange resources associated with this IO. */
4571 	case EMLXS_FCT_OWNED:
4572 		goto abort_done;
4573 
4574 	/* These are on the unsol waitQ in the driver */
4575 	case EMLXS_FCT_CMD_WAITQ:
4576 		/* Find and remove it */
4577 		mutex_enter(&EMLXS_PORT_LOCK);
4578 		cmd_sbp2 = port->fct_wait_head;
4579 		prev = NULL;
4580 		while (cmd_sbp2) {
4581 			if (cmd_sbp2 == cmd_sbp) {
4582 				/* Remove it */
4583 				if (prev) {
4584 					prev->next = cmd_sbp2->next;
4585 				}
4586 
4587 				if (port->fct_wait_head == cmd_sbp2) {
4588 					port->fct_wait_head = cmd_sbp2->next;
4589 				}
4590 
4591 				if (port->fct_wait_tail == cmd_sbp2) {
4592 					port->fct_wait_tail = prev;
4593 				}
4594 
4595 				cmd_sbp2->next = NULL;
4596 				break;
4597 			}
4598 			prev = cmd_sbp2;
4599 			cmd_sbp2 = cmd_sbp2->next;
4600 		}
4601 		mutex_exit(&EMLXS_PORT_LOCK);
4602 
4603 		/*FALLTHROUGH*/
4604 
4605 	/* These are currently owned by COMSTAR. */
4606 	/* They were last processed by emlxs_fct_cmd_post() */
4607 	/* We have residual exchange resources associated with this IO */
4608 	case EMLXS_FCT_CMD_POSTED:
4609 		switch (fct_cmd->cmd_type) {
4610 		case FCT_CMD_FCP_XCHG: /* Unsol */
4611 			TGTPORTSTAT.FctOutstandingIO--;
4612 			emlxs_abort_fct_exchange(hba, port, fct_cmd->cmd_rxid);
4613 			break;
4614 
4615 		case FCT_CMD_RCVD_ELS: /* Unsol */
4616 			emlxs_abort_els_exchange(hba, port, fct_cmd->cmd_rxid);
4617 			break;
4618 		}
4619 
4620 		goto abort_done;
4621 
4622 	/* These are active in the driver */
4623 	/* They were last processed by emlxs_fct_cmd_release() */
4624 	case EMLXS_FCT_RSP_PENDING:
4625 	case EMLXS_FCT_REQ_PENDING:
4626 	case EMLXS_FCT_REG_PENDING:
4627 	case EMLXS_FCT_DATA_PENDING:
4628 	case EMLXS_FCT_STATUS_PENDING:
4629 
4630 		/* Abort anything pending */
4631 		if (emlxs_fct_pkt_abort_txq(port, cmd_sbp)) {
4632 
4633 			if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) {
4634 				TGTPORTSTAT.FctOutstandingIO--;
4635 			}
4636 
4637 			goto abort_done;
4638 		}
4639 
4640 		/* If we're not online, then all IO will be flushed anyway */
4641 		if (!(hba->flag & FC_ONLINE_MODE)) {
4642 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4643 			    "fct_abort: Not online. fct_cmd=%p.",
4644 			    fct_cmd);
4645 
4646 			emlxs_fct_cmd_release(port, fct_cmd, 0);
4647 			/* mutex_exit(&cmd_sbp->fct_mtx); */
4648 
4649 			/* The cmd will be aborted on the */
4650 			/* next emlxs_fct_cmd_acquire */
4651 			/* because EMLXS_FCT_ABORT_INP is set. */
4652 			break;
4653 		}
4654 
4655 		/* Try to send abort request */
4656 		if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
4657 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4658 			    "fct_abort: Unable to allocate packet. "
4659 			    "fct_cmd=%p",
4660 			    fct_cmd);
4661 
4662 			emlxs_fct_cmd_release(port, fct_cmd, 0);
4663 			/* mutex_exit(&cmd_sbp->fct_mtx); */
4664 
4665 			/* The cmd will be aborted on the */
4666 			/* next emlxs_fct_cmd_acquire anyway */
4667 			/* because EMLXS_FCT_ABORT_INP is set. */
4668 			break;
4669 		}
4670 
4671 		sbp = emlxs_fct_pkt_init(port, fct_cmd, pkt);
4672 
4673 		pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4674 		pkt->pkt_timeout =
4675 		    ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov);
4676 		pkt->pkt_comp = emlxs_fct_abort_pkt_comp;
4677 
4678 		/* Build the fc header */
4679 		pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fct_cmd->cmd_rportid);
4680 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS;
4681 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
4682 		pkt->pkt_cmd_fhdr.type = FC_TYPE_BASIC_LS;
4683 		pkt->pkt_cmd_fhdr.f_ctl =
4684 		    (F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ);
4685 		pkt->pkt_cmd_fhdr.seq_id = 0;
4686 		pkt->pkt_cmd_fhdr.df_ctl = 0;
4687 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
4688 		pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid;
4689 		pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid;
4690 		pkt->pkt_cmd_fhdr.ro = 0;
4691 
4692 		/* Make sure xrip is setup */
4693 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4694 			if (!sbp->xrip || sbp->xrip->state == XRI_STATE_FREE) {
4695 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4696 				    "fct_abort: "
4697 				    "Unable to acquire xri. (xid:%x,%x)",
4698 				    fct_cmd->cmd_oxid, fct_cmd->cmd_rxid);
4699 
4700 				emlxs_pkt_free(pkt);
4701 				return (FCT_NOT_FOUND);
4702 			}
4703 		}
4704 
4705 		cmd_sbp->fct_cmd = fct_cmd;
4706 		cmd_sbp->abort_attempts++;
4707 
4708 		/* Now disassociate the sbp / pkt from the fct_cmd */
4709 		sbp->fct_cmd = NULL;
4710 
4711 		if (hba->state >= FC_LINK_UP) {
4712 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4713 			    "fct_abort: ABORT: %p xid:%x,%x",
4714 			    fct_cmd, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid);
4715 
4716 			fct_state = EMLXS_FCT_ABORT_PENDING;
4717 
4718 		} else {
4719 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4720 			    "fct_abort: CLOSE: %p xid:%x,%x",
4721 			    fct_cmd, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid);
4722 
4723 			fct_state = EMLXS_FCT_CLOSE_PENDING;
4724 		}
4725 
4726 		emlxs_fct_cmd_release(port, fct_cmd, fct_state);
4727 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4728 
4729 		if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4730 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4731 			    "fct_abort: Unable to send abort packet.");
4732 
4733 			emlxs_pkt_free(pkt);
4734 
4735 			/* The cmd will be aborted on the */
4736 			/* next emlxs_fct_cmd_acquire anyway */
4737 			/* because EMLXS_FCT_ABORT_INP is set. */
4738 		}
4739 
4740 		break;
4741 
4742 	default:
4743 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4744 		    "fct_abort: Unexpected fct_state. "
4745 		    "fct_cmd=%p state=%d",
4746 		    fct_cmd, cmd_sbp->fct_state);
4747 
4748 		emlxs_fct_cmd_release(port, fct_cmd, 0);
4749 		/* mutex_exit(&cmd_sbp->fct_mtx); */
4750 
4751 		/* The cmd will be aborted on the */
4752 		/* next emlxs_fct_cmd_acquire anyway */
4753 		/* because EMLXS_FCT_ABORT_INP is set. */
4754 
4755 	}	/* switch */
4756 
4757 	return (FCT_SUCCESS);
4758 
4759 abort_done:
4760 
4761 	emlxs_fct_cmd_done(port, fct_cmd,
4762 	    EMLXS_FCT_ABORT_DONE);
4763 	/* mutex_exit(&cmd_sbp->fct_mtx); */
4764 
4765 	return (FCT_ABORT_SUCCESS);
4766 
4767 } /* emlxs_fct_abort() */
4768 
4769 
4770 extern void
emlxs_fct_link_up(emlxs_port_t * port)4771 emlxs_fct_link_up(emlxs_port_t *port)
4772 {
4773 	emlxs_hba_t *hba = HBA;
4774 
4775 	mutex_enter(&EMLXS_PORT_LOCK);
4776 #ifdef FCT_API_TRACE
4777 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4778 	    "fct_link_up port %p fct flags x%x",
4779 	    port->fct_port, port->fct_flags);
4780 #endif /* FCT_API_TRACE */
4781 
4782 	if (port->fct_port &&
4783 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
4784 	    !(port->fct_flags & FCT_STATE_LINK_UP)) {
4785 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4786 		    "fct_link_up event.");
4787 
4788 		port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED;
4789 		port->fct_flags &= ~FCT_STATE_FLOGI_CMPL;
4790 		port->fct_flags |= FCT_STATE_LINK_UP;
4791 		mutex_exit(&EMLXS_PORT_LOCK);
4792 
4793 #ifdef FCT_API_TRACE
4794 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4795 		    "fct_handle_event LINK_UP");
4796 #endif /* FCT_API_TRACE */
4797 		MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_UP,
4798 		    0, 0);
4799 	} else if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
4800 		mutex_exit(&EMLXS_PORT_LOCK);
4801 
4802 		if (port->vpi == 0) {
4803 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4804 			    "fct_link_up event. FCT port offline (%x). "
4805 			    "Disable link.",
4806 			    port->fct_flags);
4807 
4808 			/* Take link down and hold it down */
4809 			(void) emlxs_reset_link(hba, 0, 1);
4810 		} else {
4811 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4812 			    "fct_link_up event. FCT port offline (%x).",
4813 			    port->fct_flags);
4814 		}
4815 	} else {
4816 		mutex_exit(&EMLXS_PORT_LOCK);
4817 	}
4818 
4819 	return;
4820 
4821 } /* emlxs_fct_link_up() */
4822 
4823 
4824 extern void
emlxs_fct_link_down(emlxs_port_t * port)4825 emlxs_fct_link_down(emlxs_port_t *port)
4826 {
4827 	emlxs_hba_t *hba = HBA;
4828 
4829 	mutex_enter(&EMLXS_PORT_LOCK);
4830 #ifdef FCT_API_TRACE
4831 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4832 	    "fct_link_down port %p fct flags x%x",
4833 	    port->fct_port, port->fct_flags);
4834 #endif /* FCT_API_TRACE */
4835 
4836 	if (port->fct_port &&
4837 	    (port->fct_flags & FCT_STATE_PORT_ONLINE) &&
4838 	    (port->fct_flags & FCT_STATE_LINK_UP)) {
4839 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4840 		    "fct_link_down event.");
4841 
4842 		port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED;
4843 		port->fct_flags &= ~FCT_STATE_FLOGI_CMPL;
4844 		port->fct_flags &= ~FCT_STATE_LINK_UP;
4845 		mutex_exit(&EMLXS_PORT_LOCK);
4846 
4847 #ifdef FCT_API_TRACE
4848 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4849 		    "fct_handle_event LINK_DOWN");
4850 #endif /* FCT_API_TRACE */
4851 
4852 		MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_DOWN,
4853 		    0, 0);
4854 	} else {
4855 		mutex_exit(&EMLXS_PORT_LOCK);
4856 	}
4857 
4858 	return;
4859 
4860 } /* emlxs_fct_link_down() */
4861 
4862 
4863 void
emlxs_abort_fct_exchange(emlxs_hba_t * hba,emlxs_port_t * port,uint32_t rxid)4864 emlxs_abort_fct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid)
4865 {
4866 	CHANNEL *cp;
4867 	IOCBQ *iocbq;
4868 	IOCB *iocb;
4869 
4870 	if (rxid == 0 || rxid == 0xFFFF) {
4871 		return;
4872 	}
4873 
4874 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4875 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4876 		    "Aborting FCT exchange: xid=%x", rxid);
4877 
4878 		if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) {
4879 			/* We have no way to abort unsolicited exchanges */
4880 			/* that we have not responded to at this time */
4881 			/* So we will return for now */
4882 			return;
4883 		}
4884 	}
4885 
4886 	cp = &hba->chan[hba->channel_fcp];
4887 
4888 	mutex_enter(&EMLXS_FCTAB_LOCK);
4889 
4890 	/* Create the abort IOCB */
4891 	if (hba->state >= FC_LINK_UP) {
4892 		iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp,
4893 		    CLASS3, ABORT_TYPE_ABTS);
4894 	} else {
4895 		iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp);
4896 	}
4897 
4898 	mutex_exit(&EMLXS_FCTAB_LOCK);
4899 
4900 	if (iocbq) {
4901 		iocb = &iocbq->iocb;
4902 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4903 		    "Aborting FCT exchange: xid=%x iotag=%d", rxid,
4904 		    iocb->ULPIOTAG);
4905 
4906 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq);
4907 	}
4908 
4909 } /* emlxs_abort_fct_exchange() */
4910 
4911 
4912 extern uint32_t
emlxs_fct_stmf_alloc(emlxs_hba_t * hba,MATCHMAP * mp)4913 emlxs_fct_stmf_alloc(emlxs_hba_t *hba, MATCHMAP *mp)
4914 {
4915 	emlxs_port_t *port = &PPORT;
4916 	stmf_data_buf_t *db;
4917 
4918 	if (mp->tag < MEM_FCTSEG) {
4919 		return (0);
4920 	}
4921 
4922 	db = MODSYM(stmf_alloc) (STMF_STRUCT_DATA_BUF, 0, 0);
4923 
4924 #ifdef FCT_API_TRACE
4925 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4926 	    "stmf_alloc:%p iotag=%d phys %p virt %p sz %d",
4927 	    db, mp->tag, mp->phys, mp->virt, mp->size);
4928 #endif /* FCT_API_TRACE */
4929 
4930 	if (db == NULL) {
4931 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4932 		    "emlxs_fct_stmf_alloc: alloc failed.");
4933 		return (1);
4934 	}
4935 
4936 	db->db_port_private = (void*)mp;
4937 	db->db_sglist[0].seg_addr = mp->virt;
4938 	db->db_sglist[0].seg_length = mp->size;
4939 	db->db_buf_size = mp->size;
4940 	db->db_sglist_length = 1;
4941 
4942 	mp->fct_private = (void*)db;
4943 
4944 	return (0);
4945 
4946 } /* emlxs_fct_stmf_alloc() */
4947 
4948 
4949 /* ARGSUSED */
4950 extern void
emlxs_fct_stmf_free(emlxs_hba_t * hba,MATCHMAP * mp)4951 emlxs_fct_stmf_free(emlxs_hba_t *hba, MATCHMAP *mp)
4952 {
4953 #ifdef FCT_API_TRACE
4954 	emlxs_port_t *port = &PPORT;
4955 #endif /* FCT_API_TRACE */
4956 	stmf_data_buf_t *db;
4957 
4958 	if (mp->tag < MEM_FCTSEG) {
4959 		return;
4960 	}
4961 
4962 	db = (stmf_data_buf_t *)mp->fct_private;
4963 	mp->fct_private = NULL;
4964 
4965 	if (db == NULL) {
4966 		return;
4967 	}
4968 
4969 #ifdef FCT_API_TRACE
4970 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
4971 	    "stmf_free:%p iotag=%d",
4972 	    db, mp->tag);
4973 #endif /* FCT_API_TRACE */
4974 
4975 	MODSYM(stmf_free) (db);
4976 
4977 	return;
4978 
4979 } /* emlxs_fct_stmf_free() */
4980 
4981 
4982 static void
emlxs_fct_memseg_init(emlxs_hba_t * hba)4983 emlxs_fct_memseg_init(emlxs_hba_t *hba)
4984 {
4985 	emlxs_port_t *port = &PPORT;
4986 	char **arrayp = NULL;
4987 	uint32_t cnt = 0;
4988 	char buf[32];
4989 	uint32_t rval;
4990 	uint8_t *datap;
4991 	int i;
4992 	int j;
4993 	int fct_memseg_cnt = 0;
4994 	int numblks;
4995 	int memsize;
4996 	emlxs_memseg_t *fct_memseg = NULL;
4997 	uint32_t fct_memseg_size = 0;
4998 	emlxs_memseg_t *current;
4999 	emlxs_memseg_t *next;
5000 	emlxs_memseg_t *seg;
5001 
5002 	port->fct_memseg = NULL;
5003 	port->fct_memseg_cnt = 0;
5004 
5005 	/* Check for the per adapter setting */
5006 	(void) snprintf(buf, sizeof (buf), "%s%d-fct-bufpool", DRIVER_NAME,
5007 	    hba->ddiinst);
5008 	rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
5009 	    (DDI_PROP_DONTPASS), buf, &arrayp, &cnt);
5010 
5011 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
5012 		/* Check for the global setting */
5013 		cnt = 0;
5014 		arrayp = NULL;
5015 		rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip,
5016 		    (DDI_PROP_DONTPASS), "fct-bufpool", &arrayp, &cnt);
5017 	}
5018 
5019 	if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) {
5020 		goto default_config;
5021 	}
5022 
5023 	fct_memseg_size = cnt * sizeof (emlxs_memseg_t);
5024 	fct_memseg = kmem_zalloc(fct_memseg_size, KM_SLEEP);
5025 
5026 	if (!fct_memseg) {
5027 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
5028 		    "Unable to alloc fct_memseg. cnt=%d. "
5029 		    "Trying default config.",
5030 		    cnt);
5031 		goto default_config;
5032 	}
5033 
5034 	for (i = 0; i < cnt; i++) {
5035 		datap = (uint8_t *)arrayp[i];
5036 		if (datap == 0) {
5037 			break;
5038 		}
5039 
5040 		while (*datap == ' ') {	/* Skip spaces */
5041 			datap++;
5042 		}
5043 
5044 		memsize = emlxs_str_atoi(datap);
5045 
5046 		while ((*datap != ':') && (*datap != 0)) {
5047 			datap++;
5048 		}
5049 		if (*datap == ':') { /* Skip past delimeter */
5050 			datap++;
5051 		}
5052 		while (*datap == ' ') { /* Skip spaces */
5053 			datap++;
5054 		}
5055 
5056 		numblks = emlxs_str_atoi(datap);
5057 
5058 		/* Check for a bad entry */
5059 		if (!memsize || !numblks) {
5060 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
5061 			    "fct-bufpool: Entry %d:%d. Invalid.",
5062 			    memsize, numblks);
5063 			continue;
5064 		}
5065 
5066 		fct_memseg[fct_memseg_cnt].fc_memsize = memsize;
5067 		fct_memseg[fct_memseg_cnt].fc_numblks = numblks;
5068 		fct_memseg_cnt++;
5069 
5070 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
5071 		    "fct-bufpool: Entry:%d  %d:%d",
5072 		    fct_memseg_cnt, memsize, numblks);
5073 	}
5074 
5075 	if (!fct_memseg_cnt) {
5076 		kmem_free(fct_memseg, fct_memseg_size);
5077 		fct_memseg_size = 0;
5078 		fct_memseg = NULL;
5079 	}
5080 
5081 default_config:
5082 	/* If buffer list is empty, setup defaults */
5083 	if (!fct_memseg) {
5084 
5085 		fct_memseg_size = 8 * sizeof (emlxs_memseg_t);
5086 		fct_memseg = kmem_zalloc(fct_memseg_size, KM_SLEEP);
5087 
5088 		if (!fct_memseg) {
5089 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
5090 			    "Unable to alloc default port buffer pool. "
5091 			    "fct_memseg_cnt=%d",
5092 			    cnt);
5093 			return;
5094 		}
5095 
5096 		i = 0;
5097 		numblks = FCT_BUF_COUNT_2K;
5098 		if (numblks) {
5099 			fct_memseg[i].fc_memsize = 2 * 1024;
5100 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_2K;
5101 		}
5102 		numblks = FCT_BUF_COUNT_4K;
5103 		if (numblks) {
5104 			fct_memseg[i].fc_memsize = 4 * 1024;
5105 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_4K;
5106 		}
5107 		numblks = FCT_BUF_COUNT_8K;
5108 		if (numblks) {
5109 			fct_memseg[i].fc_memsize = 8 * 1024;
5110 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_8K;
5111 		}
5112 		numblks = FCT_BUF_COUNT_16K;
5113 		if (numblks) {
5114 			fct_memseg[i].fc_memsize = 16 * 1024;
5115 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_16K;
5116 		}
5117 		numblks = FCT_BUF_COUNT_32K;
5118 		if (numblks) {
5119 			fct_memseg[i].fc_memsize = 32 * 1024;
5120 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_32K;
5121 		}
5122 		numblks = FCT_BUF_COUNT_64K;
5123 		if (numblks) {
5124 			fct_memseg[i].fc_memsize = 64 * 1024;
5125 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_64K;
5126 		}
5127 		numblks = FCT_BUF_COUNT_128K;
5128 		if (numblks) {
5129 			fct_memseg[i].fc_memsize = 128 * 1024;
5130 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_128K;
5131 		}
5132 		numblks = FCT_BUF_COUNT_256K;
5133 		if (numblks) {
5134 			fct_memseg[i].fc_memsize = 256 * 1024;
5135 			fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_256K;
5136 		}
5137 		fct_memseg_cnt = i;
5138 	}
5139 
5140 	port->fct_memseg = kmem_zalloc((fct_memseg_cnt *
5141 	    sizeof (emlxs_memseg_t)), KM_SLEEP);
5142 
5143 	if (!port->fct_memseg) {
5144 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
5145 		    "Unable to alloc port buffer pool. fct_memseg_cnt=%d",
5146 		    fct_memseg_cnt);
5147 		kmem_free(fct_memseg, fct_memseg_size);
5148 		return;
5149 	}
5150 
5151 	/* Initalize port bucket list */
5152 	port->fct_memseg_cnt = fct_memseg_cnt;
5153 
5154 	/* Sort the entries smallest to largest */
5155 	seg = port->fct_memseg;
5156 	for (i = 0; i < fct_memseg_cnt; i++, seg++) {
5157 
5158 		/* Find next smallest buffer */
5159 		current = fct_memseg;
5160 		next = NULL;
5161 		for (j = 0; j < fct_memseg_cnt; j++, current++) {
5162 			if (current->fc_memsize == 0) {
5163 				continue;
5164 			}
5165 
5166 			if (next == NULL) {
5167 				next = current;
5168 				continue;
5169 			}
5170 
5171 			if (current->fc_memsize < next->fc_memsize) {
5172 				next = current;
5173 			}
5174 		}
5175 
5176 		/* Save next entry */
5177 		seg->fc_memsize = next->fc_memsize;
5178 		seg->fc_numblks = next->fc_numblks;
5179 		next->fc_memsize = 0;
5180 		next->fc_numblks = 0;
5181 	}
5182 
5183 	kmem_free(fct_memseg, fct_memseg_size);
5184 
5185 	/* Complete the initialization */
5186 	seg = port->fct_memseg;
5187 	for (i = 0; i < port->fct_memseg_cnt; i++, seg++) {
5188 /*		seg->fc_memsize = ; Already setup */
5189 /*		seg->fc_numblks = ; Already setup */
5190 
5191 		(void) snprintf(seg->fc_label, sizeof (seg->fc_label),
5192 		    "FCT_DMEM_%d", seg->fc_memsize);
5193 
5194 		seg->fc_memtag   = MEM_FCTSEG + i;
5195 		seg->fc_memflag  = FC_MBUF_DMA | FC_MBUF_SNGLSG;
5196 		seg->fc_memalign = 32;
5197 		seg->fc_hi_water = 0xFFFF;
5198 		seg->fc_lo_water = seg->fc_numblks;
5199 		seg->fc_numblks  = 0;
5200 		seg->fc_step = 1;
5201 	}
5202 
5203 	return;
5204 
5205 } /* emlxs_fct_memseg_init() */
5206 
5207 
5208 fct_status_t
emlxs_fct_dmem_init(emlxs_port_t * port)5209 emlxs_fct_dmem_init(emlxs_port_t *port)
5210 {
5211 	emlxs_hba_t *hba = HBA;
5212 	emlxs_memseg_t *seg;
5213 	int32_t i;
5214 
5215 	/* Initialize the fct memseg list */
5216 	emlxs_fct_memseg_init(hba);
5217 
5218 	if (!port->fct_memseg || !port->fct_memseg_cnt) {
5219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
5220 		    "fct_dmem_init: fct_memseg list is empty.");
5221 		return (FCT_FAILURE);
5222 	}
5223 
5224 	/* Create the DMA buffer pools */
5225 	seg = port->fct_memseg;
5226 	for (i = 0; i < port->fct_memseg_cnt; i++, seg++) {
5227 
5228 		(void) emlxs_mem_pool_create(hba, seg);
5229 
5230 		if (seg->fc_numblks < seg->fc_lo_water) {
5231 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
5232 			    "%s: count=%d size=%d flags=%x lo=%d hi=%d",
5233 			    seg->fc_label, seg->fc_numblks,
5234 			    seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water,
5235 			    seg->fc_hi_water);
5236 		}
5237 	}
5238 
5239 	return (FCT_SUCCESS);
5240 
5241 } /* emlxs_fct_dmem_init */
5242 
5243 
5244 void
emlxs_fct_dmem_fini(emlxs_port_t * port)5245 emlxs_fct_dmem_fini(emlxs_port_t *port)
5246 {
5247 	emlxs_hba_t *hba = HBA;
5248 	emlxs_memseg_t *seg;
5249 	int32_t i;
5250 
5251 	if (!port->fct_memseg || !port->fct_memseg_cnt) {
5252 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
5253 		    "fct_dmem_fini: fct_memseg list is empty.");
5254 		return;
5255 	}
5256 
5257 	/* Destroy the dmem buffer pools */
5258 	seg = port->fct_memseg;
5259 	for (i = 0; i < port->fct_memseg_cnt; i++, seg++) {
5260 		(void) emlxs_mem_pool_destroy(hba, seg);
5261 	}
5262 
5263 	/* Clear the segment space */
5264 	kmem_free(port->fct_memseg,
5265 	    (port->fct_memseg_cnt * sizeof (emlxs_memseg_t)));
5266 
5267 	port->fct_memseg = 0;
5268 	port->fct_memseg_cnt = 0;
5269 
5270 	return;
5271 
5272 } /* emlxs_fct_dmem_fini */
5273 
5274 
5275 /* COMSTAR ENTER POINT */
5276 /*ARGSUSED*/
5277 static stmf_data_buf_t *
emlxs_fct_dbuf_alloc(fct_local_port_t * fct_port,uint32_t size,uint32_t * pminsize,uint32_t flags)5278 emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, uint32_t size,
5279     uint32_t *pminsize, uint32_t flags)
5280 {
5281 	emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private;
5282 	emlxs_hba_t *hba = HBA;
5283 	emlxs_memseg_t *seg;
5284 	stmf_data_buf_t *db;
5285 	MATCHMAP *mp;
5286 	int i;
5287 	uint32_t minsize = 0;
5288 
5289 	if (!port->fct_memseg || !port->fct_memseg_cnt) {
5290 		goto failed;
5291 	}
5292 
5293 	/* Check if our largest buffer is too small */
5294 	seg = &port->fct_memseg[port->fct_memseg_cnt-1];
5295 	if (size > seg->fc_memsize) {
5296 		goto partial_alloc;
5297 	}
5298 
5299 	/* Find smallest available buffer >= size */
5300 	seg = port->fct_memseg;
5301 	for (i = 0; i < port->fct_memseg_cnt; i++, seg++) {
5302 		if (seg->fc_memsize < size) {
5303 			continue;
5304 		}
5305 
5306 		mp = (MATCHMAP*)emlxs_mem_pool_get(hba, seg);
5307 
5308 		if (mp) {
5309 			goto success;
5310 		}
5311 	}
5312 
5313 	seg = &port->fct_memseg[port->fct_memseg_cnt-1];
5314 
5315 partial_alloc:
5316 	/* Find largest available buffer >= *pminsize */
5317 	for (i = port->fct_memseg_cnt-1; i >= 0; i--, seg--) {
5318 		if (seg->fc_memsize < *pminsize) {
5319 			minsize = seg->fc_memsize;
5320 			goto failed;
5321 		}
5322 
5323 		mp = (MATCHMAP*)emlxs_mem_pool_get(hba, seg);
5324 
5325 		if (mp) {
5326 			goto success;
5327 		}
5328 	}
5329 
5330 failed:
5331 	*pminsize = minsize;
5332 	TGTPORTSTAT.FctNoBuffer++;
5333 
5334 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5335 	    "fct_dbuf_alloc:Failed. size=%d minsize=%d",
5336 	    size, *pminsize);
5337 
5338 	return (NULL);
5339 
5340 success:
5341 	/* Setup the data buffer */
5342 	db = (stmf_data_buf_t *)mp->fct_private;
5343 	db->db_data_size = min(size, mp->size);
5344 
5345 #ifdef FCT_API_TRACE
5346 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5347 	    "fct_dbuf_alloc:%p iotag=%d size=%d,%d",
5348 	    db, mp->tag, size,  mp->size);
5349 #endif /* FCT_API_TRACE */
5350 
5351 	return (db);
5352 
5353 } /* emlxs_fct_dbuf_alloc() */
5354 
5355 
5356 /* COMSTAR ENTER POINT */
5357 /*ARGSUSED*/
5358 static void
emlxs_fct_dbuf_free(fct_dbuf_store_t * fds,stmf_data_buf_t * db)5359 emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *db)
5360 {
5361 	emlxs_port_t *port = (emlxs_port_t *)fds->fds_fca_private;
5362 	emlxs_hba_t *hba = HBA;
5363 	MATCHMAP *mp = (MATCHMAP *)db->db_port_private;
5364 
5365 	if (!mp) {
5366 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5367 		    "fct_dbuf_free:%p  NULL mp found!",
5368 		    db);
5369 		return;
5370 	}
5371 
5372 #ifdef FCT_API_TRACE
5373 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5374 	    "fct_dbuf_free:%p iotag=%d",
5375 	    db, mp->tag);
5376 #endif /* FCT_API_TRACE */
5377 
5378 	emlxs_mem_pool_put(hba, mp->segment, (void *)mp);
5379 
5380 } /* emlxs_fct_dbuf_free() */
5381 
5382 
5383 static int
emlxs_fct_dbuf_dma_sync(emlxs_hba_t * hba,stmf_data_buf_t * db,uint_t sync_type)5384 emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *db,
5385     uint_t sync_type)
5386 {
5387 	emlxs_port_t *port = &PPORT;
5388 	MATCHMAP *mp = (MATCHMAP *)db->db_port_private;
5389 
5390 	if (!mp) {
5391 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5392 		    "fct_dbuf_dma_sync:%p  NULL mp found!",
5393 		    db);
5394 		return (0);
5395 	}
5396 
5397 #ifdef FCT_API_TRACE
5398 {
5399 	char buf[16];
5400 
5401 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg,
5402 	    "fct_dbuf_dma_sync:%p iotag=%d size=%d",
5403 	    db, mp->tag, db->db_data_size);
5404 
5405 	(void) snprintf(buf, sizeof (buf), "TAG%d:", mp->tag);
5406 	emlxs_data_dump(port, buf, (uint32_t *)db->db_sglist[0].seg_addr,
5407 	    36, 0);
5408 }
5409 #endif /* FCT_API_TRACE */
5410 
5411 	EMLXS_MPDATA_SYNC(mp->dma_handle, 0, db->db_data_size, sync_type);
5412 
5413 #ifdef FMA_SUPPORT
5414 	if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
5415 	    != DDI_FM_OK) {
5416 		EMLXS_MSGF(EMLXS_CONTEXT,
5417 		    &emlxs_invalid_dma_handle_msg,
5418 		    "fct_dbuf_dma_sync:%p iotag=%d",
5419 		    db, mp->tag);
5420 		return (1);
5421 	}
5422 #endif  /* FMA_SUPPORT */
5423 
5424 	return (0);
5425 
5426 } /* emlxs_fct_dbuf_dma_sync() */
5427 
5428 #endif /* SFCT_SUPPORT */
5429