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