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