From 6fef3902889ade6270a942cc2554252dbff1146c Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Sun, 22 Jan 2012 17:30:10 -0800 Subject: [SCSI] fcoe: Add support for FDMI in fcoe This adds support for updating the FC-GS FDMI attributes in the fcoe driver. Signed-off-by: Neerav Parikh Tested-by: Ross Brattain Acked-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'drivers/scsi/fcoe') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index e9599600aa23..b222e2dd5def 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -734,6 +734,85 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev) return 0; } + +/** + * fcoe_fdmi_info() - Get FDMI related info from net devive for SW FCoE + * @lport: The local port that is associated with the net device + * @netdev: The associated net device + * + * Must be called after fcoe_shost_config() as it will use local port mutex + * + */ +static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev) +{ + struct fcoe_interface *fcoe; + struct fcoe_port *port; + struct net_device *realdev; + int rc; + struct netdev_fcoe_hbainfo fdmi; + + port = lport_priv(lport); + fcoe = port->priv; + realdev = fcoe->realdev; + + if (!realdev) + return; + + /* No FDMI state m/c for NPIV ports */ + if (lport->vport) + return; + + if (realdev->netdev_ops->ndo_fcoe_get_hbainfo) { + memset(&fdmi, 0, sizeof(fdmi)); + rc = realdev->netdev_ops->ndo_fcoe_get_hbainfo(realdev, + &fdmi); + if (rc) { + printk(KERN_INFO "fcoe: Failed to retrieve FDMI " + "information from netdev.\n"); + return; + } + + snprintf(fc_host_serial_number(lport->host), + FC_SERIAL_NUMBER_SIZE, + "%s", + fdmi.serial_number); + snprintf(fc_host_manufacturer(lport->host), + FC_SERIAL_NUMBER_SIZE, + "%s", + fdmi.manufacturer); + snprintf(fc_host_model(lport->host), + FC_SYMBOLIC_NAME_SIZE, + "%s", + fdmi.model); + snprintf(fc_host_model_description(lport->host), + FC_SYMBOLIC_NAME_SIZE, + "%s", + fdmi.model_description); + snprintf(fc_host_hardware_version(lport->host), + FC_VERSION_STRING_SIZE, + "%s", + fdmi.hardware_version); + snprintf(fc_host_driver_version(lport->host), + FC_VERSION_STRING_SIZE, + "%s", + fdmi.driver_version); + snprintf(fc_host_optionrom_version(lport->host), + FC_VERSION_STRING_SIZE, + "%s", + fdmi.optionrom_version); + snprintf(fc_host_firmware_version(lport->host), + FC_VERSION_STRING_SIZE, + "%s", + fdmi.firmware_version); + + /* Enable FDMI lport states */ + lport->fdmi_enabled = 1; + } else { + lport->fdmi_enabled = 0; + printk(KERN_INFO "fcoe: No FDMI support.\n"); + } +} + /** * fcoe_oem_match() - The match routine for the offloaded exchange manager * @fp: The I/O frame @@ -1047,6 +1126,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, goto out_lp_destroy; } + /* Initialized FDMI information */ + fcoe_fdmi_info(lport, netdev); + /* * fcoe_em_alloc() and fcoe_hostlist_add() both * need to be atomic with respect to other changes to the -- cgit From 9f71af2febd53620a379d71527f98bbc2ba67e61 Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Sun, 22 Jan 2012 17:30:16 -0800 Subject: [SCSI] fcoe: Allow exposing FDMI attributes via sysfs Allow FDMI attributes to be exposed via the fc_host class object for the fcoe driver. Signed-off-by: Neerav Parikh Tested-by: Ross Brattain Acked-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/scsi/fcoe') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index b222e2dd5def..5e77f23423db 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 = { .show_host_supported_fc4s = 1, .show_host_active_fc4s = 1, .show_host_maxframe_size = 1, + .show_host_serial_number = 1, + .show_host_manufacturer = 1, + .show_host_model = 1, + .show_host_model_description = 1, + .show_host_hardware_version = 1, + .show_host_driver_version = 1, + .show_host_firmware_version = 1, + .show_host_optionrom_version = 1, .show_host_port_id = 1, .show_host_supported_speeds = 1, -- cgit From b99fbf6a4e96ecacadf0f4868942774e0d64a648 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 10 Feb 2012 17:17:59 -0800 Subject: [SCSI] libfcoe: Don't KERN_ERR on netdev notification This is more of a debug statement. As a KERN_ERR we generate log entries anytime any netdev goes up or down, so when booting there are notification log entries for all system interfaces including 'lo'. This is too much. Let's just log when necessary. Signed-off-by: Robert Love Tested-by: Ross Brattain Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_transport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/fcoe') diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index bd97b2273f20..0897be0ad7b6 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -620,8 +620,8 @@ static int libfcoe_device_notification(struct notifier_block *notifier, switch (event) { case NETDEV_UNREGISTER: - printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n", - netdev->name); + LIBFCOE_TRANSPORT_DBG("NETDEV_UNREGISTER %s\n", + netdev->name); fcoe_del_netdev_mapping(netdev); break; } -- cgit From 7e5adcfb31c26a68b75a249ef1c7f52fc5ec6e1b Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Fri, 10 Feb 2012 17:18:31 -0800 Subject: [SCSI] fcoe: Allow exposing FDMI attributes via sysfs Allow FDMI attributes to be exposed via the fc_host class object for the fcoe driver. Signed-off-by: Neerav Parikh Tested-by: Ross Brattain Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/scsi/fcoe') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 5e77f23423db..67f6685de7fd 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -216,6 +216,14 @@ static struct fc_function_template fcoe_vport_fc_functions = { .show_host_supported_fc4s = 1, .show_host_active_fc4s = 1, .show_host_maxframe_size = 1, + .show_host_serial_number = 1, + .show_host_manufacturer = 1, + .show_host_model = 1, + .show_host_model_description = 1, + .show_host_hardware_version = 1, + .show_host_driver_version = 1, + .show_host_firmware_version = 1, + .show_host_optionrom_version = 1, .show_host_port_id = 1, .show_host_supported_speeds = 1, -- cgit From 6f68794c9283bbce3f7c91d3be34cb4f4f6ed960 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 10 Feb 2012 17:18:36 -0800 Subject: [SCSI] fcoe: Rename out_nomod label to out_putmod The label implies that it should be called when there is 'nomod.' I read that to mean that the module reference 'get' failed. However, it's only called when the module reference 'get' succeeded. I think it makes more sense to name the label, 'out_putmod' since it should be called when we need to 'put' the module reference taken in the routine before returning. Signed-off-by: Robert Love Tested-by: Ross Brattain Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/fcoe') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 67f6685de7fd..449d31ea07bd 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -380,7 +380,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, if (!fcoe) { FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); fcoe = ERR_PTR(-ENOMEM); - goto out_nomod; + goto out_putmod; } dev_hold(netdev); @@ -400,12 +400,12 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, kfree(fcoe); dev_put(netdev); fcoe = ERR_PTR(err); - goto out_nomod; + goto out_putmod; } goto out; -out_nomod: +out_putmod: module_put(THIS_MODULE); out: return fcoe; -- cgit From ccefd23ed2d683ad3c0282280e6e6d0b163ad041 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 10 Feb 2012 17:18:41 -0800 Subject: [SCSI] fcoe: Do not switch context in vport_delete callback Currently all port deletion is routed though the FCoE workqueue (fcoe_wq). When fc_remove_host is called on an N_Port (for example, from fcoe_destroy) the vports are queued into a FC Transport workqueue. fc_remove_host flushes that queue and each vport is passed to fcoe's fcoe_vport_destroy, which simply queues the associated fcoe_ports for later deletion. This queue cannot be flushed within the N_Ports destroy path because of circular locking issues. The result is that the NPIV ports are destroyed after the N_Port, which is reverse of how they are created. This quirk causes fcoe to keep references on the fcoe_interface shared by each of these ports (N_Port and NPIV). Changing the ordering such that NPIV ports are destroyed before the N_Port will allow us to remove reference counting on the fcoe_interface instances. This patch simply allows fcoe_vport_destory to destroy NPIV ports without deferring them to a workqueue context. This ensures that when fc_remove_host is called the NPIV ports will be destroyed first before the N_Port and allows reference counting on the fcoe's fcoe_interface to be remove in a later patch. Signed-off-by: Robert Love Tested-by: Ross Brattain Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/scsi/fcoe') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 449d31ea07bd..5126685ab982 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2107,20 +2107,14 @@ static void fcoe_destroy_work(struct work_struct *work) { struct fcoe_port *port; struct fcoe_interface *fcoe; - int npiv = 0; port = container_of(work, struct fcoe_port, destroy_work); mutex_lock(&fcoe_config_mutex); - /* set if this is an NPIV port */ - npiv = port->lport->vport ? 1 : 0; - fcoe = port->priv; fcoe_if_destroy(port->lport); - /* Do not tear down the fcoe interface for NPIV port */ - if (!npiv) - fcoe_interface_cleanup(fcoe); + fcoe_interface_cleanup(fcoe); mutex_unlock(&fcoe_config_mutex); } @@ -2691,12 +2685,15 @@ static int fcoe_vport_destroy(struct fc_vport *vport) struct Scsi_Host *shost = vport_to_shost(vport); struct fc_lport *n_port = shost_priv(shost); struct fc_lport *vn_port = vport->dd_data; - struct fcoe_port *port = lport_priv(vn_port); mutex_lock(&n_port->lp_mutex); list_del(&vn_port->list); mutex_unlock(&n_port->lp_mutex); - queue_work(fcoe_wq, &port->destroy_work); + + mutex_lock(&fcoe_config_mutex); + fcoe_if_destroy(vn_port); + mutex_unlock(&fcoe_config_mutex); + return 0; } -- cgit From 1a8ef414d97bf3f293e286f02002f8db768f9867 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 10 Feb 2012 17:18:46 -0800 Subject: [SCSI] fcoe: Remove reference counting on 'stuct fcoe_interface' The reference counting was necessary on these instances because it was possible for NPIV ports to be destroyed after the N_Port. A previous patch ensures that all NPIV ports are destroyed before the N_Port making the need to track references on the interface unnecessary. Signed-off-by: Robert Love Tested-by: Ross Brattain Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 48 +++++------------------------------------------- drivers/scsi/fcoe/fcoe.h | 3 --- 2 files changed, 5 insertions(+), 46 deletions(-) (limited to 'drivers/scsi/fcoe') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 5126685ab982..278958157e24 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -384,7 +384,6 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, } dev_hold(netdev); - kref_init(&fcoe->kref); /* * Initialize FIP. @@ -411,42 +410,6 @@ out: return fcoe; } -/** - * fcoe_interface_release() - fcoe_port kref release function - * @kref: Embedded reference count in an fcoe_interface struct - */ -static void fcoe_interface_release(struct kref *kref) -{ - struct fcoe_interface *fcoe; - struct net_device *netdev; - - fcoe = container_of(kref, struct fcoe_interface, kref); - netdev = fcoe->netdev; - /* tear-down the FCoE controller */ - fcoe_ctlr_destroy(&fcoe->ctlr); - kfree(fcoe); - dev_put(netdev); - module_put(THIS_MODULE); -} - -/** - * fcoe_interface_get() - Get a reference to a FCoE interface - * @fcoe: The FCoE interface to be held - */ -static inline void fcoe_interface_get(struct fcoe_interface *fcoe) -{ - kref_get(&fcoe->kref); -} - -/** - * fcoe_interface_put() - Put a reference to a FCoE interface - * @fcoe: The FCoE interface to be released - */ -static inline void fcoe_interface_put(struct fcoe_interface *fcoe) -{ - kref_put(&fcoe->kref, fcoe_interface_release); -} - /** * fcoe_interface_cleanup() - Clean up a FCoE interface * @fcoe: The FCoE interface to be cleaned up @@ -494,7 +457,11 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) rtnl_unlock(); /* Release the self-reference taken during fcoe_interface_create() */ - fcoe_interface_put(fcoe); + /* tear-down the FCoE controller */ + fcoe_ctlr_destroy(fip); + kfree(fcoe); + dev_put(netdev); + module_put(THIS_MODULE); } /** @@ -976,9 +943,6 @@ static void fcoe_if_destroy(struct fc_lport *lport) dev_uc_del(netdev, port->data_src_addr); rtnl_unlock(); - /* Release reference held in fcoe_if_create() */ - fcoe_interface_put(fcoe); - /* Free queued packets for the per-CPU receive threads */ fcoe_percpu_clean(lport); @@ -1168,7 +1132,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, goto out_lp_destroy; } - fcoe_interface_get(fcoe); return lport; out_lp_destroy: @@ -2113,7 +2076,6 @@ static void fcoe_destroy_work(struct work_struct *work) fcoe = port->priv; fcoe_if_destroy(port->lport); - fcoe_interface_cleanup(fcoe); mutex_unlock(&fcoe_config_mutex); diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index bcc89e639495..3c2733a12aa1 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h @@ -71,8 +71,6 @@ do { \ * @ctlr: The FCoE controller (for FIP) * @oem: The offload exchange manager for all local port * instances associated with this port - * @kref: The kernel reference - * * This structure is 1:1 with a net devive. */ struct fcoe_interface { @@ -83,7 +81,6 @@ struct fcoe_interface { struct packet_type fip_packet_type; struct fcoe_ctlr ctlr; struct fc_exch_mgr *oem; - struct kref kref; }; #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) -- cgit