Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[linux-2.6.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 void __fcoe_get_lesb(struct fc_lport *lport,
87                      struct fc_els_lesb *fc_lesb,
88                      struct net_device *netdev)
89 {
90         unsigned int cpu;
91         u32 lfc, vlfc, mdac;
92         struct fcoe_dev_stats *devst;
93         struct fcoe_fc_els_lesb *lesb;
94         struct rtnl_link_stats64 temp;
95
96         lfc = 0;
97         vlfc = 0;
98         mdac = 0;
99         lesb = (struct fcoe_fc_els_lesb *)fc_lesb;
100         memset(lesb, 0, sizeof(*lesb));
101         for_each_possible_cpu(cpu) {
102                 devst = per_cpu_ptr(lport->dev_stats, cpu);
103                 lfc += devst->LinkFailureCount;
104                 vlfc += devst->VLinkFailureCount;
105                 mdac += devst->MissDiscAdvCount;
106         }
107         lesb->lesb_link_fail = htonl(lfc);
108         lesb->lesb_vlink_fail = htonl(vlfc);
109         lesb->lesb_miss_fka = htonl(mdac);
110         lesb->lesb_fcs_error =
111                         htonl(dev_get_stats(netdev, &temp)->rx_crc_errors);
112 }
113 EXPORT_SYMBOL_GPL(__fcoe_get_lesb);
114
115 void fcoe_wwn_to_str(u64 wwn, char *buf, int len)
116 {
117         u8 wwpn[8];
118
119         u64_to_wwn(wwn, wwpn);
120         snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
121                  wwpn[0], wwpn[1], wwpn[2], wwpn[3],
122                  wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
123 }
124 EXPORT_SYMBOL_GPL(fcoe_wwn_to_str);
125
126 /**
127  * fcoe_validate_vport_create() - Validate a vport before creating it
128  * @vport: NPIV port to be created
129  *
130  * This routine is meant to add validation for a vport before creating it
131  * via fcoe_vport_create().
132  * Current validations are:
133  *      - WWPN supplied is unique for given lport
134  */
135 int fcoe_validate_vport_create(struct fc_vport *vport)
136 {
137         struct Scsi_Host *shost = vport_to_shost(vport);
138         struct fc_lport *n_port = shost_priv(shost);
139         struct fc_lport *vn_port;
140         int rc = 0;
141         char buf[32];
142
143         mutex_lock(&n_port->lp_mutex);
144
145         fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
146         /* Check if the wwpn is not same as that of the lport */
147         if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
148                 LIBFCOE_TRANSPORT_DBG("vport WWPN 0x%s is same as that of the "
149                                       "base port WWPN\n", buf);
150                 rc = -EINVAL;
151                 goto out;
152         }
153
154         /* Check if there is any existing vport with same wwpn */
155         list_for_each_entry(vn_port, &n_port->vports, list) {
156                 if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
157                         LIBFCOE_TRANSPORT_DBG("vport with given WWPN 0x%s "
158                                               "already exists\n", buf);
159                         rc = -EINVAL;
160                         break;
161                 }
162         }
163 out:
164         mutex_unlock(&n_port->lp_mutex);
165         return rc;
166 }
167 EXPORT_SYMBOL_GPL(fcoe_validate_vport_create);
168
169 /**
170  * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
171  * @netdev: the associated net device
172  * @wwn: the output WWN
173  * @type: the type of WWN (WWPN or WWNN)
174  *
175  * Returns: 0 for success
176  */
177 int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
178 {
179         const struct net_device_ops *ops = netdev->netdev_ops;
180
181         if (ops->ndo_fcoe_get_wwn)
182                 return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
183         return -EINVAL;
184 }
185 EXPORT_SYMBOL_GPL(fcoe_get_wwn);
186
187 /**
188  * fcoe_fc_crc() - Calculates the CRC for a given frame
189  * @fp: The frame to be checksumed
190  *
191  * This uses crc32() routine to calculate the CRC for a frame
192  *
193  * Return: The 32 bit CRC value
194  */
195 u32 fcoe_fc_crc(struct fc_frame *fp)
196 {
197         struct sk_buff *skb = fp_skb(fp);
198         struct skb_frag_struct *frag;
199         unsigned char *data;
200         unsigned long off, len, clen;
201         u32 crc;
202         unsigned i;
203
204         crc = crc32(~0, skb->data, skb_headlen(skb));
205
206         for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
207                 frag = &skb_shinfo(skb)->frags[i];
208                 off = frag->page_offset;
209                 len = skb_frag_size(frag);
210                 while (len > 0) {
211                         clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
212                         data = kmap_atomic(
213                                 skb_frag_page(frag) + (off >> PAGE_SHIFT),
214                                 KM_SKB_DATA_SOFTIRQ);
215                         crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
216                         kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
217                         off += clen;
218                         len -= clen;
219                 }
220         }
221         return crc;
222 }
223 EXPORT_SYMBOL_GPL(fcoe_fc_crc);
224
225 /**
226  * fcoe_start_io() - Start FCoE I/O
227  * @skb: The packet to be transmitted
228  *
229  * This routine is called from the net device to start transmitting
230  * FCoE packets.
231  *
232  * Returns: 0 for success
233  */
234 int fcoe_start_io(struct sk_buff *skb)
235 {
236         struct sk_buff *nskb;
237         int rc;
238
239         nskb = skb_clone(skb, GFP_ATOMIC);
240         if (!nskb)
241                 return -ENOMEM;
242         rc = dev_queue_xmit(nskb);
243         if (rc != 0)
244                 return rc;
245         kfree_skb(skb);
246         return 0;
247 }
248 EXPORT_SYMBOL_GPL(fcoe_start_io);
249
250
251 /**
252  * fcoe_clean_pending_queue() - Dequeue a skb and free it
253  * @lport: The local port to dequeue a skb on
254  */
255 void fcoe_clean_pending_queue(struct fc_lport *lport)
256 {
257         struct fcoe_port  *port = lport_priv(lport);
258         struct sk_buff *skb;
259
260         spin_lock_bh(&port->fcoe_pending_queue.lock);
261         while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
262                 spin_unlock_bh(&port->fcoe_pending_queue.lock);
263                 kfree_skb(skb);
264                 spin_lock_bh(&port->fcoe_pending_queue.lock);
265         }
266         spin_unlock_bh(&port->fcoe_pending_queue.lock);
267 }
268 EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
269
270 /**
271  * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
272  * @lport: The local port whose backlog is to be cleared
273  *
274  * This empties the wait_queue, dequeues the head of the wait_queue queue
275  * and calls fcoe_start_io() for each packet. If all skb have been
276  * transmitted it returns the qlen. If an error occurs it restores
277  * wait_queue (to try again later) and returns -1.
278  *
279  * The wait_queue is used when the skb transmit fails. The failed skb
280  * will go in the wait_queue which will be emptied by the timer function or
281  * by the next skb transmit.
282  */
283 void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
284 {
285         struct fcoe_port *port = lport_priv(lport);
286         int rc;
287
288         spin_lock_bh(&port->fcoe_pending_queue.lock);
289
290         if (skb)
291                 __skb_queue_tail(&port->fcoe_pending_queue, skb);
292
293         if (port->fcoe_pending_queue_active)
294                 goto out;
295         port->fcoe_pending_queue_active = 1;
296
297         while (port->fcoe_pending_queue.qlen) {
298                 /* keep qlen > 0 until fcoe_start_io succeeds */
299                 port->fcoe_pending_queue.qlen++;
300                 skb = __skb_dequeue(&port->fcoe_pending_queue);
301
302                 spin_unlock_bh(&port->fcoe_pending_queue.lock);
303                 rc = fcoe_start_io(skb);
304                 spin_lock_bh(&port->fcoe_pending_queue.lock);
305
306                 if (rc) {
307                         __skb_queue_head(&port->fcoe_pending_queue, skb);
308                         /* undo temporary increment above */
309                         port->fcoe_pending_queue.qlen--;
310                         break;
311                 }
312                 /* undo temporary increment above */
313                 port->fcoe_pending_queue.qlen--;
314         }
315
316         if (port->fcoe_pending_queue.qlen < port->min_queue_depth)
317                 lport->qfull = 0;
318         if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
319                 mod_timer(&port->timer, jiffies + 2);
320         port->fcoe_pending_queue_active = 0;
321 out:
322         if (port->fcoe_pending_queue.qlen > port->max_queue_depth)
323                 lport->qfull = 1;
324         spin_unlock_bh(&port->fcoe_pending_queue.lock);
325 }
326 EXPORT_SYMBOL_GPL(fcoe_check_wait_queue);
327
328 /**
329  * fcoe_queue_timer() - The fcoe queue timer
330  * @lport: The local port
331  *
332  * Calls fcoe_check_wait_queue on timeout
333  */
334 void fcoe_queue_timer(ulong lport)
335 {
336         fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
337 }
338 EXPORT_SYMBOL_GPL(fcoe_queue_timer);
339
340 /**
341  * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
342  * @skb:  The packet to be transmitted
343  * @tlen: The total length of the trailer
344  * @fps:  The fcoe context
345  *
346  * This routine allocates a page for frame trailers. The page is re-used if
347  * there is enough room left on it for the current trailer. If there isn't
348  * enough buffer left a new page is allocated for the trailer. Reference to
349  * the page from this function as well as the skbs using the page fragments
350  * ensure that the page is freed at the appropriate time.
351  *
352  * Returns: 0 for success
353  */
354 int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
355                            struct fcoe_percpu_s *fps)
356 {
357         struct page *page;
358
359         page = fps->crc_eof_page;
360         if (!page) {
361                 page = alloc_page(GFP_ATOMIC);
362                 if (!page)
363                         return -ENOMEM;
364
365                 fps->crc_eof_page = page;
366                 fps->crc_eof_offset = 0;
367         }
368
369         get_page(page);
370         skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
371                            fps->crc_eof_offset, tlen);
372         skb->len += tlen;
373         skb->data_len += tlen;
374         skb->truesize += tlen;
375         fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
376
377         if (fps->crc_eof_offset >= PAGE_SIZE) {
378                 fps->crc_eof_page = NULL;
379                 fps->crc_eof_offset = 0;
380                 put_page(page);
381         }
382
383         return 0;
384 }
385 EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof);
386
387 /**
388  * fcoe_transport_lookup - find an fcoe transport that matches a netdev
389  * @netdev: The netdev to look for from all attached transports
390  *
391  * Returns : ptr to the fcoe transport that supports this netdev or NULL
392  * if not found.
393  *
394  * The ft_mutex should be held when this is called
395  */
396 static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev)
397 {
398         struct fcoe_transport *ft = NULL;
399
400         list_for_each_entry(ft, &fcoe_transports, list)
401                 if (ft->match && ft->match(netdev))
402                         return ft;
403         return NULL;
404 }
405
406 /**
407  * fcoe_transport_attach - Attaches an FCoE transport
408  * @ft: The fcoe transport to be attached
409  *
410  * Returns : 0 for success
411  */
412 int fcoe_transport_attach(struct fcoe_transport *ft)
413 {
414         int rc = 0;
415
416         mutex_lock(&ft_mutex);
417         if (ft->attached) {
418                 LIBFCOE_TRANSPORT_DBG("transport %s already attached\n",
419                                        ft->name);
420                 rc = -EEXIST;
421                 goto out_attach;
422         }
423
424         /* Add default transport to the tail */
425         if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT))
426                 list_add(&ft->list, &fcoe_transports);
427         else
428                 list_add_tail(&ft->list, &fcoe_transports);
429
430         ft->attached = true;
431         LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name);
432
433 out_attach:
434         mutex_unlock(&ft_mutex);
435         return rc;
436 }
437 EXPORT_SYMBOL(fcoe_transport_attach);
438
439 /**
440  * fcoe_transport_detach - Detaches an FCoE transport
441  * @ft: The fcoe transport to be attached
442  *
443  * Returns : 0 for success
444  */
445 int fcoe_transport_detach(struct fcoe_transport *ft)
446 {
447         int rc = 0;
448         struct fcoe_netdev_mapping *nm = NULL, *tmp;
449
450         mutex_lock(&ft_mutex);
451         if (!ft->attached) {
452                 LIBFCOE_TRANSPORT_DBG("transport %s already detached\n",
453                         ft->name);
454                 rc = -ENODEV;
455                 goto out_attach;
456         }
457
458         /* remove netdev mapping for this transport as it is going away */
459         mutex_lock(&fn_mutex);
460         list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
461                 if (nm->ft == ft) {
462                         LIBFCOE_TRANSPORT_DBG("transport %s going away, "
463                                 "remove its netdev mapping for %s\n",
464                                 ft->name, nm->netdev->name);
465                         list_del(&nm->list);
466                         kfree(nm);
467                 }
468         }
469         mutex_unlock(&fn_mutex);
470
471         list_del(&ft->list);
472         ft->attached = false;
473         LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name);
474
475 out_attach:
476         mutex_unlock(&ft_mutex);
477         return rc;
478
479 }
480 EXPORT_SYMBOL(fcoe_transport_detach);
481
482 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
483 {
484         int i, j;
485         struct fcoe_transport *ft = NULL;
486
487         i = j = sprintf(buffer, "Attached FCoE transports:");
488         mutex_lock(&ft_mutex);
489         list_for_each_entry(ft, &fcoe_transports, list) {
490                 if (i >= PAGE_SIZE - IFNAMSIZ)
491                         break;
492                 i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
493         }
494         mutex_unlock(&ft_mutex);
495         if (i == j)
496                 i += snprintf(&buffer[i], IFNAMSIZ, "none");
497         return i;
498 }
499
500 static int __init fcoe_transport_init(void)
501 {
502         register_netdevice_notifier(&libfcoe_notifier);
503         return 0;
504 }
505
506 static int __exit fcoe_transport_exit(void)
507 {
508         struct fcoe_transport *ft;
509
510         unregister_netdevice_notifier(&libfcoe_notifier);
511         mutex_lock(&ft_mutex);
512         list_for_each_entry(ft, &fcoe_transports, list)
513                 printk(KERN_ERR "FCoE transport %s is still attached!\n",
514                       ft->name);
515         mutex_unlock(&ft_mutex);
516         return 0;
517 }
518
519
520 static int fcoe_add_netdev_mapping(struct net_device *netdev,
521                                         struct fcoe_transport *ft)
522 {
523         struct fcoe_netdev_mapping *nm;
524
525         nm = kmalloc(sizeof(*nm), GFP_KERNEL);
526         if (!nm) {
527                 printk(KERN_ERR "Unable to allocate netdev_mapping");
528                 return -ENOMEM;
529         }
530
531         nm->netdev = netdev;
532         nm->ft = ft;
533
534         mutex_lock(&fn_mutex);
535         list_add(&nm->list, &fcoe_netdevs);
536         mutex_unlock(&fn_mutex);
537         return 0;
538 }
539
540
541 static void fcoe_del_netdev_mapping(struct net_device *netdev)
542 {
543         struct fcoe_netdev_mapping *nm = NULL, *tmp;
544
545         mutex_lock(&fn_mutex);
546         list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
547                 if (nm->netdev == netdev) {
548                         list_del(&nm->list);
549                         kfree(nm);
550                         mutex_unlock(&fn_mutex);
551                         return;
552                 }
553         }
554         mutex_unlock(&fn_mutex);
555 }
556
557
558 /**
559  * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which
560  * it was created
561  *
562  * Returns : ptr to the fcoe transport that supports this netdev or NULL
563  * if not found.
564  *
565  * The ft_mutex should be held when this is called
566  */
567 static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
568 {
569         struct fcoe_transport *ft = NULL;
570         struct fcoe_netdev_mapping *nm;
571
572         mutex_lock(&fn_mutex);
573         list_for_each_entry(nm, &fcoe_netdevs, list) {
574                 if (netdev == nm->netdev) {
575                         ft = nm->ft;
576                         mutex_unlock(&fn_mutex);
577                         return ft;
578                 }
579         }
580
581         mutex_unlock(&fn_mutex);
582         return NULL;
583 }
584
585 /**
586  * fcoe_if_to_netdev() - Parse a name buffer to get a net device
587  * @buffer: The name of the net device
588  *
589  * Returns: NULL or a ptr to net_device
590  */
591 static struct net_device *fcoe_if_to_netdev(const char *buffer)
592 {
593         char *cp;
594         char ifname[IFNAMSIZ + 2];
595
596         if (buffer) {
597                 strlcpy(ifname, buffer, IFNAMSIZ);
598                 cp = ifname + strlen(ifname);
599                 while (--cp >= ifname && *cp == '\n')
600                         *cp = '\0';
601                 return dev_get_by_name(&init_net, ifname);
602         }
603         return NULL;
604 }
605
606 /**
607  * libfcoe_device_notification() - Handler for net device events
608  * @notifier: The context of the notification
609  * @event:    The type of event
610  * @ptr:      The net device that the event was on
611  *
612  * This function is called by the Ethernet driver in case of link change event.
613  *
614  * Returns: 0 for success
615  */
616 static int libfcoe_device_notification(struct notifier_block *notifier,
617                                     ulong event, void *ptr)
618 {
619         struct net_device *netdev = ptr;
620
621         switch (event) {
622         case NETDEV_UNREGISTER:
623                 printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n",
624                                 netdev->name);
625                 fcoe_del_netdev_mapping(netdev);
626                 break;
627         }
628         return NOTIFY_OK;
629 }
630
631
632 /**
633  * fcoe_transport_create() - Create a fcoe interface
634  * @buffer: The name of the Ethernet interface to create on
635  * @kp:     The associated kernel param
636  *
637  * Called from sysfs. This holds the ft_mutex while calling the
638  * registered fcoe transport's create function.
639  *
640  * Returns: 0 for success
641  */
642 static int fcoe_transport_create(const char *buffer, struct kernel_param *kp)
643 {
644         int rc = -ENODEV;
645         struct net_device *netdev = NULL;
646         struct fcoe_transport *ft = NULL;
647         enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
648
649         mutex_lock(&ft_mutex);
650
651         netdev = fcoe_if_to_netdev(buffer);
652         if (!netdev) {
653                 LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer);
654                 goto out_nodev;
655         }
656
657         ft = fcoe_netdev_map_lookup(netdev);
658         if (ft) {
659                 LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
660                                       "FCoE instance on %s.\n",
661                                       ft->name, netdev->name);
662                 rc = -EEXIST;
663                 goto out_putdev;
664         }
665
666         ft = fcoe_transport_lookup(netdev);
667         if (!ft) {
668                 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
669                                       netdev->name);
670                 goto out_putdev;
671         }
672
673         rc = fcoe_add_netdev_mapping(netdev, ft);
674         if (rc) {
675                 LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
676                                       "for FCoE transport %s for %s.\n",
677                                       ft->name, netdev->name);
678                 goto out_putdev;
679         }
680
681         /* pass to transport create */
682         rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV;
683         if (rc)
684                 fcoe_del_netdev_mapping(netdev);
685
686         LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
687                               ft->name, (rc) ? "failed" : "succeeded",
688                               netdev->name);
689
690 out_putdev:
691         dev_put(netdev);
692 out_nodev:
693         mutex_unlock(&ft_mutex);
694         return rc;
695 }
696
697 /**
698  * fcoe_transport_destroy() - Destroy a FCoE interface
699  * @buffer: The name of the Ethernet interface to be destroyed
700  * @kp:     The associated kernel parameter
701  *
702  * Called from sysfs. This holds the ft_mutex while calling the
703  * registered fcoe transport's destroy function.
704  *
705  * Returns: 0 for success
706  */
707 static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp)
708 {
709         int rc = -ENODEV;
710         struct net_device *netdev = NULL;
711         struct fcoe_transport *ft = NULL;
712
713         mutex_lock(&ft_mutex);
714
715         netdev = fcoe_if_to_netdev(buffer);
716         if (!netdev) {
717                 LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer);
718                 goto out_nodev;
719         }
720
721         ft = fcoe_netdev_map_lookup(netdev);
722         if (!ft) {
723                 LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
724                                       netdev->name);
725                 goto out_putdev;
726         }
727
728         /* pass to transport destroy */
729         rc = ft->destroy ? ft->destroy(netdev) : -ENODEV;
730         fcoe_del_netdev_mapping(netdev);
731         LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
732                               ft->name, (rc) ? "failed" : "succeeded",
733                               netdev->name);
734
735 out_putdev:
736         dev_put(netdev);
737 out_nodev:
738         mutex_unlock(&ft_mutex);
739         return rc;
740 }
741
742 /**
743  * fcoe_transport_disable() - Disables a FCoE interface
744  * @buffer: The name of the Ethernet interface to be disabled
745  * @kp:     The associated kernel parameter
746  *
747  * Called from sysfs.
748  *
749  * Returns: 0 for success
750  */
751 static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp)
752 {
753         int rc = -ENODEV;
754         struct net_device *netdev = NULL;
755         struct fcoe_transport *ft = NULL;
756
757         mutex_lock(&ft_mutex);
758
759         netdev = fcoe_if_to_netdev(buffer);
760         if (!netdev)
761                 goto out_nodev;
762
763         ft = fcoe_netdev_map_lookup(netdev);
764         if (!ft)
765                 goto out_putdev;
766
767         rc = ft->disable ? ft->disable(netdev) : -ENODEV;
768
769 out_putdev:
770         dev_put(netdev);
771 out_nodev:
772         mutex_unlock(&ft_mutex);
773
774         if (rc == -ERESTARTSYS)
775                 return restart_syscall();
776         else
777                 return rc;
778 }
779
780 /**
781  * fcoe_transport_enable() - Enables a FCoE interface
782  * @buffer: The name of the Ethernet interface to be enabled
783  * @kp:     The associated kernel parameter
784  *
785  * Called from sysfs.
786  *
787  * Returns: 0 for success
788  */
789 static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp)
790 {
791         int rc = -ENODEV;
792         struct net_device *netdev = NULL;
793         struct fcoe_transport *ft = NULL;
794
795         mutex_lock(&ft_mutex);
796
797         netdev = fcoe_if_to_netdev(buffer);
798         if (!netdev)
799                 goto out_nodev;
800
801         ft = fcoe_netdev_map_lookup(netdev);
802         if (!ft)
803                 goto out_putdev;
804
805         rc = ft->enable ? ft->enable(netdev) : -ENODEV;
806
807 out_putdev:
808         dev_put(netdev);
809 out_nodev:
810         mutex_unlock(&ft_mutex);
811         return rc;
812 }
813
814 /**
815  * libfcoe_init() - Initialization routine for libfcoe.ko
816  */
817 static int __init libfcoe_init(void)
818 {
819         fcoe_transport_init();
820
821         return 0;
822 }
823 module_init(libfcoe_init);
824
825 /**
826  * libfcoe_exit() - Tear down libfcoe.ko
827  */
828 static void __exit libfcoe_exit(void)
829 {
830         fcoe_transport_exit();
831 }
832 module_exit(libfcoe_exit);