aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/libfcoe.c
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/scsi/fcoe/libfcoe.c
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/scsi/fcoe/libfcoe.c')
-rw-r--r--drivers/scsi/fcoe/libfcoe.c501
1 files changed, 493 insertions, 8 deletions
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);