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 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);
1462
1463 /*
1464 * process associator
1465 */
1466 offset = 8;
1467 FCOE_V2B_4(fcp_spp->orig_process_associator, FPLD + offset);
1468
1469 offset = 12;
1470 FCOE_V2B_4(fcp_spp->resp_process_associator, FPLD + offset);
1471
1472 /*
1473 * FC-4 type
1474 */
1475 offset = 16;
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);
1482 }
1483
1484 /*
1485 * fcoei_fill_els_scr_cmd
1486 * Fill SCR (state change register) command frame
1487 *
1488 * Input:
1489 * fpkt = LV fc_packet
1490 * frm = Unsolicited frame containing SCR command
1491 *
1492 * Returns:
1493 * N/A
1494 *
1495 * Comments:
1496 * N/A
1497 */
1498 static void
fcoei_fill_els_scr_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1499 fcoei_fill_els_scr_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1500 {
1501 fc_scr_req_t *els_scr = (fc_scr_req_t *)(void *)fpkt->pkt_cmd;
1502 int offset;
1503
1504 offset = 0;
1505 FCOE_V2B_1(els_scr->ls_code.ls_code, FPLD + offset);
1506
1507 offset = 7;
1508 FCOE_V2B_1(els_scr->scr_func, FPLD + offset);
1509 }
1510
1511 /*
1512 * fcoei_fill_els_adisc_cmd
1513 * Fill ADISC command frame
1514 *
1515 * Input:
1516 * fpkt = LV fc_packet
1517 * frm = Unsolicited frame containing ADISC command
1518 *
1519 * Returns:
1520 * N/A
1521 *
1522 * Comments:
1523 * N/A
1524 */
1525 static void
fcoei_fill_els_adisc_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1526 fcoei_fill_els_adisc_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1527 {
1528 la_els_adisc_t *els_adisc = (la_els_adisc_t *)(void *)fpkt->pkt_cmd;
1529 int offset;
1530
1531 offset = 0;
1532 FCOE_V2B_1(els_adisc->ls_code.ls_code, FPLD + offset);
1533
1534 offset = 5;
1535 FCOE_V2B_3(els_adisc->hard_addr.hard_addr, FPLD + offset);
1536
1537 offset = 8;
1538 bcopy(&els_adisc->port_wwn, FPLD + offset, 8);
1539
1540 offset = 16;
1541 bcopy(&els_adisc->node_wwn, FPLD + offset, 8);
1542
1543 offset = 25;
1544 FCOE_V2B_3(els_adisc->nport_id.port_id, FPLD + offset);
1545 }
1546
1547 /*
1548 * fcoei_fill_els_linit_cmd
1549 * Fill LINIT command frame
1550 *
1551 * Input:
1552 * fpkt = LV fc_packet
1553 * frm = Unsolicited frame containing LINIT command
1554 *
1555 * Returns:
1556 * N/A
1557 *
1558 * Comments:
1559 * N/A
1560 */
1561 /* ARGSUSED */
1562 static void
fcoei_fill_els_linit_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1563 fcoei_fill_els_linit_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1564 {
1565 ASSERT(fpkt && frm);
1566 }
1567
1568 /*
1569 * fcoei_fill_els_logo_cmd
1570 * Fill LOGO command frame
1571 *
1572 * Input:
1573 * fpkt = LV fc_packet
1574 * frm = Unsolicited frame containing LOGO command
1575 *
1576 * Returns:
1577 * N/A
1578 *
1579 * Comments:
1580 * N/A
1581 */
1582 static void
fcoei_fill_els_logo_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1583 fcoei_fill_els_logo_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1584 {
1585 la_els_logo_t *els_logo = (la_els_logo_t *)(void *)fpkt->pkt_cmd;
1586 int offset;
1587
1588 offset = 0;
1589 FCOE_V2B_1(els_logo->ls_code.ls_code, FPLD + offset);
1590
1591 offset = 5;
1592 FCOE_V2B_3(els_logo->nport_id.port_id, FPLD + offset);
1593
1594 offset = 8;
1595 bcopy(&els_logo->nport_ww_name, FPLD + offset, 8);
1596 }
1597
1598 static void
fcoei_fill_els_rls_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1599 fcoei_fill_els_rls_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1600 {
1601 la_els_rls_t *els_rls = (la_els_rls_t *)(void *)fpkt->pkt_cmd;
1602 int offset;
1603
1604 offset = 0;
1605 FCOE_V2B_1(els_rls->ls_code.ls_code, FPLD + offset);
1606
1607 offset = 5;
1608 FCOE_V2B_3(els_rls->rls_portid.port_id, FPLD + offset);
1609 }
1610
1611 static void
fcoei_fill_els_rnid_cmd(fc_packet_t * fpkt,fcoe_frame_t * frm)1612 fcoei_fill_els_rnid_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm)
1613 {
1614 la_els_rnid_t *els_rnid = (la_els_rnid_t *)(void *)fpkt->pkt_cmd;
1615 int offset;
1616
1617 offset = 0;
1618 FCOE_V2B_1(els_rnid->ls_code.ls_code, FPLD + offset);
1619
1620 offset = 4;
1621 bcopy(&els_rnid->data_format, FPLD + offset, 1);
1622 }
1623 /*
1624 * fcoei_fill_els_acc_resp
1625 * Fill ELS ACC response frame
1626 *
1627 * Input:
1628 * fpkt = LV fc_packet
1629 * frm = Unsolicited frame containing ELS ACC response
1630 *
1631 * Returns:
1632 * N/A
1633 *
1634 * Comments:
1635 * N/A
1636 */
1637 static void
fcoei_fill_els_acc_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1638 fcoei_fill_els_acc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1639 {
1640 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1641 int offset;
1642
1643 offset = 0;
1644 FCOE_V2B_1(els_code->ls_code, FPLD + offset);
1645
1646 offset = 1;
1647 FCOE_V2B_3(els_code->mbz, FPLD + offset);
1648 }
1649
1650 /*
1651 * fcoei_fill_els_rjt_resp
1652 * Fill ELS RJT response frame
1653 *
1654 * Input:
1655 * fpkt = LV fc_packet
1656 * frm = Unsolicited frame containg ELS RJT response
1657 *
1658 * Returns:
1659 * N/A
1660 *
1661 * Comments:
1662 * N/A
1663 */
1664 static void
fcoei_fill_els_rjt_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1665 fcoei_fill_els_rjt_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1666 {
1667 la_els_rjt_t *els_rjt = (la_els_rjt_t *)(void *)fpkt->pkt_cmd;
1668 int offset;
1669
1670 offset = 0; /* reset ls code */
1671 FCOE_V2B_1(els_rjt->ls_code.ls_code, FPLD + offset);
1672
1673 offset = 5; /* reason code */
1674 FCOE_V2B_1(els_rjt->action, FPLD + offset);
1675
1676 offset = 6; /* reason explanation */
1677 FCOE_V2B_1(els_rjt->reason, FPLD + offset);
1678
1679 offset = 7; /* vendor unique */
1680 FCOE_V2B_1(els_rjt->vu, FPLD + offset);
1681 }
1682
1683 /*
1684 * fcoei_fill_els_adisc_resp
1685 * Fill ADISC response frame
1686 *
1687 * Input:
1688 * fpkt = LV fc_packet
1689 * frm = Unsolicited frame containing ADISC response
1690 *
1691 * Returns:
1692 * N/A
1693 *
1694 * Comments:
1695 * N/A
1696 */
1697 static void
fcoei_fill_els_adisc_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1698 fcoei_fill_els_adisc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1699 {
1700 la_els_adisc_t *els_adisc = (la_els_adisc_t *)(void *)fpkt->pkt_cmd;
1701 int offset;
1702
1703 if (els_adisc->ls_code.ls_code == LA_ELS_RJT) {
1704 fcoei_fill_els_rjt_resp(fpkt, frm);
1705 } else {
1706 offset = 0;
1707 FCOE_V2B_1(els_adisc->ls_code.ls_code, FPLD + offset);
1708
1709 offset = 5;
1710 FCOE_V2B_3(els_adisc->hard_addr.hard_addr, FPLD + offset);
1711
1712 offset = 8;
1713 bcopy(&els_adisc->port_wwn, FPLD + offset, FC_WWN_SIZE);
1714
1715 offset = 16;
1716 bcopy(&els_adisc->node_wwn, FPLD + offset, FC_WWN_SIZE);
1717
1718 offset = 25;
1719 FCOE_V2B_3(els_adisc->nport_id.port_id, FPLD + offset);
1720 }
1721 }
1722
1723 /*
1724 * fcoei_fill_els_logi_resp
1725 * Fill FLOGI/PLOGI response frame
1726 *
1727 * Input:
1728 * fpkt = LV fc_packet
1729 * frm = Unsolicited frame containing LOGI response
1730 *
1731 * Returns:
1732 * N/A
1733 *
1734 * Comments:
1735 * N/A
1736 */
1737 static void
fcoei_fill_els_logi_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1738 fcoei_fill_els_logi_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1739 {
1740 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1741
1742 if (els_code->ls_code == LA_ELS_RJT) {
1743 fcoei_fill_els_rjt_resp(fpkt, frm);
1744 } else {
1745 fcoei_fill_els_logi_cmd(fpkt, frm);
1746 }
1747 }
1748
1749 /*
1750 * fcoei_fill_els_prli_resp
1751 * Fill PRLI response frame
1752 *
1753 * Input:
1754 * fpkt = LV fc_packet
1755 * frm = Unsolicited frame containing PRLI response
1756 *
1757 * Returns:
1758 * N/A
1759 *
1760 * Comments:
1761 * N/A
1762 */
1763 static void
fcoei_fill_els_prli_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1764 fcoei_fill_els_prli_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1765 {
1766 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1767
1768 if (els_code->ls_code == LA_ELS_RJT) {
1769 fcoei_fill_els_rjt_resp(fpkt, frm);
1770 } else {
1771 fcoei_fill_els_prli_cmd(fpkt, frm);
1772 }
1773 }
1774
1775 /*
1776 * fcoei_fill_els_logo_resp
1777 * Fill LOGO response frame
1778 *
1779 * Input:
1780 * fpkt = LV fc_packet
1781 * frm = Unsolicited frame containing LOGO response
1782 *
1783 * Returns:
1784 * N/A
1785 *
1786 * Comments:
1787 * N/A
1788 */
1789 static void
fcoei_fill_els_logo_resp(fc_packet_t * fpkt,fcoe_frame_t * frm)1790 fcoei_fill_els_logo_resp(fc_packet_t *fpkt, fcoe_frame_t *frm)
1791 {
1792 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd;
1793
1794 if (els_code->ls_code == LA_ELS_RJT) {
1795 fcoei_fill_els_rjt_resp(fpkt, frm);
1796 } else {
1797 fcoei_fill_els_acc_resp(fpkt, frm);
1798 }
1799 }
1800
1801 /*
1802 * fcoei_logo_peer
1803 * Send LOGO to the peer to emulate link offline event
1804 *
1805 * Input:
1806 * arg - fcoei soft state set in fcoei_bind_port
1807 *
1808 * Returns:
1809 * N/A
1810 *
1811 * Comments:
1812 * N/A
1813 */
1814 static void
fcoei_logo_peer(void * arg)1815 fcoei_logo_peer(void *arg)
1816 {
1817 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)arg;
1818 fc_packet_t *fpkt;
1819 fcoei_exchange_t *xch;
1820 la_els_logo_t *els_logo;
1821
1822 /*
1823 * Allocate space for exchange
1824 */
1825 xch = kmem_zalloc(sizeof (*xch), KM_SLEEP);
1826
1827 /*
1828 * Allocate space for fc_packet
1829 */
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);
1835
1836 /*
1837 * Link them together
1838 */
1839 fpkt->pkt_fca_private = xch;
1840 (void) fcoei_init_pkt(ss, fpkt, 0);
1841
1842 /*
1843 * Initialize FC frame header
1844 */
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;
1847 } else {
1848 fpkt->pkt_cmd_fhdr.d_id = 0xFFFFFE;
1849 }
1850
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;
1856
1857 /*
1858 * Initialize LOGO payload
1859 */
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);
1864
1865 /*
1866 * Set the completion function
1867 */
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);
1872 }
1873 }
1874
1875 /*
1876 * fcoei_fpkt_comp
1877 * internal exchange completion
1878 *
1879 * Input:
1880 * fpkt - fc_packet_t to be completed
1881 *
1882 * Returns:
1883 * N/A
1884 *
1885 * Comments:
1886 *
1887 */
1888 static void
fcoei_fpkt_comp(fc_packet_t * fpkt)1889 fcoei_fpkt_comp(fc_packet_t *fpkt)
1890 {
1891 fcoei_exchange_t *xch = FPKT2XCH(fpkt);
1892
1893 FCOEI_LOG(__FUNCTION__, "internal exchange is completed: %p", xch);
1894
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));
1900 }
1901
1902 /*
1903 * fcoei_xch_abort
1904 * Prepare to abort the exchange
1905 *
1906 * Input:
1907 * key = oxid/rxid of the exchange
1908 * val = the exchange
1909 * arg = the soft state
1910 *
1911 * Returns:
1912 * MH_WALK_CONTINUE = continue to walk
1913 *
1914 * Comments:
1915 * N/A
1916 */
1917 /* ARGSUSED */
1918 static uint32_t
fcoei_xch_abort(mod_hash_key_t key,mod_hash_val_t * val,void * arg)1919 fcoei_xch_abort(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
1920 {
1921 fcoei_exchange_t *xch = (fcoei_exchange_t *)val;
1922
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);
1930 }
1931
1932 /*
1933 * fcoei_init_fcatran_vectors
1934 * Initialize fc_fca_tran vectors that are defined in this file
1935 *
1936 * Input:
1937 * fcatran - fc_fca_tran of the soft state
1938 *
1939 * Returns:
1940 * N/A
1941 *
1942 * Comments:
1943 * N/A
1944 */
1945 void
fcoei_init_fcatran_vectors(fc_fca_tran_t * fcatran)1946 fcoei_init_fcatran_vectors(fc_fca_tran_t *fcatran)
1947 {
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;
1965 }
1966
1967 /*
1968 * fcoei_process_event_reset
1969 * link reset phase II
1970 *
1971 * Input:
1972 * arg - fcoei soft state set in fcoei_bind_port
1973 *
1974 * Returns:
1975 * N/A
1976 *
1977 * Comments:
1978 *
1979 */
1980 void
fcoei_process_event_reset(fcoei_event_t * ae)1981 fcoei_process_event_reset(fcoei_event_t *ae)
1982 {
1983 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)ae->ae_obj;
1984
1985 ASSERT(!MUTEX_HELD(&ss->ss_watchdog_mutex));
1986 kmem_free(ae, sizeof (*ae));
1987
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);
1991
1992 /*
1993 * Notify LV that the link is up now
1994 */
1995 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_ONLINE, 0);
1996 }
1997
1998 /*
1999 * fcoei_process_event_exchange
2000 * Process exchange in the single thread context
2001 *
2002 * Input:
2003 * ae = the exchange event
2004 *
2005 * Returns:
2006 * N/A
2007 *
2008 * Comments:
2009 * N/A
2010 */
2011 void
fcoei_process_event_exchange(fcoei_event_t * ae)2012 fcoei_process_event_exchange(fcoei_event_t *ae)
2013 {
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;
2017
2018 /*
2019 * These 4 elements need reset, pkt_state & pkt_reason will be set
2020 */
2021 fpkt->pkt_action = 0;
2022 fpkt->pkt_expln = 0;
2023 fpkt->pkt_data_resid = 0;
2024 fpkt->pkt_resp_resid = 0;
2025
2026 /*
2027 * port state sanity checking
2028 */
2029 if ((xch->xch_ss->ss_link_state != FC_STATE_ONLINE) ||
2030 xch->xch_ss->ss_port_event_counter) {
2031 /*
2032 * LV will retry it after one second
2033 */
2034 fcoei_complete_xch(xch, NULL, FC_PKT_PORT_OFFLINE,
2035 FC_REASON_OFFLINE);
2036 return;
2037 }
2038
2039 switch (fpkt->pkt_cmd_fhdr.r_ctl) {
2040 case R_CTL_COMMAND:
2041 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp);
2042 fcoei_initiate_fcp_cmd(xch);
2043 break;
2044
2045 case R_CTL_ELS_REQ:
2046 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp);
2047 fcoei_initiate_els_req(xch);
2048 break;
2049
2050 case R_CTL_UNSOL_CONTROL:
2051 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp);
2052 fcoei_initiate_ct_req(xch);
2053 break;
2054
2055 case R_CTL_ELS_RSP:
2056 /*
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.
2060 */
2061 FCOEI_INIT_UNSOL_ID_HASH(xch);
2062 fcoei_initiate_els_resp(xch);
2063 break;
2064
2065 default:
2066 fcoei_complete_xch(xch, NULL, FC_PKT_FAILURE,
2067 FC_REASON_CMD_UNSUPPORTED);
2068 }
2069 }
2070