aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2009-03-27 12:06:31 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-04-03 10:23:02 -0400
commit7f3491429553cbff20367851fb897c449d028393 (patch)
tree403bc31bd97e48f6a197eb52db41b0dd827cae95 /drivers
parent61e17afa89ad042c356e37d6d6f5654cba869036 (diff)
[SCSI] fcoe: removes default sw transport code file fcoe_sw.c
Moves only required code from fcoe_sw.c to libfcoe.c towards having just one source file for fcoe module, this gets rid off default sw transport code in a separate fcoe_sw.c file. Very minor renaming along this move, dropped _sw_ or _SW_ use in names and replaced them by _if_ as a auxiliary interface functions. Now some of these funcs can be removed or merged with other func after fcoe transport is gone, but that should be in another patch to keep this patch simple. Now the libfcoe.c file name for fcoe module doesn't go along well, so the libfcoe.c file renaming to fcoe.c as the only single fcoe module file is done in next patch to keep this patch clean and small for review. Signed-off-by: Vasu Dev <vasu.dev@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/fcoe/Makefile3
-rw-r--r--drivers/scsi/fcoe/fcoe_sw.c523
-rw-r--r--drivers/scsi/fcoe/libfcoe.c501
3 files changed, 494 insertions, 533 deletions
diff --git a/drivers/scsi/fcoe/Makefile b/drivers/scsi/fcoe/Makefile
index e950adfe68c6..2d9dae48ac0e 100644
--- a/drivers/scsi/fcoe/Makefile
+++ b/drivers/scsi/fcoe/Makefile
@@ -3,5 +3,4 @@
3obj-$(CONFIG_FCOE) += fcoe.o 3obj-$(CONFIG_FCOE) += fcoe.o
4 4
5fcoe-y := \ 5fcoe-y := \
6 libfcoe.o \ 6 libfcoe.o
7 fcoe_sw.o
diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c
deleted file mode 100644
index f0602205f06f..000000000000
--- a/drivers/scsi/fcoe/fcoe_sw.c
+++ /dev/null
@@ -1,523 +0,0 @@
1/*
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/pci.h>
24#include <linux/init.h>
25#include <linux/spinlock.h>
26#include <linux/netdevice.h>
27#include <linux/etherdevice.h>
28#include <linux/if_vlan.h>
29#include <net/rtnetlink.h>
30
31#include <scsi/fc/fc_els.h>
32#include <scsi/fc/fc_encaps.h>
33#include <scsi/fc/fc_fs.h>
34#include <scsi/scsi_transport.h>
35#include <scsi/scsi_transport_fc.h>
36
37#include <scsi/libfc.h>
38#include <scsi/libfcoe.h>
39
40#define FCOE_SW_VERSION "0.1"
41#define FCOE_SW_NAME "fcoesw"
42#define FCOE_SW_VENDOR "Open-FCoE.org"
43
44#define FCOE_MAX_LUN 255
45#define FCOE_MAX_FCP_TARGET 256
46
47#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
48
49#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
50#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
51
52static struct scsi_transport_template *scsi_transport_fcoe_sw;
53
54struct fc_function_template fcoe_sw_transport_function = {
55 .show_host_node_name = 1,
56 .show_host_port_name = 1,
57 .show_host_supported_classes = 1,
58 .show_host_supported_fc4s = 1,
59 .show_host_active_fc4s = 1,
60 .show_host_maxframe_size = 1,
61
62 .show_host_port_id = 1,
63 .show_host_supported_speeds = 1,
64 .get_host_speed = fc_get_host_speed,
65 .show_host_speed = 1,
66 .show_host_port_type = 1,
67 .get_host_port_state = fc_get_host_port_state,
68 .show_host_port_state = 1,
69 .show_host_symbolic_name = 1,
70
71 .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
72 .show_rport_maxframe_size = 1,
73 .show_rport_supported_classes = 1,
74
75 .show_host_fabric_name = 1,
76 .show_starget_node_name = 1,
77 .show_starget_port_name = 1,
78 .show_starget_port_id = 1,
79 .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
80 .show_rport_dev_loss_tmo = 1,
81 .get_fc_host_stats = fc_get_host_stats,
82 .issue_fc_host_lip = fcoe_reset,
83
84 .terminate_rport_io = fc_rport_terminate_io,
85};
86
87static struct scsi_host_template fcoe_sw_shost_template = {
88 .module = THIS_MODULE,
89 .name = "FCoE Driver",
90 .proc_name = FCOE_SW_NAME,
91 .queuecommand = fc_queuecommand,
92 .eh_abort_handler = fc_eh_abort,
93 .eh_device_reset_handler = fc_eh_device_reset,
94 .eh_host_reset_handler = fc_eh_host_reset,
95 .slave_alloc = fc_slave_alloc,
96 .change_queue_depth = fc_change_queue_depth,
97 .change_queue_type = fc_change_queue_type,
98 .this_id = -1,
99 .cmd_per_lun = 32,
100 .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
101 .use_clustering = ENABLE_CLUSTERING,
102 .sg_tablesize = SG_ALL,
103 .max_sectors = 0xffff,
104};
105
106/**
107 * fcoe_sw_lport_config() - sets up the fc_lport
108 * @lp: ptr to the fc_lport
109 * @shost: ptr to the parent scsi host
110 *
111 * Returns: 0 for success
112 */
113static int fcoe_sw_lport_config(struct fc_lport *lp)
114{
115 lp->link_up = 0;
116 lp->qfull = 0;
117 lp->max_retry_count = 3;
118 lp->e_d_tov = 2 * 1000; /* FC-FS default */
119 lp->r_a_tov = 2 * 2 * 1000;
120 lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
121 FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
122
123 fc_lport_init_stats(lp);
124
125 /* lport fc_lport related configuration */
126 fc_lport_config(lp);
127
128 /* offload related configuration */
129 lp->crc_offload = 0;
130 lp->seq_offload = 0;
131 lp->lro_enabled = 0;
132 lp->lro_xid = 0;
133 lp->lso_max = 0;
134
135 return 0;
136}
137
138/**
139 * fcoe_sw_netdev_config() - Set up netdev for SW FCoE
140 * @lp : ptr to the fc_lport
141 * @netdev : ptr to the associated netdevice struct
142 *
143 * Must be called after fcoe_sw_lport_config() as it will use lport mutex
144 *
145 * Returns : 0 for success
146 */
147static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev)
148{
149 u32 mfs;
150 u64 wwnn, wwpn;
151 struct fcoe_softc *fc;
152 u8 flogi_maddr[ETH_ALEN];
153
154 /* Setup lport private data to point to fcoe softc */
155 fc = lport_priv(lp);
156 fc->lp = lp;
157 fc->real_dev = netdev;
158 fc->phys_dev = netdev;
159
160 /* Require support for get_pauseparam ethtool op. */
161 if (netdev->priv_flags & IFF_802_1Q_VLAN)
162 fc->phys_dev = vlan_dev_real_dev(netdev);
163
164 /* Do not support for bonding device */
165 if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
166 (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
167 (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
168 return -EOPNOTSUPP;
169 }
170
171 /*
172 * Determine max frame size based on underlying device and optional
173 * user-configured limit. If the MFS is too low, fcoe_link_ok()
174 * will return 0, so do this first.
175 */
176 mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
177 sizeof(struct fcoe_crc_eof));
178 if (fc_set_mfs(lp, mfs))
179 return -EINVAL;
180
181 if (!fcoe_link_ok(lp))
182 lp->link_up = 1;
183
184 /* offload features support */
185 if (fc->real_dev->features & NETIF_F_SG)
186 lp->sg_supp = 1;
187
188#ifdef NETIF_F_FCOE_CRC
189 if (netdev->features & NETIF_F_FCOE_CRC) {
190 lp->crc_offload = 1;
191 printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n",
192 netdev->name);
193 }
194#endif
195#ifdef NETIF_F_FSO
196 if (netdev->features & NETIF_F_FSO) {
197 lp->seq_offload = 1;
198 lp->lso_max = netdev->gso_max_size;
199 printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n",
200 netdev->name, lp->lso_max);
201 }
202#endif
203 if (netdev->fcoe_ddp_xid) {
204 lp->lro_enabled = 1;
205 lp->lro_xid = netdev->fcoe_ddp_xid;
206 printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n",
207 netdev->name, lp->lro_xid);
208 }
209 skb_queue_head_init(&fc->fcoe_pending_queue);
210 fc->fcoe_pending_queue_active = 0;
211
212 /* setup Source Mac Address */
213 memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr,
214 fc->real_dev->addr_len);
215
216 wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
217 fc_set_wwnn(lp, wwnn);
218 /* XXX - 3rd arg needs to be vlan id */
219 wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
220 fc_set_wwpn(lp, wwpn);
221
222 /*
223 * Add FCoE MAC address as second unicast MAC address
224 * or enter promiscuous mode if not capable of listening
225 * for multiple unicast MACs.
226 */
227 rtnl_lock();
228 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
229 dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
230 rtnl_unlock();
231
232 /*
233 * setup the receive function from ethernet driver
234 * on the ethertype for the given device
235 */
236 fc->fcoe_packet_type.func = fcoe_rcv;
237 fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
238 fc->fcoe_packet_type.dev = fc->real_dev;
239 dev_add_pack(&fc->fcoe_packet_type);
240
241 return 0;
242}
243
244/**
245 * fcoe_sw_shost_config() - Sets up fc_lport->host
246 * @lp : ptr to the fc_lport
247 * @shost : ptr to the associated scsi host
248 * @dev : device associated to scsi host
249 *
250 * Must be called after fcoe_sw_lport_config() and fcoe_sw_netdev_config()
251 *
252 * Returns : 0 for success
253 */
254static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
255 struct device *dev)
256{
257 int rc = 0;
258
259 /* lport scsi host config */
260 lp->host = shost;
261
262 lp->host->max_lun = FCOE_MAX_LUN;
263 lp->host->max_id = FCOE_MAX_FCP_TARGET;
264 lp->host->max_channel = 0;
265 lp->host->transportt = scsi_transport_fcoe_sw;
266
267 /* add the new host to the SCSI-ml */
268 rc = scsi_add_host(lp->host, dev);
269 if (rc) {
270 FC_DBG("fcoe_sw_shost_config:error on scsi_add_host\n");
271 return rc;
272 }
273 sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
274 FCOE_SW_NAME, FCOE_SW_VERSION,
275 fcoe_netdev(lp)->name);
276
277 return 0;
278}
279
280/**
281 * fcoe_sw_em_config() - allocates em for this lport
282 * @lp: the port that em is to allocated for
283 *
284 * Returns : 0 on success
285 */
286static inline int fcoe_sw_em_config(struct fc_lport *lp)
287{
288 BUG_ON(lp->emp);
289
290 lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
291 FCOE_MIN_XID, FCOE_MAX_XID);
292 if (!lp->emp)
293 return -ENOMEM;
294
295 return 0;
296}
297
298/**
299 * fcoe_sw_destroy() - FCoE software HBA tear-down function
300 * @netdev: ptr to the associated net_device
301 *
302 * Returns: 0 if link is OK for use by FCoE.
303 */
304int fcoe_sw_destroy(struct net_device *netdev)
305{
306 struct fc_lport *lp = NULL;
307 struct fcoe_softc *fc;
308 u8 flogi_maddr[ETH_ALEN];
309
310 BUG_ON(!netdev);
311
312 printk(KERN_DEBUG "fcoe_sw_destroy:interface on %s\n",
313 netdev->name);
314
315 lp = fcoe_hostlist_lookup(netdev);
316 if (!lp)
317 return -ENODEV;
318
319 fc = lport_priv(lp);
320
321 /* Logout of the fabric */
322 fc_fabric_logoff(lp);
323
324 /* Remove the instance from fcoe's list */
325 fcoe_hostlist_remove(lp);
326
327 /* Don't listen for Ethernet packets anymore */
328 dev_remove_pack(&fc->fcoe_packet_type);
329
330 /* Cleanup the fc_lport */
331 fc_lport_destroy(lp);
332 fc_fcp_destroy(lp);
333
334 /* Detach from the scsi-ml */
335 fc_remove_host(lp->host);
336 scsi_remove_host(lp->host);
337
338 /* There are no more rports or I/O, free the EM */
339 if (lp->emp)
340 fc_exch_mgr_free(lp->emp);
341
342 /* Delete secondary MAC addresses */
343 rtnl_lock();
344 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
345 dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
346 if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
347 dev_unicast_delete(fc->real_dev, fc->data_src_addr, ETH_ALEN);
348 rtnl_unlock();
349
350 /* Free the per-CPU revieve threads */
351 fcoe_percpu_clean(lp);
352
353 /* Free existing skbs */
354 fcoe_clean_pending_queue(lp);
355
356 /* Free memory used by statistical counters */
357 fc_lport_free_stats(lp);
358
359 /* Release the net_device and Scsi_Host */
360 dev_put(fc->real_dev);
361 scsi_host_put(lp->host);
362
363 return 0;
364}
365
366/*
367 * fcoe_sw_ddp_setup - calls LLD's ddp_setup through net_device
368 * @lp: the corresponding fc_lport
369 * @xid: the exchange id for this ddp transfer
370 * @sgl: the scatterlist describing this transfer
371 * @sgc: number of sg items
372 *
373 * Returns : 0 no ddp
374 */
375static int fcoe_sw_ddp_setup(struct fc_lport *lp, u16 xid,
376 struct scatterlist *sgl, unsigned int sgc)
377{
378 struct net_device *n = fcoe_netdev(lp);
379
380 if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup)
381 return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc);
382
383 return 0;
384}
385
386/*
387 * fcoe_sw_ddp_done - calls LLD's ddp_done through net_device
388 * @lp: the corresponding fc_lport
389 * @xid: the exchange id for this ddp transfer
390 *
391 * Returns : the length of data that have been completed by ddp
392 */
393static int fcoe_sw_ddp_done(struct fc_lport *lp, u16 xid)
394{
395 struct net_device *n = fcoe_netdev(lp);
396
397 if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done)
398 return n->netdev_ops->ndo_fcoe_ddp_done(n, xid);
399 return 0;
400}
401
402static struct libfc_function_template fcoe_sw_libfc_fcn_templ = {
403 .frame_send = fcoe_xmit,
404 .ddp_setup = fcoe_sw_ddp_setup,
405 .ddp_done = fcoe_sw_ddp_done,
406};
407
408/**
409 * fcoe_sw_create() - this function creates the fcoe interface
410 * @netdev: pointer the associated netdevice
411 *
412 * Creates fc_lport struct and scsi_host for lport, configures lport
413 * and starts fabric login.
414 *
415 * Returns : 0 on success
416 */
417int fcoe_sw_create(struct net_device *netdev)
418{
419 int rc;
420 struct fc_lport *lp = NULL;
421 struct fcoe_softc *fc;
422 struct Scsi_Host *shost;
423
424 BUG_ON(!netdev);
425
426 printk(KERN_DEBUG "fcoe_sw_create:interface on %s\n",
427 netdev->name);
428
429 lp = fcoe_hostlist_lookup(netdev);
430 if (lp)
431 return -EEXIST;
432
433 shost = fcoe_host_alloc(&fcoe_sw_shost_template,
434 sizeof(struct fcoe_softc));
435 if (!shost) {
436 FC_DBG("Could not allocate host structure\n");
437 return -ENOMEM;
438 }
439 lp = shost_priv(shost);
440 fc = lport_priv(lp);
441
442 /* configure fc_lport, e.g., em */
443 rc = fcoe_sw_lport_config(lp);
444 if (rc) {
445 FC_DBG("Could not configure lport\n");
446 goto out_host_put;
447 }
448
449 /* configure lport network properties */
450 rc = fcoe_sw_netdev_config(lp, netdev);
451 if (rc) {
452 FC_DBG("Could not configure netdev for lport\n");
453 goto out_host_put;
454 }
455
456 /* configure lport scsi host properties */
457 rc = fcoe_sw_shost_config(lp, shost, &netdev->dev);
458 if (rc) {
459 FC_DBG("Could not configure shost for lport\n");
460 goto out_host_put;
461 }
462
463 /* lport exch manager allocation */
464 rc = fcoe_sw_em_config(lp);
465 if (rc) {
466 FC_DBG("Could not configure em for lport\n");
467 goto out_host_put;
468 }
469
470 /* Initialize the library */
471 rc = fcoe_libfc_config(lp, &fcoe_sw_libfc_fcn_templ);
472 if (rc) {
473 FC_DBG("Could not configure libfc for lport!\n");
474 goto out_lp_destroy;
475 }
476
477 /* add to lports list */
478 fcoe_hostlist_add(lp);
479
480 lp->boot_time = jiffies;
481
482 fc_fabric_login(lp);
483
484 dev_hold(netdev);
485
486 return rc;
487
488out_lp_destroy:
489 fc_exch_mgr_free(lp->emp); /* Free the EM */
490out_host_put:
491 scsi_host_put(lp->host);
492 return rc;
493}
494
495/**
496 * fcoe_sw_init() - attach to scsi transport
497 *
498 * Returns : 0 on success
499 */
500int __init fcoe_sw_init(void)
501{
502 /* attach to scsi transport */
503 scsi_transport_fcoe_sw =
504 fc_attach_transport(&fcoe_sw_transport_function);
505
506 if (!scsi_transport_fcoe_sw) {
507 printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n");
508 return -ENODEV;
509 }
510
511 return 0;
512}
513
514/**
515 * fcoe_sw_exit() - detach from scsi transport
516 *
517 * Returns : 0 on success
518 */
519int __exit fcoe_sw_exit(void)
520{
521 fc_release_transport(scsi_transport_fcoe_sw);
522 return 0;
523}
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 334db95f36af..a81a8ec3908e 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -56,6 +56,18 @@ static int debug_fcoe;
56 56
57#define FCOE_WORD_TO_BYTE 4 57#define FCOE_WORD_TO_BYTE 4
58 58
59#define FCOE_VERSION "0.1"
60#define FCOE_NAME "fcoe"
61#define FCOE_VENDOR "Open-FCoE.org"
62
63#define FCOE_MAX_LUN 255
64#define FCOE_MAX_FCP_TARGET 256
65
66#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
67
68#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
69#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
70
59MODULE_AUTHOR("Open-FCoE.org"); 71MODULE_AUTHOR("Open-FCoE.org");
60MODULE_DESCRIPTION("FCoE"); 72MODULE_DESCRIPTION("FCoE");
61MODULE_LICENSE("GPL"); 73MODULE_LICENSE("GPL");
@@ -79,6 +91,479 @@ static struct notifier_block fcoe_notifier = {
79 .notifier_call = fcoe_device_notification, 91 .notifier_call = fcoe_device_notification,
80}; 92};
81 93
94static struct scsi_transport_template *scsi_transport_fcoe_sw;
95
96struct fc_function_template fcoe_transport_function = {
97 .show_host_node_name = 1,
98 .show_host_port_name = 1,
99 .show_host_supported_classes = 1,
100 .show_host_supported_fc4s = 1,
101 .show_host_active_fc4s = 1,
102 .show_host_maxframe_size = 1,
103
104 .show_host_port_id = 1,
105 .show_host_supported_speeds = 1,
106 .get_host_speed = fc_get_host_speed,
107 .show_host_speed = 1,
108 .show_host_port_type = 1,
109 .get_host_port_state = fc_get_host_port_state,
110 .show_host_port_state = 1,
111 .show_host_symbolic_name = 1,
112
113 .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
114 .show_rport_maxframe_size = 1,
115 .show_rport_supported_classes = 1,
116
117 .show_host_fabric_name = 1,
118 .show_starget_node_name = 1,
119 .show_starget_port_name = 1,
120 .show_starget_port_id = 1,
121 .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
122 .show_rport_dev_loss_tmo = 1,
123 .get_fc_host_stats = fc_get_host_stats,
124 .issue_fc_host_lip = fcoe_reset,
125
126 .terminate_rport_io = fc_rport_terminate_io,
127};
128
129static struct scsi_host_template fcoe_shost_template = {
130 .module = THIS_MODULE,
131 .name = "FCoE Driver",
132 .proc_name = FCOE_NAME,
133 .queuecommand = fc_queuecommand,
134 .eh_abort_handler = fc_eh_abort,
135 .eh_device_reset_handler = fc_eh_device_reset,
136 .eh_host_reset_handler = fc_eh_host_reset,
137 .slave_alloc = fc_slave_alloc,
138 .change_queue_depth = fc_change_queue_depth,
139 .change_queue_type = fc_change_queue_type,
140 .this_id = -1,
141 .cmd_per_lun = 32,
142 .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
143 .use_clustering = ENABLE_CLUSTERING,
144 .sg_tablesize = SG_ALL,
145 .max_sectors = 0xffff,
146};
147
148/**
149 * fcoe_lport_config() - sets up the fc_lport
150 * @lp: ptr to the fc_lport
151 * @shost: ptr to the parent scsi host
152 *
153 * Returns: 0 for success
154 */
155static int fcoe_lport_config(struct fc_lport *lp)
156{
157 lp->link_up = 0;
158 lp->qfull = 0;
159 lp->max_retry_count = 3;
160 lp->e_d_tov = 2 * 1000; /* FC-FS default */
161 lp->r_a_tov = 2 * 2 * 1000;
162 lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
163 FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
164
165 fc_lport_init_stats(lp);
166
167 /* lport fc_lport related configuration */
168 fc_lport_config(lp);
169
170 /* offload related configuration */
171 lp->crc_offload = 0;
172 lp->seq_offload = 0;
173 lp->lro_enabled = 0;
174 lp->lro_xid = 0;
175 lp->lso_max = 0;
176
177 return 0;
178}
179
180/**
181 * fcoe_netdev_config() - Set up netdev for SW FCoE
182 * @lp : ptr to the fc_lport
183 * @netdev : ptr to the associated netdevice struct
184 *
185 * Must be called after fcoe_lport_config() as it will use lport mutex
186 *
187 * Returns : 0 for success
188 */
189static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
190{
191 u32 mfs;
192 u64 wwnn, wwpn;
193 struct fcoe_softc *fc;
194 u8 flogi_maddr[ETH_ALEN];
195
196 /* Setup lport private data to point to fcoe softc */
197 fc = lport_priv(lp);
198 fc->lp = lp;
199 fc->real_dev = netdev;
200 fc->phys_dev = netdev;
201
202 /* Require support for get_pauseparam ethtool op. */
203 if (netdev->priv_flags & IFF_802_1Q_VLAN)
204 fc->phys_dev = vlan_dev_real_dev(netdev);
205
206 /* Do not support for bonding device */
207 if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
208 (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
209 (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
210 return -EOPNOTSUPP;
211 }
212
213 /*
214 * Determine max frame size based on underlying device and optional
215 * user-configured limit. If the MFS is too low, fcoe_link_ok()
216 * will return 0, so do this first.
217 */
218 mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
219 sizeof(struct fcoe_crc_eof));
220 if (fc_set_mfs(lp, mfs))
221 return -EINVAL;
222
223 if (!fcoe_link_ok(lp))
224 lp->link_up = 1;
225
226 /* offload features support */
227 if (fc->real_dev->features & NETIF_F_SG)
228 lp->sg_supp = 1;
229
230#ifdef NETIF_F_FCOE_CRC
231 if (netdev->features & NETIF_F_FCOE_CRC) {
232 lp->crc_offload = 1;
233 printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n",
234 netdev->name);
235 }
236#endif
237#ifdef NETIF_F_FSO
238 if (netdev->features & NETIF_F_FSO) {
239 lp->seq_offload = 1;
240 lp->lso_max = netdev->gso_max_size;
241 printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n",
242 netdev->name, lp->lso_max);
243 }
244#endif
245 if (netdev->fcoe_ddp_xid) {
246 lp->lro_enabled = 1;
247 lp->lro_xid = netdev->fcoe_ddp_xid;
248 printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n",
249 netdev->name, lp->lro_xid);
250 }
251 skb_queue_head_init(&fc->fcoe_pending_queue);
252 fc->fcoe_pending_queue_active = 0;
253
254 /* setup Source Mac Address */
255 memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr,
256 fc->real_dev->addr_len);
257
258 wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
259 fc_set_wwnn(lp, wwnn);
260 /* XXX - 3rd arg needs to be vlan id */
261 wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
262 fc_set_wwpn(lp, wwpn);
263
264 /*
265 * Add FCoE MAC address as second unicast MAC address
266 * or enter promiscuous mode if not capable of listening
267 * for multiple unicast MACs.
268 */
269 rtnl_lock();
270 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
271 dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
272 rtnl_unlock();
273
274 /*
275 * setup the receive function from ethernet driver
276 * on the ethertype for the given device
277 */
278 fc->fcoe_packet_type.func = fcoe_rcv;
279 fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
280 fc->fcoe_packet_type.dev = fc->real_dev;
281 dev_add_pack(&fc->fcoe_packet_type);
282
283 return 0;
284}
285
286/**
287 * fcoe_shost_config() - Sets up fc_lport->host
288 * @lp : ptr to the fc_lport
289 * @shost : ptr to the associated scsi host
290 * @dev : device associated to scsi host
291 *
292 * Must be called after fcoe_lport_config() and fcoe_netdev_config()
293 *
294 * Returns : 0 for success
295 */
296static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
297 struct device *dev)
298{
299 int rc = 0;
300
301 /* lport scsi host config */
302 lp->host = shost;
303
304 lp->host->max_lun = FCOE_MAX_LUN;
305 lp->host->max_id = FCOE_MAX_FCP_TARGET;
306 lp->host->max_channel = 0;
307 lp->host->transportt = scsi_transport_fcoe_sw;
308
309 /* add the new host to the SCSI-ml */
310 rc = scsi_add_host(lp->host, dev);
311 if (rc) {
312 FC_DBG("fcoe_shost_config:error on scsi_add_host\n");
313 return rc;
314 }
315 sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
316 FCOE_NAME, FCOE_VERSION,
317 fcoe_netdev(lp)->name);
318
319 return 0;
320}
321
322/**
323 * fcoe_em_config() - allocates em for this lport
324 * @lp: the port that em is to allocated for
325 *
326 * Returns : 0 on success
327 */
328static inline int fcoe_em_config(struct fc_lport *lp)
329{
330 BUG_ON(lp->emp);
331
332 lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
333 FCOE_MIN_XID, FCOE_MAX_XID);
334 if (!lp->emp)
335 return -ENOMEM;
336
337 return 0;
338}
339
340/**
341 * fcoe_if_destroy() - FCoE software HBA tear-down function
342 * @netdev: ptr to the associated net_device
343 *
344 * Returns: 0 if link is OK for use by FCoE.
345 */
346static int fcoe_if_destroy(struct net_device *netdev)
347{
348 struct fc_lport *lp = NULL;
349 struct fcoe_softc *fc;
350 u8 flogi_maddr[ETH_ALEN];
351
352 BUG_ON(!netdev);
353
354 printk(KERN_DEBUG "fcoe_if_destroy:interface on %s\n",
355 netdev->name);
356
357 lp = fcoe_hostlist_lookup(netdev);
358 if (!lp)
359 return -ENODEV;
360
361 fc = lport_priv(lp);
362
363 /* Logout of the fabric */
364 fc_fabric_logoff(lp);
365
366 /* Remove the instance from fcoe's list */
367 fcoe_hostlist_remove(lp);
368
369 /* Don't listen for Ethernet packets anymore */
370 dev_remove_pack(&fc->fcoe_packet_type);
371
372 /* Cleanup the fc_lport */
373 fc_lport_destroy(lp);
374 fc_fcp_destroy(lp);
375
376 /* Detach from the scsi-ml */
377 fc_remove_host(lp->host);
378 scsi_remove_host(lp->host);
379
380 /* There are no more rports or I/O, free the EM */
381 if (lp->emp)
382 fc_exch_mgr_free(lp->emp);
383
384 /* Delete secondary MAC addresses */
385 rtnl_lock();
386 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
387 dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
388 if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
389 dev_unicast_delete(fc->real_dev, fc->data_src_addr, ETH_ALEN);
390 rtnl_unlock();
391
392 /* Free the per-CPU revieve threads */
393 fcoe_percpu_clean(lp);
394
395 /* Free existing skbs */
396 fcoe_clean_pending_queue(lp);
397
398 /* Free memory used by statistical counters */
399 fc_lport_free_stats(lp);
400
401 /* Release the net_device and Scsi_Host */
402 dev_put(fc->real_dev);
403 scsi_host_put(lp->host);
404
405 return 0;
406}
407
408/*
409 * fcoe_ddp_setup - calls LLD's ddp_setup through net_device
410 * @lp: the corresponding fc_lport
411 * @xid: the exchange id for this ddp transfer
412 * @sgl: the scatterlist describing this transfer
413 * @sgc: number of sg items
414 *
415 * Returns : 0 no ddp
416 */
417static int fcoe_ddp_setup(struct fc_lport *lp, u16 xid,
418 struct scatterlist *sgl, unsigned int sgc)
419{
420 struct net_device *n = fcoe_netdev(lp);
421
422 if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup)
423 return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc);
424
425 return 0;
426}
427
428/*
429 * fcoe_ddp_done - calls LLD's ddp_done through net_device
430 * @lp: the corresponding fc_lport
431 * @xid: the exchange id for this ddp transfer
432 *
433 * Returns : the length of data that have been completed by ddp
434 */
435static int fcoe_ddp_done(struct fc_lport *lp, u16 xid)
436{
437 struct net_device *n = fcoe_netdev(lp);
438
439 if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done)
440 return n->netdev_ops->ndo_fcoe_ddp_done(n, xid);
441 return 0;
442}
443
444static struct libfc_function_template fcoe_libfc_fcn_templ = {
445 .frame_send = fcoe_xmit,
446 .ddp_setup = fcoe_ddp_setup,
447 .ddp_done = fcoe_ddp_done,
448};
449
450/**
451 * fcoe_if_create() - this function creates the fcoe interface
452 * @netdev: pointer the associated netdevice
453 *
454 * Creates fc_lport struct and scsi_host for lport, configures lport
455 * and starts fabric login.
456 *
457 * Returns : 0 on success
458 */
459static int fcoe_if_create(struct net_device *netdev)
460{
461 int rc;
462 struct fc_lport *lp = NULL;
463 struct fcoe_softc *fc;
464 struct Scsi_Host *shost;
465
466 BUG_ON(!netdev);
467
468 printk(KERN_DEBUG "fcoe_if_create:interface on %s\n",
469 netdev->name);
470
471 lp = fcoe_hostlist_lookup(netdev);
472 if (lp)
473 return -EEXIST;
474
475 shost = fcoe_host_alloc(&fcoe_shost_template,
476 sizeof(struct fcoe_softc));
477 if (!shost) {
478 FC_DBG("Could not allocate host structure\n");
479 return -ENOMEM;
480 }
481 lp = shost_priv(shost);
482 fc = lport_priv(lp);
483
484 /* configure fc_lport, e.g., em */
485 rc = fcoe_lport_config(lp);
486 if (rc) {
487 FC_DBG("Could not configure lport\n");
488 goto out_host_put;
489 }
490
491 /* configure lport network properties */
492 rc = fcoe_netdev_config(lp, netdev);
493 if (rc) {
494 FC_DBG("Could not configure netdev for lport\n");
495 goto out_host_put;
496 }
497
498 /* configure lport scsi host properties */
499 rc = fcoe_shost_config(lp, shost, &netdev->dev);
500 if (rc) {
501 FC_DBG("Could not configure shost for lport\n");
502 goto out_host_put;
503 }
504
505 /* lport exch manager allocation */
506 rc = fcoe_em_config(lp);
507 if (rc) {
508 FC_DBG("Could not configure em for lport\n");
509 goto out_host_put;
510 }
511
512 /* Initialize the library */
513 rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
514 if (rc) {
515 FC_DBG("Could not configure libfc for lport!\n");
516 goto out_lp_destroy;
517 }
518
519 /* add to lports list */
520 fcoe_hostlist_add(lp);
521
522 lp->boot_time = jiffies;
523
524 fc_fabric_login(lp);
525
526 dev_hold(netdev);
527
528 return rc;
529
530out_lp_destroy:
531 fc_exch_mgr_free(lp->emp); /* Free the EM */
532out_host_put:
533 scsi_host_put(lp->host);
534 return rc;
535}
536
537/**
538 * fcoe_if_init() - attach to scsi transport
539 *
540 * Returns : 0 on success
541 */
542static int __init fcoe_if_init(void)
543{
544 /* attach to scsi transport */
545 scsi_transport_fcoe_sw =
546 fc_attach_transport(&fcoe_transport_function);
547
548 if (!scsi_transport_fcoe_sw) {
549 printk(KERN_ERR "fcoe_init:fc_attach_transport() failed\n");
550 return -ENODEV;
551 }
552
553 return 0;
554}
555
556/**
557 * fcoe_if_exit() - detach from scsi transport
558 *
559 * Returns : 0 on success
560 */
561int __exit fcoe_if_exit(void)
562{
563 fc_release_transport(scsi_transport_fcoe_sw);
564 return 0;
565}
566
82/** 567/**
83 * fcoe_percpu_thread_create() - Create a receive thread for an online cpu 568 * fcoe_percpu_thread_create() - Create a receive thread for an online cpu
84 * @cpu: cpu index for the online cpu 569 * @cpu: cpu index for the online cpu
@@ -1080,9 +1565,9 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
1080 rc = -ENODEV; 1565 rc = -ENODEV;
1081 goto out_putdev; 1566 goto out_putdev;
1082 } 1567 }
1083 rc = fcoe_sw_destroy(netdev); 1568 rc = fcoe_if_destroy(netdev);
1084 if (rc) { 1569 if (rc) {
1085 printk(KERN_ERR "fcoe: fcoe_sw_destroy(%s) failed\n", 1570 printk(KERN_ERR "fcoe: fcoe_if_destroy(%s) failed\n",
1086 netdev->name); 1571 netdev->name);
1087 rc = -EIO; 1572 rc = -EIO;
1088 goto out_putdev; 1573 goto out_putdev;
@@ -1119,9 +1604,9 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
1119 } 1604 }
1120 fcoe_ethdrv_get(netdev); 1605 fcoe_ethdrv_get(netdev);
1121 1606
1122 rc = fcoe_sw_create(netdev); 1607 rc = fcoe_if_create(netdev);
1123 if (rc) { 1608 if (rc) {
1124 printk(KERN_ERR "fcoe: fcoe_sw_create(%s) failed\n", 1609 printk(KERN_ERR "fcoe: fcoe_if_create(%s) failed\n",
1125 netdev->name); 1610 netdev->name);
1126 fcoe_ethdrv_put(netdev); 1611 fcoe_ethdrv_put(netdev);
1127 rc = -EIO; 1612 rc = -EIO;
@@ -1457,7 +1942,7 @@ static int __init fcoe_init(void)
1457 1942
1458 mod_timer(&fcoe_timer, jiffies + (10 * HZ)); 1943 mod_timer(&fcoe_timer, jiffies + (10 * HZ));
1459 1944
1460 fcoe_sw_init(); 1945 fcoe_if_init();
1461 1946
1462 return 0; 1947 return 0;
1463 1948
@@ -1487,7 +1972,7 @@ static void __exit fcoe_exit(void)
1487 1972
1488 /* releases the associated fcoe hosts */ 1973 /* releases the associated fcoe hosts */
1489 list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) 1974 list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
1490 fcoe_sw_destroy(fc->real_dev); 1975 fcoe_if_destroy(fc->real_dev);
1491 1976
1492 unregister_hotcpu_notifier(&fcoe_cpu_notifier); 1977 unregister_hotcpu_notifier(&fcoe_cpu_notifier);
1493 1978
@@ -1495,7 +1980,7 @@ static void __exit fcoe_exit(void)
1495 fcoe_percpu_thread_destroy(cpu); 1980 fcoe_percpu_thread_destroy(cpu);
1496 } 1981 }
1497 1982
1498 /* remove sw trasnport */ 1983 /* detach from scsi transport */
1499 fcoe_sw_exit(); 1984 fcoe_if_exit();
1500} 1985}
1501module_exit(fcoe_exit); 1986module_exit(fcoe_exit);