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.
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.
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]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * This file defines interfaces between FCOE and LEADVILLE
31 * Driver kernel header files
37 #include <sys/sunddi.h>
38 #include <sys/modctl.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>
48 * LEADVILLE header files
50 #include <sys/fibre-channel/fc.h>
51 #include <sys/fibre-channel/impl/fc_fcaif.h>
54 * COMSTAR head files (BIT_* macro)
56 #include <sys/stmf_defines.h>
61 #include <sys/fcoe/fcoe_common.h>
64 * Driver's own header files
69 * forward declaration of static functions
71 static void fcoei_port_enabled(void *arg
);
73 static void fcoei_populate_hba_fru_details(fcoei_soft_state_t
*ss
,
74 fc_fca_port_info_t
*port_info
);
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
);
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
);
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
);
97 static void fcoei_logo_peer(void *arg
);
98 static void fcoei_fpkt_comp(fc_packet_t
*fpkt
);
101 fcoei_xch_abort(mod_hash_key_t key
, mod_hash_val_t
*val
, void *arg
);
106 * Bind LV port instance with fcoei soft state
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
114 * The pointer to fcoei soft state
117 * Unpon the completion of this call, the port must be offline.
118 * fcoei_port_enabled could trigger it to online
121 fcoei_bind_port(dev_info_t
*dip
, fc_fca_port_info_t
*port_info
,
122 fc_fca_bind_info_t
*bind_info
)
124 fcoei_soft_state_t
*ss
;
127 * get state info based on the dip
129 ss
= (fcoei_soft_state_t
*)
130 ddi_get_soft_state(fcoei_state
, ddi_get_instance(dip
));
132 FCOEI_LOG(__FUNCTION__
, "ss is NULL");
137 * make sure this port isn't bound
139 if (ss
->ss_flags
& SS_FLAG_LV_BOUND
) {
140 port_info
->pi_error
= FC_ALREADY
;
141 FCOEI_LOG(__FUNCTION__
, "ss has been bound");
145 if (bind_info
->port_num
) {
147 * make sure request is in bounds
149 port_info
->pi_error
= FC_OUTOFBOUNDS
;
150 FCOEI_LOG(__FUNCTION__
, "port_num is not 0");
155 * stash the ss_bind_info supplied by the FC Transport
157 bcopy(bind_info
, &ss
->ss_bind_info
, sizeof (fc_fca_bind_info_t
));
158 ss
->ss_port
= bind_info
->port_handle
;
163 port_info
->pi_rnid_params
.status
= FC_FAILURE
;
166 * populate T11 FC-HBA details
168 fcoei_populate_hba_fru_details(ss
, port_info
);
171 * set port's current state, and it is always offline before binding
173 * We hack pi_port_state to tell LV if it's NODMA_FCA
175 port_info
->pi_port_state
= FC_STATE_FCA_IS_NODMA
;
180 bcopy(&ss
->ss_els_logi
, &port_info
->pi_login_params
,
181 sizeof (la_els_logi_t
));
186 atomic_or_32(&ss
->ss_flags
, SS_FLAG_LV_BOUND
);
189 * Let fcoe to report the link status
191 fcoei_port_enabled((void *)ss
);
193 FCOEI_LOG(__FUNCTION__
, "Exit fcoei_bind_port: %p", ss
);
199 * Un-bind the fcoei port
202 * fca_handle = fcoei soft state set in fcoei_bind_port
211 fcoei_unbind_port(void *fca_handle
)
213 fcoei_soft_state_t
*ss
= (fcoei_soft_state_t
*)fca_handle
;
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
);
222 * Initialize fcoei related part of fc_packet
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
230 * FC_SUCCESS - Initialization completed successfully
233 * Link the exchange elements with proper objects
237 fcoei_init_pkt(void *fca_handle
, fc_packet_t
*fpkt
, int sleep
)
239 fcoei_soft_state_t
*ss
= (fcoei_soft_state_t
*)fca_handle
;
240 fcoei_exchange_t
*xch
= FPKT2XCH(fpkt
);
244 xch
->xch_fpkt
= fpkt
;
251 * Uninitialize fcoei related part of fc_packet
254 * fca_handle = fcoei soft state set in fcoei_bind_port
255 * fpkt = The pointer to fc_packet
258 * FC_SUCCESS - Uninitialize successfully
261 * Very simple, just return successfully
265 fcoei_un_init_pkt(void *fca_handle
, fc_packet_t
*fpkt
)
267 ASSERT(fca_handle
&& fpkt
);
273 * Export FCA hardware and software capability.
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
281 * FC_CAP_ERROR - no such capability
282 * FC_CAP_FOUND - the capability was returned and cannot be set
285 * FC_CAP_UNSOL_BUF is one important capability, it will affect the
286 * implementation of fcoei_ub_alloc/free.
289 fcoei_get_cap(void * fca_handle
, char *cap
, void *ptr
)
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
;
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) {
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
;
313 FCOEI_LOG(__FUNCTION__
, "not supported");
321 * Allow the FC Transport to set FCA capabilities if possible
324 * fca_handle = fcoei soft state set in fcoei_bind_port
325 * cap = pointer to the capabilities string.
326 * ptr = buffer pointer for capability.
329 * FC_CAP_ERROR - no such capability
332 * Currently, all capabilities can't be changed.
335 fcoei_set_cap(void * fca_handle
, char *cap
, void *ptr
)
337 FCOEI_LOG(__FUNCTION__
, "cap: %s, %p, %p", cap
, fca_handle
, ptr
);
338 return (FC_CAP_ERROR
);
346 * fca_handle = fcoei soft state set in fcoei_bind_port
347 * mapbuf = the buffer to store lilp map
350 * FC_FAILURE - Can't get the lilp map
353 * fcoei can't work in loop topology, so it should never get called
356 fcoei_getmap(void * fca_handle
, fc_lilpmap_t
*mapbuf
)
358 FCOEI_LOG(__FUNCTION__
, "not: %p-%p", fca_handle
, mapbuf
);
364 * Pre-allocate unsolicited buffers at the request of LV
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
374 * FC_SUCCESS - The requested buffers have been freeed
377 * fcoei_get_cap will set UNSOL_BUF to 0, so it should never get called.
380 fcoei_ub_alloc(void * fca_handle
, uint64_t tokens
[], uint32_t size
,
381 uint32_t *count
, uint32_t type
)
383 FCOEI_LOG(__FUNCTION__
, "not: %p-%p-%x-%p-%x", fca_handle
, tokens
,
390 * Free the pre-allocated unsolicited buffers at the request of LV
393 * fca_handle = fcoei soft state set in fcoei_bind_port
394 * count = number of buffers.
395 * tokens = token array for each buffer.
398 * FC_SUCCESS - The requested buffers have been freeed
401 * fcoei_get_cap will set UNSOL_BUF to 0, so it should never get called.
404 fcoei_ub_free(void * fca_handle
, uint32_t count
, uint64_t tokens
[])
406 FCOEI_EXT_LOG(__FUNCTION__
, "not: %p-%x-%p", fca_handle
, count
, tokens
);
412 * Release unsolicited buffers from FC Transport to FCA for future use
415 * fca_handle = fcoei soft state set in fcoei_bind_port
416 * count = number of buffers.
417 * tokens = token array for each buffer.
420 * FC_SUCCESS - The requested buffers have been released.
421 * FC_FAILURE - The requested buffers have not been released.
424 * It will always succeed. It has nothing to do with fcoei_ub_alloc/free.
427 fcoei_ub_release(void * fca_handle
, uint32_t count
, uint64_t tokens
[])
429 fc_unsol_buf_t
*ub
= *((fc_unsol_buf_t
**)tokens
);
432 FCOEI_LOG(__FUNCTION__
, "count is not 1: %p", fca_handle
);
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");
444 * Direct FCA driver to abort an outstanding exchange associated with a
445 * specified fc_packet_t struct
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.
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.
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
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.
471 * Unfortunately, LV doesn't conform to the spec. It will take all these
472 * legal return value as failure to abort.
475 fcoei_abort(void * fca_handle
, fc_packet_t
*fpkt
, int flags
)
477 FCOEI_LOG(__FUNCTION__
, "not: %p-%p-%x", fca_handle
, fpkt
, flags
);
483 * Reset link or hardware
486 * fca_handle = fcoei soft state set in fcoei_bind_port
487 * cmd = reset type command
490 * FC_SUCCESS - Reset has completed successfully
491 * FC_FAILURE - Reset has failed
497 fcoei_reset(void * fca_handle
, uint32_t cmd
)
499 int rval
= FC_SUCCESS
;
500 fcoei_soft_state_t
*ss
= (fcoei_soft_state_t
*)fca_handle
;
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
);
512 * This is linkreset phase I
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
);
520 * Perpare linkreset phase II
522 ae
= kmem_zalloc(sizeof (*ae
), KM_SLEEP
);
523 ae
->ae_type
= AE_EVENT_RESET
;
526 mutex_enter(&ss
->ss_watchdog_mutex
);
527 list_insert_tail(&ss
->ss_event_list
, ae
);
528 mutex_exit(&ss
->ss_watchdog_mutex
);
537 case FC_FCA_RESET_CORE
:
542 FCOEI_LOG(__FUNCTION__
, "cmd-%x not supported", cmd
);
551 * Perform various port management operations at the request of LV
554 * fca_handle = fcoei soft state set in fcoei_bind_port
555 * pm = the pointer to the struct specifying the port management operation
558 * FC_SUCCESS - The request completed successfully
559 * FC_FAILURE - The request did not complete successfully
565 fcoei_port_manage(void * fca_handle
, fc_fca_pm_t
*pm
)
567 int rval
= FC_FAILURE
;
568 fcoei_soft_state_t
*ss
= (fcoei_soft_state_t
*)fca_handle
;
570 if (fca_handle
== NULL
|| pm
== NULL
) {
574 FCOEI_LOG(__FUNCTION__
, "code0x%x, %p", pm
->pm_cmd_code
, fca_handle
);
575 switch (pm
->pm_cmd_code
) {
577 case FC_PORT_GET_NODE_ID
:
579 if (pm
->pm_data_len
< sizeof (fc_rnid_t
)) {
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
));
590 case FC_PORT_SET_NODE_ID
:
592 if (pm
->pm_data_len
< sizeof (fc_rnid_t
)) {
596 bcopy(pm
->pm_data_buf
,
597 (void *)&ss
->ss_rnid
, sizeof (fc_rnid_t
));
603 FCOEI_LOG(__FUNCTION__
, "unsupported cmd-%x", pm
->pm_cmd_code
);
604 rval
= FC_INVALID_REQUEST
;
613 * Get fcoei remote port with FCID of d_id
616 * fca_handle = fcoei soft state set in fcoei_bind_port
617 * d_id = 24-bit FCID of remote port
620 * The pointer to fcoei remote port
623 * fcoei has no remote port device
626 fcoei_get_device(void *fca_handle
, fc_portid_t d_id
)
628 FCOEI_EXT_LOG(__FUNCTION__
, "not supported: %p-%x", fca_handle
, d_id
);
634 * Notify the change of target device
637 * fca_handle = fcoei soft state set in fcoei_bind_port
641 * FC_SUCCESS - Notification completed successfully
644 * It's only needed to support non-COMSTAR FC target, so it should
648 fcoei_notify(void *fca_handle
, uint32_t cmd
)
650 FCOEI_LOG(__FUNCTION__
, "not supported: %p-%x", fca_handle
, cmd
);
656 * Submit FCP/CT requests
659 * fca_handle - fcoei soft state set in fcoei_bind_port
660 * fpkt - LV fc_packet
669 fcoei_transport(void *fca_handle
, fc_packet_t
*fpkt
)
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
;
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
;
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
);
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
);
691 mutex_exit(&ss
->ss_watchdog_mutex
);
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
);
705 * Submit ELS request or response
708 * fca_handle - fcoei soft state set in fcoei_bind_port
709 * fpkt = LV fc_packet
718 fcoei_els_send(void *fca_handle
, fc_packet_t
*fpkt
)
720 fcoei_soft_state_t
*ss
= (fcoei_soft_state_t
*)fca_handle
;
721 fcoei_exchange_t
*xch
= FPKT2XCH(fpkt
);
723 if (fpkt
->pkt_tran_flags
& FC_TRAN_NO_INTR
) {
724 FCOEI_LOG(__FUNCTION__
, "ELS poll mode is not supported");
725 return (FC_BADPACKET
);
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
;
735 * LV could release ub after this call, so we must save the ub type
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];
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
);
748 mutex_exit(&ss
->ss_watchdog_mutex
);
754 * fcoei_populate_hba_fru_details
755 * Fill detailed information about HBA
758 * ss - fcoei soft state
759 * port_info = fc_fca_port_info_t that need be updated
768 fcoei_populate_hba_fru_details(fcoei_soft_state_t
*ss
,
769 fc_fca_port_info_t
*port_info
)
771 fca_port_attrs_t
*port_attrs
= &(port_info
->pi_attrs
);
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");
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);
802 * Notify fcoe that the port has been enabled
805 * arg = the related soft state
811 * Only after this, fcoe will report the link status to us
814 fcoei_port_enabled(void *arg
)
816 fcoei_soft_state_t
*ss
= (fcoei_soft_state_t
*)arg
;
818 ss
->ss_eport
->eport_ctl(ss
->ss_eport
, FCOE_CMD_PORT_ONLINE
, NULL
);
823 * fcoei_initiate_ct_req
824 * Fill and submit CT request
827 * xch - the exchange that will be initiated
836 fcoei_initiate_ct_req(fcoei_exchange_t
*xch
)
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
;
844 uint32_t cmd_len
= fpkt
->pkt_cmdlen
;
847 * Ensure it's 4-byte aligned
849 cmd_len
= P2ROUNDUP(cmd_len
, 4);
852 * Allocate CT request frame
854 frm
= xch
->xch_ss
->ss_eport
->eport_alloc_frame(xch
->xch_ss
->ss_eport
,
855 cmd_len
+ FCFH_SIZE
, NULL
);
857 FCOEI_LOG(__FUNCTION__
, "failed to alloc: %p", xch
);
861 bzero(frm
->frm_payload
, cmd_len
);
862 xch
->xch_cnt
= xch
->xch_ss
->ss_sol_cnt
;
863 atomic_inc_32(xch
->xch_cnt
);
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
);
875 * CT header (FC payload)
878 FCOE_V2B_1(ct
->ct_rev
, FPLD
+ offset
);
881 FCOE_V2B_3(ct
->ct_inid
, FPLD
+ offset
);
884 FCOE_V2B_1(ct
->ct_fcstype
, FPLD
+ offset
);
887 FCOE_V2B_1(ct
->ct_fcssubtype
, FPLD
+ offset
);
890 FCOE_V2B_1(ct
->ct_options
, FPLD
+ offset
);
893 FCOE_V2B_2(ct
->ct_cmdrsp
, FPLD
+ offset
);
896 FCOE_V2B_2(ct
->ct_aiusize
, FPLD
+ offset
);
899 FCOE_V2B_1(ct
->ct_reason
, FPLD
+ offset
);
902 FCOE_V2B_1(ct
->ct_expln
, FPLD
+ offset
);
905 FCOE_V2B_1(ct
->ct_vendor
, FPLD
+ offset
);
908 * CT payload (FC payload)
910 switch (ct
->ct_fcstype
) {
911 case FCSTYPE_DIRECTORY
:
912 switch (ct
->ct_cmdrsp
) {
924 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp
+ offset
))[0],
930 bcopy(bp
+ offset
, FPLD
+ offset
, 8);
936 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp
+ offset
))[0],
940 bcopy(bp
+ offset
, FPLD
+ offset
, 8);
945 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp
+ offset
))[0],
949 bcopy(bp
+ offset
, FPLD
+ offset
, bp
[20] + 1);
954 bcopy(bp
+ offset
, FPLD
+ offset
, 8);
957 bcopy(bp
+ offset
, FPLD
+ offset
, bp
[24] + 1);
962 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp
+ offset
))[0],
966 * fp use bcopy to copy fp_fc4_types,
967 * we need to swap order for each integer
970 for (idx
= 0; idx
< 8; idx
++) {
972 ((uint32_t *)(intptr_t)(bp
+ offset
))[0],
981 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp
+ offset
))[0],
985 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp
+ offset
))[0],
991 bcopy(bp
+ offset
, FPLD
+ offset
, 24);
995 fcoei_complete_xch(xch
, frm
, FC_PKT_FAILURE
,
996 FC_REASON_CMD_UNSUPPORTED
);
999 break; /* FCSTYPE_DIRECTORY */
1001 case FCSTYPE_MGMTSERVICE
:
1002 switch (ct
->ct_cmdrsp
) {
1004 FCOEI_LOG(__FUNCTION__
,
1005 "MS_GIEL ct_fcstype %x, ct_cmdrsp: %x",
1006 ct
->ct_fcstype
, ct
->ct_cmdrsp
);
1010 fcoei_complete_xch(xch
, frm
, FC_PKT_FAILURE
,
1011 FC_REASON_CMD_UNSUPPORTED
);
1014 break; /* FCSTYPE_MGMTSERVICE */
1017 fcoei_complete_xch(xch
, frm
, FC_PKT_FAILURE
,
1018 FC_REASON_CMD_UNSUPPORTED
);
1021 xch
->xch_ss
->ss_eport
->eport_tx_frame(frm
);
1025 * fcoei_initiate_fcp_cmd
1026 * Submit FCP command
1029 * xch - the exchange to be submitted
1038 fcoei_initiate_fcp_cmd(fcoei_exchange_t
*xch
)
1040 fc_packet_t
*fpkt
= xch
->xch_fpkt
;
1042 fcp_cmd_t
*fcp_cmd_iu
= (fcp_cmd_t
*)(void *)fpkt
->pkt_cmd
;
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
);
1051 fcoei_init_ifm(frm
, xch
);
1052 bzero(frm
->frm_payload
, fpkt
->pkt_cmdlen
);
1056 * This will affect timing check
1058 xch
->xch_cnt
= xch
->xch_ss
->ss_sol_cnt
;
1059 atomic_inc_32(xch
->xch_cnt
);
1062 * Set exchange residual bytes
1064 xch
->xch_resid
= (int)fpkt
->pkt_datalen
;
1067 * Fill FCP command IU
1071 FCOE_V2B_2(fcp_cmd_iu
->fcp_ent_addr
.ent_addr_0
,
1072 frm
->frm_payload
+ offset
);
1074 FCOE_V2B_2(fcp_cmd_iu
->fcp_ent_addr
.ent_addr_1
,
1075 frm
->frm_payload
+ offset
);
1077 FCOE_V2B_2(fcp_cmd_iu
->fcp_ent_addr
.ent_addr_2
,
1078 frm
->frm_payload
+ offset
);
1080 FCOE_V2B_2(fcp_cmd_iu
->fcp_ent_addr
.ent_addr_3
,
1081 frm
->frm_payload
+ offset
);
1085 offset
= offsetof(fcp_cmd_t
, fcp_cntl
);
1086 frm
->frm_payload
[offset
] = 0;
1089 frm
->frm_payload
[offset
] = fcp_cmd_iu
->fcp_cntl
.cntl_qtype
& 0x07;
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);
1099 frm
->frm_payload
[offset
] =
1100 (fcp_cmd_iu
->fcp_cntl
.cntl_read_data
<< 1) |
1101 (fcp_cmd_iu
->fcp_cntl
.cntl_write_data
);
1105 offset
= offsetof(fcp_cmd_t
, fcp_cdb
);
1106 bcopy(fcp_cmd_iu
->fcp_cdb
, frm
->frm_payload
+ offset
, FCP_CDB_SIZE
);
1110 offset
+= FCP_CDB_SIZE
;
1111 FCOE_V2B_4(fcp_cmd_iu
->fcp_data_len
, frm
->frm_payload
+ offset
);
1116 FRM2IFM(frm
)->ifm_rctl
= fpkt
->pkt_cmd_fhdr
.r_ctl
;
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
);
1126 xch
->xch_ss
->ss_eport
->eport_tx_frame(frm
);
1130 * fcoei_initiate_els_req
1131 * Initiate ELS request
1134 * xch = the exchange that will be initiated
1143 fcoei_initiate_els_req(fcoei_exchange_t
*xch
)
1145 fc_packet_t
*fpkt
= xch
->xch_fpkt
;
1147 ls_code_t
*els_code
;
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
);
1155 fcoei_init_ifm(frm
, xch
);
1156 bzero(frm
->frm_payload
, fpkt
->pkt_cmdlen
);
1160 * This will affect timing check
1162 xch
->xch_cnt
= xch
->xch_ss
->ss_sol_cnt
;
1163 atomic_inc_32(xch
->xch_cnt
);
1165 els_code
= (ls_code_t
*)(void *)fpkt
->pkt_cmd
;
1166 switch (els_code
->ls_code
) {
1169 * For FLOGI, we expect response within E_D_TOV
1171 xch
->xch_start_tick
= ddi_get_lbolt();
1172 xch
->xch_end_tick
= xch
->xch_start_tick
+
1174 xch
->xch_ss
->ss_flags
&= ~SS_FLAG_FLOGI_FAILED
;
1178 fcoei_fill_els_logi_cmd(fpkt
, frm
);
1182 fcoei_fill_els_prli_cmd(fpkt
, frm
);
1186 fcoei_fill_els_scr_cmd(fpkt
, frm
);
1190 fcoei_fill_els_linit_cmd(fpkt
, frm
);
1194 fcoei_fill_els_adisc_cmd(fpkt
, frm
);
1199 * For LOGO, we expect response within E_D_TOV
1201 xch
->xch_start_tick
= ddi_get_lbolt();
1202 xch
->xch_end_tick
= xch
->xch_start_tick
+
1204 fcoei_fill_els_logo_cmd(fpkt
, frm
);
1207 fcoei_fill_els_rls_cmd(fpkt
, frm
);
1210 fcoei_fill_els_rnid_cmd(fpkt
, frm
);
1213 fcoei_complete_xch(xch
, frm
, FC_PKT_FAILURE
,
1214 FC_REASON_CMD_UNSUPPORTED
);
1221 FRM2IFM(frm
)->ifm_rctl
= fpkt
->pkt_cmd_fhdr
.r_ctl
;
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
);
1234 xch
->xch_ss
->ss_eport
->eport_tx_frame(frm
);
1238 * fcoei_initiate_els_resp
1239 * Originate ELS response
1242 * xch = the associated exchange
1251 fcoei_initiate_els_resp(fcoei_exchange_t
*xch
)
1253 fc_packet_t
*fpkt
= xch
->xch_fpkt
;
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
);
1262 fcoei_init_ifm(frm
, xch
);
1263 bzero(frm
->frm_payload
, fpkt
->pkt_cmdlen
);
1267 * This will affect timing check
1269 xch
->xch_cnt
= xch
->xch_ss
->ss_unsol_cnt
;
1270 atomic_inc_32(xch
->xch_cnt
);
1275 FRM2IFM(frm
)->ifm_rctl
= fpkt
->pkt_cmd_fhdr
.r_ctl
;
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
);
1288 switch (((uint8_t *)&fpkt
->pkt_fca_rsvd1
)[0]) {
1290 fcoei_fill_els_logi_resp(fpkt
, frm
);
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
);
1300 fcoei_fill_els_logi_resp(fpkt
, frm
);
1304 fcoei_fill_els_prli_resp(fpkt
, frm
);
1308 fcoei_fill_els_adisc_resp(fpkt
, frm
);
1312 fcoei_fill_els_logo_resp(fpkt
, frm
);
1315 fcoei_fill_els_acc_resp(fpkt
, frm
);
1319 fcoei_complete_xch(xch
, frm
, FC_PKT_FAILURE
,
1320 FC_REASON_CMD_UNSUPPORTED
);
1324 xch
->xch_ss
->ss_eport
->eport_tx_frame(frm
);
1328 * fcoei_fill_els_logi_cmd
1329 * Fill SCR (state change register) command frame
1332 * fpkt = LV fc_packet
1333 * frm = Unsolicited frame containing LOGI response
1342 fcoei_fill_els_logi_cmd(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1344 la_els_logi_t
*els_logi
= (la_els_logi_t
*)(void *)fpkt
->pkt_cmd
;
1351 FCOE_V2B_1(els_logi
->ls_code
.ls_code
, FPLD
+ offset
);
1354 * fill common service parameters
1357 FCOE_V2B_2(els_logi
->common_service
.fcph_version
, FPLD
+ offset
);
1360 FCOE_V2B_2(els_logi
->common_service
.btob_credit
, FPLD
+ offset
);
1363 FCOE_V2B_2(els_logi
->common_service
.cmn_features
, FPLD
+ offset
);
1366 FCOE_V2B_2(els_logi
->common_service
.rx_bufsize
, FPLD
+ offset
);
1369 FCOE_V2B_2(els_logi
->common_service
.conc_sequences
, FPLD
+ offset
);
1372 FCOE_V2B_2(els_logi
->common_service
.relative_offset
, FPLD
+ offset
);
1375 FCOE_V2B_4(els_logi
->common_service
.e_d_tov
, FPLD
+ offset
);
1381 bcopy(&els_logi
->nport_ww_name
, FPLD
+ offset
, 8);
1384 bcopy(&els_logi
->node_ww_name
, FPLD
+ offset
, 8);
1390 FCOE_V2B_2(els_logi
->class_3
.class_opt
, FPLD
+ offset
);
1393 FCOE_V2B_2(els_logi
->class_3
.initiator_ctl
, FPLD
+ offset
);
1396 FCOE_V2B_2(els_logi
->class_3
.recipient_ctl
, FPLD
+ offset
);
1399 FCOE_V2B_2(els_logi
->class_3
.rcv_size
, FPLD
+ offset
);
1402 FCOE_V2B_2(els_logi
->class_3
.conc_sequences
, FPLD
+ offset
);
1405 FCOE_V2B_2(els_logi
->class_3
.n_port_e_to_e_credit
, FPLD
+ offset
);
1408 FCOE_V2B_2(els_logi
->class_3
.open_seq_per_xchng
, FPLD
+ offset
);
1410 * needn't touch other fields
1415 * fcoei_fill_prli_cmd
1416 * Fill PRLI command frame
1419 * fpkt = LV fc_packet
1420 * frm = Unsolicited frame containing PRLI response
1429 fcoei_fill_els_prli_cmd(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
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
;
1437 * fill basic PRLI fields
1440 FCOE_V2B_1(els_prli
->ls_code
, FPLD
+ offset
);
1443 FCOE_V2B_1(els_prli
->page_length
, FPLD
+ offset
);
1446 FCOE_V2B_2(els_prli
->payload_length
, FPLD
+ offset
);
1449 * fill FCP service parameters page
1452 FCOE_V2B_1(fcp_spp
->type
, FPLD
+ offset
);
1455 * PRLI flags, only 3 bits are valid
1459 FCOE_V2B_2(((fcp_spp
->orig_process_assoc_valid
<< 15) |
1460 (fcp_spp
->resp_process_assoc_valid
<< 14) |
1461 (fcp_spp
->establish_image_pair
<< 13)), FPLD
+ offset
);
1464 * process associator
1467 FCOE_V2B_4(fcp_spp
->orig_process_associator
, FPLD
+ offset
);
1470 FCOE_V2B_4(fcp_spp
->resp_process_associator
, FPLD
+ offset
);
1476 FCOE_V2B_4((fcp_spp
->retry
<< 8) |
1477 (fcp_spp
->confirmed_compl_allowed
<< 7) |
1478 (fcp_spp
->data_overlay_allowed
<< 6) |
1479 (fcp_spp
->initiator_fn
<< 5) | (fcp_spp
->target_fn
<< 4) |
1480 (fcp_spp
->read_xfer_rdy_disabled
<< 1) |
1481 (fcp_spp
->write_xfer_rdy_disabled
), FPLD
+ offset
);
1485 * fcoei_fill_els_scr_cmd
1486 * Fill SCR (state change register) command frame
1489 * fpkt = LV fc_packet
1490 * frm = Unsolicited frame containing SCR command
1499 fcoei_fill_els_scr_cmd(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1501 fc_scr_req_t
*els_scr
= (fc_scr_req_t
*)(void *)fpkt
->pkt_cmd
;
1505 FCOE_V2B_1(els_scr
->ls_code
.ls_code
, FPLD
+ offset
);
1508 FCOE_V2B_1(els_scr
->scr_func
, FPLD
+ offset
);
1512 * fcoei_fill_els_adisc_cmd
1513 * Fill ADISC command frame
1516 * fpkt = LV fc_packet
1517 * frm = Unsolicited frame containing ADISC command
1526 fcoei_fill_els_adisc_cmd(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1528 la_els_adisc_t
*els_adisc
= (la_els_adisc_t
*)(void *)fpkt
->pkt_cmd
;
1532 FCOE_V2B_1(els_adisc
->ls_code
.ls_code
, FPLD
+ offset
);
1535 FCOE_V2B_3(els_adisc
->hard_addr
.hard_addr
, FPLD
+ offset
);
1538 bcopy(&els_adisc
->port_wwn
, FPLD
+ offset
, 8);
1541 bcopy(&els_adisc
->node_wwn
, FPLD
+ offset
, 8);
1544 FCOE_V2B_3(els_adisc
->nport_id
.port_id
, FPLD
+ offset
);
1548 * fcoei_fill_els_linit_cmd
1549 * Fill LINIT command frame
1552 * fpkt = LV fc_packet
1553 * frm = Unsolicited frame containing LINIT command
1563 fcoei_fill_els_linit_cmd(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1565 ASSERT(fpkt
&& frm
);
1569 * fcoei_fill_els_logo_cmd
1570 * Fill LOGO command frame
1573 * fpkt = LV fc_packet
1574 * frm = Unsolicited frame containing LOGO command
1583 fcoei_fill_els_logo_cmd(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1585 la_els_logo_t
*els_logo
= (la_els_logo_t
*)(void *)fpkt
->pkt_cmd
;
1589 FCOE_V2B_1(els_logo
->ls_code
.ls_code
, FPLD
+ offset
);
1592 FCOE_V2B_3(els_logo
->nport_id
.port_id
, FPLD
+ offset
);
1595 bcopy(&els_logo
->nport_ww_name
, FPLD
+ offset
, 8);
1599 fcoei_fill_els_rls_cmd(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1601 la_els_rls_t
*els_rls
= (la_els_rls_t
*)(void *)fpkt
->pkt_cmd
;
1605 FCOE_V2B_1(els_rls
->ls_code
.ls_code
, FPLD
+ offset
);
1608 FCOE_V2B_3(els_rls
->rls_portid
.port_id
, FPLD
+ offset
);
1612 fcoei_fill_els_rnid_cmd(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1614 la_els_rnid_t
*els_rnid
= (la_els_rnid_t
*)(void *)fpkt
->pkt_cmd
;
1618 FCOE_V2B_1(els_rnid
->ls_code
.ls_code
, FPLD
+ offset
);
1621 bcopy(&els_rnid
->data_format
, FPLD
+ offset
, 1);
1624 * fcoei_fill_els_acc_resp
1625 * Fill ELS ACC response frame
1628 * fpkt = LV fc_packet
1629 * frm = Unsolicited frame containing ELS ACC response
1638 fcoei_fill_els_acc_resp(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1640 ls_code_t
*els_code
= (ls_code_t
*)(void *)fpkt
->pkt_cmd
;
1644 FCOE_V2B_1(els_code
->ls_code
, FPLD
+ offset
);
1647 FCOE_V2B_3(els_code
->mbz
, FPLD
+ offset
);
1651 * fcoei_fill_els_rjt_resp
1652 * Fill ELS RJT response frame
1655 * fpkt = LV fc_packet
1656 * frm = Unsolicited frame containg ELS RJT response
1665 fcoei_fill_els_rjt_resp(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1667 la_els_rjt_t
*els_rjt
= (la_els_rjt_t
*)(void *)fpkt
->pkt_cmd
;
1670 offset
= 0; /* reset ls code */
1671 FCOE_V2B_1(els_rjt
->ls_code
.ls_code
, FPLD
+ offset
);
1673 offset
= 5; /* reason code */
1674 FCOE_V2B_1(els_rjt
->action
, FPLD
+ offset
);
1676 offset
= 6; /* reason explanation */
1677 FCOE_V2B_1(els_rjt
->reason
, FPLD
+ offset
);
1679 offset
= 7; /* vendor unique */
1680 FCOE_V2B_1(els_rjt
->vu
, FPLD
+ offset
);
1684 * fcoei_fill_els_adisc_resp
1685 * Fill ADISC response frame
1688 * fpkt = LV fc_packet
1689 * frm = Unsolicited frame containing ADISC response
1698 fcoei_fill_els_adisc_resp(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1700 la_els_adisc_t
*els_adisc
= (la_els_adisc_t
*)(void *)fpkt
->pkt_cmd
;
1703 if (els_adisc
->ls_code
.ls_code
== LA_ELS_RJT
) {
1704 fcoei_fill_els_rjt_resp(fpkt
, frm
);
1707 FCOE_V2B_1(els_adisc
->ls_code
.ls_code
, FPLD
+ offset
);
1710 FCOE_V2B_3(els_adisc
->hard_addr
.hard_addr
, FPLD
+ offset
);
1713 bcopy(&els_adisc
->port_wwn
, FPLD
+ offset
, FC_WWN_SIZE
);
1716 bcopy(&els_adisc
->node_wwn
, FPLD
+ offset
, FC_WWN_SIZE
);
1719 FCOE_V2B_3(els_adisc
->nport_id
.port_id
, FPLD
+ offset
);
1724 * fcoei_fill_els_logi_resp
1725 * Fill FLOGI/PLOGI response frame
1728 * fpkt = LV fc_packet
1729 * frm = Unsolicited frame containing LOGI response
1738 fcoei_fill_els_logi_resp(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1740 ls_code_t
*els_code
= (ls_code_t
*)(void *)fpkt
->pkt_cmd
;
1742 if (els_code
->ls_code
== LA_ELS_RJT
) {
1743 fcoei_fill_els_rjt_resp(fpkt
, frm
);
1745 fcoei_fill_els_logi_cmd(fpkt
, frm
);
1750 * fcoei_fill_els_prli_resp
1751 * Fill PRLI response frame
1754 * fpkt = LV fc_packet
1755 * frm = Unsolicited frame containing PRLI response
1764 fcoei_fill_els_prli_resp(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1766 ls_code_t
*els_code
= (ls_code_t
*)(void *)fpkt
->pkt_cmd
;
1768 if (els_code
->ls_code
== LA_ELS_RJT
) {
1769 fcoei_fill_els_rjt_resp(fpkt
, frm
);
1771 fcoei_fill_els_prli_cmd(fpkt
, frm
);
1776 * fcoei_fill_els_logo_resp
1777 * Fill LOGO response frame
1780 * fpkt = LV fc_packet
1781 * frm = Unsolicited frame containing LOGO response
1790 fcoei_fill_els_logo_resp(fc_packet_t
*fpkt
, fcoe_frame_t
*frm
)
1792 ls_code_t
*els_code
= (ls_code_t
*)(void *)fpkt
->pkt_cmd
;
1794 if (els_code
->ls_code
== LA_ELS_RJT
) {
1795 fcoei_fill_els_rjt_resp(fpkt
, frm
);
1797 fcoei_fill_els_acc_resp(fpkt
, frm
);
1803 * Send LOGO to the peer to emulate link offline event
1806 * arg - fcoei soft state set in fcoei_bind_port
1815 fcoei_logo_peer(void *arg
)
1817 fcoei_soft_state_t
*ss
= (fcoei_soft_state_t
*)arg
;
1819 fcoei_exchange_t
*xch
;
1820 la_els_logo_t
*els_logo
;
1823 * Allocate space for exchange
1825 xch
= kmem_zalloc(sizeof (*xch
), KM_SLEEP
);
1828 * Allocate space for fc_packet
1830 fpkt
= kmem_zalloc(sizeof (fc_packet_t
), KM_SLEEP
);
1831 fpkt
->pkt_cmdlen
= 20;
1832 fpkt
->pkt_cmd
= kmem_zalloc(fpkt
->pkt_cmdlen
, KM_SLEEP
);
1833 fpkt
->pkt_rsplen
= 20;
1834 fpkt
->pkt_resp
= kmem_zalloc(fpkt
->pkt_rsplen
, KM_SLEEP
);
1837 * Link them together
1839 fpkt
->pkt_fca_private
= xch
;
1840 (void) fcoei_init_pkt(ss
, fpkt
, 0);
1843 * Initialize FC frame header
1845 if (ss
->ss_eport
->eport_flags
& EPORT_FLAG_IS_DIRECT_P2P
) {
1846 fpkt
->pkt_cmd_fhdr
.d_id
= ss
->ss_p2p_info
.d_id
;
1848 fpkt
->pkt_cmd_fhdr
.d_id
= 0xFFFFFE;
1851 fpkt
->pkt_cmd_fhdr
.s_id
= ss
->ss_p2p_info
.fca_d_id
;
1852 fpkt
->pkt_cmd_fhdr
.r_ctl
= R_CTL_ELS_REQ
;
1853 fpkt
->pkt_cmd_fhdr
.type
= FC_TYPE_EXTENDED_LS
;
1854 fpkt
->pkt_cmd_fhdr
.f_ctl
= 0x290000;
1855 fpkt
->pkt_timeout
= 1;
1858 * Initialize LOGO payload
1860 els_logo
= (la_els_logo_t
*)(void *)fpkt
->pkt_cmd
;
1861 els_logo
->ls_code
.ls_code
= LA_ELS_LOGO
;
1862 els_logo
->nport_id
.port_id
= ss
->ss_p2p_info
.fca_d_id
;
1863 bcopy(ss
->ss_eport
->eport_portwwn
, &els_logo
->nport_ww_name
, 8);
1866 * Set the completion function
1868 fpkt
->pkt_comp
= fcoei_fpkt_comp
;
1869 if (fcoei_transport(ss
, fpkt
) != FC_SUCCESS
) {
1870 FCOEI_LOG(__FUNCTION__
, "fcoei_transport LOGO failed");
1871 fcoei_fpkt_comp(fpkt
);
1877 * internal exchange completion
1880 * fpkt - fc_packet_t to be completed
1889 fcoei_fpkt_comp(fc_packet_t
*fpkt
)
1891 fcoei_exchange_t
*xch
= FPKT2XCH(fpkt
);
1893 FCOEI_LOG(__FUNCTION__
, "internal exchange is completed: %p", xch
);
1895 (void) fcoei_un_init_pkt(xch
->xch_ss
, xch
->xch_fpkt
);
1896 kmem_free(xch
->xch_fpkt
->pkt_cmd
, xch
->xch_fpkt
->pkt_cmdlen
);
1897 kmem_free(xch
->xch_fpkt
->pkt_resp
, xch
->xch_fpkt
->pkt_rsplen
);
1898 kmem_free(xch
->xch_fpkt
, sizeof (fc_packet_t
));
1899 kmem_free(xch
, sizeof (fcoei_exchange_t
));
1904 * Prepare to abort the exchange
1907 * key = oxid/rxid of the exchange
1908 * val = the exchange
1909 * arg = the soft state
1912 * MH_WALK_CONTINUE = continue to walk
1919 fcoei_xch_abort(mod_hash_key_t key
, mod_hash_val_t
*val
, void *arg
)
1921 fcoei_exchange_t
*xch
= (fcoei_exchange_t
*)val
;
1923 ASSERT(arg
== xch
->xch_ss
);
1924 ASSERT(CMHK(key
) != 0xFFFF);
1925 xch
->xch_flags
|= XCH_FLAG_ABORT
;
1926 xch
->xch_fpkt
->pkt_state
= FC_PKT_LOCAL_RJT
;
1927 xch
->xch_fpkt
->pkt_reason
= FC_REASON_OFFLINE
;
1928 list_insert_tail(&xch
->xch_ss
->ss_comp_xch_list
, xch
);
1929 return (MH_WALK_CONTINUE
);
1933 * fcoei_init_fcatran_vectors
1934 * Initialize fc_fca_tran vectors that are defined in this file
1937 * fcatran - fc_fca_tran of the soft state
1946 fcoei_init_fcatran_vectors(fc_fca_tran_t
*fcatran
)
1948 fcatran
->fca_bind_port
= fcoei_bind_port
;
1949 fcatran
->fca_unbind_port
= fcoei_unbind_port
;
1950 fcatran
->fca_init_pkt
= fcoei_init_pkt
;
1951 fcatran
->fca_un_init_pkt
= fcoei_un_init_pkt
;
1952 fcatran
->fca_els_send
= fcoei_els_send
;
1953 fcatran
->fca_get_cap
= fcoei_get_cap
;
1954 fcatran
->fca_set_cap
= fcoei_set_cap
;
1955 fcatran
->fca_getmap
= fcoei_getmap
;
1956 fcatran
->fca_transport
= fcoei_transport
;
1957 fcatran
->fca_ub_alloc
= fcoei_ub_alloc
;
1958 fcatran
->fca_ub_free
= fcoei_ub_free
;
1959 fcatran
->fca_ub_release
= fcoei_ub_release
;
1960 fcatran
->fca_abort
= fcoei_abort
;
1961 fcatran
->fca_reset
= fcoei_reset
;
1962 fcatran
->fca_port_manage
= fcoei_port_manage
;
1963 fcatran
->fca_get_device
= fcoei_get_device
;
1964 fcatran
->fca_notify
= fcoei_notify
;
1968 * fcoei_process_event_reset
1969 * link reset phase II
1972 * arg - fcoei soft state set in fcoei_bind_port
1981 fcoei_process_event_reset(fcoei_event_t
*ae
)
1983 fcoei_soft_state_t
*ss
= (fcoei_soft_state_t
*)ae
->ae_obj
;
1985 ASSERT(!MUTEX_HELD(&ss
->ss_watchdog_mutex
));
1986 kmem_free(ae
, sizeof (*ae
));
1988 mod_hash_walk(ss
->ss_sol_oxid_hash
, fcoei_xch_abort
, ss
);
1989 mod_hash_walk(ss
->ss_unsol_rxid_hash
, fcoei_xch_abort
, ss
);
1990 fcoei_handle_comp_xch_list(ss
);
1993 * Notify LV that the link is up now
1995 ss
->ss_eport
->eport_ctl(ss
->ss_eport
, FCOE_CMD_PORT_ONLINE
, 0);
1999 * fcoei_process_event_exchange
2000 * Process exchange in the single thread context
2003 * ae = the exchange event
2012 fcoei_process_event_exchange(fcoei_event_t
*ae
)
2014 fcoei_exchange_t
*xch
= (fcoei_exchange_t
*)ae
->ae_obj
;
2015 fcoei_exchange_t
*xch_tmp
;
2016 fc_packet_t
*fpkt
= xch
->xch_fpkt
;
2019 * These 4 elements need reset, pkt_state & pkt_reason will be set
2021 fpkt
->pkt_action
= 0;
2022 fpkt
->pkt_expln
= 0;
2023 fpkt
->pkt_data_resid
= 0;
2024 fpkt
->pkt_resp_resid
= 0;
2027 * port state sanity checking
2029 if ((xch
->xch_ss
->ss_link_state
!= FC_STATE_ONLINE
) ||
2030 xch
->xch_ss
->ss_port_event_counter
) {
2032 * LV will retry it after one second
2034 fcoei_complete_xch(xch
, NULL
, FC_PKT_PORT_OFFLINE
,
2039 switch (fpkt
->pkt_cmd_fhdr
.r_ctl
) {
2041 FCOEI_INIT_SOL_ID_HASH(xch
, xch_tmp
);
2042 fcoei_initiate_fcp_cmd(xch
);
2046 FCOEI_INIT_SOL_ID_HASH(xch
, xch_tmp
);
2047 fcoei_initiate_els_req(xch
);
2050 case R_CTL_UNSOL_CONTROL
:
2051 FCOEI_INIT_SOL_ID_HASH(xch
, xch_tmp
);
2052 fcoei_initiate_ct_req(xch
);
2057 * Caution: in leadville, it still uses pkt_cmd_fhdr
2058 * oxid & rxid have been decided when we get unsolicited frames.
2059 * pkt_cmd_fhdr has contained the right oxid and rxid now.
2061 FCOEI_INIT_UNSOL_ID_HASH(xch
);
2062 fcoei_initiate_els_resp(xch
);
2066 fcoei_complete_xch(xch
, NULL
, FC_PKT_FAILURE
,
2067 FC_REASON_CMD_UNSUPPORTED
);