Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
0004  *
0005  * Maintained at www.Open-FCoE.org
0006  */
0007 
0008 #include <linux/types.h>
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/list.h>
0012 #include <linux/netdevice.h>
0013 #include <linux/ethtool.h>
0014 #include <linux/errno.h>
0015 #include <linux/crc32.h>
0016 #include <scsi/libfcoe.h>
0017 
0018 #include "libfcoe.h"
0019 
0020 MODULE_AUTHOR("Open-FCoE.org");
0021 MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs");
0022 MODULE_LICENSE("GPL v2");
0023 
0024 static int fcoe_transport_create(const char *, const struct kernel_param *);
0025 static int fcoe_transport_destroy(const char *, const struct kernel_param *);
0026 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
0027 static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
0028 static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
0029 static int fcoe_transport_enable(const char *, const struct kernel_param *);
0030 static int fcoe_transport_disable(const char *, const struct kernel_param *);
0031 static int libfcoe_device_notification(struct notifier_block *notifier,
0032                     ulong event, void *ptr);
0033 
0034 static LIST_HEAD(fcoe_transports);
0035 static DEFINE_MUTEX(ft_mutex);
0036 static LIST_HEAD(fcoe_netdevs);
0037 static DEFINE_MUTEX(fn_mutex);
0038 
0039 unsigned int libfcoe_debug_logging;
0040 module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
0041 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
0042 
0043 module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR);
0044 __MODULE_PARM_TYPE(show, "string");
0045 MODULE_PARM_DESC(show, " Show attached FCoE transports");
0046 
0047 module_param_call(create, fcoe_transport_create, NULL,
0048           (void *)FIP_MODE_FABRIC, S_IWUSR);
0049 __MODULE_PARM_TYPE(create, "string");
0050 MODULE_PARM_DESC(create, " Creates fcoe instance on an ethernet interface");
0051 
0052 module_param_call(create_vn2vn, fcoe_transport_create, NULL,
0053           (void *)FIP_MODE_VN2VN, S_IWUSR);
0054 __MODULE_PARM_TYPE(create_vn2vn, "string");
0055 MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
0056          "on an Ethernet interface");
0057 
0058 module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR);
0059 __MODULE_PARM_TYPE(destroy, "string");
0060 MODULE_PARM_DESC(destroy, " Destroys fcoe instance on an ethernet interface");
0061 
0062 module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR);
0063 __MODULE_PARM_TYPE(enable, "string");
0064 MODULE_PARM_DESC(enable, " Enables fcoe on an ethernet interface.");
0065 
0066 module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
0067 __MODULE_PARM_TYPE(disable, "string");
0068 MODULE_PARM_DESC(disable, " Disables fcoe on an ethernet interface.");
0069 
0070 /* notification function for packets from net device */
0071 static struct notifier_block libfcoe_notifier = {
0072     .notifier_call = libfcoe_device_notification,
0073 };
0074 
0075 static const struct {
0076     u32 fc_port_speed;
0077 #define SPEED_2000  2000
0078 #define SPEED_4000  4000
0079 #define SPEED_8000  8000
0080 #define SPEED_16000 16000
0081 #define SPEED_32000 32000
0082     u32 eth_port_speed;
0083 } fcoe_port_speed_mapping[] = {
0084     { FC_PORTSPEED_1GBIT,   SPEED_1000   },
0085     { FC_PORTSPEED_2GBIT,   SPEED_2000   },
0086     { FC_PORTSPEED_4GBIT,   SPEED_4000   },
0087     { FC_PORTSPEED_8GBIT,   SPEED_8000   },
0088     { FC_PORTSPEED_10GBIT,  SPEED_10000  },
0089     { FC_PORTSPEED_16GBIT,  SPEED_16000  },
0090     { FC_PORTSPEED_20GBIT,  SPEED_20000  },
0091     { FC_PORTSPEED_25GBIT,  SPEED_25000  },
0092     { FC_PORTSPEED_32GBIT,  SPEED_32000  },
0093     { FC_PORTSPEED_40GBIT,  SPEED_40000  },
0094     { FC_PORTSPEED_50GBIT,  SPEED_50000  },
0095     { FC_PORTSPEED_100GBIT, SPEED_100000 },
0096 };
0097 
0098 static inline u32 eth2fc_speed(u32 eth_port_speed)
0099 {
0100     int i;
0101 
0102     for (i = 0; i < ARRAY_SIZE(fcoe_port_speed_mapping); i++) {
0103         if (fcoe_port_speed_mapping[i].eth_port_speed == eth_port_speed)
0104             return fcoe_port_speed_mapping[i].fc_port_speed;
0105     }
0106 
0107     return FC_PORTSPEED_UNKNOWN;
0108 }
0109 
0110 /**
0111  * fcoe_link_speed_update() - Update the supported and actual link speeds
0112  * @lport: The local port to update speeds for
0113  *
0114  * Returns: 0 if the ethtool query was successful
0115  *          -1 if the ethtool query failed
0116  */
0117 int fcoe_link_speed_update(struct fc_lport *lport)
0118 {
0119     struct net_device *netdev = fcoe_get_netdev(lport);
0120     struct ethtool_link_ksettings ecmd;
0121 
0122     if (!__ethtool_get_link_ksettings(netdev, &ecmd)) {
0123         lport->link_supported_speeds &= ~(FC_PORTSPEED_1GBIT  |
0124                                           FC_PORTSPEED_10GBIT |
0125                                           FC_PORTSPEED_20GBIT |
0126                                           FC_PORTSPEED_40GBIT);
0127 
0128         if (ecmd.link_modes.supported[0] & (
0129                 SUPPORTED_1000baseT_Half |
0130                 SUPPORTED_1000baseT_Full |
0131                 SUPPORTED_1000baseKX_Full))
0132             lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
0133 
0134         if (ecmd.link_modes.supported[0] & (
0135                 SUPPORTED_10000baseT_Full   |
0136                 SUPPORTED_10000baseKX4_Full |
0137                 SUPPORTED_10000baseKR_Full  |
0138                 SUPPORTED_10000baseR_FEC))
0139             lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
0140 
0141         if (ecmd.link_modes.supported[0] & (
0142                 SUPPORTED_20000baseMLD2_Full |
0143                 SUPPORTED_20000baseKR2_Full))
0144             lport->link_supported_speeds |= FC_PORTSPEED_20GBIT;
0145 
0146         if (ecmd.link_modes.supported[0] & (
0147                 SUPPORTED_40000baseKR4_Full |
0148                 SUPPORTED_40000baseCR4_Full |
0149                 SUPPORTED_40000baseSR4_Full |
0150                 SUPPORTED_40000baseLR4_Full))
0151             lport->link_supported_speeds |= FC_PORTSPEED_40GBIT;
0152 
0153         lport->link_speed = eth2fc_speed(ecmd.base.speed);
0154         return 0;
0155     }
0156     return -1;
0157 }
0158 EXPORT_SYMBOL_GPL(fcoe_link_speed_update);
0159 
0160 /**
0161  * __fcoe_get_lesb() - Get the Link Error Status Block (LESB) for a given lport
0162  * @lport: The local port to update speeds for
0163  * @fc_lesb: Pointer to the LESB to be filled up
0164  * @netdev: Pointer to the netdev that is associated with the lport
0165  *
0166  * Note, the Link Error Status Block (LESB) for FCoE is defined in FC-BB-6
0167  * Clause 7.11 in v1.04.
0168  */
0169 void __fcoe_get_lesb(struct fc_lport *lport,
0170              struct fc_els_lesb *fc_lesb,
0171              struct net_device *netdev)
0172 {
0173     unsigned int cpu;
0174     u32 lfc, vlfc, mdac;
0175     struct fc_stats *stats;
0176     struct fcoe_fc_els_lesb *lesb;
0177     struct rtnl_link_stats64 temp;
0178 
0179     lfc = 0;
0180     vlfc = 0;
0181     mdac = 0;
0182     lesb = (struct fcoe_fc_els_lesb *)fc_lesb;
0183     memset(lesb, 0, sizeof(*lesb));
0184     for_each_possible_cpu(cpu) {
0185         stats = per_cpu_ptr(lport->stats, cpu);
0186         lfc += READ_ONCE(stats->LinkFailureCount);
0187         vlfc += READ_ONCE(stats->VLinkFailureCount);
0188         mdac += READ_ONCE(stats->MissDiscAdvCount);
0189     }
0190     lesb->lesb_link_fail = htonl(lfc);
0191     lesb->lesb_vlink_fail = htonl(vlfc);
0192     lesb->lesb_miss_fka = htonl(mdac);
0193     lesb->lesb_fcs_error =
0194             htonl(dev_get_stats(netdev, &temp)->rx_crc_errors);
0195 }
0196 EXPORT_SYMBOL_GPL(__fcoe_get_lesb);
0197 
0198 /**
0199  * fcoe_get_lesb() - Fill the FCoE Link Error Status Block
0200  * @lport: the local port
0201  * @fc_lesb: the link error status block
0202  */
0203 void fcoe_get_lesb(struct fc_lport *lport,
0204              struct fc_els_lesb *fc_lesb)
0205 {
0206     struct net_device *netdev = fcoe_get_netdev(lport);
0207 
0208     __fcoe_get_lesb(lport, fc_lesb, netdev);
0209 }
0210 EXPORT_SYMBOL_GPL(fcoe_get_lesb);
0211 
0212 /**
0213  * fcoe_ctlr_get_lesb() - Get the Link Error Status Block (LESB) for a given
0214  * fcoe controller device
0215  * @ctlr_dev: The given fcoe controller device
0216  *
0217  */
0218 void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
0219 {
0220     struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
0221     struct net_device *netdev = fcoe_get_netdev(fip->lp);
0222     struct fc_els_lesb *fc_lesb;
0223 
0224     fc_lesb = (struct fc_els_lesb *)(&ctlr_dev->lesb);
0225     __fcoe_get_lesb(fip->lp, fc_lesb, netdev);
0226 }
0227 EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb);
0228 
0229 void fcoe_wwn_to_str(u64 wwn, char *buf, int len)
0230 {
0231     u8 wwpn[8];
0232 
0233     u64_to_wwn(wwn, wwpn);
0234     snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
0235          wwpn[0], wwpn[1], wwpn[2], wwpn[3],
0236          wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
0237 }
0238 EXPORT_SYMBOL_GPL(fcoe_wwn_to_str);
0239 
0240 /**
0241  * fcoe_validate_vport_create() - Validate a vport before creating it
0242  * @vport: NPIV port to be created
0243  *
0244  * This routine is meant to add validation for a vport before creating it
0245  * via fcoe_vport_create().
0246  * Current validations are:
0247  *      - WWPN supplied is unique for given lport
0248  */
0249 int fcoe_validate_vport_create(struct fc_vport *vport)
0250 {
0251     struct Scsi_Host *shost = vport_to_shost(vport);
0252     struct fc_lport *n_port = shost_priv(shost);
0253     struct fc_lport *vn_port;
0254     int rc = 0;
0255     char buf[32];
0256 
0257     mutex_lock(&n_port->lp_mutex);
0258 
0259     fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
0260     /* Check if the wwpn is not same as that of the lport */
0261     if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
0262         LIBFCOE_TRANSPORT_DBG("vport WWPN 0x%s is same as that of the "
0263                       "base port WWPN\n", buf);
0264         rc = -EINVAL;
0265         goto out;
0266     }
0267 
0268     /* Check if there is any existing vport with same wwpn */
0269     list_for_each_entry(vn_port, &n_port->vports, list) {
0270         if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
0271             LIBFCOE_TRANSPORT_DBG("vport with given WWPN 0x%s "
0272                           "already exists\n", buf);
0273             rc = -EINVAL;
0274             break;
0275         }
0276     }
0277 out:
0278     mutex_unlock(&n_port->lp_mutex);
0279     return rc;
0280 }
0281 EXPORT_SYMBOL_GPL(fcoe_validate_vport_create);
0282 
0283 /**
0284  * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
0285  * @netdev: the associated net device
0286  * @wwn: the output WWN
0287  * @type: the type of WWN (WWPN or WWNN)
0288  *
0289  * Returns: 0 for success
0290  */
0291 int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
0292 {
0293     const struct net_device_ops *ops = netdev->netdev_ops;
0294 
0295     if (ops->ndo_fcoe_get_wwn)
0296         return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
0297     return -EINVAL;
0298 }
0299 EXPORT_SYMBOL_GPL(fcoe_get_wwn);
0300 
0301 /**
0302  * fcoe_fc_crc() - Calculates the CRC for a given frame
0303  * @fp: The frame to be checksumed
0304  *
0305  * This uses crc32() routine to calculate the CRC for a frame
0306  *
0307  * Return: The 32 bit CRC value
0308  */
0309 u32 fcoe_fc_crc(struct fc_frame *fp)
0310 {
0311     struct sk_buff *skb = fp_skb(fp);
0312     skb_frag_t *frag;
0313     unsigned char *data;
0314     unsigned long off, len, clen;
0315     u32 crc;
0316     unsigned i;
0317 
0318     crc = crc32(~0, skb->data, skb_headlen(skb));
0319 
0320     for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
0321         frag = &skb_shinfo(skb)->frags[i];
0322         off = skb_frag_off(frag);
0323         len = skb_frag_size(frag);
0324         while (len > 0) {
0325             clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
0326             data = kmap_atomic(
0327                 skb_frag_page(frag) + (off >> PAGE_SHIFT));
0328             crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
0329             kunmap_atomic(data);
0330             off += clen;
0331             len -= clen;
0332         }
0333     }
0334     return crc;
0335 }
0336 EXPORT_SYMBOL_GPL(fcoe_fc_crc);
0337 
0338 /**
0339  * fcoe_start_io() - Start FCoE I/O
0340  * @skb: The packet to be transmitted
0341  *
0342  * This routine is called from the net device to start transmitting
0343  * FCoE packets.
0344  *
0345  * Returns: 0 for success
0346  */
0347 int fcoe_start_io(struct sk_buff *skb)
0348 {
0349     struct sk_buff *nskb;
0350     int rc;
0351 
0352     nskb = skb_clone(skb, GFP_ATOMIC);
0353     if (!nskb)
0354         return -ENOMEM;
0355     rc = dev_queue_xmit(nskb);
0356     if (rc != 0)
0357         return rc;
0358     kfree_skb(skb);
0359     return 0;
0360 }
0361 EXPORT_SYMBOL_GPL(fcoe_start_io);
0362 
0363 
0364 /**
0365  * fcoe_clean_pending_queue() - Dequeue a skb and free it
0366  * @lport: The local port to dequeue a skb on
0367  */
0368 void fcoe_clean_pending_queue(struct fc_lport *lport)
0369 {
0370     struct fcoe_port  *port = lport_priv(lport);
0371     struct sk_buff *skb;
0372 
0373     spin_lock_bh(&port->fcoe_pending_queue.lock);
0374     while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
0375         spin_unlock_bh(&port->fcoe_pending_queue.lock);
0376         kfree_skb(skb);
0377         spin_lock_bh(&port->fcoe_pending_queue.lock);
0378     }
0379     spin_unlock_bh(&port->fcoe_pending_queue.lock);
0380 }
0381 EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
0382 
0383 /**
0384  * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
0385  * @lport: The local port whose backlog is to be cleared
0386  * @skb: The received FIP packet
0387  *
0388  * This empties the wait_queue, dequeues the head of the wait_queue queue
0389  * and calls fcoe_start_io() for each packet. If all skb have been
0390  * transmitted it returns the qlen. If an error occurs it restores
0391  * wait_queue (to try again later) and returns -1.
0392  *
0393  * The wait_queue is used when the skb transmit fails. The failed skb
0394  * will go in the wait_queue which will be emptied by the timer function or
0395  * by the next skb transmit.
0396  */
0397 void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
0398 {
0399     struct fcoe_port *port = lport_priv(lport);
0400     int rc;
0401 
0402     spin_lock_bh(&port->fcoe_pending_queue.lock);
0403 
0404     if (skb)
0405         __skb_queue_tail(&port->fcoe_pending_queue, skb);
0406 
0407     if (port->fcoe_pending_queue_active)
0408         goto out;
0409     port->fcoe_pending_queue_active = 1;
0410 
0411     while (port->fcoe_pending_queue.qlen) {
0412         /* keep qlen > 0 until fcoe_start_io succeeds */
0413         port->fcoe_pending_queue.qlen++;
0414         skb = __skb_dequeue(&port->fcoe_pending_queue);
0415 
0416         spin_unlock_bh(&port->fcoe_pending_queue.lock);
0417         rc = fcoe_start_io(skb);
0418         spin_lock_bh(&port->fcoe_pending_queue.lock);
0419 
0420         if (rc) {
0421             __skb_queue_head(&port->fcoe_pending_queue, skb);
0422             /* undo temporary increment above */
0423             port->fcoe_pending_queue.qlen--;
0424             break;
0425         }
0426         /* undo temporary increment above */
0427         port->fcoe_pending_queue.qlen--;
0428     }
0429 
0430     if (port->fcoe_pending_queue.qlen < port->min_queue_depth)
0431         lport->qfull = 0;
0432     if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
0433         mod_timer(&port->timer, jiffies + 2);
0434     port->fcoe_pending_queue_active = 0;
0435 out:
0436     if (port->fcoe_pending_queue.qlen > port->max_queue_depth)
0437         lport->qfull = 1;
0438     spin_unlock_bh(&port->fcoe_pending_queue.lock);
0439 }
0440 EXPORT_SYMBOL_GPL(fcoe_check_wait_queue);
0441 
0442 /**
0443  * fcoe_queue_timer() - The fcoe queue timer
0444  * @t: Timer context use to obtain the FCoE port
0445  *
0446  * Calls fcoe_check_wait_queue on timeout
0447  */
0448 void fcoe_queue_timer(struct timer_list *t)
0449 {
0450     struct fcoe_port *port = from_timer(port, t, timer);
0451 
0452     fcoe_check_wait_queue(port->lport, NULL);
0453 }
0454 EXPORT_SYMBOL_GPL(fcoe_queue_timer);
0455 
0456 /**
0457  * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
0458  * @skb:  The packet to be transmitted
0459  * @tlen: The total length of the trailer
0460  * @fps:  The fcoe context
0461  *
0462  * This routine allocates a page for frame trailers. The page is re-used if
0463  * there is enough room left on it for the current trailer. If there isn't
0464  * enough buffer left a new page is allocated for the trailer. Reference to
0465  * the page from this function as well as the skbs using the page fragments
0466  * ensure that the page is freed at the appropriate time.
0467  *
0468  * Returns: 0 for success
0469  */
0470 int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
0471                struct fcoe_percpu_s *fps)
0472 {
0473     struct page *page;
0474 
0475     page = fps->crc_eof_page;
0476     if (!page) {
0477         page = alloc_page(GFP_ATOMIC);
0478         if (!page)
0479             return -ENOMEM;
0480 
0481         fps->crc_eof_page = page;
0482         fps->crc_eof_offset = 0;
0483     }
0484 
0485     get_page(page);
0486     skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
0487                fps->crc_eof_offset, tlen);
0488     skb->len += tlen;
0489     skb->data_len += tlen;
0490     skb->truesize += tlen;
0491     fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
0492 
0493     if (fps->crc_eof_offset >= PAGE_SIZE) {
0494         fps->crc_eof_page = NULL;
0495         fps->crc_eof_offset = 0;
0496         put_page(page);
0497     }
0498 
0499     return 0;
0500 }
0501 EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof);
0502 
0503 /**
0504  * fcoe_transport_lookup - find an fcoe transport that matches a netdev
0505  * @netdev: The netdev to look for from all attached transports
0506  *
0507  * Returns : ptr to the fcoe transport that supports this netdev or NULL
0508  * if not found.
0509  *
0510  * The ft_mutex should be held when this is called
0511  */
0512 static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev)
0513 {
0514     struct fcoe_transport *ft = NULL;
0515 
0516     list_for_each_entry(ft, &fcoe_transports, list)
0517         if (ft->match && ft->match(netdev))
0518             return ft;
0519     return NULL;
0520 }
0521 
0522 /**
0523  * fcoe_transport_attach - Attaches an FCoE transport
0524  * @ft: The fcoe transport to be attached
0525  *
0526  * Returns : 0 for success
0527  */
0528 int fcoe_transport_attach(struct fcoe_transport *ft)
0529 {
0530     int rc = 0;
0531 
0532     mutex_lock(&ft_mutex);
0533     if (ft->attached) {
0534         LIBFCOE_TRANSPORT_DBG("transport %s already attached\n",
0535                        ft->name);
0536         rc = -EEXIST;
0537         goto out_attach;
0538     }
0539 
0540     /* Add default transport to the tail */
0541     if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT))
0542         list_add(&ft->list, &fcoe_transports);
0543     else
0544         list_add_tail(&ft->list, &fcoe_transports);
0545 
0546     ft->attached = true;
0547     LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name);
0548 
0549 out_attach:
0550     mutex_unlock(&ft_mutex);
0551     return rc;
0552 }
0553 EXPORT_SYMBOL(fcoe_transport_attach);
0554 
0555 /**
0556  * fcoe_transport_detach - Detaches an FCoE transport
0557  * @ft: The fcoe transport to be attached
0558  *
0559  * Returns : 0 for success
0560  */
0561 int fcoe_transport_detach(struct fcoe_transport *ft)
0562 {
0563     int rc = 0;
0564     struct fcoe_netdev_mapping *nm = NULL, *tmp;
0565 
0566     mutex_lock(&ft_mutex);
0567     if (!ft->attached) {
0568         LIBFCOE_TRANSPORT_DBG("transport %s already detached\n",
0569             ft->name);
0570         rc = -ENODEV;
0571         goto out_attach;
0572     }
0573 
0574     /* remove netdev mapping for this transport as it is going away */
0575     mutex_lock(&fn_mutex);
0576     list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
0577         if (nm->ft == ft) {
0578             LIBFCOE_TRANSPORT_DBG("transport %s going away, "
0579                 "remove its netdev mapping for %s\n",
0580                 ft->name, nm->netdev->name);
0581             list_del(&nm->list);
0582             kfree(nm);
0583         }
0584     }
0585     mutex_unlock(&fn_mutex);
0586 
0587     list_del(&ft->list);
0588     ft->attached = false;
0589     LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name);
0590 
0591 out_attach:
0592     mutex_unlock(&ft_mutex);
0593     return rc;
0594 
0595 }
0596 EXPORT_SYMBOL(fcoe_transport_detach);
0597 
0598 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
0599 {
0600     int i, j;
0601     struct fcoe_transport *ft = NULL;
0602 
0603     i = j = sprintf(buffer, "Attached FCoE transports:");
0604     mutex_lock(&ft_mutex);
0605     list_for_each_entry(ft, &fcoe_transports, list) {
0606         if (i >= PAGE_SIZE - IFNAMSIZ)
0607             break;
0608         i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
0609     }
0610     mutex_unlock(&ft_mutex);
0611     if (i == j)
0612         i += snprintf(&buffer[i], IFNAMSIZ, "none");
0613     return i;
0614 }
0615 
0616 static int __init fcoe_transport_init(void)
0617 {
0618     register_netdevice_notifier(&libfcoe_notifier);
0619     return 0;
0620 }
0621 
0622 static int fcoe_transport_exit(void)
0623 {
0624     struct fcoe_transport *ft;
0625 
0626     unregister_netdevice_notifier(&libfcoe_notifier);
0627     mutex_lock(&ft_mutex);
0628     list_for_each_entry(ft, &fcoe_transports, list)
0629         printk(KERN_ERR "FCoE transport %s is still attached!\n",
0630               ft->name);
0631     mutex_unlock(&ft_mutex);
0632     return 0;
0633 }
0634 
0635 
0636 static int fcoe_add_netdev_mapping(struct net_device *netdev,
0637                     struct fcoe_transport *ft)
0638 {
0639     struct fcoe_netdev_mapping *nm;
0640 
0641     nm = kmalloc(sizeof(*nm), GFP_KERNEL);
0642     if (!nm) {
0643         printk(KERN_ERR "Unable to allocate netdev_mapping");
0644         return -ENOMEM;
0645     }
0646 
0647     nm->netdev = netdev;
0648     nm->ft = ft;
0649 
0650     mutex_lock(&fn_mutex);
0651     list_add(&nm->list, &fcoe_netdevs);
0652     mutex_unlock(&fn_mutex);
0653     return 0;
0654 }
0655 
0656 
0657 static void fcoe_del_netdev_mapping(struct net_device *netdev)
0658 {
0659     struct fcoe_netdev_mapping *nm = NULL, *tmp;
0660 
0661     mutex_lock(&fn_mutex);
0662     list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
0663         if (nm->netdev == netdev) {
0664             list_del(&nm->list);
0665             kfree(nm);
0666             mutex_unlock(&fn_mutex);
0667             return;
0668         }
0669     }
0670     mutex_unlock(&fn_mutex);
0671 }
0672 
0673 
0674 /**
0675  * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which
0676  * it was created
0677  * @netdev: The net device that the FCoE interface is on
0678  *
0679  * Returns : ptr to the fcoe transport that supports this netdev or NULL
0680  * if not found.
0681  *
0682  * The ft_mutex should be held when this is called
0683  */
0684 static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
0685 {
0686     struct fcoe_transport *ft = NULL;
0687     struct fcoe_netdev_mapping *nm;
0688 
0689     mutex_lock(&fn_mutex);
0690     list_for_each_entry(nm, &fcoe_netdevs, list) {
0691         if (netdev == nm->netdev) {
0692             ft = nm->ft;
0693             mutex_unlock(&fn_mutex);
0694             return ft;
0695         }
0696     }
0697 
0698     mutex_unlock(&fn_mutex);
0699     return NULL;
0700 }
0701 
0702 /**
0703  * fcoe_if_to_netdev() - Parse a name buffer to get a net device
0704  * @buffer: The name of the net device
0705  *
0706  * Returns: NULL or a ptr to net_device
0707  */
0708 static struct net_device *fcoe_if_to_netdev(const char *buffer)
0709 {
0710     char *cp;
0711     char ifname[IFNAMSIZ + 2];
0712 
0713     if (buffer) {
0714         strlcpy(ifname, buffer, IFNAMSIZ);
0715         cp = ifname + strlen(ifname);
0716         while (--cp >= ifname && *cp == '\n')
0717             *cp = '\0';
0718         return dev_get_by_name(&init_net, ifname);
0719     }
0720     return NULL;
0721 }
0722 
0723 /**
0724  * libfcoe_device_notification() - Handler for net device events
0725  * @notifier: The context of the notification
0726  * @event:    The type of event
0727  * @ptr:      The net device that the event was on
0728  *
0729  * This function is called by the Ethernet driver in case of link change event.
0730  *
0731  * Returns: 0 for success
0732  */
0733 static int libfcoe_device_notification(struct notifier_block *notifier,
0734                     ulong event, void *ptr)
0735 {
0736     struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
0737 
0738     switch (event) {
0739     case NETDEV_UNREGISTER:
0740         LIBFCOE_TRANSPORT_DBG("NETDEV_UNREGISTER %s\n",
0741                       netdev->name);
0742         fcoe_del_netdev_mapping(netdev);
0743         break;
0744     }
0745     return NOTIFY_OK;
0746 }
0747 
0748 ssize_t fcoe_ctlr_create_store(struct bus_type *bus,
0749                    const char *buf, size_t count)
0750 {
0751     struct net_device *netdev = NULL;
0752     struct fcoe_transport *ft = NULL;
0753     int rc = 0;
0754     int err;
0755 
0756     mutex_lock(&ft_mutex);
0757 
0758     netdev = fcoe_if_to_netdev(buf);
0759     if (!netdev) {
0760         LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buf);
0761         rc = -ENODEV;
0762         goto out_nodev;
0763     }
0764 
0765     ft = fcoe_netdev_map_lookup(netdev);
0766     if (ft) {
0767         LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
0768                       "FCoE instance on %s.\n",
0769                       ft->name, netdev->name);
0770         rc = -EEXIST;
0771         goto out_putdev;
0772     }
0773 
0774     ft = fcoe_transport_lookup(netdev);
0775     if (!ft) {
0776         LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
0777                       netdev->name);
0778         rc = -ENODEV;
0779         goto out_putdev;
0780     }
0781 
0782     /* pass to transport create */
0783     err = ft->alloc ? ft->alloc(netdev) : -ENODEV;
0784     if (err) {
0785         fcoe_del_netdev_mapping(netdev);
0786         rc = -ENOMEM;
0787         goto out_putdev;
0788     }
0789 
0790     err = fcoe_add_netdev_mapping(netdev, ft);
0791     if (err) {
0792         LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
0793                       "for FCoE transport %s for %s.\n",
0794                       ft->name, netdev->name);
0795         rc = -ENODEV;
0796         goto out_putdev;
0797     }
0798 
0799     LIBFCOE_TRANSPORT_DBG("transport %s succeeded to create fcoe on %s.\n",
0800                   ft->name, netdev->name);
0801 
0802 out_putdev:
0803     dev_put(netdev);
0804 out_nodev:
0805     mutex_unlock(&ft_mutex);
0806     if (rc)
0807         return rc;
0808     return count;
0809 }
0810 
0811 ssize_t fcoe_ctlr_destroy_store(struct bus_type *bus,
0812                 const char *buf, size_t count)
0813 {
0814     int rc = -ENODEV;
0815     struct net_device *netdev = NULL;
0816     struct fcoe_transport *ft = NULL;
0817 
0818     mutex_lock(&ft_mutex);
0819 
0820     netdev = fcoe_if_to_netdev(buf);
0821     if (!netdev) {
0822         LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buf);
0823         goto out_nodev;
0824     }
0825 
0826     ft = fcoe_netdev_map_lookup(netdev);
0827     if (!ft) {
0828         LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
0829                       netdev->name);
0830         goto out_putdev;
0831     }
0832 
0833     /* pass to transport destroy */
0834     rc = ft->destroy(netdev);
0835     if (rc)
0836         goto out_putdev;
0837 
0838     fcoe_del_netdev_mapping(netdev);
0839     LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
0840                   ft->name, (rc) ? "failed" : "succeeded",
0841                   netdev->name);
0842     rc = count; /* required for successful return */
0843 out_putdev:
0844     dev_put(netdev);
0845 out_nodev:
0846     mutex_unlock(&ft_mutex);
0847     return rc;
0848 }
0849 
0850 /**
0851  * fcoe_transport_create() - Create a fcoe interface
0852  * @buffer: The name of the Ethernet interface to create on
0853  * @kp:     The associated kernel param
0854  *
0855  * Called from sysfs. This holds the ft_mutex while calling the
0856  * registered fcoe transport's create function.
0857  *
0858  * Returns: 0 for success
0859  */
0860 static int fcoe_transport_create(const char *buffer,
0861                  const struct kernel_param *kp)
0862 {
0863     int rc = -ENODEV;
0864     struct net_device *netdev = NULL;
0865     struct fcoe_transport *ft = NULL;
0866     enum fip_mode fip_mode = (enum fip_mode)(uintptr_t)kp->arg;
0867 
0868     mutex_lock(&ft_mutex);
0869 
0870     netdev = fcoe_if_to_netdev(buffer);
0871     if (!netdev) {
0872         LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer);
0873         goto out_nodev;
0874     }
0875 
0876     ft = fcoe_netdev_map_lookup(netdev);
0877     if (ft) {
0878         LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
0879                       "FCoE instance on %s.\n",
0880                       ft->name, netdev->name);
0881         rc = -EEXIST;
0882         goto out_putdev;
0883     }
0884 
0885     ft = fcoe_transport_lookup(netdev);
0886     if (!ft) {
0887         LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
0888                       netdev->name);
0889         goto out_putdev;
0890     }
0891 
0892     rc = fcoe_add_netdev_mapping(netdev, ft);
0893     if (rc) {
0894         LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
0895                       "for FCoE transport %s for %s.\n",
0896                       ft->name, netdev->name);
0897         goto out_putdev;
0898     }
0899 
0900     /* pass to transport create */
0901     rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV;
0902     if (rc)
0903         fcoe_del_netdev_mapping(netdev);
0904 
0905     LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
0906                   ft->name, (rc) ? "failed" : "succeeded",
0907                   netdev->name);
0908 
0909 out_putdev:
0910     dev_put(netdev);
0911 out_nodev:
0912     mutex_unlock(&ft_mutex);
0913     return rc;
0914 }
0915 
0916 /**
0917  * fcoe_transport_destroy() - Destroy a FCoE interface
0918  * @buffer: The name of the Ethernet interface to be destroyed
0919  * @kp:     The associated kernel parameter
0920  *
0921  * Called from sysfs. This holds the ft_mutex while calling the
0922  * registered fcoe transport's destroy function.
0923  *
0924  * Returns: 0 for success
0925  */
0926 static int fcoe_transport_destroy(const char *buffer,
0927                   const struct kernel_param *kp)
0928 {
0929     int rc = -ENODEV;
0930     struct net_device *netdev = NULL;
0931     struct fcoe_transport *ft = NULL;
0932 
0933     mutex_lock(&ft_mutex);
0934 
0935     netdev = fcoe_if_to_netdev(buffer);
0936     if (!netdev) {
0937         LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer);
0938         goto out_nodev;
0939     }
0940 
0941     ft = fcoe_netdev_map_lookup(netdev);
0942     if (!ft) {
0943         LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
0944                       netdev->name);
0945         goto out_putdev;
0946     }
0947 
0948     /* pass to transport destroy */
0949     rc = ft->destroy ? ft->destroy(netdev) : -ENODEV;
0950     fcoe_del_netdev_mapping(netdev);
0951     LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
0952                   ft->name, (rc) ? "failed" : "succeeded",
0953                   netdev->name);
0954 
0955 out_putdev:
0956     dev_put(netdev);
0957 out_nodev:
0958     mutex_unlock(&ft_mutex);
0959     return rc;
0960 }
0961 
0962 /**
0963  * fcoe_transport_disable() - Disables a FCoE interface
0964  * @buffer: The name of the Ethernet interface to be disabled
0965  * @kp:     The associated kernel parameter
0966  *
0967  * Called from sysfs.
0968  *
0969  * Returns: 0 for success
0970  */
0971 static int fcoe_transport_disable(const char *buffer,
0972                   const struct kernel_param *kp)
0973 {
0974     int rc = -ENODEV;
0975     struct net_device *netdev = NULL;
0976     struct fcoe_transport *ft = NULL;
0977 
0978     mutex_lock(&ft_mutex);
0979 
0980     netdev = fcoe_if_to_netdev(buffer);
0981     if (!netdev)
0982         goto out_nodev;
0983 
0984     ft = fcoe_netdev_map_lookup(netdev);
0985     if (!ft)
0986         goto out_putdev;
0987 
0988     rc = ft->disable ? ft->disable(netdev) : -ENODEV;
0989 
0990 out_putdev:
0991     dev_put(netdev);
0992 out_nodev:
0993     mutex_unlock(&ft_mutex);
0994     return rc;
0995 }
0996 
0997 /**
0998  * fcoe_transport_enable() - Enables a FCoE interface
0999  * @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  */
1006 static 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 
1025 out_putdev:
1026     dev_put(netdev);
1027 out_nodev:
1028     mutex_unlock(&ft_mutex);
1029     return rc;
1030 }
1031 
1032 /**
1033  * libfcoe_init() - Initialization routine for libfcoe.ko
1034  */
1035 static 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 }
1049 module_init(libfcoe_init);
1050 
1051 /**
1052  * libfcoe_exit() - Tear down libfcoe.ko
1053  */
1054 static void __exit libfcoe_exit(void)
1055 {
1056     fcoe_sysfs_teardown();
1057     fcoe_transport_exit();
1058 }
1059 module_exit(libfcoe_exit);