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