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