root/drivers/scsi/fcoe/fcoe_transport.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. eth2fc_speed
  2. fcoe_link_speed_update
  3. __fcoe_get_lesb
  4. fcoe_get_lesb
  5. fcoe_ctlr_get_lesb
  6. fcoe_wwn_to_str
  7. fcoe_validate_vport_create
  8. fcoe_get_wwn
  9. fcoe_fc_crc
  10. fcoe_start_io
  11. fcoe_clean_pending_queue
  12. fcoe_check_wait_queue
  13. fcoe_queue_timer
  14. fcoe_get_paged_crc_eof
  15. fcoe_transport_lookup
  16. fcoe_transport_attach
  17. fcoe_transport_detach
  18. fcoe_transport_show
  19. fcoe_transport_init
  20. fcoe_transport_exit
  21. fcoe_add_netdev_mapping
  22. fcoe_del_netdev_mapping
  23. fcoe_netdev_map_lookup
  24. fcoe_if_to_netdev
  25. libfcoe_device_notification
  26. fcoe_ctlr_create_store
  27. fcoe_ctlr_destroy_store
  28. fcoe_transport_create
  29. fcoe_transport_destroy
  30. fcoe_transport_disable
  31. fcoe_transport_enable
  32. libfcoe_init
  33. libfcoe_exit

   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 
  19 MODULE_AUTHOR("Open-FCoE.org");
  20 MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs");
  21 MODULE_LICENSE("GPL v2");
  22 
  23 static int fcoe_transport_create(const char *, const struct kernel_param *);
  24 static int fcoe_transport_destroy(const char *, const struct kernel_param *);
  25 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
  26 static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
  27 static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
  28 static int fcoe_transport_enable(const char *, const struct kernel_param *);
  29 static int fcoe_transport_disable(const char *, const struct kernel_param *);
  30 static int libfcoe_device_notification(struct notifier_block *notifier,
  31                                     ulong event, void *ptr);
  32 
  33 static LIST_HEAD(fcoe_transports);
  34 static DEFINE_MUTEX(ft_mutex);
  35 static LIST_HEAD(fcoe_netdevs);
  36 static DEFINE_MUTEX(fn_mutex);
  37 
  38 unsigned int libfcoe_debug_logging;
  39 module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
  40 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
  41 
  42 module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR);
  43 __MODULE_PARM_TYPE(show, "string");
  44 MODULE_PARM_DESC(show, " Show attached FCoE transports");
  45 
  46 module_param_call(create, fcoe_transport_create, NULL,
  47                   (void *)FIP_MODE_FABRIC, S_IWUSR);
  48 __MODULE_PARM_TYPE(create, "string");
  49 MODULE_PARM_DESC(create, " Creates fcoe instance on an ethernet interface");
  50 
  51 module_param_call(create_vn2vn, fcoe_transport_create, NULL,
  52                   (void *)FIP_MODE_VN2VN, S_IWUSR);
  53 __MODULE_PARM_TYPE(create_vn2vn, "string");
  54 MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
  55                  "on an Ethernet interface");
  56 
  57 module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR);
  58 __MODULE_PARM_TYPE(destroy, "string");
  59 MODULE_PARM_DESC(destroy, " Destroys fcoe instance on an ethernet interface");
  60 
  61 module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR);
  62 __MODULE_PARM_TYPE(enable, "string");
  63 MODULE_PARM_DESC(enable, " Enables fcoe on an ethernet interface.");
  64 
  65 module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
  66 __MODULE_PARM_TYPE(disable, "string");
  67 MODULE_PARM_DESC(disable, " Disables fcoe on an ethernet interface.");
  68 
  69 /* notification function for packets from net device */
  70 static struct notifier_block libfcoe_notifier = {
  71         .notifier_call = libfcoe_device_notification,
  72 };
  73 
  74 static 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 
  97 static 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  */
 116 int 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 }
 157 EXPORT_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  */
 168 void __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 }
 195 EXPORT_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  */
 202 void 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 }
 209 EXPORT_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  */
 217 void 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 }
 226 EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb);
 227 
 228 void 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 }
 237 EXPORT_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  */
 248 int 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         }
 276 out:
 277         mutex_unlock(&n_port->lp_mutex);
 278         return rc;
 279 }
 280 EXPORT_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  */
 290 int 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 }
 298 EXPORT_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  */
 308 u32 fcoe_fc_crc(struct fc_frame *fp)
 309 {
 310         struct sk_buff *skb = fp_skb(fp);
 311         skb_frag_t *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 = skb_frag_off(frag);
 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 }
 335 EXPORT_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  */
 346 int 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 }
 360 EXPORT_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  */
 367 void 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 }
 380 EXPORT_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  */
 395 void 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;
 433 out:
 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 }
 438 EXPORT_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  */
 446 void 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 }
 452 EXPORT_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  */
 468 int 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 }
 499 EXPORT_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  */
 510 static 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  */
 526 int 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 
 547 out_attach:
 548         mutex_unlock(&ft_mutex);
 549         return rc;
 550 }
 551 EXPORT_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  */
 559 int 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 
 589 out_attach:
 590         mutex_unlock(&ft_mutex);
 591         return rc;
 592 
 593 }
 594 EXPORT_SYMBOL(fcoe_transport_detach);
 595 
 596 static 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 
 614 static int __init fcoe_transport_init(void)
 615 {
 616         register_netdevice_notifier(&libfcoe_notifier);
 617         return 0;
 618 }
 619 
 620 static 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 
 634 static 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 
 655 static 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  */
 681 static 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  */
 705 static 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  */
 730 static 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 
 745 ssize_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 
 799 out_putdev:
 800         dev_put(netdev);
 801 out_nodev:
 802         mutex_unlock(&ft_mutex);
 803         if (rc)
 804                 return rc;
 805         return count;
 806 }
 807 
 808 ssize_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 */
 840 out_putdev:
 841         dev_put(netdev);
 842 out_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  */
 857 static 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 
 906 out_putdev:
 907         dev_put(netdev);
 908 out_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  */
 923 static 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 
 952 out_putdev:
 953         dev_put(netdev);
 954 out_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  */
 968 static 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 
 987 out_putdev:
 988         dev_put(netdev);
 989 out_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  */
1003 static 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 
1022 out_putdev:
1023         dev_put(netdev);
1024 out_nodev:
1025         mutex_unlock(&ft_mutex);
1026         return rc;
1027 }
1028 
1029 /**
1030  * libfcoe_init() - Initialization routine for libfcoe.ko
1031  */
1032 static 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 }
1046 module_init(libfcoe_init);
1047 
1048 /**
1049  * libfcoe_exit() - Tear down libfcoe.ko
1050  */
1051 static void __exit libfcoe_exit(void)
1052 {
1053         fcoe_sysfs_teardown();
1054         fcoe_transport_exit();
1055 }
1056 module_exit(libfcoe_exit);

/* [<][>][^][v][top][bottom][index][help] */