xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/fca/fcoei/fcoei_lv.c (revision a8f5dec3ef73cc0bafb200f4f554dc1a6ac0a12f)
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