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