Initial commit
[kernel/linux-3.0.git] / drivers / scsi / fcoe / fcoe_transport.c
1 /*
2  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16  *
17  * Maintained at www.Open-FCoE.org
18  */
19
20 #include <linux/types.h>
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/list.h>
24 #include <linux/netdevice.h>
25 #include <linux/errno.h>
26 #include <linux/crc32.h>
27 #include <scsi/libfcoe.h>
28
29 #include "libfcoe.h"
30
31 MODULE_AUTHOR("Open-FCoE.org");
32 MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs");
33 MODULE_LICENSE("GPL v2");
34
35 static int fcoe_transport_create(const char *, struct kernel_param *);
36 static int fcoe_transport_destroy(const char *, struct kernel_param *);
37 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
38 static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
39 static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
40 static int fcoe_transport_enable(const char *, struct kernel_param *);
41 static int fcoe_transport_disable(const char *, struct kernel_param *);
42 static int libfcoe_device_notification(struct notifier_block *notifier,
43                                     ulong event, void *ptr);
44
45 static LIST_HEAD(fcoe_transports);
46 static DEFINE_MUTEX(ft_mutex);
47 static LIST_HEAD(fcoe_netdevs);
48 static DEFINE_MUTEX(fn_mutex);
49
50 unsigned int libfcoe_debug_logging;
51 module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
52 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
53
54 module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR);
55 __MODULE_PARM_TYPE(show, "string");
56 MODULE_PARM_DESC(show, " Show attached FCoE transports");
57
58 module_param_call(create, fcoe_transport_create, NULL,
59                   (void *)FIP_MODE_FABRIC, S_IWUSR);
60 __MODULE_PARM_TYPE(create, "string");
61 MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
62
63 module_param_call(create_vn2vn, fcoe_transport_create, NULL,
64                   (void *)FIP_MODE_VN2VN, S_IWUSR);
65 __MODULE_PARM_TYPE(create_vn2vn, "string");
66 MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
67                  "on an Ethernet interface");
68
69 module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR);
70 __MODULE_PARM_TYPE(destroy, "string");
71 MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
72
73 module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR);
74 __MODULE_PARM_TYPE(enable, "string");
75 MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
76
77 module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
78 __MODULE_PARM_TYPE(disable, "string");
79 MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
80
81 /* notification function for packets from net device */
82 static struct notifier_block libfcoe_notifier = {
83         .notifier_call = libfcoe_device_notification,
84 };
85
86 /**
87  * fcoe_fc_crc() - Calculates the CRC for a given frame
88  * @fp: The frame to be checksumed
89  *
90  * This uses crc32() routine to calculate the CRC for a frame
91  *
92  * Return: The 32 bit CRC value
93  */
94 u32 fcoe_fc_crc(struct fc_frame *fp)
95 {
96         struct sk_buff *skb = fp_skb(fp);
97         struct skb_frag_struct *frag;
98         unsigned char *data;
99         unsigned long off, len, clen;
100         u32 crc;
101         unsigned i;
102
103         crc = crc32(~0, skb->data, skb_headlen(skb));
104
105         for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
106                 frag = &skb_shinfo(skb)->frags[i];
107                 off = frag->page_offset;
108                 len = frag->size;
109                 while (len > 0) {
110                         clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
111                         data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
112                                            KM_SKB_DATA_SOFTIRQ);
113                         crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
114                         kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
115                         off += clen;
116                         len -= clen;
117                 }
118         }
119         return crc;
120 }
121 EXPORT_SYMBOL_GPL(fcoe_fc_crc);
122
123 /**
124  * fcoe_start_io() - Start FCoE I/O
125  * @skb: The packet to be transmitted
126  *
127  * This routine is called from the net device to start transmitting
128  * FCoE packets.
129  *
130  * Returns: 0 for success
131  */
132 int fcoe_start_io(struct sk_buff *skb)
133 {
134         struct sk_buff *nskb;
135         int rc;
136
137         nskb = skb_clone(skb, GFP_ATOMIC);
138         if (!nskb)
139                 return -ENOMEM;
140         rc = dev_queue_xmit(nskb);
141         if (rc != 0)
142                 return rc;
143         kfree_skb(skb);
144         return 0;
145 }
146 EXPORT_SYMBOL_GPL(fcoe_start_io);
147
148
149 /**
150  * fcoe_clean_pending_queue() - Dequeue a skb and free it
151  * @lport: The local port to dequeue a skb on
152  */
153 void fcoe_clean_pending_queue(struct fc_lport *lport)
154 {
155         struct fcoe_port  *port = lport_priv(lport);
156         struct sk_buff *skb;
157
158         spin_lock_bh(&port->fcoe_pending_queue.lock);
159         while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
160                 spin_unlock_bh(&port->fcoe_pending_queue.lock);
161                 kfree_skb(skb);
162                 spin_lock_bh(&port->fcoe_pending_queue.lock);
163         }
164         spin_unlock_bh(&port->fcoe_pending_queue.lock);
165 }
166 EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
167
168 /**
169  * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
170  * @lport: The local port whose backlog is to be cleared
171  *
172  * This empties the wait_queue, dequeues the head of the wait_queue queue
173  * and calls fcoe_start_io() for each packet. If all skb have been
174  * transmitted it returns the qlen. If an error occurs it restores
175  * wait_queue (to try again later) and returns -1.
176  *
177  * The wait_queue is used when the skb transmit fails. The failed skb
178  * will go in the wait_queue which will be emptied by the timer function or
179  * by the next skb transmit.
180  */
181 void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
182 {
183         struct fcoe_port *port = lport_priv(lport);
184         int rc;
185
186         spin_lock_bh(&port->fcoe_pending_queue.lock);
187
188         if (skb)
189                 __skb_queue_tail(&port->fcoe_pending_queue, skb);
190
191         if (port->fcoe_pending_queue_active)
192                 goto out;
193         port->fcoe_pending_queue_active = 1;
194
195         while (port->fcoe_pending_queue.qlen) {
196                 /* keep qlen > 0 until fcoe_start_io succeeds */
197                 port->fcoe_pending_queue.qlen++;
198                 skb = __skb_dequeue(&port->fcoe_pending_queue);
199
200                 spin_unlock_bh(&port->fcoe_pending_queue.lock);
201                 rc = fcoe_start_io(skb);
202                 spin_lock_bh(&port->fcoe_pending_queue.lock);
203
204                 if (rc) {
205                         __skb_queue_head(&port->fcoe_pending_queue, skb);
206                         /* undo temporary increment above */
207                         port->fcoe_pending_queue.qlen--;
208                         break;
209                 }
210                 /* undo temporary increment above */
211                 port->fcoe_pending_queue.qlen--;
212         }
213
214         if (port->fcoe_pending_queue.qlen < port->min_queue_depth)
215                 lport->qfull = 0;
216         if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
217                 mod_timer(&port->timer, jiffies + 2);
218         port->fcoe_pending_queue_active = 0;
219 out:
220         if (port->fcoe_pending_queue.qlen > port->max_queue_depth)
221                 lport->qfull = 1;
222         spin_unlock_bh(&port->fcoe_pending_queue.lock);
223 }
224 EXPORT_SYMBOL_GPL(fcoe_check_wait_queue);
225
226 /**
227  * fcoe_queue_timer() - The fcoe queue timer
228  * @lport: The local port
229  *
230  * Calls fcoe_check_wait_queue on timeout
231  */
232 void fcoe_queue_timer(ulong lport)
233 {
234         fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
235 }
236 EXPORT_SYMBOL_GPL(fcoe_queue_timer);
237
238 /**
239  * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
240  * @skb:  The packet to be transmitted
241  * @tlen: The total length of the trailer
242  * @fps:  The fcoe context
243  *
244  * This routine allocates a page for frame trailers. The page is re-used if
245  * there is enough room left on it for the current trailer. If there isn't
246  * enough buffer left a new page is allocated for the trailer. Reference to
247  * the page from this function as well as the skbs using the page fragments
248  * ensure that the page is freed at the appropriate time.
249  *
250  * Returns: 0 for success
251  */
252 int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
253                            struct fcoe_percpu_s *fps)
254 {
255         struct page *page;
256
257         page = fps->crc_eof_page;
258         if (!page) {
259                 page = alloc_page(GFP_ATOMIC);
260                 if (!page)
261                         return -ENOMEM;
262
263                 fps->crc_eof_page = page;
264                 fps->crc_eof_offset = 0;
265         }
266
267         get_page(page);
268         skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
269                            fps->crc_eof_offset, tlen);
270         skb->len += tlen;
271         skb->data_len += tlen;
272         skb->truesize += tlen;
273         fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
274
275         if (fps->crc_eof_offset >= PAGE_SIZE) {
276                 fps->crc_eof_page = NULL;
277                 fps->crc_eof_offset = 0;
278                 put_page(page);
279         }
280
281         return 0;
282 }
283 EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof);
284
285 /**
286  * fcoe_transport_lookup - find an fcoe transport that matches a netdev
287  * @netdev: The netdev to look for from all attached transports
288  *
289  * Returns : ptr to the fcoe transport that supports this netdev or NULL
290  * if not found.
291  *
292  * The ft_mutex should be held when this is called
293  */
294 static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev)
295 {
296         struct fcoe_transport *ft = NULL;
297
298         list_for_each_entry(ft, &fcoe_transports, list)
299                 if (ft->match && ft->match(netdev))
300                         return ft;
301         return NULL;
302 }
303
304 /**
305  * fcoe_transport_attach - Attaches an FCoE transport
306  * @ft: The fcoe transport to be attached
307  *
308  * Returns : 0 for success
309  */
310 int fcoe_transport_attach(struct fcoe_transport *ft)
311 {
312         int rc = 0;
313
314         mutex_lock(&ft_mutex);
315         if (ft->attached) {
316                 LIBFCOE_TRANSPORT_DBG("transport %s already attached\n",
317                                        ft->name);
318                 rc = -EEXIST;
319                 goto out_attach;
320         }
321
322         /* Add default transport to the tail */
323         if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT))
324                 list_add(&ft->list, &fcoe_transports);
325         else
326                 list_add_tail(&ft->list, &fcoe_transports);
327
328         ft->attached = true;
329         LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name);
330
331 out_attach:
332         mutex_unlock(&ft_mutex);
333         return rc;
334 }
335 EXPORT_SYMBOL(fcoe_transport_attach);
336
337 /**
338  * fcoe_transport_detach - Detaches an FCoE transport
339  * @ft: The fcoe transport to be attached
340  *
341  * Returns : 0 for success
342  */
343 int fcoe_transport_detach(struct fcoe_transport *ft)
344 {
345         int rc = 0;
346         struct fcoe_netdev_mapping *nm = NULL, *tmp;
347
348         mutex_lock(&ft_mutex);
349         if (!ft->attached) {
350                 LIBFCOE_TRANSPORT_DBG("transport %s already detached\n",
351                         ft->name);
352                 rc = -ENODEV;
353                 goto out_attach;
354         }
355
356         /* remove netdev mapping for this transport as it is going away */
357         mutex_lock(&fn_mutex);
358         list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
359                 if (nm->ft == ft) {
360                         LIBFCOE_TRANSPORT_DBG("transport %s going away, "
361                                 "remove its netdev mapping for %s\n",
362                                 ft->name, nm->netdev->name);
363                         list_del(&nm->list);
364                         kfree(nm);
365                 }
366         }
367         mutex_unlock(&fn_mutex);
368
369         list_del(&ft->list);
370         ft->attached = false;
371         LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name);
372
373 out_attach:
374         mutex_unlock(&ft_mutex);
375         return rc;
376
377 }
378 EXPORT_SYMBOL(fcoe_transport_detach);
379
380 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
381 {
382         int i, j;
383         struct fcoe_transport *ft = NULL;
384
385         i = j = sprintf(buffer, "Attached FCoE transports:");
386         mutex_lock(&ft_mutex);
387         list_for_each_entry(ft, &fcoe_transports, list) {
388                 if (i >= PAGE_SIZE - IFNAMSIZ)
389                         break;
390                 i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
391         }
392         mutex_unlock(&ft_mutex);
393         if (i == j)
394                 i += snprintf(&buffer[i], IFNAMSIZ, "none");
395         return i;
396 }
397
398 static int __init fcoe_transport_init(void)
399 {
400         register_netdevice_notifier(&libfcoe_notifier);
401         return 0;
402 }
403
404 static int __exit fcoe_transport_exit(void)
405 {
406         struct fcoe_transport *ft;
407
408         unregister_netdevice_notifier(&libfcoe_notifier);
409         mutex_lock(&ft_mutex);
410         list_for_each_entry(ft, &fcoe_transports, list)
411                 printk(KERN_ERR "FCoE transport %s is still attached!\n",
412                       ft->name);
413         mutex_unlock(&ft_mutex);
414         return 0;
415 }
416
417
418 static int fcoe_add_netdev_mapping(struct net_device *netdev,
419                                         struct fcoe_transport *ft)
420 {
421         struct fcoe_netdev_mapping *nm;
422
423         nm = kmalloc(sizeof(*nm), GFP_KERNEL);
424         if (!nm) {
425                 printk(KERN_ERR "Unable to allocate netdev_mapping");
426                 return -ENOMEM;
427         }
428
429         nm->netdev = netdev;
430         nm->ft = ft;
431
432         mutex_lock(&fn_mutex);
433         list_add(&nm->list, &fcoe_netdevs);
434         mutex_unlock(&fn_mutex);
435         return 0;
436 }
437
438
439 static void fcoe_del_netdev_mapping(struct net_device *netdev)
440 {
441         struct fcoe_netdev_mapping *nm = NULL, *tmp;
442
443         mutex_lock(&fn_mutex);
444         list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
445                 if (nm->netdev == netdev) {
446                         list_del(&nm->list);
447                         kfree(nm);
448                         mutex_unlock(&fn_mutex);
449                         return;
450                 }
451         }
452         mutex_unlock(&fn_mutex);
453 }
454
455
456 /**
457  * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which
458  * it was created
459  *
460  * Returns : ptr to the fcoe transport that supports this netdev or NULL
461  * if not found.
462  *
463  * The ft_mutex should be held when this is called
464  */
465 static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
466 {
467         struct fcoe_transport *ft = NULL;
468         struct fcoe_netdev_mapping *nm;
469
470         mutex_lock(&fn_mutex);
471         list_for_each_entry(nm, &fcoe_netdevs, list) {
472                 if (netdev == nm->netdev) {
473                         ft = nm->ft;
474                         mutex_unlock(&fn_mutex);
475                         return ft;
476                 }
477         }
478
479         mutex_unlock(&fn_mutex);
480         return NULL;
481 }
482
483 /**
484  * fcoe_if_to_netdev() - Parse a name buffer to get a net device
485  * @buffer: The name of the net device
486  *
487  * Returns: NULL or a ptr to net_device
488  */
489 static struct net_device *fcoe_if_to_netdev(const char *buffer)
490 {
491         char *cp;
492         char ifname[IFNAMSIZ + 2];
493
494         if (buffer) {
495                 strlcpy(ifname, buffer, IFNAMSIZ);
496                 cp = ifname + strlen(ifname);
497                 while (--cp >= ifname && *cp == '\n')
498                         *cp = '\0';
499                 return dev_get_by_name(&init_net, ifname);
500         }
501         return NULL;
502 }
503
504 /**
505  * libfcoe_device_notification() - Handler for net device events
506  * @notifier: The context of the notification
507  * @event:    The type of event
508  * @ptr:      The net device that the event was on
509  *
510  * This function is called by the Ethernet driver in case of link change event.
511  *
512  * Returns: 0 for success
513  */
514 static int libfcoe_device_notification(struct notifier_block *notifier,
515                                     ulong event, void *ptr)
516 {
517         struct net_device *netdev = ptr;
518
519         switch (event) {
520         case NETDEV_UNREGISTER:
521                 printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n",
522                                 netdev->name);
523                 fcoe_del_netdev_mapping(netdev);
524                 break;
525         }
526         return NOTIFY_OK;
527 }
528
529
530 /**
531  * fcoe_transport_create() - Create a fcoe interface
532  * @buffer: The name of the Ethernet interface to create on
533  * @kp:     The associated kernel param
534  *
535  * Called from sysfs. This holds the ft_mutex while calling the
536  * registered fcoe transport's create function.
537  *
538  * Returns: 0 for success
539  */
540 static int fcoe_transport_create(const char *buffer, struct kernel_param *kp)
541 {
542         int rc = -ENODEV;
543         struct net_device *netdev = NULL;
544         struct fcoe_transport *ft = NULL;
545         enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
546
547         mutex_lock(&ft_mutex);
548
549         netdev = fcoe_if_to_netdev(buffer);
550         if (!netdev) {
551                 LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer);
552                 goto out_nodev;
553         }
554
555         ft = fcoe_netdev_map_lookup(netdev);
556         if (ft) {
557                 LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
558                                       "FCoE instance on %s.\n",
559                                       ft->name, netdev->name);
560                 rc = -EEXIST;
561                 goto out_putdev;
562         }
563
564         ft = fcoe_transport_lookup(netdev);
565         if (!ft) {
566                 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
567                                       netdev->name);
568                 goto out_putdev;
569         }
570
571         rc = fcoe_add_netdev_mapping(netdev, ft);
572         if (rc) {
573                 LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
574                                       "for FCoE transport %s for %s.\n",
575                                       ft->name, netdev->name);
576                 goto out_putdev;
577         }
578
579         /* pass to transport create */
580         rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV;
581         if (rc)
582                 fcoe_del_netdev_mapping(netdev);
583
584         LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
585                               ft->name, (rc) ? "failed" : "succeeded",
586                               netdev->name);
587
588 out_putdev:
589         dev_put(netdev);
590 out_nodev:
591         mutex_unlock(&ft_mutex);
592         return rc;
593 }
594
595 /**
596  * fcoe_transport_destroy() - Destroy a FCoE interface
597  * @buffer: The name of the Ethernet interface to be destroyed
598  * @kp:     The associated kernel parameter
599  *
600  * Called from sysfs. This holds the ft_mutex while calling the
601  * registered fcoe transport's destroy function.
602  *
603  * Returns: 0 for success
604  */
605 static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp)
606 {
607         int rc = -ENODEV;
608         struct net_device *netdev = NULL;
609         struct fcoe_transport *ft = NULL;
610
611         mutex_lock(&ft_mutex);
612
613         netdev = fcoe_if_to_netdev(buffer);
614         if (!netdev) {
615                 LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer);
616                 goto out_nodev;
617         }
618
619         ft = fcoe_netdev_map_lookup(netdev);
620         if (!ft) {
621                 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
622                                       netdev->name);
623                 goto out_putdev;
624         }
625
626         /* pass to transport destroy */
627         rc = ft->destroy ? ft->destroy(netdev) : -ENODEV;
628         fcoe_del_netdev_mapping(netdev);
629         LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
630                               ft->name, (rc) ? "failed" : "succeeded",
631                               netdev->name);
632
633 out_putdev:
634         dev_put(netdev);
635 out_nodev:
636         mutex_unlock(&ft_mutex);
637         return rc;
638 }
639
640 /**
641  * fcoe_transport_disable() - Disables a FCoE interface
642  * @buffer: The name of the Ethernet interface to be disabled
643  * @kp:     The associated kernel parameter
644  *
645  * Called from sysfs.
646  *
647  * Returns: 0 for success
648  */
649 static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp)
650 {
651         int rc = -ENODEV;
652         struct net_device *netdev = NULL;
653         struct fcoe_transport *ft = NULL;
654
655         mutex_lock(&ft_mutex);
656
657         netdev = fcoe_if_to_netdev(buffer);
658         if (!netdev)
659                 goto out_nodev;
660
661         ft = fcoe_netdev_map_lookup(netdev);
662         if (!ft)
663                 goto out_putdev;
664
665         rc = ft->disable ? ft->disable(netdev) : -ENODEV;
666
667 out_putdev:
668         dev_put(netdev);
669 out_nodev:
670         mutex_unlock(&ft_mutex);
671
672         if (rc == -ERESTARTSYS)
673                 return restart_syscall();
674         else
675                 return rc;
676 }
677
678 /**
679  * fcoe_transport_enable() - Enables a FCoE interface
680  * @buffer: The name of the Ethernet interface to be enabled
681  * @kp:     The associated kernel parameter
682  *
683  * Called from sysfs.
684  *
685  * Returns: 0 for success
686  */
687 static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp)
688 {
689         int rc = -ENODEV;
690         struct net_device *netdev = NULL;
691         struct fcoe_transport *ft = NULL;
692
693         mutex_lock(&ft_mutex);
694
695         netdev = fcoe_if_to_netdev(buffer);
696         if (!netdev)
697                 goto out_nodev;
698
699         ft = fcoe_netdev_map_lookup(netdev);
700         if (!ft)
701                 goto out_putdev;
702
703         rc = ft->enable ? ft->enable(netdev) : -ENODEV;
704
705 out_putdev:
706         dev_put(netdev);
707 out_nodev:
708         mutex_unlock(&ft_mutex);
709         return rc;
710 }
711
712 /**
713  * libfcoe_init() - Initialization routine for libfcoe.ko
714  */
715 static int __init libfcoe_init(void)
716 {
717         fcoe_transport_init();
718
719         return 0;
720 }
721 module_init(libfcoe_init);
722
723 /**
724  * libfcoe_exit() - Tear down libfcoe.ko
725  */
726 static void __exit libfcoe_exit(void)
727 {
728         fcoe_transport_exit();
729 }
730 module_exit(libfcoe_exit);