Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/fcoe/fcoe.c
+++ new/usr/src/uts/common/io/fcoe/fcoe.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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25 /*
26 26 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
27 27 */
28 28
29 29 /*
30 30 * The following notice accompanied the original version of this file:
31 31 *
32 32 * BSD LICENSE
33 33 *
34 34 * Copyright(c) 2007 Intel Corporation. All rights reserved.
35 35 * All rights reserved.
36 36 *
37 37 * Redistribution and use in source and binary forms, with or without
38 38 * modification, are permitted provided that the following conditions
39 39 * are met:
40 40 *
41 41 * * Redistributions of source code must retain the above copyright
42 42 * notice, this list of conditions and the following disclaimer.
43 43 * * Redistributions in binary form must reproduce the above copyright
44 44 * notice, this list of conditions and the following disclaimer in
45 45 * the documentation and/or other materials provided with the
46 46 * distribution.
47 47 * * Neither the name of Intel Corporation nor the names of its
48 48 * contributors may be used to endorse or promote products derived
49 49 * from this software without specific prior written permission.
50 50 *
51 51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52 52 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53 53 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
54 54 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
55 55 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
56 56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
57 57 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
61 61 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 62 */
63 63
64 64 /*
65 65 * Common FCoE interface interacts with MAC and FCoE clients, managing
66 66 * FCoE ports, doing MAC address discovery/managment, and FC frame
67 67 * encapsulation/decapsulation
68 68 */
69 69
70 70 #include <sys/stat.h>
71 71 #include <sys/conf.h>
72 72 #include <sys/file.h>
73 73 #include <sys/cred.h>
74 74
75 75 #include <sys/ddi.h>
76 76 #include <sys/sunddi.h>
77 77 #include <sys/sunndi.h>
78 78 #include <sys/byteorder.h>
79 79 #include <sys/atomic.h>
80 80 #include <sys/sysmacros.h>
81 81 #include <sys/cmn_err.h>
82 82 #include <sys/crc32.h>
83 83 #include <sys/strsubr.h>
84 84
85 85 #include <sys/mac_client.h>
86 86
87 87 /*
88 88 * FCoE header files
89 89 */
90 90 #include <sys/fcoe/fcoeio.h>
91 91 #include <sys/fcoe/fcoe_common.h>
92 92
93 93 /*
94 94 * Driver's own header files
95 95 */
96 96 #include <fcoe.h>
97 97 #include <fcoe_fc.h>
98 98 #include <fcoe_eth.h>
99 99
100 100 /*
101 101 * Function forward declaration
102 102 */
103 103 static int fcoe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
104 104 static int fcoe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
105 105 static int fcoe_bus_ctl(dev_info_t *fca_dip, dev_info_t *rip,
106 106 ddi_ctl_enum_t op, void *arg, void *result);
107 107 static int fcoe_open(dev_t *devp, int flag, int otype, cred_t *credp);
108 108 static int fcoe_close(dev_t dev, int flag, int otype, cred_t *credp);
109 109 static int fcoe_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
110 110 cred_t *credp, int *rval);
111 111 static int fcoe_copyin_iocdata(intptr_t data, int mode, fcoeio_t **fcoeio,
112 112 void **ibuf, void **abuf, void **obuf);
113 113 static int fcoe_copyout_iocdata(intptr_t data, int mode, fcoeio_t *fcoeio,
114 114 void *obuf);
115 115 static int fcoe_iocmd(fcoe_soft_state_t *ss, intptr_t data, int mode);
116 116 static int fcoe_attach_init(fcoe_soft_state_t *this_ss);
117 117 static int fcoe_detach_uninit(fcoe_soft_state_t *this_ss);
118 118 static int fcoe_initchild(dev_info_t *fcoe_dip, dev_info_t *client_dip);
119 119 static int fcoe_uninitchild(dev_info_t *fcoe_dip, dev_info_t *client_dip);
120 120 static void fcoe_init_wwn_from_mac(uint8_t *wwn, uint8_t *mac,
121 121 int is_pwwn, uint8_t idx);
122 122 static fcoe_mac_t *fcoe_create_mac_by_id(datalink_id_t linkid);
123 123 static int fcoe_cmp_wwn(fcoe_mac_t *checkedmac);
124 124 static void fcoe_watchdog(void *arg);
125 125 static void fcoe_worker_init();
126 126 static int fcoe_worker_fini();
127 127 static void fcoe_worker_frame();
128 128 static int fcoe_get_port_list(fcoe_port_instance_t *ports, int count);
129 129 static boolean_t fcoe_mac_existed(fcoe_mac_t *pmac);
130 130
131 131 /*
132 132 * Driver identificaton stuff
133 133 */
134 134 static struct cb_ops fcoe_cb_ops = {
135 135 fcoe_open,
136 136 fcoe_close,
137 137 nodev,
138 138 nodev,
139 139 nodev,
140 140 nodev,
141 141 nodev,
142 142 fcoe_ioctl,
143 143 nodev,
144 144 nodev,
145 145 nodev,
146 146 nochpoll,
147 147 ddi_prop_op,
148 148 0,
149 149 D_MP | D_NEW | D_HOTPLUG,
150 150 CB_REV,
151 151 nodev,
152 152 nodev
153 153 };
154 154
155 155 static struct bus_ops fcoe_busops = {
156 156 BUSO_REV,
157 157 nullbusmap, /* bus_map */
158 158 NULL, /* bus_get_intrspec */
159 159 NULL, /* bus_add_intrspec */
160 160 NULL, /* bus_remove_intrspec */
161 161 i_ddi_map_fault, /* bus_map_fault */
162 162 NULL, /* bus_dma_map */
163 163 ddi_dma_allochdl, /* bus_dma_allochdl */
164 164 ddi_dma_freehdl, /* bus_dma_freehdl */
165 165 ddi_dma_bindhdl, /* bus_dma_bindhdl */
166 166 ddi_dma_unbindhdl, /* bus_unbindhdl */
167 167 ddi_dma_flush, /* bus_dma_flush */
168 168 ddi_dma_win, /* bus_dma_win */
169 169 ddi_dma_mctl, /* bus_dma_ctl */
170 170 fcoe_bus_ctl, /* bus_ctl */
171 171 ddi_bus_prop_op, /* bus_prop_op */
172 172 NULL, /* bus_get_eventcookie */
173 173 NULL, /* bus_add_eventcall */
174 174 NULL, /* bus_remove_event */
175 175 NULL, /* bus_post_event */
176 176 NULL, /* bus_intr_ctl */
177 177 NULL, /* bus_config */
178 178 NULL, /* bus_unconfig */
179 179 NULL, /* bus_fm_init */
180 180 NULL, /* bus_fm_fini */
181 181 NULL, /* bus_fm_access_enter */
182 182 NULL, /* bus_fm_access_exit */
183 183 NULL, /* bus_power */
184 184 NULL
185 185 };
186 186
187 187 static struct dev_ops fcoe_ops = {
188 188 DEVO_REV,
189 189 0,
190 190 nodev,
191 191 nulldev,
192 192 nulldev,
193 193 fcoe_attach,
194 194 fcoe_detach,
195 195 nodev,
196 196 &fcoe_cb_ops,
197 197 &fcoe_busops,
198 198 ddi_power,
199 199 ddi_quiesce_not_needed
200 200 };
201 201
202 202 #define FCOE_VERSION "20091123-1.02"
↓ open down ↓ |
202 lines elided |
↑ open up ↑ |
203 203 #define FCOE_NAME "FCoE Transport v" FCOE_VERSION
204 204 #define TASKQ_NAME_LEN 32
205 205
206 206 static struct modldrv modldrv = {
207 207 &mod_driverops,
208 208 FCOE_NAME,
209 209 &fcoe_ops,
210 210 };
211 211
212 212 static struct modlinkage modlinkage = {
213 - MODREV_1, &modldrv, NULL
213 + MODREV_1, { &modldrv, NULL }
214 214 };
215 215
216 216 /*
217 217 * TRACE for all FCoE related modules
218 218 */
219 219 static kmutex_t fcoe_trace_buf_lock;
220 220 static int fcoe_trace_buf_curndx = 0;
221 221 static int fcoe_trace_on = 1;
222 222 static caddr_t fcoe_trace_buf = NULL;
223 223 static clock_t fcoe_trace_start = 0;
224 224 static caddr_t ftb = NULL;
225 225 static int fcoe_trace_buf_size = (1 * 1024 * 1024);
226 226
227 227 /*
228 228 * Driver's global variables
229 229 */
230 230 const fcoe_ver_e fcoe_ver_now = FCOE_VER_NOW;
231 231 static void *fcoe_state = NULL;
232 232 fcoe_soft_state_t *fcoe_global_ss = NULL;
233 233 int fcoe_use_ext_log = 1;
234 234
235 235 static ddi_taskq_t *fcoe_worker_taskq;
236 236 static fcoe_worker_t *fcoe_workers;
237 237 static uint32_t fcoe_nworkers_running;
238 238
239 239 const char *fcoe_workers_num = "workers-number";
240 240 volatile int fcoe_nworkers;
241 241
242 242 /*
243 243 * Common loadable module entry points _init, _fini, _info
244 244 */
245 245
246 246 int
247 247 _init(void)
248 248 {
249 249 int ret;
250 250
251 251 ret = ddi_soft_state_init(&fcoe_state, sizeof (fcoe_soft_state_t), 0);
252 252 if (ret == 0) {
253 253 ret = mod_install(&modlinkage);
254 254 if (ret != 0) {
255 255 ddi_soft_state_fini(&fcoe_state);
256 256 } else {
257 257 fcoe_trace_start = ddi_get_lbolt();
258 258 ftb = kmem_zalloc(fcoe_trace_buf_size,
259 259 KM_SLEEP);
260 260 fcoe_trace_buf = ftb;
261 261 mutex_init(&fcoe_trace_buf_lock, NULL, MUTEX_DRIVER, 0);
262 262 }
263 263 }
264 264
265 265 FCOE_LOG("fcoe", "exit _init with %x", ret);
266 266
267 267 return (ret);
268 268 }
269 269
270 270 int
271 271 _fini(void)
272 272 {
273 273 int ret;
274 274
275 275 ret = mod_remove(&modlinkage);
276 276 if (ret == 0) {
277 277 ddi_soft_state_fini(&fcoe_state);
278 278 }
279 279
280 280 FCOE_LOG("fcoe", "exit _fini with %x", ret);
281 281 if (ret == 0) {
282 282 kmem_free(fcoe_trace_buf, fcoe_trace_buf_size);
283 283 mutex_destroy(&fcoe_trace_buf_lock);
284 284 }
285 285
286 286 return (ret);
287 287 }
288 288
289 289 int
290 290 _info(struct modinfo *modinfop)
291 291 {
292 292 return (mod_info(&modlinkage, modinfop));
293 293 }
294 294
295 295 /*
296 296 * Autoconfiguration entry points: attach, detach, getinfo
297 297 */
298 298
299 299 static int
300 300 fcoe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
301 301 {
302 302 int ret = DDI_FAILURE;
303 303 int fcoe_ret;
304 304 int instance;
305 305 fcoe_soft_state_t *ss;
306 306
307 307 instance = ddi_get_instance(dip);
308 308 switch (cmd) {
309 309 case DDI_ATTACH:
310 310 ret = ddi_soft_state_zalloc(fcoe_state, instance);
311 311 if (ret == DDI_FAILURE) {
312 312 FCOE_LOG(0, "soft_state_zalloc-%x/%x", ret, instance);
313 313 return (ret);
314 314 }
315 315
316 316 ss = ddi_get_soft_state(fcoe_state, instance);
317 317 ss->ss_dip = dip;
318 318
319 319 ASSERT(fcoe_global_ss == NULL);
320 320 fcoe_global_ss = ss;
321 321 fcoe_ret = fcoe_attach_init(ss);
322 322 if (fcoe_ret == FCOE_SUCCESS) {
323 323 ret = DDI_SUCCESS;
324 324 }
325 325
326 326 FCOE_LOG("fcoe", "fcoe_attach_init end with-%x", fcoe_ret);
327 327 break;
328 328
329 329 case DDI_RESUME:
330 330 ret = DDI_SUCCESS;
331 331 break;
332 332
333 333 default:
334 334 FCOE_LOG("fcoe", "unsupported attach cmd-%x", cmd);
335 335 break;
336 336 }
337 337
338 338 return (ret);
339 339 }
340 340
341 341 static int
342 342 fcoe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
343 343 {
344 344 int ret = DDI_FAILURE;
345 345 int fcoe_ret;
346 346 int instance;
347 347 fcoe_soft_state_t *ss;
348 348
349 349 instance = ddi_get_instance(dip);
350 350 ss = ddi_get_soft_state(fcoe_state, instance);
351 351 if (ss == NULL) {
352 352 return (ret);
353 353 }
354 354
355 355 ASSERT(fcoe_global_ss != NULL);
356 356 ASSERT(dip == fcoe_global_ss->ss_dip);
357 357 switch (cmd) {
358 358 case DDI_DETACH:
359 359 fcoe_ret = fcoe_detach_uninit(ss);
360 360 if (fcoe_ret == FCOE_SUCCESS) {
361 361 ret = DDI_SUCCESS;
362 362 fcoe_global_ss = NULL;
363 363 }
364 364
365 365 break;
366 366
367 367 case DDI_SUSPEND:
368 368 ret = DDI_SUCCESS;
369 369 break;
370 370
371 371 default:
372 372 FCOE_LOG(0, "unsupported detach cmd-%x", cmd);
373 373 break;
374 374 }
375 375
376 376 return (ret);
377 377 }
378 378
379 379 /*
380 380 * FCA driver's intercepted bus control operations.
381 381 */
382 382 static int
383 383 fcoe_bus_ctl(dev_info_t *fcoe_dip, dev_info_t *rip,
384 384 ddi_ctl_enum_t op, void *clientarg, void *result)
385 385 {
386 386 int ret;
387 387 switch (op) {
388 388 case DDI_CTLOPS_REPORTDEV:
389 389 case DDI_CTLOPS_IOMIN:
390 390 ret = DDI_SUCCESS;
391 391 break;
392 392
393 393 case DDI_CTLOPS_INITCHILD:
394 394 ret = fcoe_initchild(fcoe_dip, (dev_info_t *)clientarg);
395 395 break;
396 396
397 397 case DDI_CTLOPS_UNINITCHILD:
398 398 ret = fcoe_uninitchild(fcoe_dip, (dev_info_t *)clientarg);
399 399 break;
400 400
401 401 default:
402 402 ret = ddi_ctlops(fcoe_dip, rip, op, clientarg, result);
403 403 break;
404 404 }
405 405
406 406 return (ret);
407 407 }
408 408
409 409 /*
410 410 * We need specify the dev address for client driver's instance, or we
411 411 * can't online client driver's instance.
412 412 */
413 413 /* ARGSUSED */
414 414 static int
415 415 fcoe_initchild(dev_info_t *fcoe_dip, dev_info_t *client_dip)
416 416 {
417 417 char client_addr[FCOE_STR_LEN];
418 418 int rval;
419 419
420 420 rval = ddi_prop_get_int(DDI_DEV_T_ANY, client_dip,
421 421 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "mac_id", -1);
422 422 if (rval == -1) {
423 423 FCOE_LOG(__FUNCTION__, "no mac_id property: %p", client_dip);
424 424 return (DDI_FAILURE);
425 425 }
426 426
427 427 bzero(client_addr, FCOE_STR_LEN);
428 428 (void) sprintf((char *)client_addr, "%x,0", rval);
429 429 ddi_set_name_addr(client_dip, client_addr);
430 430 return (DDI_SUCCESS);
431 431 }
432 432
433 433 /* ARGSUSED */
434 434 static int
435 435 fcoe_uninitchild(dev_info_t *fcoe_dip, dev_info_t *client_dip)
436 436 {
437 437 ddi_set_name_addr(client_dip, NULL);
438 438 return (DDI_SUCCESS);
439 439 }
440 440
441 441 /*
442 442 * Device access entry points
443 443 */
444 444 static int
445 445 fcoe_open(dev_t *devp, int flag, int otype, cred_t *credp)
446 446 {
447 447 int instance;
448 448 fcoe_soft_state_t *ss;
449 449
450 450 if (otype != OTYP_CHR) {
451 451 return (EINVAL);
452 452 }
453 453
454 454 /*
455 455 * Since this is for debugging only, only allow root to issue ioctl now
456 456 */
457 457 if (drv_priv(credp) != 0) {
458 458 return (EPERM);
459 459 }
460 460
461 461 instance = (int)getminor(*devp);
462 462 ss = ddi_get_soft_state(fcoe_state, instance);
463 463 if (ss == NULL) {
464 464 return (ENXIO);
465 465 }
466 466
467 467 mutex_enter(&ss->ss_ioctl_mutex);
468 468 if (ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_EXCL) {
469 469 /*
470 470 * It is already open for exclusive access.
471 471 * So shut the door on this caller.
472 472 */
473 473 mutex_exit(&ss->ss_ioctl_mutex);
474 474 return (EBUSY);
475 475 }
476 476
477 477 if (flag & FEXCL) {
478 478 if (ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_OPEN) {
479 479 /*
480 480 * Exclusive operation not possible
481 481 * as it is already opened
482 482 */
483 483 mutex_exit(&ss->ss_ioctl_mutex);
484 484 return (EBUSY);
485 485 }
486 486 ss->ss_ioctl_flags |= FCOE_IOCTL_FLAG_EXCL;
487 487 }
488 488
489 489 ss->ss_ioctl_flags |= FCOE_IOCTL_FLAG_OPEN;
490 490 mutex_exit(&ss->ss_ioctl_mutex);
491 491
492 492 return (0);
493 493 }
494 494
495 495 /* ARGSUSED */
496 496 static int
497 497 fcoe_close(dev_t dev, int flag, int otype, cred_t *credp)
498 498 {
499 499 int instance;
500 500 fcoe_soft_state_t *ss;
501 501
502 502 if (otype != OTYP_CHR) {
503 503 return (EINVAL);
504 504 }
505 505
506 506 instance = (int)getminor(dev);
507 507 ss = ddi_get_soft_state(fcoe_state, instance);
508 508 if (ss == NULL) {
509 509 return (ENXIO);
510 510 }
511 511
512 512 mutex_enter(&ss->ss_ioctl_mutex);
513 513 if ((ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_OPEN) == 0) {
514 514 mutex_exit(&ss->ss_ioctl_mutex);
515 515 return (ENODEV);
516 516 }
517 517
518 518 ss->ss_ioctl_flags &= ~FCOE_IOCTL_FLAG_MASK;
519 519 mutex_exit(&ss->ss_ioctl_mutex);
520 520
521 521 return (0);
522 522 }
523 523
524 524 /* ARGSUSED */
525 525 static int
526 526 fcoe_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
527 527 cred_t *credp, int *rval)
528 528 {
529 529 fcoe_soft_state_t *ss;
530 530 int ret = 0;
531 531
532 532 if (drv_priv(credp) != 0) {
533 533 return (EPERM);
534 534 }
535 535
536 536 ss = ddi_get_soft_state(fcoe_state, (int32_t)getminor(dev));
537 537 if (ss == NULL) {
538 538 return (ENXIO);
539 539 }
540 540
541 541 mutex_enter(&ss->ss_ioctl_mutex);
542 542 if ((ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_OPEN) == 0) {
543 543 mutex_exit(&ss->ss_ioctl_mutex);
544 544 return (ENXIO);
545 545 }
546 546 mutex_exit(&ss->ss_ioctl_mutex);
547 547
548 548 switch (cmd) {
549 549 case FCOEIO_CMD:
550 550 ret = fcoe_iocmd(ss, data, mode);
551 551 break;
552 552 default:
553 553 FCOE_LOG(0, "fcoe_ioctl: ioctl-0x%02X", cmd);
554 554 ret = ENOTTY;
555 555 break;
556 556 }
557 557
558 558 return (ret);
559 559 }
560 560
561 561 static int
562 562 fcoe_copyin_iocdata(intptr_t data, int mode, fcoeio_t **fcoeio,
563 563 void **ibuf, void **abuf, void **obuf)
564 564 {
565 565 int ret = 0;
566 566
567 567 *ibuf = NULL;
568 568 *abuf = NULL;
569 569 *obuf = NULL;
570 570 *fcoeio = kmem_zalloc(sizeof (fcoeio_t), KM_SLEEP);
571 571 if (ddi_copyin((void *)data, *fcoeio, sizeof (fcoeio_t), mode) != 0) {
572 572 ret = EFAULT;
573 573 goto copyin_iocdata_fail;
574 574 }
575 575
576 576 if ((*fcoeio)->fcoeio_ilen > FCOEIO_MAX_BUF_LEN ||
577 577 (*fcoeio)->fcoeio_alen > FCOEIO_MAX_BUF_LEN ||
578 578 (*fcoeio)->fcoeio_olen > FCOEIO_MAX_BUF_LEN) {
579 579 ret = EFAULT;
580 580 goto copyin_iocdata_fail;
581 581 }
582 582
583 583 if ((*fcoeio)->fcoeio_ilen) {
584 584 *ibuf = kmem_zalloc((*fcoeio)->fcoeio_ilen, KM_SLEEP);
585 585 if (ddi_copyin((void *)(unsigned long)(*fcoeio)->fcoeio_ibuf,
586 586 *ibuf, (*fcoeio)->fcoeio_ilen, mode) != 0) {
587 587 ret = EFAULT;
588 588 goto copyin_iocdata_fail;
589 589 }
590 590 }
591 591
592 592 if ((*fcoeio)->fcoeio_alen) {
593 593 *abuf = kmem_zalloc((*fcoeio)->fcoeio_alen, KM_SLEEP);
594 594 if (ddi_copyin((void *)(unsigned long)(*fcoeio)->fcoeio_abuf,
595 595 *abuf, (*fcoeio)->fcoeio_alen, mode) != 0) {
596 596 ret = EFAULT;
597 597 goto copyin_iocdata_fail;
598 598 }
599 599 }
600 600
601 601 if ((*fcoeio)->fcoeio_olen) {
602 602 *obuf = kmem_zalloc((*fcoeio)->fcoeio_olen, KM_SLEEP);
603 603 }
604 604 return (ret);
605 605
606 606 copyin_iocdata_fail:
607 607 if (*abuf) {
608 608 kmem_free(*abuf, (*fcoeio)->fcoeio_alen);
609 609 *abuf = NULL;
610 610 }
611 611
612 612 if (*ibuf) {
613 613 kmem_free(*ibuf, (*fcoeio)->fcoeio_ilen);
614 614 *ibuf = NULL;
615 615 }
616 616
617 617 kmem_free(*fcoeio, sizeof (fcoeio_t));
618 618 return (ret);
619 619 }
620 620
621 621 static int
622 622 fcoe_copyout_iocdata(intptr_t data, int mode, fcoeio_t *fcoeio, void *obuf)
623 623 {
624 624 if (fcoeio->fcoeio_olen) {
625 625 if (ddi_copyout(obuf,
626 626 (void *)(unsigned long)fcoeio->fcoeio_obuf,
627 627 fcoeio->fcoeio_olen, mode) != 0) {
628 628 return (EFAULT);
629 629 }
630 630 }
631 631
632 632 if (ddi_copyout(fcoeio, (void *)data, sizeof (fcoeio_t), mode) != 0) {
633 633 return (EFAULT);
634 634 }
635 635 return (0);
636 636 }
637 637
638 638 static int
639 639 fcoe_iocmd(fcoe_soft_state_t *ss, intptr_t data, int mode)
640 640 {
641 641 int ret;
642 642 fcoe_mac_t *fcoe_mac;
643 643 void *ibuf = NULL;
644 644 void *obuf = NULL;
645 645 void *abuf = NULL;
646 646 fcoeio_t *fcoeio;
647 647
648 648 ret = fcoe_copyin_iocdata(data, mode, &fcoeio, &ibuf, &abuf, &obuf);
649 649 if (ret != 0) {
650 650 goto fcoeiocmd_release_buf;
651 651 }
652 652
653 653 /*
654 654 * If an exclusive open was demanded during open, ensure that
655 655 * only one thread can execute an ioctl at a time
656 656 */
657 657 mutex_enter(&ss->ss_ioctl_mutex);
658 658 if (ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_EXCL) {
659 659 if (ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_EXCL_BUSY) {
660 660 mutex_exit(&ss->ss_ioctl_mutex);
661 661 fcoeio->fcoeio_status = FCOEIOE_BUSY;
662 662 ret = EBUSY;
663 663 goto fcoeiocmd_release_buf;
664 664 }
665 665 ss->ss_ioctl_flags |= FCOE_IOCTL_FLAG_EXCL_BUSY;
666 666 }
667 667 mutex_exit(&ss->ss_ioctl_mutex);
668 668
669 669 fcoeio->fcoeio_status = 0;
670 670
671 671 switch (fcoeio->fcoeio_cmd) {
672 672 case FCOEIO_CREATE_FCOE_PORT: {
673 673 fcoeio_create_port_param_t *param =
674 674 (fcoeio_create_port_param_t *)ibuf;
675 675 int cmpwwn = 0;
676 676 fcoe_port_t *eport;
677 677
678 678 if (fcoeio->fcoeio_ilen !=
679 679 sizeof (fcoeio_create_port_param_t) ||
680 680 fcoeio->fcoeio_xfer != FCOEIO_XFER_WRITE) {
681 681 fcoeio->fcoeio_status = FCOEIOE_INVAL_ARG;
682 682 ret = EINVAL;
683 683 break;
684 684 }
685 685
686 686 mutex_enter(&ss->ss_ioctl_mutex);
687 687 fcoe_mac = fcoe_create_mac_by_id(param->fcp_mac_linkid);
688 688 if (fcoe_mac == NULL) {
689 689 mutex_exit(&ss->ss_ioctl_mutex);
690 690 fcoeio->fcoeio_status = FCOEIOE_CREATE_MAC;
691 691 ret = EIO;
692 692 break;
693 693 }
694 694
695 695 if (fcoe_mac->fm_flags & FCOE_MAC_FLAG_ENABLED) {
696 696 mutex_exit(&ss->ss_ioctl_mutex);
697 697 fcoeio->fcoeio_status = FCOEIOE_ALREADY;
698 698 ret = EALREADY;
699 699 break;
700 700 } else {
701 701 ret = fcoe_open_mac(fcoe_mac, param->fcp_force_promisc,
702 702 &fcoeio->fcoeio_status);
703 703 if (ret != 0) {
704 704 fcoe_destroy_mac(fcoe_mac);
705 705 mutex_exit(&ss->ss_ioctl_mutex);
706 706 if (fcoeio->fcoeio_status == 0) {
707 707 fcoeio->fcoeio_status =
708 708 FCOEIOE_OPEN_MAC;
709 709 }
710 710 ret = EIO;
711 711 break;
712 712 } else {
713 713 fcoe_mac->fm_flags |= FCOE_MAC_FLAG_ENABLED;
714 714 }
715 715 }
716 716
717 717 /*
718 718 * Provide PWWN and NWWN based on mac address
719 719 */
720 720 eport = &fcoe_mac->fm_eport;
721 721 if (!param->fcp_pwwn_provided) {
722 722 fcoe_init_wwn_from_mac(eport->eport_portwwn,
723 723 fcoe_mac->fm_current_addr, 1, 0);
724 724 } else {
725 725 (void) memcpy(eport->eport_portwwn, param->fcp_pwwn, 8);
726 726 }
727 727
728 728 if (!param->fcp_nwwn_provided) {
729 729 fcoe_init_wwn_from_mac(eport->eport_nodewwn,
730 730 fcoe_mac->fm_current_addr, 0, 0);
731 731 } else {
732 732 (void) memcpy(eport->eport_nodewwn, param->fcp_nwwn, 8);
733 733 }
734 734
735 735 cmpwwn = fcoe_cmp_wwn(fcoe_mac);
736 736
737 737 if (cmpwwn != 0) {
738 738 if (cmpwwn == 1) {
739 739 fcoeio->fcoeio_status = FCOEIOE_PWWN_CONFLICTED;
740 740 } else if (cmpwwn == -1) {
741 741 fcoeio->fcoeio_status = FCOEIOE_NWWN_CONFLICTED;
742 742 }
743 743 (void) fcoe_close_mac(fcoe_mac);
744 744 fcoe_destroy_mac(fcoe_mac);
745 745 mutex_exit(&ss->ss_ioctl_mutex);
746 746 ret = ENOTUNIQ;
747 747 break;
748 748 }
749 749
750 750 if (ret == 0) {
751 751 ret = fcoe_create_port(ss->ss_dip,
752 752 fcoe_mac,
753 753 (param->fcp_port_type == FCOE_CLIENT_TARGET));
754 754 if (ret != 0) {
755 755 if (fcoe_mac_existed(fcoe_mac) == B_TRUE) {
756 756 (void) fcoe_close_mac(fcoe_mac);
757 757 fcoe_destroy_mac(fcoe_mac);
758 758 }
759 759 fcoeio->fcoeio_status = FCOEIOE_CREATE_PORT;
760 760 ret = EIO;
761 761 }
762 762 }
763 763 mutex_exit(&ss->ss_ioctl_mutex);
764 764
765 765 break;
766 766 }
767 767
768 768 case FCOEIO_DELETE_FCOE_PORT: {
769 769 fcoeio_delete_port_param_t *del_port_param =
770 770 (fcoeio_delete_port_param_t *)ibuf;
771 771 uint64_t *is_target = (uint64_t *)obuf;
772 772
773 773 if (fcoeio->fcoeio_ilen < sizeof (fcoeio_delete_port_param_t) ||
774 774 fcoeio->fcoeio_olen != sizeof (uint64_t) ||
775 775 fcoeio->fcoeio_xfer != FCOEIO_XFER_RW) {
776 776 fcoeio->fcoeio_status = FCOEIOE_INVAL_ARG;
777 777 ret = EINVAL;
778 778 break;
779 779 }
780 780
781 781 mutex_enter(&ss->ss_ioctl_mutex);
782 782 ret = fcoe_delete_port(ss->ss_dip, fcoeio,
783 783 del_port_param->fdp_mac_linkid, is_target);
784 784 mutex_exit(&ss->ss_ioctl_mutex);
785 785 FCOE_LOG("fcoe", "fcoe_delete_port %x return: %d",
786 786 del_port_param->fdp_mac_linkid, ret);
787 787 break;
788 788 }
789 789
790 790 case FCOEIO_GET_FCOE_PORT_LIST: {
791 791 fcoe_port_list_t *list = (fcoe_port_list_t *)obuf;
792 792 int count;
793 793
794 794 if (fcoeio->fcoeio_xfer != FCOEIO_XFER_READ ||
795 795 fcoeio->fcoeio_olen < sizeof (fcoe_port_list_t)) {
796 796 fcoeio->fcoeio_status = FCOEIOE_INVAL_ARG;
797 797 ret = EINVAL;
798 798 break;
799 799 }
800 800 mutex_enter(&ss->ss_ioctl_mutex);
801 801
802 802 list->numPorts = 1 + (fcoeio->fcoeio_olen -
803 803 sizeof (fcoe_port_list_t))/sizeof (fcoe_port_instance_t);
804 804
805 805 count = fcoe_get_port_list(list->ports, list->numPorts);
806 806
807 807 if (count > list->numPorts) {
808 808 fcoeio->fcoeio_status = FCOEIOE_MORE_DATA;
809 809 ret = ENOSPC;
810 810 }
811 811 list->numPorts = count;
812 812 mutex_exit(&ss->ss_ioctl_mutex);
813 813
814 814 break;
815 815
816 816 }
817 817
818 818 default:
819 819 return (ENOTTY);
820 820 }
821 821
822 822 FCOE_LOG("fcoe", "fcoe_ioctl %x returned %d, fcoeio_status = %d",
823 823 fcoeio->fcoeio_cmd, ret, fcoeio->fcoeio_status);
824 824
825 825 fcoeiocmd_release_buf:
826 826 if (ret == 0) {
827 827 ret = fcoe_copyout_iocdata(data, mode, fcoeio, obuf);
828 828 } else if (fcoeio->fcoeio_status) {
829 829 (void) fcoe_copyout_iocdata(data, mode, fcoeio, obuf);
830 830 }
831 831
832 832 if (obuf != NULL) {
833 833 kmem_free(obuf, fcoeio->fcoeio_olen);
834 834 obuf = NULL;
835 835 }
836 836 if (abuf != NULL) {
837 837 kmem_free(abuf, fcoeio->fcoeio_alen);
838 838 abuf = NULL;
839 839 }
840 840
841 841 if (ibuf != NULL) {
842 842 kmem_free(ibuf, fcoeio->fcoeio_ilen);
843 843 ibuf = NULL;
844 844 }
845 845 kmem_free(fcoeio, sizeof (fcoeio_t));
846 846
847 847 return (ret);
848 848 }
849 849
850 850 /*
851 851 * Finish final initialization
852 852 */
853 853 static int
854 854 fcoe_attach_init(fcoe_soft_state_t *ss)
855 855 {
856 856 char taskq_name[TASKQ_NAME_LEN];
857 857
858 858 if (ddi_create_minor_node(ss->ss_dip, "admin", S_IFCHR,
859 859 ddi_get_instance(ss->ss_dip), DDI_PSEUDO, 0) != DDI_SUCCESS) {
860 860 FCOE_LOG("FCOE", "ddi_create_minor_node failed");
861 861 return (FCOE_FAILURE);
862 862 }
863 863
864 864 /*
865 865 * watchdog responsible for release frame and dispatch events
866 866 */
867 867 (void) snprintf(taskq_name, sizeof (taskq_name), "fcoe_mac");
868 868 taskq_name[TASKQ_NAME_LEN - 1] = 0;
869 869 if ((ss->ss_watchdog_taskq = ddi_taskq_create(NULL,
870 870 taskq_name, 2, TASKQ_DEFAULTPRI, 0)) == NULL) {
871 871 return (FCOE_FAILURE);
872 872 }
873 873
874 874 ss->ss_ioctl_flags = 0;
875 875 mutex_init(&ss->ss_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
876 876 list_create(&ss->ss_mac_list, sizeof (fcoe_mac_t),
877 877 offsetof(fcoe_mac_t, fm_ss_node));
878 878 list_create(&ss->ss_pfrm_list, sizeof (fcoe_i_frame_t),
879 879 offsetof(fcoe_i_frame_t, fmi_pending_node));
880 880
881 881 mutex_init(&ss->ss_watch_mutex, 0, MUTEX_DRIVER, 0);
882 882 cv_init(&ss->ss_watch_cv, NULL, CV_DRIVER, NULL);
883 883 ss->ss_flags &= ~SS_FLAG_TERMINATE_WATCHDOG;
884 884 (void) ddi_taskq_dispatch(ss->ss_watchdog_taskq,
885 885 fcoe_watchdog, ss, DDI_SLEEP);
886 886 while ((ss->ss_flags & SS_FLAG_WATCHDOG_RUNNING) == 0) {
887 887 delay(10);
888 888 }
889 889 fcoe_nworkers = ddi_prop_get_int(DDI_DEV_T_ANY, ss->ss_dip,
890 890 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, (char *)fcoe_workers_num, 4);
891 891 if (fcoe_nworkers < 1) {
892 892 fcoe_nworkers = 4;
893 893 }
894 894 fcoe_worker_init();
895 895
896 896 ddi_report_dev(ss->ss_dip);
897 897 return (FCOE_SUCCESS);
898 898 }
899 899
900 900 /*
901 901 * Finish final uninitialization
902 902 */
903 903 static int
904 904 fcoe_detach_uninit(fcoe_soft_state_t *ss)
905 905 {
906 906 int ret;
907 907 if (!list_is_empty(&ss->ss_mac_list)) {
908 908 FCOE_LOG("fcoe", "ss_mac_list is not empty when detach");
909 909 return (FCOE_FAILURE);
910 910 }
911 911
912 912 if ((ret = fcoe_worker_fini()) != FCOE_SUCCESS) {
913 913 return (ret);
914 914 }
915 915
916 916 /*
917 917 * Stop watchdog
918 918 */
919 919 if (ss->ss_flags & SS_FLAG_WATCHDOG_RUNNING) {
920 920 mutex_enter(&ss->ss_watch_mutex);
921 921 ss->ss_flags |= SS_FLAG_TERMINATE_WATCHDOG;
922 922 cv_broadcast(&ss->ss_watch_cv);
923 923 mutex_exit(&ss->ss_watch_mutex);
924 924 while (ss->ss_flags & SS_FLAG_WATCHDOG_RUNNING) {
925 925 delay(10);
926 926 }
927 927 }
928 928
929 929 ddi_taskq_destroy(ss->ss_watchdog_taskq);
930 930 mutex_destroy(&ss->ss_watch_mutex);
931 931 cv_destroy(&ss->ss_watch_cv);
932 932
933 933 ddi_remove_minor_node(ss->ss_dip, NULL);
934 934 mutex_destroy(&ss->ss_ioctl_mutex);
935 935 list_destroy(&ss->ss_mac_list);
936 936
937 937 return (FCOE_SUCCESS);
938 938 }
939 939
940 940 /*
941 941 * Return mac instance if it exist, or else return NULL.
942 942 */
943 943 fcoe_mac_t *
944 944 fcoe_lookup_mac_by_id(datalink_id_t linkid)
945 945 {
946 946 fcoe_mac_t *mac = NULL;
947 947
948 948 ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
949 949 for (mac = list_head(&fcoe_global_ss->ss_mac_list); mac;
950 950 mac = list_next(&fcoe_global_ss->ss_mac_list, mac)) {
951 951 if (linkid != mac->fm_linkid) {
952 952 continue;
953 953 }
954 954 return (mac);
955 955 }
956 956 return (NULL);
957 957 }
958 958
959 959 /*
960 960 * Return B_TRUE if mac exists, or else return B_FALSE
961 961 */
962 962 static boolean_t
963 963 fcoe_mac_existed(fcoe_mac_t *pmac)
964 964 {
965 965 fcoe_mac_t *mac = NULL;
966 966
967 967 ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
968 968 for (mac = list_head(&fcoe_global_ss->ss_mac_list); mac;
969 969 mac = list_next(&fcoe_global_ss->ss_mac_list, mac)) {
970 970 if (mac == pmac) {
971 971 return (B_TRUE);
972 972 }
973 973 }
974 974 return (B_FALSE);
975 975 }
976 976
977 977 /*
978 978 * port wwn will start with 20:..., node wwn will start with 10:...
979 979 */
980 980 static void
981 981 fcoe_init_wwn_from_mac(uint8_t *wwn, uint8_t *mac, int is_pwwn, uint8_t idx)
982 982 {
983 983 ASSERT(wwn != NULL);
984 984 ASSERT(mac != NULL);
985 985 wwn[0] = (is_pwwn + 1) << 4;
986 986 wwn[1] = idx;
987 987 bcopy(mac, wwn + 2, ETHERADDRL);
988 988 }
989 989
990 990 /*
991 991 * Return fcoe_mac if it exists, otherwise create a new one
992 992 */
993 993 static fcoe_mac_t *
994 994 fcoe_create_mac_by_id(datalink_id_t linkid)
995 995 {
996 996 fcoe_mac_t *mac = NULL;
997 997 ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
998 998
999 999 mac = fcoe_lookup_mac_by_id(linkid);
1000 1000 if (mac != NULL) {
1001 1001 FCOE_LOG("fcoe", "fcoe_create_mac_by_id found one mac %d",
1002 1002 linkid);
1003 1003 return (mac);
1004 1004 }
1005 1005
1006 1006 mac = kmem_zalloc(sizeof (fcoe_mac_t), KM_SLEEP);
1007 1007 mac->fm_linkid = linkid;
1008 1008 mac->fm_flags = 0;
1009 1009 mac->fm_ss = fcoe_global_ss;
1010 1010 list_insert_tail(&mac->fm_ss->ss_mac_list, mac);
1011 1011 FCOE_LOG("fcoe", "fcoe_create_mac_by_id created one mac %d", linkid);
1012 1012 return (mac);
1013 1013 }
1014 1014
1015 1015 void
1016 1016 fcoe_destroy_mac(fcoe_mac_t *mac)
1017 1017 {
1018 1018 ASSERT(mac != NULL);
1019 1019 list_remove(&mac->fm_ss->ss_mac_list, mac);
1020 1020 kmem_free(mac, sizeof (fcoe_mac_t));
1021 1021 }
1022 1022
1023 1023 /*
1024 1024 * raw frame layout:
1025 1025 * ethernet header + vlan header (optional) + FCoE header +
1026 1026 * FC frame + FCoE tailer
1027 1027 */
1028 1028 /* ARGSUSED */
1029 1029 mblk_t *
1030 1030 fcoe_get_mblk(fcoe_mac_t *mac, uint32_t raw_frame_size)
1031 1031 {
1032 1032 mblk_t *mp;
1033 1033 int err;
1034 1034
1035 1035 /*
1036 1036 * FCFH_SIZE + PADDING_SIZE
1037 1037 */
1038 1038 ASSERT(raw_frame_size >= 60);
1039 1039 while ((mp = allocb((size_t)raw_frame_size, 0)) == NULL) {
1040 1040 if ((err = strwaitbuf((size_t)raw_frame_size, BPRI_LO)) != 0) {
1041 1041 FCOE_LOG("fcoe_get_mblk", "strwaitbuf return %d", err);
1042 1042 return (NULL);
1043 1043 }
1044 1044 }
1045 1045 mp->b_wptr = mp->b_rptr + raw_frame_size;
1046 1046
1047 1047 /*
1048 1048 * We should always zero FC frame header
1049 1049 */
1050 1050 bzero(mp->b_rptr + PADDING_HEADER_SIZE,
1051 1051 sizeof (fcoe_fc_frame_header_t));
1052 1052 return (mp);
1053 1053 }
1054 1054
1055 1055 static void
1056 1056 fcoe_watchdog(void *arg)
1057 1057 {
1058 1058 fcoe_soft_state_t *ss = (fcoe_soft_state_t *)arg;
1059 1059 fcoe_i_frame_t *fmi;
1060 1060 fcoe_mac_t *mac = NULL;
1061 1061
1062 1062 FCOE_LOG("fcoe", "fcoe_soft_state is %p", ss);
1063 1063
1064 1064 mutex_enter(&ss->ss_watch_mutex);
1065 1065 ss->ss_flags |= SS_FLAG_WATCHDOG_RUNNING;
1066 1066 while ((ss->ss_flags & SS_FLAG_TERMINATE_WATCHDOG) == 0) {
1067 1067 while (fmi = (fcoe_i_frame_t *)list_head(&ss->ss_pfrm_list)) {
1068 1068 list_remove(&ss->ss_pfrm_list, fmi);
1069 1069 mutex_exit(&ss->ss_watch_mutex);
1070 1070
1071 1071 mac = EPORT2MAC(fmi->fmi_frame->frm_eport);
1072 1072 mac->fm_client.ect_release_sol_frame(fmi->fmi_frame);
1073 1073
1074 1074 mutex_enter(&ss->ss_watch_mutex);
1075 1075 mac->fm_frm_cnt--;
1076 1076 }
1077 1077
1078 1078 ss->ss_flags |= SS_FLAG_DOG_WAITING;
1079 1079 (void) cv_wait(&ss->ss_watch_cv, &ss->ss_watch_mutex);
1080 1080 ss->ss_flags &= ~SS_FLAG_DOG_WAITING;
1081 1081 }
1082 1082
1083 1083 ss->ss_flags &= ~SS_FLAG_WATCHDOG_RUNNING;
1084 1084 mutex_exit(&ss->ss_watch_mutex);
1085 1085 }
1086 1086
1087 1087 static void
1088 1088 fcoe_worker_init()
1089 1089 {
1090 1090 uint32_t i;
1091 1091
1092 1092 fcoe_nworkers_running = 0;
1093 1093 fcoe_worker_taskq = ddi_taskq_create(0, "FCOE_WORKER_TASKQ",
1094 1094 fcoe_nworkers, TASKQ_DEFAULTPRI, 0);
1095 1095 fcoe_workers = (fcoe_worker_t *)kmem_zalloc(sizeof (fcoe_worker_t) *
1096 1096 fcoe_nworkers, KM_SLEEP);
1097 1097 for (i = 0; i < fcoe_nworkers; i++) {
1098 1098 fcoe_worker_t *w = &fcoe_workers[i];
1099 1099 mutex_init(&w->worker_lock, NULL, MUTEX_DRIVER, NULL);
1100 1100 cv_init(&w->worker_cv, NULL, CV_DRIVER, NULL);
1101 1101 w->worker_flags &= ~FCOE_WORKER_TERMINATE;
1102 1102 list_create(&w->worker_frm_list, sizeof (fcoe_i_frame_t),
1103 1103 offsetof(fcoe_i_frame_t, fmi_pending_node));
1104 1104 (void) ddi_taskq_dispatch(fcoe_worker_taskq, fcoe_worker_frame,
1105 1105 w, DDI_SLEEP);
1106 1106 }
1107 1107 while (fcoe_nworkers_running != fcoe_nworkers) {
1108 1108 delay(10);
1109 1109 }
1110 1110 }
1111 1111
1112 1112 static int
1113 1113 fcoe_worker_fini()
1114 1114 {
1115 1115 uint32_t i;
1116 1116
1117 1117 for (i = 0; i < fcoe_nworkers; i++) {
1118 1118 fcoe_worker_t *w = &fcoe_workers[i];
1119 1119 mutex_enter(&w->worker_lock);
1120 1120 if (w->worker_flags & FCOE_WORKER_STARTED) {
1121 1121 w->worker_flags |= FCOE_WORKER_TERMINATE;
1122 1122 cv_signal(&w->worker_cv);
1123 1123 }
1124 1124 mutex_exit(&w->worker_lock);
1125 1125 }
1126 1126
1127 1127 while (fcoe_nworkers_running != 0) {
1128 1128 delay(drv_usectohz(10000));
1129 1129 }
1130 1130
1131 1131 ddi_taskq_destroy(fcoe_worker_taskq);
1132 1132 kmem_free(fcoe_workers, sizeof (fcoe_worker_t) * fcoe_nworkers);
1133 1133 fcoe_workers = NULL;
1134 1134 return (FCOE_SUCCESS);
1135 1135 }
1136 1136
1137 1137 static int
1138 1138 fcoe_crc_verify(fcoe_frame_t *frm)
1139 1139 {
1140 1140 uint32_t crc;
1141 1141 uint8_t *crc_array = FRM2FMI(frm)->fmi_fft->fft_crc;
1142 1142 uint32_t crc_from_frame = ~(crc_array[0] | (crc_array[1] << 8) |
1143 1143 (crc_array[2] << 16) | (crc_array[3] << 24));
1144 1144 CRC32(crc, frm->frm_fc_frame, frm->frm_fc_frame_size, -1U, crc32_table);
1145 1145 return (crc == crc_from_frame ? FCOE_SUCCESS : FCOE_FAILURE);
1146 1146 }
1147 1147
1148 1148 static void
1149 1149 fcoe_worker_frame(void *arg)
1150 1150 {
1151 1151 fcoe_worker_t *w = (fcoe_worker_t *)arg;
1152 1152 fcoe_i_frame_t *fmi;
1153 1153 int ret;
1154 1154
1155 1155 atomic_inc_32(&fcoe_nworkers_running);
1156 1156 mutex_enter(&w->worker_lock);
1157 1157 w->worker_flags |= FCOE_WORKER_STARTED | FCOE_WORKER_ACTIVE;
1158 1158 while ((w->worker_flags & FCOE_WORKER_TERMINATE) == 0) {
1159 1159 /*
1160 1160 * loop through the frames
1161 1161 */
1162 1162 while (fmi = list_head(&w->worker_frm_list)) {
1163 1163 list_remove(&w->worker_frm_list, fmi);
1164 1164 mutex_exit(&w->worker_lock);
1165 1165 /*
1166 1166 * do the checksum
1167 1167 */
1168 1168 ret = fcoe_crc_verify(fmi->fmi_frame);
1169 1169 if (ret == FCOE_SUCCESS) {
1170 1170 fmi->fmi_mac->fm_client.ect_rx_frame(
1171 1171 fmi->fmi_frame);
1172 1172 } else {
1173 1173 fcoe_release_frame(fmi->fmi_frame);
1174 1174 }
1175 1175 mutex_enter(&w->worker_lock);
1176 1176 w->worker_ntasks--;
1177 1177 }
1178 1178 w->worker_flags &= ~FCOE_WORKER_ACTIVE;
1179 1179 cv_wait(&w->worker_cv, &w->worker_lock);
1180 1180 w->worker_flags |= FCOE_WORKER_ACTIVE;
1181 1181 }
1182 1182 w->worker_flags &= ~(FCOE_WORKER_STARTED | FCOE_WORKER_ACTIVE);
1183 1183 mutex_exit(&w->worker_lock);
1184 1184 atomic_dec_32(&fcoe_nworkers_running);
1185 1185 list_destroy(&w->worker_frm_list);
1186 1186 }
1187 1187
1188 1188 void
1189 1189 fcoe_post_frame(fcoe_frame_t *frm)
1190 1190 {
1191 1191 fcoe_worker_t *w;
1192 1192 uint16_t oxid = FRM_OXID(frm);
1193 1193
1194 1194 w = &fcoe_workers[oxid % fcoe_nworkers_running];
1195 1195 mutex_enter(&w->worker_lock);
1196 1196 list_insert_tail(&w->worker_frm_list, frm->frm_fcoe_private);
1197 1197 w->worker_ntasks++;
1198 1198 if ((w->worker_flags & FCOE_WORKER_ACTIVE) == 0) {
1199 1199 cv_signal(&w->worker_cv);
1200 1200 }
1201 1201 mutex_exit(&w->worker_lock);
1202 1202 }
1203 1203
1204 1204 /*
1205 1205 * The max length of every LOG is 158
1206 1206 */
1207 1207 void
1208 1208 fcoe_trace(caddr_t ident, const char *fmt, ...)
1209 1209 {
1210 1210 va_list args;
1211 1211 char tbuf[160];
1212 1212 int len;
1213 1213 clock_t curclock;
1214 1214 clock_t usec;
1215 1215
1216 1216 if (fcoe_trace_on == 0) {
1217 1217 return;
1218 1218 }
1219 1219
1220 1220 curclock = ddi_get_lbolt();
1221 1221 usec = (curclock - fcoe_trace_start) * usec_per_tick;
1222 1222 len = snprintf(tbuf, 158, "%lu.%03lus 0t%lu %s ", (usec /
1223 1223 (1000 * 1000)), ((usec % (1000 * 1000)) / 1000),
1224 1224 curclock, (ident ? ident : "unknown"));
1225 1225 va_start(args, fmt);
1226 1226 len += vsnprintf(tbuf + len, 158 - len, fmt, args);
1227 1227 va_end(args);
1228 1228
1229 1229 if (len > 158) {
1230 1230 len = 158;
1231 1231 }
1232 1232 tbuf[len++] = '\n';
1233 1233 tbuf[len] = 0;
1234 1234
1235 1235 mutex_enter(&fcoe_trace_buf_lock);
1236 1236 bcopy(tbuf, &fcoe_trace_buf[fcoe_trace_buf_curndx], len+1);
1237 1237 fcoe_trace_buf_curndx += len;
1238 1238 if (fcoe_trace_buf_curndx > (fcoe_trace_buf_size - 320)) {
1239 1239 fcoe_trace_buf_curndx = 0;
1240 1240 }
1241 1241 mutex_exit(&fcoe_trace_buf_lock);
1242 1242 }
1243 1243
1244 1244 /*
1245 1245 * Check whether the pwwn or nwwn already exist or not
1246 1246 * Return value:
1247 1247 * 1: PWWN conflicted
1248 1248 * -1: NWWN conflicted
1249 1249 * 0: No conflict
1250 1250 */
1251 1251 static int
1252 1252 fcoe_cmp_wwn(fcoe_mac_t *checkedmac)
1253 1253 {
1254 1254 fcoe_mac_t *mac;
1255 1255 uint8_t *nwwn, *pwwn, *cnwwn, *cpwwn;
1256 1256
1257 1257 cnwwn = checkedmac->fm_eport.eport_nodewwn;
1258 1258 cpwwn = checkedmac->fm_eport.eport_portwwn;
1259 1259 ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
1260 1260
1261 1261 for (mac = list_head(&fcoe_global_ss->ss_mac_list); mac;
1262 1262 mac = list_next(&fcoe_global_ss->ss_mac_list, mac)) {
1263 1263 if (mac == checkedmac) {
1264 1264 continue;
1265 1265 }
1266 1266 nwwn = mac->fm_eport.eport_nodewwn;
1267 1267 pwwn = mac->fm_eport.eport_portwwn;
1268 1268
1269 1269 if (memcmp(nwwn, cnwwn, 8) == 0) {
1270 1270 return (-1);
1271 1271 }
1272 1272
1273 1273 if (memcmp(pwwn, cpwwn, 8) == 0) {
1274 1274 return (1);
1275 1275 }
1276 1276 }
1277 1277 return (0);
1278 1278 }
1279 1279
1280 1280 static int
1281 1281 fcoe_get_port_list(fcoe_port_instance_t *ports, int count)
1282 1282 {
1283 1283 fcoe_mac_t *mac = NULL;
1284 1284 int i = 0;
1285 1285
1286 1286 ASSERT(ports != NULL);
1287 1287 ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
1288 1288
1289 1289 for (mac = list_head(&fcoe_global_ss->ss_mac_list); mac;
1290 1290 mac = list_next(&fcoe_global_ss->ss_mac_list, mac)) {
1291 1291 if (i < count) {
1292 1292 bcopy(mac->fm_eport.eport_portwwn,
1293 1293 ports[i].fpi_pwwn, 8);
1294 1294 ports[i].fpi_mac_linkid = mac->fm_linkid;
1295 1295 bcopy(mac->fm_current_addr,
1296 1296 ports[i].fpi_mac_current_addr, ETHERADDRL);
1297 1297 bcopy(mac->fm_primary_addr,
1298 1298 ports[i].fpi_mac_factory_addr, ETHERADDRL);
1299 1299 ports[i].fpi_port_type =
1300 1300 EPORT_CLT_TYPE(&mac->fm_eport);
1301 1301 ports[i].fpi_mtu_size =
1302 1302 mac->fm_eport.eport_mtu;
1303 1303 ports[i].fpi_mac_promisc =
1304 1304 mac->fm_promisc_handle != NULL ? 1 : 0;
1305 1305 }
1306 1306 i++;
1307 1307 }
1308 1308 return (i);
1309 1309 }
↓ open down ↓ |
1086 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX