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