]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/open-fcoe-driver
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / open-fcoe-driver
1 From: Hannes Reinecke <hare@suse.de>
2 Date: Wed, 17 Sep 2008 16:25:23 +0200
3 Subject: fcoe: Fibre Channel over Ethernet driver
4 References: FATE#303913
5
6 Encapsulation protocol for running Fibre Channel over Ethernet interfaces.
7 Creates virtual Fibre Channel host adapters using libfc.
8
9 Signed-off-by: Robert Love <robert.w.love@intel.com>
10 Signed-off-by: Chris Leech <christopher.leech@intel.com>
11 Signed-off-by: Vasu Dev <vasu.dev@intel.com>
12 Signed-off-by: Yi Zou <yi.zou@intel.com>
13 Signed-off-by: Steve Ma <steve.ma@intel.com>
14 Signed-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
30 diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
31 index 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
47 diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
48 index 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
59 diff --git a/drivers/scsi/fcoe/Makefile b/drivers/scsi/fcoe/Makefile
60 new file mode 100644
61 index 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
73 diff --git a/drivers/scsi/fcoe/fcoe_def.h b/drivers/scsi/fcoe/fcoe_def.h
74 new file mode 100644
75 index 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_ */
179 diff --git a/drivers/scsi/fcoe/fcoe_dev.c b/drivers/scsi/fcoe/fcoe_dev.c
180 new file mode 100644
181 index 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 +}
818 diff --git a/drivers/scsi/fcoe/fcoe_if.c b/drivers/scsi/fcoe/fcoe_if.c
819 new file mode 100644
820 index 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 +}
1321 diff --git a/drivers/scsi/fcoe/fcoeinit.c b/drivers/scsi/fcoe/fcoeinit.c
1322 new file mode 100644
1323 index 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 --
1768 1.5.2.4
1769