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