]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/open-fcoe-driver
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / open-fcoe-driver
CommitLineData
2cb7cef9
BS
1From: Hannes Reinecke <hare@suse.de>
2Date: Wed, 17 Sep 2008 16:25:23 +0200
3Subject: fcoe: Fibre Channel over Ethernet driver
4References: FATE#303913
5
6Encapsulation protocol for running Fibre Channel over Ethernet interfaces.
7Creates virtual Fibre Channel host adapters using libfc.
8
9Signed-off-by: Robert Love <robert.w.love@intel.com>
10Signed-off-by: Chris Leech <christopher.leech@intel.com>
11Signed-off-by: Vasu Dev <vasu.dev@intel.com>
12Signed-off-by: Yi Zou <yi.zou@intel.com>
13Signed-off-by: Steve Ma <steve.ma@intel.com>
14Signed-off-by: Hannes Reinecke <hare@suse.de>
15---
16 drivers/scsi/Kconfig | 6 +
17 drivers/scsi/Makefile | 1 +
18 drivers/scsi/fcoe/Makefile | 8 +
19 drivers/scsi/fcoe/fcoe_def.h | 100 +++++++
20 drivers/scsi/fcoe/fcoe_dev.c | 633 ++++++++++++++++++++++++++++++++++++++++++
21 drivers/scsi/fcoe/fcoe_if.c | 497 +++++++++++++++++++++++++++++++++
22 drivers/scsi/fcoe/fcoeinit.c | 440 +++++++++++++++++++++++++++++
23 7 files changed, 1685 insertions(+), 0 deletions(-)
24 create mode 100644 drivers/scsi/fcoe/Makefile
25 create mode 100644 drivers/scsi/fcoe/fcoe_def.h
26 create mode 100644 drivers/scsi/fcoe/fcoe_dev.c
27 create mode 100644 drivers/scsi/fcoe/fcoe_if.c
28 create mode 100644 drivers/scsi/fcoe/fcoeinit.c
29
30diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
31index bd480d2..f382eea 100644
32--- a/drivers/scsi/Kconfig
33+++ b/drivers/scsi/Kconfig
34@@ -334,6 +334,12 @@ config LIBFC
35 ---help---
36 Fibre Channel library module
37
38+config FCOE
39+ tristate "FCoE module"
40+ depends on LIBFC
41+ ---help---
42+ Fibre Channel over Ethernet module
43+
44 config ISCSI_TCP
45 tristate "iSCSI Initiator over TCP/IP"
46 depends on SCSI && INET
47diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
48index 9158dc6..22c01e5 100644
49--- a/drivers/scsi/Makefile
50+++ b/drivers/scsi/Makefile
51@@ -37,6 +37,7 @@ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o
52 obj-$(CONFIG_SCSI_DH) += device_handler/
53
54 obj-$(CONFIG_LIBFC) += libfc/
55+obj-$(CONFIG_FCOE) += fcoe/
56 obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o
57 obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o
58 obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o
59diff --git a/drivers/scsi/fcoe/Makefile b/drivers/scsi/fcoe/Makefile
60new file mode 100644
61index 0000000..342e2ad
62--- /dev/null
63+++ b/drivers/scsi/fcoe/Makefile
64@@ -0,0 +1,8 @@
65+# $Id: Makefile
66+
67+obj-$(CONFIG_FCOE) += fcoe.o
68+
69+fcoe-y := \
70+ fcoe_dev.o \
71+ fcoe_if.o \
72+ fcoeinit.o
73diff --git a/drivers/scsi/fcoe/fcoe_def.h b/drivers/scsi/fcoe/fcoe_def.h
74new file mode 100644
75index 0000000..12bf69c
76--- /dev/null
77+++ b/drivers/scsi/fcoe/fcoe_def.h
78@@ -0,0 +1,100 @@
79+/*
80+ * Copyright(c) 2007 Intel Corporation. All rights reserved.
81+ *
82+ * This program is free software; you can redistribute it and/or modify it
83+ * under the terms and conditions of the GNU General Public License,
84+ * version 2, as published by the Free Software Foundation.
85+ *
86+ * This program is distributed in the hope it will be useful, but WITHOUT
87+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
88+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
89+ * more details.
90+ *
91+ * You should have received a copy of the GNU General Public License along with
92+ * this program; if not, write to the Free Software Foundation, Inc.,
93+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
94+ *
95+ * Maintained at www.Open-FCoE.org
96+ */
97+
98+#ifndef _FCOE_DEF_H_
99+#define _FCOE_DEF_H_
100+
101+#include <linux/etherdevice.h>
102+#include <linux/if_ether.h>
103+
104+#include <scsi/libfc/libfc.h>
105+
106+#include <scsi/fc/fc_fcoe.h>
107+
108+#define FCOE_DRIVER_NAME "fcoe" /* driver name for ioctls */
109+#define FCOE_DRIVER_VENDOR "Open-FC.org" /* vendor name for ioctls */
110+
111+#define FCOE_MIN_FRAME 36
112+#define FCOE_WORD_TO_BYTE 4
113+
114+/*
115+ * this is the main common structure across all instance of fcoe driver.
116+ * There is one to one mapping between hba struct and ethernet nic.
117+ * list of hbas contains pointer to the hba struct, these structures are
118+ * stored in this array using there corresponding if_index.
119+ */
120+
121+struct fcoe_percpu_s {
122+ int cpu;
123+ struct task_struct *thread;
124+ struct sk_buff_head fcoe_rx_list;
125+ struct page *crc_eof_page;
126+ int crc_eof_offset;
127+};
128+
129+struct fcoe_info {
130+ struct timer_list timer;
131+ /*
132+ * fcoe host list is protected by the following read/write lock
133+ */
134+ rwlock_t fcoe_hostlist_lock;
135+ struct list_head fcoe_hostlist;
136+
137+ struct fcoe_percpu_s *fcoe_percpu[NR_CPUS];
138+};
139+
140+struct fcoe_softc {
141+ struct list_head list;
142+ struct fc_lport *lp;
143+ struct net_device *real_dev;
144+ struct net_device *phys_dev; /* device with ethtool_ops */
145+ struct packet_type fcoe_packet_type;
146+ struct sk_buff_head fcoe_pending_queue;
147+ u16 user_mfs; /* configured max frame size */
148+
149+ u8 dest_addr[ETH_ALEN];
150+ u8 ctl_src_addr[ETH_ALEN];
151+ u8 data_src_addr[ETH_ALEN];
152+ /*
153+ * fcoe protocol address learning related stuff
154+ */
155+ u16 flogi_oxid;
156+ u8 flogi_progress;
157+ u8 address_mode;
158+};
159+
160+extern int debug_fcoe;
161+extern struct fcoe_percpu_s *fcoe_percpu[];
162+extern struct scsi_transport_template *fcoe_transport_template;
163+int fcoe_percpu_receive_thread(void *arg);
164+
165+/*
166+ * HBA transport ops prototypes
167+ */
168+extern struct fcoe_info fcoei;
169+
170+void fcoe_clean_pending_queue(struct fc_lport *fd);
171+void fcoe_watchdog(ulong vp);
172+int fcoe_destroy_interface(const char *ifname);
173+int fcoe_create_interface(const char *ifname);
174+int fcoe_xmit(struct fc_lport *, struct fc_frame *);
175+int fcoe_rcv(struct sk_buff *, struct net_device *,
176+ struct packet_type *, struct net_device *);
177+int fcoe_link_ok(struct fc_lport *);
178+#endif /* _FCOE_DEF_H_ */
179diff --git a/drivers/scsi/fcoe/fcoe_dev.c b/drivers/scsi/fcoe/fcoe_dev.c
180new file mode 100644
181index 0000000..d5a354f
182--- /dev/null
183+++ b/drivers/scsi/fcoe/fcoe_dev.c
184@@ -0,0 +1,633 @@
185+/*
186+ * Copyright(c) 2007 Intel Corporation. All rights reserved.
187+ *
188+ * This program is free software; you can redistribute it and/or modify it
189+ * under the terms and conditions of the GNU General Public License,
190+ * version 2, as published by the Free Software Foundation.
191+ *
192+ * This program is distributed in the hope it will be useful, but WITHOUT
193+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
194+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
195+ * more details.
196+ *
197+ * You should have received a copy of the GNU General Public License along with
198+ * this program; if not, write to the Free Software Foundation, Inc.,
199+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
200+ *
201+ * Maintained at www.Open-FCoE.org
202+ */
203+
204+/*
205+ * FCOE protocol file
206+ */
207+
208+#include <linux/module.h>
209+#include <linux/version.h>
210+#include <linux/kernel.h>
211+#include <linux/spinlock.h>
212+#include <linux/skbuff.h>
213+#include <linux/netdevice.h>
214+#include <linux/etherdevice.h>
215+#include <linux/if_ether.h>
216+#include <linux/kthread.h>
217+#include <linux/crc32.h>
218+#include <scsi/scsi_tcq.h>
219+#include <scsi/scsicam.h>
220+#include <scsi/scsi_transport.h>
221+#include <scsi/scsi_transport_fc.h>
222+#include <net/rtnetlink.h>
223+
224+#include <scsi/fc/fc_encaps.h>
225+
226+#include <scsi/libfc/libfc.h>
227+#include <scsi/libfc/fc_frame.h>
228+
229+#include <scsi/fc/fc_fcoe.h>
230+#include "fcoe_def.h"
231+
232+#define FCOE_MAX_QUEUE_DEPTH 256
233+
234+/* destination address mode */
235+#define FCOE_GW_ADDR_MODE 0x00
236+#define FCOE_FCOUI_ADDR_MODE 0x01
237+
238+/* Function Prototyes */
239+static int fcoe_check_wait_queue(struct fc_lport *);
240+static void fcoe_insert_wait_queue_head(struct fc_lport *, struct sk_buff *);
241+static void fcoe_insert_wait_queue(struct fc_lport *, struct sk_buff *);
242+static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *);
243+
244+/*
245+ * this is the fcoe receive function
246+ * called by NET_RX_SOFTIRQ
247+ * this function will receive the packet and
248+ * build fc frame and pass it up
249+ */
250+int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
251+ struct packet_type *ptype, struct net_device *olddev)
252+{
253+ struct fc_lport *lp;
254+ struct fcoe_rcv_info *fr;
255+ struct fcoe_softc *fc;
256+ struct fcoe_dev_stats *stats;
257+ u8 *data;
258+ struct fc_frame_header *fh;
259+ unsigned short oxid;
260+ int cpu_idx;
261+ struct fcoe_percpu_s *fps;
262+ struct fcoe_info *fci = &fcoei;
263+
264+ fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
265+ lp = fc->lp;
266+ if (unlikely(lp == NULL)) {
267+ FC_DBG("cannot find hba structure");
268+ goto err2;
269+ }
270+
271+ if (unlikely(debug_fcoe)) {
272+ FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p "
273+ "end:%p sum:%d dev:%s", skb->len, skb->data_len,
274+ skb->head, skb->data, skb_tail_pointer(skb),
275+ skb_end_pointer(skb), skb->csum,
276+ skb->dev ? skb->dev->name : "<NULL>");
277+
278+ }
279+
280+ /* check for FCOE packet type */
281+ if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
282+ FC_DBG("wrong FC type frame");
283+ goto err;
284+ }
285+ data = skb->data;
286+ data += sizeof(struct fcoe_hdr);
287+ fh = (struct fc_frame_header *)data;
288+ oxid = ntohs(fh->fh_ox_id);
289+
290+ fr = fcoe_dev_from_skb(skb);
291+ fr->fr_dev = lp;
292+ fr->ptype = ptype;
293+ cpu_idx = 0;
294+#ifdef CONFIG_SMP
295+ /*
296+ * The exchange ID are ANDed with num of online CPUs,
297+ * so that will have the least lock contention in
298+ * handling the exchange. if there is no thread
299+ * for a given idx then use first online cpu.
300+ */
301+ cpu_idx = oxid & (num_online_cpus() >> 1);
302+ if (fci->fcoe_percpu[cpu_idx] == NULL)
303+ cpu_idx = first_cpu(cpu_online_map);
304+#endif
305+ fps = fci->fcoe_percpu[cpu_idx];
306+
307+ spin_lock_bh(&fps->fcoe_rx_list.lock);
308+ __skb_queue_tail(&fps->fcoe_rx_list, skb);
309+ if (fps->fcoe_rx_list.qlen == 1)
310+ wake_up_process(fps->thread);
311+
312+ spin_unlock_bh(&fps->fcoe_rx_list.lock);
313+
314+ return 0;
315+err:
316+#ifdef CONFIG_SMP
317+ stats = lp->dev_stats[smp_processor_id()];
318+#else
319+ stats = lp->dev_stats[0];
320+#endif
321+ stats->ErrorFrames++;
322+
323+err2:
324+ kfree_skb(skb);
325+ return -1;
326+}
327+
328+static inline int fcoe_start_io(struct sk_buff *skb)
329+{
330+ int rc;
331+
332+ skb_get(skb);
333+ rc = dev_queue_xmit(skb);
334+ if (rc != 0)
335+ return rc;
336+ kfree_skb(skb);
337+ return 0;
338+}
339+
340+static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
341+{
342+ struct fcoe_info *fci = &fcoei;
343+ struct fcoe_percpu_s *fps;
344+ struct page *page;
345+ int cpu_idx;
346+
347+ cpu_idx = get_cpu();
348+ fps = fci->fcoe_percpu[cpu_idx];
349+ page = fps->crc_eof_page;
350+ if (!page) {
351+ page = alloc_page(GFP_ATOMIC);
352+ if (!page) {
353+ put_cpu();
354+ return -ENOMEM;
355+ }
356+ fps->crc_eof_page = page;
357+ WARN_ON(fps->crc_eof_offset != 0);
358+ }
359+
360+ get_page(page);
361+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
362+ fps->crc_eof_offset, tlen);
363+ skb->len += tlen;
364+ skb->data_len += tlen;
365+ skb->truesize += tlen;
366+ fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
367+
368+ if (fps->crc_eof_offset >= PAGE_SIZE) {
369+ fps->crc_eof_page = NULL;
370+ fps->crc_eof_offset = 0;
371+ put_page(page);
372+ }
373+ put_cpu();
374+ return 0;
375+}
376+
377+/*
378+ * this is the frame xmit routine
379+ */
380+int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
381+{
382+ int indx;
383+ int wlen, rc = 0;
384+ u32 crc;
385+ struct ethhdr *eh;
386+ struct fcoe_crc_eof *cp;
387+ struct sk_buff *skb;
388+ struct fcoe_dev_stats *stats;
389+ struct fc_frame_header *fh;
390+ unsigned int hlen; /* header length implies the version */
391+ unsigned int tlen; /* trailer length */
392+ int flogi_in_progress = 0;
393+ struct fcoe_softc *fc;
394+ void *data;
395+ u8 sof, eof;
396+ struct fcoe_hdr *hp;
397+
398+ WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
399+
400+ fc = (struct fcoe_softc *)lp->drv_priv;
401+ /*
402+ * if it is a flogi then we need to learn gw-addr
403+ * and my own fcid
404+ */
405+ fh = fc_frame_header_get(fp);
406+ if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
407+ if (fc_frame_payload_op(fp) == ELS_FLOGI) {
408+ fc->flogi_oxid = ntohs(fh->fh_ox_id);
409+ fc->address_mode = FCOE_FCOUI_ADDR_MODE;
410+ fc->flogi_progress = 1;
411+ flogi_in_progress = 1;
412+ } else if (fc->flogi_progress && ntoh24(fh->fh_s_id) != 0) {
413+ /*
414+ * Here we must've gotten an SID by accepting an FLOGI
415+ * from a point-to-point connection. Switch to using
416+ * the source mac based on the SID. The destination
417+ * MAC in this case would have been set by receving the
418+ * FLOGI.
419+ */
420+ fc_fcoe_set_mac(fc->data_src_addr, fh->fh_s_id);
421+ fc->flogi_progress = 0;
422+ }
423+ }
424+
425+ skb = fp_skb(fp);
426+ sof = fr_sof(fp);
427+ eof = fr_eof(fp);
428+
429+ crc = ~0;
430+ crc = crc32(crc, skb->data, skb_headlen(skb));
431+
432+ for (indx = 0; indx < skb_shinfo(skb)->nr_frags; indx++) {
433+ skb_frag_t *frag = &skb_shinfo(skb)->frags[indx];
434+ unsigned long off = frag->page_offset;
435+ unsigned long len = frag->size;
436+
437+ while (len > 0) {
438+ unsigned long clen;
439+
440+ clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
441+ data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
442+ KM_SKB_DATA_SOFTIRQ);
443+ crc = crc32(crc, data + (off & ~PAGE_MASK),
444+ clen);
445+ kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
446+ off += clen;
447+ len -= clen;
448+ }
449+ }
450+
451+ /*
452+ * Get header and trailer lengths.
453+ * This is temporary code until we get rid of the old protocol.
454+ * Both versions have essentially the same trailer layout but T11
455+ * has padding afterwards.
456+ */
457+ hlen = sizeof(struct fcoe_hdr);
458+ tlen = sizeof(struct fcoe_crc_eof);
459+
460+ /*
461+ * copy fc crc and eof to the skb buff
462+ * Use utility buffer in the fc_frame part of the sk_buff for the
463+ * trailer.
464+ * We don't do a get_page for this frag, since that page may not be
465+ * managed that way. So that skb_free() doesn't do that either, we
466+ * setup the destructor to remove this frag.
467+ */
468+ if (skb_is_nonlinear(skb)) {
469+ skb_frag_t *frag;
470+ if (fcoe_get_paged_crc_eof(skb, tlen)) {
471+ kfree(skb);
472+ return -ENOMEM;
473+ }
474+ frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
475+ cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
476+ + frag->page_offset;
477+ } else {
478+ cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
479+ }
480+
481+ cp->fcoe_eof = eof;
482+ cp->fcoe_crc32 = cpu_to_le32(~crc);
483+ if (tlen == sizeof(*cp))
484+ memset(cp->fcoe_resvd, 0, sizeof(cp->fcoe_resvd));
485+ wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE;
486+
487+ if (skb_is_nonlinear(skb)) {
488+ kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
489+ cp = NULL;
490+ }
491+
492+ /*
493+ * Fill in the control structures
494+ */
495+ skb->ip_summed = CHECKSUM_NONE;
496+ eh = (struct ethhdr *)skb_push(skb, hlen + sizeof(struct ethhdr));
497+ if (fc->address_mode == FCOE_FCOUI_ADDR_MODE)
498+ fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
499+ else
500+ /* insert GW address */
501+ memcpy(eh->h_dest, fc->dest_addr, ETH_ALEN);
502+
503+ if (unlikely(flogi_in_progress))
504+ memcpy(eh->h_source, fc->ctl_src_addr, ETH_ALEN);
505+ else
506+ memcpy(eh->h_source, fc->data_src_addr, ETH_ALEN);
507+
508+ eh->h_proto = htons(ETH_P_FCOE);
509+ skb->protocol = htons(ETH_P_802_3);
510+ skb_reset_mac_header(skb);
511+ skb_reset_network_header(skb);
512+
513+ hp = (struct fcoe_hdr *)(eh + 1);
514+ memset(hp, 0, sizeof(*hp));
515+ if (FC_FCOE_VER)
516+ FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
517+ hp->fcoe_sof = sof;
518+
519+ stats = lp->dev_stats[smp_processor_id()];
520+ stats->TxFrames++;
521+ stats->TxWords += wlen;
522+ skb->dev = fc->real_dev;
523+
524+ fr_dev(fp) = lp;
525+ if (fc->fcoe_pending_queue.qlen)
526+ rc = fcoe_check_wait_queue(lp);
527+
528+ if (rc == 0)
529+ rc = fcoe_start_io(skb);
530+
531+ if (rc) {
532+ fcoe_insert_wait_queue(lp, skb);
533+ if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
534+ fc_pause(lp);
535+ }
536+
537+ return 0;
538+}
539+
540+int fcoe_percpu_receive_thread(void *arg)
541+{
542+ struct fcoe_percpu_s *p = arg;
543+ u32 fr_len;
544+ unsigned int hlen;
545+ unsigned int tlen;
546+ struct fc_lport *lp;
547+ struct fcoe_rcv_info *fr;
548+ struct fcoe_dev_stats *stats;
549+ struct fc_frame_header *fh;
550+ struct sk_buff *skb;
551+ struct fcoe_crc_eof *cp;
552+ enum fc_sof sof;
553+ struct fc_frame *fp;
554+ u8 *mac = NULL;
555+ struct fcoe_softc *fc;
556+ struct fcoe_hdr *hp;
557+
558+ set_user_nice(current, 19);
559+
560+ while (!kthread_should_stop()) {
561+
562+ spin_lock_bh(&p->fcoe_rx_list.lock);
563+ while ((skb = __skb_dequeue(&p->fcoe_rx_list)) == NULL) {
564+ set_current_state(TASK_INTERRUPTIBLE);
565+ spin_unlock_bh(&p->fcoe_rx_list.lock);
566+ schedule();
567+ set_current_state(TASK_RUNNING);
568+ if (kthread_should_stop())
569+ return 0;
570+ spin_lock_bh(&p->fcoe_rx_list.lock);
571+ }
572+ spin_unlock_bh(&p->fcoe_rx_list.lock);
573+ fr = fcoe_dev_from_skb(skb);
574+ lp = fr->fr_dev;
575+ if (unlikely(lp == NULL)) {
576+ FC_DBG("invalid HBA Structure");
577+ kfree_skb(skb);
578+ continue;
579+ }
580+
581+ stats = lp->dev_stats[smp_processor_id()];
582+
583+ if (unlikely(debug_fcoe)) {
584+ FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p "
585+ "tail:%p end:%p sum:%d dev:%s",
586+ skb->len, skb->data_len,
587+ skb->head, skb->data, skb_tail_pointer(skb),
588+ skb_end_pointer(skb), skb->csum,
589+ skb->dev ? skb->dev->name : "<NULL>");
590+ }
591+
592+ /*
593+ * Save source MAC address before discarding header.
594+ */
595+ fc = lp->drv_priv;
596+ if (unlikely(fc->flogi_progress))
597+ mac = eth_hdr(skb)->h_source;
598+
599+ if (skb_is_nonlinear(skb))
600+ skb_linearize(skb); /* not ideal */
601+
602+ /*
603+ * Check the header and pull it off.
604+ */
605+ hlen = sizeof(struct fcoe_hdr);
606+
607+ hp = (struct fcoe_hdr *)skb->data;
608+ if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
609+ if (stats->ErrorFrames < 5)
610+ FC_DBG("unknown FCoE version %x",
611+ FC_FCOE_DECAPS_VER(hp));
612+ stats->ErrorFrames++;
613+ kfree_skb(skb);
614+ continue;
615+ }
616+ sof = hp->fcoe_sof;
617+ skb_pull(skb, sizeof(*hp));
618+ fr_len = skb->len - sizeof(struct fcoe_crc_eof);
619+ skb_trim(skb, fr_len);
620+ tlen = sizeof(struct fcoe_crc_eof);
621+
622+ if (unlikely(fr_len > skb->len)) {
623+ if (stats->ErrorFrames < 5)
624+ FC_DBG("length error fr_len 0x%x skb->len 0x%x",
625+ fr_len, skb->len);
626+ stats->ErrorFrames++;
627+ kfree_skb(skb);
628+ continue;
629+ }
630+ stats->RxFrames++;
631+ stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
632+
633+ fp = (struct fc_frame *) skb;
634+ fc_frame_init(fp);
635+ cp = (struct fcoe_crc_eof *)(skb->data + fr_len);
636+ fr_eof(fp) = cp->fcoe_eof;
637+ fr_sof(fp) = sof;
638+ fr_dev(fp) = lp;
639+
640+ /*
641+ * Check the CRC here, unless it's solicited data for SCSI.
642+ * In that case, the SCSI layer can check it during the copy,
643+ * and it'll be more cache-efficient.
644+ */
645+ fh = fc_frame_header_get(fp);
646+ if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
647+ fh->fh_type == FC_TYPE_FCP) {
648+ fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
649+ fc_exch_recv(lp, lp->emp, fp);
650+ } else if (le32_to_cpu(cp->fcoe_crc32) ==
651+ ~crc32(~0, skb->data, fr_len)) {
652+ if (unlikely(fc->flogi_progress))
653+ fcoe_recv_flogi(fc, fp, mac);
654+ fc_exch_recv(lp, lp->emp, fp);
655+ } else {
656+ if (debug_fcoe || stats->InvalidCRCCount < 5) {
657+ printk(KERN_WARNING \
658+ "fcoe: dropping frame with CRC error");
659+ }
660+ stats->InvalidCRCCount++;
661+ stats->ErrorFrames++;
662+ fc_frame_free(fp);
663+ }
664+ }
665+ return 0;
666+}
667+
668+/*
669+ * Snoop potential response to FLOGI or even incoming FLOGI.
670+ */
671+static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa)
672+{
673+ struct fc_frame_header *fh;
674+ u8 op;
675+
676+ fh = fc_frame_header_get(fp);
677+ if (fh->fh_type != FC_TYPE_ELS)
678+ return;
679+ op = fc_frame_payload_op(fp);
680+ if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
681+ fc->flogi_oxid == ntohs(fh->fh_ox_id)) {
682+ /*
683+ * FLOGI accepted.
684+ * If the src mac addr is FC_OUI-based, then we mark the
685+ * address_mode flag to use FC_OUI-based Ethernet DA.
686+ * Otherwise we use the FCoE gateway addr
687+ */
688+ if (!compare_ether_addr(sa, (u8[6]) FC_FCOE_FLOGI_MAC)) {
689+ fc->address_mode = FCOE_FCOUI_ADDR_MODE;
690+ } else {
691+ memcpy(fc->dest_addr, sa, ETH_ALEN);
692+ fc->address_mode = FCOE_GW_ADDR_MODE;
693+ }
694+
695+ /*
696+ * Remove any previously-set unicast MAC filter.
697+ * Add secondary FCoE MAC address filter for our OUI.
698+ */
699+ rtnl_lock();
700+ if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
701+ dev_unicast_delete(fc->real_dev, fc->data_src_addr,
702+ ETH_ALEN);
703+ fc_fcoe_set_mac(fc->data_src_addr, fh->fh_d_id);
704+ dev_unicast_add(fc->real_dev, fc->data_src_addr, ETH_ALEN);
705+ rtnl_unlock();
706+
707+ fc->flogi_progress = 0;
708+ } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
709+ /*
710+ * Save source MAC for point-to-point responses.
711+ */
712+ memcpy(fc->dest_addr, sa, ETH_ALEN);
713+ fc->address_mode = FCOE_GW_ADDR_MODE;
714+ }
715+}
716+
717+void fcoe_watchdog(ulong vp)
718+{
719+ struct fc_lport *lp;
720+ struct fcoe_softc *fc;
721+ struct fcoe_info *fci = &fcoei;
722+ int paused = 0;
723+
724+ read_lock(&fci->fcoe_hostlist_lock);
725+ list_for_each_entry(fc, &fci->fcoe_hostlist, list) {
726+ lp = fc->lp;
727+ if (lp) {
728+ if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
729+ paused = 1;
730+ if (fcoe_check_wait_queue(lp) < FCOE_MAX_QUEUE_DEPTH) {
731+ if (paused)
732+ fc_unpause(lp);
733+ }
734+ }
735+ }
736+ read_unlock(&fci->fcoe_hostlist_lock);
737+
738+ fci->timer.expires = jiffies + (1 * HZ);
739+ add_timer(&fci->timer);
740+}
741+
742+/*
743+ * the wait_queue is used when the skb transmit fails. skb will go
744+ * in the wait_queue which will be emptied by the time function OR
745+ * by the next skb transmit.
746+ *
747+ */
748+
749+/*
750+ * Function name : fcoe_check_wait_queue()
751+ *
752+ * Return Values : 0 or error
753+ *
754+ * Description : empties the wait_queue
755+ * dequeue the head of the wait_queue queue and
756+ * calls fcoe_start_io() for each packet
757+ * if all skb have been transmitted, return 0
758+ * if a error occurs, then restore wait_queue and try again
759+ * later
760+ *
761+ */
762+
763+static int fcoe_check_wait_queue(struct fc_lport *lp)
764+{
765+ int rc, unpause = 0;
766+ int paused = 0;
767+ struct sk_buff *skb;
768+ struct fcoe_softc *fc;
769+
770+ fc = (struct fcoe_softc *)lp->drv_priv;
771+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
772+
773+ /*
774+ * is this interface paused?
775+ */
776+ if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
777+ paused = 1;
778+ if (fc->fcoe_pending_queue.qlen) {
779+ while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
780+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
781+ rc = fcoe_start_io(skb);
782+ if (rc) {
783+ fcoe_insert_wait_queue_head(lp, skb);
784+ return rc;
785+ }
786+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
787+ }
788+ if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH)
789+ unpause = 1;
790+ }
791+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
792+ if ((unpause) && (paused))
793+ fc_unpause(lp);
794+ return fc->fcoe_pending_queue.qlen;
795+}
796+
797+static void fcoe_insert_wait_queue_head(struct fc_lport *lp,
798+ struct sk_buff *skb)
799+{
800+ struct fcoe_softc *fc;
801+
802+ fc = (struct fcoe_softc *)lp->drv_priv;
803+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
804+ __skb_queue_head(&fc->fcoe_pending_queue, skb);
805+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
806+}
807+
808+static void fcoe_insert_wait_queue(struct fc_lport *lp,
809+ struct sk_buff *skb)
810+{
811+ struct fcoe_softc *fc;
812+
813+ fc = (struct fcoe_softc *)lp->drv_priv;
814+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
815+ __skb_queue_tail(&fc->fcoe_pending_queue, skb);
816+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
817+}
818diff --git a/drivers/scsi/fcoe/fcoe_if.c b/drivers/scsi/fcoe/fcoe_if.c
819new file mode 100644
820index 0000000..7f983e2
821--- /dev/null
822+++ b/drivers/scsi/fcoe/fcoe_if.c
823@@ -0,0 +1,497 @@
824+/*
825+ * Copyright(c) 2007 Intel Corporation. All rights reserved.
826+ *
827+ * This program is free software; you can redistribute it and/or modify it
828+ * under the terms and conditions of the GNU General Public License,
829+ * version 2, as published by the Free Software Foundation.
830+ *
831+ * This program is distributed in the hope it will be useful, but WITHOUT
832+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
833+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
834+ * more details.
835+ *
836+ * You should have received a copy of the GNU General Public License along with
837+ * this program; if not, write to the Free Software Foundation, Inc.,
838+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
839+ *
840+ * Maintained at www.Open-FCoE.org
841+ */
842+
843+/*
844+ * FCOE protocol file
845+ */
846+
847+#include <linux/module.h>
848+#include <linux/version.h>
849+#include <linux/kernel.h>
850+#include <linux/init.h>
851+#include <linux/spinlock.h>
852+#include <linux/netdevice.h>
853+#include <linux/etherdevice.h>
854+#include <linux/ethtool.h>
855+#include <linux/if_ether.h>
856+#include <linux/if_vlan.h>
857+#include <net/rtnetlink.h>
858+
859+#include <scsi/fc/fc_els.h>
860+#include <scsi/fc/fc_encaps.h>
861+#include <scsi/fc/fc_fs.h>
862+#include <scsi/scsi_transport.h>
863+#include <scsi/scsi_transport_fc.h>
864+
865+#include <scsi/libfc/libfc.h>
866+
867+#include <scsi/fc/fc_fcoe.h>
868+#include "fcoe_def.h"
869+
870+#define FCOE_VERSION "0.1"
871+
872+#define FCOE_MAX_LUN 255
873+#define FCOE_MAX_FCP_TARGET 256
874+
875+#define FCOE_MIN_XID 0x0004
876+#define FCOE_MAX_XID 0x07ef
877+
878+int debug_fcoe;
879+
880+struct fcoe_info fcoei = {
881+ .fcoe_hostlist = LIST_HEAD_INIT(fcoei.fcoe_hostlist),
882+};
883+
884+static struct fcoe_softc *fcoe_find_fc_lport(const char *name)
885+{
886+ struct fcoe_softc *fc;
887+ struct fc_lport *lp;
888+ struct fcoe_info *fci = &fcoei;
889+
890+ read_lock(&fci->fcoe_hostlist_lock);
891+ list_for_each_entry(fc, &fci->fcoe_hostlist, list) {
892+ lp = fc->lp;
893+ if (!strncmp(name, lp->ifname, IFNAMSIZ)) {
894+ read_unlock(&fci->fcoe_hostlist_lock);
895+ return fc;
896+ }
897+ }
898+ read_unlock(&fci->fcoe_hostlist_lock);
899+ return NULL;
900+}
901+
902+/*
903+ * Convert 48-bit IEEE MAC address to 64-bit FC WWN.
904+ */
905+static u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
906+ unsigned int scheme, unsigned int port)
907+{
908+ u64 wwn;
909+ u64 host_mac;
910+
911+ /* The MAC is in NO, so flip only the low 48 bits */
912+ host_mac = ((u64) mac[0] << 40) |
913+ ((u64) mac[1] << 32) |
914+ ((u64) mac[2] << 24) |
915+ ((u64) mac[3] << 16) |
916+ ((u64) mac[4] << 8) |
917+ (u64) mac[5];
918+
919+ WARN_ON(host_mac >= (1ULL << 48));
920+ wwn = host_mac | ((u64) scheme << 60);
921+ switch (scheme) {
922+ case 1:
923+ WARN_ON(port != 0);
924+ break;
925+ case 2:
926+ WARN_ON(port >= 0xfff);
927+ wwn |= (u64) port << 48;
928+ break;
929+ default:
930+ WARN_ON(1);
931+ break;
932+ }
933+
934+ return wwn;
935+}
936+
937+static struct scsi_host_template fcoe_driver_template = {
938+ .module = THIS_MODULE,
939+ .name = "FCoE Driver",
940+ .proc_name = FCOE_DRIVER_NAME,
941+ .queuecommand = fc_queuecommand,
942+ .eh_abort_handler = fc_eh_abort,
943+ .eh_device_reset_handler = fc_eh_device_reset,
944+ .eh_host_reset_handler = fc_eh_host_reset,
945+ .slave_alloc = fc_slave_alloc,
946+ .change_queue_depth = fc_change_queue_depth,
947+ .change_queue_type = fc_change_queue_type,
948+ .this_id = -1,
949+ .cmd_per_lun = 32,
950+ .can_queue = FC_MAX_OUTSTANDING_COMMANDS,
951+ .use_clustering = ENABLE_CLUSTERING,
952+ .sg_tablesize = 4,
953+ .max_sectors = 0xffff,
954+};
955+
956+int fcoe_destroy_interface(const char *ifname)
957+{
958+ int cpu, idx;
959+ struct fcoe_dev_stats *p;
960+ struct fcoe_percpu_s *pp;
961+ struct fcoe_softc *fc;
962+ struct fcoe_rcv_info *fr;
963+ struct fcoe_info *fci = &fcoei;
964+ struct sk_buff_head *list;
965+ struct sk_buff *skb, *next;
966+ struct sk_buff *head;
967+ struct fc_lport *lp;
968+ u8 flogi_maddr[ETH_ALEN];
969+
970+ fc = fcoe_find_fc_lport(ifname);
971+ if (!fc)
972+ return -ENODEV;
973+
974+ lp = fc->lp;
975+
976+ /* Remove the instance from fcoe's list */
977+ write_lock_bh(&fci->fcoe_hostlist_lock);
978+ list_del(&fc->list);
979+ write_unlock_bh(&fci->fcoe_hostlist_lock);
980+
981+ /* Cleanup the fc_lport */
982+ fc_lport_destroy(lp);
983+ fc_fcp_destroy(lp);
984+ if (lp->emp)
985+ fc_exch_mgr_free(lp->emp);
986+
987+ /* Detach from the scsi-ml */
988+ fc_remove_host(lp->host);
989+ scsi_remove_host(lp->host);
990+
991+ /* Don't listen for Ethernet packets anymore */
992+ dev_remove_pack(&fc->fcoe_packet_type);
993+
994+ /* Delete secondary MAC addresses */
995+ rtnl_lock();
996+ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
997+ dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
998+ if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
999+ dev_unicast_delete(fc->real_dev, fc->data_src_addr, ETH_ALEN);
1000+ rtnl_unlock();
1001+
1002+ /* Free the per-CPU revieve threads */
1003+ for (idx = 0; idx < NR_CPUS; idx++) {
1004+ if (fci->fcoe_percpu[idx]) {
1005+ pp = fci->fcoe_percpu[idx];
1006+ spin_lock_bh(&pp->fcoe_rx_list.lock);
1007+ list = &pp->fcoe_rx_list;
1008+ head = list->next;
1009+ for (skb = head; skb != (struct sk_buff *)list;
1010+ skb = next) {
1011+ next = skb->next;
1012+ fr = fcoe_dev_from_skb(skb);
1013+ if (fr->fr_dev == fc->lp) {
1014+ __skb_unlink(skb, list);
1015+ kfree_skb(skb);
1016+ }
1017+ }
1018+ spin_unlock_bh(&pp->fcoe_rx_list.lock);
1019+ }
1020+ }
1021+
1022+ /* Free existing skbs */
1023+ fcoe_clean_pending_queue(lp);
1024+
1025+ /* Free memory used by statistical counters */
1026+ for_each_online_cpu(cpu) {
1027+ p = lp->dev_stats[cpu];
1028+ if (p) {
1029+ lp->dev_stats[cpu] = NULL;
1030+ kfree(p);
1031+ }
1032+ }
1033+
1034+ /* Release the net_device and Scsi_Host */
1035+ dev_put(fc->real_dev);
1036+ scsi_host_put(lp->host);
1037+ return 0;
1038+}
1039+
1040+/*
1041+ * Return zero if link is OK for use by FCoE.
1042+ * Any permanently-disqualifying conditions have been previously checked.
1043+ * This also updates the speed setting, which may change with link for 100/1000.
1044+ *
1045+ * This function should probably be checking for PAUSE support at some point
1046+ * in the future. Currently Per-priority-pause is not determinable using
1047+ * ethtool, so we shouldn't be restrictive until that problem is resolved.
1048+ */
1049+int fcoe_link_ok(struct fc_lport *lp)
1050+{
1051+ struct fcoe_softc *fc = (struct fcoe_softc *)lp->drv_priv;
1052+ struct net_device *dev = fc->real_dev;
1053+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
1054+ int rc = 0;
1055+
1056+ if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) {
1057+ dev = fc->phys_dev;
1058+ if (dev->ethtool_ops->get_settings) {
1059+ dev->ethtool_ops->get_settings(dev, &ecmd);
1060+ lp->link_supported_speeds &=
1061+ ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
1062+ if (ecmd.supported & (SUPPORTED_1000baseT_Half |
1063+ SUPPORTED_1000baseT_Full))
1064+ lp->link_supported_speeds |= FC_PORTSPEED_1GBIT;
1065+ if (ecmd.supported & SUPPORTED_10000baseT_Full)
1066+ lp->link_supported_speeds |=
1067+ FC_PORTSPEED_10GBIT;
1068+ if (ecmd.speed == SPEED_1000)
1069+ lp->link_speed = FC_PORTSPEED_1GBIT;
1070+ if (ecmd.speed == SPEED_10000)
1071+ lp->link_speed = FC_PORTSPEED_10GBIT;
1072+ }
1073+ } else
1074+ rc = -1;
1075+
1076+ return rc;
1077+}
1078+
1079+static struct libfc_function_template fcoe_libfc_fcn_templ = {
1080+ .frame_send = fcoe_xmit,
1081+};
1082+
1083+static int lport_config(struct fc_lport *lp, struct Scsi_Host *shost)
1084+{
1085+ int i = 0;
1086+ struct fcoe_dev_stats *p;
1087+
1088+ lp->host = shost;
1089+ lp->drv_priv = (void *)(lp + 1);
1090+
1091+ lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
1092+ FCOE_MIN_XID, FCOE_MAX_XID);
1093+ if (!lp->emp)
1094+ return -ENOMEM;
1095+
1096+ lp->link_status = 0;
1097+ lp->max_retry_count = 3;
1098+ lp->e_d_tov = 2 * 1000; /* FC-FS default */
1099+ lp->r_a_tov = 2 * 2 * 1000;
1100+ lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
1101+ FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
1102+
1103+ /*
1104+ * allocate per cpu stats block
1105+ */
1106+ for_each_online_cpu(i) {
1107+ p = kzalloc(sizeof(struct fcoe_dev_stats), GFP_KERNEL);
1108+ if (p)
1109+ lp->dev_stats[i] = p;
1110+ }
1111+
1112+ /* Finish fc_lport configuration */
1113+ fc_lport_config(lp);
1114+
1115+ return 0;
1116+}
1117+
1118+static int net_config(struct fc_lport *lp)
1119+{
1120+ u32 mfs;
1121+ u64 wwnn, wwpn;
1122+ struct net_device *net_dev;
1123+ struct fcoe_softc *fc = (struct fcoe_softc *)lp->drv_priv;
1124+ u8 flogi_maddr[ETH_ALEN];
1125+
1126+ /* Require support for get_pauseparam ethtool op. */
1127+ net_dev = fc->real_dev;
1128+ if (!net_dev->ethtool_ops && (net_dev->priv_flags & IFF_802_1Q_VLAN))
1129+ net_dev = vlan_dev_real_dev(net_dev);
1130+ if (!net_dev->ethtool_ops || !net_dev->ethtool_ops->get_pauseparam)
1131+ return -EOPNOTSUPP;
1132+
1133+ fc->phys_dev = net_dev;
1134+
1135+ /* Do not support for bonding device */
1136+ if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
1137+ (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
1138+ (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
1139+ return -EOPNOTSUPP;
1140+ }
1141+
1142+ /*
1143+ * Determine max frame size based on underlying device and optional
1144+ * user-configured limit. If the MFS is too low, fcoe_link_ok()
1145+ * will return 0, so do this first.
1146+ */
1147+ mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
1148+ sizeof(struct fcoe_crc_eof));
1149+ fc_set_mfs(lp, mfs);
1150+
1151+ lp->link_status = ~FC_PAUSE & ~FC_LINK_UP;
1152+ if (!fcoe_link_ok(lp))
1153+ lp->link_status |= FC_LINK_UP;
1154+
1155+ if (fc->real_dev->features & NETIF_F_SG)
1156+ lp->capabilities = TRANS_C_SG;
1157+
1158+
1159+ skb_queue_head_init(&fc->fcoe_pending_queue);
1160+
1161+ memcpy(lp->ifname, fc->real_dev->name, IFNAMSIZ);
1162+
1163+ /* setup Source Mac Address */
1164+ memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr,
1165+ fc->real_dev->addr_len);
1166+
1167+ wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
1168+ fc_set_wwnn(lp, wwnn);
1169+ /* XXX - 3rd arg needs to be vlan id */
1170+ wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
1171+ fc_set_wwpn(lp, wwpn);
1172+
1173+ /*
1174+ * Add FCoE MAC address as second unicast MAC address
1175+ * or enter promiscuous mode if not capable of listening
1176+ * for multiple unicast MACs.
1177+ */
1178+ rtnl_lock();
1179+ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
1180+ dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
1181+ rtnl_unlock();
1182+
1183+ /*
1184+ * setup the receive function from ethernet driver
1185+ * on the ethertype for the given device
1186+ */
1187+ fc->fcoe_packet_type.func = fcoe_rcv;
1188+ fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
1189+ fc->fcoe_packet_type.dev = fc->real_dev;
1190+ dev_add_pack(&fc->fcoe_packet_type);
1191+
1192+ return 0;
1193+}
1194+
1195+static void shost_config(struct fc_lport *lp)
1196+{
1197+ lp->host->max_lun = FCOE_MAX_LUN;
1198+ lp->host->max_id = FCOE_MAX_FCP_TARGET;
1199+ lp->host->max_channel = 0;
1200+ lp->host->transportt = fcoe_transport_template;
1201+}
1202+
1203+static int libfc_config(struct fc_lport *lp)
1204+{
1205+ /* Set the function pointers set by the LLDD */
1206+ memcpy(&lp->tt, &fcoe_libfc_fcn_templ,
1207+ sizeof(struct libfc_function_template));
1208+
1209+ if (fc_fcp_init(lp))
1210+ return -ENOMEM;
1211+ fc_exch_init(lp);
1212+ fc_lport_init(lp);
1213+ fc_rport_init(lp);
1214+ fc_ns_init(lp);
1215+ fc_attr_init(lp);
1216+
1217+ return 0;
1218+}
1219+
1220+/*
1221+ * This function creates the fcoe interface
1222+ * create struct fcdev which is a shared structure between opefc
1223+ * and transport level protocol.
1224+ */
1225+int fcoe_create_interface(const char *ifname)
1226+{
1227+ struct fc_lport *lp = NULL;
1228+ struct fcoe_softc *fc;
1229+ struct net_device *net_dev;
1230+ struct Scsi_Host *shost;
1231+ struct fcoe_info *fci = &fcoei;
1232+ int rc = 0;
1233+
1234+ net_dev = dev_get_by_name(&init_net, ifname);
1235+ if (net_dev == NULL) {
1236+ FC_DBG("could not get network device for %s",
1237+ ifname);
1238+ return -ENODEV;
1239+ }
1240+
1241+ if (fcoe_find_fc_lport(net_dev->name) != NULL) {
1242+ rc = -EEXIST;
1243+ goto out_put_dev;
1244+ }
1245+
1246+ shost = scsi_host_alloc(&fcoe_driver_template,
1247+ sizeof(struct fc_lport) +
1248+ sizeof(struct fcoe_softc));
1249+
1250+ if (!shost) {
1251+ FC_DBG("Could not allocate host structure\n");
1252+ rc = -ENOMEM;
1253+ goto out_put_dev;
1254+ }
1255+
1256+ lp = shost_priv(shost);
1257+ rc = lport_config(lp, shost);
1258+ if (rc)
1259+ goto out_host_put;
1260+
1261+ /* Configure the fcoe_softc */
1262+ fc = (struct fcoe_softc *)lp->drv_priv;
1263+ fc->lp = lp;
1264+ fc->real_dev = net_dev;
1265+ shost_config(lp);
1266+
1267+
1268+ /* Add the new host to the SCSI-ml */
1269+ rc = scsi_add_host(lp->host, NULL);
1270+ if (rc) {
1271+ FC_DBG("error on scsi_add_host\n");
1272+ goto out_lp_destroy;
1273+ }
1274+
1275+ sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
1276+ FCOE_DRIVER_NAME, FCOE_VERSION,
1277+ ifname);
1278+
1279+ /* Configure netdev and networking properties of the lp */
1280+ rc = net_config(lp);
1281+ if (rc)
1282+ goto out_lp_destroy;
1283+
1284+ /* Initialize the library */
1285+ rc = libfc_config(lp);
1286+ if (rc)
1287+ goto out_lp_destroy;
1288+
1289+ write_lock_bh(&fci->fcoe_hostlist_lock);
1290+ list_add_tail(&fc->list, &fci->fcoe_hostlist);
1291+ write_unlock_bh(&fci->fcoe_hostlist_lock);
1292+
1293+ lp->boot_time = jiffies;
1294+
1295+ fc_fabric_login(lp);
1296+
1297+ return rc;
1298+
1299+out_lp_destroy:
1300+ fc_exch_mgr_free(lp->emp); /* Free the EM */
1301+out_host_put:
1302+ scsi_host_put(lp->host);
1303+out_put_dev:
1304+ dev_put(net_dev);
1305+ return rc;
1306+}
1307+
1308+void fcoe_clean_pending_queue(struct fc_lport *lp)
1309+{
1310+ struct fcoe_softc *fc = lp->drv_priv;
1311+ struct sk_buff *skb;
1312+
1313+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
1314+ while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
1315+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
1316+ kfree_skb(skb);
1317+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
1318+ }
1319+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
1320+}
1321diff --git a/drivers/scsi/fcoe/fcoeinit.c b/drivers/scsi/fcoe/fcoeinit.c
1322new file mode 100644
1323index 0000000..e069835
1324--- /dev/null
1325+++ b/drivers/scsi/fcoe/fcoeinit.c
1326@@ -0,0 +1,440 @@
1327+/*
1328+ * Copyright(c) 2007 Intel Corporation. All rights reserved.
1329+ *
1330+ * This program is free software; you can redistribute it and/or modify it
1331+ * under the terms and conditions of the GNU General Public License,
1332+ * version 2, as published by the Free Software Foundation.
1333+ *
1334+ * This program is distributed in the hope it will be useful, but WITHOUT
1335+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1336+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1337+ * more details.
1338+ *
1339+ * You should have received a copy of the GNU General Public License along with
1340+ * this program; if not, write to the Free Software Foundation, Inc.,
1341+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
1342+ *
1343+ * Maintained at www.Open-FCoE.org
1344+ */
1345+
1346+#include <linux/module.h>
1347+#include <linux/version.h>
1348+#include <linux/kernel.h>
1349+#include <linux/kthread.h>
1350+#include <linux/spinlock.h>
1351+#include <linux/cpu.h>
1352+#include <linux/netdevice.h>
1353+#include <linux/etherdevice.h>
1354+#include <linux/ethtool.h>
1355+#include <linux/if_ether.h>
1356+#include <linux/fs.h>
1357+#include <linux/sysfs.h>
1358+#include <linux/ctype.h>
1359+
1360+#include <scsi/libfc/libfc.h>
1361+
1362+#include "fcoe_def.h"
1363+
1364+MODULE_AUTHOR("Open-FCoE.org");
1365+MODULE_DESCRIPTION("FCoE");
1366+MODULE_LICENSE("GPL");
1367+
1368+/*
1369+ * Static functions and variables definations
1370+ */
1371+#ifdef CONFIG_HOTPLUG_CPU
1372+static int fcoe_cpu_callback(struct notifier_block *, ulong, void *);
1373+#endif /* CONFIG_HOTPLUG_CPU */
1374+static int fcoe_device_notification(struct notifier_block *, ulong, void *);
1375+static void fcoe_dev_setup(void);
1376+static void fcoe_dev_cleanup(void);
1377+
1378+struct scsi_transport_template *fcoe_transport_template;
1379+
1380+static int fcoe_reset(struct Scsi_Host *shost)
1381+{
1382+ struct fc_lport *lp = shost_priv(shost);
1383+ fc_lport_enter_reset(lp);
1384+ return 0;
1385+}
1386+
1387+struct fc_function_template fcoe_transport_function = {
1388+ .show_host_node_name = 1,
1389+ .show_host_port_name = 1,
1390+ .show_host_supported_classes = 1,
1391+ .show_host_supported_fc4s = 1,
1392+ .show_host_active_fc4s = 1,
1393+ .show_host_maxframe_size = 1,
1394+
1395+ .get_host_port_id = fc_get_host_port_id,
1396+ .show_host_port_id = 1,
1397+ .get_host_speed = fc_get_host_speed,
1398+ .show_host_speed = 1,
1399+ .get_host_port_type = fc_get_host_port_type,
1400+ .show_host_port_type = 1,
1401+ .get_host_port_state = fc_get_host_port_state,
1402+ .show_host_port_state = 1,
1403+ .show_host_symbolic_name = 1,
1404+
1405+ .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
1406+ .show_rport_maxframe_size = 1,
1407+ .show_rport_supported_classes = 1,
1408+
1409+ .get_host_fabric_name = fc_get_host_fabric_name,
1410+ .show_host_fabric_name = 1,
1411+ .show_starget_node_name = 1,
1412+ .show_starget_port_name = 1,
1413+ .show_starget_port_id = 1,
1414+ .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
1415+ .show_rport_dev_loss_tmo = 1,
1416+ .get_fc_host_stats = fc_get_host_stats,
1417+ .issue_fc_host_lip = fcoe_reset,
1418+};
1419+
1420+struct fcoe_percpu_s *fcoe_percpu[NR_CPUS];
1421+
1422+#ifdef CONFIG_HOTPLUG_CPU
1423+static struct notifier_block fcoe_cpu_notifier = {
1424+ .notifier_call = fcoe_cpu_callback,
1425+};
1426+#endif /* CONFIG_HOTPLUG_CPU */
1427+
1428+/*
1429+ * notification function from net device
1430+ */
1431+static struct notifier_block fcoe_notifier = {
1432+ .notifier_call = fcoe_device_notification,
1433+};
1434+
1435+#ifdef CONFIG_HOTPLUG_CPU
1436+/*
1437+ * create percpu stats block
1438+ * called by cpu add/remove notifier
1439+ */
1440+static void fcoe_create_percpu_data(int cpu)
1441+{
1442+ struct fc_lport *lp;
1443+ struct fcoe_softc *fc;
1444+ struct fcoe_dev_stats *p;
1445+ struct fcoe_info *fci = &fcoei;
1446+
1447+ write_lock_bh(&fci->fcoe_hostlist_lock);
1448+ list_for_each_entry(fc, &fci->fcoe_hostlist, list) {
1449+ lp = fc->lp;
1450+ if (lp->dev_stats[cpu] == NULL) {
1451+ p = kzalloc(sizeof(struct fcoe_dev_stats), GFP_KERNEL);
1452+ if (p)
1453+ lp->dev_stats[cpu] = p;
1454+ }
1455+ }
1456+ write_unlock_bh(&fci->fcoe_hostlist_lock);
1457+}
1458+
1459+/*
1460+ * destroy percpu stats block
1461+ * called by cpu add/remove notifier
1462+ */
1463+static void fcoe_destroy_percpu_data(int cpu)
1464+{
1465+ struct fcoe_dev_stats *p;
1466+ struct fc_lport *lp;
1467+ struct fcoe_softc *fc;
1468+ struct fcoe_info *fci = &fcoei;
1469+
1470+ write_lock_bh(&fci->fcoe_hostlist_lock);
1471+ list_for_each_entry(fc, &fci->fcoe_hostlist, list) {
1472+ lp = fc->lp;
1473+ p = lp->dev_stats[cpu];
1474+ if (p != NULL) {
1475+ lp->dev_stats[cpu] = NULL;
1476+ kfree(p);
1477+ }
1478+ }
1479+ write_unlock_bh(&fci->fcoe_hostlist_lock);
1480+}
1481+
1482+/*
1483+ * Get notified when a cpu comes on/off. Be hotplug friendly.
1484+ */
1485+static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action,
1486+ void *hcpu)
1487+{
1488+ unsigned int cpu = (unsigned long)hcpu;
1489+
1490+ switch (action) {
1491+ case CPU_ONLINE:
1492+ fcoe_create_percpu_data(cpu);
1493+ break;
1494+ case CPU_DEAD:
1495+ fcoe_destroy_percpu_data(cpu);
1496+ break;
1497+ default:
1498+ break;
1499+ }
1500+ return NOTIFY_OK;
1501+}
1502+#endif /* CONFIG_HOTPLUG_CPU */
1503+
1504+/*
1505+ * function to setup link change notification interface
1506+ */
1507+static void fcoe_dev_setup(void)
1508+{
1509+ /*
1510+ * here setup a interface specific wd time to
1511+ * monitor the link state
1512+ */
1513+ register_netdevice_notifier(&fcoe_notifier);
1514+}
1515+
1516+/*
1517+ * function to cleanup link change notification interface
1518+ */
1519+static void fcoe_dev_cleanup(void)
1520+{
1521+ unregister_netdevice_notifier(&fcoe_notifier);
1522+}
1523+
1524+/*
1525+ * This function is called by the ethernet driver
1526+ * this is called in case of link change event
1527+ */
1528+static int fcoe_device_notification(struct notifier_block *notifier,
1529+ ulong event, void *ptr)
1530+{
1531+ struct fc_lport *lp = NULL;
1532+ struct net_device *real_dev = ptr;
1533+ struct fcoe_softc *fc;
1534+ struct fcoe_dev_stats *stats;
1535+ struct fcoe_info *fci = &fcoei;
1536+ u16 new_status;
1537+ u32 mfs;
1538+ int rc = NOTIFY_OK;
1539+
1540+ read_lock(&fci->fcoe_hostlist_lock);
1541+ list_for_each_entry(fc, &fci->fcoe_hostlist, list) {
1542+ if (fc->real_dev == real_dev) {
1543+ lp = fc->lp;
1544+ break;
1545+ }
1546+ }
1547+ read_unlock(&fci->fcoe_hostlist_lock);
1548+ if (lp == NULL) {
1549+ rc = NOTIFY_DONE;
1550+ goto out;
1551+ }
1552+
1553+ new_status = lp->link_status;
1554+ switch (event) {
1555+ case NETDEV_DOWN:
1556+ case NETDEV_GOING_DOWN:
1557+ new_status &= ~FC_LINK_UP;
1558+ break;
1559+ case NETDEV_UP:
1560+ case NETDEV_CHANGE:
1561+ new_status &= ~FC_LINK_UP;
1562+ if (!fcoe_link_ok(lp))
1563+ new_status |= FC_LINK_UP;
1564+ break;
1565+ case NETDEV_CHANGEMTU:
1566+ mfs = fc->real_dev->mtu -
1567+ (sizeof(struct fcoe_hdr) +
1568+ sizeof(struct fcoe_crc_eof));
1569+ if (fc->user_mfs && fc->user_mfs < mfs)
1570+ mfs = fc->user_mfs;
1571+ if (mfs >= FC_MIN_MAX_FRAME)
1572+ fc_set_mfs(lp, mfs);
1573+ new_status &= ~FC_LINK_UP;
1574+ if (!fcoe_link_ok(lp))
1575+ new_status |= FC_LINK_UP;
1576+ break;
1577+ case NETDEV_REGISTER:
1578+ break;
1579+ default:
1580+ FC_DBG("unknown event %ld call", event);
1581+ }
1582+ if (lp->link_status != new_status) {
1583+ if ((new_status & FC_LINK_UP) == FC_LINK_UP)
1584+ fc_linkup(lp);
1585+ else {
1586+ stats = lp->dev_stats[smp_processor_id()];
1587+ stats->LinkFailureCount++;
1588+ fc_linkdown(lp);
1589+ fcoe_clean_pending_queue(lp);
1590+ }
1591+ }
1592+out:
1593+ return rc;
1594+}
1595+
1596+static void trimstr(char *str, int len)
1597+{
1598+ char *cp = str + len;
1599+ while (--cp >= str && *cp == '\n')
1600+ *cp = '\0';
1601+}
1602+
1603+static ssize_t fcoe_destroy(struct kobject *kobj, struct kobj_attribute *attr,
1604+ const char *buffer, size_t size)
1605+{
1606+ char ifname[40];
1607+ strcpy(ifname, buffer);
1608+ trimstr(ifname, strlen(ifname));
1609+ fcoe_destroy_interface(ifname);
1610+ return size;
1611+}
1612+
1613+static ssize_t fcoe_create(struct kobject *kobj, struct kobj_attribute *attr,
1614+ const char *buffer, size_t size)
1615+{
1616+ char ifname[40];
1617+ strcpy(ifname, buffer);
1618+ trimstr(ifname, strlen(ifname));
1619+ fcoe_create_interface(ifname);
1620+ return size;
1621+}
1622+
1623+static const struct kobj_attribute fcoe_destroyattr = \
1624+ __ATTR(destroy, S_IWUSR, NULL, fcoe_destroy);
1625+static const struct kobj_attribute fcoe_createattr = \
1626+ __ATTR(create, S_IWUSR, NULL, fcoe_create);
1627+
1628+/*
1629+ * Initialization routine
1630+ * 1. Will create fc transport software structure
1631+ * 2. initialize the link list of port information structure
1632+ */
1633+static int __init fcoeinit(void)
1634+{
1635+ int rc = 0;
1636+ int cpu;
1637+ struct fcoe_percpu_s *p;
1638+ struct fcoe_info *fci = &fcoei;
1639+
1640+ rc = sysfs_create_file(&THIS_MODULE->mkobj.kobj,
1641+ &fcoe_destroyattr.attr);
1642+ if (!rc)
1643+ rc = sysfs_create_file(&THIS_MODULE->mkobj.kobj,
1644+ &fcoe_createattr.attr);
1645+
1646+ if (rc)
1647+ return rc;
1648+
1649+ rwlock_init(&fci->fcoe_hostlist_lock);
1650+
1651+#ifdef CONFIG_HOTPLUG_CPU
1652+ register_cpu_notifier(&fcoe_cpu_notifier);
1653+#endif /* CONFIG_HOTPLUG_CPU */
1654+
1655+ /*
1656+ * initialize per CPU interrupt thread
1657+ */
1658+ for_each_online_cpu(cpu) {
1659+ p = kzalloc(sizeof(struct fcoe_percpu_s), GFP_KERNEL);
1660+ if (p) {
1661+ p->thread = kthread_create(fcoe_percpu_receive_thread,
1662+ (void *)p,
1663+ "fcoethread/%d", cpu);
1664+
1665+ /*
1666+ * if there is no error then bind the thread to the cpu
1667+ * initialize the semaphore and skb queue head
1668+ */
1669+ if (likely(!IS_ERR(p->thread))) {
1670+ p->cpu = cpu;
1671+ fci->fcoe_percpu[cpu] = p;
1672+ skb_queue_head_init(&p->fcoe_rx_list);
1673+ kthread_bind(p->thread, cpu);
1674+ wake_up_process(p->thread);
1675+ } else {
1676+ fci->fcoe_percpu[cpu] = NULL;
1677+ kfree(p);
1678+
1679+ }
1680+ }
1681+ }
1682+ if (rc < 0) {
1683+ FC_DBG("failed to initialize proc intrerface\n");
1684+ rc = -ENODEV;
1685+ goto out_chrdev;
1686+ }
1687+
1688+ /*
1689+ * setup link change notification
1690+ */
1691+ fcoe_dev_setup();
1692+
1693+ init_timer(&fci->timer);
1694+ fci->timer.data = (ulong) fci;
1695+ fci->timer.function = fcoe_watchdog;
1696+ fci->timer.expires = (jiffies + (10 * HZ));
1697+ add_timer(&fci->timer);
1698+
1699+ fcoe_transport_template =
1700+ fc_attach_transport(&fcoe_transport_function);
1701+
1702+ if (fcoe_transport_template == NULL) {
1703+ FC_DBG("fail to attach fc transport");
1704+ return -1;
1705+ }
1706+
1707+ return 0;
1708+
1709+out_chrdev:
1710+#ifdef CONFIG_HOTPLUG_CPU
1711+ unregister_cpu_notifier(&fcoe_cpu_notifier);
1712+#endif /* CONFIG_HOTPLUG_CPU */
1713+ return rc;
1714+}
1715+
1716+static void __exit fcoe_exit(void)
1717+{
1718+ u32 idx;
1719+ struct fcoe_softc *fc, *tmp;
1720+ struct fc_lport *lp;
1721+ struct fcoe_info *fci = &fcoei;
1722+ struct fcoe_percpu_s *p;
1723+ struct sk_buff *skb;
1724+
1725+ /*
1726+ * Stop all call back interfaces
1727+ */
1728+#ifdef CONFIG_HOTPLUG_CPU
1729+ unregister_cpu_notifier(&fcoe_cpu_notifier);
1730+#endif /* CONFIG_HOTPLUG_CPU */
1731+ fcoe_dev_cleanup();
1732+
1733+ /*
1734+ * stop timer
1735+ */
1736+ del_timer_sync(&fci->timer);
1737+
1738+ /*
1739+ * assuming that at this time there will be no
1740+ * ioctl in prograss, therefore we do not need to lock the
1741+ * list.
1742+ */
1743+ list_for_each_entry_safe(fc, tmp, &fci->fcoe_hostlist, list) {
1744+ lp = fc->lp;
1745+ fcoe_destroy_interface(lp->ifname);
1746+ }
1747+
1748+ for (idx = 0; idx < NR_CPUS; idx++) {
1749+ if (fci->fcoe_percpu[idx]) {
1750+ kthread_stop(fci->fcoe_percpu[idx]->thread);
1751+ p = fci->fcoe_percpu[idx];
1752+ spin_lock_bh(&p->fcoe_rx_list.lock);
1753+ while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
1754+ kfree_skb(skb);
1755+ spin_unlock_bh(&p->fcoe_rx_list.lock);
1756+ if (fci->fcoe_percpu[idx]->crc_eof_page)
1757+ put_page(fci->fcoe_percpu[idx]->crc_eof_page);
1758+ kfree(fci->fcoe_percpu[idx]);
1759+ }
1760+ }
1761+
1762+ fc_release_transport(fcoe_transport_template);
1763+}
1764+
1765+module_init(fcoeinit);
1766+module_exit(fcoe_exit);
1767--
17681.5.2.4
1769