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