1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * This file defines interfaces between FCOE and LEADVILLE
28 */
29
30 /*
31 * Driver kernel header files
32 */
33 #include <sys/conf.h>
34 #include <sys/ddi.h>
35 #include <sys/stat.h>
36 #include <sys/pci.h>
37 #include <sys/sunddi.h>
38 #include <sys/modctl.h>
39 #include <sys/file.h>
40 #include <sys/cred.h>
41 #include <sys/byteorder.h>
42 #include <sys/atomic.h>
43 #include <sys/scsi/scsi.h>
44 #include <sys/mac_client.h>
45 #include <sys/modhash.h>
46
47 /*
48 * LEADVILLE header files
49 */
50 #include <sys/fibre-channel/fc.h>
51 #include <sys/fibre-channel/impl/fc_fcaif.h>
52
53 /*
54 * COMSTAR head files (BIT_* macro)
55 */
56 #include <sys/stmf_defines.h>
57
58 /*
59 * FCOE header files
60 */
61 #include <sys/fcoe/fcoe_common.h>
62
63 /*
64 * Driver's own header files
65 */
66 #include <fcoei.h>
67
68 /*
69 * forward declaration of static functions
70 */
71 static void fcoei_port_enabled(void *arg);
72
73 static void fcoei_populate_hba_fru_details(fcoei_soft_state_t *ss,
74 fc_fca_port_info_t *port_info);
75
76 static void fcoei_initiate_ct_req(fcoei_exchange_t *xch);
77 static void fcoei_initiate_fcp_cmd(fcoei_exchange_t *xch);
78 static void fcoei_initiate_els_req(fcoei_exchange_t *xch);
79 static void fcoei_initiate_els_resp(fcoei_exchange_t *xch);
80
81 static void fcoei_fill_els_logi_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm);
82 static void fcoei_fill_els_prli_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm);
83 static void fcoei_fill_els_logo_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm);
84 static void fcoei_fill_els_scr_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm);
85 static void fcoei_fill_els_adisc_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm);
86 static void fcoei_fill_els_linit_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm);
87 static void fcoei_fill_els_rls_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm);
88 static void fcoei_fill_els_rnid_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm);
89
90 static void fcoei_fill_els_acc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm);
91 static void fcoei_fill_els_rjt_resp(fc_packet_t *fpkt, fcoe_frame_t *frm);
92 static void fcoei_fill_els_logi_resp(fc_packet_t *fpkt, fcoe_frame_t *frm);
93 static void fcoei_fill_els_prli_resp(fc_packet_t *fpkt, fcoe_frame_t *frm);
94 static void fcoei_fill_els_logo_resp(fc_packet_t *fpkt, fcoe_frame_t *frm);
95 static void fcoei_fill_els_adisc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm);
96
97 static void fcoei_logo_peer(void *arg);
98 static void fcoei_fpkt_comp(fc_packet_t *fpkt);
99
100 static uint32_t
101 fcoei_xch_abort(mod_hash_key_t key, mod_hash_val_t *val, void *arg);
102
103
104 /*
105 * fcoei_bind_port
106 * Bind LV port instance with fcoei soft state
107 *
108 * Input:
109 * dip = dev info of fcoei soft state
110 * port_info = fcoei specific parameters about LV port
111 * bind_info = LV specific parameters about fcoei soft state
112 *
113 * Returns:
114 * The pointer to fcoei soft state
115 *
116 * Comments:
117 * Unpon the completion of this call, the port must be offline.
118 * fcoei_port_enabled could trigger it to online
119 */
120 static void *
fcoei_bind_port(dev_info_t * dip,fc_fca_port_info_t * port_info,fc_fca_bind_info_t * bind_info)121 fcoei_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info,
122 fc_fca_bind_info_t *bind_info)
123 {
124 fcoei_soft_state_t *ss;
125
126 /*
127 * get state info based on the dip
128 */
129 ss = (fcoei_soft_state_t *)
130 ddi_get_soft_state(fcoei_state, ddi_get_instance(dip));
131 if (!ss) {
132 FCOEI_LOG(__FUNCTION__, "ss is NULL");
133 return (NULL);
134 }
135
136 /*
137 * make sure this port isn't bound
138 */
139 if (ss->ss_flags & SS_FLAG_LV_BOUND) {
140 port_info->pi_error = FC_ALREADY;
141 FCOEI_LOG(__FUNCTION__, "ss has been bound");
142 return (NULL);
143 }
144
145 if (bind_info->port_num) {
146 /*
147 * make sure request is in bounds
148 */
149 port_info->pi_error = FC_OUTOFBOUNDS;
150 FCOEI_LOG(__FUNCTION__, "port_num is not 0");
151 return (NULL);
152 }
153
154 /*
155 * stash the ss_bind_info supplied by the FC Transport
156 */
157 bcopy(bind_info, &ss->ss_bind_info, sizeof (fc_fca_bind_info_t));
158 ss->ss_port = bind_info->port_handle;
159
160 /*
161 * RNID parameter
162 */
163 port_info->pi_rnid_params.status = FC_FAILURE;
164
165 /*
166 * populate T11 FC-HBA details
167 */
168 fcoei_populate_hba_fru_details(ss, port_info);
169
170 /*
171 * set port's current state, and it is always offline before binding
172 *
173 * We hack pi_port_state to tell LV if it's NODMA_FCA
174 */
175 port_info->pi_port_state = FC_STATE_FCA_IS_NODMA;
176
177 /*
178 * copy login param
179 */
180 bcopy(&ss->ss_els_logi, &port_info->pi_login_params,
181 sizeof (la_els_logi_t));
182
183 /*
184 * Mark it as bound
185 */
186 atomic_or_32(&ss->ss_flags, SS_FLAG_LV_BOUND);
187
188 /*
189 * Let fcoe to report the link status
190 */
191 fcoei_port_enabled((void *)ss);
192
193 FCOEI_LOG(__FUNCTION__, "Exit fcoei_bind_port: %p", ss);
194 return (ss);
195 }
196
197 /*
198 * fcoei_unbind_port
199 * Un-bind the fcoei port
200 *
201 * Input:
202 * fca_handle = fcoei soft state set in fcoei_bind_port
203 *
204 * Returns:
205 * N/A
206 *
207 * Comments:
208 * Clear binding flag
209 */
210 static void
fcoei_unbind_port(void * fca_handle)211 fcoei_unbind_port(void *fca_handle)
212 {
213 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle;
214
215 atomic_and_32(&ss->ss_flags, ~SS_FLAG_LV_BOUND);
216 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_OFFLINE, NULL);
217 FCOEI_LOG(__FUNCTION__, "Exit fcoei_unbind_port: %p", ss);
218 }
219
220 /*
221 * fcoei_init_pkt
222 * Initialize fcoei related part of fc_packet
223 *
224 * Input:
225 * fca_handle = fcoei soft state set in fcoei_bind_port
226 * fpkt = The pointer to fc_packet
227 * sleep = This call can sleep or not
228 *
229 * Returns:
230 * FC_SUCCESS - Initialization completed successfully
231 *
232 * Comments:
233 * Link the exchange elements with proper objects
234 */
235 /* ARGSUSED */
236 static int
fcoei_init_pkt(void * fca_handle,fc_packet_t * fpkt,int sleep)237 fcoei_init_pkt(void *fca_handle, fc_packet_t *fpkt, int sleep)
238 {
239 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle;
240 fcoei_exchange_t *xch = FPKT2XCH(fpkt);
241
242 ASSERT(sleep + 1);
243 xch->xch_ss = ss;
244 xch->xch_fpkt = fpkt;
245 xch->xch_flags = 0;
246 return (FC_SUCCESS);
247 }
248
249 /*
250 * fcoei_un_init_pkt
251 * Uninitialize fcoei related part of fc_packet
252 *
253 * Input:
254 * fca_handle = fcoei soft state set in fcoei_bind_port
255 * fpkt = The pointer to fc_packet
256 *
257 * Returns:
258 * FC_SUCCESS - Uninitialize successfully
259 *
260 * Comments:
261 * Very simple, just return successfully
262 */
263 /* ARGSUSED */
264 static int
fcoei_un_init_pkt(void * fca_handle,fc_packet_t * fpkt)265 fcoei_un_init_pkt(void *fca_handle, fc_packet_t *fpkt)
266 {
267 ASSERT(fca_handle && fpkt);
268 return (FC_SUCCESS);
269 }
270
271 /*
272 * fcoei_get_cap
273 * Export FCA hardware and software capability.
274 *
275 * Input:
276 * fca_handle = fcoei soft state set in fcoei_bind_port
277 * cap = pointer to the capability string
278 * ptr = buffer pointer for returning capability
279 *
280 * Returns:
281 * FC_CAP_ERROR - no such capability
282 * FC_CAP_FOUND - the capability was returned and cannot be set
283 *
284 * Comments:
285 * FC_CAP_UNSOL_BUF is one important capability, it will affect the
286 * implementation of fcoei_ub_alloc/free.
287 */
288 static int
fcoei_get_cap(void * fca_handle,char * cap,void * ptr)289 fcoei_get_cap(void * fca_handle, char *cap, void *ptr)
290 {
291 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle;
292 uint32_t *rptr = (uint32_t *)ptr;
293 int rval = FC_CAP_FOUND;
294
295 ASSERT(fca_handle);
296 FCOEI_LOG(__FUNCTION__, "cap: %s", cap);
297 if (strcmp(cap, FC_NODE_WWN) == 0) {
298 bcopy(&ss->ss_els_logi.node_ww_name.raw_wwn[0], ptr, 8);
299 } else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
300 bcopy((void *)&ss->ss_els_logi, ptr, sizeof (la_els_logi_t));
301 } else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) {
302 *rptr = (uint32_t)0;
303 } else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) {
304 *rptr = (uint32_t)FC_ALLOW_STREAMING;
305 } else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
306 *rptr = (uint32_t)2136;
307 } else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
308 *rptr = FC_RESET_RETURN_ALL;
309 } else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) {
310 *rptr = FC_NO_DVMA_SPACE;
311 } else {
312 rval = FC_CAP_ERROR;
313 FCOEI_LOG(__FUNCTION__, "not supported");
314 }
315
316 return (rval);
317 }
318
319 /*
320 * fcoei_set_cap
321 * Allow the FC Transport to set FCA capabilities if possible
322 *
323 * Input:
324 * fca_handle = fcoei soft state set in fcoei_bind_port
325 * cap = pointer to the capabilities string.
326 * ptr = buffer pointer for capability.
327 *
328 * Returns:
329 * FC_CAP_ERROR - no such capability
330 *
331 * Comments:
332 * Currently, all capabilities can't be changed.
333 */
334 static int
fcoei_set_cap(void * fca_handle,char * cap,void * ptr)335 fcoei_set_cap(void * fca_handle, char *cap, void *ptr)
336 {
337 FCOEI_LOG(__FUNCTION__, "cap: %s, %p, %p", cap, fca_handle, ptr);
338 return (FC_CAP_ERROR);
339 }
340
341 /*
342 * fcoei_getmap
343 * Get lilp map
344 *
345 * Input:
346 * fca_handle = fcoei soft state set in fcoei_bind_port
347 * mapbuf = the buffer to store lilp map
348 *
349 * Returns:
350 * FC_FAILURE - Can't get the lilp map
351 *
352 * Comments:
353 * fcoei can't work in loop topology, so it should never get called
354 */
355 static int
fcoei_getmap(void * fca_handle,fc_lilpmap_t * mapbuf)356 fcoei_getmap(void * fca_handle, fc_lilpmap_t *mapbuf)
357 {
358 FCOEI_LOG(__FUNCTION__, "not: %p-%p", fca_handle, mapbuf);
359 return (FC_FAILURE);
360 }
361
362 /*
363 * fcoei_ub_alloc
364 * Pre-allocate unsolicited buffers at the request of LV
365 *
366 * Input:
367 * fca_handle = fcoei soft state set in fcoei_bind_port
368 * tokens = token array for each buffer.
369 * size = number of tokens
370 * count = the acutual number of allocated unsolicited buffers
371 * type = unsolicited buffer type
372 *
373 * Returns:
374 * FC_SUCCESS - The requested buffers have been freeed
375 *
376 * Comments:
377 * fcoei_get_cap will set UNSOL_BUF to 0, so it should never get called.
378 */
379 static int
fcoei_ub_alloc(void * fca_handle,uint64_t tokens[],uint32_t size,uint32_t * count,uint32_t type)380 fcoei_ub_alloc(void * fca_handle, uint64_t tokens[], uint32_t size,
381 uint32_t *count, uint32_t type)
382 {
383 FCOEI_LOG(__FUNCTION__, "not: %p-%p-%x-%p-%x", fca_handle, tokens,
384 size, count, type);
385 return (FC_SUCCESS);
386 }
387
388 /*
389 * fcoei_ub_free
390 * Free the pre-allocated unsolicited buffers at the request of LV
391 *
392 * Input:
393 * fca_handle = fcoei soft state set in fcoei_bind_port
394 * count = number of buffers.
395 * tokens = token array for each buffer.
396 *
397 * Returns:
398 * FC_SUCCESS - The requested buffers have been freeed
399 *
400 * Comments:
401 * fcoei_get_cap will set UNSOL_BUF to 0, so it should never get called.
402 */
403 static int
fcoei_ub_free(void * fca_handle,uint32_t count,uint64_t tokens[])404 fcoei_ub_free(void * fca_handle, uint32_t count, uint64_t tokens[])
405 {
406 FCOEI_EXT_LOG(__FUNCTION__, "not: %p-%x-%p", fca_handle, count, tokens);
407 return (FC_SUCCESS);
408 }
409
410 /*
411 * fcoei_ub_release
412 * Release unsolicited buffers from FC Transport to FCA for future use
413 *
414 * Input:
415 * fca_handle = fcoei soft state set in fcoei_bind_port
416 * count = number of buffers.
417 * tokens = token array for each buffer.
418 *
419 * Returns:
420 * FC_SUCCESS - The requested buffers have been released.
421 * FC_FAILURE - The requested buffers have not been released.
422 *
423 * Comments:
424 * It will always succeed. It has nothing to do with fcoei_ub_alloc/free.
425 */
426 static int
fcoei_ub_release(void * fca_handle,uint32_t count,uint64_t tokens[])427 fcoei_ub_release(void * fca_handle, uint32_t count, uint64_t tokens[])
428 {
429 fc_unsol_buf_t *ub = *((fc_unsol_buf_t **)tokens);
430
431 if (count != 1) {
432 FCOEI_LOG(__FUNCTION__, "count is not 1: %p", fca_handle);
433 return (FC_FAILURE);
434 }
435
436 kmem_free(ub->ub_buffer, ub->ub_bufsize);
437 kmem_free(ub, sizeof (fc_unsol_buf_t));
438 FCOEI_EXT_LOG(__FUNCTION__, "ub is freeed");
439 return (FC_SUCCESS);
440 }
441
442 /*
443 * fcoei_abort
444 * Direct FCA driver to abort an outstanding exchange associated with a
445 * specified fc_packet_t struct
446 *
447 * Input:
448 * fca_handle - fcoei soft state set in fcoei_bind_port
449 * fpkt - A pointer to the fc_packet_t for the exchange to be aborted.
450 * flags - Set to KM_SLEEP if the function may sleep, or KM_NOSLEEP if
451 * the function may not sleep.
452 *
453 * Returns:
454 * FC_ABORTED - The specified exchange was successfully aborted.
455 * FC_ABORTING - The specified exchange is being aborted.
456 * FC_ABORT_FAILED - The specified exchange could not be aborted.
457 * FC_TRANSPORT_ERROR - A transport error occurred while attempting to
458 * abort the specified exchange.
459 * FC_BADEXCHANGE - The specified exchange does not exist.
460 *
461 * Comments:
462 * After the exchange is aborted, the FCA driver must update the relevant
463 * fields in the fc_packet_t struct as per normal exchange completion and
464 * call the pkt_comp function to return the fc_packet_t struct to the FC
465 * Transport.
466 * When an exchange is successfully aborted, the FCA driver must set the
467 * pkt_reason field in the fc_packet_t to FC_REASON_ABORTED and the
468 * pkt_state field in the fc_packet_t to FC_PKT_LOCAL_RJT before returning
469 * the fc_packet_t to the FC Transport.
470 *
471 * Unfortunately, LV doesn't conform to the spec. It will take all these
472 * legal return value as failure to abort.
473 */
474 static int
fcoei_abort(void * fca_handle,fc_packet_t * fpkt,int flags)475 fcoei_abort(void * fca_handle, fc_packet_t *fpkt, int flags)
476 {
477 FCOEI_LOG(__FUNCTION__, "not: %p-%p-%x", fca_handle, fpkt, flags);
478 return (FC_SUCCESS);
479 }
480
481 /*
482 * fcoei_reset
483 * Reset link or hardware
484 *
485 * Input:
486 * fca_handle = fcoei soft state set in fcoei_bind_port
487 * cmd = reset type command
488 *
489 * Returns:
490 * FC_SUCCESS - Reset has completed successfully
491 * FC_FAILURE - Reset has failed
492 *
493 * Comments:
494 * N/A
495 */
496 static int
fcoei_reset(void * fca_handle,uint32_t cmd)497 fcoei_reset(void * fca_handle, uint32_t cmd)
498 {
499 int rval = FC_SUCCESS;
500 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle;
501 fcoei_event_t *ae;
502
503 switch (cmd) {
504 case FC_FCA_LINK_RESET:
505 if (ss->ss_link_state != FC_STATE_ONLINE) {
506 FCOEI_LOG(__FUNCTION__, "not online now: ss-%p", ss);
507 rval = FC_FAILURE;
508 break;
509 }
510
511 /*
512 * This is linkreset phase I
513 */
514 fcoei_logo_peer(ss);
515 delay(FCOE_SEC2TICK(1) / 10);
516 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_OFFLINE, 0);
517 fcoei_port_event(ss->ss_eport, FCOE_NOTIFY_EPORT_LINK_DOWN);
518
519 /*
520 * Perpare linkreset phase II
521 */
522 ae = kmem_zalloc(sizeof (*ae), KM_SLEEP);
523 ae->ae_type = AE_EVENT_RESET;
524 ae->ae_obj = ss;
525
526 mutex_enter(&ss->ss_watchdog_mutex);
527 list_insert_tail(&ss->ss_event_list, ae);
528 mutex_exit(&ss->ss_watchdog_mutex);
529 break;
530
531 case FC_FCA_RESET:
532 break;
533
534 case FC_FCA_CORE:
535 break;
536
537 case FC_FCA_RESET_CORE:
538 break;
539
540 default:
541 rval = FC_FAILURE;
542 FCOEI_LOG(__FUNCTION__, "cmd-%x not supported", cmd);
543 break;
544 }
545
546 return (rval);
547 }
548
549 /*
550 * fcoei_port_manage
551 * Perform various port management operations at the request of LV
552 *
553 * Input:
554 * fca_handle = fcoei soft state set in fcoei_bind_port
555 * pm = the pointer to the struct specifying the port management operation
556 *
557 * Returns:
558 * FC_SUCCESS - The request completed successfully
559 * FC_FAILURE - The request did not complete successfully
560 *
561 * Comments:
562 * N/A
563 */
564 static int
fcoei_port_manage(void * fca_handle,fc_fca_pm_t * pm)565 fcoei_port_manage(void * fca_handle, fc_fca_pm_t *pm)
566 {
567 int rval = FC_FAILURE;
568 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle;
569
570 if (fca_handle == NULL || pm == NULL) {
571 return (rval);
572 }
573
574 FCOEI_LOG(__FUNCTION__, "code0x%x, %p", pm->pm_cmd_code, fca_handle);
575 switch (pm->pm_cmd_code) {
576
577 case FC_PORT_GET_NODE_ID:
578 {
579 if (pm->pm_data_len < sizeof (fc_rnid_t)) {
580 rval = FC_NOMEM;
581 break;
582 }
583 ss->ss_rnid.port_id = ss->ss_p2p_info.fca_d_id;
584 bcopy((void *)&ss->ss_rnid,
585 pm->pm_data_buf, sizeof (fc_rnid_t));
586 rval = FC_SUCCESS;
587 break;
588 }
589
590 case FC_PORT_SET_NODE_ID:
591 {
592 if (pm->pm_data_len < sizeof (fc_rnid_t)) {
593 rval = FC_NOMEM;
594 break;
595 }
596 bcopy(pm->pm_data_buf,
597 (void *)&ss->ss_rnid, sizeof (fc_rnid_t));
598 rval = FC_SUCCESS;
599 break;
600 }
601
602 default:
603 FCOEI_LOG(__FUNCTION__, "unsupported cmd-%x", pm->pm_cmd_code);
604 rval = FC_INVALID_REQUEST;
605 break;
606 }
607
608 return (rval);
609 }
610
611 /*
612 * fcoei_get_device
613 * Get fcoei remote port with FCID of d_id
614 *
615 * Input:
616 * fca_handle = fcoei soft state set in fcoei_bind_port
617 * d_id = 24-bit FCID of remote port
618 *
619 * Returns:
620 * The pointer to fcoei remote port
621 *
622 * Comments:
623 * fcoei has no remote port device
624 */
625 static void *
fcoei_get_device(void * fca_handle,fc_portid_t d_id)626 fcoei_get_device(void *fca_handle, fc_portid_t d_id)
627 {
628 FCOEI_EXT_LOG(__FUNCTION__, "not supported: %p-%x", fca_handle, d_id);
629 return (NULL);
630 }
631
632 /*
633 * fcoei_notify
634 * Notify the change of target device
635 *
636 * Input:
637 * fca_handle = fcoei soft state set in fcoei_bind_port
638 * cmd = detailed cmd
639 *
640 * Returns:
641 * FC_SUCCESS - Notification completed successfully
642 *
643 * Comments:
644 * It's only needed to support non-COMSTAR FC target, so it should
645 * never get called.
646 */
647 static int
fcoei_notify(void * fca_handle,uint32_t cmd)648 fcoei_notify(void *fca_handle, uint32_t cmd)
649 {
650 FCOEI_LOG(__FUNCTION__, "not supported: %p-%x", fca_handle, cmd);
651 return (FC_SUCCESS);
652 }
653
654 /*
655 * fcoei_transport
656 * Submit FCP/CT requests
657 *
658 * Input:
659 * fca_handle - fcoei soft state set in fcoei_bind_port
660 * fpkt - LV fc_packet
661 *
662 * Returns:
663 * N/A
664 *
665 * Comments:
666 * N/A
667 */
668 static int
fcoei_transport(void * fca_handle,fc_packet_t * fpkt)669 fcoei_transport(void *fca_handle, fc_packet_t *fpkt)
670 {
671 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle;
672 fcoei_exchange_t *xch = FPKT2XCH(fpkt);
673 uint16_t pkt_tran_flags = fpkt->pkt_tran_flags;
674
675 xch->xch_start_tick = ddi_get_lbolt();
676 xch->xch_end_tick = xch->xch_start_tick +
677 FCOE_SEC2TICK(fpkt->pkt_timeout);
678 xch->xch_ae.ae_type = AE_EVENT_EXCHANGE;
679 xch->xch_ae.ae_obj = xch;
680
681 if (pkt_tran_flags & FC_TRAN_NO_INTR) {
682 FCOEI_LOG(__FUNCTION__, "AaA polling: %p-%p", fpkt, xch);
683 sema_init(&xch->xch_sema, 0, NULL, SEMA_DRIVER, NULL);
684 }
685
686 mutex_enter(&ss->ss_watchdog_mutex);
687 list_insert_tail(&ss->ss_event_list, &xch->xch_ae);
688 if (ss->ss_flags & SS_FLAG_WATCHDOG_IDLE) {
689 cv_signal(&ss->ss_watchdog_cv);
690 }
691 mutex_exit(&ss->ss_watchdog_mutex);
692
693 if (pkt_tran_flags & FC_TRAN_NO_INTR) {
694 FCOEI_LOG(__FUNCTION__, "BaB polling: %p-%p", fpkt, xch);
695 sema_p(&xch->xch_sema);
696 sema_destroy(&xch->xch_sema);
697 FCOEI_LOG(__FUNCTION__, "after polling: %p-%p", fpkt, xch);
698 }
699
700 return (FC_SUCCESS);
701 }
702
703 /*
704 * fcoei_els_send
705 * Submit ELS request or response
706 *
707 * Input:
708 * fca_handle - fcoei soft state set in fcoei_bind_port
709 * fpkt = LV fc_packet
710 *
711 * Returns:
712 * N/A
713 *
714 * Comments:
715 * N/A
716 */
717 static int
fcoei_els_send(void * fca_handle,fc_packet_t * fpkt)718 fcoei_els_send(void *fca_handle, fc_packet_t *fpkt)
719 {
720 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle;
721 fcoei_exchange_t *xch = FPKT2XCH(fpkt);
722
723 if (fpkt->pkt_tran_flags & FC_TRAN_NO_INTR) {
724 FCOEI_LOG(__FUNCTION__, "ELS poll mode is not supported");
725 return (FC_BADPACKET);
726 }
727
728 xch->xch_start_tick = ddi_get_lbolt();
729 xch->xch_end_tick = xch->xch_start_tick +
730 FCOE_SEC2TICK(fpkt->pkt_timeout);
731 xch->xch_ae.ae_type = AE_EVENT_EXCHANGE;
732 xch->xch_ae.ae_obj = xch;
733
734 /*
735 * LV could release ub after this call, so we must save the ub type
736 * for later use
737 */
738 if (fpkt->pkt_cmd_fhdr.r_ctl == R_CTL_ELS_RSP) {
739 ((uint8_t *)&fpkt->pkt_fca_rsvd1)[0] =
740 ((fc_unsol_buf_t *)fpkt->pkt_ub_resp_token)->ub_buffer[0];
741 }
742
743 mutex_enter(&ss->ss_watchdog_mutex);
744 list_insert_tail(&ss->ss_event_list, &xch->xch_ae);
745 if (ss->ss_flags & SS_FLAG_WATCHDOG_IDLE) {
746 cv_signal(&ss->ss_watchdog_cv);
747 }
748 mutex_exit(&ss->ss_watchdog_mutex);
749
750 return (FC_SUCCESS);
751 }
752
753 /*
754 * fcoei_populate_hba_fru_details
755 * Fill detailed information about HBA
756 *
757 * Input:
758 * ss - fcoei soft state
759 * port_info = fc_fca_port_info_t that need be updated
760 *
761 * Returns:
762 * N/A
763 *
764 * Comments:
765 * N/A
766 */
767 static void
fcoei_populate_hba_fru_details(fcoei_soft_state_t * ss,fc_fca_port_info_t * port_info)768 fcoei_populate_hba_fru_details(fcoei_soft_state_t *ss,
769 fc_fca_port_info_t *port_info)
770 {
771 fca_port_attrs_t *port_attrs = &(port_info->pi_attrs);
772 int instance;
773
774 ASSERT(ss != NULL);
775 (void) snprintf(port_attrs->manufacturer, FCHBA_MANUFACTURER_LEN,
776 "Sun Microsystems, Inc.");
777 (void) snprintf(port_attrs->driver_name, FCHBA_DRIVER_NAME_LEN,
778 "%s", FCOEI_NAME_VERSION);
779 (void) snprintf(port_attrs->driver_version, FCHBA_DRIVER_VERSION_LEN,
780 "%s", FCOEI_VERSION);
781 (void) strcpy(port_attrs->serial_number, "N/A");
782 (void) strcpy(port_attrs->hardware_version, "N/A");
783 (void) strcpy(port_attrs->model, "FCoE Virtual FC HBA");
784 (void) strcpy(port_attrs->model_description, "N/A");
785 (void) strcpy(port_attrs->firmware_version, "N/A");
786 (void) strcpy(port_attrs->option_rom_version, "N/A");
787
788 port_attrs->vendor_specific_id = 0xFC0E;
789 port_attrs->max_frame_size = FCOE_MAX_FC_FRAME_SIZE;
790 port_attrs->supported_cos = 0x10000000;
791 port_attrs->supported_speed = FC_HBA_PORTSPEED_1GBIT |
792 FC_HBA_PORTSPEED_10GBIT;
793 instance = ddi_get_instance(ss->ss_dip);
794 port_attrs->hba_fru_details.high =
795 (short)((instance & 0xffff0000) >> 16);
796 port_attrs->hba_fru_details.low =
797 (short)(instance & 0x0000ffff);
798 }
799
800 /*
801 * fcoei_port_enabled
802 * Notify fcoe that the port has been enabled
803 *
804 * Input:
805 * arg = the related soft state
806 *
807 * Returns:
808 * N/A
809 *
810 * Comments:
811 * Only after this, fcoe will report the link status to us
812 */
813 static void
fcoei_port_enabled(void * arg)814 fcoei_port_enabled(void *arg)
815 {
816 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)arg;
817
818 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_ONLINE, NULL);
819 }
820
821
822 /*
823 * fcoei_initiate_ct_req
824 * Fill and submit CT request
825 *
826 * Input:
827 * xch - the exchange that will be initiated
828 *
829 * Returns:
830 * N/A
831 *
832 * Comments:
833 * N/A
834 */
835 static void
fcoei_initiate_ct_req(fcoei_exchange_t * xch)836 fcoei_initiate_ct_req(fcoei_exchange_t *xch)
837 {
838 fc_packet_t *fpkt = xch->xch_fpkt;
839 fc_ct_header_t *ct = (fc_ct_header_t *)(void *)fpkt->pkt_cmd;
840 uint8_t *bp = (uint8_t *)fpkt->pkt_cmd;
841 fcoe_frame_t *frm;
842 int offset;
843 int idx;
844 uint32_t cmd_len = fpkt->pkt_cmdlen;
845
846 /*
847 * Ensure it's 4-byte aligned
848 */
849 cmd_len = P2ROUNDUP(cmd_len, 4);
850
851 /*
852 * Allocate CT request frame
853 */
854 frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport,
855 cmd_len + FCFH_SIZE, NULL);
856 if (frm == NULL) {
857 FCOEI_LOG(__FUNCTION__, "failed to alloc: %p", xch);
858 return;
859 }
860
861 bzero(frm->frm_payload, cmd_len);
862 xch->xch_cnt = xch->xch_ss->ss_sol_cnt;
863 atomic_inc_32(xch->xch_cnt);
864
865 FFM_R_CTL(fpkt->pkt_cmd_fhdr.r_ctl, frm);
866 FFM_D_ID(fpkt->pkt_cmd_fhdr.d_id, frm);
867 FFM_S_ID(fpkt->pkt_cmd_fhdr.s_id, frm);
868 FFM_TYPE(fpkt->pkt_cmd_fhdr.type, frm);
869 FFM_F_CTL(fpkt->pkt_cmd_fhdr.f_ctl, frm);
870 FFM_OXID(xch->xch_oxid, frm);
871 FFM_RXID(xch->xch_rxid, frm);
872 fcoei_init_ifm(frm, xch);
873
874 /*
875 * CT header (FC payload)
876 */
877 offset = 0;
878 FCOE_V2B_1(ct->ct_rev, FPLD + offset);
879
880 offset = 1;
881 FCOE_V2B_3(ct->ct_inid, FPLD + offset);
882
883 offset = 4;
884 FCOE_V2B_1(ct->ct_fcstype, FPLD + offset);
885
886 offset = 5;
887 FCOE_V2B_1(ct->ct_fcssubtype, FPLD + offset);
888
889 offset = 6;
890 FCOE_V2B_1(ct->ct_options, FPLD + offset);
891
892 offset = 8;
893 FCOE_V2B_2(ct->ct_cmdrsp, FPLD + offset);
894
895 offset = 10;
896 FCOE_V2B_2(ct->ct_aiusize, FPLD + offset);
897
898 offset = 13;
899 FCOE_V2B_1(ct->ct_reason, FPLD + offset);
900
901 offset = 14;
902 FCOE_V2B_1(ct->ct_expln, FPLD + offset);
903
904 offset = 15;
905 FCOE_V2B_1(ct->ct_vendor, FPLD + offset);
906
907 /*
908 * CT payload (FC payload)
909 */
910 switch (ct->ct_fcstype) {
911 case FCSTYPE_DIRECTORY:
912 switch (ct->ct_cmdrsp) {
913 case NS_GA_NXT:
914 case NS_GPN_ID:
915 case NS_GNN_ID:
916 case NS_GCS_ID:
917 case NS_GFT_ID:
918 case NS_GSPN_ID:
919 case NS_GPT_ID:
920 case NS_GID_FT:
921 case NS_GID_PT:
922 case NS_DA_ID:
923 offset = 16;
924 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0],
925 FPLD + offset);
926 break;
927
928 case NS_GID_PN:
929 offset = 16;
930 bcopy(bp + offset, FPLD + offset, 8);
931 break;
932
933 case NS_RNN_ID:
934 case NS_RPN_ID:
935 offset = 16;
936 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0],
937 FPLD + offset);
938
939 offset = 20;
940 bcopy(bp + offset, FPLD + offset, 8);
941 break;
942
943 case NS_RSPN_ID:
944 offset = 16;
945 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0],
946 FPLD + offset);
947
948 offset = 20;
949 bcopy(bp + offset, FPLD + offset, bp[20] + 1);
950 break;
951
952 case NS_RSNN_NN:
953 offset = 16;
954 bcopy(bp + offset, FPLD + offset, 8);
955
956 offset = 24;
957 bcopy(bp + offset, FPLD + offset, bp[24] + 1);
958 break;
959
960 case NS_RFT_ID:
961 offset = 16;
962 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0],
963 FPLD + offset);
964
965 /*
966 * fp use bcopy to copy fp_fc4_types,
967 * we need to swap order for each integer
968 */
969 offset = 20;
970 for (idx = 0; idx < 8; idx++) {
971 FCOE_V2B_4(
972 ((uint32_t *)(intptr_t)(bp + offset))[0],
973 FPLD + offset);
974 offset += 4;
975 }
976 break;
977
978 case NS_RCS_ID:
979 case NS_RPT_ID:
980 offset = 16;
981 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0],
982 FPLD + offset);
983
984 offset = 20;
985 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0],
986 FPLD + offset);
987 break;
988
989 case NS_RIP_NN:
990 offset = 16;
991 bcopy(bp + offset, FPLD + offset, 24);
992 break;
993
994 default:
995 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE,
996 FC_REASON_CMD_UNSUPPORTED);
997 break;
998 }
999 break; /* FCSTYPE_DIRECTORY */
1000
1001 case FCSTYPE_MGMTSERVICE:
1002 switch (ct->ct_cmdrsp) {
1003 case MS_GIEL:
1004 FCOEI_LOG(__FUNCTION__,
1005 "MS_GIEL ct_fcstype %x, ct_cmdrsp: %x",
1006 ct->ct_fcstype, ct->ct_cmdrsp);
1007 break;
1008
1009 default:
1010 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE,
1011 FC_REASON_CMD_UNSUPPORTED);
1012 break;
1013 }
1014 break; /* FCSTYPE_MGMTSERVICE */
1015
1016 default:
1017 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE,
1018 FC_REASON_CMD_UNSUPPORTED);
1019 break;
1020 }
1021 xch->xch_ss->ss_eport->eport_tx_frame(frm);
1022 }
1023
1024 /*
1025 * fcoei_initiate_fcp_cmd
1026 * Submit FCP command
1027 *
1028 * Input:
1029 * xch - the exchange to be submitted
1030 *
1031 * Returns:
1032 * N/A
1033 *
1034 * Comments:
1035 * N/A
1036 */
1037 static void
fcoei_initiate_fcp_cmd(fcoei_exchange_t * xch)1038 fcoei_initiate_fcp_cmd(fcoei_exchange_t *xch)
1039 {
1040 fc_packet_t *fpkt = xch->xch_fpkt;
1041 fcoe_frame_t *frm;
1042 fcp_cmd_t *fcp_cmd_iu = (fcp_cmd_t *)(void *)fpkt->pkt_cmd;
1043 int offset = 0;
1044
1045 ASSERT((fpkt->pkt_cmdlen % 4) == 0);
1046 frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport,
1047 fpkt->pkt_cmdlen + FCFH_SIZE, NULL);
1048 if (!frm) {
1049 ASSERT(0);
1050 } else {
1051 fcoei_init_ifm(frm, xch);
1052 bzero(frm->frm_payload, fpkt->pkt_cmdlen);
1053 }
1054
1055 /*
1056 * This will affect timing check
1057 */
1058 xch->xch_cnt = xch->xch_ss->ss_sol_cnt;
1059 atomic_inc_32(xch->xch_cnt);
1060
1061 /*
1062 * Set exchange residual bytes
1063 */
1064 xch->xch_resid = (int)fpkt->pkt_datalen;
1065
1066 /*
1067 * Fill FCP command IU
1068 *
1069 * fcp_ent_addr
1070 */
1071 FCOE_V2B_2(fcp_cmd_iu->fcp_ent_addr.ent_addr_0,
1072 frm->frm_payload + offset);
1073 offset += 2;
1074 FCOE_V2B_2(fcp_cmd_iu->fcp_ent_addr.ent_addr_1,
1075 frm->frm_payload + offset);
1076 offset += 2;
1077 FCOE_V2B_2(fcp_cmd_iu->fcp_ent_addr.ent_addr_2,
1078 frm->frm_payload + offset);
1079 offset += 2;
1080 FCOE_V2B_2(fcp_cmd_iu->fcp_ent_addr.ent_addr_3,
1081 frm->frm_payload + offset);
1082 /*
1083 * fcp_cntl
1084 */
1085 offset = offsetof(fcp_cmd_t, fcp_cntl);
1086 frm->frm_payload[offset] = 0;
1087
1088 offset += 1;
1089 frm->frm_payload[offset] = fcp_cmd_iu->fcp_cntl.cntl_qtype & 0x07;
1090 offset += 1;
1091 frm->frm_payload[offset] =
1092 (fcp_cmd_iu->fcp_cntl.cntl_kill_tsk << 7) |
1093 (fcp_cmd_iu->fcp_cntl.cntl_clr_aca << 6) |
1094 (fcp_cmd_iu->fcp_cntl.cntl_reset_tgt << 5) |
1095 (fcp_cmd_iu->fcp_cntl.cntl_reset_lun << 4) |
1096 (fcp_cmd_iu->fcp_cntl.cntl_clr_tsk << 2) |
1097 (fcp_cmd_iu->fcp_cntl.cntl_abort_tsk << 1);
1098 offset += 1;
1099 frm->frm_payload[offset] =
1100 (fcp_cmd_iu->fcp_cntl.cntl_read_data << 1) |
1101 (fcp_cmd_iu->fcp_cntl.cntl_write_data);
1102 /*
1103 * fcp_cdb
1104 */
1105 offset = offsetof(fcp_cmd_t, fcp_cdb);
1106 bcopy(fcp_cmd_iu->fcp_cdb, frm->frm_payload + offset, FCP_CDB_SIZE);
1107 /*
1108 * fcp_data_len
1109 */
1110 offset += FCP_CDB_SIZE;
1111 FCOE_V2B_4(fcp_cmd_iu->fcp_data_len, frm->frm_payload + offset);
1112
1113 /*
1114 * FC frame header
1115 */
1116 FRM2IFM(frm)->ifm_rctl = fpkt->pkt_cmd_fhdr.r_ctl;
1117
1118 FFM_R_CTL(fpkt->pkt_cmd_fhdr.r_ctl, frm);
1119 FFM_D_ID(fpkt->pkt_cmd_fhdr.d_id, frm);
1120 FFM_S_ID(fpkt->pkt_cmd_fhdr.s_id, frm);
1121 FFM_TYPE(fpkt->pkt_cmd_fhdr.type, frm);
1122 FFM_F_CTL(0x290000, frm);
1123 FFM_OXID(xch->xch_oxid, frm);
1124 FFM_RXID(xch->xch_rxid, frm);
1125
1126 xch->xch_ss->ss_eport->eport_tx_frame(frm);
1127 }
1128
1129 /*
1130 * fcoei_initiate_els_req
1131 * Initiate ELS request
1132 *
1133 * Input:
1134 * xch = the exchange that will be initiated
1135 *
1136 * Returns:
1137 * N/A
1138 *
1139 * Comments:
1140 * N/A
1141 */
1142 static void
fcoei_initiate_els_req(fcoei_exchange_t * xch)1143 fcoei_initiate_els_req(fcoei_exchange_t *xch)
1144 {
1145 fc_packet_t *fpkt = xch->xch_fpkt;
1146 fcoe_frame_t *frm;
1147 ls_code_t *els_code;
1148
1149 ASSERT((fpkt->pkt_cmdlen % 4) == 0);
1150 frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport,
1151 fpkt->pkt_cmdlen + FCFH_SIZE, NULL);
1152 if (!frm) {
1153 ASSERT(0);
1154 } else {
1155 fcoei_init_ifm(frm, xch);
1156 bzero(frm->frm_payload, fpkt->pkt_cmdlen);
1157 }
1158
1159 /*
1160 * This will affect timing check
1161 */
1162 xch->xch_cnt = xch->xch_ss->ss_sol_cnt;
1163 atomic_inc_32(xch->xch_cnt);
1164
1165 els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1166 switch (els_code->ls_code) {
1167 case LA_ELS_FLOGI:
1168 /*
1169 * For FLOGI, we expect response within E_D_TOV
1170 */
1171 xch->xch_start_tick = ddi_get_lbolt();
1172 xch->xch_end_tick = xch->xch_start_tick +
1173 FCOE_SEC2TICK(2);
1174 xch->xch_ss->ss_flags &= ~SS_FLAG_FLOGI_FAILED;
1175 /* FALLTHROUGH */
1176
1177 case LA_ELS_PLOGI:
1178 fcoei_fill_els_logi_cmd(fpkt, frm);
1179 break;
1180
1181 case LA_ELS_PRLI:
1182 fcoei_fill_els_prli_cmd(fpkt, frm);
1183 break;
1184
1185 case LA_ELS_SCR:
1186 fcoei_fill_els_scr_cmd(fpkt, frm);
1187 break;
1188
1189 case LA_ELS_LINIT:
1190 fcoei_fill_els_linit_cmd(fpkt, frm);
1191 break;
1192
1193 case LA_ELS_ADISC:
1194 fcoei_fill_els_adisc_cmd(fpkt, frm);
1195 break;
1196
1197 case LA_ELS_LOGO:
1198 /*
1199 * For LOGO, we expect response within E_D_TOV
1200 */
1201 xch->xch_start_tick = ddi_get_lbolt();
1202 xch->xch_end_tick = xch->xch_start_tick +
1203 FCOE_SEC2TICK(2);
1204 fcoei_fill_els_logo_cmd(fpkt, frm);
1205 break;
1206 case LA_ELS_RLS:
1207 fcoei_fill_els_rls_cmd(fpkt, frm);
1208 break;
1209 case LA_ELS_RNID:
1210 fcoei_fill_els_rnid_cmd(fpkt, frm);
1211 break;
1212 default:
1213 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE,
1214 FC_REASON_CMD_UNSUPPORTED);
1215 return;
1216 }
1217
1218 /*
1219 * set ifm_rtcl
1220 */
1221 FRM2IFM(frm)->ifm_rctl = fpkt->pkt_cmd_fhdr.r_ctl;
1222
1223 /*
1224 * FCPH
1225 */
1226 FFM_R_CTL(fpkt->pkt_cmd_fhdr.r_ctl, frm);
1227 FFM_D_ID(fpkt->pkt_cmd_fhdr.d_id, frm);
1228 FFM_S_ID(fpkt->pkt_cmd_fhdr.s_id, frm);
1229 FFM_TYPE(fpkt->pkt_cmd_fhdr.type, frm);
1230 FFM_F_CTL(0x290000, frm);
1231 FFM_OXID(xch->xch_oxid, frm);
1232 FFM_RXID(xch->xch_rxid, frm);
1233
1234 xch->xch_ss->ss_eport->eport_tx_frame(frm);
1235 }
1236
1237 /*
1238 * fcoei_initiate_els_resp
1239 * Originate ELS response
1240 *
1241 * Input:
1242 * xch = the associated exchange
1243 *
1244 * Returns:
1245 * N/A
1246 *
1247 * Comments:
1248 * N/A
1249 */
1250 static void
fcoei_initiate_els_resp(fcoei_exchange_t * xch)1251 fcoei_initiate_els_resp(fcoei_exchange_t *xch)
1252 {
1253 fc_packet_t *fpkt = xch->xch_fpkt;
1254 fcoe_frame_t *frm;
1255
1256 ASSERT((fpkt->pkt_cmdlen % 4) == 0);
1257 frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport,
1258 fpkt->pkt_cmdlen + FCFH_SIZE, NULL);
1259 if (!frm) {
1260 ASSERT(0);
1261 } else {
1262 fcoei_init_ifm(frm, xch);
1263 bzero(frm->frm_payload, fpkt->pkt_cmdlen);
1264 }
1265
1266 /*
1267 * This will affect timing check
1268 */
1269 xch->xch_cnt = xch->xch_ss->ss_unsol_cnt;
1270 atomic_inc_32(xch->xch_cnt);
1271
1272 /*
1273 * Set ifm_rctl
1274 */
1275 FRM2IFM(frm)->ifm_rctl = fpkt->pkt_cmd_fhdr.r_ctl;
1276
1277 /*
1278 * FCPH
1279 */
1280 FFM_R_CTL(fpkt->pkt_cmd_fhdr.r_ctl, frm);
1281 FFM_D_ID(fpkt->pkt_cmd_fhdr.d_id, frm);
1282 FFM_S_ID(fpkt->pkt_cmd_fhdr.s_id, frm);
1283 FFM_TYPE(fpkt->pkt_cmd_fhdr.type, frm);
1284 FFM_F_CTL(0x980000, frm);
1285 FFM_OXID(xch->xch_oxid, frm);
1286 FFM_RXID(xch->xch_rxid, frm);
1287
1288 switch (((uint8_t *)&fpkt->pkt_fca_rsvd1)[0]) {
1289 case LA_ELS_FLOGI:
1290 fcoei_fill_els_logi_resp(fpkt, frm);
1291 break;
1292
1293 case LA_ELS_PLOGI:
1294 if (FRM2SS(frm)->ss_eport->eport_flags &
1295 EPORT_FLAG_IS_DIRECT_P2P) {
1296 FRM2SS(frm)->ss_p2p_info.fca_d_id = FRM_S_ID(frm);
1297 FRM2SS(frm)->ss_p2p_info.d_id = FRM_D_ID(frm);
1298 }
1299
1300 fcoei_fill_els_logi_resp(fpkt, frm);
1301 break;
1302
1303 case LA_ELS_PRLI:
1304 fcoei_fill_els_prli_resp(fpkt, frm);
1305 break;
1306
1307 case LA_ELS_ADISC:
1308 fcoei_fill_els_adisc_resp(fpkt, frm);
1309 break;
1310
1311 case LA_ELS_LOGO:
1312 fcoei_fill_els_logo_resp(fpkt, frm);
1313 break;
1314 case LA_ELS_RSCN:
1315 fcoei_fill_els_acc_resp(fpkt, frm);
1316 break;
1317
1318 default:
1319 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE,
1320 FC_REASON_CMD_UNSUPPORTED);
1321 return;
1322 }
1323
1324 xch->xch_ss->ss_eport->eport_tx_frame(frm);
1325 }
1326
1327 /*
1328 * fcoei_fill_els_logi_cmd
1329 * Fill SCR (state change register) command frame
1330 *
1331 * Input:
1332 * fpkt = LV fc_packet
1333 * frm = Unsolicited frame containing LOGI response
1334 *
1335 * Returns:
1336 * N/A
1337 *
1338 * Comments:
1339 * N/A
1340 */
1341 static void
fcoei_fill_els_logi_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1342 fcoei_fill_els_logi_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1343 {
1344 la_els_logi_t *els_logi = (la_els_logi_t *)(void *)fpkt->pkt_cmd;
1345 int offset;
1346
1347 /*
1348 * fill ls_code
1349 */
1350 offset = 0;
1351 FCOE_V2B_1(els_logi->ls_code.ls_code, FPLD + offset);
1352
1353 /*
1354 * fill common service parameters
1355 */
1356 offset = 4;
1357 FCOE_V2B_2(els_logi->common_service.fcph_version, FPLD + offset);
1358
1359 offset = 6;
1360 FCOE_V2B_2(els_logi->common_service.btob_credit, FPLD + offset);
1361
1362 offset = 8;
1363 FCOE_V2B_2(els_logi->common_service.cmn_features, FPLD + offset);
1364
1365 offset = 10;
1366 FCOE_V2B_2(els_logi->common_service.rx_bufsize, FPLD + offset);
1367
1368 offset = 12;
1369 FCOE_V2B_2(els_logi->common_service.conc_sequences, FPLD + offset);
1370
1371 offset = 14;
1372 FCOE_V2B_2(els_logi->common_service.relative_offset, FPLD + offset);
1373
1374 offset = 16;
1375 FCOE_V2B_4(els_logi->common_service.e_d_tov, FPLD + offset);
1376
1377 /*
1378 * port/node wwn
1379 */
1380 offset = 20;
1381 bcopy(&els_logi->nport_ww_name, FPLD + offset, 8);
1382
1383 offset = 28;
1384 bcopy(&els_logi->node_ww_name, FPLD + offset, 8);
1385
1386 /*
1387 * class_3
1388 */
1389 offset = 68;
1390 FCOE_V2B_2(els_logi->class_3.class_opt, FPLD + offset);
1391
1392 offset = 70;
1393 FCOE_V2B_2(els_logi->class_3.initiator_ctl, FPLD + offset);
1394
1395 offset = 72;
1396 FCOE_V2B_2(els_logi->class_3.recipient_ctl, FPLD + offset);
1397
1398 offset = 74;
1399 FCOE_V2B_2(els_logi->class_3.rcv_size, FPLD + offset);
1400
1401 offset = 76;
1402 FCOE_V2B_2(els_logi->class_3.conc_sequences, FPLD + offset);
1403
1404 offset = 78;
1405 FCOE_V2B_2(els_logi->class_3.n_port_e_to_e_credit, FPLD + offset);
1406
1407 offset = 80;
1408 FCOE_V2B_2(els_logi->class_3.open_seq_per_xchng, FPLD + offset);
1409 /*
1410 * needn't touch other fields
1411 */
1412 }
1413
1414 /*
1415 * fcoei_fill_prli_cmd
1416 * Fill PRLI command frame
1417 *
1418 * Input:
1419 * fpkt = LV fc_packet
1420 * frm = Unsolicited frame containing PRLI response
1421 *
1422 * Returns:
1423 * N/A
1424 *
1425 * Comments:
1426 * N/A
1427 */
1428 static void
fcoei_fill_els_prli_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1429 fcoei_fill_els_prli_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1430 {
1431 int offset = 0;
1432 la_els_prli_t *els_prli = (la_els_prli_t *)(void *)fpkt->pkt_cmd;
1433 struct fcp_prli *fcp_spp =
1434 (struct fcp_prli *)(void *)els_prli->service_params;
1435
1436 /*
1437 * fill basic PRLI fields
1438 */
1439 offset = 0;
1440 FCOE_V2B_1(els_prli->ls_code, FPLD + offset);
1441
1442 offset = 1;
1443 FCOE_V2B_1(els_prli->page_length, FPLD + offset);
1444
1445 offset = 2;
1446 FCOE_V2B_2(els_prli->payload_length, FPLD + offset);
1447
1448 /*
1449 * fill FCP service parameters page
1450 */
1451 offset = 4;
1452 FCOE_V2B_1(fcp_spp->type, FPLD + offset);
1453
1454 /*
1455 * PRLI flags, only 3 bits are valid
1456 */
1457 offset = 6;
1458
1459 uint16_t prli_flags = ((fcp_spp->orig_process_assoc_valid << 15) |
1460 (fcp_spp->resp_process_assoc_valid << 14) |
1461 (fcp_spp->establish_image_pair << 13));
1462 FCOE_V2B_2(prli_flags, FPLD + offset);
1463
1464 /*
1465 * process associator
1466 */
1467 offset = 8;
1468 FCOE_V2B_4(fcp_spp->orig_process_associator, FPLD + offset);
1469
1470 offset = 12;
1471 FCOE_V2B_4(fcp_spp->resp_process_associator, FPLD + offset);
1472
1473 /*
1474 * FC-4 type
1475 */
1476 offset = 16;
1477 FCOE_V2B_4((fcp_spp->retry << 8) |
1478 (fcp_spp->confirmed_compl_allowed << 7) |
1479 (fcp_spp->data_overlay_allowed << 6) |
1480 (fcp_spp->initiator_fn << 5) | (fcp_spp->target_fn << 4) |
1481 (fcp_spp->read_xfer_rdy_disabled << 1) |
1482 (fcp_spp->write_xfer_rdy_disabled), FPLD + offset);
1483 }
1484
1485 /*
1486 * fcoei_fill_els_scr_cmd
1487 * Fill SCR (state change register) command frame
1488 *
1489 * Input:
1490 * fpkt = LV fc_packet
1491 * frm = Unsolicited frame containing SCR command
1492 *
1493 * Returns:
1494 * N/A
1495 *
1496 * Comments:
1497 * N/A
1498 */
1499 static void
fcoei_fill_els_scr_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1500 fcoei_fill_els_scr_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1501 {
1502 fc_scr_req_t *els_scr = (fc_scr_req_t *)(void *)fpkt->pkt_cmd;
1503 int offset;
1504
1505 offset = 0;
1506 FCOE_V2B_1(els_scr->ls_code.ls_code, FPLD + offset);
1507
1508 offset = 7;
1509 FCOE_V2B_1(els_scr->scr_func, FPLD + offset);
1510 }
1511
1512 /*
1513 * fcoei_fill_els_adisc_cmd
1514 * Fill ADISC command frame
1515 *
1516 * Input:
1517 * fpkt = LV fc_packet
1518 * frm = Unsolicited frame containing ADISC command
1519 *
1520 * Returns:
1521 * N/A
1522 *
1523 * Comments:
1524 * N/A
1525 */
1526 static void
fcoei_fill_els_adisc_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1527 fcoei_fill_els_adisc_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1528 {
1529 la_els_adisc_t *els_adisc = (la_els_adisc_t *)(void *)fpkt->pkt_cmd;
1530 int offset;
1531
1532 offset = 0;
1533 FCOE_V2B_1(els_adisc->ls_code.ls_code, FPLD + offset);
1534
1535 offset = 5;
1536 FCOE_V2B_3(els_adisc->hard_addr.hard_addr, FPLD + offset);
1537
1538 offset = 8;
1539 bcopy(&els_adisc->port_wwn, FPLD + offset, 8);
1540
1541 offset = 16;
1542 bcopy(&els_adisc->node_wwn, FPLD + offset, 8);
1543
1544 offset = 25;
1545 FCOE_V2B_3(els_adisc->nport_id.port_id, FPLD + offset);
1546 }
1547
1548 /*
1549 * fcoei_fill_els_linit_cmd
1550 * Fill LINIT command frame
1551 *
1552 * Input:
1553 * fpkt = LV fc_packet
1554 * frm = Unsolicited frame containing LINIT command
1555 *
1556 * Returns:
1557 * N/A
1558 *
1559 * Comments:
1560 * N/A
1561 */
1562 /* ARGSUSED */
1563 static void
fcoei_fill_els_linit_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1564 fcoei_fill_els_linit_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1565 {
1566 ASSERT(fpkt && frm);
1567 }
1568
1569 /*
1570 * fcoei_fill_els_logo_cmd
1571 * Fill LOGO command frame
1572 *
1573 * Input:
1574 * fpkt = LV fc_packet
1575 * frm = Unsolicited frame containing LOGO command
1576 *
1577 * Returns:
1578 * N/A
1579 *
1580 * Comments:
1581 * N/A
1582 */
1583 static void
fcoei_fill_els_logo_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1584 fcoei_fill_els_logo_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1585 {
1586 la_els_logo_t *els_logo = (la_els_logo_t *)(void *)fpkt->pkt_cmd;
1587 int offset;
1588
1589 offset = 0;
1590 FCOE_V2B_1(els_logo->ls_code.ls_code, FPLD + offset);
1591
1592 offset = 5;
1593 FCOE_V2B_3(els_logo->nport_id.port_id, FPLD + offset);
1594
1595 offset = 8;
1596 bcopy(&els_logo->nport_ww_name, FPLD + offset, 8);
1597 }
1598
1599 static void
fcoei_fill_els_rls_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1600 fcoei_fill_els_rls_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1601 {
1602 la_els_rls_t *els_rls = (la_els_rls_t *)(void *)fpkt->pkt_cmd;
1603 int offset;
1604
1605 offset = 0;
1606 FCOE_V2B_1(els_rls->ls_code.ls_code, FPLD + offset);
1607
1608 offset = 5;
1609 FCOE_V2B_3(els_rls->rls_portid.port_id, FPLD + offset);
1610 }
1611
1612 static void
fcoei_fill_els_rnid_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1613 fcoei_fill_els_rnid_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1614 {
1615 la_els_rnid_t *els_rnid = (la_els_rnid_t *)(void *)fpkt->pkt_cmd;
1616 int offset;
1617
1618 offset = 0;
1619 FCOE_V2B_1(els_rnid->ls_code.ls_code, FPLD + offset);
1620
1621 offset = 4;
1622 bcopy(&els_rnid->data_format, FPLD + offset, 1);
1623 }
1624 /*
1625 * fcoei_fill_els_acc_resp
1626 * Fill ELS ACC response frame
1627 *
1628 * Input:
1629 * fpkt = LV fc_packet
1630 * frm = Unsolicited frame containing ELS ACC response
1631 *
1632 * Returns:
1633 * N/A
1634 *
1635 * Comments:
1636 * N/A
1637 */
1638 static void
fcoei_fill_els_acc_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1639 fcoei_fill_els_acc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1640 {
1641 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1642 int offset;
1643
1644 offset = 0;
1645 FCOE_V2B_1(els_code->ls_code, FPLD + offset);
1646
1647 offset = 1;
1648 FCOE_V2B_3(els_code->mbz, FPLD + offset);
1649 }
1650
1651 /*
1652 * fcoei_fill_els_rjt_resp
1653 * Fill ELS RJT response frame
1654 *
1655 * Input:
1656 * fpkt = LV fc_packet
1657 * frm = Unsolicited frame containg ELS RJT response
1658 *
1659 * Returns:
1660 * N/A
1661 *
1662 * Comments:
1663 * N/A
1664 */
1665 static void
fcoei_fill_els_rjt_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1666 fcoei_fill_els_rjt_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1667 {
1668 la_els_rjt_t *els_rjt = (la_els_rjt_t *)(void *)fpkt->pkt_cmd;
1669 int offset;
1670
1671 offset = 0; /* reset ls code */
1672 FCOE_V2B_1(els_rjt->ls_code.ls_code, FPLD + offset);
1673
1674 offset = 5; /* reason code */
1675 FCOE_V2B_1(els_rjt->action, FPLD + offset);
1676
1677 offset = 6; /* reason explanation */
1678 FCOE_V2B_1(els_rjt->reason, FPLD + offset);
1679
1680 offset = 7; /* vendor unique */
1681 FCOE_V2B_1(els_rjt->vu, FPLD + offset);
1682 }
1683
1684 /*
1685 * fcoei_fill_els_adisc_resp
1686 * Fill ADISC response frame
1687 *
1688 * Input:
1689 * fpkt = LV fc_packet
1690 * frm = Unsolicited frame containing ADISC response
1691 *
1692 * Returns:
1693 * N/A
1694 *
1695 * Comments:
1696 * N/A
1697 */
1698 static void
fcoei_fill_els_adisc_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1699 fcoei_fill_els_adisc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1700 {
1701 la_els_adisc_t *els_adisc = (la_els_adisc_t *)(void *)fpkt->pkt_cmd;
1702 int offset;
1703
1704 if (els_adisc->ls_code.ls_code == LA_ELS_RJT) {
1705 fcoei_fill_els_rjt_resp(fpkt, frm);
1706 } else {
1707 offset = 0;
1708 FCOE_V2B_1(els_adisc->ls_code.ls_code, FPLD + offset);
1709
1710 offset = 5;
1711 FCOE_V2B_3(els_adisc->hard_addr.hard_addr, FPLD + offset);
1712
1713 offset = 8;
1714 bcopy(&els_adisc->port_wwn, FPLD + offset, FC_WWN_SIZE);
1715
1716 offset = 16;
1717 bcopy(&els_adisc->node_wwn, FPLD + offset, FC_WWN_SIZE);
1718
1719 offset = 25;
1720 FCOE_V2B_3(els_adisc->nport_id.port_id, FPLD + offset);
1721 }
1722 }
1723
1724 /*
1725 * fcoei_fill_els_logi_resp
1726 * Fill FLOGI/PLOGI response frame
1727 *
1728 * Input:
1729 * fpkt = LV fc_packet
1730 * frm = Unsolicited frame containing LOGI response
1731 *
1732 * Returns:
1733 * N/A
1734 *
1735 * Comments:
1736 * N/A
1737 */
1738 static void
fcoei_fill_els_logi_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1739 fcoei_fill_els_logi_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1740 {
1741 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1742
1743 if (els_code->ls_code == LA_ELS_RJT) {
1744 fcoei_fill_els_rjt_resp(fpkt, frm);
1745 } else {
1746 fcoei_fill_els_logi_cmd(fpkt, frm);
1747 }
1748 }
1749
1750 /*
1751 * fcoei_fill_els_prli_resp
1752 * Fill PRLI response frame
1753 *
1754 * Input:
1755 * fpkt = LV fc_packet
1756 * frm = Unsolicited frame containing PRLI response
1757 *
1758 * Returns:
1759 * N/A
1760 *
1761 * Comments:
1762 * N/A
1763 */
1764 static void
fcoei_fill_els_prli_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1765 fcoei_fill_els_prli_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1766 {
1767 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1768
1769 if (els_code->ls_code == LA_ELS_RJT) {
1770 fcoei_fill_els_rjt_resp(fpkt, frm);
1771 } else {
1772 fcoei_fill_els_prli_cmd(fpkt, frm);
1773 }
1774 }
1775
1776 /*
1777 * fcoei_fill_els_logo_resp
1778 * Fill LOGO response frame
1779 *
1780 * Input:
1781 * fpkt = LV fc_packet
1782 * frm = Unsolicited frame containing LOGO response
1783 *
1784 * Returns:
1785 * N/A
1786 *
1787 * Comments:
1788 * N/A
1789 */
1790 static void
fcoei_fill_els_logo_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1791 fcoei_fill_els_logo_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1792 {
1793 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1794
1795 if (els_code->ls_code == LA_ELS_RJT) {
1796 fcoei_fill_els_rjt_resp(fpkt, frm);
1797 } else {
1798 fcoei_fill_els_acc_resp(fpkt, frm);
1799 }
1800 }
1801
1802 /*
1803 * fcoei_logo_peer
1804 * Send LOGO to the peer to emulate link offline event
1805 *
1806 * Input:
1807 * arg - fcoei soft state set in fcoei_bind_port
1808 *
1809 * Returns:
1810 * N/A
1811 *
1812 * Comments:
1813 * N/A
1814 */
1815 static void
fcoei_logo_peer(void * arg)1816 fcoei_logo_peer(void *arg)
1817 {
1818 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)arg;
1819 fc_packet_t *fpkt;
1820 fcoei_exchange_t *xch;
1821 la_els_logo_t *els_logo;
1822
1823 /*
1824 * Allocate space for exchange
1825 */
1826 xch = kmem_zalloc(sizeof (*xch), KM_SLEEP);
1827
1828 /*
1829 * Allocate space for fc_packet
1830 */
1831 fpkt = kmem_zalloc(sizeof (fc_packet_t), KM_SLEEP);
1832 fpkt->pkt_cmdlen = 20;
1833 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, KM_SLEEP);
1834 fpkt->pkt_rsplen = 20;
1835 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, KM_SLEEP);
1836
1837 /*
1838 * Link them together
1839 */
1840 fpkt->pkt_fca_private = xch;
1841 (void) fcoei_init_pkt(ss, fpkt, 0);
1842
1843 /*
1844 * Initialize FC frame header
1845 */
1846 if (ss->ss_eport->eport_flags & EPORT_FLAG_IS_DIRECT_P2P) {
1847 fpkt->pkt_cmd_fhdr.d_id = ss->ss_p2p_info.d_id;
1848 } else {
1849 fpkt->pkt_cmd_fhdr.d_id = 0xFFFFFE;
1850 }
1851
1852 fpkt->pkt_cmd_fhdr.s_id = ss->ss_p2p_info.fca_d_id;
1853 fpkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
1854 fpkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
1855 fpkt->pkt_cmd_fhdr.f_ctl = 0x290000;
1856 fpkt->pkt_timeout = 1;
1857
1858 /*
1859 * Initialize LOGO payload
1860 */
1861 els_logo = (la_els_logo_t *)(void *)fpkt->pkt_cmd;
1862 els_logo->ls_code.ls_code = LA_ELS_LOGO;
1863 els_logo->nport_id.port_id = ss->ss_p2p_info.fca_d_id;
1864 bcopy(ss->ss_eport->eport_portwwn, &els_logo->nport_ww_name, 8);
1865
1866 /*
1867 * Set the completion function
1868 */
1869 fpkt->pkt_comp = fcoei_fpkt_comp;
1870 if (fcoei_transport(ss, fpkt) != FC_SUCCESS) {
1871 FCOEI_LOG(__FUNCTION__, "fcoei_transport LOGO failed");
1872 fcoei_fpkt_comp(fpkt);
1873 }
1874 }
1875
1876 /*
1877 * fcoei_fpkt_comp
1878 * internal exchange completion
1879 *
1880 * Input:
1881 * fpkt - fc_packet_t to be completed
1882 *
1883 * Returns:
1884 * N/A
1885 *
1886 * Comments:
1887 *
1888 */
1889 static void
fcoei_fpkt_comp(fc_packet_t * fpkt)1890 fcoei_fpkt_comp(fc_packet_t *fpkt)
1891 {
1892 fcoei_exchange_t *xch = FPKT2XCH(fpkt);
1893
1894 FCOEI_LOG(__FUNCTION__, "internal exchange is completed: %p", xch);
1895
1896 (void) fcoei_un_init_pkt(xch->xch_ss, xch->xch_fpkt);
1897 kmem_free(xch->xch_fpkt->pkt_cmd, xch->xch_fpkt->pkt_cmdlen);
1898 kmem_free(xch->xch_fpkt->pkt_resp, xch->xch_fpkt->pkt_rsplen);
1899 kmem_free(xch->xch_fpkt, sizeof (fc_packet_t));
1900 kmem_free(xch, sizeof (fcoei_exchange_t));
1901 }
1902
1903 /*
1904 * fcoei_xch_abort
1905 * Prepare to abort the exchange
1906 *
1907 * Input:
1908 * key = oxid/rxid of the exchange
1909 * val = the exchange
1910 * arg = the soft state
1911 *
1912 * Returns:
1913 * MH_WALK_CONTINUE = continue to walk
1914 *
1915 * Comments:
1916 * N/A
1917 */
1918 /* ARGSUSED */
1919 static uint32_t
fcoei_xch_abort(mod_hash_key_t key,mod_hash_val_t * val,void * arg)1920 fcoei_xch_abort(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
1921 {
1922 fcoei_exchange_t *xch = (fcoei_exchange_t *)val;
1923
1924 ASSERT(arg == xch->xch_ss);
1925 ASSERT(CMHK(key) != 0xFFFF);
1926 xch->xch_flags |= XCH_FLAG_ABORT;
1927 xch->xch_fpkt->pkt_state = FC_PKT_LOCAL_RJT;
1928 xch->xch_fpkt->pkt_reason = FC_REASON_OFFLINE;
1929 list_insert_tail(&xch->xch_ss->ss_comp_xch_list, xch);
1930 return (MH_WALK_CONTINUE);
1931 }
1932
1933 /*
1934 * fcoei_init_fcatran_vectors
1935 * Initialize fc_fca_tran vectors that are defined in this file
1936 *
1937 * Input:
1938 * fcatran - fc_fca_tran of the soft state
1939 *
1940 * Returns:
1941 * N/A
1942 *
1943 * Comments:
1944 * N/A
1945 */
1946 void
fcoei_init_fcatran_vectors(fc_fca_tran_t * fcatran)1947 fcoei_init_fcatran_vectors(fc_fca_tran_t *fcatran)
1948 {
1949 fcatran->fca_bind_port = fcoei_bind_port;
1950 fcatran->fca_unbind_port = fcoei_unbind_port;
1951 fcatran->fca_init_pkt = fcoei_init_pkt;
1952 fcatran->fca_un_init_pkt = fcoei_un_init_pkt;
1953 fcatran->fca_els_send = fcoei_els_send;
1954 fcatran->fca_get_cap = fcoei_get_cap;
1955 fcatran->fca_set_cap = fcoei_set_cap;
1956 fcatran->fca_getmap = fcoei_getmap;
1957 fcatran->fca_transport = fcoei_transport;
1958 fcatran->fca_ub_alloc = fcoei_ub_alloc;
1959 fcatran->fca_ub_free = fcoei_ub_free;
1960 fcatran->fca_ub_release = fcoei_ub_release;
1961 fcatran->fca_abort = fcoei_abort;
1962 fcatran->fca_reset = fcoei_reset;
1963 fcatran->fca_port_manage = fcoei_port_manage;
1964 fcatran->fca_get_device = fcoei_get_device;
1965 fcatran->fca_notify = fcoei_notify;
1966 }
1967
1968 /*
1969 * fcoei_process_event_reset
1970 * link reset phase II
1971 *
1972 * Input:
1973 * arg - fcoei soft state set in fcoei_bind_port
1974 *
1975 * Returns:
1976 * N/A
1977 *
1978 * Comments:
1979 *
1980 */
1981 void
fcoei_process_event_reset(fcoei_event_t * ae)1982 fcoei_process_event_reset(fcoei_event_t *ae)
1983 {
1984 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)ae->ae_obj;
1985
1986 ASSERT(!MUTEX_HELD(&ss->ss_watchdog_mutex));
1987 kmem_free(ae, sizeof (*ae));
1988
1989 mod_hash_walk(ss->ss_sol_oxid_hash, fcoei_xch_abort, ss);
1990 mod_hash_walk(ss->ss_unsol_rxid_hash, fcoei_xch_abort, ss);
1991 fcoei_handle_comp_xch_list(ss);
1992
1993 /*
1994 * Notify LV that the link is up now
1995 */
1996 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_ONLINE, 0);
1997 }
1998
1999 /*
2000 * fcoei_process_event_exchange
2001 * Process exchange in the single thread context
2002 *
2003 * Input:
2004 * ae = the exchange event
2005 *
2006 * Returns:
2007 * N/A
2008 *
2009 * Comments:
2010 * N/A
2011 */
2012 void
fcoei_process_event_exchange(fcoei_event_t * ae)2013 fcoei_process_event_exchange(fcoei_event_t *ae)
2014 {
2015 fcoei_exchange_t *xch = (fcoei_exchange_t *)ae->ae_obj;
2016 fcoei_exchange_t *xch_tmp;
2017 fc_packet_t *fpkt = xch->xch_fpkt;
2018
2019 /*
2020 * These 4 elements need reset, pkt_state & pkt_reason will be set
2021 */
2022 fpkt->pkt_action = 0;
2023 fpkt->pkt_expln = 0;
2024 fpkt->pkt_data_resid = 0;
2025 fpkt->pkt_resp_resid = 0;
2026
2027 /*
2028 * port state sanity checking
2029 */
2030 if ((xch->xch_ss->ss_link_state != FC_STATE_ONLINE) ||
2031 xch->xch_ss->ss_port_event_counter) {
2032 /*
2033 * LV will retry it after one second
2034 */
2035 fcoei_complete_xch(xch, NULL, FC_PKT_PORT_OFFLINE,
2036 FC_REASON_OFFLINE);
2037 return;
2038 }
2039
2040 switch (fpkt->pkt_cmd_fhdr.r_ctl) {
2041 case R_CTL_COMMAND:
2042 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp);
2043 fcoei_initiate_fcp_cmd(xch);
2044 break;
2045
2046 case R_CTL_ELS_REQ:
2047 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp);
2048 fcoei_initiate_els_req(xch);
2049 break;
2050
2051 case R_CTL_UNSOL_CONTROL:
2052 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp);
2053 fcoei_initiate_ct_req(xch);
2054 break;
2055
2056 case R_CTL_ELS_RSP:
2057 /*
2058 * Caution: in leadville, it still uses pkt_cmd_fhdr
2059 * oxid & rxid have been decided when we get unsolicited frames.
2060 * pkt_cmd_fhdr has contained the right oxid and rxid now.
2061 */
2062 FCOEI_INIT_UNSOL_ID_HASH(xch);
2063 fcoei_initiate_els_resp(xch);
2064 break;
2065
2066 default:
2067 fcoei_complete_xch(xch, NULL, FC_PKT_FAILURE,
2068 FC_REASON_CMD_UNSUPPORTED);
2069 }
2070 }
2071