blob: 6acb7778f5571d833259487616beb7f6fa2b14df [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>
Robert Love85b4aa42008-12-09 15:10:24 -080022#include <linux/spinlock.h>
Robert Love85b4aa42008-12-09 15:10:24 -080023#include <linux/netdevice.h>
24#include <linux/etherdevice.h>
25#include <linux/ethtool.h>
26#include <linux/if_ether.h>
27#include <linux/if_vlan.h>
Robert Love85b4aa42008-12-09 15:10:24 -080028#include <linux/crc32.h>
29#include <linux/cpu.h>
30#include <linux/fs.h>
31#include <linux/sysfs.h>
32#include <linux/ctype.h>
33#include <scsi/scsi_tcq.h>
34#include <scsi/scsicam.h>
35#include <scsi/scsi_transport.h>
36#include <scsi/scsi_transport_fc.h>
37#include <net/rtnetlink.h>
38
39#include <scsi/fc/fc_encaps.h>
Joe Eykholt97c83892009-03-17 11:42:40 -070040#include <scsi/fc/fc_fip.h>
Robert Love85b4aa42008-12-09 15:10:24 -080041
42#include <scsi/libfc.h>
43#include <scsi/fc_frame.h>
44#include <scsi/libfcoe.h>
Robert Love85b4aa42008-12-09 15:10:24 -080045
Vasu Devfdd78022009-03-17 11:42:24 -070046#include "fcoe.h"
47
Robert Love85b4aa42008-12-09 15:10:24 -080048static int debug_fcoe;
49
Robert Love85b4aa42008-12-09 15:10:24 -080050MODULE_AUTHOR("Open-FCoE.org");
51MODULE_DESCRIPTION("FCoE");
Vasu Dev9b34ecf2009-03-17 11:42:13 -070052MODULE_LICENSE("GPL v2");
Robert Love85b4aa42008-12-09 15:10:24 -080053
54/* fcoe host list */
55LIST_HEAD(fcoe_hostlist);
56DEFINE_RWLOCK(fcoe_hostlist_lock);
57DEFINE_TIMER(fcoe_timer, NULL, 0, 0);
Robert Love5e5e92d2009-03-17 11:41:35 -070058DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
Robert Love85b4aa42008-12-09 15:10:24 -080059
Chris Leechdd3fd722009-04-21 16:27:36 -070060/* Function Prototypes */
Vasu Devfdd78022009-03-17 11:42:24 -070061static int fcoe_reset(struct Scsi_Host *shost);
62static int fcoe_xmit(struct fc_lport *, struct fc_frame *);
63static int fcoe_rcv(struct sk_buff *, struct net_device *,
64 struct packet_type *, struct net_device *);
65static int fcoe_percpu_receive_thread(void *arg);
66static void fcoe_clean_pending_queue(struct fc_lport *lp);
67static void fcoe_percpu_clean(struct fc_lport *lp);
68static int fcoe_link_ok(struct fc_lport *lp);
69
70static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
71static int fcoe_hostlist_add(const struct fc_lport *);
72static int fcoe_hostlist_remove(const struct fc_lport *);
73
Robert Love85b4aa42008-12-09 15:10:24 -080074static int fcoe_check_wait_queue(struct fc_lport *);
Robert Love85b4aa42008-12-09 15:10:24 -080075static int fcoe_device_notification(struct notifier_block *, ulong, void *);
76static void fcoe_dev_setup(void);
77static void fcoe_dev_cleanup(void);
78
79/* notification function from net device */
80static struct notifier_block fcoe_notifier = {
81 .notifier_call = fcoe_device_notification,
82};
83
Vasu Dev7f349142009-03-27 09:06:31 -070084static struct scsi_transport_template *scsi_transport_fcoe_sw;
85
86struct fc_function_template fcoe_transport_function = {
87 .show_host_node_name = 1,
88 .show_host_port_name = 1,
89 .show_host_supported_classes = 1,
90 .show_host_supported_fc4s = 1,
91 .show_host_active_fc4s = 1,
92 .show_host_maxframe_size = 1,
93
94 .show_host_port_id = 1,
95 .show_host_supported_speeds = 1,
96 .get_host_speed = fc_get_host_speed,
97 .show_host_speed = 1,
98 .show_host_port_type = 1,
99 .get_host_port_state = fc_get_host_port_state,
100 .show_host_port_state = 1,
101 .show_host_symbolic_name = 1,
102
103 .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
104 .show_rport_maxframe_size = 1,
105 .show_rport_supported_classes = 1,
106
107 .show_host_fabric_name = 1,
108 .show_starget_node_name = 1,
109 .show_starget_port_name = 1,
110 .show_starget_port_id = 1,
111 .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
112 .show_rport_dev_loss_tmo = 1,
113 .get_fc_host_stats = fc_get_host_stats,
114 .issue_fc_host_lip = fcoe_reset,
115
116 .terminate_rport_io = fc_rport_terminate_io,
117};
118
119static struct scsi_host_template fcoe_shost_template = {
120 .module = THIS_MODULE,
121 .name = "FCoE Driver",
122 .proc_name = FCOE_NAME,
123 .queuecommand = fc_queuecommand,
124 .eh_abort_handler = fc_eh_abort,
125 .eh_device_reset_handler = fc_eh_device_reset,
126 .eh_host_reset_handler = fc_eh_host_reset,
127 .slave_alloc = fc_slave_alloc,
128 .change_queue_depth = fc_change_queue_depth,
129 .change_queue_type = fc_change_queue_type,
130 .this_id = -1,
131 .cmd_per_lun = 32,
132 .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
133 .use_clustering = ENABLE_CLUSTERING,
134 .sg_tablesize = SG_ALL,
135 .max_sectors = 0xffff,
136};
137
138/**
139 * fcoe_lport_config() - sets up the fc_lport
140 * @lp: ptr to the fc_lport
Vasu Dev7f349142009-03-27 09:06:31 -0700141 *
142 * Returns: 0 for success
143 */
144static int fcoe_lport_config(struct fc_lport *lp)
145{
146 lp->link_up = 0;
147 lp->qfull = 0;
148 lp->max_retry_count = 3;
Abhijeet Joglekara3666952009-05-01 10:01:26 -0700149 lp->max_rport_retry_count = 3;
Vasu Dev7f349142009-03-27 09:06:31 -0700150 lp->e_d_tov = 2 * 1000; /* FC-FS default */
151 lp->r_a_tov = 2 * 2 * 1000;
152 lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
153 FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
154
155 fc_lport_init_stats(lp);
156
157 /* lport fc_lport related configuration */
158 fc_lport_config(lp);
159
160 /* offload related configuration */
161 lp->crc_offload = 0;
162 lp->seq_offload = 0;
163 lp->lro_enabled = 0;
164 lp->lro_xid = 0;
165 lp->lso_max = 0;
166
167 return 0;
168}
169
170/**
171 * fcoe_netdev_config() - Set up netdev for SW FCoE
172 * @lp : ptr to the fc_lport
173 * @netdev : ptr to the associated netdevice struct
174 *
175 * Must be called after fcoe_lport_config() as it will use lport mutex
176 *
177 * Returns : 0 for success
178 */
179static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
180{
181 u32 mfs;
182 u64 wwnn, wwpn;
183 struct fcoe_softc *fc;
184 u8 flogi_maddr[ETH_ALEN];
185
186 /* Setup lport private data to point to fcoe softc */
187 fc = lport_priv(lp);
Joe Eykholt97c83892009-03-17 11:42:40 -0700188 fc->ctlr.lp = lp;
Vasu Dev7f349142009-03-27 09:06:31 -0700189 fc->real_dev = netdev;
190 fc->phys_dev = netdev;
191
192 /* Require support for get_pauseparam ethtool op. */
193 if (netdev->priv_flags & IFF_802_1Q_VLAN)
194 fc->phys_dev = vlan_dev_real_dev(netdev);
195
196 /* Do not support for bonding device */
197 if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
198 (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
199 (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
200 return -EOPNOTSUPP;
201 }
202
203 /*
204 * Determine max frame size based on underlying device and optional
205 * user-configured limit. If the MFS is too low, fcoe_link_ok()
206 * will return 0, so do this first.
207 */
208 mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
209 sizeof(struct fcoe_crc_eof));
210 if (fc_set_mfs(lp, mfs))
211 return -EINVAL;
212
Vasu Dev7f349142009-03-27 09:06:31 -0700213 /* offload features support */
214 if (fc->real_dev->features & NETIF_F_SG)
215 lp->sg_supp = 1;
216
217#ifdef NETIF_F_FCOE_CRC
218 if (netdev->features & NETIF_F_FCOE_CRC) {
219 lp->crc_offload = 1;
220 printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n",
221 netdev->name);
222 }
223#endif
224#ifdef NETIF_F_FSO
225 if (netdev->features & NETIF_F_FSO) {
226 lp->seq_offload = 1;
227 lp->lso_max = netdev->gso_max_size;
228 printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n",
229 netdev->name, lp->lso_max);
230 }
231#endif
232 if (netdev->fcoe_ddp_xid) {
233 lp->lro_enabled = 1;
234 lp->lro_xid = netdev->fcoe_ddp_xid;
235 printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n",
236 netdev->name, lp->lro_xid);
237 }
238 skb_queue_head_init(&fc->fcoe_pending_queue);
239 fc->fcoe_pending_queue_active = 0;
240
241 /* setup Source Mac Address */
Joe Eykholt97c83892009-03-17 11:42:40 -0700242 memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr,
Vasu Dev7f349142009-03-27 09:06:31 -0700243 fc->real_dev->addr_len);
244
245 wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
246 fc_set_wwnn(lp, wwnn);
247 /* XXX - 3rd arg needs to be vlan id */
248 wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
249 fc_set_wwpn(lp, wwpn);
250
251 /*
252 * Add FCoE MAC address as second unicast MAC address
253 * or enter promiscuous mode if not capable of listening
254 * for multiple unicast MACs.
255 */
256 rtnl_lock();
257 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
258 dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
Joe Eykholt6401bdc2009-04-21 16:27:46 -0700259 dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
Vasu Dev7f349142009-03-27 09:06:31 -0700260 rtnl_unlock();
261
262 /*
263 * setup the receive function from ethernet driver
264 * on the ethertype for the given device
265 */
266 fc->fcoe_packet_type.func = fcoe_rcv;
267 fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
268 fc->fcoe_packet_type.dev = fc->real_dev;
269 dev_add_pack(&fc->fcoe_packet_type);
270
271 return 0;
272}
273
274/**
275 * fcoe_shost_config() - Sets up fc_lport->host
276 * @lp : ptr to the fc_lport
277 * @shost : ptr to the associated scsi host
278 * @dev : device associated to scsi host
279 *
280 * Must be called after fcoe_lport_config() and fcoe_netdev_config()
281 *
282 * Returns : 0 for success
283 */
284static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
285 struct device *dev)
286{
287 int rc = 0;
288
289 /* lport scsi host config */
290 lp->host = shost;
291
292 lp->host->max_lun = FCOE_MAX_LUN;
293 lp->host->max_id = FCOE_MAX_FCP_TARGET;
294 lp->host->max_channel = 0;
295 lp->host->transportt = scsi_transport_fcoe_sw;
296
297 /* add the new host to the SCSI-ml */
298 rc = scsi_add_host(lp->host, dev);
299 if (rc) {
300 FC_DBG("fcoe_shost_config:error on scsi_add_host\n");
301 return rc;
302 }
303 sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
304 FCOE_NAME, FCOE_VERSION,
305 fcoe_netdev(lp)->name);
306
307 return 0;
308}
309
310/**
311 * fcoe_em_config() - allocates em for this lport
312 * @lp: the port that em is to allocated for
313 *
314 * Returns : 0 on success
315 */
316static inline int fcoe_em_config(struct fc_lport *lp)
317{
318 BUG_ON(lp->emp);
319
320 lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
321 FCOE_MIN_XID, FCOE_MAX_XID);
322 if (!lp->emp)
323 return -ENOMEM;
324
325 return 0;
326}
327
328/**
329 * fcoe_if_destroy() - FCoE software HBA tear-down function
330 * @netdev: ptr to the associated net_device
331 *
332 * Returns: 0 if link is OK for use by FCoE.
333 */
334static int fcoe_if_destroy(struct net_device *netdev)
335{
336 struct fc_lport *lp = NULL;
337 struct fcoe_softc *fc;
338 u8 flogi_maddr[ETH_ALEN];
339
340 BUG_ON(!netdev);
341
342 printk(KERN_DEBUG "fcoe_if_destroy:interface on %s\n",
343 netdev->name);
344
345 lp = fcoe_hostlist_lookup(netdev);
346 if (!lp)
347 return -ENODEV;
348
349 fc = lport_priv(lp);
350
351 /* Logout of the fabric */
352 fc_fabric_logoff(lp);
353
354 /* Remove the instance from fcoe's list */
355 fcoe_hostlist_remove(lp);
356
357 /* Don't listen for Ethernet packets anymore */
358 dev_remove_pack(&fc->fcoe_packet_type);
Joe Eykholt97c83892009-03-17 11:42:40 -0700359 dev_remove_pack(&fc->fip_packet_type);
360 fcoe_ctlr_destroy(&fc->ctlr);
Vasu Dev7f349142009-03-27 09:06:31 -0700361
362 /* Cleanup the fc_lport */
363 fc_lport_destroy(lp);
364 fc_fcp_destroy(lp);
365
366 /* Detach from the scsi-ml */
367 fc_remove_host(lp->host);
368 scsi_remove_host(lp->host);
369
370 /* There are no more rports or I/O, free the EM */
371 if (lp->emp)
372 fc_exch_mgr_free(lp->emp);
373
374 /* Delete secondary MAC addresses */
375 rtnl_lock();
376 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
377 dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
Joe Eykholt97c83892009-03-17 11:42:40 -0700378 if (!is_zero_ether_addr(fc->ctlr.data_src_addr))
379 dev_unicast_delete(fc->real_dev,
380 fc->ctlr.data_src_addr, ETH_ALEN);
381 dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
Vasu Dev7f349142009-03-27 09:06:31 -0700382 rtnl_unlock();
383
Chris Leechdd3fd722009-04-21 16:27:36 -0700384 /* Free the per-CPU receive threads */
Vasu Dev7f349142009-03-27 09:06:31 -0700385 fcoe_percpu_clean(lp);
386
387 /* Free existing skbs */
388 fcoe_clean_pending_queue(lp);
389
390 /* Free memory used by statistical counters */
391 fc_lport_free_stats(lp);
392
393 /* Release the net_device and Scsi_Host */
394 dev_put(fc->real_dev);
395 scsi_host_put(lp->host);
396
397 return 0;
398}
399
400/*
401 * fcoe_ddp_setup - calls LLD's ddp_setup through net_device
402 * @lp: the corresponding fc_lport
403 * @xid: the exchange id for this ddp transfer
404 * @sgl: the scatterlist describing this transfer
405 * @sgc: number of sg items
406 *
407 * Returns : 0 no ddp
408 */
409static int fcoe_ddp_setup(struct fc_lport *lp, u16 xid,
410 struct scatterlist *sgl, unsigned int sgc)
411{
412 struct net_device *n = fcoe_netdev(lp);
413
414 if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup)
415 return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc);
416
417 return 0;
418}
419
420/*
421 * fcoe_ddp_done - calls LLD's ddp_done through net_device
422 * @lp: the corresponding fc_lport
423 * @xid: the exchange id for this ddp transfer
424 *
425 * Returns : the length of data that have been completed by ddp
426 */
427static int fcoe_ddp_done(struct fc_lport *lp, u16 xid)
428{
429 struct net_device *n = fcoe_netdev(lp);
430
431 if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done)
432 return n->netdev_ops->ndo_fcoe_ddp_done(n, xid);
433 return 0;
434}
435
436static struct libfc_function_template fcoe_libfc_fcn_templ = {
437 .frame_send = fcoe_xmit,
438 .ddp_setup = fcoe_ddp_setup,
439 .ddp_done = fcoe_ddp_done,
440};
441
442/**
Joe Eykholt97c83892009-03-17 11:42:40 -0700443 * fcoe_fip_recv - handle a received FIP frame.
444 * @skb: the receive skb
445 * @dev: associated &net_device
446 * @ptype: the &packet_type structure which was used to register this handler.
447 * @orig_dev: original receive &net_device, in case @dev is a bond.
448 *
449 * Returns: 0 for success
450 */
451static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
452 struct packet_type *ptype,
453 struct net_device *orig_dev)
454{
455 struct fcoe_softc *fc;
456
457 fc = container_of(ptype, struct fcoe_softc, fip_packet_type);
458 fcoe_ctlr_recv(&fc->ctlr, skb);
459 return 0;
460}
461
462/**
463 * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame.
464 * @fip: FCoE controller.
465 * @skb: FIP Packet.
466 */
467static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
468{
469 skb->dev = fcoe_from_ctlr(fip)->real_dev;
470 dev_queue_xmit(skb);
471}
472
473/**
474 * fcoe_update_src_mac() - Update Ethernet MAC filters.
475 * @fip: FCoE controller.
476 * @old: Unicast MAC address to delete if the MAC is non-zero.
477 * @new: Unicast MAC address to add.
478 *
479 * Remove any previously-set unicast MAC filter.
480 * Add secondary FCoE MAC address filter for our OUI.
481 */
482static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
483{
484 struct fcoe_softc *fc;
485
486 fc = fcoe_from_ctlr(fip);
487 rtnl_lock();
488 if (!is_zero_ether_addr(old))
489 dev_unicast_delete(fc->real_dev, old, ETH_ALEN);
490 dev_unicast_add(fc->real_dev, new, ETH_ALEN);
491 rtnl_unlock();
492}
493
494/**
Vasu Dev7f349142009-03-27 09:06:31 -0700495 * fcoe_if_create() - this function creates the fcoe interface
496 * @netdev: pointer the associated netdevice
497 *
498 * Creates fc_lport struct and scsi_host for lport, configures lport
499 * and starts fabric login.
500 *
501 * Returns : 0 on success
502 */
503static int fcoe_if_create(struct net_device *netdev)
504{
505 int rc;
506 struct fc_lport *lp = NULL;
507 struct fcoe_softc *fc;
508 struct Scsi_Host *shost;
509
510 BUG_ON(!netdev);
511
512 printk(KERN_DEBUG "fcoe_if_create:interface on %s\n",
513 netdev->name);
514
515 lp = fcoe_hostlist_lookup(netdev);
516 if (lp)
517 return -EEXIST;
518
Vasu Deva0a25da2009-03-17 11:42:29 -0700519 shost = libfc_host_alloc(&fcoe_shost_template,
520 sizeof(struct fcoe_softc));
Vasu Dev7f349142009-03-27 09:06:31 -0700521 if (!shost) {
522 FC_DBG("Could not allocate host structure\n");
523 return -ENOMEM;
524 }
525 lp = shost_priv(shost);
526 fc = lport_priv(lp);
527
528 /* configure fc_lport, e.g., em */
529 rc = fcoe_lport_config(lp);
530 if (rc) {
531 FC_DBG("Could not configure lport\n");
532 goto out_host_put;
533 }
534
535 /* configure lport network properties */
536 rc = fcoe_netdev_config(lp, netdev);
537 if (rc) {
538 FC_DBG("Could not configure netdev for lport\n");
539 goto out_host_put;
540 }
541
Joe Eykholt97c83892009-03-17 11:42:40 -0700542 /*
543 * Initialize FIP.
544 */
545 fcoe_ctlr_init(&fc->ctlr);
546 fc->ctlr.send = fcoe_fip_send;
547 fc->ctlr.update_mac = fcoe_update_src_mac;
548
549 fc->fip_packet_type.func = fcoe_fip_recv;
550 fc->fip_packet_type.type = htons(ETH_P_FIP);
551 fc->fip_packet_type.dev = fc->real_dev;
552 dev_add_pack(&fc->fip_packet_type);
553
Vasu Dev7f349142009-03-27 09:06:31 -0700554 /* configure lport scsi host properties */
555 rc = fcoe_shost_config(lp, shost, &netdev->dev);
556 if (rc) {
557 FC_DBG("Could not configure shost for lport\n");
558 goto out_host_put;
559 }
560
561 /* lport exch manager allocation */
562 rc = fcoe_em_config(lp);
563 if (rc) {
564 FC_DBG("Could not configure em for lport\n");
565 goto out_host_put;
566 }
567
568 /* Initialize the library */
569 rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
570 if (rc) {
571 FC_DBG("Could not configure libfc for lport!\n");
572 goto out_lp_destroy;
573 }
574
575 /* add to lports list */
576 fcoe_hostlist_add(lp);
577
578 lp->boot_time = jiffies;
579
580 fc_fabric_login(lp);
581
Joe Eykholt97c83892009-03-17 11:42:40 -0700582 if (!fcoe_link_ok(lp))
583 fcoe_ctlr_link_up(&fc->ctlr);
584
Vasu Dev7f349142009-03-27 09:06:31 -0700585 dev_hold(netdev);
586
587 return rc;
588
589out_lp_destroy:
590 fc_exch_mgr_free(lp->emp); /* Free the EM */
591out_host_put:
592 scsi_host_put(lp->host);
593 return rc;
594}
595
596/**
597 * fcoe_if_init() - attach to scsi transport
598 *
599 * Returns : 0 on success
600 */
601static int __init fcoe_if_init(void)
602{
603 /* attach to scsi transport */
604 scsi_transport_fcoe_sw =
605 fc_attach_transport(&fcoe_transport_function);
606
607 if (!scsi_transport_fcoe_sw) {
608 printk(KERN_ERR "fcoe_init:fc_attach_transport() failed\n");
609 return -ENODEV;
610 }
611
612 return 0;
613}
614
615/**
616 * fcoe_if_exit() - detach from scsi transport
617 *
618 * Returns : 0 on success
619 */
620int __exit fcoe_if_exit(void)
621{
622 fc_release_transport(scsi_transport_fcoe_sw);
623 return 0;
624}
625
Robert Love85b4aa42008-12-09 15:10:24 -0800626/**
Robert Love8976f422009-03-17 11:41:46 -0700627 * fcoe_percpu_thread_create() - Create a receive thread for an online cpu
628 * @cpu: cpu index for the online cpu
629 */
630static void fcoe_percpu_thread_create(unsigned int cpu)
631{
632 struct fcoe_percpu_s *p;
633 struct task_struct *thread;
634
635 p = &per_cpu(fcoe_percpu, cpu);
636
637 thread = kthread_create(fcoe_percpu_receive_thread,
638 (void *)p, "fcoethread/%d", cpu);
639
640 if (likely(!IS_ERR(p->thread))) {
641 kthread_bind(thread, cpu);
642 wake_up_process(thread);
643
644 spin_lock_bh(&p->fcoe_rx_list.lock);
645 p->thread = thread;
646 spin_unlock_bh(&p->fcoe_rx_list.lock);
647 }
648}
649
650/**
651 * fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu
652 * @cpu: cpu index the rx thread is to be removed
653 *
654 * Destroys a per-CPU Rx thread. Any pending skbs are moved to the
655 * current CPU's Rx thread. If the thread being destroyed is bound to
656 * the CPU processing this context the skbs will be freed.
657 */
658static void fcoe_percpu_thread_destroy(unsigned int cpu)
659{
660 struct fcoe_percpu_s *p;
661 struct task_struct *thread;
662 struct page *crc_eof;
663 struct sk_buff *skb;
664#ifdef CONFIG_SMP
665 struct fcoe_percpu_s *p0;
666 unsigned targ_cpu = smp_processor_id();
667#endif /* CONFIG_SMP */
668
669 printk(KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n", cpu);
670
671 /* Prevent any new skbs from being queued for this CPU. */
672 p = &per_cpu(fcoe_percpu, cpu);
673 spin_lock_bh(&p->fcoe_rx_list.lock);
674 thread = p->thread;
675 p->thread = NULL;
676 crc_eof = p->crc_eof_page;
677 p->crc_eof_page = NULL;
678 p->crc_eof_offset = 0;
679 spin_unlock_bh(&p->fcoe_rx_list.lock);
680
681#ifdef CONFIG_SMP
682 /*
683 * Don't bother moving the skb's if this context is running
684 * on the same CPU that is having its thread destroyed. This
685 * can easily happen when the module is removed.
686 */
687 if (cpu != targ_cpu) {
688 p0 = &per_cpu(fcoe_percpu, targ_cpu);
689 spin_lock_bh(&p0->fcoe_rx_list.lock);
690 if (p0->thread) {
691 FC_DBG("Moving frames from CPU %d to CPU %d\n",
692 cpu, targ_cpu);
693
694 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
695 __skb_queue_tail(&p0->fcoe_rx_list, skb);
696 spin_unlock_bh(&p0->fcoe_rx_list.lock);
697 } else {
698 /*
699 * The targeted CPU is not initialized and cannot accept
700 * new skbs. Unlock the targeted CPU and drop the skbs
701 * on the CPU that is going offline.
702 */
703 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
704 kfree_skb(skb);
705 spin_unlock_bh(&p0->fcoe_rx_list.lock);
706 }
707 } else {
708 /*
709 * This scenario occurs when the module is being removed
710 * and all threads are being destroyed. skbs will continue
711 * to be shifted from the CPU thread that is being removed
712 * to the CPU thread associated with the CPU that is processing
713 * the module removal. Once there is only one CPU Rx thread it
714 * will reach this case and we will drop all skbs and later
715 * stop the thread.
716 */
717 spin_lock_bh(&p->fcoe_rx_list.lock);
718 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
719 kfree_skb(skb);
720 spin_unlock_bh(&p->fcoe_rx_list.lock);
721 }
722#else
723 /*
Chris Leechdd3fd722009-04-21 16:27:36 -0700724 * This a non-SMP scenario where the singular Rx thread is
Robert Love8976f422009-03-17 11:41:46 -0700725 * being removed. Free all skbs and stop the thread.
726 */
727 spin_lock_bh(&p->fcoe_rx_list.lock);
728 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
729 kfree_skb(skb);
730 spin_unlock_bh(&p->fcoe_rx_list.lock);
731#endif
732
733 if (thread)
734 kthread_stop(thread);
735
736 if (crc_eof)
737 put_page(crc_eof);
738}
739
740/**
741 * fcoe_cpu_callback() - fcoe cpu hotplug event callback
742 * @nfb: callback data block
743 * @action: event triggering the callback
744 * @hcpu: index for the cpu of this event
745 *
746 * This creates or destroys per cpu data for fcoe
747 *
748 * Returns NOTIFY_OK always.
749 */
750static int fcoe_cpu_callback(struct notifier_block *nfb,
751 unsigned long action, void *hcpu)
752{
753 unsigned cpu = (unsigned long)hcpu;
754
755 switch (action) {
756 case CPU_ONLINE:
757 case CPU_ONLINE_FROZEN:
758 FC_DBG("CPU %x online: Create Rx thread\n", cpu);
759 fcoe_percpu_thread_create(cpu);
760 break;
761 case CPU_DEAD:
762 case CPU_DEAD_FROZEN:
763 FC_DBG("CPU %x offline: Remove Rx thread\n", cpu);
764 fcoe_percpu_thread_destroy(cpu);
765 break;
766 default:
767 break;
768 }
769 return NOTIFY_OK;
770}
771
772static struct notifier_block fcoe_cpu_notifier = {
773 .notifier_call = fcoe_cpu_callback,
774};
775
776/**
Robert Love34f42a02009-02-27 10:55:45 -0800777 * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ
Robert Love85b4aa42008-12-09 15:10:24 -0800778 * @skb: the receive skb
779 * @dev: associated net device
780 * @ptype: context
Chris Leechdd3fd722009-04-21 16:27:36 -0700781 * @olddev: last device
Robert Love85b4aa42008-12-09 15:10:24 -0800782 *
783 * this function will receive the packet and build fc frame and pass it up
784 *
785 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800786 */
Robert Love85b4aa42008-12-09 15:10:24 -0800787int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
788 struct packet_type *ptype, struct net_device *olddev)
789{
790 struct fc_lport *lp;
791 struct fcoe_rcv_info *fr;
792 struct fcoe_softc *fc;
Robert Love85b4aa42008-12-09 15:10:24 -0800793 struct fc_frame_header *fh;
Robert Love85b4aa42008-12-09 15:10:24 -0800794 struct fcoe_percpu_s *fps;
Robert Love38eccab2009-03-17 11:41:30 -0700795 unsigned short oxid;
Robert Love8976f422009-03-17 11:41:46 -0700796 unsigned int cpu = 0;
Robert Love85b4aa42008-12-09 15:10:24 -0800797
798 fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
Joe Eykholt97c83892009-03-17 11:42:40 -0700799 lp = fc->ctlr.lp;
Robert Love85b4aa42008-12-09 15:10:24 -0800800 if (unlikely(lp == NULL)) {
801 FC_DBG("cannot find hba structure");
802 goto err2;
803 }
Joe Eykholt97c83892009-03-17 11:42:40 -0700804 if (!lp->link_up)
805 goto err2;
Robert Love85b4aa42008-12-09 15:10:24 -0800806
807 if (unlikely(debug_fcoe)) {
808 FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p "
809 "end:%p sum:%d dev:%s", skb->len, skb->data_len,
810 skb->head, skb->data, skb_tail_pointer(skb),
811 skb_end_pointer(skb), skb->csum,
812 skb->dev ? skb->dev->name : "<NULL>");
813
814 }
815
816 /* check for FCOE packet type */
817 if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
818 FC_DBG("wrong FC type frame");
819 goto err;
820 }
821
822 /*
823 * Check for minimum frame length, and make sure required FCoE
824 * and FC headers are pulled into the linear data area.
825 */
826 if (unlikely((skb->len < FCOE_MIN_FRAME) ||
827 !pskb_may_pull(skb, FCOE_HEADER_LEN)))
828 goto err;
829
830 skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
831 fh = (struct fc_frame_header *) skb_transport_header(skb);
832
833 oxid = ntohs(fh->fh_ox_id);
834
835 fr = fcoe_dev_from_skb(skb);
836 fr->fr_dev = lp;
837 fr->ptype = ptype;
Robert Love5e5e92d2009-03-17 11:41:35 -0700838
Robert Love85b4aa42008-12-09 15:10:24 -0800839#ifdef CONFIG_SMP
840 /*
841 * The incoming frame exchange id(oxid) is ANDed with num of online
Robert Love8976f422009-03-17 11:41:46 -0700842 * cpu bits to get cpu and then this cpu is used for selecting
843 * a per cpu kernel thread from fcoe_percpu.
Robert Love85b4aa42008-12-09 15:10:24 -0800844 */
Robert Love8976f422009-03-17 11:41:46 -0700845 cpu = oxid & (num_online_cpus() - 1);
Robert Love85b4aa42008-12-09 15:10:24 -0800846#endif
Robert Love5e5e92d2009-03-17 11:41:35 -0700847
Robert Love8976f422009-03-17 11:41:46 -0700848 fps = &per_cpu(fcoe_percpu, cpu);
Robert Love85b4aa42008-12-09 15:10:24 -0800849 spin_lock_bh(&fps->fcoe_rx_list.lock);
Robert Love8976f422009-03-17 11:41:46 -0700850 if (unlikely(!fps->thread)) {
851 /*
852 * The targeted CPU is not ready, let's target
853 * the first CPU now. For non-SMP systems this
854 * will check the same CPU twice.
855 */
856 FC_DBG("CPU is online, but no receive thread ready "
857 "for incoming skb- using first online CPU.\n");
858
859 spin_unlock_bh(&fps->fcoe_rx_list.lock);
860 cpu = first_cpu(cpu_online_map);
861 fps = &per_cpu(fcoe_percpu, cpu);
862 spin_lock_bh(&fps->fcoe_rx_list.lock);
863 if (!fps->thread) {
864 spin_unlock_bh(&fps->fcoe_rx_list.lock);
865 goto err;
866 }
867 }
868
869 /*
870 * We now have a valid CPU that we're targeting for
871 * this skb. We also have this receive thread locked,
872 * so we're free to queue skbs into it's queue.
873 */
Robert Love85b4aa42008-12-09 15:10:24 -0800874 __skb_queue_tail(&fps->fcoe_rx_list, skb);
875 if (fps->fcoe_rx_list.qlen == 1)
876 wake_up_process(fps->thread);
877
878 spin_unlock_bh(&fps->fcoe_rx_list.lock);
879
880 return 0;
881err:
Robert Love582b45b2009-03-31 15:51:50 -0700882 fc_lport_get_stats(lp)->ErrorFrames++;
Robert Love85b4aa42008-12-09 15:10:24 -0800883
884err2:
885 kfree_skb(skb);
886 return -1;
887}
Robert Love85b4aa42008-12-09 15:10:24 -0800888
889/**
Robert Love34f42a02009-02-27 10:55:45 -0800890 * fcoe_start_io() - pass to netdev to start xmit for fcoe
Robert Love85b4aa42008-12-09 15:10:24 -0800891 * @skb: the skb to be xmitted
892 *
893 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800894 */
Robert Love85b4aa42008-12-09 15:10:24 -0800895static inline int fcoe_start_io(struct sk_buff *skb)
896{
897 int rc;
898
899 skb_get(skb);
900 rc = dev_queue_xmit(skb);
901 if (rc != 0)
902 return rc;
903 kfree_skb(skb);
904 return 0;
905}
906
907/**
Chris Leechdd3fd722009-04-21 16:27:36 -0700908 * fcoe_get_paged_crc_eof() - in case we need to alloc a page for crc_eof
Robert Love85b4aa42008-12-09 15:10:24 -0800909 * @skb: the skb to be xmitted
910 * @tlen: total len
911 *
912 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800913 */
Robert Love85b4aa42008-12-09 15:10:24 -0800914static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
915{
916 struct fcoe_percpu_s *fps;
917 struct page *page;
Robert Love85b4aa42008-12-09 15:10:24 -0800918
Robert Love5e5e92d2009-03-17 11:41:35 -0700919 fps = &get_cpu_var(fcoe_percpu);
Robert Love85b4aa42008-12-09 15:10:24 -0800920 page = fps->crc_eof_page;
921 if (!page) {
922 page = alloc_page(GFP_ATOMIC);
923 if (!page) {
Robert Love5e5e92d2009-03-17 11:41:35 -0700924 put_cpu_var(fcoe_percpu);
Robert Love85b4aa42008-12-09 15:10:24 -0800925 return -ENOMEM;
926 }
927 fps->crc_eof_page = page;
Robert Love8976f422009-03-17 11:41:46 -0700928 fps->crc_eof_offset = 0;
Robert Love85b4aa42008-12-09 15:10:24 -0800929 }
930
931 get_page(page);
932 skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
933 fps->crc_eof_offset, tlen);
934 skb->len += tlen;
935 skb->data_len += tlen;
936 skb->truesize += tlen;
937 fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
938
939 if (fps->crc_eof_offset >= PAGE_SIZE) {
940 fps->crc_eof_page = NULL;
941 fps->crc_eof_offset = 0;
942 put_page(page);
943 }
Robert Love5e5e92d2009-03-17 11:41:35 -0700944 put_cpu_var(fcoe_percpu);
Robert Love85b4aa42008-12-09 15:10:24 -0800945 return 0;
946}
947
948/**
Robert Love34f42a02009-02-27 10:55:45 -0800949 * fcoe_fc_crc() - calculates FC CRC in this fcoe skb
Chris Leechdd3fd722009-04-21 16:27:36 -0700950 * @fp: the fc_frame containing data to be checksummed
Robert Love85b4aa42008-12-09 15:10:24 -0800951 *
952 * This uses crc32() to calculate the crc for fc frame
953 * Return : 32 bit crc
Robert Love34f42a02009-02-27 10:55:45 -0800954 */
Robert Love85b4aa42008-12-09 15:10:24 -0800955u32 fcoe_fc_crc(struct fc_frame *fp)
956{
957 struct sk_buff *skb = fp_skb(fp);
958 struct skb_frag_struct *frag;
959 unsigned char *data;
960 unsigned long off, len, clen;
961 u32 crc;
962 unsigned i;
963
964 crc = crc32(~0, skb->data, skb_headlen(skb));
965
966 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
967 frag = &skb_shinfo(skb)->frags[i];
968 off = frag->page_offset;
969 len = frag->size;
970 while (len > 0) {
971 clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
972 data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
973 KM_SKB_DATA_SOFTIRQ);
974 crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
975 kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
976 off += clen;
977 len -= clen;
978 }
979 }
980 return crc;
981}
Robert Love85b4aa42008-12-09 15:10:24 -0800982
983/**
Robert Love34f42a02009-02-27 10:55:45 -0800984 * fcoe_xmit() - FCoE frame transmit function
Robert Love85b4aa42008-12-09 15:10:24 -0800985 * @lp: the associated local port
986 * @fp: the fc_frame to be transmitted
987 *
988 * Return : 0 for success
Robert Love34f42a02009-02-27 10:55:45 -0800989 */
Robert Love85b4aa42008-12-09 15:10:24 -0800990int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
991{
992 int wlen, rc = 0;
993 u32 crc;
994 struct ethhdr *eh;
995 struct fcoe_crc_eof *cp;
996 struct sk_buff *skb;
997 struct fcoe_dev_stats *stats;
998 struct fc_frame_header *fh;
999 unsigned int hlen; /* header length implies the version */
1000 unsigned int tlen; /* trailer length */
1001 unsigned int elen; /* eth header, may include vlan */
Robert Love85b4aa42008-12-09 15:10:24 -08001002 struct fcoe_softc *fc;
1003 u8 sof, eof;
1004 struct fcoe_hdr *hp;
1005
1006 WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
1007
Robert Lovefc47ff62009-02-27 10:55:55 -08001008 fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001009 fh = fc_frame_header_get(fp);
Joe Eykholt97c83892009-03-17 11:42:40 -07001010 skb = fp_skb(fp);
1011 wlen = skb->len / FCOE_WORD_TO_BYTE;
1012
1013 if (!lp->link_up) {
Dan Carpenter3caf02e2009-04-21 16:27:25 -07001014 kfree_skb(skb);
Joe Eykholt97c83892009-03-17 11:42:40 -07001015 return 0;
Robert Love85b4aa42008-12-09 15:10:24 -08001016 }
1017
Joe Eykholt97c83892009-03-17 11:42:40 -07001018 if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
1019 fcoe_ctlr_els_send(&fc->ctlr, skb))
1020 return 0;
1021
Robert Love85b4aa42008-12-09 15:10:24 -08001022 sof = fr_sof(fp);
1023 eof = fr_eof(fp);
1024
1025 elen = (fc->real_dev->priv_flags & IFF_802_1Q_VLAN) ?
1026 sizeof(struct vlan_ethhdr) : sizeof(struct ethhdr);
1027 hlen = sizeof(struct fcoe_hdr);
1028 tlen = sizeof(struct fcoe_crc_eof);
1029 wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE;
1030
1031 /* crc offload */
1032 if (likely(lp->crc_offload)) {
Yi Zou39ca9a02009-02-27 14:07:15 -08001033 skb->ip_summed = CHECKSUM_PARTIAL;
Robert Love85b4aa42008-12-09 15:10:24 -08001034 skb->csum_start = skb_headroom(skb);
1035 skb->csum_offset = skb->len;
1036 crc = 0;
1037 } else {
1038 skb->ip_summed = CHECKSUM_NONE;
1039 crc = fcoe_fc_crc(fp);
1040 }
1041
1042 /* copy fc crc and eof to the skb buff */
1043 if (skb_is_nonlinear(skb)) {
1044 skb_frag_t *frag;
1045 if (fcoe_get_paged_crc_eof(skb, tlen)) {
Roel Kluine9041582009-02-27 10:56:22 -08001046 kfree_skb(skb);
Robert Love85b4aa42008-12-09 15:10:24 -08001047 return -ENOMEM;
1048 }
1049 frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
1050 cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
1051 + frag->page_offset;
1052 } else {
1053 cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
1054 }
1055
1056 memset(cp, 0, sizeof(*cp));
1057 cp->fcoe_eof = eof;
1058 cp->fcoe_crc32 = cpu_to_le32(~crc);
1059
1060 if (skb_is_nonlinear(skb)) {
1061 kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
1062 cp = NULL;
1063 }
1064
Chris Leechdd3fd722009-04-21 16:27:36 -07001065 /* adjust skb network/transport offsets to match mac/fcoe/fc */
Robert Love85b4aa42008-12-09 15:10:24 -08001066 skb_push(skb, elen + hlen);
1067 skb_reset_mac_header(skb);
1068 skb_reset_network_header(skb);
1069 skb->mac_len = elen;
Yi Zou211c7382009-02-27 14:06:37 -08001070 skb->protocol = htons(ETH_P_FCOE);
Robert Love85b4aa42008-12-09 15:10:24 -08001071 skb->dev = fc->real_dev;
1072
1073 /* fill up mac and fcoe headers */
1074 eh = eth_hdr(skb);
1075 eh->h_proto = htons(ETH_P_FCOE);
Joe Eykholt97c83892009-03-17 11:42:40 -07001076 if (fc->ctlr.map_dest)
Robert Love85b4aa42008-12-09 15:10:24 -08001077 fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
1078 else
1079 /* insert GW address */
Joe Eykholt97c83892009-03-17 11:42:40 -07001080 memcpy(eh->h_dest, fc->ctlr.dest_addr, ETH_ALEN);
Robert Love85b4aa42008-12-09 15:10:24 -08001081
Joe Eykholt97c83892009-03-17 11:42:40 -07001082 if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN))
1083 memcpy(eh->h_source, fc->ctlr.ctl_src_addr, ETH_ALEN);
Robert Love85b4aa42008-12-09 15:10:24 -08001084 else
Joe Eykholt97c83892009-03-17 11:42:40 -07001085 memcpy(eh->h_source, fc->ctlr.data_src_addr, ETH_ALEN);
Robert Love85b4aa42008-12-09 15:10:24 -08001086
1087 hp = (struct fcoe_hdr *)(eh + 1);
1088 memset(hp, 0, sizeof(*hp));
1089 if (FC_FCOE_VER)
1090 FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
1091 hp->fcoe_sof = sof;
1092
Yi Zou39ca9a02009-02-27 14:07:15 -08001093#ifdef NETIF_F_FSO
1094 /* fcoe lso, mss is in max_payload which is non-zero for FCP data */
1095 if (lp->seq_offload && fr_max_payload(fp)) {
1096 skb_shinfo(skb)->gso_type = SKB_GSO_FCOE;
1097 skb_shinfo(skb)->gso_size = fr_max_payload(fp);
1098 } else {
1099 skb_shinfo(skb)->gso_type = 0;
1100 skb_shinfo(skb)->gso_size = 0;
1101 }
1102#endif
Robert Love85b4aa42008-12-09 15:10:24 -08001103 /* update tx stats: regardless if LLD fails */
Robert Love582b45b2009-03-31 15:51:50 -07001104 stats = fc_lport_get_stats(lp);
1105 stats->TxFrames++;
1106 stats->TxWords += wlen;
Robert Love85b4aa42008-12-09 15:10:24 -08001107
1108 /* send down to lld */
1109 fr_dev(fp) = lp;
1110 if (fc->fcoe_pending_queue.qlen)
1111 rc = fcoe_check_wait_queue(lp);
1112
1113 if (rc == 0)
1114 rc = fcoe_start_io(skb);
1115
1116 if (rc) {
Chris Leech55c8baf2009-02-27 10:56:32 -08001117 spin_lock_bh(&fc->fcoe_pending_queue.lock);
1118 __skb_queue_tail(&fc->fcoe_pending_queue, skb);
1119 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
Robert Love85b4aa42008-12-09 15:10:24 -08001120 if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
Vasu Devbc0e17f2009-02-27 10:54:57 -08001121 lp->qfull = 1;
Robert Love85b4aa42008-12-09 15:10:24 -08001122 }
1123
1124 return 0;
1125}
Robert Love85b4aa42008-12-09 15:10:24 -08001126
Robert Love34f42a02009-02-27 10:55:45 -08001127/**
1128 * fcoe_percpu_receive_thread() - recv thread per cpu
Robert Love85b4aa42008-12-09 15:10:24 -08001129 * @arg: ptr to the fcoe per cpu struct
1130 *
1131 * Return: 0 for success
Robert Love85b4aa42008-12-09 15:10:24 -08001132 */
1133int fcoe_percpu_receive_thread(void *arg)
1134{
1135 struct fcoe_percpu_s *p = arg;
1136 u32 fr_len;
1137 struct fc_lport *lp;
1138 struct fcoe_rcv_info *fr;
1139 struct fcoe_dev_stats *stats;
1140 struct fc_frame_header *fh;
1141 struct sk_buff *skb;
1142 struct fcoe_crc_eof crc_eof;
1143 struct fc_frame *fp;
1144 u8 *mac = NULL;
1145 struct fcoe_softc *fc;
1146 struct fcoe_hdr *hp;
1147
Robert Love4469c192009-02-27 10:56:38 -08001148 set_user_nice(current, -20);
Robert Love85b4aa42008-12-09 15:10:24 -08001149
1150 while (!kthread_should_stop()) {
1151
1152 spin_lock_bh(&p->fcoe_rx_list.lock);
1153 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) == NULL) {
1154 set_current_state(TASK_INTERRUPTIBLE);
1155 spin_unlock_bh(&p->fcoe_rx_list.lock);
1156 schedule();
1157 set_current_state(TASK_RUNNING);
1158 if (kthread_should_stop())
1159 return 0;
1160 spin_lock_bh(&p->fcoe_rx_list.lock);
1161 }
1162 spin_unlock_bh(&p->fcoe_rx_list.lock);
1163 fr = fcoe_dev_from_skb(skb);
1164 lp = fr->fr_dev;
1165 if (unlikely(lp == NULL)) {
1166 FC_DBG("invalid HBA Structure");
1167 kfree_skb(skb);
1168 continue;
1169 }
1170
Robert Love85b4aa42008-12-09 15:10:24 -08001171 if (unlikely(debug_fcoe)) {
1172 FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p "
1173 "tail:%p end:%p sum:%d dev:%s",
1174 skb->len, skb->data_len,
1175 skb->head, skb->data, skb_tail_pointer(skb),
1176 skb_end_pointer(skb), skb->csum,
1177 skb->dev ? skb->dev->name : "<NULL>");
1178 }
1179
1180 /*
1181 * Save source MAC address before discarding header.
1182 */
1183 fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001184 if (skb_is_nonlinear(skb))
1185 skb_linearize(skb); /* not ideal */
Joe Eykholt97c83892009-03-17 11:42:40 -07001186 mac = eth_hdr(skb)->h_source;
Robert Love85b4aa42008-12-09 15:10:24 -08001187
1188 /*
1189 * Frame length checks and setting up the header pointers
1190 * was done in fcoe_rcv already.
1191 */
1192 hp = (struct fcoe_hdr *) skb_network_header(skb);
1193 fh = (struct fc_frame_header *) skb_transport_header(skb);
1194
Robert Love582b45b2009-03-31 15:51:50 -07001195 stats = fc_lport_get_stats(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001196 if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
Robert Love582b45b2009-03-31 15:51:50 -07001197 if (stats->ErrorFrames < 5)
1198 printk(KERN_WARNING "FCoE version "
1199 "mismatch: The frame has "
1200 "version %x, but the "
1201 "initiator supports version "
1202 "%x\n", FC_FCOE_DECAPS_VER(hp),
1203 FC_FCOE_VER);
1204 stats->ErrorFrames++;
Robert Love85b4aa42008-12-09 15:10:24 -08001205 kfree_skb(skb);
1206 continue;
1207 }
1208
1209 skb_pull(skb, sizeof(struct fcoe_hdr));
1210 fr_len = skb->len - sizeof(struct fcoe_crc_eof);
1211
Robert Love582b45b2009-03-31 15:51:50 -07001212 stats->RxFrames++;
1213 stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
Robert Love85b4aa42008-12-09 15:10:24 -08001214
1215 fp = (struct fc_frame *)skb;
1216 fc_frame_init(fp);
1217 fr_dev(fp) = lp;
1218 fr_sof(fp) = hp->fcoe_sof;
1219
1220 /* Copy out the CRC and EOF trailer for access */
1221 if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
1222 kfree_skb(skb);
1223 continue;
1224 }
1225 fr_eof(fp) = crc_eof.fcoe_eof;
1226 fr_crc(fp) = crc_eof.fcoe_crc32;
1227 if (pskb_trim(skb, fr_len)) {
1228 kfree_skb(skb);
1229 continue;
1230 }
1231
1232 /*
1233 * We only check CRC if no offload is available and if it is
1234 * it's solicited data, in which case, the FCP layer would
1235 * check it during the copy.
1236 */
Yi Zou07c00ec2009-02-27 14:07:31 -08001237 if (lp->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY)
Robert Love85b4aa42008-12-09 15:10:24 -08001238 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1239 else
1240 fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
1241
1242 fh = fc_frame_header_get(fp);
1243 if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
1244 fh->fh_type == FC_TYPE_FCP) {
1245 fc_exch_recv(lp, lp->emp, fp);
1246 continue;
1247 }
1248 if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
1249 if (le32_to_cpu(fr_crc(fp)) !=
1250 ~crc32(~0, skb->data, fr_len)) {
1251 if (debug_fcoe || stats->InvalidCRCCount < 5)
1252 printk(KERN_WARNING "fcoe: dropping "
1253 "frame with CRC error\n");
1254 stats->InvalidCRCCount++;
1255 stats->ErrorFrames++;
1256 fc_frame_free(fp);
1257 continue;
1258 }
1259 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1260 }
Joe Eykholt97c83892009-03-17 11:42:40 -07001261 if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN) &&
1262 fcoe_ctlr_recv_flogi(&fc->ctlr, fp, mac)) {
1263 fc_frame_free(fp);
1264 continue;
1265 }
Robert Love85b4aa42008-12-09 15:10:24 -08001266 fc_exch_recv(lp, lp->emp, fp);
1267 }
1268 return 0;
1269}
1270
1271/**
Robert Love34f42a02009-02-27 10:55:45 -08001272 * fcoe_watchdog() - fcoe timer callback
Robert Love85b4aa42008-12-09 15:10:24 -08001273 * @vp:
1274 *
Vasu Devbc0e17f2009-02-27 10:54:57 -08001275 * This checks the pending queue length for fcoe and set lport qfull
Robert Love85b4aa42008-12-09 15:10:24 -08001276 * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the
1277 * fcoe_hostlist.
1278 *
1279 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001280 */
Robert Love85b4aa42008-12-09 15:10:24 -08001281void fcoe_watchdog(ulong vp)
1282{
Robert Love85b4aa42008-12-09 15:10:24 -08001283 struct fcoe_softc *fc;
Robert Love85b4aa42008-12-09 15:10:24 -08001284
1285 read_lock(&fcoe_hostlist_lock);
1286 list_for_each_entry(fc, &fcoe_hostlist, list) {
Joe Eykholt97c83892009-03-17 11:42:40 -07001287 if (fc->ctlr.lp)
1288 fcoe_check_wait_queue(fc->ctlr.lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001289 }
1290 read_unlock(&fcoe_hostlist_lock);
1291
1292 fcoe_timer.expires = jiffies + (1 * HZ);
1293 add_timer(&fcoe_timer);
1294}
1295
1296
1297/**
Chris Leechdd3fd722009-04-21 16:27:36 -07001298 * fcoe_check_wait_queue() - attempt to clear the transmit backlog
1299 * @lp: the fc_lport
Robert Love85b4aa42008-12-09 15:10:24 -08001300 *
1301 * This empties the wait_queue, dequeue the head of the wait_queue queue
1302 * and calls fcoe_start_io() for each packet, if all skb have been
Vasu Devc826a312009-02-27 10:56:27 -08001303 * transmitted, return qlen or -1 if a error occurs, then restore
Chris Leechdd3fd722009-04-21 16:27:36 -07001304 * wait_queue and try again later.
Robert Love85b4aa42008-12-09 15:10:24 -08001305 *
1306 * The wait_queue is used when the skb transmit fails. skb will go
Chris Leechdd3fd722009-04-21 16:27:36 -07001307 * in the wait_queue which will be emptied by the timer function or
Robert Love85b4aa42008-12-09 15:10:24 -08001308 * by the next skb transmit.
1309 *
1310 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001311 */
Robert Love85b4aa42008-12-09 15:10:24 -08001312static int fcoe_check_wait_queue(struct fc_lport *lp)
1313{
Chris Leech55c8baf2009-02-27 10:56:32 -08001314 struct fcoe_softc *fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001315 struct sk_buff *skb;
Vasu Devc826a312009-02-27 10:56:27 -08001316 int rc = -1;
Robert Love85b4aa42008-12-09 15:10:24 -08001317
Robert Love85b4aa42008-12-09 15:10:24 -08001318 spin_lock_bh(&fc->fcoe_pending_queue.lock);
Vasu Devc826a312009-02-27 10:56:27 -08001319 if (fc->fcoe_pending_queue_active)
1320 goto out;
1321 fc->fcoe_pending_queue_active = 1;
Chris Leech55c8baf2009-02-27 10:56:32 -08001322
1323 while (fc->fcoe_pending_queue.qlen) {
1324 /* keep qlen > 0 until fcoe_start_io succeeds */
1325 fc->fcoe_pending_queue.qlen++;
1326 skb = __skb_dequeue(&fc->fcoe_pending_queue);
1327
1328 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
1329 rc = fcoe_start_io(skb);
1330 spin_lock_bh(&fc->fcoe_pending_queue.lock);
1331
1332 if (rc) {
1333 __skb_queue_head(&fc->fcoe_pending_queue, skb);
1334 /* undo temporary increment above */
1335 fc->fcoe_pending_queue.qlen--;
1336 break;
Robert Love85b4aa42008-12-09 15:10:24 -08001337 }
Chris Leech55c8baf2009-02-27 10:56:32 -08001338 /* undo temporary increment above */
1339 fc->fcoe_pending_queue.qlen--;
Robert Love85b4aa42008-12-09 15:10:24 -08001340 }
Chris Leech55c8baf2009-02-27 10:56:32 -08001341
1342 if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
1343 lp->qfull = 0;
Vasu Devc826a312009-02-27 10:56:27 -08001344 fc->fcoe_pending_queue_active = 0;
1345 rc = fc->fcoe_pending_queue.qlen;
1346out:
Robert Love85b4aa42008-12-09 15:10:24 -08001347 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
Vasu Devc826a312009-02-27 10:56:27 -08001348 return rc;
Robert Love85b4aa42008-12-09 15:10:24 -08001349}
1350
1351/**
Robert Love34f42a02009-02-27 10:55:45 -08001352 * fcoe_dev_setup() - setup link change notification interface
1353 */
Randy Dunlapb0d428a2009-04-27 21:49:31 -07001354static void fcoe_dev_setup(void)
Robert Love85b4aa42008-12-09 15:10:24 -08001355{
Robert Love85b4aa42008-12-09 15:10:24 -08001356 register_netdevice_notifier(&fcoe_notifier);
1357}
1358
1359/**
Randy Dunlapb0d428a2009-04-27 21:49:31 -07001360 * fcoe_dev_cleanup() - cleanup link change notification interface
Robert Love34f42a02009-02-27 10:55:45 -08001361 */
Robert Love85b4aa42008-12-09 15:10:24 -08001362static void fcoe_dev_cleanup(void)
1363{
1364 unregister_netdevice_notifier(&fcoe_notifier);
1365}
1366
1367/**
Robert Love34f42a02009-02-27 10:55:45 -08001368 * fcoe_device_notification() - netdev event notification callback
Robert Love85b4aa42008-12-09 15:10:24 -08001369 * @notifier: context of the notification
1370 * @event: type of event
1371 * @ptr: fixed array for output parsed ifname
1372 *
1373 * This function is called by the ethernet driver in case of link change event
1374 *
1375 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001376 */
Robert Love85b4aa42008-12-09 15:10:24 -08001377static int fcoe_device_notification(struct notifier_block *notifier,
1378 ulong event, void *ptr)
1379{
1380 struct fc_lport *lp = NULL;
1381 struct net_device *real_dev = ptr;
1382 struct fcoe_softc *fc;
1383 struct fcoe_dev_stats *stats;
Joe Eykholt97c83892009-03-17 11:42:40 -07001384 u32 link_possible = 1;
Robert Love85b4aa42008-12-09 15:10:24 -08001385 u32 mfs;
1386 int rc = NOTIFY_OK;
1387
1388 read_lock(&fcoe_hostlist_lock);
1389 list_for_each_entry(fc, &fcoe_hostlist, list) {
1390 if (fc->real_dev == real_dev) {
Joe Eykholt97c83892009-03-17 11:42:40 -07001391 lp = fc->ctlr.lp;
Robert Love85b4aa42008-12-09 15:10:24 -08001392 break;
1393 }
1394 }
1395 read_unlock(&fcoe_hostlist_lock);
1396 if (lp == NULL) {
1397 rc = NOTIFY_DONE;
1398 goto out;
1399 }
1400
Robert Love85b4aa42008-12-09 15:10:24 -08001401 switch (event) {
1402 case NETDEV_DOWN:
1403 case NETDEV_GOING_DOWN:
Joe Eykholt97c83892009-03-17 11:42:40 -07001404 link_possible = 0;
Robert Love85b4aa42008-12-09 15:10:24 -08001405 break;
1406 case NETDEV_UP:
1407 case NETDEV_CHANGE:
Robert Love85b4aa42008-12-09 15:10:24 -08001408 break;
1409 case NETDEV_CHANGEMTU:
1410 mfs = fc->real_dev->mtu -
1411 (sizeof(struct fcoe_hdr) +
1412 sizeof(struct fcoe_crc_eof));
1413 if (mfs >= FC_MIN_MAX_FRAME)
1414 fc_set_mfs(lp, mfs);
Robert Love85b4aa42008-12-09 15:10:24 -08001415 break;
1416 case NETDEV_REGISTER:
1417 break;
1418 default:
Joe Eykholt97c83892009-03-17 11:42:40 -07001419 FC_DBG("Unknown event %ld from netdev netlink\n", event);
Robert Love85b4aa42008-12-09 15:10:24 -08001420 }
Joe Eykholt97c83892009-03-17 11:42:40 -07001421 if (link_possible && !fcoe_link_ok(lp))
1422 fcoe_ctlr_link_up(&fc->ctlr);
1423 else if (fcoe_ctlr_link_down(&fc->ctlr)) {
1424 stats = fc_lport_get_stats(lp);
1425 stats->LinkFailureCount++;
1426 fcoe_clean_pending_queue(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001427 }
1428out:
1429 return rc;
1430}
1431
1432/**
Robert Love34f42a02009-02-27 10:55:45 -08001433 * fcoe_if_to_netdev() - parse a name buffer to get netdev
Robert Love85b4aa42008-12-09 15:10:24 -08001434 * @buffer: incoming buffer to be copied
1435 *
Chris Leechdd3fd722009-04-21 16:27:36 -07001436 * Returns: NULL or ptr to net_device
Robert Love34f42a02009-02-27 10:55:45 -08001437 */
Robert Love85b4aa42008-12-09 15:10:24 -08001438static struct net_device *fcoe_if_to_netdev(const char *buffer)
1439{
1440 char *cp;
1441 char ifname[IFNAMSIZ + 2];
1442
1443 if (buffer) {
1444 strlcpy(ifname, buffer, IFNAMSIZ);
1445 cp = ifname + strlen(ifname);
1446 while (--cp >= ifname && *cp == '\n')
1447 *cp = '\0';
1448 return dev_get_by_name(&init_net, ifname);
1449 }
1450 return NULL;
1451}
1452
1453/**
Chris Leechdd3fd722009-04-21 16:27:36 -07001454 * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev
Robert Love85b4aa42008-12-09 15:10:24 -08001455 * @netdev: the target netdev
1456 *
1457 * Returns: ptr to the struct module, NULL for failure
Robert Love34f42a02009-02-27 10:55:45 -08001458 */
Robert Loveb2ab99c2009-02-27 10:55:50 -08001459static struct module *
1460fcoe_netdev_to_module_owner(const struct net_device *netdev)
Robert Love85b4aa42008-12-09 15:10:24 -08001461{
1462 struct device *dev;
1463
1464 if (!netdev)
1465 return NULL;
1466
1467 dev = netdev->dev.parent;
1468 if (!dev)
1469 return NULL;
1470
1471 if (!dev->driver)
1472 return NULL;
1473
1474 return dev->driver->owner;
1475}
1476
1477/**
Robert Love34f42a02009-02-27 10:55:45 -08001478 * fcoe_ethdrv_get() - Hold the Ethernet driver
Robert Love85b4aa42008-12-09 15:10:24 -08001479 * @netdev: the target netdev
1480 *
Robert Love34f42a02009-02-27 10:55:45 -08001481 * Holds the Ethernet driver module by try_module_get() for
1482 * the corresponding netdev.
1483 *
Chris Leechdd3fd722009-04-21 16:27:36 -07001484 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001485 */
Robert Love85b4aa42008-12-09 15:10:24 -08001486static int fcoe_ethdrv_get(const struct net_device *netdev)
1487{
1488 struct module *owner;
1489
1490 owner = fcoe_netdev_to_module_owner(netdev);
1491 if (owner) {
James Bottomley56b854b2008-12-29 15:45:41 -06001492 printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n",
1493 module_name(owner), netdev->name);
Robert Love85b4aa42008-12-09 15:10:24 -08001494 return try_module_get(owner);
1495 }
1496 return -ENODEV;
1497}
1498
1499/**
Robert Love34f42a02009-02-27 10:55:45 -08001500 * fcoe_ethdrv_put() - Release the Ethernet driver
Robert Love85b4aa42008-12-09 15:10:24 -08001501 * @netdev: the target netdev
1502 *
Robert Love34f42a02009-02-27 10:55:45 -08001503 * Releases the Ethernet driver module by module_put for
1504 * the corresponding netdev.
1505 *
Chris Leechdd3fd722009-04-21 16:27:36 -07001506 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001507 */
Robert Love85b4aa42008-12-09 15:10:24 -08001508static int fcoe_ethdrv_put(const struct net_device *netdev)
1509{
1510 struct module *owner;
1511
1512 owner = fcoe_netdev_to_module_owner(netdev);
1513 if (owner) {
James Bottomley56b854b2008-12-29 15:45:41 -06001514 printk(KERN_DEBUG "fcoe:release driver module %s for %s\n",
1515 module_name(owner), netdev->name);
Robert Love85b4aa42008-12-09 15:10:24 -08001516 module_put(owner);
1517 return 0;
1518 }
1519 return -ENODEV;
1520}
1521
1522/**
Robert Love34f42a02009-02-27 10:55:45 -08001523 * fcoe_destroy() - handles the destroy from sysfs
Chris Leechdd3fd722009-04-21 16:27:36 -07001524 * @buffer: expected to be an eth if name
Robert Love85b4aa42008-12-09 15:10:24 -08001525 * @kp: associated kernel param
1526 *
1527 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001528 */
Robert Love85b4aa42008-12-09 15:10:24 -08001529static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
1530{
1531 int rc;
1532 struct net_device *netdev;
1533
1534 netdev = fcoe_if_to_netdev(buffer);
1535 if (!netdev) {
1536 rc = -ENODEV;
1537 goto out_nodev;
1538 }
1539 /* look for existing lport */
1540 if (!fcoe_hostlist_lookup(netdev)) {
1541 rc = -ENODEV;
1542 goto out_putdev;
1543 }
Vasu Dev7f349142009-03-27 09:06:31 -07001544 rc = fcoe_if_destroy(netdev);
Robert Love85b4aa42008-12-09 15:10:24 -08001545 if (rc) {
Vasu Dev7f349142009-03-27 09:06:31 -07001546 printk(KERN_ERR "fcoe: fcoe_if_destroy(%s) failed\n",
Robert Love85b4aa42008-12-09 15:10:24 -08001547 netdev->name);
1548 rc = -EIO;
1549 goto out_putdev;
1550 }
1551 fcoe_ethdrv_put(netdev);
1552 rc = 0;
1553out_putdev:
1554 dev_put(netdev);
1555out_nodev:
1556 return rc;
1557}
1558
1559/**
Robert Love34f42a02009-02-27 10:55:45 -08001560 * fcoe_create() - Handles the create call from sysfs
Chris Leechdd3fd722009-04-21 16:27:36 -07001561 * @buffer: expected to be an eth if name
Robert Love85b4aa42008-12-09 15:10:24 -08001562 * @kp: associated kernel param
1563 *
1564 * Returns: 0 for success
Robert Love34f42a02009-02-27 10:55:45 -08001565 */
Robert Love85b4aa42008-12-09 15:10:24 -08001566static int fcoe_create(const char *buffer, struct kernel_param *kp)
1567{
1568 int rc;
1569 struct net_device *netdev;
1570
1571 netdev = fcoe_if_to_netdev(buffer);
1572 if (!netdev) {
1573 rc = -ENODEV;
1574 goto out_nodev;
1575 }
1576 /* look for existing lport */
1577 if (fcoe_hostlist_lookup(netdev)) {
1578 rc = -EEXIST;
1579 goto out_putdev;
1580 }
1581 fcoe_ethdrv_get(netdev);
1582
Vasu Dev7f349142009-03-27 09:06:31 -07001583 rc = fcoe_if_create(netdev);
Robert Love85b4aa42008-12-09 15:10:24 -08001584 if (rc) {
Vasu Dev7f349142009-03-27 09:06:31 -07001585 printk(KERN_ERR "fcoe: fcoe_if_create(%s) failed\n",
Robert Love85b4aa42008-12-09 15:10:24 -08001586 netdev->name);
1587 fcoe_ethdrv_put(netdev);
1588 rc = -EIO;
1589 goto out_putdev;
1590 }
1591 rc = 0;
1592out_putdev:
1593 dev_put(netdev);
1594out_nodev:
1595 return rc;
1596}
1597
1598module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
1599__MODULE_PARM_TYPE(create, "string");
1600MODULE_PARM_DESC(create, "Create fcoe port using net device passed in.");
1601module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
1602__MODULE_PARM_TYPE(destroy, "string");
1603MODULE_PARM_DESC(destroy, "Destroy fcoe port");
1604
Robert Love34f42a02009-02-27 10:55:45 -08001605/**
1606 * fcoe_link_ok() - Check if link is ok for the fc_lport
Robert Love85b4aa42008-12-09 15:10:24 -08001607 * @lp: ptr to the fc_lport
1608 *
1609 * Any permanently-disqualifying conditions have been previously checked.
1610 * This also updates the speed setting, which may change with link for 100/1000.
1611 *
1612 * This function should probably be checking for PAUSE support at some point
1613 * in the future. Currently Per-priority-pause is not determinable using
1614 * ethtool, so we shouldn't be restrictive until that problem is resolved.
1615 *
1616 * Returns: 0 if link is OK for use by FCoE.
1617 *
1618 */
1619int fcoe_link_ok(struct fc_lport *lp)
1620{
Robert Lovefc47ff62009-02-27 10:55:55 -08001621 struct fcoe_softc *fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001622 struct net_device *dev = fc->real_dev;
1623 struct ethtool_cmd ecmd = { ETHTOOL_GSET };
1624 int rc = 0;
1625
1626 if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) {
1627 dev = fc->phys_dev;
1628 if (dev->ethtool_ops->get_settings) {
1629 dev->ethtool_ops->get_settings(dev, &ecmd);
1630 lp->link_supported_speeds &=
1631 ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
1632 if (ecmd.supported & (SUPPORTED_1000baseT_Half |
1633 SUPPORTED_1000baseT_Full))
1634 lp->link_supported_speeds |= FC_PORTSPEED_1GBIT;
1635 if (ecmd.supported & SUPPORTED_10000baseT_Full)
1636 lp->link_supported_speeds |=
1637 FC_PORTSPEED_10GBIT;
1638 if (ecmd.speed == SPEED_1000)
1639 lp->link_speed = FC_PORTSPEED_1GBIT;
1640 if (ecmd.speed == SPEED_10000)
1641 lp->link_speed = FC_PORTSPEED_10GBIT;
1642 }
1643 } else
1644 rc = -1;
1645
1646 return rc;
1647}
Robert Love85b4aa42008-12-09 15:10:24 -08001648
Robert Love34f42a02009-02-27 10:55:45 -08001649/**
1650 * fcoe_percpu_clean() - Clear the pending skbs for an lport
Robert Love85b4aa42008-12-09 15:10:24 -08001651 * @lp: the fc_lport
1652 */
1653void fcoe_percpu_clean(struct fc_lport *lp)
1654{
Robert Love85b4aa42008-12-09 15:10:24 -08001655 struct fcoe_percpu_s *pp;
1656 struct fcoe_rcv_info *fr;
1657 struct sk_buff_head *list;
1658 struct sk_buff *skb, *next;
1659 struct sk_buff *head;
Robert Love5e5e92d2009-03-17 11:41:35 -07001660 unsigned int cpu;
Robert Love85b4aa42008-12-09 15:10:24 -08001661
Robert Love5e5e92d2009-03-17 11:41:35 -07001662 for_each_possible_cpu(cpu) {
1663 pp = &per_cpu(fcoe_percpu, cpu);
1664 spin_lock_bh(&pp->fcoe_rx_list.lock);
1665 list = &pp->fcoe_rx_list;
1666 head = list->next;
1667 for (skb = head; skb != (struct sk_buff *)list;
1668 skb = next) {
1669 next = skb->next;
1670 fr = fcoe_dev_from_skb(skb);
1671 if (fr->fr_dev == lp) {
1672 __skb_unlink(skb, list);
1673 kfree_skb(skb);
Robert Love85b4aa42008-12-09 15:10:24 -08001674 }
Robert Love85b4aa42008-12-09 15:10:24 -08001675 }
Robert Love5e5e92d2009-03-17 11:41:35 -07001676 spin_unlock_bh(&pp->fcoe_rx_list.lock);
Robert Love85b4aa42008-12-09 15:10:24 -08001677 }
1678}
Robert Love85b4aa42008-12-09 15:10:24 -08001679
1680/**
Robert Love34f42a02009-02-27 10:55:45 -08001681 * fcoe_clean_pending_queue() - Dequeue a skb and free it
Robert Love85b4aa42008-12-09 15:10:24 -08001682 * @lp: the corresponding fc_lport
1683 *
1684 * Returns: none
Robert Love34f42a02009-02-27 10:55:45 -08001685 */
Robert Love85b4aa42008-12-09 15:10:24 -08001686void fcoe_clean_pending_queue(struct fc_lport *lp)
1687{
1688 struct fcoe_softc *fc = lport_priv(lp);
1689 struct sk_buff *skb;
1690
1691 spin_lock_bh(&fc->fcoe_pending_queue.lock);
1692 while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
1693 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
1694 kfree_skb(skb);
1695 spin_lock_bh(&fc->fcoe_pending_queue.lock);
1696 }
1697 spin_unlock_bh(&fc->fcoe_pending_queue.lock);
1698}
Robert Love85b4aa42008-12-09 15:10:24 -08001699
1700/**
Robert Love34f42a02009-02-27 10:55:45 -08001701 * fcoe_reset() - Resets the fcoe
Robert Love85b4aa42008-12-09 15:10:24 -08001702 * @shost: shost the reset is from
1703 *
1704 * Returns: always 0
1705 */
1706int fcoe_reset(struct Scsi_Host *shost)
1707{
1708 struct fc_lport *lport = shost_priv(shost);
1709 fc_lport_reset(lport);
1710 return 0;
1711}
Robert Love85b4aa42008-12-09 15:10:24 -08001712
Robert Love34f42a02009-02-27 10:55:45 -08001713/**
Robert Love34f42a02009-02-27 10:55:45 -08001714 * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
Chris Leechdd3fd722009-04-21 16:27:36 -07001715 * @dev: this is currently ptr to net_device
Robert Love85b4aa42008-12-09 15:10:24 -08001716 *
1717 * Returns: NULL or the located fcoe_softc
1718 */
Robert Loveb2ab99c2009-02-27 10:55:50 -08001719static struct fcoe_softc *
1720fcoe_hostlist_lookup_softc(const struct net_device *dev)
Robert Love85b4aa42008-12-09 15:10:24 -08001721{
1722 struct fcoe_softc *fc;
1723
1724 read_lock(&fcoe_hostlist_lock);
1725 list_for_each_entry(fc, &fcoe_hostlist, list) {
1726 if (fc->real_dev == dev) {
1727 read_unlock(&fcoe_hostlist_lock);
1728 return fc;
1729 }
1730 }
1731 read_unlock(&fcoe_hostlist_lock);
1732 return NULL;
1733}
1734
Robert Love34f42a02009-02-27 10:55:45 -08001735/**
1736 * fcoe_hostlist_lookup() - Find the corresponding lport by netdev
Robert Love85b4aa42008-12-09 15:10:24 -08001737 * @netdev: ptr to net_device
1738 *
1739 * Returns: 0 for success
1740 */
1741struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
1742{
1743 struct fcoe_softc *fc;
1744
1745 fc = fcoe_hostlist_lookup_softc(netdev);
1746
Joe Eykholt97c83892009-03-17 11:42:40 -07001747 return (fc) ? fc->ctlr.lp : NULL;
Robert Love85b4aa42008-12-09 15:10:24 -08001748}
Robert Love85b4aa42008-12-09 15:10:24 -08001749
Robert Love34f42a02009-02-27 10:55:45 -08001750/**
1751 * fcoe_hostlist_add() - Add a lport to lports list
Chris Leechdd3fd722009-04-21 16:27:36 -07001752 * @lp: ptr to the fc_lport to be added
Robert Love85b4aa42008-12-09 15:10:24 -08001753 *
1754 * Returns: 0 for success
1755 */
1756int fcoe_hostlist_add(const struct fc_lport *lp)
1757{
1758 struct fcoe_softc *fc;
1759
1760 fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
1761 if (!fc) {
Robert Lovefc47ff62009-02-27 10:55:55 -08001762 fc = lport_priv(lp);
Robert Love85b4aa42008-12-09 15:10:24 -08001763 write_lock_bh(&fcoe_hostlist_lock);
1764 list_add_tail(&fc->list, &fcoe_hostlist);
1765 write_unlock_bh(&fcoe_hostlist_lock);
1766 }
1767 return 0;
1768}
Robert Love85b4aa42008-12-09 15:10:24 -08001769
Robert Love34f42a02009-02-27 10:55:45 -08001770/**
1771 * fcoe_hostlist_remove() - remove a lport from lports list
Chris Leechdd3fd722009-04-21 16:27:36 -07001772 * @lp: ptr to the fc_lport to be removed
Robert Love85b4aa42008-12-09 15:10:24 -08001773 *
1774 * Returns: 0 for success
1775 */
1776int fcoe_hostlist_remove(const struct fc_lport *lp)
1777{
1778 struct fcoe_softc *fc;
1779
1780 fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
1781 BUG_ON(!fc);
1782 write_lock_bh(&fcoe_hostlist_lock);
1783 list_del(&fc->list);
1784 write_unlock_bh(&fcoe_hostlist_lock);
1785
1786 return 0;
1787}
Robert Love85b4aa42008-12-09 15:10:24 -08001788
1789/**
Robert Love34f42a02009-02-27 10:55:45 -08001790 * fcoe_init() - fcoe module loading initialization
Robert Love85b4aa42008-12-09 15:10:24 -08001791 *
Robert Love85b4aa42008-12-09 15:10:24 -08001792 * Returns 0 on success, negative on failure
Robert Love34f42a02009-02-27 10:55:45 -08001793 */
Robert Love85b4aa42008-12-09 15:10:24 -08001794static int __init fcoe_init(void)
1795{
Robert Love38eccab2009-03-17 11:41:30 -07001796 unsigned int cpu;
Robert Love8976f422009-03-17 11:41:46 -07001797 int rc = 0;
Robert Love85b4aa42008-12-09 15:10:24 -08001798 struct fcoe_percpu_s *p;
1799
Robert Love85b4aa42008-12-09 15:10:24 -08001800 INIT_LIST_HEAD(&fcoe_hostlist);
1801 rwlock_init(&fcoe_hostlist_lock);
1802
Robert Love38eccab2009-03-17 11:41:30 -07001803 for_each_possible_cpu(cpu) {
Robert Love5e5e92d2009-03-17 11:41:35 -07001804 p = &per_cpu(fcoe_percpu, cpu);
Robert Love38eccab2009-03-17 11:41:30 -07001805 skb_queue_head_init(&p->fcoe_rx_list);
1806 }
1807
Robert Love8976f422009-03-17 11:41:46 -07001808 for_each_online_cpu(cpu)
1809 fcoe_percpu_thread_create(cpu);
Robert Love85b4aa42008-12-09 15:10:24 -08001810
Robert Love8976f422009-03-17 11:41:46 -07001811 /* Initialize per CPU interrupt thread */
1812 rc = register_hotcpu_notifier(&fcoe_cpu_notifier);
1813 if (rc)
1814 goto out_free;
Robert Love85b4aa42008-12-09 15:10:24 -08001815
Robert Love8976f422009-03-17 11:41:46 -07001816 /* Setup link change notification */
Robert Love85b4aa42008-12-09 15:10:24 -08001817 fcoe_dev_setup();
1818
Robert Lovea468f322009-02-27 10:56:00 -08001819 setup_timer(&fcoe_timer, fcoe_watchdog, 0);
1820
1821 mod_timer(&fcoe_timer, jiffies + (10 * HZ));
Robert Love85b4aa42008-12-09 15:10:24 -08001822
Vasu Dev7f349142009-03-27 09:06:31 -07001823 fcoe_if_init();
Robert Love85b4aa42008-12-09 15:10:24 -08001824
1825 return 0;
Robert Love8976f422009-03-17 11:41:46 -07001826
1827out_free:
1828 for_each_online_cpu(cpu) {
1829 fcoe_percpu_thread_destroy(cpu);
1830 }
1831
1832 return rc;
Robert Love85b4aa42008-12-09 15:10:24 -08001833}
1834module_init(fcoe_init);
1835
1836/**
Robert Love34f42a02009-02-27 10:55:45 -08001837 * fcoe_exit() - fcoe module unloading cleanup
Robert Love85b4aa42008-12-09 15:10:24 -08001838 *
1839 * Returns 0 on success, negative on failure
Robert Love34f42a02009-02-27 10:55:45 -08001840 */
Robert Love85b4aa42008-12-09 15:10:24 -08001841static void __exit fcoe_exit(void)
1842{
Robert Love5e5e92d2009-03-17 11:41:35 -07001843 unsigned int cpu;
Robert Love85b4aa42008-12-09 15:10:24 -08001844 struct fcoe_softc *fc, *tmp;
Robert Love85b4aa42008-12-09 15:10:24 -08001845
Robert Love85b4aa42008-12-09 15:10:24 -08001846 fcoe_dev_cleanup();
1847
Robert Love582b45b2009-03-31 15:51:50 -07001848 /* Stop the timer */
Robert Love85b4aa42008-12-09 15:10:24 -08001849 del_timer_sync(&fcoe_timer);
1850
Vasu Dev5919a592009-03-27 09:03:29 -07001851 /* releases the associated fcoe hosts */
Robert Love85b4aa42008-12-09 15:10:24 -08001852 list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
Vasu Dev7f349142009-03-27 09:06:31 -07001853 fcoe_if_destroy(fc->real_dev);
Robert Love85b4aa42008-12-09 15:10:24 -08001854
Robert Love8976f422009-03-17 11:41:46 -07001855 unregister_hotcpu_notifier(&fcoe_cpu_notifier);
1856
1857 for_each_online_cpu(cpu) {
1858 fcoe_percpu_thread_destroy(cpu);
Robert Love85b4aa42008-12-09 15:10:24 -08001859 }
1860
Vasu Dev7f349142009-03-27 09:06:31 -07001861 /* detach from scsi transport */
1862 fcoe_if_exit();
Robert Love85b4aa42008-12-09 15:10:24 -08001863}
1864module_exit(fcoe_exit);