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