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 &= ~(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