1 /* 2 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 * 17 * Maintained at www.Open-FCoE.org 18 */ 19 20 #include <linux/types.h> 21 #include <linux/module.h> 22 #include <linux/kernel.h> 23 #include <linux/list.h> 24 #include <linux/netdevice.h> 25 #include <linux/errno.h> 26 #include <linux/crc32.h> 27 #include <scsi/libfcoe.h> 28 29 #include "libfcoe.h" 30 31 MODULE_AUTHOR("Open-FCoE.org"); 32 MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs"); 33 MODULE_LICENSE("GPL v2"); 34 35 static int fcoe_transport_create(const char *, struct kernel_param *); 36 static int fcoe_transport_destroy(const char *, struct kernel_param *); 37 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp); 38 static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device); 39 static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device); 40 static int fcoe_transport_enable(const char *, struct kernel_param *); 41 static int fcoe_transport_disable(const char *, struct kernel_param *); 42 static int libfcoe_device_notification(struct notifier_block *notifier, 43 ulong event, void *ptr); 44 45 static LIST_HEAD(fcoe_transports); 46 static DEFINE_MUTEX(ft_mutex); 47 static LIST_HEAD(fcoe_netdevs); 48 static DEFINE_MUTEX(fn_mutex); 49 50 unsigned int libfcoe_debug_logging; 51 module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); 52 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); 53 54 module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR); 55 __MODULE_PARM_TYPE(show, "string"); 56 MODULE_PARM_DESC(show, " Show attached FCoE transports"); 57 58 module_param_call(create, fcoe_transport_create, NULL, 59 (void *)FIP_MODE_FABRIC, S_IWUSR); 60 __MODULE_PARM_TYPE(create, "string"); 61 MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface"); 62 63 module_param_call(create_vn2vn, fcoe_transport_create, NULL, 64 (void *)FIP_MODE_VN2VN, S_IWUSR); 65 __MODULE_PARM_TYPE(create_vn2vn, "string"); 66 MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance " 67 "on an Ethernet interface"); 68 69 module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR); 70 __MODULE_PARM_TYPE(destroy, "string"); 71 MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface"); 72 73 module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR); 74 __MODULE_PARM_TYPE(enable, "string"); 75 MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface."); 76 77 module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR); 78 __MODULE_PARM_TYPE(disable, "string"); 79 MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); 80 81 /* notification function for packets from net device */ 82 static struct notifier_block libfcoe_notifier = { 83 .notifier_call = libfcoe_device_notification, 84 }; 85 86 /** 87 * fcoe_fc_crc() - Calculates the CRC for a given frame 88 * @fp: The frame to be checksumed 89 * 90 * This uses crc32() routine to calculate the CRC for a frame 91 * 92 * Return: The 32 bit CRC value 93 */ 94 u32 fcoe_fc_crc(struct fc_frame *fp) 95 { 96 struct sk_buff *skb = fp_skb(fp); 97 struct skb_frag_struct *frag; 98 unsigned char *data; 99 unsigned long off, len, clen; 100 u32 crc; 101 unsigned i; 102 103 crc = crc32(~0, skb->data, skb_headlen(skb)); 104 105 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 106 frag = &skb_shinfo(skb)->frags[i]; 107 off = frag->page_offset; 108 len = frag->size; 109 while (len > 0) { 110 clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); 111 data = kmap_atomic(frag->page + (off >> PAGE_SHIFT), 112 KM_SKB_DATA_SOFTIRQ); 113 crc = crc32(crc, data + (off & ~PAGE_MASK), clen); 114 kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ); 115 off += clen; 116 len -= clen; 117 } 118 } 119 return crc; 120 } 121 EXPORT_SYMBOL_GPL(fcoe_fc_crc); 122 123 /** 124 * fcoe_start_io() - Start FCoE I/O 125 * @skb: The packet to be transmitted 126 * 127 * This routine is called from the net device to start transmitting 128 * FCoE packets. 129 * 130 * Returns: 0 for success 131 */ 132 int fcoe_start_io(struct sk_buff *skb) 133 { 134 struct sk_buff *nskb; 135 int rc; 136 137 nskb = skb_clone(skb, GFP_ATOMIC); 138 if (!nskb) 139 return -ENOMEM; 140 rc = dev_queue_xmit(nskb); 141 if (rc != 0) 142 return rc; 143 kfree_skb(skb); 144 return 0; 145 } 146 EXPORT_SYMBOL_GPL(fcoe_start_io); 147 148 149 /** 150 * fcoe_clean_pending_queue() - Dequeue a skb and free it 151 * @lport: The local port to dequeue a skb on 152 */ 153 void fcoe_clean_pending_queue(struct fc_lport *lport) 154 { 155 struct fcoe_port *port = lport_priv(lport); 156 struct sk_buff *skb; 157 158 spin_lock_bh(&port->fcoe_pending_queue.lock); 159 while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) { 160 spin_unlock_bh(&port->fcoe_pending_queue.lock); 161 kfree_skb(skb); 162 spin_lock_bh(&port->fcoe_pending_queue.lock); 163 } 164 spin_unlock_bh(&port->fcoe_pending_queue.lock); 165 } 166 EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); 167 168 /** 169 * fcoe_check_wait_queue() - Attempt to clear the transmit backlog 170 * @lport: The local port whose backlog is to be cleared 171 * 172 * This empties the wait_queue, dequeues the head of the wait_queue queue 173 * and calls fcoe_start_io() for each packet. If all skb have been 174 * transmitted it returns the qlen. If an error occurs it restores 175 * wait_queue (to try again later) and returns -1. 176 * 177 * The wait_queue is used when the skb transmit fails. The failed skb 178 * will go in the wait_queue which will be emptied by the timer function or 179 * by the next skb transmit. 180 */ 181 void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb) 182 { 183 struct fcoe_port *port = lport_priv(lport); 184 int rc; 185 186 spin_lock_bh(&port->fcoe_pending_queue.lock); 187 188 if (skb) 189 __skb_queue_tail(&port->fcoe_pending_queue, skb); 190 191 if (port->fcoe_pending_queue_active) 192 goto out; 193 port->fcoe_pending_queue_active = 1; 194 195 while (port->fcoe_pending_queue.qlen) { 196 /* keep qlen > 0 until fcoe_start_io succeeds */ 197 port->fcoe_pending_queue.qlen++; 198 skb = __skb_dequeue(&port->fcoe_pending_queue); 199 200 spin_unlock_bh(&port->fcoe_pending_queue.lock); 201 rc = fcoe_start_io(skb); 202 spin_lock_bh(&port->fcoe_pending_queue.lock); 203 204 if (rc) { 205 __skb_queue_head(&port->fcoe_pending_queue, skb); 206 /* undo temporary increment above */ 207 port->fcoe_pending_queue.qlen--; 208 break; 209 } 210 /* undo temporary increment above */ 211 port->fcoe_pending_queue.qlen--; 212 } 213 214 if (port->fcoe_pending_queue.qlen < port->min_queue_depth) 215 lport->qfull = 0; 216 if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) 217 mod_timer(&port->timer, jiffies + 2); 218 port->fcoe_pending_queue_active = 0; 219 out: 220 if (port->fcoe_pending_queue.qlen > port->max_queue_depth) 221 lport->qfull = 1; 222 spin_unlock_bh(&port->fcoe_pending_queue.lock); 223 } 224 EXPORT_SYMBOL_GPL(fcoe_check_wait_queue); 225 226 /** 227 * fcoe_queue_timer() - The fcoe queue timer 228 * @lport: The local port 229 * 230 * Calls fcoe_check_wait_queue on timeout 231 */ 232 void fcoe_queue_timer(ulong lport) 233 { 234 fcoe_check_wait_queue((struct fc_lport *)lport, NULL); 235 } 236 EXPORT_SYMBOL_GPL(fcoe_queue_timer); 237 238 /** 239 * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC 240 * @skb: The packet to be transmitted 241 * @tlen: The total length of the trailer 242 * @fps: The fcoe context 243 * 244 * This routine allocates a page for frame trailers. The page is re-used if 245 * there is enough room left on it for the current trailer. If there isn't 246 * enough buffer left a new page is allocated for the trailer. Reference to 247 * the page from this function as well as the skbs using the page fragments 248 * ensure that the page is freed at the appropriate time. 249 * 250 * Returns: 0 for success 251 */ 252 int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen, 253 struct fcoe_percpu_s *fps) 254 { 255 struct page *page; 256 257 page = fps->crc_eof_page; 258 if (!page) { 259 page = alloc_page(GFP_ATOMIC); 260 if (!page) 261 return -ENOMEM; 262 263 fps->crc_eof_page = page; 264 fps->crc_eof_offset = 0; 265 } 266 267 get_page(page); 268 skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 269 fps->crc_eof_offset, tlen); 270 skb->len += tlen; 271 skb->data_len += tlen; 272 skb->truesize += tlen; 273 fps->crc_eof_offset += sizeof(struct fcoe_crc_eof); 274 275 if (fps->crc_eof_offset >= PAGE_SIZE) { 276 fps->crc_eof_page = NULL; 277 fps->crc_eof_offset = 0; 278 put_page(page); 279 } 280 281 return 0; 282 } 283 EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof); 284 285 /** 286 * fcoe_transport_lookup - find an fcoe transport that matches a netdev 287 * @netdev: The netdev to look for from all attached transports 288 * 289 * Returns : ptr to the fcoe transport that supports this netdev or NULL 290 * if not found. 291 * 292 * The ft_mutex should be held when this is called 293 */ 294 static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev) 295 { 296 struct fcoe_transport *ft = NULL; 297 298 list_for_each_entry(ft, &fcoe_transports, list) 299 if (ft->match && ft->match(netdev)) 300 return ft; 301 return NULL; 302 } 303 304 /** 305 * fcoe_transport_attach - Attaches an FCoE transport 306 * @ft: The fcoe transport to be attached 307 * 308 * Returns : 0 for success 309 */ 310 int fcoe_transport_attach(struct fcoe_transport *ft) 311 { 312 int rc = 0; 313 314 mutex_lock(&ft_mutex); 315 if (ft->attached) { 316 LIBFCOE_TRANSPORT_DBG("transport %s already attached\n", 317 ft->name); 318 rc = -EEXIST; 319 goto out_attach; 320 } 321 322 /* Add default transport to the tail */ 323 if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT)) 324 list_add(&ft->list, &fcoe_transports); 325 else 326 list_add_tail(&ft->list, &fcoe_transports); 327 328 ft->attached = true; 329 LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name); 330 331 out_attach: 332 mutex_unlock(&ft_mutex); 333 return rc; 334 } 335 EXPORT_SYMBOL(fcoe_transport_attach); 336 337 /** 338 * fcoe_transport_detach - Detaches an FCoE transport 339 * @ft: The fcoe transport to be attached 340 * 341 * Returns : 0 for success 342 */ 343 int fcoe_transport_detach(struct fcoe_transport *ft) 344 { 345 int rc = 0; 346 struct fcoe_netdev_mapping *nm = NULL, *tmp; 347 348 mutex_lock(&ft_mutex); 349 if (!ft->attached) { 350 LIBFCOE_TRANSPORT_DBG("transport %s already detached\n", 351 ft->name); 352 rc = -ENODEV; 353 goto out_attach; 354 } 355 356 /* remove netdev mapping for this transport as it is going away */ 357 mutex_lock(&fn_mutex); 358 list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) { 359 if (nm->ft == ft) { 360 LIBFCOE_TRANSPORT_DBG("transport %s going away, " 361 "remove its netdev mapping for %s\n", 362 ft->name, nm->netdev->name); 363 list_del(&nm->list); 364 kfree(nm); 365 } 366 } 367 mutex_unlock(&fn_mutex); 368 369 list_del(&ft->list); 370 ft->attached = false; 371 LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name); 372 373 out_attach: 374 mutex_unlock(&ft_mutex); 375 return rc; 376 377 } 378 EXPORT_SYMBOL(fcoe_transport_detach); 379 380 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp) 381 { 382 int i, j; 383 struct fcoe_transport *ft = NULL; 384 385 i = j = sprintf(buffer, "Attached FCoE transports:"); 386 mutex_lock(&ft_mutex); 387 list_for_each_entry(ft, &fcoe_transports, list) { 388 if (i >= PAGE_SIZE - IFNAMSIZ) 389 break; 390 i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name); 391 } 392 mutex_unlock(&ft_mutex); 393 if (i == j) 394 i += snprintf(&buffer[i], IFNAMSIZ, "none"); 395 return i; 396 } 397 398 static int __init fcoe_transport_init(void) 399 { 400 register_netdevice_notifier(&libfcoe_notifier); 401 return 0; 402 } 403 404 static int __exit fcoe_transport_exit(void) 405 { 406 struct fcoe_transport *ft; 407 408 unregister_netdevice_notifier(&libfcoe_notifier); 409 mutex_lock(&ft_mutex); 410 list_for_each_entry(ft, &fcoe_transports, list) 411 printk(KERN_ERR "FCoE transport %s is still attached!\n", 412 ft->name); 413 mutex_unlock(&ft_mutex); 414 return 0; 415 } 416 417 418 static int fcoe_add_netdev_mapping(struct net_device *netdev, 419 struct fcoe_transport *ft) 420 { 421 struct fcoe_netdev_mapping *nm; 422 423 nm = kmalloc(sizeof(*nm), GFP_KERNEL); 424 if (!nm) { 425 printk(KERN_ERR "Unable to allocate netdev_mapping"); 426 return -ENOMEM; 427 } 428 429 nm->netdev = netdev; 430 nm->ft = ft; 431 432 mutex_lock(&fn_mutex); 433 list_add(&nm->list, &fcoe_netdevs); 434 mutex_unlock(&fn_mutex); 435 return 0; 436 } 437 438 439 static void fcoe_del_netdev_mapping(struct net_device *netdev) 440 { 441 struct fcoe_netdev_mapping *nm = NULL, *tmp; 442 443 mutex_lock(&fn_mutex); 444 list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) { 445 if (nm->netdev == netdev) { 446 list_del(&nm->list); 447 kfree(nm); 448 mutex_unlock(&fn_mutex); 449 return; 450 } 451 } 452 mutex_unlock(&fn_mutex); 453 } 454 455 456 /** 457 * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which 458 * it was created 459 * 460 * Returns : ptr to the fcoe transport that supports this netdev or NULL 461 * if not found. 462 * 463 * The ft_mutex should be held when this is called 464 */ 465 static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev) 466 { 467 struct fcoe_transport *ft = NULL; 468 struct fcoe_netdev_mapping *nm; 469 470 mutex_lock(&fn_mutex); 471 list_for_each_entry(nm, &fcoe_netdevs, list) { 472 if (netdev == nm->netdev) { 473 ft = nm->ft; 474 mutex_unlock(&fn_mutex); 475 return ft; 476 } 477 } 478 479 mutex_unlock(&fn_mutex); 480 return NULL; 481 } 482 483 /** 484 * fcoe_if_to_netdev() - Parse a name buffer to get a net device 485 * @buffer: The name of the net device 486 * 487 * Returns: NULL or a ptr to net_device 488 */ 489 static struct net_device *fcoe_if_to_netdev(const char *buffer) 490 { 491 char *cp; 492 char ifname[IFNAMSIZ + 2]; 493 494 if (buffer) { 495 strlcpy(ifname, buffer, IFNAMSIZ); 496 cp = ifname + strlen(ifname); 497 while (--cp >= ifname && *cp == '\n') 498 *cp = '\0'; 499 return dev_get_by_name(&init_net, ifname); 500 } 501 return NULL; 502 } 503 504 /** 505 * libfcoe_device_notification() - Handler for net device events 506 * @notifier: The context of the notification 507 * @event: The type of event 508 * @ptr: The net device that the event was on 509 * 510 * This function is called by the Ethernet driver in case of link change event. 511 * 512 * Returns: 0 for success 513 */ 514 static int libfcoe_device_notification(struct notifier_block *notifier, 515 ulong event, void *ptr) 516 { 517 struct net_device *netdev = ptr; 518 519 switch (event) { 520 case NETDEV_UNREGISTER: 521 printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n", 522 netdev->name); 523 fcoe_del_netdev_mapping(netdev); 524 break; 525 } 526 return NOTIFY_OK; 527 } 528 529 530 /** 531 * fcoe_transport_create() - Create a fcoe interface 532 * @buffer: The name of the Ethernet interface to create on 533 * @kp: The associated kernel param 534 * 535 * Called from sysfs. This holds the ft_mutex while calling the 536 * registered fcoe transport's create function. 537 * 538 * Returns: 0 for success 539 */ 540 static int fcoe_transport_create(const char *buffer, struct kernel_param *kp) 541 { 542 int rc = -ENODEV; 543 struct net_device *netdev = NULL; 544 struct fcoe_transport *ft = NULL; 545 enum fip_state fip_mode = (enum fip_state)(long)kp->arg; 546 547 mutex_lock(&ft_mutex); 548 549 netdev = fcoe_if_to_netdev(buffer); 550 if (!netdev) { 551 LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer); 552 goto out_nodev; 553 } 554 555 ft = fcoe_netdev_map_lookup(netdev); 556 if (ft) { 557 LIBFCOE_TRANSPORT_DBG("transport %s already has existing " 558 "FCoE instance on %s.\n", 559 ft->name, netdev->name); 560 rc = -EEXIST; 561 goto out_putdev; 562 } 563 564 ft = fcoe_transport_lookup(netdev); 565 if (!ft) { 566 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", 567 netdev->name); 568 goto out_putdev; 569 } 570 571 rc = fcoe_add_netdev_mapping(netdev, ft); 572 if (rc) { 573 LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping " 574 "for FCoE transport %s for %s.\n", 575 ft->name, netdev->name); 576 goto out_putdev; 577 } 578 579 /* pass to transport create */ 580 rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV; 581 if (rc) 582 fcoe_del_netdev_mapping(netdev); 583 584 LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n", 585 ft->name, (rc) ? "failed" : "succeeded", 586 netdev->name); 587 588 out_putdev: 589 dev_put(netdev); 590 out_nodev: 591 mutex_unlock(&ft_mutex); 592 return rc; 593 } 594 595 /** 596 * fcoe_transport_destroy() - Destroy a FCoE interface 597 * @buffer: The name of the Ethernet interface to be destroyed 598 * @kp: The associated kernel parameter 599 * 600 * Called from sysfs. This holds the ft_mutex while calling the 601 * registered fcoe transport's destroy function. 602 * 603 * Returns: 0 for success 604 */ 605 static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp) 606 { 607 int rc = -ENODEV; 608 struct net_device *netdev = NULL; 609 struct fcoe_transport *ft = NULL; 610 611 mutex_lock(&ft_mutex); 612 613 netdev = fcoe_if_to_netdev(buffer); 614 if (!netdev) { 615 LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer); 616 goto out_nodev; 617 } 618 619 ft = fcoe_netdev_map_lookup(netdev); 620 if (!ft) { 621 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", 622 netdev->name); 623 goto out_putdev; 624 } 625 626 /* pass to transport destroy */ 627 rc = ft->destroy ? ft->destroy(netdev) : -ENODEV; 628 fcoe_del_netdev_mapping(netdev); 629 LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n", 630 ft->name, (rc) ? "failed" : "succeeded", 631 netdev->name); 632 633 out_putdev: 634 dev_put(netdev); 635 out_nodev: 636 mutex_unlock(&ft_mutex); 637 return rc; 638 } 639 640 /** 641 * fcoe_transport_disable() - Disables a FCoE interface 642 * @buffer: The name of the Ethernet interface to be disabled 643 * @kp: The associated kernel parameter 644 * 645 * Called from sysfs. 646 * 647 * Returns: 0 for success 648 */ 649 static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp) 650 { 651 int rc = -ENODEV; 652 struct net_device *netdev = NULL; 653 struct fcoe_transport *ft = NULL; 654 655 mutex_lock(&ft_mutex); 656 657 netdev = fcoe_if_to_netdev(buffer); 658 if (!netdev) 659 goto out_nodev; 660 661 ft = fcoe_netdev_map_lookup(netdev); 662 if (!ft) 663 goto out_putdev; 664 665 rc = ft->disable ? ft->disable(netdev) : -ENODEV; 666 667 out_putdev: 668 dev_put(netdev); 669 out_nodev: 670 mutex_unlock(&ft_mutex); 671 672 if (rc == -ERESTARTSYS) 673 return restart_syscall(); 674 else 675 return rc; 676 } 677 678 /** 679 * fcoe_transport_enable() - Enables a FCoE interface 680 * @buffer: The name of the Ethernet interface to be enabled 681 * @kp: The associated kernel parameter 682 * 683 * Called from sysfs. 684 * 685 * Returns: 0 for success 686 */ 687 static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) 688 { 689 int rc = -ENODEV; 690 struct net_device *netdev = NULL; 691 struct fcoe_transport *ft = NULL; 692 693 mutex_lock(&ft_mutex); 694 695 netdev = fcoe_if_to_netdev(buffer); 696 if (!netdev) 697 goto out_nodev; 698 699 ft = fcoe_netdev_map_lookup(netdev); 700 if (!ft) 701 goto out_putdev; 702 703 rc = ft->enable ? ft->enable(netdev) : -ENODEV; 704 705 out_putdev: 706 dev_put(netdev); 707 out_nodev: 708 mutex_unlock(&ft_mutex); 709 return rc; 710 } 711 712 /** 713 * libfcoe_init() - Initialization routine for libfcoe.ko 714 */ 715 static int __init libfcoe_init(void) 716 { 717 fcoe_transport_init(); 718 719 return 0; 720 } 721 module_init(libfcoe_init); 722 723 /** 724 * libfcoe_exit() - Tear down libfcoe.ko 725 */ 726 static void __exit libfcoe_exit(void) 727 { 728 fcoe_transport_exit(); 729 } 730 module_exit(libfcoe_exit); 731