aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r--drivers/scsi/fcoe/fcoe.c167
1 files changed, 112 insertions, 55 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index cc75cbea936b..ae7d15c44e2a 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -168,6 +168,14 @@ static struct fc_function_template fcoe_nport_fc_functions = {
168 .show_host_supported_fc4s = 1, 168 .show_host_supported_fc4s = 1,
169 .show_host_active_fc4s = 1, 169 .show_host_active_fc4s = 1,
170 .show_host_maxframe_size = 1, 170 .show_host_maxframe_size = 1,
171 .show_host_serial_number = 1,
172 .show_host_manufacturer = 1,
173 .show_host_model = 1,
174 .show_host_model_description = 1,
175 .show_host_hardware_version = 1,
176 .show_host_driver_version = 1,
177 .show_host_firmware_version = 1,
178 .show_host_optionrom_version = 1,
171 179
172 .show_host_port_id = 1, 180 .show_host_port_id = 1,
173 .show_host_supported_speeds = 1, 181 .show_host_supported_speeds = 1,
@@ -208,6 +216,14 @@ static struct fc_function_template fcoe_vport_fc_functions = {
208 .show_host_supported_fc4s = 1, 216 .show_host_supported_fc4s = 1,
209 .show_host_active_fc4s = 1, 217 .show_host_active_fc4s = 1,
210 .show_host_maxframe_size = 1, 218 .show_host_maxframe_size = 1,
219 .show_host_serial_number = 1,
220 .show_host_manufacturer = 1,
221 .show_host_model = 1,
222 .show_host_model_description = 1,
223 .show_host_hardware_version = 1,
224 .show_host_driver_version = 1,
225 .show_host_firmware_version = 1,
226 .show_host_optionrom_version = 1,
211 227
212 .show_host_port_id = 1, 228 .show_host_port_id = 1,
213 .show_host_supported_speeds = 1, 229 .show_host_supported_speeds = 1,
@@ -364,11 +380,10 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
364 if (!fcoe) { 380 if (!fcoe) {
365 FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); 381 FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n");
366 fcoe = ERR_PTR(-ENOMEM); 382 fcoe = ERR_PTR(-ENOMEM);
367 goto out_nomod; 383 goto out_putmod;
368 } 384 }
369 385
370 dev_hold(netdev); 386 dev_hold(netdev);
371 kref_init(&fcoe->kref);
372 387
373 /* 388 /*
374 * Initialize FIP. 389 * Initialize FIP.
@@ -384,54 +399,18 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
384 kfree(fcoe); 399 kfree(fcoe);
385 dev_put(netdev); 400 dev_put(netdev);
386 fcoe = ERR_PTR(err); 401 fcoe = ERR_PTR(err);
387 goto out_nomod; 402 goto out_putmod;
388 } 403 }
389 404
390 goto out; 405 goto out;
391 406
392out_nomod: 407out_putmod:
393 module_put(THIS_MODULE); 408 module_put(THIS_MODULE);
394out: 409out:
395 return fcoe; 410 return fcoe;
396} 411}
397 412
398/** 413/**
399 * fcoe_interface_release() - fcoe_port kref release function
400 * @kref: Embedded reference count in an fcoe_interface struct
401 */
402static void fcoe_interface_release(struct kref *kref)
403{
404 struct fcoe_interface *fcoe;
405 struct net_device *netdev;
406
407 fcoe = container_of(kref, struct fcoe_interface, kref);
408 netdev = fcoe->netdev;
409 /* tear-down the FCoE controller */
410 fcoe_ctlr_destroy(&fcoe->ctlr);
411 kfree(fcoe);
412 dev_put(netdev);
413 module_put(THIS_MODULE);
414}
415
416/**
417 * fcoe_interface_get() - Get a reference to a FCoE interface
418 * @fcoe: The FCoE interface to be held
419 */
420static inline void fcoe_interface_get(struct fcoe_interface *fcoe)
421{
422 kref_get(&fcoe->kref);
423}
424
425/**
426 * fcoe_interface_put() - Put a reference to a FCoE interface
427 * @fcoe: The FCoE interface to be released
428 */
429static inline void fcoe_interface_put(struct fcoe_interface *fcoe)
430{
431 kref_put(&fcoe->kref, fcoe_interface_release);
432}
433
434/**
435 * fcoe_interface_cleanup() - Clean up a FCoE interface 414 * fcoe_interface_cleanup() - Clean up a FCoE interface
436 * @fcoe: The FCoE interface to be cleaned up 415 * @fcoe: The FCoE interface to be cleaned up
437 * 416 *
@@ -478,7 +457,11 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
478 rtnl_unlock(); 457 rtnl_unlock();
479 458
480 /* Release the self-reference taken during fcoe_interface_create() */ 459 /* Release the self-reference taken during fcoe_interface_create() */
481 fcoe_interface_put(fcoe); 460 /* tear-down the FCoE controller */
461 fcoe_ctlr_destroy(fip);
462 kfree(fcoe);
463 dev_put(netdev);
464 module_put(THIS_MODULE);
482} 465}
483 466
484/** 467/**
@@ -734,6 +717,85 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev)
734 return 0; 717 return 0;
735} 718}
736 719
720
721/**
722 * fcoe_fdmi_info() - Get FDMI related info from net devive for SW FCoE
723 * @lport: The local port that is associated with the net device
724 * @netdev: The associated net device
725 *
726 * Must be called after fcoe_shost_config() as it will use local port mutex
727 *
728 */
729static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev)
730{
731 struct fcoe_interface *fcoe;
732 struct fcoe_port *port;
733 struct net_device *realdev;
734 int rc;
735 struct netdev_fcoe_hbainfo fdmi;
736
737 port = lport_priv(lport);
738 fcoe = port->priv;
739 realdev = fcoe->realdev;
740
741 if (!realdev)
742 return;
743
744 /* No FDMI state m/c for NPIV ports */
745 if (lport->vport)
746 return;
747
748 if (realdev->netdev_ops->ndo_fcoe_get_hbainfo) {
749 memset(&fdmi, 0, sizeof(fdmi));
750 rc = realdev->netdev_ops->ndo_fcoe_get_hbainfo(realdev,
751 &fdmi);
752 if (rc) {
753 printk(KERN_INFO "fcoe: Failed to retrieve FDMI "
754 "information from netdev.\n");
755 return;
756 }
757
758 snprintf(fc_host_serial_number(lport->host),
759 FC_SERIAL_NUMBER_SIZE,
760 "%s",
761 fdmi.serial_number);
762 snprintf(fc_host_manufacturer(lport->host),
763 FC_SERIAL_NUMBER_SIZE,
764 "%s",
765 fdmi.manufacturer);
766 snprintf(fc_host_model(lport->host),
767 FC_SYMBOLIC_NAME_SIZE,
768 "%s",
769 fdmi.model);
770 snprintf(fc_host_model_description(lport->host),
771 FC_SYMBOLIC_NAME_SIZE,
772 "%s",
773 fdmi.model_description);
774 snprintf(fc_host_hardware_version(lport->host),
775 FC_VERSION_STRING_SIZE,
776 "%s",
777 fdmi.hardware_version);
778 snprintf(fc_host_driver_version(lport->host),
779 FC_VERSION_STRING_SIZE,
780 "%s",
781 fdmi.driver_version);
782 snprintf(fc_host_optionrom_version(lport->host),
783 FC_VERSION_STRING_SIZE,
784 "%s",
785 fdmi.optionrom_version);
786 snprintf(fc_host_firmware_version(lport->host),
787 FC_VERSION_STRING_SIZE,
788 "%s",
789 fdmi.firmware_version);
790
791 /* Enable FDMI lport states */
792 lport->fdmi_enabled = 1;
793 } else {
794 lport->fdmi_enabled = 0;
795 printk(KERN_INFO "fcoe: No FDMI support.\n");
796 }
797}
798
737/** 799/**
738 * fcoe_oem_match() - The match routine for the offloaded exchange manager 800 * fcoe_oem_match() - The match routine for the offloaded exchange manager
739 * @fp: The I/O frame 801 * @fp: The I/O frame
@@ -881,9 +943,6 @@ static void fcoe_if_destroy(struct fc_lport *lport)
881 dev_uc_del(netdev, port->data_src_addr); 943 dev_uc_del(netdev, port->data_src_addr);
882 rtnl_unlock(); 944 rtnl_unlock();
883 945
884 /* Release reference held in fcoe_if_create() */
885 fcoe_interface_put(fcoe);
886
887 /* Free queued packets for the per-CPU receive threads */ 946 /* Free queued packets for the per-CPU receive threads */
888 fcoe_percpu_clean(lport); 947 fcoe_percpu_clean(lport);
889 948
@@ -1047,6 +1106,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
1047 goto out_lp_destroy; 1106 goto out_lp_destroy;
1048 } 1107 }
1049 1108
1109 /* Initialized FDMI information */
1110 fcoe_fdmi_info(lport, netdev);
1111
1050 /* 1112 /*
1051 * fcoe_em_alloc() and fcoe_hostlist_add() both 1113 * fcoe_em_alloc() and fcoe_hostlist_add() both
1052 * need to be atomic with respect to other changes to the 1114 * need to be atomic with respect to other changes to the
@@ -1070,7 +1132,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
1070 goto out_lp_destroy; 1132 goto out_lp_destroy;
1071 } 1133 }
1072 1134
1073 fcoe_interface_get(fcoe);
1074 return lport; 1135 return lport;
1075 1136
1076out_lp_destroy: 1137out_lp_destroy:
@@ -2009,20 +2070,13 @@ static void fcoe_destroy_work(struct work_struct *work)
2009{ 2070{
2010 struct fcoe_port *port; 2071 struct fcoe_port *port;
2011 struct fcoe_interface *fcoe; 2072 struct fcoe_interface *fcoe;
2012 int npiv = 0;
2013 2073
2014 port = container_of(work, struct fcoe_port, destroy_work); 2074 port = container_of(work, struct fcoe_port, destroy_work);
2015 mutex_lock(&fcoe_config_mutex); 2075 mutex_lock(&fcoe_config_mutex);
2016 2076
2017 /* set if this is an NPIV port */
2018 npiv = port->lport->vport ? 1 : 0;
2019
2020 fcoe = port->priv; 2077 fcoe = port->priv;
2021 fcoe_if_destroy(port->lport); 2078 fcoe_if_destroy(port->lport);
2022 2079 fcoe_interface_cleanup(fcoe);
2023 /* Do not tear down the fcoe interface for NPIV port */
2024 if (!npiv)
2025 fcoe_interface_cleanup(fcoe);
2026 2080
2027 mutex_unlock(&fcoe_config_mutex); 2081 mutex_unlock(&fcoe_config_mutex);
2028} 2082}
@@ -2593,12 +2647,15 @@ static int fcoe_vport_destroy(struct fc_vport *vport)
2593 struct Scsi_Host *shost = vport_to_shost(vport); 2647 struct Scsi_Host *shost = vport_to_shost(vport);
2594 struct fc_lport *n_port = shost_priv(shost); 2648 struct fc_lport *n_port = shost_priv(shost);
2595 struct fc_lport *vn_port = vport->dd_data; 2649 struct fc_lport *vn_port = vport->dd_data;
2596 struct fcoe_port *port = lport_priv(vn_port);
2597 2650
2598 mutex_lock(&n_port->lp_mutex); 2651 mutex_lock(&n_port->lp_mutex);
2599 list_del(&vn_port->list); 2652 list_del(&vn_port->list);
2600 mutex_unlock(&n_port->lp_mutex); 2653 mutex_unlock(&n_port->lp_mutex);
2601 queue_work(fcoe_wq, &port->destroy_work); 2654
2655 mutex_lock(&fcoe_config_mutex);
2656 fcoe_if_destroy(vn_port);
2657 mutex_unlock(&fcoe_config_mutex);
2658
2602 return 0; 2659 return 0;
2603} 2660}
2604 2661