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