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 31MODULE_AUTHOR("Open-FCoE.org"); 32MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs"); 33MODULE_LICENSE("GPL v2"); 34 35static int fcoe_transport_create(const char *, struct kernel_param *); 36static int fcoe_transport_destroy(const char *, struct kernel_param *); 37static int fcoe_transport_show(char *buffer, const struct kernel_param *kp); 38static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device); 39static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device); 40static int fcoe_transport_enable(const char *, struct kernel_param *); 41static int fcoe_transport_disable(const char *, struct kernel_param *); 42static int libfcoe_device_notification(struct notifier_block *notifier, 43 ulong event, void *ptr); 44 45static LIST_HEAD(fcoe_transports); 46static DEFINE_MUTEX(ft_mutex); 47static LIST_HEAD(fcoe_netdevs); 48static DEFINE_MUTEX(fn_mutex); 49 50unsigned int libfcoe_debug_logging; 51module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); 52MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); 53 54module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR); 55__MODULE_PARM_TYPE(show, "string"); 56MODULE_PARM_DESC(show, " Show attached FCoE transports"); 57 58module_param_call(create, fcoe_transport_create, NULL, 59 (void *)FIP_MODE_FABRIC, S_IWUSR); 60__MODULE_PARM_TYPE(create, "string"); 61MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface"); 62 63module_param_call(create_vn2vn, fcoe_transport_create, NULL, 64 (void *)FIP_MODE_VN2VN, S_IWUSR); 65__MODULE_PARM_TYPE(create_vn2vn, "string"); 66MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance " 67 "on an Ethernet interface"); 68 69module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR); 70__MODULE_PARM_TYPE(destroy, "string"); 71MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface"); 72 73module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR); 74__MODULE_PARM_TYPE(enable, "string"); 75MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface."); 76 77module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR); 78__MODULE_PARM_TYPE(disable, "string"); 79MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); 80 81/* notification function for packets from net device */ 82static struct notifier_block libfcoe_notifier = { 83 .notifier_call = libfcoe_device_notification, 84}; 85 86/** 87 * fcoe_link_speed_update() - Update the supported and actual link speeds 88 * @lport: The local port to update speeds for 89 * 90 * Returns: 0 if the ethtool query was successful 91 * -1 if the ethtool query failed 92 */ 93int fcoe_link_speed_update(struct fc_lport *lport) 94{ 95 struct net_device *netdev = fcoe_get_netdev(lport); 96 struct ethtool_cmd ecmd; 97 98 if (!__ethtool_get_settings(netdev, &ecmd)) { 99 lport->link_supported_speeds &= ~(FC_PORTSPEED_1GBIT | 100 FC_PORTSPEED_10GBIT | 101 FC_PORTSPEED_20GBIT | 102 FC_PORTSPEED_40GBIT); 103 104 if (ecmd.supported & (SUPPORTED_1000baseT_Half | 105 SUPPORTED_1000baseT_Full | 106 SUPPORTED_1000baseKX_Full)) 107 lport->link_supported_speeds |= FC_PORTSPEED_1GBIT; 108 109 if (ecmd.supported & (SUPPORTED_10000baseT_Full | 110 SUPPORTED_10000baseKX4_Full | 111 SUPPORTED_10000baseKR_Full | 112 SUPPORTED_10000baseR_FEC)) 113 lport->link_supported_speeds |= FC_PORTSPEED_10GBIT; 114 115 if (ecmd.supported & (SUPPORTED_20000baseMLD2_Full | 116 SUPPORTED_20000baseKR2_Full)) 117 lport->link_supported_speeds |= FC_PORTSPEED_20GBIT; 118 119 if (ecmd.supported & (SUPPORTED_40000baseKR4_Full | 120 SUPPORTED_40000baseCR4_Full | 121 SUPPORTED_40000baseSR4_Full | 122 SUPPORTED_40000baseLR4_Full)) 123 lport->link_supported_speeds |= FC_PORTSPEED_40GBIT; 124 125 switch (ethtool_cmd_speed(&ecmd)) { 126 case SPEED_1000: 127 lport->link_speed = FC_PORTSPEED_1GBIT; 128 break; 129 case SPEED_10000: 130 lport->link_speed = FC_PORTSPEED_10GBIT; 131 break; 132 case 20000: 133 lport->link_speed = FC_PORTSPEED_20GBIT; 134 break; 135 case 40000: 136 lport->link_speed = FC_PORTSPEED_40GBIT; 137 break; 138 default: 139 lport->link_speed = FC_PORTSPEED_UNKNOWN; 140 break; 141 } 142 return 0; 143 } 144 return -1; 145} 146EXPORT_SYMBOL_GPL(fcoe_link_speed_update); 147 148/** 149 * __fcoe_get_lesb() - Get the Link Error Status Block (LESB) for a given lport 150 * @lport: The local port to update speeds for 151 * @fc_lesb: Pointer to the LESB to be filled up 152 * @netdev: Pointer to the netdev that is associated with the lport 153 * 154 * Note, the Link Error Status Block (LESB) for FCoE is defined in FC-BB-6 155 * Clause 7.11 in v1.04. 156 */ 157void __fcoe_get_lesb(struct fc_lport *lport, 158 struct fc_els_lesb *fc_lesb, 159 struct net_device *netdev) 160{ 161 unsigned int cpu; 162 u32 lfc, vlfc, mdac; 163 struct fc_stats *stats; 164 struct fcoe_fc_els_lesb *lesb; 165 struct rtnl_link_stats64 temp; 166 167 lfc = 0; 168 vlfc = 0; 169 mdac = 0; 170 lesb = (struct fcoe_fc_els_lesb *)fc_lesb; 171 memset(lesb, 0, sizeof(*lesb)); 172 for_each_possible_cpu(cpu) { 173 stats = per_cpu_ptr(lport->stats, cpu); 174 lfc += stats->LinkFailureCount; 175 vlfc += stats->VLinkFailureCount; 176 mdac += stats->MissDiscAdvCount; 177 } 178 lesb->lesb_link_fail = htonl(lfc); 179 lesb->lesb_vlink_fail = htonl(vlfc); 180 lesb->lesb_miss_fka = htonl(mdac); 181 lesb->lesb_fcs_error = 182 htonl(dev_get_stats(netdev, &temp)->rx_crc_errors); 183} 184EXPORT_SYMBOL_GPL(__fcoe_get_lesb); 185 186/** 187 * fcoe_get_lesb() - Fill the FCoE Link Error Status Block 188 * @lport: the local port 189 * @fc_lesb: the link error status block 190 */ 191void fcoe_get_lesb(struct fc_lport *lport, 192 struct fc_els_lesb *fc_lesb) 193{ 194 struct net_device *netdev = fcoe_get_netdev(lport); 195 196 __fcoe_get_lesb(lport, fc_lesb, netdev); 197} 198EXPORT_SYMBOL_GPL(fcoe_get_lesb); 199 200/** 201 * fcoe_ctlr_get_lesb() - Get the Link Error Status Block (LESB) for a given 202 * fcoe controller device 203 * @ctlr_dev: The given fcoe controller device 204 * 205 */ 206void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev) 207{ 208 struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); 209 struct net_device *netdev = fcoe_get_netdev(fip->lp); 210 struct fc_els_lesb *fc_lesb; 211 212 fc_lesb = (struct fc_els_lesb *)(&ctlr_dev->lesb); 213 __fcoe_get_lesb(fip->lp, fc_lesb, netdev); 214} 215EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb); 216 217void fcoe_wwn_to_str(u64 wwn, char *buf, int len) 218{ 219 u8 wwpn[8]; 220 221 u64_to_wwn(wwn, wwpn); 222 snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x", 223 wwpn[0], wwpn[1], wwpn[2], wwpn[3], 224 wwpn[4], wwpn[5], wwpn[6], wwpn[7]); 225} 226EXPORT_SYMBOL_GPL(fcoe_wwn_to_str); 227 228/** 229 * fcoe_validate_vport_create() - Validate a vport before creating it 230 * @vport: NPIV port to be created 231 * 232 * This routine is meant to add validation for a vport before creating it 233 * via fcoe_vport_create(). 234 * Current validations are: 235 * - WWPN supplied is unique for given lport 236 */ 237int fcoe_validate_vport_create(struct fc_vport *vport) 238{ 239 struct Scsi_Host *shost = vport_to_shost(vport); 240 struct fc_lport *n_port = shost_priv(shost); 241 struct fc_lport *vn_port; 242 int rc = 0; 243 char buf[32]; 244 245 mutex_lock(&n_port->lp_mutex); 246 247 fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf)); 248 /* Check if the wwpn is not same as that of the lport */ 249 if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) { 250 LIBFCOE_TRANSPORT_DBG("vport WWPN 0x%s is same as that of the " 251 "base port WWPN\n", buf); 252 rc = -EINVAL; 253 goto out; 254 } 255 256 /* Check if there is any existing vport with same wwpn */ 257 list_for_each_entry(vn_port, &n_port->vports, list) { 258 if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) { 259 LIBFCOE_TRANSPORT_DBG("vport with given WWPN 0x%s " 260 "already exists\n", buf); 261 rc = -EINVAL; 262 break; 263 } 264 } 265out: 266 mutex_unlock(&n_port->lp_mutex); 267 return rc; 268} 269EXPORT_SYMBOL_GPL(fcoe_validate_vport_create); 270 271/** 272 * fcoe_get_wwn() - Get the world wide name from LLD if it supports it 273 * @netdev: the associated net device 274 * @wwn: the output WWN 275 * @type: the type of WWN (WWPN or WWNN) 276 * 277 * Returns: 0 for success 278 */ 279int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type) 280{ 281 const struct net_device_ops *ops = netdev->netdev_ops; 282 283 if (ops->ndo_fcoe_get_wwn) 284 return ops->ndo_fcoe_get_wwn(netdev, wwn, type); 285 return -EINVAL; 286} 287EXPORT_SYMBOL_GPL(fcoe_get_wwn); 288 289/** 290 * fcoe_fc_crc() - Calculates the CRC for a given frame 291 * @fp: The frame to be checksumed 292 * 293 * This uses crc32() routine to calculate the CRC for a frame 294 * 295 * Return: The 32 bit CRC value 296 */ 297u32 fcoe_fc_crc(struct fc_frame *fp) 298{ 299 struct sk_buff *skb = fp_skb(fp); 300 struct skb_frag_struct *frag; 301 unsigned char *data; 302 unsigned long off, len, clen; 303 u32 crc; 304 unsigned i; 305 306 crc = crc32(~0, skb->data, skb_headlen(skb)); 307 308 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 309 frag = &skb_shinfo(skb)->frags[i]; 310 off = frag->page_offset; 311 len = skb_frag_size(frag); 312 while (len > 0) { 313 clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); 314 data = kmap_atomic( 315 skb_frag_page(frag) + (off >> PAGE_SHIFT)); 316 crc = crc32(crc, data + (off & ~PAGE_MASK), clen); 317 kunmap_atomic(data); 318 off += clen; 319 len -= clen; 320 } 321 } 322 return crc; 323} 324EXPORT_SYMBOL_GPL(fcoe_fc_crc); 325 326/** 327 * fcoe_start_io() - Start FCoE I/O 328 * @skb: The packet to be transmitted 329 * 330 * This routine is called from the net device to start transmitting 331 * FCoE packets. 332 * 333 * Returns: 0 for success 334 */ 335int fcoe_start_io(struct sk_buff *skb) 336{ 337 struct sk_buff *nskb; 338 int rc; 339 340 nskb = skb_clone(skb, GFP_ATOMIC); 341 if (!nskb) 342 return -ENOMEM; 343 rc = dev_queue_xmit(nskb); 344 if (rc != 0) 345 return rc; 346 kfree_skb(skb); 347 return 0; 348} 349EXPORT_SYMBOL_GPL(fcoe_start_io); 350 351 352/** 353 * fcoe_clean_pending_queue() - Dequeue a skb and free it 354 * @lport: The local port to dequeue a skb on 355 */ 356void fcoe_clean_pending_queue(struct fc_lport *lport) 357{ 358 struct fcoe_port *port = lport_priv(lport); 359 struct sk_buff *skb; 360 361 spin_lock_bh(&port->fcoe_pending_queue.lock); 362 while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) { 363 spin_unlock_bh(&port->fcoe_pending_queue.lock); 364 kfree_skb(skb); 365 spin_lock_bh(&port->fcoe_pending_queue.lock); 366 } 367 spin_unlock_bh(&port->fcoe_pending_queue.lock); 368} 369EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); 370 371/** 372 * fcoe_check_wait_queue() - Attempt to clear the transmit backlog 373 * @lport: The local port whose backlog is to be cleared 374 * 375 * This empties the wait_queue, dequeues the head of the wait_queue queue 376 * and calls fcoe_start_io() for each packet. If all skb have been 377 * transmitted it returns the qlen. If an error occurs it restores 378 * wait_queue (to try again later) and returns -1. 379 * 380 * The wait_queue is used when the skb transmit fails. The failed skb 381 * will go in the wait_queue which will be emptied by the timer function or 382 * by the next skb transmit. 383 */ 384void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb) 385{ 386 struct fcoe_port *port = lport_priv(lport); 387 int rc; 388 389 spin_lock_bh(&port->fcoe_pending_queue.lock); 390 391 if (skb) 392 __skb_queue_tail(&port->fcoe_pending_queue, skb); 393 394 if (port->fcoe_pending_queue_active) 395 goto out; 396 port->fcoe_pending_queue_active = 1; 397 398 while (port->fcoe_pending_queue.qlen) { 399 /* keep qlen > 0 until fcoe_start_io succeeds */ 400 port->fcoe_pending_queue.qlen++; 401 skb = __skb_dequeue(&port->fcoe_pending_queue); 402 403 spin_unlock_bh(&port->fcoe_pending_queue.lock); 404 rc = fcoe_start_io(skb); 405 spin_lock_bh(&port->fcoe_pending_queue.lock); 406 407 if (rc) { 408 __skb_queue_head(&port->fcoe_pending_queue, skb); 409 /* undo temporary increment above */ 410 port->fcoe_pending_queue.qlen--; 411 break; 412 } 413 /* undo temporary increment above */ 414 port->fcoe_pending_queue.qlen--; 415 } 416 417 if (port->fcoe_pending_queue.qlen < port->min_queue_depth) 418 lport->qfull = 0; 419 if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) 420 mod_timer(&port->timer, jiffies + 2); 421 port->fcoe_pending_queue_active = 0; 422out: 423 if (port->fcoe_pending_queue.qlen > port->max_queue_depth) 424 lport->qfull = 1; 425 spin_unlock_bh(&port->fcoe_pending_queue.lock); 426} 427EXPORT_SYMBOL_GPL(fcoe_check_wait_queue); 428 429/** 430 * fcoe_queue_timer() - The fcoe queue timer 431 * @lport: The local port 432 * 433 * Calls fcoe_check_wait_queue on timeout 434 */ 435void fcoe_queue_timer(ulong lport) 436{ 437 fcoe_check_wait_queue((struct fc_lport *)lport, NULL); 438} 439EXPORT_SYMBOL_GPL(fcoe_queue_timer); 440 441/** 442 * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC 443 * @skb: The packet to be transmitted 444 * @tlen: The total length of the trailer 445 * @fps: The fcoe context 446 * 447 * This routine allocates a page for frame trailers. The page is re-used if 448 * there is enough room left on it for the current trailer. If there isn't 449 * enough buffer left a new page is allocated for the trailer. Reference to 450 * the page from this function as well as the skbs using the page fragments 451 * ensure that the page is freed at the appropriate time. 452 * 453 * Returns: 0 for success 454 */ 455int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen, 456 struct fcoe_percpu_s *fps) 457{ 458 struct page *page; 459 460 page = fps->crc_eof_page; 461 if (!page) { 462 page = alloc_page(GFP_ATOMIC); 463 if (!page) 464 return -ENOMEM; 465 466 fps->crc_eof_page = page; 467 fps->crc_eof_offset = 0; 468 } 469 470 get_page(page); 471 skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 472 fps->crc_eof_offset, tlen); 473 skb->len += tlen; 474 skb->data_len += tlen; 475 skb->truesize += tlen; 476 fps->crc_eof_offset += sizeof(struct fcoe_crc_eof); 477 478 if (fps->crc_eof_offset >= PAGE_SIZE) { 479 fps->crc_eof_page = NULL; 480 fps->crc_eof_offset = 0; 481 put_page(page); 482 } 483 484 return 0; 485} 486EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof); 487 488/** 489 * fcoe_transport_lookup - find an fcoe transport that matches a netdev 490 * @netdev: The netdev to look for from all attached transports 491 * 492 * Returns : ptr to the fcoe transport that supports this netdev or NULL 493 * if not found. 494 * 495 * The ft_mutex should be held when this is called 496 */ 497static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev) 498{ 499 struct fcoe_transport *ft = NULL; 500 501 list_for_each_entry(ft, &fcoe_transports, list) 502 if (ft->match && ft->match(netdev)) 503 return ft; 504 return NULL; 505} 506 507/** 508 * fcoe_transport_attach - Attaches an FCoE transport 509 * @ft: The fcoe transport to be attached 510 * 511 * Returns : 0 for success 512 */ 513int fcoe_transport_attach(struct fcoe_transport *ft) 514{ 515 int rc = 0; 516 517 mutex_lock(&ft_mutex); 518 if (ft->attached) { 519 LIBFCOE_TRANSPORT_DBG("transport %s already attached\n", 520 ft->name); 521 rc = -EEXIST; 522 goto out_attach; 523 } 524 525 /* Add default transport to the tail */ 526 if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT)) 527 list_add(&ft->list, &fcoe_transports); 528 else 529 list_add_tail(&ft->list, &fcoe_transports); 530 531 ft->attached = true; 532 LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name); 533 534out_attach: 535 mutex_unlock(&ft_mutex); 536 return rc; 537} 538EXPORT_SYMBOL(fcoe_transport_attach); 539 540/** 541 * fcoe_transport_detach - Detaches an FCoE transport 542 * @ft: The fcoe transport to be attached 543 * 544 * Returns : 0 for success 545 */ 546int fcoe_transport_detach(struct fcoe_transport *ft) 547{ 548 int rc = 0; 549 struct fcoe_netdev_mapping *nm = NULL, *tmp; 550 551 mutex_lock(&ft_mutex); 552 if (!ft->attached) { 553 LIBFCOE_TRANSPORT_DBG("transport %s already detached\n", 554 ft->name); 555 rc = -ENODEV; 556 goto out_attach; 557 } 558 559 /* remove netdev mapping for this transport as it is going away */ 560 mutex_lock(&fn_mutex); 561 list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) { 562 if (nm->ft == ft) { 563 LIBFCOE_TRANSPORT_DBG("transport %s going away, " 564 "remove its netdev mapping for %s\n", 565 ft->name, nm->netdev->name); 566 list_del(&nm->list); 567 kfree(nm); 568 } 569 } 570 mutex_unlock(&fn_mutex); 571 572 list_del(&ft->list); 573 ft->attached = false; 574 LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name); 575 576out_attach: 577 mutex_unlock(&ft_mutex); 578 return rc; 579 580} 581EXPORT_SYMBOL(fcoe_transport_detach); 582 583static int fcoe_transport_show(char *buffer, const struct kernel_param *kp) 584{ 585 int i, j; 586 struct fcoe_transport *ft = NULL; 587 588 i = j = sprintf(buffer, "Attached FCoE transports:"); 589 mutex_lock(&ft_mutex); 590 list_for_each_entry(ft, &fcoe_transports, list) { 591 if (i >= PAGE_SIZE - IFNAMSIZ) 592 break; 593 i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name); 594 } 595 mutex_unlock(&ft_mutex); 596 if (i == j) 597 i += snprintf(&buffer[i], IFNAMSIZ, "none"); 598 return i; 599} 600 601static int __init fcoe_transport_init(void) 602{ 603 register_netdevice_notifier(&libfcoe_notifier); 604 return 0; 605} 606 607static int fcoe_transport_exit(void) 608{ 609 struct fcoe_transport *ft; 610 611 unregister_netdevice_notifier(&libfcoe_notifier); 612 mutex_lock(&ft_mutex); 613 list_for_each_entry(ft, &fcoe_transports, list) 614 printk(KERN_ERR "FCoE transport %s is still attached!\n", 615 ft->name); 616 mutex_unlock(&ft_mutex); 617 return 0; 618} 619 620 621static int fcoe_add_netdev_mapping(struct net_device *netdev, 622 struct fcoe_transport *ft) 623{ 624 struct fcoe_netdev_mapping *nm; 625 626 nm = kmalloc(sizeof(*nm), GFP_KERNEL); 627 if (!nm) { 628 printk(KERN_ERR "Unable to allocate netdev_mapping"); 629 return -ENOMEM; 630 } 631 632 nm->netdev = netdev; 633 nm->ft = ft; 634 635 mutex_lock(&fn_mutex); 636 list_add(&nm->list, &fcoe_netdevs); 637 mutex_unlock(&fn_mutex); 638 return 0; 639} 640 641 642static void fcoe_del_netdev_mapping(struct net_device *netdev) 643{ 644 struct fcoe_netdev_mapping *nm = NULL, *tmp; 645 646 mutex_lock(&fn_mutex); 647 list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) { 648 if (nm->netdev == netdev) { 649 list_del(&nm->list); 650 kfree(nm); 651 mutex_unlock(&fn_mutex); 652 return; 653 } 654 } 655 mutex_unlock(&fn_mutex); 656} 657 658 659/** 660 * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which 661 * it was created 662 * 663 * Returns : ptr to the fcoe transport that supports this netdev or NULL 664 * if not found. 665 * 666 * The ft_mutex should be held when this is called 667 */ 668static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev) 669{ 670 struct fcoe_transport *ft = NULL; 671 struct fcoe_netdev_mapping *nm; 672 673 mutex_lock(&fn_mutex); 674 list_for_each_entry(nm, &fcoe_netdevs, list) { 675 if (netdev == nm->netdev) { 676 ft = nm->ft; 677 mutex_unlock(&fn_mutex); 678 return ft; 679 } 680 } 681 682 mutex_unlock(&fn_mutex); 683 return NULL; 684} 685 686/** 687 * fcoe_if_to_netdev() - Parse a name buffer to get a net device 688 * @buffer: The name of the net device 689 * 690 * Returns: NULL or a ptr to net_device 691 */ 692static struct net_device *fcoe_if_to_netdev(const char *buffer) 693{ 694 char *cp; 695 char ifname[IFNAMSIZ + 2]; 696 697 if (buffer) { 698 strlcpy(ifname, buffer, IFNAMSIZ); 699 cp = ifname + strlen(ifname); 700 while (--cp >= ifname && *cp == '\n') 701 *cp = '\0'; 702 return dev_get_by_name(&init_net, ifname); 703 } 704 return NULL; 705} 706 707/** 708 * libfcoe_device_notification() - Handler for net device events 709 * @notifier: The context of the notification 710 * @event: The type of event 711 * @ptr: The net device that the event was on 712 * 713 * This function is called by the Ethernet driver in case of link change event. 714 * 715 * Returns: 0 for success 716 */ 717static int libfcoe_device_notification(struct notifier_block *notifier, 718 ulong event, void *ptr) 719{ 720 struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 721 722 switch (event) { 723 case NETDEV_UNREGISTER: 724 LIBFCOE_TRANSPORT_DBG("NETDEV_UNREGISTER %s\n", 725 netdev->name); 726 fcoe_del_netdev_mapping(netdev); 727 break; 728 } 729 return NOTIFY_OK; 730} 731 732ssize_t fcoe_ctlr_create_store(struct bus_type *bus, 733 const char *buf, size_t count) 734{ 735 struct net_device *netdev = NULL; 736 struct fcoe_transport *ft = NULL; 737 int rc = 0; 738 int err; 739 740 mutex_lock(&ft_mutex); 741 742 netdev = fcoe_if_to_netdev(buf); 743 if (!netdev) { 744 LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buf); 745 rc = -ENODEV; 746 goto out_nodev; 747 } 748 749 ft = fcoe_netdev_map_lookup(netdev); 750 if (ft) { 751 LIBFCOE_TRANSPORT_DBG("transport %s already has existing " 752 "FCoE instance on %s.\n", 753 ft->name, netdev->name); 754 rc = -EEXIST; 755 goto out_putdev; 756 } 757 758 ft = fcoe_transport_lookup(netdev); 759 if (!ft) { 760 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", 761 netdev->name); 762 rc = -ENODEV; 763 goto out_putdev; 764 } 765 766 /* pass to transport create */ 767 err = ft->alloc ? ft->alloc(netdev) : -ENODEV; 768 if (err) { 769 fcoe_del_netdev_mapping(netdev); 770 rc = -ENOMEM; 771 goto out_putdev; 772 } 773 774 err = fcoe_add_netdev_mapping(netdev, ft); 775 if (err) { 776 LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping " 777 "for FCoE transport %s for %s.\n", 778 ft->name, netdev->name); 779 rc = -ENODEV; 780 goto out_putdev; 781 } 782 783 LIBFCOE_TRANSPORT_DBG("transport %s succeeded to create fcoe on %s.\n", 784 ft->name, netdev->name); 785 786out_putdev: 787 dev_put(netdev); 788out_nodev: 789 mutex_unlock(&ft_mutex); 790 if (rc) 791 return rc; 792 return count; 793} 794 795ssize_t fcoe_ctlr_destroy_store(struct bus_type *bus, 796 const char *buf, size_t count) 797{ 798 int rc = -ENODEV; 799 struct net_device *netdev = NULL; 800 struct fcoe_transport *ft = NULL; 801 802 mutex_lock(&ft_mutex); 803 804 netdev = fcoe_if_to_netdev(buf); 805 if (!netdev) { 806 LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buf); 807 goto out_nodev; 808 } 809 810 ft = fcoe_netdev_map_lookup(netdev); 811 if (!ft) { 812 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", 813 netdev->name); 814 goto out_putdev; 815 } 816 817 /* pass to transport destroy */ 818 rc = ft->destroy(netdev); 819 if (rc) 820 goto out_putdev; 821 822 fcoe_del_netdev_mapping(netdev); 823 LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n", 824 ft->name, (rc) ? "failed" : "succeeded", 825 netdev->name); 826 rc = count; /* required for successful return */ 827out_putdev: 828 dev_put(netdev); 829out_nodev: 830 mutex_unlock(&ft_mutex); 831 return rc; 832} 833EXPORT_SYMBOL(fcoe_ctlr_destroy_store); 834 835/** 836 * fcoe_transport_create() - Create a fcoe interface 837 * @buffer: The name of the Ethernet interface to create on 838 * @kp: The associated kernel param 839 * 840 * Called from sysfs. This holds the ft_mutex while calling the 841 * registered fcoe transport's create function. 842 * 843 * Returns: 0 for success 844 */ 845static int fcoe_transport_create(const char *buffer, struct kernel_param *kp) 846{ 847 int rc = -ENODEV; 848 struct net_device *netdev = NULL; 849 struct fcoe_transport *ft = NULL; 850 enum fip_state fip_mode = (enum fip_state)(long)kp->arg; 851 852 mutex_lock(&ft_mutex); 853 854 netdev = fcoe_if_to_netdev(buffer); 855 if (!netdev) { 856 LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer); 857 goto out_nodev; 858 } 859 860 ft = fcoe_netdev_map_lookup(netdev); 861 if (ft) { 862 LIBFCOE_TRANSPORT_DBG("transport %s already has existing " 863 "FCoE instance on %s.\n", 864 ft->name, netdev->name); 865 rc = -EEXIST; 866 goto out_putdev; 867 } 868 869 ft = fcoe_transport_lookup(netdev); 870 if (!ft) { 871 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", 872 netdev->name); 873 goto out_putdev; 874 } 875 876 rc = fcoe_add_netdev_mapping(netdev, ft); 877 if (rc) { 878 LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping " 879 "for FCoE transport %s for %s.\n", 880 ft->name, netdev->name); 881 goto out_putdev; 882 } 883 884 /* pass to transport create */ 885 rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV; 886 if (rc) 887 fcoe_del_netdev_mapping(netdev); 888 889 LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n", 890 ft->name, (rc) ? "failed" : "succeeded", 891 netdev->name); 892 893out_putdev: 894 dev_put(netdev); 895out_nodev: 896 mutex_unlock(&ft_mutex); 897 return rc; 898} 899 900/** 901 * fcoe_transport_destroy() - Destroy a FCoE interface 902 * @buffer: The name of the Ethernet interface to be destroyed 903 * @kp: The associated kernel parameter 904 * 905 * Called from sysfs. This holds the ft_mutex while calling the 906 * registered fcoe transport's destroy function. 907 * 908 * Returns: 0 for success 909 */ 910static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp) 911{ 912 int rc = -ENODEV; 913 struct net_device *netdev = NULL; 914 struct fcoe_transport *ft = NULL; 915 916 mutex_lock(&ft_mutex); 917 918 netdev = fcoe_if_to_netdev(buffer); 919 if (!netdev) { 920 LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer); 921 goto out_nodev; 922 } 923 924 ft = fcoe_netdev_map_lookup(netdev); 925 if (!ft) { 926 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", 927 netdev->name); 928 goto out_putdev; 929 } 930 931 /* pass to transport destroy */ 932 rc = ft->destroy ? ft->destroy(netdev) : -ENODEV; 933 fcoe_del_netdev_mapping(netdev); 934 LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n", 935 ft->name, (rc) ? "failed" : "succeeded", 936 netdev->name); 937 938out_putdev: 939 dev_put(netdev); 940out_nodev: 941 mutex_unlock(&ft_mutex); 942 return rc; 943} 944 945/** 946 * fcoe_transport_disable() - Disables a FCoE interface 947 * @buffer: The name of the Ethernet interface to be disabled 948 * @kp: The associated kernel parameter 949 * 950 * Called from sysfs. 951 * 952 * Returns: 0 for success 953 */ 954static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp) 955{ 956 int rc = -ENODEV; 957 struct net_device *netdev = NULL; 958 struct fcoe_transport *ft = NULL; 959 960 mutex_lock(&ft_mutex); 961 962 netdev = fcoe_if_to_netdev(buffer); 963 if (!netdev) 964 goto out_nodev; 965 966 ft = fcoe_netdev_map_lookup(netdev); 967 if (!ft) 968 goto out_putdev; 969 970 rc = ft->disable ? ft->disable(netdev) : -ENODEV; 971 972out_putdev: 973 dev_put(netdev); 974out_nodev: 975 mutex_unlock(&ft_mutex); 976 return rc; 977} 978 979/** 980 * fcoe_transport_enable() - Enables a FCoE interface 981 * @buffer: The name of the Ethernet interface to be enabled 982 * @kp: The associated kernel parameter 983 * 984 * Called from sysfs. 985 * 986 * Returns: 0 for success 987 */ 988static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) 989{ 990 int rc = -ENODEV; 991 struct net_device *netdev = NULL; 992 struct fcoe_transport *ft = NULL; 993 994 mutex_lock(&ft_mutex); 995 996 netdev = fcoe_if_to_netdev(buffer); 997 if (!netdev) 998 goto out_nodev; 999 1000 ft = fcoe_netdev_map_lookup(netdev); 1001 if (!ft) 1002 goto out_putdev; 1003 1004 rc = ft->enable ? ft->enable(netdev) : -ENODEV; 1005 1006out_putdev: 1007 dev_put(netdev); 1008out_nodev: 1009 mutex_unlock(&ft_mutex); 1010 return rc; 1011} 1012 1013/** 1014 * libfcoe_init() - Initialization routine for libfcoe.ko 1015 */ 1016static int __init libfcoe_init(void) 1017{ 1018 int rc = 0; 1019 1020 rc = fcoe_transport_init(); 1021 if (rc) 1022 return rc; 1023 1024 rc = fcoe_sysfs_setup(); 1025 if (rc) 1026 fcoe_transport_exit(); 1027 1028 return rc; 1029} 1030module_init(libfcoe_init); 1031 1032/** 1033 * libfcoe_exit() - Tear down libfcoe.ko 1034 */ 1035static void __exit libfcoe_exit(void) 1036{ 1037 fcoe_sysfs_teardown(); 1038 fcoe_transport_exit(); 1039} 1040module_exit(libfcoe_exit); 1041