[go: nahoru, domu]

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
31MODULE_AUTHOR("Open-FCoE.org");
32MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs");
33MODULE_LICENSE("GPL v2");
34
35static int fcoe_transport_create(const char *, struct kernel_param *);
36static int fcoe_transport_destroy(const char *, struct kernel_param *);
37static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
38static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
39static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
40static int fcoe_transport_enable(const char *, struct kernel_param *);
41static int fcoe_transport_disable(const char *, struct kernel_param *);
42static int libfcoe_device_notification(struct notifier_block *notifier,
43				    ulong event, void *ptr);
44
45static LIST_HEAD(fcoe_transports);
46static DEFINE_MUTEX(ft_mutex);
47static LIST_HEAD(fcoe_netdevs);
48static DEFINE_MUTEX(fn_mutex);
49
50unsigned int libfcoe_debug_logging;
51module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
52MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
53
54module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR);
55__MODULE_PARM_TYPE(show, "string");
56MODULE_PARM_DESC(show, " Show attached FCoE transports");
57
58module_param_call(create, fcoe_transport_create, NULL,
59		  (void *)FIP_MODE_FABRIC, S_IWUSR);
60__MODULE_PARM_TYPE(create, "string");
61MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
62
63module_param_call(create_vn2vn, fcoe_transport_create, NULL,
64		  (void *)FIP_MODE_VN2VN, S_IWUSR);
65__MODULE_PARM_TYPE(create_vn2vn, "string");
66MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
67		 "on an Ethernet interface");
68
69module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR);
70__MODULE_PARM_TYPE(destroy, "string");
71MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
72
73module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR);
74__MODULE_PARM_TYPE(enable, "string");
75MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
76
77module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
78__MODULE_PARM_TYPE(disable, "string");
79MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
80
81/* notification function for packets from net device */
82static struct notifier_block libfcoe_notifier = {
83	.notifier_call = libfcoe_device_notification,
84};
85
86/**
87 * fcoe_link_speed_update() - Update the supported and actual link speeds
88 * @lport: The local port to update speeds for
89 *
90 * Returns: 0 if the ethtool query was successful
91 *          -1 if the ethtool query failed
92 */
93int fcoe_link_speed_update(struct fc_lport *lport)
94{
95	struct net_device *netdev = fcoe_get_netdev(lport);
96	struct ethtool_cmd ecmd;
97
98	if (!__ethtool_get_settings(netdev, &ecmd)) {
99		lport->link_supported_speeds &= ~(FC_PORTSPEED_1GBIT  |
100		                                  FC_PORTSPEED_10GBIT |
101		                                  FC_PORTSPEED_20GBIT |
102		                                  FC_PORTSPEED_40GBIT);
103
104		if (ecmd.supported & (SUPPORTED_1000baseT_Half |
105		                      SUPPORTED_1000baseT_Full |
106		                      SUPPORTED_1000baseKX_Full))
107			lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
108
109		if (ecmd.supported & (SUPPORTED_10000baseT_Full   |
110		                      SUPPORTED_10000baseKX4_Full |
111		                      SUPPORTED_10000baseKR_Full  |
112		                      SUPPORTED_10000baseR_FEC))
113			lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
114
115		if (ecmd.supported & (SUPPORTED_20000baseMLD2_Full |
116		                      SUPPORTED_20000baseKR2_Full))
117			lport->link_supported_speeds |= FC_PORTSPEED_20GBIT;
118
119		if (ecmd.supported & (SUPPORTED_40000baseKR4_Full |
120		                      SUPPORTED_40000baseCR4_Full |
121		                      SUPPORTED_40000baseSR4_Full |
122		                      SUPPORTED_40000baseLR4_Full))
123			lport->link_supported_speeds |= FC_PORTSPEED_40GBIT;
124
125		switch (ethtool_cmd_speed(&ecmd)) {
126		case SPEED_1000:
127			lport->link_speed = FC_PORTSPEED_1GBIT;
128			break;
129		case SPEED_10000:
130			lport->link_speed = FC_PORTSPEED_10GBIT;
131			break;
132		case 20000:
133			lport->link_speed = FC_PORTSPEED_20GBIT;
134			break;
135		case 40000:
136			lport->link_speed = FC_PORTSPEED_40GBIT;
137			break;
138		default:
139			lport->link_speed = FC_PORTSPEED_UNKNOWN;
140			break;
141		}
142		return 0;
143	}
144	return -1;
145}
146EXPORT_SYMBOL_GPL(fcoe_link_speed_update);
147
148/**
149 * __fcoe_get_lesb() - Get the Link Error Status Block (LESB) for a given lport
150 * @lport: The local port to update speeds for
151 * @fc_lesb: Pointer to the LESB to be filled up
152 * @netdev: Pointer to the netdev that is associated with the lport
153 *
154 * Note, the Link Error Status Block (LESB) for FCoE is defined in FC-BB-6
155 * Clause 7.11 in v1.04.
156 */
157void __fcoe_get_lesb(struct fc_lport *lport,
158		     struct fc_els_lesb *fc_lesb,
159		     struct net_device *netdev)
160{
161	unsigned int cpu;
162	u32 lfc, vlfc, mdac;
163	struct fc_stats *stats;
164	struct fcoe_fc_els_lesb *lesb;
165	struct rtnl_link_stats64 temp;
166
167	lfc = 0;
168	vlfc = 0;
169	mdac = 0;
170	lesb = (struct fcoe_fc_els_lesb *)fc_lesb;
171	memset(lesb, 0, sizeof(*lesb));
172	for_each_possible_cpu(cpu) {
173		stats = per_cpu_ptr(lport->stats, cpu);
174		lfc += stats->LinkFailureCount;
175		vlfc += stats->VLinkFailureCount;
176		mdac += stats->MissDiscAdvCount;
177	}
178	lesb->lesb_link_fail = htonl(lfc);
179	lesb->lesb_vlink_fail = htonl(vlfc);
180	lesb->lesb_miss_fka = htonl(mdac);
181	lesb->lesb_fcs_error =
182			htonl(dev_get_stats(netdev, &temp)->rx_crc_errors);
183}
184EXPORT_SYMBOL_GPL(__fcoe_get_lesb);
185
186/**
187 * fcoe_get_lesb() - Fill the FCoE Link Error Status Block
188 * @lport: the local port
189 * @fc_lesb: the link error status block
190 */
191void fcoe_get_lesb(struct fc_lport *lport,
192			 struct fc_els_lesb *fc_lesb)
193{
194	struct net_device *netdev = fcoe_get_netdev(lport);
195
196	__fcoe_get_lesb(lport, fc_lesb, netdev);
197}
198EXPORT_SYMBOL_GPL(fcoe_get_lesb);
199
200/**
201 * fcoe_ctlr_get_lesb() - Get the Link Error Status Block (LESB) for a given
202 * fcoe controller device
203 * @ctlr_dev: The given fcoe controller device
204 *
205 */
206void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
207{
208	struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
209	struct net_device *netdev = fcoe_get_netdev(fip->lp);
210	struct fc_els_lesb *fc_lesb;
211
212	fc_lesb = (struct fc_els_lesb *)(&ctlr_dev->lesb);
213	__fcoe_get_lesb(fip->lp, fc_lesb, netdev);
214}
215EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb);
216
217void fcoe_wwn_to_str(u64 wwn, char *buf, int len)
218{
219	u8 wwpn[8];
220
221	u64_to_wwn(wwn, wwpn);
222	snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
223		 wwpn[0], wwpn[1], wwpn[2], wwpn[3],
224		 wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
225}
226EXPORT_SYMBOL_GPL(fcoe_wwn_to_str);
227
228/**
229 * fcoe_validate_vport_create() - Validate a vport before creating it
230 * @vport: NPIV port to be created
231 *
232 * This routine is meant to add validation for a vport before creating it
233 * via fcoe_vport_create().
234 * Current validations are:
235 *      - WWPN supplied is unique for given lport
236 */
237int fcoe_validate_vport_create(struct fc_vport *vport)
238{
239	struct Scsi_Host *shost = vport_to_shost(vport);
240	struct fc_lport *n_port = shost_priv(shost);
241	struct fc_lport *vn_port;
242	int rc = 0;
243	char buf[32];
244
245	mutex_lock(&n_port->lp_mutex);
246
247	fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
248	/* Check if the wwpn is not same as that of the lport */
249	if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
250		LIBFCOE_TRANSPORT_DBG("vport WWPN 0x%s is same as that of the "
251				      "base port WWPN\n", buf);
252		rc = -EINVAL;
253		goto out;
254	}
255
256	/* Check if there is any existing vport with same wwpn */
257	list_for_each_entry(vn_port, &n_port->vports, list) {
258		if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
259			LIBFCOE_TRANSPORT_DBG("vport with given WWPN 0x%s "
260					      "already exists\n", buf);
261			rc = -EINVAL;
262			break;
263		}
264	}
265out:
266	mutex_unlock(&n_port->lp_mutex);
267	return rc;
268}
269EXPORT_SYMBOL_GPL(fcoe_validate_vport_create);
270
271/**
272 * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
273 * @netdev: the associated net device
274 * @wwn: the output WWN
275 * @type: the type of WWN (WWPN or WWNN)
276 *
277 * Returns: 0 for success
278 */
279int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
280{
281	const struct net_device_ops *ops = netdev->netdev_ops;
282
283	if (ops->ndo_fcoe_get_wwn)
284		return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
285	return -EINVAL;
286}
287EXPORT_SYMBOL_GPL(fcoe_get_wwn);
288
289/**
290 * fcoe_fc_crc() - Calculates the CRC for a given frame
291 * @fp: The frame to be checksumed
292 *
293 * This uses crc32() routine to calculate the CRC for a frame
294 *
295 * Return: The 32 bit CRC value
296 */
297u32 fcoe_fc_crc(struct fc_frame *fp)
298{
299	struct sk_buff *skb = fp_skb(fp);
300	struct skb_frag_struct *frag;
301	unsigned char *data;
302	unsigned long off, len, clen;
303	u32 crc;
304	unsigned i;
305
306	crc = crc32(~0, skb->data, skb_headlen(skb));
307
308	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
309		frag = &skb_shinfo(skb)->frags[i];
310		off = frag->page_offset;
311		len = skb_frag_size(frag);
312		while (len > 0) {
313			clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
314			data = kmap_atomic(
315				skb_frag_page(frag) + (off >> PAGE_SHIFT));
316			crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
317			kunmap_atomic(data);
318			off += clen;
319			len -= clen;
320		}
321	}
322	return crc;
323}
324EXPORT_SYMBOL_GPL(fcoe_fc_crc);
325
326/**
327 * fcoe_start_io() - Start FCoE I/O
328 * @skb: The packet to be transmitted
329 *
330 * This routine is called from the net device to start transmitting
331 * FCoE packets.
332 *
333 * Returns: 0 for success
334 */
335int fcoe_start_io(struct sk_buff *skb)
336{
337	struct sk_buff *nskb;
338	int rc;
339
340	nskb = skb_clone(skb, GFP_ATOMIC);
341	if (!nskb)
342		return -ENOMEM;
343	rc = dev_queue_xmit(nskb);
344	if (rc != 0)
345		return rc;
346	kfree_skb(skb);
347	return 0;
348}
349EXPORT_SYMBOL_GPL(fcoe_start_io);
350
351
352/**
353 * fcoe_clean_pending_queue() - Dequeue a skb and free it
354 * @lport: The local port to dequeue a skb on
355 */
356void fcoe_clean_pending_queue(struct fc_lport *lport)
357{
358	struct fcoe_port  *port = lport_priv(lport);
359	struct sk_buff *skb;
360
361	spin_lock_bh(&port->fcoe_pending_queue.lock);
362	while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
363		spin_unlock_bh(&port->fcoe_pending_queue.lock);
364		kfree_skb(skb);
365		spin_lock_bh(&port->fcoe_pending_queue.lock);
366	}
367	spin_unlock_bh(&port->fcoe_pending_queue.lock);
368}
369EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
370
371/**
372 * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
373 * @lport: The local port whose backlog is to be cleared
374 *
375 * This empties the wait_queue, dequeues the head of the wait_queue queue
376 * and calls fcoe_start_io() for each packet. If all skb have been
377 * transmitted it returns the qlen. If an error occurs it restores
378 * wait_queue (to try again later) and returns -1.
379 *
380 * The wait_queue is used when the skb transmit fails. The failed skb
381 * will go in the wait_queue which will be emptied by the timer function or
382 * by the next skb transmit.
383 */
384void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
385{
386	struct fcoe_port *port = lport_priv(lport);
387	int rc;
388
389	spin_lock_bh(&port->fcoe_pending_queue.lock);
390
391	if (skb)
392		__skb_queue_tail(&port->fcoe_pending_queue, skb);
393
394	if (port->fcoe_pending_queue_active)
395		goto out;
396	port->fcoe_pending_queue_active = 1;
397
398	while (port->fcoe_pending_queue.qlen) {
399		/* keep qlen > 0 until fcoe_start_io succeeds */
400		port->fcoe_pending_queue.qlen++;
401		skb = __skb_dequeue(&port->fcoe_pending_queue);
402
403		spin_unlock_bh(&port->fcoe_pending_queue.lock);
404		rc = fcoe_start_io(skb);
405		spin_lock_bh(&port->fcoe_pending_queue.lock);
406
407		if (rc) {
408			__skb_queue_head(&port->fcoe_pending_queue, skb);
409			/* undo temporary increment above */
410			port->fcoe_pending_queue.qlen--;
411			break;
412		}
413		/* undo temporary increment above */
414		port->fcoe_pending_queue.qlen--;
415	}
416
417	if (port->fcoe_pending_queue.qlen < port->min_queue_depth)
418		lport->qfull = 0;
419	if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
420		mod_timer(&port->timer, jiffies + 2);
421	port->fcoe_pending_queue_active = 0;
422out:
423	if (port->fcoe_pending_queue.qlen > port->max_queue_depth)
424		lport->qfull = 1;
425	spin_unlock_bh(&port->fcoe_pending_queue.lock);
426}
427EXPORT_SYMBOL_GPL(fcoe_check_wait_queue);
428
429/**
430 * fcoe_queue_timer() - The fcoe queue timer
431 * @lport: The local port
432 *
433 * Calls fcoe_check_wait_queue on timeout
434 */
435void fcoe_queue_timer(ulong lport)
436{
437	fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
438}
439EXPORT_SYMBOL_GPL(fcoe_queue_timer);
440
441/**
442 * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
443 * @skb:  The packet to be transmitted
444 * @tlen: The total length of the trailer
445 * @fps:  The fcoe context
446 *
447 * This routine allocates a page for frame trailers. The page is re-used if
448 * there is enough room left on it for the current trailer. If there isn't
449 * enough buffer left a new page is allocated for the trailer. Reference to
450 * the page from this function as well as the skbs using the page fragments
451 * ensure that the page is freed at the appropriate time.
452 *
453 * Returns: 0 for success
454 */
455int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
456			   struct fcoe_percpu_s *fps)
457{
458	struct page *page;
459
460	page = fps->crc_eof_page;
461	if (!page) {
462		page = alloc_page(GFP_ATOMIC);
463		if (!page)
464			return -ENOMEM;
465
466		fps->crc_eof_page = page;
467		fps->crc_eof_offset = 0;
468	}
469
470	get_page(page);
471	skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
472			   fps->crc_eof_offset, tlen);
473	skb->len += tlen;
474	skb->data_len += tlen;
475	skb->truesize += tlen;
476	fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
477
478	if (fps->crc_eof_offset >= PAGE_SIZE) {
479		fps->crc_eof_page = NULL;
480		fps->crc_eof_offset = 0;
481		put_page(page);
482	}
483
484	return 0;
485}
486EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof);
487
488/**
489 * fcoe_transport_lookup - find an fcoe transport that matches a netdev
490 * @netdev: The netdev to look for from all attached transports
491 *
492 * Returns : ptr to the fcoe transport that supports this netdev or NULL
493 * if not found.
494 *
495 * The ft_mutex should be held when this is called
496 */
497static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev)
498{
499	struct fcoe_transport *ft = NULL;
500
501	list_for_each_entry(ft, &fcoe_transports, list)
502		if (ft->match && ft->match(netdev))
503			return ft;
504	return NULL;
505}
506
507/**
508 * fcoe_transport_attach - Attaches an FCoE transport
509 * @ft: The fcoe transport to be attached
510 *
511 * Returns : 0 for success
512 */
513int fcoe_transport_attach(struct fcoe_transport *ft)
514{
515	int rc = 0;
516
517	mutex_lock(&ft_mutex);
518	if (ft->attached) {
519		LIBFCOE_TRANSPORT_DBG("transport %s already attached\n",
520				       ft->name);
521		rc = -EEXIST;
522		goto out_attach;
523	}
524
525	/* Add default transport to the tail */
526	if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT))
527		list_add(&ft->list, &fcoe_transports);
528	else
529		list_add_tail(&ft->list, &fcoe_transports);
530
531	ft->attached = true;
532	LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name);
533
534out_attach:
535	mutex_unlock(&ft_mutex);
536	return rc;
537}
538EXPORT_SYMBOL(fcoe_transport_attach);
539
540/**
541 * fcoe_transport_detach - Detaches an FCoE transport
542 * @ft: The fcoe transport to be attached
543 *
544 * Returns : 0 for success
545 */
546int fcoe_transport_detach(struct fcoe_transport *ft)
547{
548	int rc = 0;
549	struct fcoe_netdev_mapping *nm = NULL, *tmp;
550
551	mutex_lock(&ft_mutex);
552	if (!ft->attached) {
553		LIBFCOE_TRANSPORT_DBG("transport %s already detached\n",
554			ft->name);
555		rc = -ENODEV;
556		goto out_attach;
557	}
558
559	/* remove netdev mapping for this transport as it is going away */
560	mutex_lock(&fn_mutex);
561	list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
562		if (nm->ft == ft) {
563			LIBFCOE_TRANSPORT_DBG("transport %s going away, "
564				"remove its netdev mapping for %s\n",
565				ft->name, nm->netdev->name);
566			list_del(&nm->list);
567			kfree(nm);
568		}
569	}
570	mutex_unlock(&fn_mutex);
571
572	list_del(&ft->list);
573	ft->attached = false;
574	LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name);
575
576out_attach:
577	mutex_unlock(&ft_mutex);
578	return rc;
579
580}
581EXPORT_SYMBOL(fcoe_transport_detach);
582
583static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
584{
585	int i, j;
586	struct fcoe_transport *ft = NULL;
587
588	i = j = sprintf(buffer, "Attached FCoE transports:");
589	mutex_lock(&ft_mutex);
590	list_for_each_entry(ft, &fcoe_transports, list) {
591		if (i >= PAGE_SIZE - IFNAMSIZ)
592			break;
593		i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
594	}
595	mutex_unlock(&ft_mutex);
596	if (i == j)
597		i += snprintf(&buffer[i], IFNAMSIZ, "none");
598	return i;
599}
600
601static int __init fcoe_transport_init(void)
602{
603	register_netdevice_notifier(&libfcoe_notifier);
604	return 0;
605}
606
607static int fcoe_transport_exit(void)
608{
609	struct fcoe_transport *ft;
610
611	unregister_netdevice_notifier(&libfcoe_notifier);
612	mutex_lock(&ft_mutex);
613	list_for_each_entry(ft, &fcoe_transports, list)
614		printk(KERN_ERR "FCoE transport %s is still attached!\n",
615		      ft->name);
616	mutex_unlock(&ft_mutex);
617	return 0;
618}
619
620
621static int fcoe_add_netdev_mapping(struct net_device *netdev,
622					struct fcoe_transport *ft)
623{
624	struct fcoe_netdev_mapping *nm;
625
626	nm = kmalloc(sizeof(*nm), GFP_KERNEL);
627	if (!nm) {
628		printk(KERN_ERR "Unable to allocate netdev_mapping");
629		return -ENOMEM;
630	}
631
632	nm->netdev = netdev;
633	nm->ft = ft;
634
635	mutex_lock(&fn_mutex);
636	list_add(&nm->list, &fcoe_netdevs);
637	mutex_unlock(&fn_mutex);
638	return 0;
639}
640
641
642static void fcoe_del_netdev_mapping(struct net_device *netdev)
643{
644	struct fcoe_netdev_mapping *nm = NULL, *tmp;
645
646	mutex_lock(&fn_mutex);
647	list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
648		if (nm->netdev == netdev) {
649			list_del(&nm->list);
650			kfree(nm);
651			mutex_unlock(&fn_mutex);
652			return;
653		}
654	}
655	mutex_unlock(&fn_mutex);
656}
657
658
659/**
660 * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which
661 * it was created
662 *
663 * Returns : ptr to the fcoe transport that supports this netdev or NULL
664 * if not found.
665 *
666 * The ft_mutex should be held when this is called
667 */
668static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
669{
670	struct fcoe_transport *ft = NULL;
671	struct fcoe_netdev_mapping *nm;
672
673	mutex_lock(&fn_mutex);
674	list_for_each_entry(nm, &fcoe_netdevs, list) {
675		if (netdev == nm->netdev) {
676			ft = nm->ft;
677			mutex_unlock(&fn_mutex);
678			return ft;
679		}
680	}
681
682	mutex_unlock(&fn_mutex);
683	return NULL;
684}
685
686/**
687 * fcoe_if_to_netdev() - Parse a name buffer to get a net device
688 * @buffer: The name of the net device
689 *
690 * Returns: NULL or a ptr to net_device
691 */
692static struct net_device *fcoe_if_to_netdev(const char *buffer)
693{
694	char *cp;
695	char ifname[IFNAMSIZ + 2];
696
697	if (buffer) {
698		strlcpy(ifname, buffer, IFNAMSIZ);
699		cp = ifname + strlen(ifname);
700		while (--cp >= ifname && *cp == '\n')
701			*cp = '\0';
702		return dev_get_by_name(&init_net, ifname);
703	}
704	return NULL;
705}
706
707/**
708 * libfcoe_device_notification() - Handler for net device events
709 * @notifier: The context of the notification
710 * @event:    The type of event
711 * @ptr:      The net device that the event was on
712 *
713 * This function is called by the Ethernet driver in case of link change event.
714 *
715 * Returns: 0 for success
716 */
717static int libfcoe_device_notification(struct notifier_block *notifier,
718				    ulong event, void *ptr)
719{
720	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
721
722	switch (event) {
723	case NETDEV_UNREGISTER:
724		LIBFCOE_TRANSPORT_DBG("NETDEV_UNREGISTER %s\n",
725				      netdev->name);
726		fcoe_del_netdev_mapping(netdev);
727		break;
728	}
729	return NOTIFY_OK;
730}
731
732ssize_t fcoe_ctlr_create_store(struct bus_type *bus,
733			       const char *buf, size_t count)
734{
735	struct net_device *netdev = NULL;
736	struct fcoe_transport *ft = NULL;
737	int rc = 0;
738	int err;
739
740	mutex_lock(&ft_mutex);
741
742	netdev = fcoe_if_to_netdev(buf);
743	if (!netdev) {
744		LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buf);
745		rc = -ENODEV;
746		goto out_nodev;
747	}
748
749	ft = fcoe_netdev_map_lookup(netdev);
750	if (ft) {
751		LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
752				      "FCoE instance on %s.\n",
753				      ft->name, netdev->name);
754		rc = -EEXIST;
755		goto out_putdev;
756	}
757
758	ft = fcoe_transport_lookup(netdev);
759	if (!ft) {
760		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
761				      netdev->name);
762		rc = -ENODEV;
763		goto out_putdev;
764	}
765
766	/* pass to transport create */
767	err = ft->alloc ? ft->alloc(netdev) : -ENODEV;
768	if (err) {
769		fcoe_del_netdev_mapping(netdev);
770		rc = -ENOMEM;
771		goto out_putdev;
772	}
773
774	err = fcoe_add_netdev_mapping(netdev, ft);
775	if (err) {
776		LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
777				      "for FCoE transport %s for %s.\n",
778				      ft->name, netdev->name);
779		rc = -ENODEV;
780		goto out_putdev;
781	}
782
783	LIBFCOE_TRANSPORT_DBG("transport %s succeeded to create fcoe on %s.\n",
784			      ft->name, netdev->name);
785
786out_putdev:
787	dev_put(netdev);
788out_nodev:
789	mutex_unlock(&ft_mutex);
790	if (rc)
791		return rc;
792	return count;
793}
794
795ssize_t fcoe_ctlr_destroy_store(struct bus_type *bus,
796				const char *buf, size_t count)
797{
798	int rc = -ENODEV;
799	struct net_device *netdev = NULL;
800	struct fcoe_transport *ft = NULL;
801
802	mutex_lock(&ft_mutex);
803
804	netdev = fcoe_if_to_netdev(buf);
805	if (!netdev) {
806		LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buf);
807		goto out_nodev;
808	}
809
810	ft = fcoe_netdev_map_lookup(netdev);
811	if (!ft) {
812		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
813				      netdev->name);
814		goto out_putdev;
815	}
816
817	/* pass to transport destroy */
818	rc = ft->destroy(netdev);
819	if (rc)
820		goto out_putdev;
821
822	fcoe_del_netdev_mapping(netdev);
823	LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
824			      ft->name, (rc) ? "failed" : "succeeded",
825			      netdev->name);
826	rc = count; /* required for successful return */
827out_putdev:
828	dev_put(netdev);
829out_nodev:
830	mutex_unlock(&ft_mutex);
831	return rc;
832}
833EXPORT_SYMBOL(fcoe_ctlr_destroy_store);
834
835/**
836 * fcoe_transport_create() - Create a fcoe interface
837 * @buffer: The name of the Ethernet interface to create on
838 * @kp:	    The associated kernel param
839 *
840 * Called from sysfs. This holds the ft_mutex while calling the
841 * registered fcoe transport's create function.
842 *
843 * Returns: 0 for success
844 */
845static int fcoe_transport_create(const char *buffer, struct kernel_param *kp)
846{
847	int rc = -ENODEV;
848	struct net_device *netdev = NULL;
849	struct fcoe_transport *ft = NULL;
850	enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
851
852	mutex_lock(&ft_mutex);
853
854	netdev = fcoe_if_to_netdev(buffer);
855	if (!netdev) {
856		LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer);
857		goto out_nodev;
858	}
859
860	ft = fcoe_netdev_map_lookup(netdev);
861	if (ft) {
862		LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
863				      "FCoE instance on %s.\n",
864				      ft->name, netdev->name);
865		rc = -EEXIST;
866		goto out_putdev;
867	}
868
869	ft = fcoe_transport_lookup(netdev);
870	if (!ft) {
871		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
872				      netdev->name);
873		goto out_putdev;
874	}
875
876	rc = fcoe_add_netdev_mapping(netdev, ft);
877	if (rc) {
878		LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
879				      "for FCoE transport %s for %s.\n",
880				      ft->name, netdev->name);
881		goto out_putdev;
882	}
883
884	/* pass to transport create */
885	rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV;
886	if (rc)
887		fcoe_del_netdev_mapping(netdev);
888
889	LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
890			      ft->name, (rc) ? "failed" : "succeeded",
891			      netdev->name);
892
893out_putdev:
894	dev_put(netdev);
895out_nodev:
896	mutex_unlock(&ft_mutex);
897	return rc;
898}
899
900/**
901 * fcoe_transport_destroy() - Destroy a FCoE interface
902 * @buffer: The name of the Ethernet interface to be destroyed
903 * @kp:	    The associated kernel parameter
904 *
905 * Called from sysfs. This holds the ft_mutex while calling the
906 * registered fcoe transport's destroy function.
907 *
908 * Returns: 0 for success
909 */
910static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp)
911{
912	int rc = -ENODEV;
913	struct net_device *netdev = NULL;
914	struct fcoe_transport *ft = NULL;
915
916	mutex_lock(&ft_mutex);
917
918	netdev = fcoe_if_to_netdev(buffer);
919	if (!netdev) {
920		LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer);
921		goto out_nodev;
922	}
923
924	ft = fcoe_netdev_map_lookup(netdev);
925	if (!ft) {
926		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
927				      netdev->name);
928		goto out_putdev;
929	}
930
931	/* pass to transport destroy */
932	rc = ft->destroy ? ft->destroy(netdev) : -ENODEV;
933	fcoe_del_netdev_mapping(netdev);
934	LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
935			      ft->name, (rc) ? "failed" : "succeeded",
936			      netdev->name);
937
938out_putdev:
939	dev_put(netdev);
940out_nodev:
941	mutex_unlock(&ft_mutex);
942	return rc;
943}
944
945/**
946 * fcoe_transport_disable() - Disables a FCoE interface
947 * @buffer: The name of the Ethernet interface to be disabled
948 * @kp:	    The associated kernel parameter
949 *
950 * Called from sysfs.
951 *
952 * Returns: 0 for success
953 */
954static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp)
955{
956	int rc = -ENODEV;
957	struct net_device *netdev = NULL;
958	struct fcoe_transport *ft = NULL;
959
960	mutex_lock(&ft_mutex);
961
962	netdev = fcoe_if_to_netdev(buffer);
963	if (!netdev)
964		goto out_nodev;
965
966	ft = fcoe_netdev_map_lookup(netdev);
967	if (!ft)
968		goto out_putdev;
969
970	rc = ft->disable ? ft->disable(netdev) : -ENODEV;
971
972out_putdev:
973	dev_put(netdev);
974out_nodev:
975	mutex_unlock(&ft_mutex);
976	return rc;
977}
978
979/**
980 * fcoe_transport_enable() - Enables a FCoE interface
981 * @buffer: The name of the Ethernet interface to be enabled
982 * @kp:     The associated kernel parameter
983 *
984 * Called from sysfs.
985 *
986 * Returns: 0 for success
987 */
988static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp)
989{
990	int rc = -ENODEV;
991	struct net_device *netdev = NULL;
992	struct fcoe_transport *ft = NULL;
993
994	mutex_lock(&ft_mutex);
995
996	netdev = fcoe_if_to_netdev(buffer);
997	if (!netdev)
998		goto out_nodev;
999
1000	ft = fcoe_netdev_map_lookup(netdev);
1001	if (!ft)
1002		goto out_putdev;
1003
1004	rc = ft->enable ? ft->enable(netdev) : -ENODEV;
1005
1006out_putdev:
1007	dev_put(netdev);
1008out_nodev:
1009	mutex_unlock(&ft_mutex);
1010	return rc;
1011}
1012
1013/**
1014 * libfcoe_init() - Initialization routine for libfcoe.ko
1015 */
1016static int __init libfcoe_init(void)
1017{
1018	int rc = 0;
1019
1020	rc = fcoe_transport_init();
1021	if (rc)
1022		return rc;
1023
1024	rc = fcoe_sysfs_setup();
1025	if (rc)
1026		fcoe_transport_exit();
1027
1028	return rc;
1029}
1030module_init(libfcoe_init);
1031
1032/**
1033 * libfcoe_exit() - Tear down libfcoe.ko
1034 */
1035static void __exit libfcoe_exit(void)
1036{
1037	fcoe_sysfs_teardown();
1038	fcoe_transport_exit();
1039}
1040module_exit(libfcoe_exit);
1041