0001
0002
0003
0004
0005
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
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
0112
0113
0114
0115
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
0162
0163
0164
0165
0166
0167
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
0200
0201
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
0214
0215
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
0242
0243
0244
0245
0246
0247
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
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
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
0285
0286
0287
0288
0289
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
0303
0304
0305
0306
0307
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
0340
0341
0342
0343
0344
0345
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
0366
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
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
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
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
0423 port->fcoe_pending_queue.qlen--;
0424 break;
0425 }
0426
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
0444
0445
0446
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
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
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
0505
0506
0507
0508
0509
0510
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
0524
0525
0526
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
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
0557
0558
0559
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
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
0676
0677
0678
0679
0680
0681
0682
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
0704
0705
0706
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
0725
0726
0727
0728
0729
0730
0731
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
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
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;
0843 out_putdev:
0844 dev_put(netdev);
0845 out_nodev:
0846 mutex_unlock(&ft_mutex);
0847 return rc;
0848 }
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
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
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
0918
0919
0920
0921
0922
0923
0924
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
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
0964
0965
0966
0967
0968
0969
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
0999
1000
1001
1002
1003
1004
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
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
1053
1054 static void __exit libfcoe_exit(void)
1055 {
1056 fcoe_sysfs_teardown();
1057 fcoe_transport_exit();
1058 }
1059 module_exit(libfcoe_exit);