blob: 334db95f36afd6e5f5f0c97060851b425e46346c [file] [log] [blame]
Robert Love85b4aa42008-12-09 15:10:24 -08001/*
2 * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * Maintained at www.Open-FCoE.org
18 */
19
20#include <linux/module.h>
21#include <linux/version.h>
22#include <linux/kernel.h>
23#include <linux/spinlock.h>
24#include <linux/skbuff.h>
25#include <linux/netdevice.h>
26#include <linux/etherdevice.h>
27#include <linux/ethtool.h>
28#include <linux/if_ether.h>
29#include <linux/if_vlan.h>
30#include <linux/kthread.h>
31#include <linux/crc32.h>
32#include <linux/cpu.h>
33#include <linux/fs.h>
34#include <linux/sysfs.h>
35#include <linux/ctype.h>
36#include <scsi/scsi_tcq.h>
37#include <scsi/scsicam.h>
38#include <scsi/scsi_transport.h>
39#include <scsi/scsi_transport_fc.h>
40#include <net/rtnetlink.h>
41
42#include <scsi/fc/fc_encaps.h>
43
44#include <scsi/libfc.h>
45#include <scsi/fc_frame.h>
46#include <scsi/libfcoe.h>
Robert Love85b4aa42008-12-09 15:10:24 -080047
48static int debug_fcoe;
49
50#define FCOE_MAX_QUEUE_DEPTH 256
Vasu Devc826a312009-02-27 10:56:27 -080051#define FCOE_LOW_QUEUE_DEPTH 32
Robert Love85b4aa42008-12-09 15:10:24 -080052
53/* destination address mode */
54#define FCOE_GW_ADDR_MODE 0x00
55#define FCOE_FCOUI_ADDR_MODE 0x01
56
57#define FCOE_WORD_TO_BYTE 4
58
59MODULE_AUTHOR("Open-FCoE.org");
60MODULE_DESCRIPTION("FCoE");
61MODULE_LICENSE("GPL");
62
63/* fcoe host list */
64LIST_HEAD(fcoe_hostlist);
65DEFINE_RWLOCK(fcoe_hostlist_lock);
66DEFINE_TIMER(fcoe_timer, NULL, 0, 0);
Robert Love5e5e92d2009-03-17 11:41:35 -070067DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
Robert Love85b4aa42008-12-09 15:10:24 -080068
69
70/* Function Prototyes */
71static int fcoe_check_wait_queue(struct fc_lport *);
Robert Love85b4aa42008-12-09 15:10:24 -080072static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *);
Robert Love85b4aa42008-12-09 15:10:24 -080073static int fcoe_device_notification(struct notifier_block *, ulong, void *);
74static void fcoe_dev_setup(void);
75static void fcoe_dev_cleanup(void);
76
77/* notification function from net device */
78static struct notifier_block fcoe_notifier = {
79 .notifier_call = fcoe_device_notification,
80};
81
Robert Love85b4aa42008-12-09 15:10:24 -080082/**
Robert Love8976f422009-03-17 11:41:46 -070083 * fcoe_percpu_thread_create() - Create a receive thread for an online cpu
84 * @cpu: cpu index for the online cpu
85 */
86static void fcoe_percpu_thread_create(unsigned int cpu)
87{
88 struct fcoe_percpu_s *p;
89 struct task_struct *thread;
90
91 p = &per_cpu(fcoe_percpu, cpu);
92
93 thread = kthread_create(fcoe_percpu_receive_thread,
94 (void *)p, "fcoethread/%d", cpu);
95
96 if (likely(!IS_ERR(p->thread))) {
97 kthread_bind(thread, cpu);
98 wake_up_process(thread);
99
100 spin_lock_bh(&p->fcoe_rx_list.lock);
101 p->thread = thread;
102 spin_unlock_bh(&p->fcoe_rx_list.lock);
103 }
104}
105
106/**
107 * fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu
108 * @cpu: cpu index the rx thread is to be removed
109 *
110 * Destroys a per-CPU Rx thread. Any pending skbs are moved to the
111 * current CPU's Rx thread. If the thread being destroyed is bound to
112 * the CPU processing this context the skbs will be freed.
113 */
114static void fcoe_percpu_thread_destroy(unsigned int cpu)
115{
116 struct fcoe_percpu_s *p;
117 struct task_struct *thread;
118 struct page *crc_eof;
119 struct sk_buff *skb;
120#ifdef CONFIG_SMP
121 struct fcoe_percpu_s *p0;
122 unsigned targ_cpu = smp_processor_id();
123#endif /* CONFIG_SMP */
124
125 printk(KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n", cpu);
126
127 /* Prevent any new skbs from being queued for this CPU. */
128 p = &per_cpu(fcoe_percpu, cpu);
129 spin_lock_bh(&p->fcoe_rx_list.lock);
130 thread = p->thread;
131 p->thread = NULL;
132 crc_eof = p->crc_eof_page;
133 p->crc_eof_page = NULL;
134 p->crc_eof_offset = 0;
135 spin_unlock_bh(&p->fcoe_rx_list.lock);
136
137#ifdef CONFIG_SMP
138 /*
139 * Don't bother moving the skb's if this context is running
140 * on the same CPU that is having its thread destroyed. This
141 * can easily happen when the module is removed.
142 */
143 if (cpu != targ_cpu) {
144 p0 = &per_cpu(fcoe_percpu, targ_cpu);
145 spin_lock_bh(&p0->fcoe_rx_list.lock);
146 if (p0->thread) {
147 FC_DBG("Moving frames from CPU %d to CPU %d\n",
148 cpu, targ_cpu);
149
150 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
151 __skb_queue_tail(&p0->fcoe_rx_list, skb);
152 spin_unlock_bh(&p0->fcoe_rx_list.lock);
153 } else {
154 /*
155 * The targeted CPU is not initialized and cannot accept
156 * new skbs. Unlock the targeted CPU and drop the skbs
157 * on the CPU that is going offline.
158 */
159 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
160 kfree_skb(skb);
161 spin_unlock_bh(&p0->fcoe_rx_list.lock);
162 }
163 } else {
164 /*
165 * This scenario occurs when the module is being removed
166 * and all threads are being destroyed. skbs will continue
167 * to be shifted from the CPU thread that is being removed
168 * to the CPU thread associated with the CPU that is processing
169 * the module removal. Once there is only one CPU Rx thread it
170 * will reach this case and we will drop all skbs and later
171 * stop the thread.
172 */
173 spin_lock_bh(&p->fcoe_rx_list.lock);
174 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
175 kfree_skb(skb);
176 spin_unlock_bh(&p->fcoe_rx_list.lock);
177 }
178#else
179 /*
180 * This a non-SMP scenario where the singluar Rx thread is
181 * being removed. Free all skbs and stop the thread.
182 */
183 spin_lock_bh(&p->fcoe_rx_list.lock);
184 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
185 kfree_skb(skb);
186 spin_unlock_bh(&p->fcoe_rx_list.lock);
187#endif
188
189 if (thread)
190 kthread_stop(thread);
191
192 if (crc_eof)
193 put_page(crc_eof);
194}
195
196/**
197 * fcoe_cpu_callback() - fcoe cpu hotplug event callback
198 * @nfb: callback data block
199 * @action: event triggering the callback
200 * @hcpu: index for the cpu of this event
201 *
202 * This creates or destroys per cpu data for fcoe
203 *
204 * Returns NOTIFY_OK always.
205 */
206static int fcoe_cpu_callback(struct notifier_block *nfb,
207 unsigned long action, void *hcpu)
208{
209 unsigned cpu = (unsigned long)hcpu;
210
211 switch (action) {
212 case CPU_ONLINE:
213 case CPU_ONLINE_FROZEN:
214 FC_DBG("CPU %x online: Create Rx thread\n", cpu);
215 fcoe_percpu_thread_create(cpu);
216 break;
217 case CPU_DEAD:
218 case CPU_DEAD_FROZEN:
219 FC_DBG("CPU %x offline: Remove Rx thread\n", cpu);
220 fcoe_percpu_thread_destroy(cpu);
221 break;
222 default:
223 break;
224 }
225 return NOTIFY_OK;
226}
227
228static struct notifier_block fcoe_cpu_notifier = {
229 .notifier_call = fcoe_cpu_callback,
230};
231
232/**
Robert Love34f42a02009-02-27 10:55:45 -0800233 * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ
Robert Love85b4aa42008-12-09 15:10:24 -0800234 * @skb: the receive skb
235 * @dev: associated net device
236 * @ptype: context
237 * @odldev: last device
238 *
239 * this function will receive the packet and build fc frame and pass it up
240 *
241 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800242 */
Robert Love85b4aa42008-12-09 15:10:24 -0800243int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
244 struct packet_type *ptype, struct net_device *olddev)
245{
246 struct fc_lport *lp;
247 struct fcoe_rcv_info *fr;
248 struct fcoe_softc *fc;
Robert Love85b4aa42008-12-09 15:10:24 -0800249 struct fc_frame_header *fh;
Robert Love85b4aa42008-12-09 15:10:24 -0800250 struct fcoe_percpu_s *fps;
Robert Love38eccab2009-03-17 11:41:30 -0700251 unsigned short oxid;
Robert Love8976f422009-03-17 11:41:46 -0700252 unsigned int cpu = 0;
Robert Love85b4aa42008-12-09 15:10:24 -0800253
254 fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
255 lp = fc->lp;
256 if (unlikely(lp == NULL)) {
257 FC_DBG("cannot find hba structure");
258 goto err2;
259 }
260
261 if (unlikely(debug_fcoe)) {
262 FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p "
263 "end:%p sum:%d dev:%s", skb->len, skb->data_len,
264 skb->head, skb->data, skb_tail_pointer(skb),
265 skb_end_pointer(skb), skb->csum,
266 skb->dev ? skb->dev->name : "<NULL>");
267
268 }
269
270 /* check for FCOE packet type */
271 if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
272 FC_DBG("wrong FC type frame");
273 goto err;
274 }
275
276 /*
277 * Check for minimum frame length, and make sure required FCoE
278 * and FC headers are pulled into the linear data area.
279 */
280 if (unlikely((skb->len < FCOE_MIN_FRAME) ||
281 !pskb_may_pull(skb, FCOE_HEADER_LEN)))
282 goto err;
283
284 skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
285 fh = (struct fc_frame_header *) skb_transport_header(skb);
286
287 oxid = ntohs(fh->fh_ox_id);
288
289 fr = fcoe_dev_from_skb(skb);
290 fr->fr_dev = lp;
291 fr->ptype = ptype;
Robert Love5e5e92d2009-03-17 11:41:35 -0700292
Robert Love85b4aa42008-12-09 15:10:24 -0800293#ifdef CONFIG_SMP
294 /*
295 * The incoming frame exchange id(oxid) is ANDed with num of online
Robert Love8976f422009-03-17 11:41:46 -0700296 * cpu bits to get cpu and then this cpu is used for selecting
297 * a per cpu kernel thread from fcoe_percpu.
Robert Love85b4aa42008-12-09 15:10:24 -0800298 */
Robert Love8976f422009-03-17 11:41:46 -0700299 cpu = oxid & (num_online_cpus() - 1);
Robert Love85b4aa42008-12-09 15:10:24 -0800300#endif
Robert Love5e5e92d2009-03-17 11:41:35 -0700301
Robert Love8976f422009-03-17 11:41:46 -0700302 fps = &per_cpu(fcoe_percpu, cpu);
Robert Love85b4aa42008-12-09 15:10:24 -0800303 spin_lock_bh(&fps->fcoe_rx_list.lock);
Robert Love8976f422009-03-17 11:41:46 -0700304 if (unlikely(!fps->thread)) {
305 /*
306 * The targeted CPU is not ready, let's target
307 * the first CPU now. For non-SMP systems this
308 * will check the same CPU twice.
309 */
310 FC_DBG("CPU is online, but no receive thread ready "
311 "for incoming skb- using first online CPU.\n");
312
313 spin_unlock_bh(&fps->fcoe_rx_list.lock);
314 cpu = first_cpu(cpu_online_map);
315 fps = &per_cpu(fcoe_percpu, cpu);
316 spin_lock_bh(&fps->fcoe_rx_list.lock);
317 if (!fps->thread) {
318 spin_unlock_bh(&fps->fcoe_rx_list.lock);
319 goto err;
320 }
321 }
322
323 /*
324 * We now have a valid CPU that we're targeting for
325 * this skb. We also have this receive thread locked,
326 * so we're free to queue skbs into it's queue.
327 */
Robert Love85b4aa42008-12-09 15:10:24 -0800328 __skb_queue_tail(&fps->fcoe_rx_list, skb);
329 if (fps->fcoe_rx_list.qlen == 1)
330 wake_up_process(fps->thread);
331
332 spin_unlock_bh(&fps->fcoe_rx_list.lock);
333
334 return 0;
335err:
Robert Love582b45b2009-03-31 15:51:50 -0700336 fc_lport_get_stats(lp)->ErrorFrames++;
Robert Love85b4aa42008-12-09 15:10:24 -0800337
338err2:
339 kfree_skb(skb);
340 return -1;
341}
342EXPORT_SYMBOL_GPL(fcoe_rcv);
343
344/**
Robert Love34f42a02009-02-27 10:55:45 -0800345 * fcoe_start_io() - pass to netdev to start xmit for fcoe
Robert Love85b4aa42008-12-09 15:10:24 -0800346 * @skb: the skb to be xmitted
347 *
348 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800349 */
Robert Love85b4aa42008-12-09 15:10:24 -0800350static inline int fcoe_start_io(struct sk_buff *skb)
351{
352 int rc;
353
354 skb_get(skb);
355 rc = dev_queue_xmit(skb);
356 if (rc != 0)
357 return rc;
358 kfree_skb(skb);
359 return 0;
360}
361
362/**
Robert Love34f42a02009-02-27 10:55:45 -0800363 * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof
Robert Love85b4aa42008-12-09 15:10:24 -0800364 * @skb: the skb to be xmitted
365 * @tlen: total len
366 *
367 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800368 */
Robert Love85b4aa42008-12-09 15:10:24 -0800369static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
370{
371 struct fcoe_percpu_s *fps;
372 struct page *page;
Robert Love85b4aa42008-12-09 15:10:24 -0800373
Robert Love5e5e92d2009-03-17 11:41:35 -0700374 fps = &get_cpu_var(fcoe_percpu);
Robert Love85b4aa42008-12-09 15:10:24 -0800375 page = fps->crc_eof_page;
376 if (!page) {
377 page = alloc_page(GFP_ATOMIC);
378 if (!page) {
Robert Love5e5e92d2009-03-17 11:41:35 -0700379 put_cpu_var(fcoe_percpu);
Robert Love85b4aa42008-12-09 15:10:24 -0800380 return -ENOMEM;
381 }
382 fps->crc_eof_page = page;
Robert Love8976f422009-03-17 11:41:46 -0700383 fps->crc_eof_offset = 0;
Robert Love85b4aa42008-12-09 15:10:24 -0800384 }
385
386 get_page(page);
387 skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
388 fps->crc_eof_offset, tlen);
389 skb->len += tlen;
390 skb->data_len += tlen;
391 skb->truesize += tlen;
392 fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
393
394 if (fps->crc_eof_offset >= PAGE_SIZE) {
395 fps->crc_eof_page = NULL;
396 fps->crc_eof_offset = 0;
397 put_page(page);
398 }
Robert Love5e5e92d2009-03-17 11:41:35 -0700399 put_cpu_var(fcoe_percpu);
Robert Love85b4aa42008-12-09 15:10:24 -0800400 return 0;
401}
402
403/**
Robert Love34f42a02009-02-27 10:55:45 -0800404 * fcoe_fc_crc() - calculates FC CRC in this fcoe skb
Robert Love85b4aa42008-12-09 15:10:24 -0800405 * @fp: the fc_frame containg data to be checksummed
406 *
407 * This uses crc32() to calculate the crc for fc frame
408 * Return : 32 bit crc
Robert Love34f42a02009-02-27 10:55:45 -0800409 */
Robert Love85b4aa42008-12-09 15:10:24 -0800410u32 fcoe_fc_crc(struct fc_frame *fp)
411{
412 struct sk_buff *skb = fp_skb(fp);
413 struct skb_frag_struct *frag;
414 unsigned char *data;
415 unsigned long off, len, clen;
416 u32 crc;
417 unsigned i;
418
419 crc = crc32(~0, skb->data, skb_headlen(skb));
420
421 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
422 frag = &skb_shinfo(skb)->frags[i];
423 off = frag->page_offset;
424 len = frag->size;
425 while (len > 0) {
426 clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
427 data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
428 KM_SKB_DATA_SOFTIRQ);
429 crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
430 kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
431 off += clen;
432 len -= clen;
433 }
434 }
435 return crc;
436}
437EXPORT_SYMBOL_GPL(fcoe_fc_crc);
438
439/**
Robert Love34f42a02009-02-27 10:55:45 -0800440 * fcoe_xmit() - FCoE frame transmit function
Robert Love85b4aa42008-12-09 15:10:24 -0800441 * @lp: the associated local port
442 * @fp: the fc_frame to be transmitted
443 *
444 * Return : 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800445 */
Robert Love85b4aa42008-12-09 15:10:24 -0800446int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
447{
448 int wlen, rc = 0;
449 u32 crc;
450 struct ethhdr *eh;
451 struct fcoe_crc_eof *cp;
452 struct sk_buff *skb;
453 struct fcoe_dev_stats *stats;
454 struct fc_frame_header *fh;
455 unsigned int hlen; /* header length implies the version */
456 unsigned int tlen; /* trailer length */
457 unsigned int elen; /* eth header, may include vlan */
458 int flogi_in_progress = 0;
459 struct fcoe_softc *fc;
460 u8 sof, eof;
461 struct fcoe_hdr *hp;
462
463 WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
464
Robert Lovefc47ff62009-02-27 10:55:55 -0800465 fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -0800466 /*
467 * if it is a flogi then we need to learn gw-addr
468 * and my own fcid
469 */
470 fh = fc_frame_header_get(fp);
471 if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
472 if (fc_frame_payload_op(fp) == ELS_FLOGI) {
473 fc->flogi_oxid = ntohs(fh->fh_ox_id);
474 fc->address_mode = FCOE_FCOUI_ADDR_MODE;
475 fc->flogi_progress = 1;
476 flogi_in_progress = 1;
477 } else if (fc->flogi_progress && ntoh24(fh->fh_s_id) != 0) {
478 /*
479 * Here we must've gotten an SID by accepting an FLOGI
480 * from a point-to-point connection. Switch to using
481 * the source mac based on the SID. The destination
482 * MAC in this case would have been set by receving the
483 * FLOGI.
484 */
485 fc_fcoe_set_mac(fc->data_src_addr, fh->fh_s_id);
486 fc->flogi_progress = 0;
487 }
488 }
489
490 skb = fp_skb(fp);
491 sof = fr_sof(fp);
492 eof = fr_eof(fp);
493
494 elen = (fc->real_dev->priv_flags & IFF_802_1Q_VLAN) ?
495 sizeof(struct vlan_ethhdr) : sizeof(struct ethhdr);
496 hlen = sizeof(struct fcoe_hdr);
497 tlen = sizeof(struct fcoe_crc_eof);
498 wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE;
499
500 /* crc offload */
501 if (likely(lp->crc_offload)) {
Yi Zou39ca9a02009-02-27 14:07:15 -0800502 skb->ip_summed = CHECKSUM_PARTIAL;
Robert Love85b4aa42008-12-09 15:10:24 -0800503 skb->csum_start = skb_headroom(skb);
504 skb->csum_offset = skb->len;
505 crc = 0;
506 } else {
507 skb->ip_summed = CHECKSUM_NONE;
508 crc = fcoe_fc_crc(fp);
509 }
510
511 /* copy fc crc and eof to the skb buff */
512 if (skb_is_nonlinear(skb)) {
513 skb_frag_t *frag;
514 if (fcoe_get_paged_crc_eof(skb, tlen)) {
Roel Kluine9041582009-02-27 10:56:22 -0800515 kfree_skb(skb);
Robert Love85b4aa42008-12-09 15:10:24 -0800516 return -ENOMEM;
517 }
518 frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
519 cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
520 + frag->page_offset;
521 } else {
522 cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
523 }
524
525 memset(cp, 0, sizeof(*cp));
526 cp->fcoe_eof = eof;
527 cp->fcoe_crc32 = cpu_to_le32(~crc);
528
529 if (skb_is_nonlinear(skb)) {
530 kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
531 cp = NULL;
532 }
533
534 /* adjust skb netowrk/transport offsets to match mac/fcoe/fc */
535 skb_push(skb, elen + hlen);
536 skb_reset_mac_header(skb);
537 skb_reset_network_header(skb);
538 skb->mac_len = elen;
Yi Zou211c7382009-02-27 14:06:37 -0800539 skb->protocol = htons(ETH_P_FCOE);
Robert Love85b4aa42008-12-09 15:10:24 -0800540 skb->dev = fc->real_dev;
541
542 /* fill up mac and fcoe headers */
543 eh = eth_hdr(skb);
544 eh->h_proto = htons(ETH_P_FCOE);
545 if (fc->address_mode == FCOE_FCOUI_ADDR_MODE)
546 fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
547 else
548 /* insert GW address */
549 memcpy(eh->h_dest, fc->dest_addr, ETH_ALEN);
550
551 if (unlikely(flogi_in_progress))
552 memcpy(eh->h_source, fc->ctl_src_addr, ETH_ALEN);
553 else
554 memcpy(eh->h_source, fc->data_src_addr, ETH_ALEN);
555
556 hp = (struct fcoe_hdr *)(eh + 1);
557 memset(hp, 0, sizeof(*hp));
558 if (FC_FCOE_VER)
559 FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
560 hp->fcoe_sof = sof;
561
Yi Zou39ca9a02009-02-27 14:07:15 -0800562#ifdef NETIF_F_FSO
563 /* fcoe lso, mss is in max_payload which is non-zero for FCP data */
564 if (lp->seq_offload && fr_max_payload(fp)) {
565 skb_shinfo(skb)->gso_type = SKB_GSO_FCOE;
566 skb_shinfo(skb)->gso_size = fr_max_payload(fp);
567 } else {
568 skb_shinfo(skb)->gso_type = 0;
569 skb_shinfo(skb)->gso_size = 0;
570 }
571#endif
Robert Love85b4aa42008-12-09 15:10:24 -0800572 /* update tx stats: regardless if LLD fails */
Robert Love582b45b2009-03-31 15:51:50 -0700573 stats = fc_lport_get_stats(lp);
574 stats->TxFrames++;
575 stats->TxWords += wlen;
Robert Love85b4aa42008-12-09 15:10:24 -0800576
577 /* send down to lld */
578 fr_dev(fp) = lp;
579 if (fc->fcoe_pending_queue.qlen)
580 rc = fcoe_check_wait_queue(lp);
581
582 if (rc == 0)
583 rc = fcoe_start_io(skb);
584
585 if (rc) {
Chris Leech55c8baf2009-02-27 10:56:32 -0800586 spin_lock_bh(&fc->fcoe_pending_queue.lock);
587 __skb_queue_tail(&fc->fcoe_pending_queue, skb);
588 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
Robert Love85b4aa42008-12-09 15:10:24 -0800589 if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
Vasu Devbc0e17f2009-02-27 10:54:57 -0800590 lp->qfull = 1;
Robert Love85b4aa42008-12-09 15:10:24 -0800591 }
592
593 return 0;
594}
595EXPORT_SYMBOL_GPL(fcoe_xmit);
596
Robert Love34f42a02009-02-27 10:55:45 -0800597/**
598 * fcoe_percpu_receive_thread() - recv thread per cpu
Robert Love85b4aa42008-12-09 15:10:24 -0800599 * @arg: ptr to the fcoe per cpu struct
600 *
601 * Return: 0 for success
Robert Love85b4aa42008-12-09 15:10:24 -0800602 */
603int fcoe_percpu_receive_thread(void *arg)
604{
605 struct fcoe_percpu_s *p = arg;
606 u32 fr_len;
607 struct fc_lport *lp;
608 struct fcoe_rcv_info *fr;
609 struct fcoe_dev_stats *stats;
610 struct fc_frame_header *fh;
611 struct sk_buff *skb;
612 struct fcoe_crc_eof crc_eof;
613 struct fc_frame *fp;
614 u8 *mac = NULL;
615 struct fcoe_softc *fc;
616 struct fcoe_hdr *hp;
617
Robert Love4469c192009-02-27 10:56:38 -0800618 set_user_nice(current, -20);
Robert Love85b4aa42008-12-09 15:10:24 -0800619
620 while (!kthread_should_stop()) {
621
622 spin_lock_bh(&p->fcoe_rx_list.lock);
623 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) == NULL) {
624 set_current_state(TASK_INTERRUPTIBLE);
625 spin_unlock_bh(&p->fcoe_rx_list.lock);
626 schedule();
627 set_current_state(TASK_RUNNING);
628 if (kthread_should_stop())
629 return 0;
630 spin_lock_bh(&p->fcoe_rx_list.lock);
631 }
632 spin_unlock_bh(&p->fcoe_rx_list.lock);
633 fr = fcoe_dev_from_skb(skb);
634 lp = fr->fr_dev;
635 if (unlikely(lp == NULL)) {
636 FC_DBG("invalid HBA Structure");
637 kfree_skb(skb);
638 continue;
639 }
640
Robert Love85b4aa42008-12-09 15:10:24 -0800641 if (unlikely(debug_fcoe)) {
642 FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p "
643 "tail:%p end:%p sum:%d dev:%s",
644 skb->len, skb->data_len,
645 skb->head, skb->data, skb_tail_pointer(skb),
646 skb_end_pointer(skb), skb->csum,
647 skb->dev ? skb->dev->name : "<NULL>");
648 }
649
650 /*
651 * Save source MAC address before discarding header.
652 */
653 fc = lport_priv(lp);
654 if (unlikely(fc->flogi_progress))
655 mac = eth_hdr(skb)->h_source;
656
657 if (skb_is_nonlinear(skb))
658 skb_linearize(skb); /* not ideal */
659
660 /*
661 * Frame length checks and setting up the header pointers
662 * was done in fcoe_rcv already.
663 */
664 hp = (struct fcoe_hdr *) skb_network_header(skb);
665 fh = (struct fc_frame_header *) skb_transport_header(skb);
666
Robert Love582b45b2009-03-31 15:51:50 -0700667 stats = fc_lport_get_stats(lp);
Robert Love85b4aa42008-12-09 15:10:24 -0800668 if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
Robert Love582b45b2009-03-31 15:51:50 -0700669 if (stats->ErrorFrames < 5)
670 printk(KERN_WARNING "FCoE version "
671 "mismatch: The frame has "
672 "version %x, but the "
673 "initiator supports version "
674 "%x\n", FC_FCOE_DECAPS_VER(hp),
675 FC_FCOE_VER);
676 stats->ErrorFrames++;
Robert Love85b4aa42008-12-09 15:10:24 -0800677 kfree_skb(skb);
678 continue;
679 }
680
681 skb_pull(skb, sizeof(struct fcoe_hdr));
682 fr_len = skb->len - sizeof(struct fcoe_crc_eof);
683
Robert Love582b45b2009-03-31 15:51:50 -0700684 stats->RxFrames++;
685 stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
Robert Love85b4aa42008-12-09 15:10:24 -0800686
687 fp = (struct fc_frame *)skb;
688 fc_frame_init(fp);
689 fr_dev(fp) = lp;
690 fr_sof(fp) = hp->fcoe_sof;
691
692 /* Copy out the CRC and EOF trailer for access */
693 if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
694 kfree_skb(skb);
695 continue;
696 }
697 fr_eof(fp) = crc_eof.fcoe_eof;
698 fr_crc(fp) = crc_eof.fcoe_crc32;
699 if (pskb_trim(skb, fr_len)) {
700 kfree_skb(skb);
701 continue;
702 }
703
704 /*
705 * We only check CRC if no offload is available and if it is
706 * it's solicited data, in which case, the FCP layer would
707 * check it during the copy.
708 */
Yi Zou07c00ec2009-02-27 14:07:31 -0800709 if (lp->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY)
Robert Love85b4aa42008-12-09 15:10:24 -0800710 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
711 else
712 fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
713
714 fh = fc_frame_header_get(fp);
715 if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
716 fh->fh_type == FC_TYPE_FCP) {
717 fc_exch_recv(lp, lp->emp, fp);
718 continue;
719 }
720 if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
721 if (le32_to_cpu(fr_crc(fp)) !=
722 ~crc32(~0, skb->data, fr_len)) {
723 if (debug_fcoe || stats->InvalidCRCCount < 5)
724 printk(KERN_WARNING "fcoe: dropping "
725 "frame with CRC error\n");
726 stats->InvalidCRCCount++;
727 stats->ErrorFrames++;
728 fc_frame_free(fp);
729 continue;
730 }
731 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
732 }
733 /* non flogi and non data exchanges are handled here */
734 if (unlikely(fc->flogi_progress))
735 fcoe_recv_flogi(fc, fp, mac);
736 fc_exch_recv(lp, lp->emp, fp);
737 }
738 return 0;
739}
740
741/**
Robert Love34f42a02009-02-27 10:55:45 -0800742 * fcoe_recv_flogi() - flogi receive function
Robert Love85b4aa42008-12-09 15:10:24 -0800743 * @fc: associated fcoe_softc
744 * @fp: the recieved frame
745 * @sa: the source address of this flogi
746 *
747 * This is responsible to parse the flogi response and sets the corresponding
748 * mac address for the initiator, eitehr OUI based or GW based.
749 *
750 * Returns: none
Robert Love34f42a02009-02-27 10:55:45 -0800751 */
Robert Love85b4aa42008-12-09 15:10:24 -0800752static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa)
753{
754 struct fc_frame_header *fh;
755 u8 op;
756
757 fh = fc_frame_header_get(fp);
758 if (fh->fh_type != FC_TYPE_ELS)
759 return;
760 op = fc_frame_payload_op(fp);
761 if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
762 fc->flogi_oxid == ntohs(fh->fh_ox_id)) {
763 /*
764 * FLOGI accepted.
765 * If the src mac addr is FC_OUI-based, then we mark the
766 * address_mode flag to use FC_OUI-based Ethernet DA.
767 * Otherwise we use the FCoE gateway addr
768 */
769 if (!compare_ether_addr(sa, (u8[6]) FC_FCOE_FLOGI_MAC)) {
770 fc->address_mode = FCOE_FCOUI_ADDR_MODE;
771 } else {
772 memcpy(fc->dest_addr, sa, ETH_ALEN);
773 fc->address_mode = FCOE_GW_ADDR_MODE;
774 }
775
776 /*
777 * Remove any previously-set unicast MAC filter.
778 * Add secondary FCoE MAC address filter for our OUI.
779 */
780 rtnl_lock();
781 if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
782 dev_unicast_delete(fc->real_dev, fc->data_src_addr,
783 ETH_ALEN);
784 fc_fcoe_set_mac(fc->data_src_addr, fh->fh_d_id);
785 dev_unicast_add(fc->real_dev, fc->data_src_addr, ETH_ALEN);
786 rtnl_unlock();
787
788 fc->flogi_progress = 0;
789 } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
790 /*
791 * Save source MAC for point-to-point responses.
792 */
793 memcpy(fc->dest_addr, sa, ETH_ALEN);
794 fc->address_mode = FCOE_GW_ADDR_MODE;
795 }
796}
797
798/**
Robert Love34f42a02009-02-27 10:55:45 -0800799 * fcoe_watchdog() - fcoe timer callback
Robert Love85b4aa42008-12-09 15:10:24 -0800800 * @vp:
801 *
Vasu Devbc0e17f2009-02-27 10:54:57 -0800802 * This checks the pending queue length for fcoe and set lport qfull
Robert Love85b4aa42008-12-09 15:10:24 -0800803 * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the
804 * fcoe_hostlist.
805 *
806 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800807 */
Robert Love85b4aa42008-12-09 15:10:24 -0800808void fcoe_watchdog(ulong vp)
809{
Robert Love85b4aa42008-12-09 15:10:24 -0800810 struct fcoe_softc *fc;
Robert Love85b4aa42008-12-09 15:10:24 -0800811
812 read_lock(&fcoe_hostlist_lock);
813 list_for_each_entry(fc, &fcoe_hostlist, list) {
Vasu Devc826a312009-02-27 10:56:27 -0800814 if (fc->lp)
815 fcoe_check_wait_queue(fc->lp);
Robert Love85b4aa42008-12-09 15:10:24 -0800816 }
817 read_unlock(&fcoe_hostlist_lock);
818
819 fcoe_timer.expires = jiffies + (1 * HZ);
820 add_timer(&fcoe_timer);
821}
822
823
824/**
Robert Love34f42a02009-02-27 10:55:45 -0800825 * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue
Robert Love85b4aa42008-12-09 15:10:24 -0800826 * @lp: the fc_port for this skb
827 * @skb: the associated skb to be xmitted
828 *
829 * This empties the wait_queue, dequeue the head of the wait_queue queue
830 * and calls fcoe_start_io() for each packet, if all skb have been
Vasu Devc826a312009-02-27 10:56:27 -0800831 * transmitted, return qlen or -1 if a error occurs, then restore
832 * wait_queue and try again later.
Robert Love85b4aa42008-12-09 15:10:24 -0800833 *
834 * The wait_queue is used when the skb transmit fails. skb will go
835 * in the wait_queue which will be emptied by the time function OR
836 * by the next skb transmit.
837 *
838 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800839 */
Robert Love85b4aa42008-12-09 15:10:24 -0800840static int fcoe_check_wait_queue(struct fc_lport *lp)
841{
Chris Leech55c8baf2009-02-27 10:56:32 -0800842 struct fcoe_softc *fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -0800843 struct sk_buff *skb;
Vasu Devc826a312009-02-27 10:56:27 -0800844 int rc = -1;
Robert Love85b4aa42008-12-09 15:10:24 -0800845
Robert Love85b4aa42008-12-09 15:10:24 -0800846 spin_lock_bh(&fc->fcoe_pending_queue.lock);
Vasu Devc826a312009-02-27 10:56:27 -0800847 if (fc->fcoe_pending_queue_active)
848 goto out;
849 fc->fcoe_pending_queue_active = 1;
Chris Leech55c8baf2009-02-27 10:56:32 -0800850
851 while (fc->fcoe_pending_queue.qlen) {
852 /* keep qlen > 0 until fcoe_start_io succeeds */
853 fc->fcoe_pending_queue.qlen++;
854 skb = __skb_dequeue(&fc->fcoe_pending_queue);
855
856 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
857 rc = fcoe_start_io(skb);
858 spin_lock_bh(&fc->fcoe_pending_queue.lock);
859
860 if (rc) {
861 __skb_queue_head(&fc->fcoe_pending_queue, skb);
862 /* undo temporary increment above */
863 fc->fcoe_pending_queue.qlen--;
864 break;
Robert Love85b4aa42008-12-09 15:10:24 -0800865 }
Chris Leech55c8baf2009-02-27 10:56:32 -0800866 /* undo temporary increment above */
867 fc->fcoe_pending_queue.qlen--;
Robert Love85b4aa42008-12-09 15:10:24 -0800868 }
Chris Leech55c8baf2009-02-27 10:56:32 -0800869
870 if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
871 lp->qfull = 0;
Vasu Devc826a312009-02-27 10:56:27 -0800872 fc->fcoe_pending_queue_active = 0;
873 rc = fc->fcoe_pending_queue.qlen;
874out:
Robert Love85b4aa42008-12-09 15:10:24 -0800875 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
Vasu Devc826a312009-02-27 10:56:27 -0800876 return rc;
Robert Love85b4aa42008-12-09 15:10:24 -0800877}
878
879/**
Robert Love34f42a02009-02-27 10:55:45 -0800880 * fcoe_dev_setup() - setup link change notification interface
881 */
882static void fcoe_dev_setup()
Robert Love85b4aa42008-12-09 15:10:24 -0800883{
884 /*
885 * here setup a interface specific wd time to
886 * monitor the link state
887 */
888 register_netdevice_notifier(&fcoe_notifier);
889}
890
891/**
Robert Love34f42a02009-02-27 10:55:45 -0800892 * fcoe_dev_setup() - cleanup link change notification interface
893 */
Robert Love85b4aa42008-12-09 15:10:24 -0800894static void fcoe_dev_cleanup(void)
895{
896 unregister_netdevice_notifier(&fcoe_notifier);
897}
898
899/**
Robert Love34f42a02009-02-27 10:55:45 -0800900 * fcoe_device_notification() - netdev event notification callback
Robert Love85b4aa42008-12-09 15:10:24 -0800901 * @notifier: context of the notification
902 * @event: type of event
903 * @ptr: fixed array for output parsed ifname
904 *
905 * This function is called by the ethernet driver in case of link change event
906 *
907 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800908 */
Robert Love85b4aa42008-12-09 15:10:24 -0800909static int fcoe_device_notification(struct notifier_block *notifier,
910 ulong event, void *ptr)
911{
912 struct fc_lport *lp = NULL;
913 struct net_device *real_dev = ptr;
914 struct fcoe_softc *fc;
915 struct fcoe_dev_stats *stats;
Vasu Devbc0e17f2009-02-27 10:54:57 -0800916 u32 new_link_up;
Robert Love85b4aa42008-12-09 15:10:24 -0800917 u32 mfs;
918 int rc = NOTIFY_OK;
919
920 read_lock(&fcoe_hostlist_lock);
921 list_for_each_entry(fc, &fcoe_hostlist, list) {
922 if (fc->real_dev == real_dev) {
923 lp = fc->lp;
924 break;
925 }
926 }
927 read_unlock(&fcoe_hostlist_lock);
928 if (lp == NULL) {
929 rc = NOTIFY_DONE;
930 goto out;
931 }
932
Vasu Devbc0e17f2009-02-27 10:54:57 -0800933 new_link_up = lp->link_up;
Robert Love85b4aa42008-12-09 15:10:24 -0800934 switch (event) {
935 case NETDEV_DOWN:
936 case NETDEV_GOING_DOWN:
Vasu Devbc0e17f2009-02-27 10:54:57 -0800937 new_link_up = 0;
Robert Love85b4aa42008-12-09 15:10:24 -0800938 break;
939 case NETDEV_UP:
940 case NETDEV_CHANGE:
Vasu Devbc0e17f2009-02-27 10:54:57 -0800941 new_link_up = !fcoe_link_ok(lp);
Robert Love85b4aa42008-12-09 15:10:24 -0800942 break;
943 case NETDEV_CHANGEMTU:
944 mfs = fc->real_dev->mtu -
945 (sizeof(struct fcoe_hdr) +
946 sizeof(struct fcoe_crc_eof));
947 if (mfs >= FC_MIN_MAX_FRAME)
948 fc_set_mfs(lp, mfs);
Vasu Devbc0e17f2009-02-27 10:54:57 -0800949 new_link_up = !fcoe_link_ok(lp);
Robert Love85b4aa42008-12-09 15:10:24 -0800950 break;
951 case NETDEV_REGISTER:
952 break;
953 default:
954 FC_DBG("unknown event %ld call", event);
955 }
Vasu Devbc0e17f2009-02-27 10:54:57 -0800956 if (lp->link_up != new_link_up) {
957 if (new_link_up)
Robert Love85b4aa42008-12-09 15:10:24 -0800958 fc_linkup(lp);
959 else {
Robert Love582b45b2009-03-31 15:51:50 -0700960 stats = fc_lport_get_stats(lp);
961 stats->LinkFailureCount++;
Robert Love85b4aa42008-12-09 15:10:24 -0800962 fc_linkdown(lp);
963 fcoe_clean_pending_queue(lp);
964 }
965 }
966out:
967 return rc;
968}
969
970/**
Robert Love34f42a02009-02-27 10:55:45 -0800971 * fcoe_if_to_netdev() - parse a name buffer to get netdev
Robert Love85b4aa42008-12-09 15:10:24 -0800972 * @ifname: fixed array for output parsed ifname
973 * @buffer: incoming buffer to be copied
974 *
975 * Returns: NULL or ptr to netdeive
Robert Love34f42a02009-02-27 10:55:45 -0800976 */
Robert Love85b4aa42008-12-09 15:10:24 -0800977static struct net_device *fcoe_if_to_netdev(const char *buffer)
978{
979 char *cp;
980 char ifname[IFNAMSIZ + 2];
981
982 if (buffer) {
983 strlcpy(ifname, buffer, IFNAMSIZ);
984 cp = ifname + strlen(ifname);
985 while (--cp >= ifname && *cp == '\n')
986 *cp = '\0';
987 return dev_get_by_name(&init_net, ifname);
988 }
989 return NULL;
990}
991
992/**
Robert Love34f42a02009-02-27 10:55:45 -0800993 * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev
Robert Love85b4aa42008-12-09 15:10:24 -0800994 * @netdev: the target netdev
995 *
996 * Returns: ptr to the struct module, NULL for failure
Robert Love34f42a02009-02-27 10:55:45 -0800997 */
Robert Loveb2ab99c2009-02-27 10:55:50 -0800998static struct module *
999fcoe_netdev_to_module_owner(const struct net_device *netdev)
Robert Love85b4aa42008-12-09 15:10:24 -08001000{
1001 struct device *dev;
1002
1003 if (!netdev)
1004 return NULL;
1005
1006 dev = netdev->dev.parent;
1007 if (!dev)
1008 return NULL;
1009
1010 if (!dev->driver)
1011 return NULL;
1012
1013 return dev->driver->owner;
1014}
1015
1016/**
Robert Love34f42a02009-02-27 10:55:45 -08001017 * fcoe_ethdrv_get() - Hold the Ethernet driver
Robert Love85b4aa42008-12-09 15:10:24 -08001018 * @netdev: the target netdev
1019 *
Robert Love34f42a02009-02-27 10:55:45 -08001020 * Holds the Ethernet driver module by try_module_get() for
1021 * the corresponding netdev.
1022 *
Robert Love85b4aa42008-12-09 15:10:24 -08001023 * Returns: 0 for succsss
Robert Love34f42a02009-02-27 10:55:45 -08001024 */
Robert Love85b4aa42008-12-09 15:10:24 -08001025static int fcoe_ethdrv_get(const struct net_device *netdev)
1026{
1027 struct module *owner;
1028
1029 owner = fcoe_netdev_to_module_owner(netdev);
1030 if (owner) {
James Bottomley56b854b2008-12-29 15:45:41 -06001031 printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n",
1032 module_name(owner), netdev->name);
Robert Love85b4aa42008-12-09 15:10:24 -08001033 return try_module_get(owner);
1034 }
1035 return -ENODEV;
1036}
1037
1038/**
Robert Love34f42a02009-02-27 10:55:45 -08001039 * fcoe_ethdrv_put() - Release the Ethernet driver
Robert Love85b4aa42008-12-09 15:10:24 -08001040 * @netdev: the target netdev
1041 *
Robert Love34f42a02009-02-27 10:55:45 -08001042 * Releases the Ethernet driver module by module_put for
1043 * the corresponding netdev.
1044 *
Robert Love85b4aa42008-12-09 15:10:24 -08001045 * Returns: 0 for succsss
Robert Love34f42a02009-02-27 10:55:45 -08001046 */
Robert Love85b4aa42008-12-09 15:10:24 -08001047static int fcoe_ethdrv_put(const struct net_device *netdev)
1048{
1049 struct module *owner;
1050
1051 owner = fcoe_netdev_to_module_owner(netdev);
1052 if (owner) {
James Bottomley56b854b2008-12-29 15:45:41 -06001053 printk(KERN_DEBUG "fcoe:release driver module %s for %s\n",
1054 module_name(owner), netdev->name);
Robert Love85b4aa42008-12-09 15:10:24 -08001055 module_put(owner);
1056 return 0;
1057 }
1058 return -ENODEV;
1059}
1060
1061/**
Robert Love34f42a02009-02-27 10:55:45 -08001062 * fcoe_destroy() - handles the destroy from sysfs
Robert Love85b4aa42008-12-09 15:10:24 -08001063 * @buffer: expcted to be a eth if name
1064 * @kp: associated kernel param
1065 *
1066 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001067 */
Robert Love85b4aa42008-12-09 15:10:24 -08001068static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
1069{
1070 int rc;
1071 struct net_device *netdev;
1072
1073 netdev = fcoe_if_to_netdev(buffer);
1074 if (!netdev) {
1075 rc = -ENODEV;
1076 goto out_nodev;
1077 }
1078 /* look for existing lport */
1079 if (!fcoe_hostlist_lookup(netdev)) {
1080 rc = -ENODEV;
1081 goto out_putdev;
1082 }
Vasu Dev5919a592009-03-27 09:03:29 -07001083 rc = fcoe_sw_destroy(netdev);
Robert Love85b4aa42008-12-09 15:10:24 -08001084 if (rc) {
Vasu Dev5919a592009-03-27 09:03:29 -07001085 printk(KERN_ERR "fcoe: fcoe_sw_destroy(%s) failed\n",
Robert Love85b4aa42008-12-09 15:10:24 -08001086 netdev->name);
1087 rc = -EIO;
1088 goto out_putdev;
1089 }
1090 fcoe_ethdrv_put(netdev);
1091 rc = 0;
1092out_putdev:
1093 dev_put(netdev);
1094out_nodev:
1095 return rc;
1096}
1097
1098/**
Robert Love34f42a02009-02-27 10:55:45 -08001099 * fcoe_create() - Handles the create call from sysfs
Robert Love85b4aa42008-12-09 15:10:24 -08001100 * @buffer: expcted to be a eth if name
1101 * @kp: associated kernel param
1102 *
1103 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001104 */
Robert Love85b4aa42008-12-09 15:10:24 -08001105static int fcoe_create(const char *buffer, struct kernel_param *kp)
1106{
1107 int rc;
1108 struct net_device *netdev;
1109
1110 netdev = fcoe_if_to_netdev(buffer);
1111 if (!netdev) {
1112 rc = -ENODEV;
1113 goto out_nodev;
1114 }
1115 /* look for existing lport */
1116 if (fcoe_hostlist_lookup(netdev)) {
1117 rc = -EEXIST;
1118 goto out_putdev;
1119 }
1120 fcoe_ethdrv_get(netdev);
1121
Vasu Dev5919a592009-03-27 09:03:29 -07001122 rc = fcoe_sw_create(netdev);
Robert Love85b4aa42008-12-09 15:10:24 -08001123 if (rc) {
Vasu Dev5919a592009-03-27 09:03:29 -07001124 printk(KERN_ERR "fcoe: fcoe_sw_create(%s) failed\n",
Robert Love85b4aa42008-12-09 15:10:24 -08001125 netdev->name);
1126 fcoe_ethdrv_put(netdev);
1127 rc = -EIO;
1128 goto out_putdev;
1129 }
1130 rc = 0;
1131out_putdev:
1132 dev_put(netdev);
1133out_nodev:
1134 return rc;
1135}
1136
1137module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
1138__MODULE_PARM_TYPE(create, "string");
1139MODULE_PARM_DESC(create, "Create fcoe port using net device passed in.");
1140module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
1141__MODULE_PARM_TYPE(destroy, "string");
1142MODULE_PARM_DESC(destroy, "Destroy fcoe port");
1143
Robert Love34f42a02009-02-27 10:55:45 -08001144/**
1145 * fcoe_link_ok() - Check if link is ok for the fc_lport
Robert Love85b4aa42008-12-09 15:10:24 -08001146 * @lp: ptr to the fc_lport
1147 *
1148 * Any permanently-disqualifying conditions have been previously checked.
1149 * This also updates the speed setting, which may change with link for 100/1000.
1150 *
1151 * This function should probably be checking for PAUSE support at some point
1152 * in the future. Currently Per-priority-pause is not determinable using
1153 * ethtool, so we shouldn't be restrictive until that problem is resolved.
1154 *
1155 * Returns: 0 if link is OK for use by FCoE.
1156 *
1157 */
1158int fcoe_link_ok(struct fc_lport *lp)
1159{
Robert Lovefc47ff62009-02-27 10:55:55 -08001160 struct fcoe_softc *fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001161 struct net_device *dev = fc->real_dev;
1162 struct ethtool_cmd ecmd = { ETHTOOL_GSET };
1163 int rc = 0;
1164
1165 if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) {
1166 dev = fc->phys_dev;
1167 if (dev->ethtool_ops->get_settings) {
1168 dev->ethtool_ops->get_settings(dev, &ecmd);
1169 lp->link_supported_speeds &=
1170 ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
1171 if (ecmd.supported & (SUPPORTED_1000baseT_Half |
1172 SUPPORTED_1000baseT_Full))
1173 lp->link_supported_speeds |= FC_PORTSPEED_1GBIT;
1174 if (ecmd.supported & SUPPORTED_10000baseT_Full)
1175 lp->link_supported_speeds |=
1176 FC_PORTSPEED_10GBIT;
1177 if (ecmd.speed == SPEED_1000)
1178 lp->link_speed = FC_PORTSPEED_1GBIT;
1179 if (ecmd.speed == SPEED_10000)
1180 lp->link_speed = FC_PORTSPEED_10GBIT;
1181 }
1182 } else
1183 rc = -1;
1184
1185 return rc;
1186}
1187EXPORT_SYMBOL_GPL(fcoe_link_ok);
1188
Robert Love34f42a02009-02-27 10:55:45 -08001189/**
1190 * fcoe_percpu_clean() - Clear the pending skbs for an lport
Robert Love85b4aa42008-12-09 15:10:24 -08001191 * @lp: the fc_lport
1192 */
1193void fcoe_percpu_clean(struct fc_lport *lp)
1194{
Robert Love85b4aa42008-12-09 15:10:24 -08001195 struct fcoe_percpu_s *pp;
1196 struct fcoe_rcv_info *fr;
1197 struct sk_buff_head *list;
1198 struct sk_buff *skb, *next;
1199 struct sk_buff *head;
Robert Love5e5e92d2009-03-17 11:41:35 -07001200 unsigned int cpu;
Robert Love85b4aa42008-12-09 15:10:24 -08001201
Robert Love5e5e92d2009-03-17 11:41:35 -07001202 for_each_possible_cpu(cpu) {
1203 pp = &per_cpu(fcoe_percpu, cpu);
1204 spin_lock_bh(&pp->fcoe_rx_list.lock);
1205 list = &pp->fcoe_rx_list;
1206 head = list->next;
1207 for (skb = head; skb != (struct sk_buff *)list;
1208 skb = next) {
1209 next = skb->next;
1210 fr = fcoe_dev_from_skb(skb);
1211 if (fr->fr_dev == lp) {
1212 __skb_unlink(skb, list);
1213 kfree_skb(skb);
Robert Love85b4aa42008-12-09 15:10:24 -08001214 }
Robert Love85b4aa42008-12-09 15:10:24 -08001215 }
Robert Love5e5e92d2009-03-17 11:41:35 -07001216 spin_unlock_bh(&pp->fcoe_rx_list.lock);
Robert Love85b4aa42008-12-09 15:10:24 -08001217 }
1218}
1219EXPORT_SYMBOL_GPL(fcoe_percpu_clean);
1220
1221/**
Robert Love34f42a02009-02-27 10:55:45 -08001222 * fcoe_clean_pending_queue() - Dequeue a skb and free it
Robert Love85b4aa42008-12-09 15:10:24 -08001223 * @lp: the corresponding fc_lport
1224 *
1225 * Returns: none
Robert Love34f42a02009-02-27 10:55:45 -08001226 */
Robert Love85b4aa42008-12-09 15:10:24 -08001227void fcoe_clean_pending_queue(struct fc_lport *lp)
1228{
1229 struct fcoe_softc *fc = lport_priv(lp);
1230 struct sk_buff *skb;
1231
1232 spin_lock_bh(&fc->fcoe_pending_queue.lock);
1233 while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
1234 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
1235 kfree_skb(skb);
1236 spin_lock_bh(&fc->fcoe_pending_queue.lock);
1237 }
1238 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
1239}
1240EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
1241
1242/**
Robert Love34f42a02009-02-27 10:55:45 -08001243 * libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport
Robert Love85b4aa42008-12-09 15:10:24 -08001244 * @sht: ptr to the scsi host templ
1245 * @priv_size: size of private data after fc_lport
1246 *
1247 * Returns: ptr to Scsi_Host
Robert Love34f42a02009-02-27 10:55:45 -08001248 * TODO: to libfc?
Robert Love85b4aa42008-12-09 15:10:24 -08001249 */
Robert Loveb2ab99c2009-02-27 10:55:50 -08001250static inline struct Scsi_Host *
1251libfc_host_alloc(struct scsi_host_template *sht, int priv_size)
Robert Love85b4aa42008-12-09 15:10:24 -08001252{
1253 return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size);
1254}
1255
1256/**
Robert Love34f42a02009-02-27 10:55:45 -08001257 * fcoe_host_alloc() - Allocate a Scsi_Host with room for the fcoe_softc
Robert Love85b4aa42008-12-09 15:10:24 -08001258 * @sht: ptr to the scsi host templ
1259 * @priv_size: size of private data after fc_lport
1260 *
1261 * Returns: ptr to Scsi_Host
1262 */
1263struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *sht, int priv_size)
1264{
1265 return libfc_host_alloc(sht, sizeof(struct fcoe_softc) + priv_size);
1266}
1267EXPORT_SYMBOL_GPL(fcoe_host_alloc);
1268
Robert Love34f42a02009-02-27 10:55:45 -08001269/**
1270 * fcoe_reset() - Resets the fcoe
Robert Love85b4aa42008-12-09 15:10:24 -08001271 * @shost: shost the reset is from
1272 *
1273 * Returns: always 0
1274 */
1275int fcoe_reset(struct Scsi_Host *shost)
1276{
1277 struct fc_lport *lport = shost_priv(shost);
1278 fc_lport_reset(lport);
1279 return 0;
1280}
1281EXPORT_SYMBOL_GPL(fcoe_reset);
1282
Robert Love34f42a02009-02-27 10:55:45 -08001283/**
1284 * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN.
Robert Love85b4aa42008-12-09 15:10:24 -08001285 * @mac: mac address
1286 * @scheme: check port
1287 * @port: port indicator for converting
1288 *
1289 * Returns: u64 fc world wide name
1290 */
1291u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
1292 unsigned int scheme, unsigned int port)
1293{
1294 u64 wwn;
1295 u64 host_mac;
1296
1297 /* The MAC is in NO, so flip only the low 48 bits */
1298 host_mac = ((u64) mac[0] << 40) |
1299 ((u64) mac[1] << 32) |
1300 ((u64) mac[2] << 24) |
1301 ((u64) mac[3] << 16) |
1302 ((u64) mac[4] << 8) |
1303 (u64) mac[5];
1304
1305 WARN_ON(host_mac >= (1ULL << 48));
1306 wwn = host_mac | ((u64) scheme << 60);
1307 switch (scheme) {
1308 case 1:
1309 WARN_ON(port != 0);
1310 break;
1311 case 2:
1312 WARN_ON(port >= 0xfff);
1313 wwn |= (u64) port << 48;
1314 break;
1315 default:
1316 WARN_ON(1);
1317 break;
1318 }
1319
1320 return wwn;
1321}
1322EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
Robert Love34f42a02009-02-27 10:55:45 -08001323
1324/**
1325 * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
Robert Love85b4aa42008-12-09 15:10:24 -08001326 * @device: this is currently ptr to net_device
1327 *
1328 * Returns: NULL or the located fcoe_softc
1329 */
Robert Loveb2ab99c2009-02-27 10:55:50 -08001330static struct fcoe_softc *
1331fcoe_hostlist_lookup_softc(const struct net_device *dev)
Robert Love85b4aa42008-12-09 15:10:24 -08001332{
1333 struct fcoe_softc *fc;
1334
1335 read_lock(&fcoe_hostlist_lock);
1336 list_for_each_entry(fc, &fcoe_hostlist, list) {
1337 if (fc->real_dev == dev) {
1338 read_unlock(&fcoe_hostlist_lock);
1339 return fc;
1340 }
1341 }
1342 read_unlock(&fcoe_hostlist_lock);
1343 return NULL;
1344}
1345
Robert Love34f42a02009-02-27 10:55:45 -08001346/**
1347 * fcoe_hostlist_lookup() - Find the corresponding lport by netdev
Robert Love85b4aa42008-12-09 15:10:24 -08001348 * @netdev: ptr to net_device
1349 *
1350 * Returns: 0 for success
1351 */
1352struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
1353{
1354 struct fcoe_softc *fc;
1355
1356 fc = fcoe_hostlist_lookup_softc(netdev);
1357
1358 return (fc) ? fc->lp : NULL;
1359}
1360EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup);
1361
Robert Love34f42a02009-02-27 10:55:45 -08001362/**
1363 * fcoe_hostlist_add() - Add a lport to lports list
Robert Love85b4aa42008-12-09 15:10:24 -08001364 * @lp: ptr to the fc_lport to badded
1365 *
1366 * Returns: 0 for success
1367 */
1368int fcoe_hostlist_add(const struct fc_lport *lp)
1369{
1370 struct fcoe_softc *fc;
1371
1372 fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
1373 if (!fc) {
Robert Lovefc47ff62009-02-27 10:55:55 -08001374 fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001375 write_lock_bh(&fcoe_hostlist_lock);
1376 list_add_tail(&fc->list, &fcoe_hostlist);
1377 write_unlock_bh(&fcoe_hostlist_lock);
1378 }
1379 return 0;
1380}
1381EXPORT_SYMBOL_GPL(fcoe_hostlist_add);
1382
Robert Love34f42a02009-02-27 10:55:45 -08001383/**
1384 * fcoe_hostlist_remove() - remove a lport from lports list
Robert Love85b4aa42008-12-09 15:10:24 -08001385 * @lp: ptr to the fc_lport to badded
1386 *
1387 * Returns: 0 for success
1388 */
1389int fcoe_hostlist_remove(const struct fc_lport *lp)
1390{
1391 struct fcoe_softc *fc;
1392
1393 fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
1394 BUG_ON(!fc);
1395 write_lock_bh(&fcoe_hostlist_lock);
1396 list_del(&fc->list);
1397 write_unlock_bh(&fcoe_hostlist_lock);
1398
1399 return 0;
1400}
1401EXPORT_SYMBOL_GPL(fcoe_hostlist_remove);
1402
1403/**
Robert Love34f42a02009-02-27 10:55:45 -08001404 * fcoe_libfc_config() - sets up libfc related properties for lport
Robert Love85b4aa42008-12-09 15:10:24 -08001405 * @lp: ptr to the fc_lport
1406 * @tt: libfc function template
1407 *
1408 * Returns : 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001409 */
Robert Love85b4aa42008-12-09 15:10:24 -08001410int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt)
1411{
1412 /* Set the function pointers set by the LLDD */
1413 memcpy(&lp->tt, tt, sizeof(*tt));
1414 if (fc_fcp_init(lp))
1415 return -ENOMEM;
1416 fc_exch_init(lp);
1417 fc_elsct_init(lp);
1418 fc_lport_init(lp);
1419 fc_rport_init(lp);
1420 fc_disc_init(lp);
1421
1422 return 0;
1423}
1424EXPORT_SYMBOL_GPL(fcoe_libfc_config);
1425
1426/**
Robert Love34f42a02009-02-27 10:55:45 -08001427 * fcoe_init() - fcoe module loading initialization
Robert Love85b4aa42008-12-09 15:10:24 -08001428 *
Robert Love85b4aa42008-12-09 15:10:24 -08001429 * Returns 0 on success, negative on failure
Robert Love34f42a02009-02-27 10:55:45 -08001430 */
Robert Love85b4aa42008-12-09 15:10:24 -08001431static int __init fcoe_init(void)
1432{
Robert Love38eccab2009-03-17 11:41:30 -07001433 unsigned int cpu;
Robert Love8976f422009-03-17 11:41:46 -07001434 int rc = 0;
Robert Love85b4aa42008-12-09 15:10:24 -08001435 struct fcoe_percpu_s *p;
1436
Robert Love85b4aa42008-12-09 15:10:24 -08001437 INIT_LIST_HEAD(&fcoe_hostlist);
1438 rwlock_init(&fcoe_hostlist_lock);
1439
Robert Love38eccab2009-03-17 11:41:30 -07001440 for_each_possible_cpu(cpu) {
Robert Love5e5e92d2009-03-17 11:41:35 -07001441 p = &per_cpu(fcoe_percpu, cpu);
Robert Love38eccab2009-03-17 11:41:30 -07001442 skb_queue_head_init(&p->fcoe_rx_list);
1443 }
1444
Robert Love8976f422009-03-17 11:41:46 -07001445 for_each_online_cpu(cpu)
1446 fcoe_percpu_thread_create(cpu);
Robert Love85b4aa42008-12-09 15:10:24 -08001447
Robert Love8976f422009-03-17 11:41:46 -07001448 /* Initialize per CPU interrupt thread */
1449 rc = register_hotcpu_notifier(&fcoe_cpu_notifier);
1450 if (rc)
1451 goto out_free;
Robert Love85b4aa42008-12-09 15:10:24 -08001452
Robert Love8976f422009-03-17 11:41:46 -07001453 /* Setup link change notification */
Robert Love85b4aa42008-12-09 15:10:24 -08001454 fcoe_dev_setup();
1455
Robert Lovea468f322009-02-27 10:56:00 -08001456 setup_timer(&fcoe_timer, fcoe_watchdog, 0);
1457
1458 mod_timer(&fcoe_timer, jiffies + (10 * HZ));
Robert Love85b4aa42008-12-09 15:10:24 -08001459
Robert Love85b4aa42008-12-09 15:10:24 -08001460 fcoe_sw_init();
1461
1462 return 0;
Robert Love8976f422009-03-17 11:41:46 -07001463
1464out_free:
1465 for_each_online_cpu(cpu) {
1466 fcoe_percpu_thread_destroy(cpu);
1467 }
1468
1469 return rc;
Robert Love85b4aa42008-12-09 15:10:24 -08001470}
1471module_init(fcoe_init);
1472
1473/**
Robert Love34f42a02009-02-27 10:55:45 -08001474 * fcoe_exit() - fcoe module unloading cleanup
Robert Love85b4aa42008-12-09 15:10:24 -08001475 *
1476 * Returns 0 on success, negative on failure
Robert Love34f42a02009-02-27 10:55:45 -08001477 */
Robert Love85b4aa42008-12-09 15:10:24 -08001478static void __exit fcoe_exit(void)
1479{
Robert Love5e5e92d2009-03-17 11:41:35 -07001480 unsigned int cpu;
Robert Love85b4aa42008-12-09 15:10:24 -08001481 struct fcoe_softc *fc, *tmp;
Robert Love85b4aa42008-12-09 15:10:24 -08001482
Robert Love85b4aa42008-12-09 15:10:24 -08001483 fcoe_dev_cleanup();
1484
Robert Love582b45b2009-03-31 15:51:50 -07001485 /* Stop the timer */
Robert Love85b4aa42008-12-09 15:10:24 -08001486 del_timer_sync(&fcoe_timer);
1487
Vasu Dev5919a592009-03-27 09:03:29 -07001488 /* releases the associated fcoe hosts */
Robert Love85b4aa42008-12-09 15:10:24 -08001489 list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
Vasu Dev5919a592009-03-27 09:03:29 -07001490 fcoe_sw_destroy(fc->real_dev);
Robert Love85b4aa42008-12-09 15:10:24 -08001491
Robert Love8976f422009-03-17 11:41:46 -07001492 unregister_hotcpu_notifier(&fcoe_cpu_notifier);
1493
1494 for_each_online_cpu(cpu) {
1495 fcoe_percpu_thread_destroy(cpu);
Robert Love85b4aa42008-12-09 15:10:24 -08001496 }
1497
1498 /* remove sw trasnport */
1499 fcoe_sw_exit();
Robert Love85b4aa42008-12-09 15:10:24 -08001500}
1501module_exit(fcoe_exit);