* [RFC PATCH 5/6] fc_sysfs: Rearrange the FC transport to create FC sysfs
2010-01-27 23:24 [RFC PATCH 0/6] Work In Progress: FC sysfs Robert Love
` (3 preceding siblings ...)
2010-01-27 23:24 ` [RFC PATCH 4/6] libfc: Move the port_id into lport Robert Love
@ 2010-01-27 23:24 ` Robert Love
2010-01-27 23:24 ` [RFC PATCH 6/6] libfc, libfcoe, fcoe: Make use of " Robert Love
2010-01-28 16:01 ` [RFC PATCH 0/6] Work In Progress: " Hannes Reinecke
6 siblings, 0 replies; 10+ messages in thread
From: Robert Love @ 2010-01-27 23:24 UTC (permalink / raw)
To: linux-scsi, james.smart; +Cc: giridhar.malavali
This patch moves code from scsi_transport_fc.[ch] into
drivers/scsi/fc/* and include/scsi/fc.h. It creates new
sysfs objects to represent various FC entities in the
FC/FCoE environment. Currently it only modifies FC objects
and attributes, but I would want FCoE attributes added
once the layout matures.
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/Kconfig | 6
drivers/scsi/Makefile | 1
drivers/scsi/fc/Makefile | 8
drivers/scsi/fc/fc_sysfs.h | 35 +
drivers/scsi/fc/fcfabric.c | 441 ++++++++++++
drivers/scsi/fc/fcfport.c | 73 ++
drivers/scsi/fc/fcpinit.c | 66 ++
drivers/scsi/fc/fcport.c | 217 ++++++
drivers/scsi/fc/fcsysfs.c | 41 +
drivers/scsi/fc/fcvport.c | 485 +++++++++++++
drivers/scsi/scsi_transport_fc.c | 1411 ++++++--------------------------------
include/scsi/fc.h | 461 ++++++++++++
include/scsi/scsi_transport_fc.h | 329 ++-------
13 files changed, 2140 insertions(+), 1434 deletions(-)
create mode 100644 drivers/scsi/fc/Makefile
create mode 100644 drivers/scsi/fc/fc_sysfs.h
create mode 100644 drivers/scsi/fc/fcfabric.c
create mode 100644 drivers/scsi/fc/fcfport.c
create mode 100644 drivers/scsi/fc/fcpinit.c
create mode 100644 drivers/scsi/fc/fcport.c
create mode 100644 drivers/scsi/fc/fcsysfs.c
create mode 100644 drivers/scsi/fc/fcvport.c
create mode 100644 include/scsi/fc.h
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 9191d1e..f9130ab 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -650,9 +650,15 @@ config VMWARE_PVSCSI
To compile this driver as a module, choose M here: the
module will be called vmw_pvscsi.
+config FC_SYSFS
+ tristate "Fibre Channel sysfs representation"
+ ---help---
+ Expiramental representation of FC objects in sysfs
+
config LIBFC
tristate "LibFC module"
select SCSI_FC_ATTRS
+ select FC_SYSFS
select CRC32
---help---
Fibre Channel library module
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 92a8c50..071b757 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas/
obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o
obj-$(CONFIG_SCSI_DH) += device_handler/
+obj-$(CONFIG_FC_SYSFS) += fc/
obj-$(CONFIG_LIBFC) += libfc/
obj-$(CONFIG_LIBFCOE) += fcoe/
obj-$(CONFIG_FCOE) += fcoe/
diff --git a/drivers/scsi/fc/Makefile b/drivers/scsi/fc/Makefile
new file mode 100644
index 0000000..c3393b6
--- /dev/null
+++ b/drivers/scsi/fc/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_FC_SYSFS) += fc_sysfs.o
+
+fc_sysfs-objs := fcsysfs.o \
+ fcport.o \
+ fcfport.o \
+ fcfabric.o \
+ fcvport.o \
+ fcpinit.o
\ No newline at end of file
diff --git a/drivers/scsi/fc/fc_sysfs.h b/drivers/scsi/fc/fc_sysfs.h
new file mode 100644
index 0000000..757d5c1
--- /dev/null
+++ b/drivers/scsi/fc/fc_sysfs.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _FC_SYSFS_H_
+#define _FC_SYSFS_H_
+
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <scsi/fc.h>
+
+extern struct class fc_class;
+
+int fc_class_del_children(struct device *dev, void *data);
+int fc_fcfport_del_children(struct device *dev, void *data);
+int fc_fcfabric_del_children(struct device *dev, void *data);
+int fc_fcvport_del_children(struct device *dev, void *data);
+int fc_fcpinit_del_children(struct device *dev, void *data);
+
+int fc_vport_terminate(struct fc_fcfabric *, struct fc_fcvport *vport);
+
+#endif /*_FC_SYSFS_H_*/
diff --git a/drivers/scsi/fc/fcfabric.c b/drivers/scsi/fc/fcfabric.c
new file mode 100644
index 0000000..d6b4b99
--- /dev/null
+++ b/drivers/scsi/fc/fcfabric.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "fc_sysfs.h"
+
+#define fc_private_fcfabric_rd_attr(field, format_string, sz) \
+ fc_always_show_function(fcfabric, field, format_string, sz, ) \
+ static FC_DEVICE_ATTR(fcfabric, field, S_IRUGO, \
+ show_fcfabric_##field, NULL)
+
+#define fcfabric_rd_attr_cast(field, format_string, sz, cast) \
+ fc_conditional_show_function(fcfabric, field, format_string, sz, (cast)) \
+ static FC_DEVICE_ATTR(fcfabric, field, S_IRUGO, \
+ show_fcfabric_##field, NULL)
+
+fcfabric_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);
+fc_private_fcfabric_rd_attr(max_npiv_vports, "%u\n", 20);
+fc_private_fcfabric_rd_attr(npiv_vports_inuse, "%u\n", 20);
+
+static int
+fc_parse_wwn(const char *ns, u64 *nm)
+{
+ unsigned int i, j;
+ u8 wwn[8];
+
+ memset(wwn, 0, sizeof(wwn));
+
+ /* Validate and store the new name */
+ for (i=0, j=0; i < 16; i++) {
+ if ((*ns >= 'a') && (*ns <= 'f'))
+ j = ((j << 4) | ((*ns++ -'a') + 10));
+ else if ((*ns >= 'A') && (*ns <= 'F'))
+ j = ((j << 4) | ((*ns++ -'A') + 10));
+ else if ((*ns >= '0') && (*ns <= '9'))
+ j = ((j << 4) | (*ns++ -'0'));
+ else
+ return -EINVAL;
+ if (i % 2) {
+ wwn[i/2] = j & 0xff;
+ j = 0;
+ }
+ }
+
+ *nm = wwn_to_u64(wwn);
+
+ return 0;
+}
+
+/**
+ * fc_vport_setup - allocates and creates a FC virtual port.
+ * @shost: scsi host the virtual port is connected to.
+ * @channel: Channel on shost port connected to.
+ * @pdev: parent device for vport
+ * @ids: The world wide names, FC4 port roles, etc for
+ * the virtual port.
+ * @ret_vport: The pointer to the created vport.
+ *
+ * Allocates and creates the vport structure, calls the parent host
+ * to instantiate the vport, the completes w/ class and sysfs creation.
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
+ */
+static int
+fc_vport_setup(struct fc_fcfabric *fcfabric, int channel,
+ struct fc_vport_identifiers *ids, struct fc_fcvport **ret_vport)
+{
+ struct fc_fcvport *fcvport;
+ unsigned long flags;
+
+ *ret_vport = NULL;
+
+ if (!fcfabric->f->vport_create)
+ return -ENOENT;
+
+ fcvport = fc_fcvport_alloc(fcfabric, ids, fcfabric->fcvport_f,
+ fcfabric->f->dd_fcvport_size);
+ if (unlikely(!fcvport)) {
+ printk(KERN_ERR "%s: allocation failure\n", __func__);
+ return -ENOMEM;
+ }
+
+ spin_lock_irqsave(&fcfabric->lock, flags);
+
+ if (fcfabric->npiv_vports_inuse >= fcfabric->max_npiv_vports) {
+ spin_unlock_irqrestore(&fcfabric->lock, flags);
+ kfree(fcvport);
+ return -ENOSPC;
+ }
+
+ fcfabric->npiv_vports_inuse++;
+ fcvport->number = fcfabric->next_vport_number++;
+ list_add_tail(&fcvport->peers, &fcfabric->vports);
+
+ spin_unlock_irqrestore(&fcfabric->lock, flags);
+
+ /*
+ * TODO: Make sure this is getting released
+
+ get_device(&fcfabric->gendev); for fc_host->vport list
+
+ error = fc_fcvport_add(fcvport, fcfabric);
+ if (error) {
+ printk(KERN_ERR "FC Virtual Port device_add failed\n");
+ goto delete_vport;
+ }
+
+ *ret_vport = fcvport;
+*/
+ return 0;
+
+//delete_vport_all:
+// device_del(dev);
+/*
+delete_vport:
+
+ * TODO: This error handling is sketchy. It needs to
+ * be examined.
+
+// transport_destroy_device(dev);
+ spin_lock_irqsave(&fcfabric->lock, flags);
+ list_del(&fcvport->peers);
+// put_device(&shost->shost_gendev); for fc_host->vport list
+ fcfabric->npiv_vports_inuse--;
+
+ spin_unlock_irqrestore(&fcfabric->lock, flags);
+// put_device(dev->parent);
+ kfree(fcvport);
+
+ return error;
+*/
+}
+
+/**
+ * fc_vport_create - Admin App or LLDD requests creation of a vport
+ * @shost: scsi host the virtual port is connected to.
+ * @channel: channel on shost port connected to.
+ * @ids: The world wide names, FC4 port roles, etc for
+ * the virtual port.
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
+ */
+struct fc_fcvport *
+fc_vport_create(struct fc_fcfabric *fcfabric, int channel,
+ struct fc_vport_identifiers *ids)
+{
+ int stat;
+ struct fc_fcvport *vport;
+
+ stat = fc_vport_setup(fcfabric, channel, ids, &vport);
+
+ return stat ? NULL : vport;
+}
+EXPORT_SYMBOL(fc_vport_create);
+
+/**
+ * fc_vport_terminate - Admin App or LLDD requests termination of a vport
+ * @vport: fc_vport to be terminated
+ *
+ * Calls the LLDD vport_delete() function, then deallocates and removes
+ * the vport from the shost and object tree.
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
+ */
+int
+fc_vport_terminate(struct fc_fcfabric *fcfabric, struct fc_fcvport *vport)
+{
+ struct device *dev = &vport->gendev;
+ struct fc_fcvport *fcnport;
+ unsigned long flags;
+ int stat = 0;
+
+ spin_lock_irqsave(&vport->lock, flags);
+ if (vport->flags & FC_VPORT_CREATING) {
+ spin_unlock_irqrestore(&vport->lock, flags);
+ return -EBUSY;
+ }
+ if (vport->flags & (FC_VPORT_DEL)) {
+ spin_unlock_irqrestore(&vport->lock, flags);
+ return -EALREADY;
+ }
+ vport->flags |= FC_VPORT_DELETING;
+ spin_unlock_irqrestore(&vport->lock, flags);
+
+ if (fcfabric->f->vport_delete) {
+ fcnport = fc_fcfabric_find_nport(fcfabric);
+ if (fcnport)
+ stat = fcfabric->f->vport_delete(fcnport->priv_data, vport);
+ } else
+ stat = -ENOENT;
+
+ spin_lock_irqsave(&fcfabric->lock, flags);
+ vport->flags &= ~FC_VPORT_DELETING;
+ if (!stat) {
+ vport->flags |= FC_VPORT_DELETED;
+ list_del(&vport->peers);
+ vport->fcfabric->npiv_vports_inuse--;
+// put_device(&shost->shost_gendev); /* for fc_host->vport list */
+ }
+ spin_unlock_irqrestore(&fcfabric->lock, flags);
+
+ if (stat)
+ return stat;
+
+ /*
+ * TODO: What is this stuff? I probably need to do something here.
+
+ if (dev->parent != &shost->shost_gendev)
+ sysfs_remove_link(&shost->shost_gendev.kobj, dev_name(dev));
+ */
+// transport_remove_device(dev);
+ device_del(dev);
+// transport_destroy_device(dev);
+
+ /*
+ * Removing our self-reference should mean our
+ * release function gets called, which will drop the remaining
+ * parent reference and free the data structure.
+ */
+ put_device(dev); /* for self-reference */
+
+ return 0; /* SUCCESS */
+}
+EXPORT_SYMBOL(fc_vport_terminate);
+
+/*
+ * "Short-cut" sysfs variable to create a new vport on a FC Host.
+ * Input is a string of the form "<WWPN>:<WWNN>". Other attributes
+ * will default to a NPIV-based FCP_Initiator; The WWNs are specified
+ * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
+ */
+static ssize_t
+store_fcfabric_vport_create(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fc_fcfabric *fcfabric = dev_to_fcfabric(dev);
+ struct fc_vport_identifiers vid;
+ struct fc_fcvport *fcvport;
+ unsigned int cnt = count;
+ int stat;
+
+ memset(&vid, 0, sizeof(vid));
+
+ /* count may include a LF at end of string */
+ if (buf[cnt-1] == '\n')
+ cnt--;
+
+ /* validate we have enough characters for WWPN */
+ if ((cnt != (16+1+16)) || (buf[16] != ':'))
+ return -EINVAL;
+
+ stat = fc_parse_wwn(&buf[0], &vid.port_name);
+ if (stat)
+ return stat;
+
+ stat = fc_parse_wwn(&buf[17], &vid.node_name);
+ if (stat)
+ return stat;
+
+ vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
+ vid.vport_type = FC_PORTTYPE_NPIV;
+ /* vid.symbolic_name is already zero/NULL's */
+ vid.disable = false; /* always enabled */
+
+ /* we only allow support on Channel 0 !!! */
+ stat = fc_vport_setup(fcfabric, 0, &vid, &fcvport);
+
+ return stat ? stat : count;
+}
+static FC_DEVICE_ATTR(fcfabric, vport_create, S_IWUSR, NULL,
+ store_fcfabric_vport_create);
+
+
+/*
+ * "Short-cut" sysfs variable to delete a vport on a FC Host.
+ * Vport is identified by a string containing "<WWPN>:<WWNN>".
+ * The WWNs are specified as hex characters, and may *not* contain
+ * any prefixes (e.g. 0x, x, etc)
+ */
+static ssize_t
+store_fcfabric_vport_delete(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fc_fcfabric *fcfabric = dev_to_fcfabric(dev);
+ struct fc_fcvport *vport;
+ u64 wwpn, wwnn;
+ unsigned long flags;
+ unsigned int cnt=count;
+ int stat, match;
+
+ /* count may include a LF at end of string */
+ if (buf[cnt-1] == '\n')
+ cnt--;
+
+ /* validate we have enough characters for WWPN */
+ if ((cnt != (16+1+16)) || (buf[16] != ':'))
+ return -EINVAL;
+
+ stat = fc_parse_wwn(&buf[0], &wwpn);
+ if (stat)
+ return stat;
+
+ stat = fc_parse_wwn(&buf[17], &wwnn);
+ if (stat)
+ return stat;
+
+ spin_lock_irqsave(&fcfabric->lock, flags);
+ match = 0;
+ /* we only allow support on Channel 0 !!! */
+ list_for_each_entry(vport, &fcfabric->vports, peers) {
+ if ((vport->channel == 0) &&
+ (vport->port_name == wwpn) && (vport->node_name == wwnn)) {
+ match = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&fcfabric->lock, flags);
+
+ if (!match)
+ return -ENODEV;
+
+ stat = fc_vport_terminate(fcfabric, vport);
+ return stat ? stat : count;
+}
+static FC_DEVICE_ATTR(fcfabric, vport_delete, S_IWUSR, NULL,
+ store_fcfabric_vport_delete);
+
+
+static void fc_fcfabric_release(struct device *dev)
+{
+ struct fc_fcfabric *fcfabric = dev_to_fcfabric(dev);
+ put_device(fcfabric->gendev.parent);
+ kfree(fcfabric);
+}
+
+void fc_fcfabric_del(struct fc_fcfabric *fcfabric)
+{
+ device_del(&fcfabric->gendev);
+ put_device(&fcfabric->gendev); /* self-reference */
+}
+
+struct fc_fcfabric *fc_fcfabric_add(struct fc_fcfport *fcfport,
+ struct fcfabric_function_template *fcn_tmpl)
+{
+ struct fc_fcfabric *fcfabric;
+ int error = 0;
+ int count = 0;
+
+ fcfabric = kzalloc(sizeof(struct fc_fcfabric), GFP_KERNEL);
+
+ device_initialize(&fcfabric->gendev);
+ fcfabric->gendev.parent = get_device(&fcfport->gendev);
+ fcfabric->gendev.release = fc_fcfabric_release;
+
+ fcfabric->f = fcn_tmpl;
+ dev_set_name(&fcfabric->gendev, "fcfabric_%d", 0);
+
+ spin_lock_init(&fcfabric->lock);
+ INIT_LIST_HEAD(&fcfabric->vports);
+
+ fcfabric->fabric_name = -1;
+ fcfabric->max_npiv_vports = 0;
+ fcfabric->next_vport_number = 0;
+ fcfabric->npiv_vports_inuse = 0;
+
+ error = device_add(&fcfabric->gendev);
+ if (error)
+ goto out_del_gendev;
+
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcfabric, fabric_name);
+ if (fcn_tmpl->vport_create) {
+ FC_SETUP_ALWAYS_ATTRIBUTE_RD_NS(fcfabric, max_npiv_vports);
+ FC_SETUP_ALWAYS_ATTRIBUTE_RD_NS(fcfabric, npiv_vports_inuse);
+ }
+
+ if (fcn_tmpl->vport_create)
+ FC_SETUP_ALWAYS_ATTRIBUTE_RW(fcfabric, vport_create);
+ if (fcn_tmpl->vport_delete)
+ FC_SETUP_ALWAYS_ATTRIBUTE_RW(fcfabric, vport_delete);
+
+ BUG_ON(count > FCFABRIC_NUM_ATTRS);
+ FC_CREATE_ATTRIBUTES(fcfabric);
+
+ if (error || count != 0)
+ goto out_del_gendev;
+
+ return fcfabric;
+
+out_del_gendev:
+ device_del(&fcfabric->gendev);
+ kfree(fcfabric);
+ return NULL;
+}
+EXPORT_SYMBOL(fc_fcfabric_add);
+
+int fc_fcfabric_del_children(struct device *dev, void *data)
+{
+ struct fc_fcfabric *fcfabric = dev_to_fcfabric(dev);
+ int error = 0;
+
+ /*
+ * TODO: How should I remove vports? Using the fcfabric list or
+ * using the sysfs device_for_each_child() interface?
+ *
+ * Need to understand why these deletes are being queued.
+
+
+ Remove any vports
+ list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers)
+ fc_queue_work(shost, &vport->vport_delete_work);
+ */
+ error = device_for_each_child(dev, NULL, fc_fcvport_del_children);
+ if (!error)
+ fc_fcfabric_del(fcfabric);
+ return error;
+}
+
+struct fc_fcvport *fc_fcfabric_find_nport(struct fc_fcfabric *fcfabric)
+{
+ struct device *dev = device_find_child(&fcfabric->gendev, NULL, fc_fcvport_is_nport);
+ if (!dev)
+ return NULL;
+ return dev_to_fcvport(dev);
+}
+EXPORT_SYMBOL(fc_fcfabric_find_nport);
diff --git a/drivers/scsi/fc/fcfport.c b/drivers/scsi/fc/fcfport.c
new file mode 100644
index 0000000..107bb5a
--- /dev/null
+++ b/drivers/scsi/fc/fcfport.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "fc_sysfs.h"
+
+static void fc_fcfport_release(struct device *dev)
+{
+ struct fc_fcfport *fcfport = dev_to_fcfport(dev);
+ put_device(fcfport->gendev.parent);
+ kfree(fcfport);
+}
+
+void fc_fcfport_del(struct fc_fcfport *fcfport)
+{
+ device_del(&fcfport->gendev);
+ put_device(&fcfport->gendev); /* self-reference */
+}
+
+struct fc_fcfport *fc_fcfport_add(struct fc_fcport *fcport, const u64 name)
+{
+ struct fc_fcfport *fcfport;
+ int error = 0;
+
+ fcfport = kzalloc(sizeof(struct fc_fcfport), GFP_KERNEL);
+ device_initialize(&fcfport->gendev);
+ fcfport->gendev.parent = get_device(&fcport->gendev);
+ fcfport->gendev.release = fc_fcfport_release;
+ dev_set_name(&fcfport->gendev, "fcfport_%llx", name);
+
+ error = device_add(&fcfport->gendev);
+ if (error)
+ goto out_del_gendev;
+
+ /*
+ * TODO: The name is being embedded in the device's name, it's not
+ * being exposed as an attribute. If the name stays in the device's
+ * name then the 'name' member can be removed since its only purpose
+ * is for the attr
+ */
+ fcfport->name = name;
+
+ return fcfport;
+
+out_del_gendev:
+ device_del(&fcfport->gendev);
+ kfree(fcfport);
+ return NULL;
+}
+EXPORT_SYMBOL(fc_fcfport_add);
+
+int fc_fcfport_del_children(struct device *dev, void *data)
+{
+ int error = 0;
+ struct fc_fcfport *fcfport = dev_to_fcfport(dev);
+ error = device_for_each_child(dev, NULL, fc_fcfabric_del_children);
+ if (!error)
+ fc_fcfport_del(fcfport);
+ return error;
+}
diff --git a/drivers/scsi/fc/fcpinit.c b/drivers/scsi/fc/fcpinit.c
new file mode 100644
index 0000000..e251cb1
--- /dev/null
+++ b/drivers/scsi/fc/fcpinit.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Maintained at www.Open-FCoE.org
+ */
+
+#include "fc_sysfs.h"
+
+static void fc_fcpinit_release(struct device *dev)
+{
+ struct fc_fcpinit *fcpinit = dev_to_fcpinit(dev);
+ put_device(fcpinit->gendev.parent);
+ kfree(fcpinit);
+}
+
+void fc_fcpinit_del(struct fc_fcpinit *fcpinit)
+{
+ device_del(&fcpinit->gendev);
+ put_device(&fcpinit->gendev); /* self-reference */
+}
+
+struct fc_fcpinit *fc_fcpinit_add(struct fc_fcvport *fcvport, int hostno)
+{
+ struct fc_fcpinit *fcpinit;
+ int error = 0;
+
+ fcpinit = kzalloc(sizeof(struct fc_fcpinit), GFP_KERNEL);
+
+ device_initialize(&fcpinit->gendev);
+ fcpinit->gendev.parent = get_device(&fcvport->gendev);
+ fcpinit->gendev.release = fc_fcpinit_release;
+ dev_set_name(&fcpinit->gendev, "fcpinit_%d", hostno);
+
+ error = device_add(&fcpinit->gendev);
+ if (error)
+ goto out_del_gendev;
+
+ return fcpinit;
+
+out_del_gendev:
+ printk(KERN_ERR "deleting device, error\n");
+ device_del(&fcpinit->gendev);
+ kfree(fcpinit);
+ return NULL;
+}
+EXPORT_SYMBOL(fc_fcpinit_add);
+
+int fc_fcpinit_del_children(struct device *dev, void *data)
+{
+ struct fc_fcpinit *fcpinit = dev_to_fcpinit(dev);
+ fc_fcpinit_del(fcpinit);
+ return 0;
+}
diff --git a/drivers/scsi/fc/fcport.c b/drivers/scsi/fc/fcport.c
new file mode 100644
index 0000000..b8d8b37
--- /dev/null
+++ b/drivers/scsi/fc/fcport.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "fc_sysfs.h"
+
+static int fcport_count = 0;
+
+/* Convert FC_PORTSPEED bit values to ascii string name */
+static const struct {
+ u32 value;
+ char *name;
+} fc_port_speed_names[] = {
+ { FC_PORTSPEED_1GBIT, "1 Gbit" },
+ { FC_PORTSPEED_2GBIT, "2 Gbit" },
+ { FC_PORTSPEED_4GBIT, "4 Gbit" },
+ { FC_PORTSPEED_10GBIT, "10 Gbit" },
+ { FC_PORTSPEED_8GBIT, "8 Gbit" },
+ { FC_PORTSPEED_16GBIT, "16 Gbit" },
+ { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" },
+};
+fc_bitfield_name_search(port_speed, fc_port_speed_names)
+
+#define fc_fcport_rd_attr(field, format_string, sz) \
+ fc_always_show_function(fcport, field, format_string, sz, ) \
+ static FC_DEVICE_ATTR(fcport, field, S_IRUGO, \
+ show_fcport_##field, NULL)
+
+static int show_fc_fc4s(char *buf, u8 *fc4_list)
+{
+ int i, len=0;
+
+ for (i = 0; i < FC_FC4_LIST_SIZE; i++, fc4_list++)
+ len += sprintf(buf + len , "0x%02x ", *fc4_list);
+ len += sprintf(buf + len, "\n");
+ return len;
+}
+
+static ssize_t show_fcport_supported_fc4s(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fc_fcport *fcport = dev_to_fcport(dev);
+ return (ssize_t)show_fc_fc4s(buf, fcport_supported_fc4s(fcport));
+}
+static FC_DEVICE_ATTR(fcport, supported_fc4s, S_IRUGO,
+ show_fcport_supported_fc4s, NULL);
+
+static ssize_t show_fcport_active_fc4s (struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fc_fcport *fcport = dev_to_fcport(dev);
+ if (fcport->f->get_fcport_active_fc4s)
+ fcport->f->get_fcport_active_fc4s(fcport);
+
+ return (ssize_t)show_fc_fc4s(buf, fcport_active_fc4s(fcport));
+}
+static FC_DEVICE_ATTR(fcport, active_fc4s, S_IRUGO,
+ show_fcport_active_fc4s, NULL);
+
+static ssize_t show_fcport_speed(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fc_fcport *fcport = dev_to_fcport(dev);
+
+ if (fcport->f->get_fcport_speed)
+ fcport->f->get_fcport_speed(fcport);
+
+ if (fcport_speed(fcport) == FC_PORTSPEED_UNKNOWN)
+ return snprintf(buf, 20, "unknown\n");
+
+ return get_fc_port_speed_names(fcport_speed(fcport), buf);
+}
+static FC_DEVICE_ATTR(fcport, speed, S_IRUGO, show_fcport_speed, NULL);
+
+fc_fcport_rd_attr(maxframe_size, "%u bytes\n", 20);
+fc_fcport_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
+
+static ssize_t show_fcport_supported_speeds(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fc_fcport *fcport = dev_to_fcport(dev);
+ if (fcport_supported_speeds(fcport) == FC_PORTSPEED_UNKNOWN)
+ return snprintf(buf, 20, "unknown\n");
+
+ return get_fc_port_speed_names(fcport_supported_speeds(fcport), buf);
+}
+static FC_DEVICE_ATTR(fcport, supported_speeds, S_IRUGO,
+ show_fcport_supported_speeds, NULL);
+
+static ssize_t show_fcport_supported_classes(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fc_fcport *fcport = dev_to_fcport(dev);
+
+ if (fcport_supported_classes(fcport) == FC_COS_UNSPECIFIED)
+ return snprintf(buf, 20, "unspecified\n");
+
+ return get_fc_cos_names(fcport_supported_classes(fcport), buf);
+}
+static FC_DEVICE_ATTR(fcport, supported_classes, S_IRUGO,
+ show_fcport_supported_classes, NULL);
+
+
+/*
+ * TODO: I think I should be using the classes' release function instead
+ * of setting it directly in fc_fcport_add.
+ *
+ * .dev_release = fc_fcport_cls_release,
+ */
+struct class fc_class = {
+ .name = "fcport",
+};
+EXPORT_SYMBOL(fc_class);
+
+static void fc_fcport_release(struct device *dev)
+{
+ struct fc_fcport *fcport = dev_to_fcport(dev);
+ put_device(fcport->gendev.parent);
+ kfree(fcport);
+}
+
+void fc_fcport_del(struct fc_fcport *fcport)
+{
+ device_del(&fcport->gendev);
+ put_device(&fcport->gendev); /* self-reference */
+}
+EXPORT_SYMBOL(fc_fcport_del);
+
+static inline int get_fcport_id(void)
+{
+ return fcport_count++;
+}
+
+struct fc_fcport *fc_fcport_add(struct device *pdev,
+ struct fcport_function_template *fcn_tmpl)
+{
+ struct fc_fcport *fcport;
+ int count = 0;
+ int error = 0;
+
+ fcport = kzalloc(sizeof(struct fc_fcport), GFP_KERNEL);
+ if (!fcport)
+ goto out;
+ fcport->id = get_fcport_id();
+ device_initialize(&fcport->gendev);
+ fcport->gendev.parent = get_device(pdev);
+ fcport->gendev.release = fc_fcport_release;
+ fcport->gendev.class = &fc_class;
+ fcport->f = fcn_tmpl;
+ dev_set_name(&fcport->gendev, "fcport%d", get_fcport_id());
+
+ error = device_add(&fcport->gendev);
+ if (error)
+ goto out_del_gendev;
+
+ fcport->maxframe_size = -1;
+ fcport->supported_classes = FC_COS_UNSPECIFIED;
+ fcport->supported_speeds = FC_PORTSPEED_UNKNOWN;
+ fcport->speed = FC_PORTSPEED_UNKNOWN;
+ memset(fcport->supported_fc4s, 0,
+ sizeof(fcport->supported_fc4s));
+ memset(fcport->active_fc4s, 0,
+ sizeof(fcport->active_fc4s));
+ memset(fcport->serial_number, 0,
+ sizeof(fcport->serial_number));
+
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcport, maxframe_size);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcport, supported_speeds);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcport, speed);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcport, supported_fc4s);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcport, active_fc4s);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcport, supported_classes);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcport, serial_number);
+
+ BUG_ON(count > FCPORT_NUM_ATTRS);
+ FC_CREATE_ATTRIBUTES(fcport);
+
+ if (error || count != 0)
+ goto out_del_gendev;
+
+ return fcport;
+
+out_del_gendev:
+ device_del(&fcport->gendev);
+ kfree(fcport);
+out:
+ return NULL;
+}
+EXPORT_SYMBOL(fc_fcport_add);
+
+int fc_class_del_children(struct device *dev, void *data)
+{
+ int error = 0;
+ struct fc_fcport *fcport = dev_to_fcport(dev);
+ error = device_for_each_child(dev, NULL, fc_fcfport_del_children);
+ if (!error)
+ fc_fcport_del(fcport);
+ return error;
+}
diff --git a/drivers/scsi/fc/fcsysfs.c b/drivers/scsi/fc/fcsysfs.c
new file mode 100644
index 0000000..2b9293a
--- /dev/null
+++ b/drivers/scsi/fc/fcsysfs.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "fc_sysfs.h"
+
+MODULE_AUTHOR("Robert Love");
+MODULE_DESCRIPTION("fc_sysfs");
+MODULE_LICENSE("GPL v2");
+
+static int __init fc_sysfs_init(void)
+{
+ int error = class_register(&fc_class);
+ if (error)
+ return error;
+
+ return 0;
+}
+module_init(fc_sysfs_init);
+
+static void __exit fc_sysfs_exit(void)
+{
+ class_for_each_device(&fc_class, NULL,
+ NULL, fc_class_del_children);
+
+ class_unregister(&fc_class);
+}
+module_exit(fc_sysfs_exit);
diff --git a/drivers/scsi/fc/fcvport.c b/drivers/scsi/fc/fcvport.c
new file mode 100644
index 0000000..1208f38
--- /dev/null
+++ b/drivers/scsi/fc/fcvport.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "fc_sysfs.h"
+
+static int fcvport_count = 0;
+
+static void fc_vport_sched_delete(struct work_struct *work);
+
+#define fcvport_rd_attr(field, format_string, sz) \
+ fc_conditional_show_function(fcvport, field, format_string, sz, ) \
+ static FC_DEVICE_ATTR(fcvport, field, S_IRUGO, \
+ show_fcvport_##field, NULL)
+
+#define fc_private_fcvport_rd_attr(field, format_string, sz) \
+ fc_always_show_function(fcvport, field, format_string, sz, ) \
+ static FC_DEVICE_ATTR(fcvport, field, S_IRUGO, \
+ show_fcvport_##field, NULL)
+
+#define fc_private_fcvport_rd_attr_cast(field, format_string, sz, cast) \
+ fc_always_show_function(fcvport, field, format_string, sz, (cast)) \
+ static FC_DEVICE_ATTR(fcvport, field, S_IRUGO, \
+ show_fcvport_##field, NULL)
+
+/* Convert fc_vport_state values to ascii string name */
+static struct {
+ enum fc_vport_state value;
+ char *name;
+} fc_vport_state_names[] = {
+ { FC_VPORT_UNKNOWN, "Unknown" },
+ { FC_VPORT_ACTIVE, "Active" },
+ { FC_VPORT_DISABLED, "Disabled" },
+ { FC_VPORT_LINKDOWN, "Linkdown" },
+ { FC_VPORT_INITIALIZING, "Initializing" },
+ { FC_VPORT_NO_FABRIC_SUPP, "No Fabric Support" },
+ { FC_VPORT_NO_FABRIC_RSCS, "No Fabric Resources" },
+ { FC_VPORT_FABRIC_LOGOUT, "Fabric Logout" },
+ { FC_VPORT_FABRIC_REJ_WWN, "Fabric Rejected WWN" },
+ { FC_VPORT_FAILED, "VPort Failed" },
+};
+fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)
+#define FC_VPORTSTATE_MAX_NAMELEN 24
+
+/* Reuse fc_vport_state enum function for vport_last_state */
+#define get_fc_vport_last_state_name get_fc_vport_state_name
+
+/*
+ * TODO: Notce that we're still using get_fc_##title##_name and not
+ * a get_fcvport_##title##_name routine. The port_type structure,
+ * related lookups and names need to be somewhere global for rports
+ * and other fc_host obects.
+ */
+#define fcvport_rd_enum_attr(title, maxlen) \
+ static ssize_t show_fcvport_##title (struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct fc_fcvport *fcvport = dev_to_fcvport(dev); \
+ const char *name; \
+ if (fcvport->f->get_fcvport_##title) \
+ fcvport->f->get_fcvport_##title(fcvport); \
+ name = get_fc_##title##_name(fcvport_##title(fcvport)); \
+ if (!name) \
+ return -EINVAL; \
+ return snprintf(buf, maxlen, "%s\n", name); \
+} \
+static FC_DEVICE_ATTR(fcvport, title, S_IRUGO, show_fcvport_##title, NULL)
+
+#define fcvport_store_function(field) \
+ static ssize_t store_fcvport_##field(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ int val; \
+ struct fc_vport *vport = transport_class_to_vport(dev); \
+ struct Scsi_Host *shost = vport_to_shost(vport); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ char *cp; \
+ if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \
+ return -EBUSY; \
+ val = simple_strtoul(buf, &cp, 0); \
+ if (*cp && (*cp != '\n')) \
+ return -EINVAL; \
+ i->f->set_vport_##field(vport, val); \
+ return count; \
+}
+
+#define fcvport_store_str_function(field, slen) \
+ static ssize_t store_fcvport_##field(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct fc_fcvport *fcvport = dev_to_fcvport(dev); \
+ unsigned int cnt = count; \
+ \
+ /* count may include a LF at end of string */ \
+ if (buf[cnt-1] == '\n') \
+ cnt--; \
+ if (cnt > ((slen) - 1)) \
+ return -EINVAL; \
+ memcpy(fcvport->field, buf, cnt); \
+ fcvport->f->set_fcvport_##field(fcvport); \
+ return count; \
+}
+
+#define fcvport_rd_attr(field, format_string, sz) \
+ fc_conditional_show_function(fcvport, field, format_string, sz, ) \
+ static FC_DEVICE_ATTR(fcvport, field, S_IRUGO, \
+ show_fcvport_##field, NULL)
+
+#define fcvport_rd_attr_cast(field, format_string, sz, cast) \
+ fc_conditional_show_function(fcvport, field, format_string, sz, (cast)) \
+ static FC_DEVICE_ATTR(fcvport, field, S_IRUGO, \
+ show_fcvport_##field, NULL)
+
+#define fc_vport_rw_attr(field, format_string, sz) \
+ fc_conditional_show_function(fcvport, field, format_string, sz, ) \
+ fcvport_store_function(field) \
+ static FC_DEVICE_ATTR(fcvport, field, S_IRUGO | S_IWUSR, \
+ show_fcvport_##field, \
+ store_fcvport_##field)
+
+#define fc_private_fcvport_store_u32_function(field) \
+ static ssize_t store_fcvport_##field(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ u32 val; \
+ struct fc_fcvport *fcvport = dev_to_fcvport(dev); \
+ char *cp; \
+ if (fcvport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \
+ return -EBUSY; \
+ val = simple_strtoul(buf, &cp, 0); \
+ if (*cp && (*cp != '\n')) \
+ return -EINVAL; \
+ fcvport->field = val; \
+ return count; \
+}
+
+
+#define fc_private_fcvport_rw_u32_attr(field, format_string, sz) \
+ fc_always_show_function(fcvport, field, format_string, sz, ) \
+ fc_private_fcvport_store_u32_function(field) \
+ static FC_DEVICE_ATTR(fcvport, field, S_IRUGO | S_IWUSR, \
+ show_fcvport_##field, \
+ store_fcvport_##field)
+
+
+#define fc_private_fcvport_rd_enum_attr(title, maxlen) \
+ static ssize_t show_fcvport_##title (struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct fc_fcvport *fcvport = dev_to_fcvport(dev); \
+ const char *name; \
+ name = get_fc_##title##_name(fcvport->title); \
+ if (!name) \
+ return -EINVAL; \
+ return snprintf(buf, maxlen, "%s\n", name); \
+} \
+ static FC_DEVICE_ATTR(fcvport, title, S_IRUGO, \
+ show_fcvport_##title, NULL)
+
+/*
+ * TODO: I'm not sure how this macro is supposed to work. Why would there
+ * be a "field" in the function template? It's for vport_delete and
+ * vport_destroy, but I don't get it!
+ */
+#define SETUP_FCVPORT_ATTRIBUTE_WR(field) \
+ if (fcvport->f->field) { \
+ fcvport->attrs[count] = device_attr_fcvport_##field; \
+ device_create_file(&fcvport->gendev, &fcvport->attrs[count]); \
+ count++; \
+ }
+ /* NOTE: Above MACRO differs: checks function */
+
+#define SETUP_FCVPORT_ATTRIBUTE_RW(field) \
+ if (!fcvport->f->set_fcvport_##field) { \
+ fcvport->attrs[count] = device_attr_fcvport_##field; \
+ fcvport->attrs[count].attr.mode = S_IRUGO; \
+ fcvport->attrs[count].store = NULL; \
+ count++; \
+ }
+ /* NOTE: Above MACRO differs: does not check show bit */
+
+#define SETUP_PRIVATE_FCVPORT_ATTRIBUTE_RW(field) \
+{ \
+ fcvport->attrs[count] = device_attr_fcvport_##field; \
+ count++; \
+}
+
+
+/* The FC Transport Virtual Port Attributes: */
+
+/* Fixed Virtual Port Attributes */
+
+/* Dynamic Virtual Port Attributes */
+
+/* Private Virtual Port Attributes */
+
+fc_private_fcvport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN);
+fc_private_fcvport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN);
+fc_private_fcvport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
+fc_private_fcvport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+
+static ssize_t show_fcvport_roles(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct fc_fcvport *fcvport = dev_to_fcvport(dev);
+
+ if (fcvport->roles == FC_PORT_ROLE_UNKNOWN)
+ return snprintf(buf, 20, "unknown\n");
+ return get_fc_port_roles_names(fcvport->roles, buf);
+}
+static FC_DEVICE_ATTR(fcvport, roles, S_IRUGO, show_fcvport_roles, NULL);
+
+fc_private_fcvport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
+
+fc_always_show_function(fcvport, symbolic_name, "%s\n",
+ FC_VPORT_SYMBOLIC_NAMELEN + 1, )
+fcvport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
+static FC_DEVICE_ATTR(fcvport, symbolic_name, S_IRUGO | S_IWUSR,
+ show_fcvport_symbolic_name, store_fcvport_symbolic_name);
+
+/*
+static ssize_t
+store_fc_vport_delete(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fc_vport *vport = transport_class_to_vport(dev);
+ struct Scsi_Host *shost = vport_to_shost(vport);
+
+ fc_queue_work(shost, &vport->vport_delete_work);
+ return count;
+}
+static FC_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
+ NULL, store_fc_vport_delete);
+
+
+*
+ * Enable/Disable vport
+ * Write "1" to disable, write "0" to enable
+ *
+static ssize_t
+store_fc_vport_disable(struct device *dev, struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct fc_vport *vport = transport_class_to_vport(dev);
+ struct Scsi_Host *shost = vport_to_shost(vport);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ int stat;
+
+ if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))
+ return -EBUSY;
+
+ if (*buf == '0') {
+ if (vport->vport_state != FC_VPORT_DISABLED)
+ return -EALREADY;
+ } else if (*buf == '1') {
+ if (vport->vport_state == FC_VPORT_DISABLED)
+ return -EALREADY;
+ } else
+ return -EINVAL;
+
+ stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
+ return stat ? stat : count;
+}
+static FC_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+ NULL, store_fc_vport_disable);
+*/
+
+fcvport_rd_attr(port_id, "0x%06x\n", 20);
+fcvport_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN);
+
+static void fc_fcvport_release(struct device *dev)
+{
+ struct fc_fcvport *fcvport = dev_to_fcvport(dev);
+ put_device(fcvport->gendev.parent);
+ kfree(fcvport);
+}
+
+void fc_fcvport_del(struct fc_fcvport *fcvport)
+{
+ device_del(&fcvport->gendev);
+ put_device(&fcvport->gendev); /* self-reference */
+}
+
+static inline int get_fcvport_id(void)
+{
+ return fcvport_count++;
+}
+
+struct fc_fcvport *fc_fcvport_alloc(struct fc_fcfabric *fcfabric,
+ struct fc_vport_identifiers *ids,
+ struct fcvport_function_template *fcn_tmpl,
+ int priv_size)
+{
+ struct fc_fcvport *fcvport, *fcnport;
+ unsigned long flags;
+ int error = 0;
+ int id = get_fcvport_id();
+
+ /*
+ * TODO: Should probably pass in the WWPN to use as the fcvport's
+ * id. Right now we're just using a counter.
+ */
+ fcvport = kzalloc(sizeof(struct fc_fcvport) + priv_size, GFP_KERNEL);
+ if (!fcvport)
+ return NULL;
+
+ fcvport->vport_state = FC_VPORT_UNKNOWN;
+ fcvport->vport_last_state = FC_VPORT_UNKNOWN;
+ fcvport->node_name = ids->node_name;
+ fcvport->port_name = ids->port_name;
+ fcvport->roles = ids->roles;
+ fcvport->vport_type = ids->vport_type;
+ fcvport->id = id;
+ fcvport->port_type = FC_PORTTYPE_UNKNOWN;
+
+ /*
+ * TODO: Another example of badness due to passing in NULL
+ * for the fcfabric when creating a N_Port.
+ */
+ if (fcfabric) {
+ if (fcfabric->f->dd_fcvport_size)
+ fcvport->dd_data = &fcvport[1];
+ }
+
+ /*
+ * TODO: This is really bad. N_Ports will be passing NULL in
+ * and vports will be passing a real fabric in. This must be
+ * fixed.
+ */
+ fcvport->fcfabric = fcfabric;
+
+ INIT_WORK(&fcvport->vport_delete_work, fc_vport_sched_delete);
+ spin_lock_init(&fcvport->lock);
+ device_initialize(&fcvport->gendev);
+
+ fcvport->gendev.release = fc_fcvport_release;
+ fcvport->f = fcn_tmpl;
+
+ dev_set_name(&fcvport->gendev, "fcvport_%d", id);
+
+ /*
+ * TODO: This is ugly. We're doing different cases for N_Ports
+ * and VN_Ports since there's no fcfabric passed in for N_Ports.
+ */
+ if (fcfabric) {
+ /*
+ * TODO: Is this correct? Should vports always be created
+ * in the enabled (i.e. 0) state? The previous
+ * store_fc_host_vport_create() was zero'ing the memory,
+ * so I think they're always !disabled.
+ */
+ fcnport = fc_fcfabric_find_nport(fcfabric);
+ if (!fcnport)
+ return NULL;
+
+ error = fcfabric->f->vport_create(fcnport->priv_data, fcvport, 0);
+ if (error)
+ goto delete_vport_all;
+ }
+
+ spin_lock_irqsave(&fcvport->lock, flags);
+ fcvport->flags &= ~FC_VPORT_CREATING;
+ spin_unlock_irqrestore(&fcvport->lock, flags);
+
+ /*
+ * TODO: We probably want to re-add a dev_printk here
+ dev_printk(KERN_NOTICE, pdev,
+ "%s created via shost%d channel %d\n", dev_name(dev),
+ shost->host_no, channel);
+ */
+ return fcvport;
+
+delete_vport_all:
+/*
+ * TODO: Double check this routines error handling,
+ * we probably need to clean up more here.
+ */
+ kfree(fcvport);
+ return NULL;
+}
+EXPORT_SYMBOL(fc_fcvport_alloc);
+
+int fc_fcvport_add(struct fc_fcvport *fcvport,
+ struct fc_fcfabric *fcfabric)
+{
+ int count = 0;
+ int error = 0;
+
+ fcvport->gendev.parent = get_device(&fcfabric->gendev);
+
+ /*
+ * TODO: Should the device be free'd if the
+ * device_add() fails?
+ */
+ error = device_add(&fcvport->gendev);
+ if (error)
+ return error;
+
+ /* TODO: Check for failure */
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcvport, port_id);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcvport, node_name);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcvport, port_name);
+ FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(fcvport, port_type);
+
+ /*
+ * Setup Virtual Port Attributes.
+ */
+ FC_SETUP_ALWAYS_ATTRIBUTE_RD_NS(fcvport, vport_state);
+ FC_SETUP_ALWAYS_ATTRIBUTE_RD_NS(fcvport, vport_last_state);
+ FC_SETUP_ALWAYS_ATTRIBUTE_RD_NS(fcvport, roles);
+ FC_SETUP_ALWAYS_ATTRIBUTE_RD_NS(fcvport, vport_type);
+ FC_SETUP_ALWAYS_ATTRIBUTE_RD_NS(fcvport, symbolic_name);
+
+ /* TODO: FIX THIS
+ SETUP_VPORT_ATTRIBUTE_WR(vport_delete);
+ SETUP_VPORT_ATTRIBUTE_WR(vport_disable);
+ */
+
+ BUG_ON(count > FCVPORT_NUM_ATTRS);
+ FC_CREATE_ATTRIBUTES(fcvport);
+
+ if (error || count != 0)
+ return error;
+
+ return 0;
+}
+EXPORT_SYMBOL(fc_fcvport_add);
+
+int fc_fcvport_del_children(struct device *dev, void *data)
+{
+ int error = 0;
+ struct fc_fcvport *fcvport = dev_to_fcvport(dev);
+ error = device_for_each_child(dev, NULL, fc_fcpinit_del_children);
+ if (!error)
+ fc_fcvport_del(fcvport);
+ return error;
+}
+
+int fc_fcvport_is_nport(struct device *dev, void *data)
+{
+ struct fc_fcvport *fcvport = dev_to_fcvport(dev);
+ if (fcvport_port_type(fcvport) == FC_PORTTYPE_NPORT)
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(fc_fcvport_is_nport);
+
+/**
+ * fc_vport_sched_delete - workq-based delete request for a vport
+ * @work: vport to be deleted.
+ */
+static void
+fc_vport_sched_delete(struct work_struct *work)
+{
+ struct fc_fcvport *vport =
+ container_of(work, struct fc_fcvport, vport_delete_work);
+ int stat;
+
+ stat = fc_vport_terminate(vport->fcfabric, vport);
+ if (stat)
+ dev_printk(KERN_ERR, vport->gendev.parent,
+ "%s: %s could not be deleted created via "
+ "shost%d channel %d - error %d\n", __func__,
+ dev_name(&vport->gendev), vport->shost->host_no,
+ vport->channel, stat);
+}
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 653f22a..8d2f716 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -39,17 +39,56 @@
#include <scsi/scsi_bsg_fc.h>
#include "scsi_priv.h"
#include "scsi_transport_fc_internal.h"
+#include <scsi/fc.h>
static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
-static void fc_vport_sched_delete(struct work_struct *work);
-static int fc_vport_setup(struct Scsi_Host *shost, int channel,
- struct device *pdev, struct fc_vport_identifiers *ids,
- struct fc_vport **vport);
-static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *);
+static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_fcpinit *);
static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);
static void fc_bsg_remove(struct request_queue *);
static void fc_bsg_goose_queue(struct fc_rport *);
+
+struct _fc_port_types fc_port_type_names[] = {
+ { FC_PORTTYPE_UNKNOWN, "Unknown" },
+ { FC_PORTTYPE_OTHER, "Other" },
+ { FC_PORTTYPE_NOTPRESENT, "Not Present" },
+ { FC_PORTTYPE_NPORT, "NPort (fabric via point-to-point)" },
+ { FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" },
+ { FC_PORTTYPE_LPORT, "LPort (private loop)" },
+ { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection)" },
+ { FC_PORTTYPE_NPIV, "NPIV VPORT" },
+};
+/* Convert fc_port_type values to ascii string name */
+fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
+EXPORT_SYMBOL(get_fc_port_type_name);
+fc_enum_name_search(vport_type, fc_port_type, fc_port_type_names)
+EXPORT_SYMBOL(get_fc_vport_type_name);
+
+struct _fc_port_role_names fc_port_role_names[] = {
+ { FC_PORT_ROLE_FCP_TARGET, "FCP Target" },
+ { FC_PORT_ROLE_FCP_INITIATOR, "FCP Initiator" },
+ { FC_PORT_ROLE_IP_PORT, "IP Port" },
+};
+/* Convert FC_PORT_ROLE bit values to ascii string name */
+fc_bitfield_name_search(port_roles, fc_port_role_names)
+EXPORT_SYMBOL(get_fc_port_roles_names);
+
+struct _fc_cos_names fc_cos_names[] = {
+ { FC_COS_CLASS1, "Class 1" },
+ { FC_COS_CLASS2, "Class 2" },
+ { FC_COS_CLASS3, "Class 3" },
+ { FC_COS_CLASS4, "Class 4" },
+ { FC_COS_CLASS6, "Class 6" },
+};
+
+/* Convert FC_COS bit values to ascii string name */
+fc_bitfield_name_search(cos, fc_cos_names)
+EXPORT_SYMBOL(get_fc_cos_names);
+
+/* Reuse fc_port_type enum function for vport_type */
+//#define get_fc_vport_type_name get_fc_port_type_name
+
+
/*
* Redefine so that we can have same named attributes in the
* sdev/starget/host objects.
@@ -58,21 +97,6 @@ static void fc_bsg_goose_queue(struct fc_rport *);
struct device_attribute device_attr_##_prefix##_##_name = \
__ATTR(_name,_mode,_show,_store)
-#define fc_enum_name_search(title, table_type, table) \
-static const char *get_fc_##title##_name(enum table_type table_key) \
-{ \
- int i; \
- char *name = NULL; \
- \
- for (i = 0; i < ARRAY_SIZE(table); i++) { \
- if (table[i].value == table_key) { \
- name = table[i].name; \
- break; \
- } \
- } \
- return name; \
-}
-
#define fc_enum_name_match(title, table_type, table) \
static int get_fc_##title##_match(const char *table_key, \
enum table_type *value) \
@@ -89,33 +113,11 @@ static int get_fc_##title##_match(const char *table_key, \
return 1; /* failure */ \
}
-
-/* Convert fc_port_type values to ascii string name */
-static struct {
- enum fc_port_type value;
- char *name;
-} fc_port_type_names[] = {
- { FC_PORTTYPE_UNKNOWN, "Unknown" },
- { FC_PORTTYPE_OTHER, "Other" },
- { FC_PORTTYPE_NOTPRESENT, "Not Present" },
- { FC_PORTTYPE_NPORT, "NPort (fabric via point-to-point)" },
- { FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" },
- { FC_PORTTYPE_LPORT, "LPort (private loop)" },
- { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection)" },
- { FC_PORTTYPE_NPIV, "NPIV VPORT" },
-};
-fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
-#define FC_PORTTYPE_MAX_NAMELEN 50
-
-/* Reuse fc_port_type enum function for vport_type */
-#define get_fc_vport_type_name get_fc_port_type_name
-
-
-/* Convert fc_host_event_code values to ascii string name */
+/* Convert fcpinit_event_code values to ascii string name */
static const struct {
- enum fc_host_event_code value;
+ enum fcpinit_event_code value;
char *name;
-} fc_host_event_code_names[] = {
+} fcpinit_event_code_names[] = {
{ FCH_EVT_LIP, "lip" },
{ FCH_EVT_LINKUP, "link_up" },
{ FCH_EVT_LINKDOWN, "link_down" },
@@ -129,9 +131,9 @@ static const struct {
{ FCH_EVT_LINK_UNKNOWN, "link_unknown" },
{ FCH_EVT_VENDOR_UNIQUE, "vendor_unique" },
};
-fc_enum_name_search(host_event_code, fc_host_event_code,
- fc_host_event_code_names)
-#define FC_HOST_EVENT_CODE_MAX_NAMELEN 30
+fc_enum_name_search(fcpinit_event_code, fcpinit_event_code,
+ fcpinit_event_code_names)
+#define FCPINIT_EVENT_CODE_MAX_NAMELEN 30
/* Convert fc_port_state values to ascii string name */
@@ -154,30 +156,6 @@ static struct {
fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
#define FC_PORTSTATE_MAX_NAMELEN 20
-
-/* Convert fc_vport_state values to ascii string name */
-static struct {
- enum fc_vport_state value;
- char *name;
-} fc_vport_state_names[] = {
- { FC_VPORT_UNKNOWN, "Unknown" },
- { FC_VPORT_ACTIVE, "Active" },
- { FC_VPORT_DISABLED, "Disabled" },
- { FC_VPORT_LINKDOWN, "Linkdown" },
- { FC_VPORT_INITIALIZING, "Initializing" },
- { FC_VPORT_NO_FABRIC_SUPP, "No Fabric Support" },
- { FC_VPORT_NO_FABRIC_RSCS, "No Fabric Resources" },
- { FC_VPORT_FABRIC_LOGOUT, "Fabric Logout" },
- { FC_VPORT_FABRIC_REJ_WWN, "Fabric Rejected WWN" },
- { FC_VPORT_FAILED, "VPort Failed" },
-};
-fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)
-#define FC_VPORTSTATE_MAX_NAMELEN 24
-
-/* Reuse fc_vport_state enum function for vport_last_state */
-#define get_fc_vport_last_state_name get_fc_vport_state_name
-
-
/* Convert fc_tgtid_binding_type values to ascii string name */
static const struct {
enum fc_tgtid_binding_type value;
@@ -195,80 +173,6 @@ fc_enum_name_match(tgtid_bind_type, fc_tgtid_binding_type,
fc_tgtid_binding_type_names)
#define FC_BINDTYPE_MAX_NAMELEN 30
-
-#define fc_bitfield_name_search(title, table) \
-static ssize_t \
-get_fc_##title##_names(u32 table_key, char *buf) \
-{ \
- char *prefix = ""; \
- ssize_t len = 0; \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(table); i++) { \
- if (table[i].value & table_key) { \
- len += sprintf(buf + len, "%s%s", \
- prefix, table[i].name); \
- prefix = ", "; \
- } \
- } \
- len += sprintf(buf + len, "\n"); \
- return len; \
-}
-
-
-/* Convert FC_COS bit values to ascii string name */
-static const struct {
- u32 value;
- char *name;
-} fc_cos_names[] = {
- { FC_COS_CLASS1, "Class 1" },
- { FC_COS_CLASS2, "Class 2" },
- { FC_COS_CLASS3, "Class 3" },
- { FC_COS_CLASS4, "Class 4" },
- { FC_COS_CLASS6, "Class 6" },
-};
-fc_bitfield_name_search(cos, fc_cos_names)
-
-
-/* Convert FC_PORTSPEED bit values to ascii string name */
-static const struct {
- u32 value;
- char *name;
-} fc_port_speed_names[] = {
- { FC_PORTSPEED_1GBIT, "1 Gbit" },
- { FC_PORTSPEED_2GBIT, "2 Gbit" },
- { FC_PORTSPEED_4GBIT, "4 Gbit" },
- { FC_PORTSPEED_10GBIT, "10 Gbit" },
- { FC_PORTSPEED_8GBIT, "8 Gbit" },
- { FC_PORTSPEED_16GBIT, "16 Gbit" },
- { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" },
-};
-fc_bitfield_name_search(port_speed, fc_port_speed_names)
-
-
-static int
-show_fc_fc4s (char *buf, u8 *fc4_list)
-{
- int i, len=0;
-
- for (i = 0; i < FC_FC4_LIST_SIZE; i++, fc4_list++)
- len += sprintf(buf + len , "0x%02x ", *fc4_list);
- len += sprintf(buf + len, "\n");
- return len;
-}
-
-
-/* Convert FC_PORT_ROLE bit values to ascii string name */
-static const struct {
- u32 value;
- char *name;
-} fc_port_role_names[] = {
- { FC_PORT_ROLE_FCP_TARGET, "FCP Target" },
- { FC_PORT_ROLE_FCP_INITIATOR, "FCP Initiator" },
- { FC_PORT_ROLE_IP_PORT, "IP Port" },
-};
-fc_bitfield_name_search(port_roles, fc_port_role_names)
-
/*
* Define roles that are specific to port_id. Values are relative to ROLE_MASK.
*/
@@ -291,8 +195,6 @@ static void fc_scsi_scan_rport(struct work_struct *work);
*/
#define FC_STARGET_NUM_ATTRS 3
#define FC_RPORT_NUM_ATTRS 10
-#define FC_VPORT_NUM_ATTRS 9
-#define FC_HOST_NUM_ATTRS 22
struct fc_internal {
struct scsi_transport_template t;
@@ -308,20 +210,16 @@ struct fc_internal {
* part of the midlayer. As the remote port is specific to the
* fc transport, we must provide the attribute container.
*/
- struct device_attribute private_starget_attrs[
- FC_STARGET_NUM_ATTRS];
+ struct device_attribute private_starget_attrs[FC_STARGET_NUM_ATTRS];
struct device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1];
- struct device_attribute private_host_attrs[FC_HOST_NUM_ATTRS];
- struct device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1];
+ /* These are the fcpinit attributes */
+ struct device_attribute private_host_attrs[FCPINIT_NUM_ATTRS];
+ struct device_attribute *host_attrs[FCPINIT_NUM_ATTRS + 1];
struct transport_container rport_attr_cont;
struct device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
struct device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
-
- struct transport_container vport_attr_cont;
- struct device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
- struct device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
};
#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
@@ -356,87 +254,67 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class,
NULL,
NULL);
-static int fc_host_setup(struct transport_container *tc, struct device *dev,
+static int fcpinit_setup(struct transport_container *tc, struct device *dev,
struct device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_fcpinit *fcpinit = shost_to_fcpinit(shost);
/*
* Set default values easily detected by the midlayer as
* failure cases. The scsi lldd is responsible for initializing
* all transport attributes to valid values per host.
*/
- fc_host->node_name = -1;
- fc_host->port_name = -1;
- fc_host->permanent_port_name = -1;
- fc_host->supported_classes = FC_COS_UNSPECIFIED;
- memset(fc_host->supported_fc4s, 0,
- sizeof(fc_host->supported_fc4s));
- fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
- fc_host->maxframe_size = -1;
- fc_host->max_npiv_vports = 0;
- memset(fc_host->serial_number, 0,
- sizeof(fc_host->serial_number));
-
- fc_host->port_id = -1;
- fc_host->port_type = FC_PORTTYPE_UNKNOWN;
- fc_host->port_state = FC_PORTSTATE_UNKNOWN;
- memset(fc_host->active_fc4s, 0,
- sizeof(fc_host->active_fc4s));
- fc_host->speed = FC_PORTSPEED_UNKNOWN;
- fc_host->fabric_name = -1;
- memset(fc_host->symbolic_name, 0, sizeof(fc_host->symbolic_name));
- memset(fc_host->system_hostname, 0, sizeof(fc_host->system_hostname));
-
- fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;
-
- INIT_LIST_HEAD(&fc_host->rports);
- INIT_LIST_HEAD(&fc_host->rport_bindings);
- INIT_LIST_HEAD(&fc_host->vports);
- fc_host->next_rport_number = 0;
- fc_host->next_target_id = 0;
- fc_host->next_vport_number = 0;
- fc_host->npiv_vports_inuse = 0;
-
- snprintf(fc_host->work_q_name, sizeof(fc_host->work_q_name),
+ fcpinit->permanent_port_name = -1;
+
+ fcpinit->port_state = FC_PORTSTATE_UNKNOWN;
+ memset(fcpinit->system_hostname, 0, sizeof(fcpinit->system_hostname));
+
+ fcpinit->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;
+
+ INIT_LIST_HEAD(&fcpinit->rports);
+ INIT_LIST_HEAD(&fcpinit->rport_bindings);
+ fcpinit->next_rport_number = 0;
+ fcpinit->next_target_id = 0;
+
+ snprintf(fcpinit->work_q_name, sizeof(fcpinit->work_q_name),
"fc_wq_%d", shost->host_no);
- fc_host->work_q = create_singlethread_workqueue(
- fc_host->work_q_name);
- if (!fc_host->work_q)
+ fcpinit->work_q = create_singlethread_workqueue(
+ fcpinit->work_q_name);
+ if (!fcpinit->work_q)
return -ENOMEM;
- snprintf(fc_host->devloss_work_q_name,
- sizeof(fc_host->devloss_work_q_name),
+ snprintf(fcpinit->devloss_work_q_name,
+ sizeof(fcpinit->devloss_work_q_name),
"fc_dl_%d", shost->host_no);
- fc_host->devloss_work_q = create_singlethread_workqueue(
- fc_host->devloss_work_q_name);
- if (!fc_host->devloss_work_q) {
- destroy_workqueue(fc_host->work_q);
- fc_host->work_q = NULL;
+ fcpinit->devloss_work_q = create_singlethread_workqueue(
+ fcpinit->devloss_work_q_name);
+ if (!fcpinit->devloss_work_q) {
+ destroy_workqueue(fcpinit->work_q);
+ fcpinit->work_q = NULL;
return -ENOMEM;
}
- fc_bsg_hostadd(shost, fc_host);
+ fc_bsg_hostadd(shost, fcpinit);
/* ignore any bsg add error - we just can't do sgio */
return 0;
}
-static int fc_host_remove(struct transport_container *tc, struct device *dev,
- struct device *cdev)
+static int fcpinit_remove(struct transport_container *tc, struct device *dev,
+ struct device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_fcpinit *fcpinit = shost_to_fcpinit(shost);
- fc_bsg_remove(fc_host->rqst_q);
+ fc_bsg_remove(fcpinit->rqst_q);
return 0;
}
-static DECLARE_TRANSPORT_CLASS(fc_host_class,
- "fc_host",
- fc_host_setup,
- fc_host_remove,
+static DECLARE_TRANSPORT_CLASS(fcpinit_class,
+ "fcpinit",
+ fcpinit_setup,
+ fcpinit_remove,
NULL);
/*
@@ -450,16 +328,6 @@ static DECLARE_TRANSPORT_CLASS(fc_rport_class,
NULL);
/*
- * Setup and Remove actions for virtual ports are handled
- * in the service functions below.
- */
-static DECLARE_TRANSPORT_CLASS(fc_vport_class,
- "fc_vports",
- NULL,
- NULL,
- NULL);
-
-/*
* Module Parameters
*/
@@ -500,18 +368,18 @@ EXPORT_SYMBOL(fc_get_event_number);
/**
- * fc_host_post_event - called to post an even on an fc_host.
+ * fcpinit_post_event - called to post an even on an fcpinit.
* @shost: host the event occurred on
* @event_number: fc event number obtained from get_fc_event_number()
- * @event_code: fc_host event being posted
+ * @event_code: fcpinit event being posted
* @event_data: 32bits of data for the event being posted
*
* Notes:
* This routine assumes no locks are held on entry.
*/
void
-fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
- enum fc_host_event_code event_code, u32 event_data)
+fcpinit_post_event(struct Scsi_Host *shost, u32 event_number,
+ enum fcpinit_event_code event_code, u32 event_data)
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
@@ -559,18 +427,18 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
send_fail_skb:
kfree_skb(skb);
send_fail:
- name = get_fc_host_event_code_name(event_code);
+ name = get_fc_fcpinit_event_code_name(event_code);
printk(KERN_WARNING
"%s: Dropped Event : host %d %s data 0x%08x - err %d\n",
__func__, shost->host_no,
(name) ? name : "<unknown>", event_data, err);
return;
}
-EXPORT_SYMBOL(fc_host_post_event);
+EXPORT_SYMBOL(fcpinit_post_event);
/**
- * fc_host_post_vendor_event - called to post a vendor unique event on an fc_host
+ * fcpinit_post_vendor_event - called to post a vendor unique event on an fcpinit
* @shost: host the event occurred on
* @event_number: fc event number obtained from get_fc_event_number()
* @data_len: amount, in bytes, of vendor unique data
@@ -581,8 +449,8 @@ EXPORT_SYMBOL(fc_host_post_event);
* This routine assumes no locks are held on entry.
*/
void
-fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
- u32 data_len, char * data_buf, u64 vendor_id)
+fcpinit_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
+ u32 data_len, char * data_buf, u64 vendor_id)
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
@@ -634,7 +502,7 @@ send_vendor_fail:
__func__, shost->host_no, err);
return;
}
-EXPORT_SYMBOL(fc_host_post_vendor_event);
+EXPORT_SYMBOL(fcpinit_post_vendor_event);
@@ -644,15 +512,12 @@ static __init int fc_transport_init(void)
atomic_set(&fc_event_seq, 0);
- error = transport_class_register(&fc_host_class);
+ error = transport_class_register(&fcpinit_class);
if (error)
return error;
- error = transport_class_register(&fc_vport_class);
- if (error)
- goto unreg_host_class;
error = transport_class_register(&fc_rport_class);
if (error)
- goto unreg_vport_class;
+ goto unreg_host_class;
error = transport_class_register(&fc_transport_class);
if (error)
goto unreg_rport_class;
@@ -660,10 +525,8 @@ static __init int fc_transport_init(void)
unreg_rport_class:
transport_class_unregister(&fc_rport_class);
-unreg_vport_class:
- transport_class_unregister(&fc_vport_class);
unreg_host_class:
- transport_class_unregister(&fc_host_class);
+ transport_class_unregister(&fcpinit_class);
return error;
}
@@ -671,8 +534,7 @@ static void __exit fc_transport_exit(void)
{
transport_class_unregister(&fc_transport_class);
transport_class_unregister(&fc_rport_class);
- transport_class_unregister(&fc_host_class);
- transport_class_unregister(&fc_vport_class);
+ transport_class_unregister(&fcpinit_class);
}
/*
@@ -996,286 +858,25 @@ fc_starget_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
fc_starget_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
fc_starget_rd_attr(port_id, "0x%06x\n", 20);
-
-/*
- * FC Virtual Port Attribute Management
- */
-
-#define fc_vport_show_function(field, format_string, sz, cast) \
-static ssize_t \
-show_fc_vport_##field (struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct fc_vport *vport = transport_class_to_vport(dev); \
- struct Scsi_Host *shost = vport_to_shost(vport); \
- struct fc_internal *i = to_fc_internal(shost->transportt); \
- if ((i->f->get_vport_##field) && \
- !(vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))) \
- i->f->get_vport_##field(vport); \
- return snprintf(buf, sz, format_string, cast vport->field); \
-}
-
-#define fc_vport_store_function(field) \
-static ssize_t \
-store_fc_vport_##field(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- int val; \
- struct fc_vport *vport = transport_class_to_vport(dev); \
- struct Scsi_Host *shost = vport_to_shost(vport); \
- struct fc_internal *i = to_fc_internal(shost->transportt); \
- char *cp; \
- if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \
- return -EBUSY; \
- val = simple_strtoul(buf, &cp, 0); \
- if (*cp && (*cp != '\n')) \
- return -EINVAL; \
- i->f->set_vport_##field(vport, val); \
- return count; \
-}
-
-#define fc_vport_store_str_function(field, slen) \
-static ssize_t \
-store_fc_vport_##field(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct fc_vport *vport = transport_class_to_vport(dev); \
- struct Scsi_Host *shost = vport_to_shost(vport); \
- struct fc_internal *i = to_fc_internal(shost->transportt); \
- unsigned int cnt=count; \
- \
- /* count may include a LF at end of string */ \
- if (buf[cnt-1] == '\n') \
- cnt--; \
- if (cnt > ((slen) - 1)) \
- return -EINVAL; \
- memcpy(vport->field, buf, cnt); \
- i->f->set_vport_##field(vport); \
- return count; \
-}
-
-#define fc_vport_rd_attr(field, format_string, sz) \
- fc_vport_show_function(field, format_string, sz, ) \
-static FC_DEVICE_ATTR(vport, field, S_IRUGO, \
- show_fc_vport_##field, NULL)
-
-#define fc_vport_rd_attr_cast(field, format_string, sz, cast) \
- fc_vport_show_function(field, format_string, sz, (cast)) \
-static FC_DEVICE_ATTR(vport, field, S_IRUGO, \
- show_fc_vport_##field, NULL)
-
-#define fc_vport_rw_attr(field, format_string, sz) \
- fc_vport_show_function(field, format_string, sz, ) \
- fc_vport_store_function(field) \
-static FC_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \
- show_fc_vport_##field, \
- store_fc_vport_##field)
-
-#define fc_private_vport_show_function(field, format_string, sz, cast) \
-static ssize_t \
-show_fc_vport_##field (struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct fc_vport *vport = transport_class_to_vport(dev); \
- return snprintf(buf, sz, format_string, cast vport->field); \
-}
-
-#define fc_private_vport_store_u32_function(field) \
-static ssize_t \
-store_fc_vport_##field(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- u32 val; \
- struct fc_vport *vport = transport_class_to_vport(dev); \
- char *cp; \
- if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \
- return -EBUSY; \
- val = simple_strtoul(buf, &cp, 0); \
- if (*cp && (*cp != '\n')) \
- return -EINVAL; \
- vport->field = val; \
- return count; \
-}
-
-
-#define fc_private_vport_rd_attr(field, format_string, sz) \
- fc_private_vport_show_function(field, format_string, sz, ) \
-static FC_DEVICE_ATTR(vport, field, S_IRUGO, \
- show_fc_vport_##field, NULL)
-
-#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast) \
- fc_private_vport_show_function(field, format_string, sz, (cast)) \
-static FC_DEVICE_ATTR(vport, field, S_IRUGO, \
- show_fc_vport_##field, NULL)
-
-#define fc_private_vport_rw_u32_attr(field, format_string, sz) \
- fc_private_vport_show_function(field, format_string, sz, ) \
- fc_private_vport_store_u32_function(field) \
-static FC_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \
- show_fc_vport_##field, \
- store_fc_vport_##field)
-
-
-#define fc_private_vport_rd_enum_attr(title, maxlen) \
-static ssize_t \
-show_fc_vport_##title (struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- struct fc_vport *vport = transport_class_to_vport(dev); \
- const char *name; \
- name = get_fc_##title##_name(vport->title); \
- if (!name) \
- return -EINVAL; \
- return snprintf(buf, maxlen, "%s\n", name); \
-} \
-static FC_DEVICE_ATTR(vport, title, S_IRUGO, \
- show_fc_vport_##title, NULL)
-
-
-#define SETUP_VPORT_ATTRIBUTE_RD(field) \
- i->private_vport_attrs[count] = device_attr_vport_##field; \
- i->private_vport_attrs[count].attr.mode = S_IRUGO; \
- i->private_vport_attrs[count].store = NULL; \
- i->vport_attrs[count] = &i->private_vport_attrs[count]; \
- if (i->f->get_##field) \
- count++
- /* NOTE: Above MACRO differs: checks function not show bit */
-
-#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field) \
- i->private_vport_attrs[count] = device_attr_vport_##field; \
- i->private_vport_attrs[count].attr.mode = S_IRUGO; \
- i->private_vport_attrs[count].store = NULL; \
- i->vport_attrs[count] = &i->private_vport_attrs[count]; \
- count++
-
-#define SETUP_VPORT_ATTRIBUTE_WR(field) \
- i->private_vport_attrs[count] = device_attr_vport_##field; \
- i->vport_attrs[count] = &i->private_vport_attrs[count]; \
- if (i->f->field) \
- count++
- /* NOTE: Above MACRO differs: checks function */
-
-#define SETUP_VPORT_ATTRIBUTE_RW(field) \
- i->private_vport_attrs[count] = device_attr_vport_##field; \
- if (!i->f->set_vport_##field) { \
- i->private_vport_attrs[count].attr.mode = S_IRUGO; \
- i->private_vport_attrs[count].store = NULL; \
- } \
- i->vport_attrs[count] = &i->private_vport_attrs[count]; \
- count++
- /* NOTE: Above MACRO differs: does not check show bit */
-
-#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field) \
-{ \
- i->private_vport_attrs[count] = device_attr_vport_##field; \
- i->vport_attrs[count] = &i->private_vport_attrs[count]; \
- count++; \
-}
-
-
-/* The FC Transport Virtual Port Attributes: */
-
-/* Fixed Virtual Port Attributes */
-
-/* Dynamic Virtual Port Attributes */
-
-/* Private Virtual Port Attributes */
-
-fc_private_vport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN);
-fc_private_vport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN);
-fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
-fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
-
-static ssize_t
-show_fc_vport_roles (struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fc_vport *vport = transport_class_to_vport(dev);
-
- if (vport->roles == FC_PORT_ROLE_UNKNOWN)
- return snprintf(buf, 20, "unknown\n");
- return get_fc_port_roles_names(vport->roles, buf);
-}
-static FC_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
-
-fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
-
-fc_private_vport_show_function(symbolic_name, "%s\n",
- FC_VPORT_SYMBOLIC_NAMELEN + 1, )
-fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
-static FC_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
- show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);
-
-static ssize_t
-store_fc_vport_delete(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct fc_vport *vport = transport_class_to_vport(dev);
- struct Scsi_Host *shost = vport_to_shost(vport);
-
- fc_queue_work(shost, &vport->vport_delete_work);
- return count;
-}
-static FC_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
- NULL, store_fc_vport_delete);
-
-
-/*
- * Enable/Disable vport
- * Write "1" to disable, write "0" to enable
- */
-static ssize_t
-store_fc_vport_disable(struct device *dev, struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct fc_vport *vport = transport_class_to_vport(dev);
- struct Scsi_Host *shost = vport_to_shost(vport);
- struct fc_internal *i = to_fc_internal(shost->transportt);
- int stat;
-
- if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))
- return -EBUSY;
-
- if (*buf == '0') {
- if (vport->vport_state != FC_VPORT_DISABLED)
- return -EALREADY;
- } else if (*buf == '1') {
- if (vport->vport_state == FC_VPORT_DISABLED)
- return -EALREADY;
- } else
- return -EINVAL;
-
- stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
- return stat ? stat : count;
-}
-static FC_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
- NULL, store_fc_vport_disable);
-
-
/*
* Host Attribute Management
*/
-#define fc_host_show_function(field, format_string, sz, cast) \
+#define fcpinit_show_function(field, format_string, sz, cast) \
static ssize_t \
-show_fc_host_##field (struct device *dev, \
+show_fcpinit_##field (struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct Scsi_Host *shost = transport_class_to_shost(dev); \
struct fc_internal *i = to_fc_internal(shost->transportt); \
if (i->f->get_host_##field) \
i->f->get_host_##field(shost); \
- return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \
+ return snprintf(buf, sz, format_string, cast fcpinit_##field(shost)); \
}
-#define fc_host_store_function(field) \
+#define fcpinit_store_function(field) \
static ssize_t \
-store_fc_host_##field(struct device *dev, \
+store_fcpinit_##field(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
@@ -1291,9 +892,9 @@ store_fc_host_##field(struct device *dev, \
return count; \
}
-#define fc_host_store_str_function(field, slen) \
+#define fcpinit_store_str_function(field, slen) \
static ssize_t \
-store_fc_host_##field(struct device *dev, \
+store_fcpinit_##field(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
@@ -1306,31 +907,31 @@ store_fc_host_##field(struct device *dev, \
cnt--; \
if (cnt > ((slen) - 1)) \
return -EINVAL; \
- memcpy(fc_host_##field(shost), buf, cnt); \
+ memcpy(fcpinit_##field(shost), buf, cnt); \
i->f->set_host_##field(shost); \
return count; \
}
-#define fc_host_rd_attr(field, format_string, sz) \
- fc_host_show_function(field, format_string, sz, ) \
+#define fcpinit_rd_attr(field, format_string, sz) \
+ fcpinit_show_function(field, format_string, sz, ) \
static FC_DEVICE_ATTR(host, field, S_IRUGO, \
- show_fc_host_##field, NULL)
+ show_fcpinit_##field, NULL)
-#define fc_host_rd_attr_cast(field, format_string, sz, cast) \
- fc_host_show_function(field, format_string, sz, (cast)) \
+#define fcpinit_rd_attr_cast(field, format_string, sz, cast) \
+ fcpinit_show_function(field, format_string, sz, (cast)) \
static FC_DEVICE_ATTR(host, field, S_IRUGO, \
- show_fc_host_##field, NULL)
+ show_fcpinit_##field, NULL)
-#define fc_host_rw_attr(field, format_string, sz) \
- fc_host_show_function(field, format_string, sz, ) \
- fc_host_store_function(field) \
+#define fcpinit_rw_attr(field, format_string, sz) \
+ fcpinit_show_function(field, format_string, sz, ) \
+ fcpinit_store_function(field) \
static FC_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR, \
- show_fc_host_##field, \
- store_fc_host_##field)
+ show_fcpinit_##field, \
+ store_fcpinit_##field)
-#define fc_host_rd_enum_attr(title, maxlen) \
+#define fcpinit_rd_enum_attr(title, maxlen) \
static ssize_t \
-show_fc_host_##title (struct device *dev, \
+show_fcpinit_##title (struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct Scsi_Host *shost = transport_class_to_shost(dev); \
@@ -1338,12 +939,12 @@ show_fc_host_##title (struct device *dev, \
const char *name; \
if (i->f->get_host_##title) \
i->f->get_host_##title(shost); \
- name = get_fc_##title##_name(fc_host_##title(shost)); \
+ name = get_fc_##title##_name(fcpinit_##title(shost)); \
if (!name) \
return -EINVAL; \
return snprintf(buf, maxlen, "%s\n", name); \
} \
-static FC_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
+static FC_DEVICE_ATTR(host, title, S_IRUGO, show_fcpinit_##title, NULL)
#define SETUP_HOST_ATTRIBUTE_RD(field) \
i->private_host_attrs[count] = device_attr_host_##field; \
@@ -1373,22 +974,22 @@ static FC_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
#define fc_private_host_show_function(field, format_string, sz, cast) \
static ssize_t \
-show_fc_host_##field (struct device *dev, \
+show_fcpinit_##field (struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct Scsi_Host *shost = transport_class_to_shost(dev); \
- return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \
+ return snprintf(buf, sz, format_string, cast fcpinit_##field(shost)); \
}
#define fc_private_host_rd_attr(field, format_string, sz) \
fc_private_host_show_function(field, format_string, sz, ) \
static FC_DEVICE_ATTR(host, field, S_IRUGO, \
- show_fc_host_##field, NULL)
+ show_fcpinit_##field, NULL)
#define fc_private_host_rd_attr_cast(field, format_string, sz, cast) \
fc_private_host_show_function(field, format_string, sz, (cast)) \
static FC_DEVICE_ATTR(host, field, S_IRUGO, \
- show_fc_host_##field, NULL)
+ show_fcpinit_##field, NULL)
#define SETUP_PRIVATE_HOST_ATTRIBUTE_RD(field) \
i->private_host_attrs[count] = device_attr_host_##field; \
@@ -1407,101 +1008,18 @@ static FC_DEVICE_ATTR(host, field, S_IRUGO, \
/* Fixed Host Attributes */
-static ssize_t
-show_fc_host_supported_classes (struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = transport_class_to_shost(dev);
-
- if (fc_host_supported_classes(shost) == FC_COS_UNSPECIFIED)
- return snprintf(buf, 20, "unspecified\n");
-
- return get_fc_cos_names(fc_host_supported_classes(shost), buf);
-}
-static FC_DEVICE_ATTR(host, supported_classes, S_IRUGO,
- show_fc_host_supported_classes, NULL);
-
-static ssize_t
-show_fc_host_supported_fc4s (struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = transport_class_to_shost(dev);
- return (ssize_t)show_fc_fc4s(buf, fc_host_supported_fc4s(shost));
-}
-static FC_DEVICE_ATTR(host, supported_fc4s, S_IRUGO,
- show_fc_host_supported_fc4s, NULL);
-
-static ssize_t
-show_fc_host_supported_speeds (struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = transport_class_to_shost(dev);
-
- if (fc_host_supported_speeds(shost) == FC_PORTSPEED_UNKNOWN)
- return snprintf(buf, 20, "unknown\n");
-
- return get_fc_port_speed_names(fc_host_supported_speeds(shost), buf);
-}
-static FC_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
- show_fc_host_supported_speeds, NULL);
-
-
-fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
-fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
unsigned long long);
-fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
-fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20);
-fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
-
/* Dynamic Host Attributes */
-static ssize_t
-show_fc_host_active_fc4s (struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = transport_class_to_shost(dev);
- struct fc_internal *i = to_fc_internal(shost->transportt);
-
- if (i->f->get_host_active_fc4s)
- i->f->get_host_active_fc4s(shost);
-
- return (ssize_t)show_fc_fc4s(buf, fc_host_active_fc4s(shost));
-}
-static FC_DEVICE_ATTR(host, active_fc4s, S_IRUGO,
- show_fc_host_active_fc4s, NULL);
-
-static ssize_t
-show_fc_host_speed (struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct Scsi_Host *shost = transport_class_to_shost(dev);
- struct fc_internal *i = to_fc_internal(shost->transportt);
-
- if (i->f->get_host_speed)
- i->f->get_host_speed(shost);
-
- if (fc_host_speed(shost) == FC_PORTSPEED_UNKNOWN)
- return snprintf(buf, 20, "unknown\n");
-
- return get_fc_port_speed_names(fc_host_speed(shost), buf);
-}
-static FC_DEVICE_ATTR(host, speed, S_IRUGO,
- show_fc_host_speed, NULL);
-
-
-fc_host_rd_attr(port_id, "0x%06x\n", 20);
-fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN);
-fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
-fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);
-fc_host_rd_attr(symbolic_name, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1);
+fcpinit_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
fc_private_host_show_function(system_hostname, "%s\n",
FC_SYMBOLIC_NAME_SIZE + 1, )
-fc_host_store_str_function(system_hostname, FC_SYMBOLIC_NAME_SIZE)
+fcpinit_store_str_function(system_hostname, FC_SYMBOLIC_NAME_SIZE)
static FC_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,
- show_fc_host_system_hostname, store_fc_host_system_hostname);
+ show_fcpinit_system_hostname, store_fcpinit_system_hostname);
/* Private Host Attributes */
@@ -1513,7 +1031,7 @@ show_fc_private_host_tgtid_bind_type(struct device *dev,
struct Scsi_Host *shost = transport_class_to_shost(dev);
const char *name;
- name = get_fc_tgtid_bind_type_name(fc_host_tgtid_bind_type(shost));
+ name = get_fc_tgtid_bind_type_name(fcpinit_tgtid_bind_type(shost));
if (!name)
return -EINVAL;
return snprintf(buf, FC_BINDTYPE_MAX_NAMELEN, "%s\n", name);
@@ -1535,11 +1053,11 @@ store_fc_private_host_tgtid_bind_type(struct device *dev,
return -EINVAL;
/* if changing bind type, purge all unused consistent bindings */
- if (val != fc_host_tgtid_bind_type(shost)) {
+ if (val != fcpinit_tgtid_bind_type(shost)) {
spin_lock_irqsave(shost->host_lock, flags);
- while (!list_empty(&fc_host_rport_bindings(shost))) {
+ while (!list_empty(&fcpinit_rport_bindings(shost))) {
get_list_head_entry(rport,
- &fc_host_rport_bindings(shost), peers);
+ &fcpinit_rport_bindings(shost), peers);
list_del(&rport->peers);
rport->port_state = FC_PORTSTATE_DELETED;
fc_queue_work(shost, &rport->rport_delete_work);
@@ -1547,7 +1065,7 @@ store_fc_private_host_tgtid_bind_type(struct device *dev,
spin_unlock_irqrestore(shost->host_lock, flags);
}
- fc_host_tgtid_bind_type(shost) = val;
+ fcpinit_tgtid_bind_type(shost) = val;
return count;
}
@@ -1564,8 +1082,8 @@ store_fc_private_host_issue_lip(struct device *dev,
int ret;
/* ignore any data value written to the attribute */
- if (i->f->issue_fc_host_lip) {
- ret = i->f->issue_fc_host_lip(shost);
+ if (i->f->issue_fcpinit_lip) {
+ ret = i->f->issue_fcpinit_lip(shost);
return ret ? ret: count;
}
@@ -1575,8 +1093,6 @@ store_fc_private_host_issue_lip(struct device *dev,
static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
store_fc_private_host_issue_lip);
-fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
-
/*
* Host Statistics Management
@@ -1588,15 +1104,15 @@ fc_stat_show(const struct device *dev, char *buf, unsigned long offset)
{
struct Scsi_Host *shost = transport_class_to_shost(dev);
struct fc_internal *i = to_fc_internal(shost->transportt);
- struct fc_host_statistics *stats;
+ struct fcpinit_statistics *stats;
ssize_t ret = -ENOENT;
- if (offset > sizeof(struct fc_host_statistics) ||
+ if (offset > sizeof(struct fcpinit_statistics) ||
offset % sizeof(u64) != 0)
WARN_ON(1);
- if (i->f->get_fc_host_stats) {
- stats = (i->f->get_fc_host_stats)(shost);
+ if (i->f->get_fcpinit_stats) {
+ stats = (i->f->get_fcpinit_stats)(shost);
if (stats)
ret = snprintf(buf, 20, "0x%llx\n",
(unsigned long long)*(u64 *)(((u8 *) stats) + offset));
@@ -1606,36 +1122,36 @@ fc_stat_show(const struct device *dev, char *buf, unsigned long offset)
/* generate a read-only statistics attribute */
-#define fc_host_statistic(name) \
+#define fcpinit_statistic(name) \
static ssize_t show_fcstat_##name(struct device *cd, \
struct device_attribute *attr, \
char *buf) \
{ \
return fc_stat_show(cd, buf, \
- offsetof(struct fc_host_statistics, name)); \
+ offsetof(struct fcpinit_statistics, name)); \
} \
static FC_DEVICE_ATTR(host, name, S_IRUGO, show_fcstat_##name, NULL)
-fc_host_statistic(seconds_since_last_reset);
-fc_host_statistic(tx_frames);
-fc_host_statistic(tx_words);
-fc_host_statistic(rx_frames);
-fc_host_statistic(rx_words);
-fc_host_statistic(lip_count);
-fc_host_statistic(nos_count);
-fc_host_statistic(error_frames);
-fc_host_statistic(dumped_frames);
-fc_host_statistic(link_failure_count);
-fc_host_statistic(loss_of_sync_count);
-fc_host_statistic(loss_of_signal_count);
-fc_host_statistic(prim_seq_protocol_err_count);
-fc_host_statistic(invalid_tx_word_count);
-fc_host_statistic(invalid_crc_count);
-fc_host_statistic(fcp_input_requests);
-fc_host_statistic(fcp_output_requests);
-fc_host_statistic(fcp_control_requests);
-fc_host_statistic(fcp_input_megabytes);
-fc_host_statistic(fcp_output_megabytes);
+fcpinit_statistic(seconds_since_last_reset);
+fcpinit_statistic(tx_frames);
+fcpinit_statistic(tx_words);
+fcpinit_statistic(rx_frames);
+fcpinit_statistic(rx_words);
+fcpinit_statistic(lip_count);
+fcpinit_statistic(nos_count);
+fcpinit_statistic(error_frames);
+fcpinit_statistic(dumped_frames);
+fcpinit_statistic(link_failure_count);
+fcpinit_statistic(loss_of_sync_count);
+fcpinit_statistic(loss_of_signal_count);
+fcpinit_statistic(prim_seq_protocol_err_count);
+fcpinit_statistic(invalid_tx_word_count);
+fcpinit_statistic(invalid_crc_count);
+fcpinit_statistic(fcp_input_requests);
+fcpinit_statistic(fcp_output_requests);
+fcpinit_statistic(fcp_control_requests);
+fcpinit_statistic(fcp_input_megabytes);
+fcpinit_statistic(fcp_output_megabytes);
static ssize_t
fc_reset_statistics(struct device *dev, struct device_attribute *attr,
@@ -1645,8 +1161,8 @@ fc_reset_statistics(struct device *dev, struct device_attribute *attr,
struct fc_internal *i = to_fc_internal(shost->transportt);
/* ignore any data value written to the attribute */
- if (i->f->reset_fc_host_stats) {
- i->f->reset_fc_host_stats(shost);
+ if (i->f->reset_fcpinit_stats) {
+ i->f->reset_fcpinit_stats(shost);
return count;
}
@@ -1688,141 +1204,8 @@ static struct attribute_group fc_statistics_group = {
/* Host Vport Attributes */
-static int
-fc_parse_wwn(const char *ns, u64 *nm)
-{
- unsigned int i, j;
- u8 wwn[8];
-
- memset(wwn, 0, sizeof(wwn));
-
- /* Validate and store the new name */
- for (i=0, j=0; i < 16; i++) {
- if ((*ns >= 'a') && (*ns <= 'f'))
- j = ((j << 4) | ((*ns++ -'a') + 10));
- else if ((*ns >= 'A') && (*ns <= 'F'))
- j = ((j << 4) | ((*ns++ -'A') + 10));
- else if ((*ns >= '0') && (*ns <= '9'))
- j = ((j << 4) | (*ns++ -'0'));
- else
- return -EINVAL;
- if (i % 2) {
- wwn[i/2] = j & 0xff;
- j = 0;
- }
- }
-
- *nm = wwn_to_u64(wwn);
-
- return 0;
-}
-
-
-/*
- * "Short-cut" sysfs variable to create a new vport on a FC Host.
- * Input is a string of the form "<WWPN>:<WWNN>". Other attributes
- * will default to a NPIV-based FCP_Initiator; The WWNs are specified
- * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
- */
-static ssize_t
-store_fc_host_vport_create(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct Scsi_Host *shost = transport_class_to_shost(dev);
- struct fc_vport_identifiers vid;
- struct fc_vport *vport;
- unsigned int cnt=count;
- int stat;
-
- memset(&vid, 0, sizeof(vid));
-
- /* count may include a LF at end of string */
- if (buf[cnt-1] == '\n')
- cnt--;
-
- /* validate we have enough characters for WWPN */
- if ((cnt != (16+1+16)) || (buf[16] != ':'))
- return -EINVAL;
-
- stat = fc_parse_wwn(&buf[0], &vid.port_name);
- if (stat)
- return stat;
-
- stat = fc_parse_wwn(&buf[17], &vid.node_name);
- if (stat)
- return stat;
-
- vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
- vid.vport_type = FC_PORTTYPE_NPIV;
- /* vid.symbolic_name is already zero/NULL's */
- vid.disable = false; /* always enabled */
-
- /* we only allow support on Channel 0 !!! */
- stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport);
- return stat ? stat : count;
-}
-static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
- store_fc_host_vport_create);
-
-
-/*
- * "Short-cut" sysfs variable to delete a vport on a FC Host.
- * Vport is identified by a string containing "<WWPN>:<WWNN>".
- * The WWNs are specified as hex characters, and may *not* contain
- * any prefixes (e.g. 0x, x, etc)
- */
-static ssize_t
-store_fc_host_vport_delete(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct Scsi_Host *shost = transport_class_to_shost(dev);
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
- struct fc_vport *vport;
- u64 wwpn, wwnn;
- unsigned long flags;
- unsigned int cnt=count;
- int stat, match;
-
- /* count may include a LF at end of string */
- if (buf[cnt-1] == '\n')
- cnt--;
-
- /* validate we have enough characters for WWPN */
- if ((cnt != (16+1+16)) || (buf[16] != ':'))
- return -EINVAL;
-
- stat = fc_parse_wwn(&buf[0], &wwpn);
- if (stat)
- return stat;
-
- stat = fc_parse_wwn(&buf[17], &wwnn);
- if (stat)
- return stat;
-
- spin_lock_irqsave(shost->host_lock, flags);
- match = 0;
- /* we only allow support on Channel 0 !!! */
- list_for_each_entry(vport, &fc_host->vports, peers) {
- if ((vport->channel == 0) &&
- (vport->port_name == wwpn) && (vport->node_name == wwnn)) {
- match = 1;
- break;
- }
- }
- spin_unlock_irqrestore(shost->host_lock, flags);
-
- if (!match)
- return -ENODEV;
-
- stat = fc_vport_terminate(vport);
- return stat ? stat : count;
-}
-static FC_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
- store_fc_host_vport_delete);
-
-
-static int fc_host_match(struct attribute_container *cont,
- struct device *dev)
+static int fc_fcpinit_match(struct attribute_container *cont,
+ struct device *dev)
{
struct Scsi_Host *shost;
struct fc_internal *i;
@@ -1832,7 +1215,7 @@ static int fc_host_match(struct attribute_container *cont,
shost = dev_to_shost(dev);
if (!shost->transportt || shost->transportt->host_attrs.ac.class
- != &fc_host_class.class)
+ != &fcpinit_class.class)
return 0;
i = to_fc_internal(shost->transportt);
@@ -1851,7 +1234,7 @@ static int fc_target_match(struct attribute_container *cont,
shost = dev_to_shost(dev->parent);
if (!shost->transportt || shost->transportt->host_attrs.ac.class
- != &fc_host_class.class)
+ != &fcpinit_class.class)
return 0;
i = to_fc_internal(shost->transportt);
@@ -1883,7 +1266,7 @@ static int fc_rport_match(struct attribute_container *cont,
shost = dev_to_shost(dev->parent);
if (!shost->transportt || shost->transportt->host_attrs.ac.class
- != &fc_host_class.class)
+ != &fcpinit_class.class)
return 0;
i = to_fc_internal(shost->transportt);
@@ -1891,41 +1274,6 @@ static int fc_rport_match(struct attribute_container *cont,
return &i->rport_attr_cont.ac == cont;
}
-
-static void fc_vport_dev_release(struct device *dev)
-{
- struct fc_vport *vport = dev_to_vport(dev);
- put_device(dev->parent); /* release kobj parent */
- kfree(vport);
-}
-
-int scsi_is_fc_vport(const struct device *dev)
-{
- return dev->release == fc_vport_dev_release;
-}
-EXPORT_SYMBOL(scsi_is_fc_vport);
-
-static int fc_vport_match(struct attribute_container *cont,
- struct device *dev)
-{
- struct fc_vport *vport;
- struct Scsi_Host *shost;
- struct fc_internal *i;
-
- if (!scsi_is_fc_vport(dev))
- return 0;
- vport = dev_to_vport(dev);
-
- shost = vport_to_shost(vport);
- if (!shost->transportt || shost->transportt->host_attrs.ac.class
- != &fc_host_class.class)
- return 0;
-
- i = to_fc_internal(shost->transportt);
- return &i->vport_attr_cont.ac == cont;
-}
-
-
/**
* fc_timed_out - FC Transport I/O timeout intercept handler
* @scmd: The SCSI command which timed out
@@ -1972,7 +1320,7 @@ fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun)
spin_lock_irqsave(shost->host_lock, flags);
- list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+ list_for_each_entry(rport, &fcpinit_rports(shost), peers) {
if (rport->scsi_target_id == -1)
continue;
@@ -2060,10 +1408,10 @@ fc_attach_transport(struct fc_function_template *ft)
transport_container_register(&i->t.target_attrs);
i->t.host_attrs.ac.attrs = &i->host_attrs[0];
- i->t.host_attrs.ac.class = &fc_host_class.class;
- i->t.host_attrs.ac.match = fc_host_match;
- i->t.host_size = sizeof(struct fc_host_attrs);
- if (ft->get_fc_host_stats)
+ i->t.host_attrs.ac.class = &fcpinit_class.class;
+ i->t.host_attrs.ac.match = fc_fcpinit_match;
+ i->t.host_size = sizeof(struct fc_fcpinit);
+ if (ft->get_fcpinit_stats)
i->t.host_attrs.statistics = &fc_statistics_group;
transport_container_register(&i->t.host_attrs);
@@ -2072,11 +1420,6 @@ fc_attach_transport(struct fc_function_template *ft)
i->rport_attr_cont.ac.match = fc_rport_match;
transport_container_register(&i->rport_attr_cont);
- i->vport_attr_cont.ac.attrs = &i->vport_attrs[0];
- i->vport_attr_cont.ac.class = &fc_vport_class.class;
- i->vport_attr_cont.ac.match = fc_vport_match;
- transport_container_register(&i->vport_attr_cont);
-
i->f = ft;
/* Transport uses the shost workq for scsi scanning */
@@ -2107,38 +1450,16 @@ fc_attach_transport(struct fc_function_template *ft)
* Setup SCSI Host Attributes.
*/
count=0;
- SETUP_HOST_ATTRIBUTE_RD(node_name);
- SETUP_HOST_ATTRIBUTE_RD(port_name);
SETUP_HOST_ATTRIBUTE_RD(permanent_port_name);
- SETUP_HOST_ATTRIBUTE_RD(supported_classes);
- SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
- SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
- SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
- if (ft->vport_create) {
- SETUP_HOST_ATTRIBUTE_RD_NS(max_npiv_vports);
- SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse);
- }
- SETUP_HOST_ATTRIBUTE_RD(serial_number);
- SETUP_HOST_ATTRIBUTE_RD(port_id);
- SETUP_HOST_ATTRIBUTE_RD(port_type);
SETUP_HOST_ATTRIBUTE_RD(port_state);
- SETUP_HOST_ATTRIBUTE_RD(active_fc4s);
- SETUP_HOST_ATTRIBUTE_RD(speed);
- SETUP_HOST_ATTRIBUTE_RD(fabric_name);
- SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
SETUP_HOST_ATTRIBUTE_RW(system_hostname);
/* Transport-managed attributes */
SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
- if (ft->issue_fc_host_lip)
+ if (ft->issue_fcpinit_lip)
SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
- if (ft->vport_create)
- SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_create);
- if (ft->vport_delete)
- SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_delete);
-
- BUG_ON(count > FC_HOST_NUM_ATTRS);
+ BUG_ON(count > FCPINIT_NUM_ATTRS);
i->host_attrs[count] = NULL;
@@ -2161,24 +1482,6 @@ fc_attach_transport(struct fc_function_template *ft)
i->rport_attrs[count] = NULL;
- /*
- * Setup Virtual Port Attributes.
- */
- count=0;
- SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_state);
- SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_last_state);
- SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(node_name);
- SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(port_name);
- SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(roles);
- SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_type);
- SETUP_VPORT_ATTRIBUTE_RW(symbolic_name);
- SETUP_VPORT_ATTRIBUTE_WR(vport_delete);
- SETUP_VPORT_ATTRIBUTE_WR(vport_disable);
-
- BUG_ON(count > FC_VPORT_NUM_ATTRS);
-
- i->vport_attrs[count] = NULL;
-
return &i->t;
}
EXPORT_SYMBOL(fc_attach_transport);
@@ -2190,15 +1493,14 @@ void fc_release_transport(struct scsi_transport_template *t)
transport_container_unregister(&i->t.target_attrs);
transport_container_unregister(&i->t.host_attrs);
transport_container_unregister(&i->rport_attr_cont);
- transport_container_unregister(&i->vport_attr_cont);
kfree(i);
}
EXPORT_SYMBOL(fc_release_transport);
/**
- * fc_queue_work - Queue work to the fc_host workqueue.
- * @shost: Pointer to Scsi_Host bound to fc_host.
+ * fc_queue_work - Queue work to the fcpinit workqueue.
+ * @shost: Pointer to Scsi_Host bound to fcpinit.
* @work: Work to queue for execution.
*
* Return value:
@@ -2209,7 +1511,7 @@ EXPORT_SYMBOL(fc_release_transport);
static int
fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)
{
- if (unlikely(!fc_host_work_q(shost))) {
+ if (unlikely(!fcpinit_work_q(shost))) {
printk(KERN_ERR
"ERROR: FC host '%s' attempted to queue work, "
"when no workqueue created.\n", shost->hostt->name);
@@ -2218,17 +1520,17 @@ fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)
return -EINVAL;
}
- return queue_work(fc_host_work_q(shost), work);
+ return queue_work(fcpinit_work_q(shost), work);
}
/**
- * fc_flush_work - Flush a fc_host's workqueue.
- * @shost: Pointer to Scsi_Host bound to fc_host.
+ * fc_flush_work - Flush a fcpinit's workqueue.
+ * @shost: Pointer to Scsi_Host bound to fcpinit.
*/
static void
fc_flush_work(struct Scsi_Host *shost)
{
- if (!fc_host_work_q(shost)) {
+ if (!fcpinit_work_q(shost)) {
printk(KERN_ERR
"ERROR: FC host '%s' attempted to flush work, "
"when no workqueue created.\n", shost->hostt->name);
@@ -2236,12 +1538,12 @@ fc_flush_work(struct Scsi_Host *shost)
return;
}
- flush_workqueue(fc_host_work_q(shost));
+ flush_workqueue(fcpinit_work_q(shost));
}
/**
- * fc_queue_devloss_work - Schedule work for the fc_host devloss workqueue.
- * @shost: Pointer to Scsi_Host bound to fc_host.
+ * fc_queue_devloss_work - Schedule work for the fcpinit devloss workqueue.
+ * @shost: Pointer to Scsi_Host bound to fcpinit.
* @work: Work to queue for execution.
* @delay: jiffies to delay the work queuing
*
@@ -2252,7 +1554,7 @@ static int
fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,
unsigned long delay)
{
- if (unlikely(!fc_host_devloss_work_q(shost))) {
+ if (unlikely(!fcpinit_devloss_work_q(shost))) {
printk(KERN_ERR
"ERROR: FC host '%s' attempted to queue work, "
"when no workqueue created.\n", shost->hostt->name);
@@ -2261,17 +1563,17 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,
return -EINVAL;
}
- return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
+ return queue_delayed_work(fcpinit_devloss_work_q(shost), work, delay);
}
/**
- * fc_flush_devloss - Flush a fc_host's devloss workqueue.
- * @shost: Pointer to Scsi_Host bound to fc_host.
+ * fc_flush_devloss - Flush a fcpinit's devloss workqueue.
+ * @shost: Pointer to Scsi_Host bound to fcpinit.
*/
static void
fc_flush_devloss(struct Scsi_Host *shost)
{
- if (!fc_host_devloss_work_q(shost)) {
+ if (!fcpinit_devloss_work_q(shost)) {
printk(KERN_ERR
"ERROR: FC host '%s' attempted to flush work, "
"when no workqueue created.\n", shost->hostt->name);
@@ -2279,7 +1581,7 @@ fc_flush_devloss(struct Scsi_Host *shost)
return;
}
- flush_workqueue(fc_host_devloss_work_q(shost));
+ flush_workqueue(fcpinit_devloss_work_q(shost));
}
@@ -2301,28 +1603,23 @@ fc_flush_devloss(struct Scsi_Host *shost)
void
fc_remove_host(struct Scsi_Host *shost)
{
- struct fc_vport *vport = NULL, *next_vport = NULL;
struct fc_rport *rport = NULL, *next_rport = NULL;
struct workqueue_struct *work_q;
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_fcpinit *fcpinit = shost_to_fcpinit(shost);
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
- /* Remove any vports */
- list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers)
- fc_queue_work(shost, &vport->vport_delete_work);
-
/* Remove any remote ports */
list_for_each_entry_safe(rport, next_rport,
- &fc_host->rports, peers) {
+ &fcpinit->rports, peers) {
list_del(&rport->peers);
rport->port_state = FC_PORTSTATE_DELETED;
fc_queue_work(shost, &rport->rport_delete_work);
}
list_for_each_entry_safe(rport, next_rport,
- &fc_host->rport_bindings, peers) {
+ &fcpinit->rport_bindings, peers) {
list_del(&rport->peers);
rport->port_state = FC_PORTSTATE_DELETED;
fc_queue_work(shost, &rport->rport_delete_work);
@@ -2334,16 +1631,16 @@ fc_remove_host(struct Scsi_Host *shost)
scsi_flush_work(shost);
/* flush all stgt delete, and rport delete work items, then kill it */
- if (fc_host->work_q) {
- work_q = fc_host->work_q;
- fc_host->work_q = NULL;
+ if (fcpinit->work_q) {
+ work_q = fcpinit->work_q;
+ fcpinit->work_q = NULL;
destroy_workqueue(work_q);
}
/* flush all devloss work items, then kill it */
- if (fc_host->devloss_work_q) {
- work_q = fc_host->devloss_work_q;
- fc_host->devloss_work_q = NULL;
+ if (fcpinit->devloss_work_q) {
+ work_q = fcpinit->devloss_work_q;
+ fcpinit->devloss_work_q = NULL;
destroy_workqueue(work_q);
}
}
@@ -2451,7 +1748,7 @@ fc_rport_final_delete(struct work_struct *work)
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
- put_device(&shost->shost_gendev); /* for fc_host->rport list */
+ put_device(&shost->shost_gendev); /* for fcpinit->rport list */
put_device(dev); /* for self-reference */
}
@@ -2473,7 +1770,7 @@ static struct fc_rport *
fc_rport_create(struct Scsi_Host *shost, int channel,
struct fc_rport_identifiers *ids)
{
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_fcpinit *fcpinit = shost_to_fcpinit(shost);
struct fc_internal *fci = to_fc_internal(shost->transportt);
struct fc_rport *rport;
struct device *dev;
@@ -2509,13 +1806,13 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
spin_lock_irqsave(shost->host_lock, flags);
- rport->number = fc_host->next_rport_number++;
+ rport->number = fcpinit->next_rport_number++;
if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
- rport->scsi_target_id = fc_host->next_target_id++;
+ rport->scsi_target_id = fcpinit->next_target_id++;
else
rport->scsi_target_id = -1;
- list_add_tail(&rport->peers, &fc_host->rports);
- get_device(&shost->shost_gendev); /* for fc_host->rport list */
+ list_add_tail(&rport->peers, &fcpinit->rports);
+ get_device(&shost->shost_gendev); /* for fcpinit->rport list */
spin_unlock_irqrestore(shost->host_lock, flags);
@@ -2550,7 +1847,7 @@ delete_rport:
transport_destroy_device(dev);
spin_lock_irqsave(shost->host_lock, flags);
list_del(&rport->peers);
- put_device(&shost->shost_gendev); /* for fc_host->rport list */
+ put_device(&shost->shost_gendev); /* for fcpinit->rport list */
spin_unlock_irqrestore(shost->host_lock, flags);
put_device(dev->parent);
kfree(rport);
@@ -2600,7 +1897,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
struct fc_rport_identifiers *ids)
{
struct fc_internal *fci = to_fc_internal(shost->transportt);
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_fcpinit *fcpinit = shost_to_fcpinit(shost);
struct fc_rport *rport;
unsigned long flags;
int match = 0;
@@ -2615,12 +1912,12 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
*/
spin_lock_irqsave(shost->host_lock, flags);
- list_for_each_entry(rport, &fc_host->rports, peers) {
+ list_for_each_entry(rport, &fcpinit->rports, peers) {
if ((rport->port_state == FC_PORTSTATE_BLOCKED) &&
(rport->channel == channel)) {
- switch (fc_host->tgtid_bind_type) {
+ switch (fcpinit->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
case FC_TGTID_BIND_NONE:
if (rport->port_name == ids->port_name)
@@ -2713,16 +2010,16 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
* Search the bindings array
* Note: if never a FCP target, you won't be on this list
*/
- if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {
+ if (fcpinit->tgtid_bind_type != FC_TGTID_BIND_NONE) {
/* search for a matching consistent binding */
- list_for_each_entry(rport, &fc_host->rport_bindings,
+ list_for_each_entry(rport, &fcpinit->rport_bindings,
peers) {
if (rport->channel != channel)
continue;
- switch (fc_host->tgtid_bind_type) {
+ switch (fcpinit->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
if (rport->port_name == ids->port_name)
match = 1;
@@ -2740,7 +2037,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
}
if (match) {
- list_move_tail(&rport->peers, &fc_host->rports);
+ list_move_tail(&rport->peers, &fcpinit->rports);
break;
}
}
@@ -2789,7 +2086,7 @@ EXPORT_SYMBOL(fc_remote_port_add);
* The LLDD calls this routine to notify the transport that a remote
* port is no longer part of the topology. Note: Although a port
* may no longer be part of the topology, it may persist in the remote
- * ports displayed by the fc_host. We do this under 2 conditions:
+ * ports displayed by the fcpinit. We do this under 2 conditions:
* 1) If the port was a scsi target, we delay its deletion by "blocking" it.
* This allows the port to temporarily disappear, then reappear without
* disrupting the SCSI device tree attached to it. During the "blocked"
@@ -2840,7 +2137,7 @@ fc_remote_port_delete(struct fc_rport *rport)
unsigned long flags;
/*
- * No need to flush the fc_host work_q's, as all adds are synchronous.
+ * No need to flush the fcpinit work_q's, as all adds are synchronous.
*
* We do need to reclaim the rport scan work element, so eventually
* (in fc_rport_final_delete()) we'll flush the scsi host work_q if
@@ -2914,7 +2211,7 @@ void
fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
{
struct Scsi_Host *shost = rport_to_shost(rport);
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_fcpinit *fcpinit = shost_to_fcpinit(shost);
unsigned long flags;
int create = 0;
int ret;
@@ -2922,7 +2219,7 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
spin_lock_irqsave(shost->host_lock, flags);
if (roles & FC_PORT_ROLE_FCP_TARGET) {
if (rport->scsi_target_id == -1) {
- rport->scsi_target_id = fc_host->next_target_id++;
+ rport->scsi_target_id = fcpinit->next_target_id++;
create = 1;
} else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))
create = 1;
@@ -2988,7 +2285,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
container_of(work, struct fc_rport, dev_loss_work.work);
struct Scsi_Host *shost = rport_to_shost(rport);
struct fc_internal *i = to_fc_internal(shost->transportt);
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_fcpinit *fcpinit = shost_to_fcpinit(shost);
unsigned long flags;
int do_callback = 0;
@@ -3023,7 +2320,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
return;
}
- if ((fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) ||
+ if ((fcpinit->tgtid_bind_type == FC_TGTID_BIND_NONE) ||
(rport->scsi_target_id == -1)) {
list_del(&rport->peers);
rport->port_state = FC_PORTSTATE_DELETED;
@@ -3040,7 +2337,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
"blocked FC remote port time out: removing target and "
"saving binding\n");
- list_move_tail(&rport->peers, &fc_host->rport_bindings);
+ list_move_tail(&rport->peers, &fcpinit->rport_bindings);
/*
* Note: We do not remove or clear the hostdata area. This allows
@@ -3070,7 +2367,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
if (rport->port_state == FC_PORTSTATE_NOTPRESENT) { /* still missing */
/* remove the identifiers that aren't used in the consisting binding */
- switch (fc_host->tgtid_bind_type) {
+ switch (fcpinit->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
rport->node_name = -1;
rport->port_id = -1;
@@ -3182,246 +2479,6 @@ void fc_block_scsi_eh(struct scsi_cmnd *cmnd)
}
EXPORT_SYMBOL(fc_block_scsi_eh);
-/**
- * fc_vport_setup - allocates and creates a FC virtual port.
- * @shost: scsi host the virtual port is connected to.
- * @channel: Channel on shost port connected to.
- * @pdev: parent device for vport
- * @ids: The world wide names, FC4 port roles, etc for
- * the virtual port.
- * @ret_vport: The pointer to the created vport.
- *
- * Allocates and creates the vport structure, calls the parent host
- * to instantiate the vport, the completes w/ class and sysfs creation.
- *
- * Notes:
- * This routine assumes no locks are held on entry.
- */
-static int
-fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
- struct fc_vport_identifiers *ids, struct fc_vport **ret_vport)
-{
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
- struct fc_internal *fci = to_fc_internal(shost->transportt);
- struct fc_vport *vport;
- struct device *dev;
- unsigned long flags;
- size_t size;
- int error;
-
- *ret_vport = NULL;
-
- if ( ! fci->f->vport_create)
- return -ENOENT;
-
- size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size);
- vport = kzalloc(size, GFP_KERNEL);
- if (unlikely(!vport)) {
- printk(KERN_ERR "%s: allocation failure\n", __func__);
- return -ENOMEM;
- }
-
- vport->vport_state = FC_VPORT_UNKNOWN;
- vport->vport_last_state = FC_VPORT_UNKNOWN;
- vport->node_name = ids->node_name;
- vport->port_name = ids->port_name;
- vport->roles = ids->roles;
- vport->vport_type = ids->vport_type;
- if (fci->f->dd_fcvport_size)
- vport->dd_data = &vport[1];
- vport->shost = shost;
- vport->channel = channel;
- vport->flags = FC_VPORT_CREATING;
- INIT_WORK(&vport->vport_delete_work, fc_vport_sched_delete);
-
- spin_lock_irqsave(shost->host_lock, flags);
-
- if (fc_host->npiv_vports_inuse >= fc_host->max_npiv_vports) {
- spin_unlock_irqrestore(shost->host_lock, flags);
- kfree(vport);
- return -ENOSPC;
- }
- fc_host->npiv_vports_inuse++;
- vport->number = fc_host->next_vport_number++;
- list_add_tail(&vport->peers, &fc_host->vports);
- get_device(&shost->shost_gendev); /* for fc_host->vport list */
-
- spin_unlock_irqrestore(shost->host_lock, flags);
-
- dev = &vport->dev;
- device_initialize(dev); /* takes self reference */
- dev->parent = get_device(pdev); /* takes parent reference */
- dev->release = fc_vport_dev_release;
- dev_set_name(dev, "vport-%d:%d-%d",
- shost->host_no, channel, vport->number);
- transport_setup_device(dev);
-
- error = device_add(dev);
- if (error) {
- printk(KERN_ERR "FC Virtual Port device_add failed\n");
- goto delete_vport;
- }
- transport_add_device(dev);
- transport_configure_device(dev);
-
- error = fci->f->vport_create(vport, ids->disable);
- if (error) {
- printk(KERN_ERR "FC Virtual Port LLDD Create failed\n");
- goto delete_vport_all;
- }
-
- /*
- * if the parent isn't the physical adapter's Scsi_Host, ensure
- * the Scsi_Host at least contains ia symlink to the vport.
- */
- if (pdev != &shost->shost_gendev) {
- error = sysfs_create_link(&shost->shost_gendev.kobj,
- &dev->kobj, dev_name(dev));
- if (error)
- printk(KERN_ERR
- "%s: Cannot create vport symlinks for "
- "%s, err=%d\n",
- __func__, dev_name(dev), error);
- }
- spin_lock_irqsave(shost->host_lock, flags);
- vport->flags &= ~FC_VPORT_CREATING;
- spin_unlock_irqrestore(shost->host_lock, flags);
-
- dev_printk(KERN_NOTICE, pdev,
- "%s created via shost%d channel %d\n", dev_name(dev),
- shost->host_no, channel);
-
- *ret_vport = vport;
-
- return 0;
-
-delete_vport_all:
- transport_remove_device(dev);
- device_del(dev);
-delete_vport:
- transport_destroy_device(dev);
- spin_lock_irqsave(shost->host_lock, flags);
- list_del(&vport->peers);
- put_device(&shost->shost_gendev); /* for fc_host->vport list */
- fc_host->npiv_vports_inuse--;
- spin_unlock_irqrestore(shost->host_lock, flags);
- put_device(dev->parent);
- kfree(vport);
-
- return error;
-}
-
-/**
- * fc_vport_create - Admin App or LLDD requests creation of a vport
- * @shost: scsi host the virtual port is connected to.
- * @channel: channel on shost port connected to.
- * @ids: The world wide names, FC4 port roles, etc for
- * the virtual port.
- *
- * Notes:
- * This routine assumes no locks are held on entry.
- */
-struct fc_vport *
-fc_vport_create(struct Scsi_Host *shost, int channel,
- struct fc_vport_identifiers *ids)
-{
- int stat;
- struct fc_vport *vport;
-
- stat = fc_vport_setup(shost, channel, &shost->shost_gendev,
- ids, &vport);
- return stat ? NULL : vport;
-}
-EXPORT_SYMBOL(fc_vport_create);
-
-/**
- * fc_vport_terminate - Admin App or LLDD requests termination of a vport
- * @vport: fc_vport to be terminated
- *
- * Calls the LLDD vport_delete() function, then deallocates and removes
- * the vport from the shost and object tree.
- *
- * Notes:
- * This routine assumes no locks are held on entry.
- */
-int
-fc_vport_terminate(struct fc_vport *vport)
-{
- struct Scsi_Host *shost = vport_to_shost(vport);
- struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
- struct fc_internal *i = to_fc_internal(shost->transportt);
- struct device *dev = &vport->dev;
- unsigned long flags;
- int stat;
-
- spin_lock_irqsave(shost->host_lock, flags);
- if (vport->flags & FC_VPORT_CREATING) {
- spin_unlock_irqrestore(shost->host_lock, flags);
- return -EBUSY;
- }
- if (vport->flags & (FC_VPORT_DEL)) {
- spin_unlock_irqrestore(shost->host_lock, flags);
- return -EALREADY;
- }
- vport->flags |= FC_VPORT_DELETING;
- spin_unlock_irqrestore(shost->host_lock, flags);
-
- if (i->f->vport_delete)
- stat = i->f->vport_delete(vport);
- else
- stat = -ENOENT;
-
- spin_lock_irqsave(shost->host_lock, flags);
- vport->flags &= ~FC_VPORT_DELETING;
- if (!stat) {
- vport->flags |= FC_VPORT_DELETED;
- list_del(&vport->peers);
- fc_host->npiv_vports_inuse--;
- put_device(&shost->shost_gendev); /* for fc_host->vport list */
- }
- spin_unlock_irqrestore(shost->host_lock, flags);
-
- if (stat)
- return stat;
-
- if (dev->parent != &shost->shost_gendev)
- sysfs_remove_link(&shost->shost_gendev.kobj, dev_name(dev));
- transport_remove_device(dev);
- device_del(dev);
- transport_destroy_device(dev);
-
- /*
- * Removing our self-reference should mean our
- * release function gets called, which will drop the remaining
- * parent reference and free the data structure.
- */
- put_device(dev); /* for self-reference */
-
- return 0; /* SUCCESS */
-}
-EXPORT_SYMBOL(fc_vport_terminate);
-
-/**
- * fc_vport_sched_delete - workq-based delete request for a vport
- * @work: vport to be deleted.
- */
-static void
-fc_vport_sched_delete(struct work_struct *work)
-{
- struct fc_vport *vport =
- container_of(work, struct fc_vport, vport_delete_work);
- int stat;
-
- stat = fc_vport_terminate(vport);
- if (stat)
- dev_printk(KERN_ERR, vport->dev.parent,
- "%s: %s could not be deleted created via "
- "shost%d channel %d - error %d\n", __func__,
- dev_name(&vport->dev), vport->shost->host_no,
- vport->channel, stat);
-}
-
-
/*
* BSG support
*/
@@ -3914,11 +2971,11 @@ fc_bsg_rport_handler(struct request_queue *q)
/**
* fc_bsg_hostadd - Create and add the bsg hooks so we can receive requests
- * @shost: shost for fc_host
- * @fc_host: fc_host adding the structures to
+ * @shost: shost for fcpinit
+ * @fcpinit: fcpinit adding the structures to
*/
static int
-fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
+fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_fcpinit *fcpinit)
{
struct device *dev = &shost->shost_gendev;
struct fc_internal *i = to_fc_internal(shost->transportt);
@@ -3926,17 +2983,17 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
int err;
char bsg_name[20];
- fc_host->rqst_q = NULL;
+ fcpinit->rqst_q = NULL;
if (!i->f->bsg_request)
return -ENOTSUPP;
snprintf(bsg_name, sizeof(bsg_name),
- "fc_host%d", shost->host_no);
+ "fcpinit%d", shost->host_no);
q = __scsi_alloc_queue(shost, fc_bsg_host_handler);
if (!q) {
- printk(KERN_ERR "fc_host%d: bsg interface failed to "
+ printk(KERN_ERR "fcpinit%d: bsg interface failed to "
"initialize - no request queue\n",
shost->host_no);
return -ENOMEM;
@@ -3950,14 +3007,14 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
err = bsg_register_queue(q, dev, bsg_name, NULL);
if (err) {
- printk(KERN_ERR "fc_host%d: bsg interface failed to "
+ printk(KERN_ERR "fcpinit%d: bsg interface failed to "
"initialize - register queue\n",
shost->host_no);
blk_cleanup_queue(q);
return err;
}
- fc_host->rqst_q = q;
+ fcpinit->rqst_q = q;
return 0;
}
diff --git a/include/scsi/fc.h b/include/scsi/fc.h
new file mode 100644
index 0000000..7ca20fb
--- /dev/null
+++ b/include/scsi/fc.h
@@ -0,0 +1,461 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _FC_H_
+#define _FC_H_
+
+#include <linux/device.h>
+#include <scsi/scsi_transport_fc.h>
+
+struct fc_fcport;
+struct fc_fcvport;
+struct fc_fcfabric;
+struct fcvport_function_template;
+
+/*
+ * fc_vport_state: If you alter this, you also need to alter
+ * scsi_transport_fc.c (for the ascii descriptions).
+ */
+enum fc_vport_state {
+ FC_VPORT_UNKNOWN,
+ FC_VPORT_ACTIVE,
+ FC_VPORT_DISABLED,
+ FC_VPORT_LINKDOWN,
+ FC_VPORT_INITIALIZING,
+ FC_VPORT_NO_FABRIC_SUPP,
+ FC_VPORT_NO_FABRIC_RSCS,
+ FC_VPORT_FABRIC_LOGOUT,
+ FC_VPORT_FABRIC_REJ_WWN,
+ FC_VPORT_FAILED,
+};
+
+#define FC_SERIAL_NUMBER_SIZE 80
+
+#define dev_to_fcport(d) \
+ container_of(d, struct fc_fcport, gendev)
+
+#define dev_to_fcfport(d) \
+ container_of(d, struct fc_fcfport, gendev)
+
+#define dev_to_fcfabric(d) \
+ container_of(d, struct fc_fcfabric, gendev)
+
+#define dev_to_fcvport(d) \
+ container_of(d, struct fc_fcvport, gendev)
+
+#define dev_to_fcpinit(d) \
+ container_of(d, struct fc_fcpinit, gendev)
+
+/*
+ * TODO: Double check these maximum attribute defines
+ */
+#define FCPORT_NUM_ATTRS 7
+#define FCVPORT_NUM_ATTRS 9
+#define FCFABRIC_NUM_ATTRS 5
+#define FCPINIT_NUM_ATTRS 4
+
+struct fcport_function_template {
+ void (*get_fcport_speed)(struct fc_fcport *);
+ void (*get_fcport_active_fc4s)(struct fc_fcport *);
+
+ unsigned long show_fcport_maxframe_size:1;
+ unsigned long show_fcport_supported_speeds:1;
+ unsigned long show_fcport_speed:1;
+ unsigned long show_fcport_supported_fc4s:1;
+ unsigned long show_fcport_active_fc4s:1;
+ unsigned long show_fcport_supported_classes:1;
+ unsigned long show_fcport_serial_number:1;
+};
+
+struct fc_fcport {
+ int id;
+ struct device gendev;
+ struct fcport_function_template *f;
+ struct device_attribute attrs[FCPORT_NUM_ATTRS];
+
+ /* Fixed Attributes */
+ u8 supported_fc4s[FC_FC4_LIST_SIZE];
+ u32 maxframe_size;
+ u32 supported_classes;
+ char serial_number[FC_SERIAL_NUMBER_SIZE];
+
+ /* Dynamic Attributes*/
+ u8 active_fc4s[FC_FC4_LIST_SIZE];
+
+ /*
+ * TODO: For FCoE supported_speeds and speed
+ * can change on a link event. Previously they
+ * were listed under the "Fixed Attributes" comment,
+ * but maybe they should be moved under the
+ * "Dynamic Attributes" comment. Does this have
+ * an impact on the functionality?
+ */
+ u32 supported_speeds;
+ u32 speed;
+};
+#define fcport_maxframe_size(x) \
+ (x)->maxframe_size
+#define fcport_supported_speeds(x) \
+ (x)->supported_speeds
+#define fcport_speed(x) \
+ (x)->speed
+#define fcport_supported_fc4s(x) \
+ (x)->supported_fc4s
+#define fcport_active_fc4s(x) \
+ (x)->active_fc4s
+#define fcport_supported_classes(x) \
+ (x)->supported_classes
+#define fcport_serial_number(x) \
+ (x)->serial_number
+
+struct fc_fcfport {
+ struct device gendev;
+ int name;
+};
+
+struct fcfabric_function_template {
+ void (*get_fcfabric_fabric_name)(struct fc_fcfabric *);
+ int (*vport_create)(void *, struct fc_fcvport *, bool);
+ int (*vport_disable)(struct fc_fcvport *, bool);
+ int (*vport_delete)(void *, struct fc_fcvport *);
+
+ unsigned long show_fcfabric_fabric_name:1;
+
+ /*
+ * TODO: This seems misplaced, but the vport_create
+ * code in fcfabric needs it.
+ */
+ u32 dd_fcvport_size;
+};
+
+struct fc_fcfabric {
+ struct device gendev;
+ struct fcfabric_function_template *f;
+
+ /* Fixed Attributes */
+ u64 fabric_name;
+ u16 max_npiv_vports;
+
+ /* Dynamic Attributes */
+ u16 npiv_vports_inuse;
+
+ /* Internal Data */
+ u32 next_vport_number;
+
+ /*
+ * TODO: This violates layering, but is necessary until
+ * the fcfabric has some locking to protect it's list
+ * of vports. Right now the host_lock is used for that
+ * protection so we need the Scsi_Host until there is
+ * a replacement lock.
+ */
+ struct Scsi_Host *shost;
+
+ /* TODO: This must be moved out of here!!!! */
+ struct fcvport_function_template *fcvport_f;
+
+ struct list_head vports;
+
+ /* Replacement for shost->host_lock, protects vports list */
+ spinlock_t lock;
+
+ struct device_attribute attrs[FCFABRIC_NUM_ATTRS];
+};
+
+#define fcfabric_fabric_name(x) \
+ (x)->fabric_name
+#define fcfabric_max_npiv_vports(x) \
+ (x)->max_npiv_vports
+#define fcfabric_next_vport_number(x) \
+ (x)->next_vport_number
+#define fcfabric_npiv_vports_inuse(x) \
+ (x)->npiv_vports_inuse
+#define fcfabric_vports(x) \
+ (x)->vports
+
+
+struct fcvport_function_template {
+ void (*get_fcvport_port_id)(struct fc_fcvport *);
+ void (*get_fcvport_symbolic_name)(struct fc_fcvport *);
+ void (*get_fcvport_port_type)(struct fc_fcvport *);
+ void (*set_fcvport_symbolic_name)(struct fc_fcvport *);
+
+ unsigned long show_fcvport_port_id:1;
+ unsigned long show_fcvport_symbolic_name:1;
+ unsigned long show_fcvport_node_name:1;
+ unsigned long show_fcvport_port_name:1;
+ unsigned long show_fcvport_port_type:1;
+};
+
+/*
+ * FC Virtual Port Attributes
+ *
+ * This structure exists for each FC port is a virtual FC port. Virtual
+ * ports share the physical link with the Physical port. Each virtual
+ * ports has a unique presense on the SAN, and may be instantiated via
+ * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a
+ * unique presense, each vport has it's own view of the fabric,
+ * authentication privilege, and priorities.
+ *
+ * A virtual port may support 1 or more FC4 roles. Typically it is a
+ * FCP Initiator. It could be a FCP Target, or exist sole for an IP over FC
+ * roles. FC port attributes for the vport will be reported on any
+ * fc_host class object allocated for an FCP Initiator.
+ *
+ * --
+ *
+ * Fixed attributes are not expected to change. The driver is
+ * expected to set these values after receiving the fc_vport structure
+ * via the vport_create() call from the transport.
+ * The transport fully manages all get functions w/o driver interaction.
+ *
+ * Dynamic attributes are expected to change. The driver participates
+ * in all get/set operations via functions provided by the driver.
+ *
+ * Private attributes are transport-managed values. They are fully
+ * managed by the transport w/o driver interaction.
+ */
+struct fc_fcvport {
+ struct device gendev;
+ struct fcvport_function_template *f;
+ u32 id;
+
+ u32 port_id;
+ char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
+ u64 node_name;
+ u64 port_name;
+ enum fc_port_type port_type;
+
+ struct device_attribute attrs[FCVPORT_NUM_ATTRS];
+
+ /*
+ * TODO: Sort these members out, they are from
+ * the FC transport's vport definition.
+ */
+ /* Fixed Attributes */
+
+ /* Dynamic Attributes */
+
+ /* Private (Transport-managed) Attributes */
+ enum fc_vport_state vport_state;
+ enum fc_vport_state vport_last_state;
+ u32 roles;
+ u32 vport_id; /* Admin Identifier for the vport */
+ enum fc_port_type vport_type;
+
+ /* exported data */
+ void *dd_data; /* Used for driver-specific storage */
+
+ /* internal data */
+ struct Scsi_Host *shost; /* Physical Port Parent */
+ unsigned int channel;
+ u32 number;
+ u8 flags;
+
+ /*
+ * TODO: This is a temporary workaround, the vport structures
+ * need to be merged to remove hacks like this.
+ */
+ struct fc_fcfabric *fcfabric;
+
+ /*
+ * TODO: This is a libfc/fcoe workaround so that we can get at
+ * the lport for a N_Port in fcoe_vport_create. We really need
+ * to fix the FIP/fabric_login sequence so that the lport can
+ * be allocated with the fcvport and then we can use container_of.
+ */
+ void *priv_data;
+
+ /* Replacement for shost->host_lock, protects vport_state */
+ spinlock_t lock;
+
+ struct list_head peers;
+
+ struct work_struct vport_delete_work;
+
+} __attribute__((aligned(sizeof(unsigned long))));
+
+#define fcvport_port_id(x) \
+ (x)->port_id
+#define fcvport_symbolic_name(x) \
+ (x)->symbolic_name
+#define fcvport_node_name(x) \
+ (x)->node_name
+#define fcvport_port_name(x) \
+ (x)->port_name
+#define fcvport_port_type(x) \
+ (x)->port_type
+
+struct fc_fcpinit {
+ struct device gendev;
+
+ /* Fixed Attributes */
+ u64 permanent_port_name;
+
+ /* Dynamic Attributes */
+ enum fc_port_state port_state;
+ char system_hostname[FC_SYMBOLIC_NAME_SIZE];
+
+ /* Private (Transport-managed) Attributes */
+ enum fc_tgtid_binding_type tgtid_bind_type;
+
+ /* internal data */
+ struct list_head rports;
+ struct list_head rport_bindings;
+ u32 next_rport_number;
+ u32 next_target_id;
+
+ /* work queues for rport state manipulation */
+ char work_q_name[20];
+ struct workqueue_struct *work_q;
+ char devloss_work_q_name[20];
+ struct workqueue_struct *devloss_work_q;
+
+ /* bsg support */
+ struct request_queue *rqst_q;
+};
+
+#define shost_to_fcpinit(x) \
+ ((struct fc_fcpinit *)(x)->shost_data)
+#define fcpinit_permanent_port_name(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->permanent_port_name)
+#define fcpinit_port_state(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->port_state)
+#define fcpinit_system_hostname(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->system_hostname)
+#define fcpinit_tgtid_bind_type(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->tgtid_bind_type)
+#define fcpinit_rports(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->rports)
+#define fcpinit_rport_bindings(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->rport_bindings)
+#define fcpinit_next_rport_number(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->next_rport_number)
+#define fcpinit_next_target_id(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->next_target_id)
+#define fcpinit_work_q_name(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->work_q_name)
+#define fcpinit_work_q(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->work_q)
+#define fcpinit_devloss_work_q_name(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->devloss_work_q_name)
+#define fcpinit_devloss_work_q(x) \
+ (((struct fc_fcpinit *)(x)->shost_data)->devloss_work_q)
+
+
+/**
+ * fc_vport_set_state() - called to set a vport's state. Saves the old state,
+ * excepting the transitory states of initializing and sending the ELS
+ * traffic to instantiate the vport on the link.
+ *
+ * Assumes the driver has surrounded this with the proper locking to ensure
+ * a coherent state change.
+ *
+ * @vport: virtual port whose state is changing
+ * @new_state: new state
+ **/
+static inline void
+fc_vport_set_state(struct fc_fcvport *fcvport, enum fc_vport_state new_state)
+{
+ if ((new_state != FC_VPORT_UNKNOWN) &&
+ (new_state != FC_VPORT_INITIALIZING))
+ fcvport->vport_last_state = fcvport->vport_state;
+ fcvport->vport_state = new_state;
+}
+
+struct fc_fcfport *fc_fcfport_lookup(struct fc_fcport *fcport, const u64 name);
+struct fc_fcvport *fc_fcvport_lookup(struct fc_fcfabric *fcfabric, const u32 id);
+
+struct fc_fcport *fc_fcport_add(struct device *pdev,
+ struct fcport_function_template *,
+ int priv_size);
+struct fc_fcfport *fc_fcfport_add(struct fc_fcport *fcport, const u64 name);
+struct fc_fcfabric *fc_fcfabric_add(struct fc_fcfport *fcfport,
+ struct fcfabric_function_template *);
+struct fc_fcvport *fc_fcvport_alloc(struct fc_fcfabric *fcfabric,
+ struct fc_vport_identifiers *ids,
+ struct fcvport_function_template *fcn_tmpl,
+ int priv_size);
+struct fc_fcvport *fc_vport_create(struct fc_fcfabric *, int channel,
+ struct fc_vport_identifiers *);
+int fc_fcvport_add(struct fc_fcvport *fcvport,
+ struct fc_fcfabric *fcfabric);
+
+struct fc_fcpinit *fc_fcpinit_add(struct fc_fcvport *fcvport, int hostno);
+
+void fc_fcport_del(struct fc_fcport *fcport);
+void fc_fcfport_del(struct fc_fcfport *fcfport);
+void fc_fcfabric_del(struct fc_fcfabric *fcfabric);
+void fc_fcvport_del(struct fc_fcvport *fcvport);
+void fc_fcpinit_del(struct fc_fcpinit *fcpinit);
+
+int fc_fcvport_is_nport(struct device *dev, void *data);
+struct fc_fcvport *fc_fcfabric_find_nport(struct fc_fcfabric *fcfabric);
+
+#define FC_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+ struct device_attribute device_attr_##_prefix##_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+#define FC_CREATE_ATTRIBUTES(_var) \
+ while (count > 0) { \
+ error = device_create_file(&_var->gendev, &_var->attrs[count-1]); \
+ if (error) \
+ break; \
+ count--; \
+ }
+
+#define FC_SETUP_CONDITIONAL_ATTRIBUTE_RD(_var, field) \
+ if (_var->f->show_##_var##_##field) { \
+ _var->attrs[count] = device_attr_##_var##_##field; \
+ _var->attrs[count].attr.mode = S_IRUGO; \
+ _var->attrs[count].store = NULL; \
+ count++; \
+ }
+
+#define FC_SETUP_ALWAYS_ATTRIBUTE_RW(_var, field) \
+{ \
+ _var->attrs[count] = device_attr_##_var##_##field; \
+ count++; \
+}
+
+#define FC_SETUP_ALWAYS_ATTRIBUTE_RD_NS(_var, field) \
+ _var->attrs[count] = device_attr_##_var##_##field; \
+ _var->attrs[count].attr.mode = S_IRUGO; \
+ _var->attrs[count].store = NULL; \
+ count++
+
+#define fc_always_show_function(_obj, field, format_string, sz, cast) \
+ static ssize_t show_##_obj##_##field(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct fc_##_obj *_obj = dev_to_##_obj(dev); \
+ return snprintf(buf, sz, format_string, cast _obj##_##field(_obj)); \
+}
+
+#define fc_conditional_show_function(_obj, field, format_string, sz, cast) \
+ static ssize_t show_##_obj##_##field(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct fc_##_obj *_obj = dev_to_##_obj(dev); \
+ if (_obj->f->get_##_obj##_##field) \
+ _obj->f->get_##_obj##_##field(_obj); \
+ return snprintf(buf, sz, format_string, cast _obj##_##field(_obj)); \
+}
+
+#endif /* _FC_H_ */
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 8e86a94..88d027d 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -83,26 +83,6 @@ enum fc_port_state {
FC_PORTSTATE_DELETED,
};
-
-/*
- * fc_vport_state: If you alter this, you also need to alter
- * scsi_transport_fc.c (for the ascii descriptions).
- */
-enum fc_vport_state {
- FC_VPORT_UNKNOWN,
- FC_VPORT_ACTIVE,
- FC_VPORT_DISABLED,
- FC_VPORT_LINKDOWN,
- FC_VPORT_INITIALIZING,
- FC_VPORT_NO_FABRIC_SUPP,
- FC_VPORT_NO_FABRIC_RSCS,
- FC_VPORT_FABRIC_LOGOUT,
- FC_VPORT_FABRIC_REJ_WWN,
- FC_VPORT_FAILED,
-};
-
-
-
/*
* FC Classes of Service
* Note: values are not enumerated, as they can be "or'd" together
@@ -160,11 +140,13 @@ enum fc_tgtid_binding_type {
#define FC_RPORT_ROLE_FCP_INITIATOR FC_PORT_ROLE_FCP_INITIATOR
#define FC_RPORT_ROLE_IP_PORT FC_PORT_ROLE_IP_PORT
+/* TODO: Delete this macro, is duplicated in fcvport.c
-/* Macro for use in defining Virtual Port attributes */
+ Macro for use in defining Virtual Port attributes
#define FC_VPORT_ATTR(_name,_mode,_show,_store) \
struct device_attribute dev_attr_vport_##_name = \
__ATTR(_name,_mode,_show,_store)
+*/
/*
* fc_vport_identifiers: This set of data contains all elements
@@ -187,81 +169,12 @@ struct fc_vport_identifiers {
char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
};
-/*
- * FC Virtual Port Attributes
- *
- * This structure exists for each FC port is a virtual FC port. Virtual
- * ports share the physical link with the Physical port. Each virtual
- * ports has a unique presense on the SAN, and may be instantiated via
- * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a
- * unique presense, each vport has it's own view of the fabric,
- * authentication privilege, and priorities.
- *
- * A virtual port may support 1 or more FC4 roles. Typically it is a
- * FCP Initiator. It could be a FCP Target, or exist sole for an IP over FC
- * roles. FC port attributes for the vport will be reported on any
- * fc_host class object allocated for an FCP Initiator.
- *
- * --
- *
- * Fixed attributes are not expected to change. The driver is
- * expected to set these values after receiving the fc_vport structure
- * via the vport_create() call from the transport.
- * The transport fully manages all get functions w/o driver interaction.
- *
- * Dynamic attributes are expected to change. The driver participates
- * in all get/set operations via functions provided by the driver.
- *
- * Private attributes are transport-managed values. They are fully
- * managed by the transport w/o driver interaction.
- */
-
-struct fc_vport {
- /* Fixed Attributes */
-
- /* Dynamic Attributes */
-
- /* Private (Transport-managed) Attributes */
- enum fc_vport_state vport_state;
- enum fc_vport_state vport_last_state;
- u64 node_name;
- u64 port_name;
- u32 roles;
- u32 vport_id; /* Admin Identifier for the vport */
- enum fc_port_type vport_type;
- char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
-
- /* exported data */
- void *dd_data; /* Used for driver-specific storage */
-
- /* internal data */
- struct Scsi_Host *shost; /* Physical Port Parent */
- unsigned int channel;
- u32 number;
- u8 flags;
- struct list_head peers;
- struct device dev;
- struct work_struct vport_delete_work;
-} __attribute__((aligned(sizeof(unsigned long))));
-
/* bit field values for struct fc_vport "flags" field: */
#define FC_VPORT_CREATING 0x01
#define FC_VPORT_DELETING 0x02
#define FC_VPORT_DELETED 0x04
#define FC_VPORT_DEL 0x06 /* Any DELETE state */
-#define dev_to_vport(d) \
- container_of(d, struct fc_vport, dev)
-#define transport_class_to_vport(dev) \
- dev_to_vport(dev->parent)
-#define vport_to_shost(v) \
- (v->shost)
-#define vport_to_shost_channel(v) \
- (v->channel)
-#define vport_to_parent(v) \
- (v->dev.parent)
-
-
/* Error return codes for vport_create() callback */
#define VPCERR_UNSUPPORTED -ENOSYS /* no driver/adapter
support */
@@ -402,7 +315,7 @@ struct fc_starget_attrs { /* aka fc_target_attrs */
*/
/* FC Statistics - Following FC HBAAPI v2.0 guidelines */
-struct fc_host_statistics {
+struct fcpinit_statistics {
/* port statistics */
u64 seconds_since_last_reset;
u64 tx_frames;
@@ -434,10 +347,10 @@ struct fc_host_statistics {
*/
/*
- * fc_host_event_code: If you alter this, you also need to alter
+ * fcpinit_event_code: If you alter this, you also need to alter
* scsi_transport_fc.c (for the ascii descriptions).
*/
-enum fc_host_event_code {
+enum fcpinit_event_code {
FCH_EVT_LIP = 0x1,
FCH_EVT_LINKUP = 0x2,
FCH_EVT_LINKDOWN = 0x3,
@@ -473,114 +386,6 @@ enum fc_host_event_code {
#define FC_FC4_LIST_SIZE 32
#define FC_SYMBOLIC_NAME_SIZE 256
#define FC_VERSION_STRING_SIZE 64
-#define FC_SERIAL_NUMBER_SIZE 80
-
-struct fc_host_attrs {
- /* Fixed Attributes */
- u64 node_name;
- u64 port_name;
- u64 permanent_port_name;
- u32 supported_classes;
- u8 supported_fc4s[FC_FC4_LIST_SIZE];
- u32 supported_speeds;
- u32 maxframe_size;
- u16 max_npiv_vports;
- char serial_number[FC_SERIAL_NUMBER_SIZE];
-
- /* Dynamic Attributes */
- u32 port_id;
- enum fc_port_type port_type;
- enum fc_port_state port_state;
- u8 active_fc4s[FC_FC4_LIST_SIZE];
- u32 speed;
- u64 fabric_name;
- char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
- char system_hostname[FC_SYMBOLIC_NAME_SIZE];
-
- /* Private (Transport-managed) Attributes */
- enum fc_tgtid_binding_type tgtid_bind_type;
-
- /* internal data */
- struct list_head rports;
- struct list_head rport_bindings;
- struct list_head vports;
- u32 next_rport_number;
- u32 next_target_id;
- u32 next_vport_number;
- u16 npiv_vports_inuse;
-
- /* work queues for rport state manipulation */
- char work_q_name[20];
- struct workqueue_struct *work_q;
- char devloss_work_q_name[20];
- struct workqueue_struct *devloss_work_q;
-
- /* bsg support */
- struct request_queue *rqst_q;
-};
-
-#define shost_to_fc_host(x) \
- ((struct fc_host_attrs *)(x)->shost_data)
-
-#define fc_host_node_name(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->node_name)
-#define fc_host_port_name(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->port_name)
-#define fc_host_permanent_port_name(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->permanent_port_name)
-#define fc_host_supported_classes(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->supported_classes)
-#define fc_host_supported_fc4s(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->supported_fc4s)
-#define fc_host_supported_speeds(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
-#define fc_host_maxframe_size(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
-#define fc_host_max_npiv_vports(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->max_npiv_vports)
-#define fc_host_serial_number(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->serial_number)
-#define fc_host_port_id(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->port_id)
-#define fc_host_port_type(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->port_type)
-#define fc_host_port_state(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->port_state)
-#define fc_host_active_fc4s(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->active_fc4s)
-#define fc_host_speed(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->speed)
-#define fc_host_fabric_name(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->fabric_name)
-#define fc_host_symbolic_name(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->symbolic_name)
-#define fc_host_system_hostname(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->system_hostname)
-#define fc_host_tgtid_bind_type(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->tgtid_bind_type)
-#define fc_host_rports(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->rports)
-#define fc_host_rport_bindings(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->rport_bindings)
-#define fc_host_vports(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->vports)
-#define fc_host_next_rport_number(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
-#define fc_host_next_target_id(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
-#define fc_host_next_vport_number(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->next_vport_number)
-#define fc_host_npiv_vports_inuse(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->npiv_vports_inuse)
-#define fc_host_work_q_name(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
-#define fc_host_work_q(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->work_q)
-#define fc_host_devloss_work_q_name(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
-#define fc_host_devloss_work_q(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
-
struct fc_bsg_buffer {
unsigned int payload_len;
@@ -632,28 +437,17 @@ struct fc_function_template {
void (*get_starget_port_name)(struct scsi_target *);
void (*get_starget_port_id)(struct scsi_target *);
- void (*get_host_port_id)(struct Scsi_Host *);
- void (*get_host_port_type)(struct Scsi_Host *);
void (*get_host_port_state)(struct Scsi_Host *);
- void (*get_host_active_fc4s)(struct Scsi_Host *);
- void (*get_host_speed)(struct Scsi_Host *);
- void (*get_host_fabric_name)(struct Scsi_Host *);
- void (*get_host_symbolic_name)(struct Scsi_Host *);
void (*set_host_system_hostname)(struct Scsi_Host *);
- struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
- void (*reset_fc_host_stats)(struct Scsi_Host *);
+ struct fcpinit_statistics * (*get_fcpinit_stats)(struct Scsi_Host *);
+ void (*reset_fcpinit_stats)(struct Scsi_Host *);
- int (*issue_fc_host_lip)(struct Scsi_Host *);
+ int (*issue_fcpinit_lip)(struct Scsi_Host *);
void (*dev_loss_tmo_callbk)(struct fc_rport *);
void (*terminate_rport_io)(struct fc_rport *);
- void (*set_vport_symbolic_name)(struct fc_vport *);
- int (*vport_create)(struct fc_vport *, bool);
- int (*vport_disable)(struct fc_vport *, bool);
- int (*vport_delete)(struct fc_vport *);
-
/* target-mode drivers' functions */
int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
int (* it_nexus_response)(struct Scsi_Host *, u64, int);
@@ -664,7 +458,6 @@ struct fc_function_template {
/* allocation lengths for host-specific data */
u32 dd_fcrport_size;
- u32 dd_fcvport_size;
u32 dd_bsg_size;
/*
@@ -689,22 +482,10 @@ struct fc_function_template {
unsigned long show_starget_port_id:1;
/* host fixed attributes */
- unsigned long show_host_node_name:1;
- unsigned long show_host_port_name:1;
unsigned long show_host_permanent_port_name:1;
- unsigned long show_host_supported_classes:1;
- unsigned long show_host_supported_fc4s:1;
- unsigned long show_host_supported_speeds:1;
- unsigned long show_host_maxframe_size:1;
- unsigned long show_host_serial_number:1;
+
/* host dynamic attributes */
- unsigned long show_host_port_id:1;
- unsigned long show_host_port_type:1;
unsigned long show_host_port_state:1;
- unsigned long show_host_active_fc4s:1;
- unsigned long show_host_speed:1;
- unsigned long show_host_fabric_name:1;
- unsigned long show_host_symbolic_name:1;
unsigned long show_host_system_hostname:1;
unsigned long disable_target_scan:1;
@@ -766,26 +547,6 @@ static inline void u64_to_wwn(u64 inm, u8 *wwn)
wwn[7] = inm & 0xff;
}
-/**
- * fc_vport_set_state() - called to set a vport's state. Saves the old state,
- * excepting the transitory states of initializing and sending the ELS
- * traffic to instantiate the vport on the link.
- *
- * Assumes the driver has surrounded this with the proper locking to ensure
- * a coherent state change.
- *
- * @vport: virtual port whose state is changing
- * @new_state: new state
- **/
-static inline void
-fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state)
-{
- if ((new_state != FC_VPORT_UNKNOWN) &&
- (new_state != FC_VPORT_INITIALIZING))
- vport->vport_last_state = vport->vport_state;
- vport->vport_state = new_state;
-}
-
struct scsi_transport_template *fc_attach_transport(
struct fc_function_template *);
void fc_release_transport(struct scsi_transport_template *);
@@ -796,17 +557,71 @@ void fc_remote_port_delete(struct fc_rport *rport);
void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles);
int scsi_is_fc_rport(const struct device *);
u32 fc_get_event_number(void);
-void fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
- enum fc_host_event_code event_code, u32 event_data);
-void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
- u32 data_len, char * data_buf, u64 vendor_id);
- /* Note: when specifying vendor_id to fc_host_post_vendor_event()
+void fcpinit_post_event(struct Scsi_Host *shost, u32 event_number,
+ enum fcpinit_event_code event_code, u32 event_data);
+void fcpinit_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
+ u32 data_len, char * data_buf, u64 vendor_id);
+ /* Note: when specifying vendor_id to fcpinit_post_vendor_event()
* be sure to read the Vendor Type and ID formatting requirements
* specified in scsi_netlink.h
*/
-struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel,
- struct fc_vport_identifiers *);
-int fc_vport_terminate(struct fc_vport *vport);
void fc_block_scsi_eh(struct scsi_cmnd *cmnd);
+/* RWL - Temporarily add this to the common header */
+
+#define fc_enum_name_search(title, table_type, table) \
+ const char *get_fc_##title##_name(enum table_type table_key) \
+{ \
+ int i; \
+ char *name = NULL; \
+ \
+ for (i = 0; i < ARRAY_SIZE(table); i++) { \
+ if (table[i].value == table_key) { \
+ name = table[i].name; \
+ break; \
+ } \
+ } \
+ return name; \
+}
+
+#define fc_bitfield_name_search(title, table) \
+ssize_t get_fc_##title##_names(u32 table_key, char *buf) \
+{ \
+ char *prefix = ""; \
+ ssize_t len = 0; \
+ int i; \
+ \
+ for (i = 0; i < ARRAY_SIZE(table); i++) { \
+ if (table[i].value & table_key) { \
+ len += sprintf(buf + len, "%s%s", \
+ prefix, table[i].name); \
+ prefix = ", "; \
+ } \
+ } \
+ len += sprintf(buf + len, "\n"); \
+ return len; \
+}
+
+struct _fc_port_types {
+ enum fc_port_type value;
+ char *name;
+};
+
+struct _fc_port_role_names {
+ u32 value;
+ char *name;
+};
+
+struct _fc_cos_names {
+ u32 value;
+ char *name;
+};
+
+#define FC_PORTTYPE_MAX_NAMELEN 50
+
+const char *get_fc_port_type_name(enum fc_port_type table_key);
+const char *get_fc_vport_type_name(enum fc_port_type table_key);
+ssize_t get_fc_port_roles_names(u32 table_key, char *buf);
+ssize_t get_fc_cos_names(u32 table_key, char *buf);
+
#endif /* SCSI_TRANSPORT_FC_H */
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH 6/6] libfc, libfcoe, fcoe: Make use of FC sysfs
2010-01-27 23:24 [RFC PATCH 0/6] Work In Progress: FC sysfs Robert Love
` (4 preceding siblings ...)
2010-01-27 23:24 ` [RFC PATCH 5/6] fc_sysfs: Rearrange the FC transport to create FC sysfs Robert Love
@ 2010-01-27 23:24 ` Robert Love
2010-01-28 16:01 ` [RFC PATCH 0/6] Work In Progress: " Hannes Reinecke
6 siblings, 0 replies; 10+ messages in thread
From: Robert Love @ 2010-01-27 23:24 UTC (permalink / raw)
To: linux-scsi, james.smart; +Cc: giridhar.malavali
Previously the lport was allocated with the scsi_host,
but with FC sysfs the scsi_host is not allocated until
the lport is READY. This patch changes libfc such that
the lport is allocated with the fcport and not with the
scsi_host. FCP information is still allocated with the
scsi_host.
libfc, libfcoe and fcoe also needed to create the
various FC sysfs object as information was discovered
durring login.
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 522 ++++++++++++++++++++++++++---------------
drivers/scsi/fcoe/libfcoe.c | 43 ++-
drivers/scsi/libfc/fc_disc.c | 4
drivers/scsi/libfc/fc_exch.c | 2
drivers/scsi/libfc/fc_fcp.c | 130 ++++++----
drivers/scsi/libfc/fc_libfc.h | 28 +-
drivers/scsi/libfc/fc_lport.c | 189 ++++++++-------
drivers/scsi/libfc/fc_npiv.c | 52 ++--
drivers/scsi/libfc/fc_rport.c | 12 +
include/scsi/fc.h | 3
include/scsi/fc_encode.h | 30 +-
include/scsi/libfc.h | 127 +++++++---
12 files changed, 697 insertions(+), 445 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index a719994..7734638 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -40,6 +40,7 @@
#include <scsi/fc/fc_fip.h>
#include <scsi/libfc.h>
+#include <scsi/fc.h>
#include <scsi/fc_frame.h>
#include <scsi/libfcoe.h>
@@ -116,6 +117,15 @@ static void fcoe_recv_frame(struct sk_buff *skb);
static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
+static void fcoe_shost_config(struct fc_lport *lport, struct fc_fcp_internal *si);
+static void fcoe_set_symbolic_name(struct fc_lport *);
+static void fcoe_set_node_name(struct fc_lport *);
+static void fcoe_set_port_name(struct fc_lport *);
+static void fcoe_set_max_npiv_vports(struct fc_lport *);
+static void fcoe_get_vport_ids(struct fc_lport *lport,
+ struct fc_vport_identifiers *ids);
+
+
module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
__MODULE_PARM_TYPE(create, "string");
MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
@@ -142,10 +152,29 @@ static struct notifier_block fcoe_cpu_notifier = {
static struct scsi_transport_template *fcoe_transport_template;
static struct scsi_transport_template *fcoe_vport_transport_template;
-static int fcoe_vport_destroy(struct fc_vport *);
-static int fcoe_vport_create(struct fc_vport *, bool disabled);
-static int fcoe_vport_disable(struct fc_vport *, bool disable);
-static void fcoe_set_vport_symbolic_name(struct fc_vport *);
+static int fcoe_vport_destroy(void *, struct fc_fcvport *);
+static int fcoe_vport_create(void *, struct fc_fcvport *, bool disabled);
+static int fcoe_vport_disable(struct fc_fcvport *, bool disable);
+static void fcoe_set_vport_symbolic_name(struct fc_fcvport *);
+
+static struct scsi_host_template fcoe_shost_template = {
+ .module = THIS_MODULE,
+ .name = "FCoE Driver",
+ .proc_name = FCOE_NAME,
+ .queuecommand = fc_queuecommand,
+ .eh_abort_handler = fc_eh_abort,
+ .eh_device_reset_handler = fc_eh_device_reset,
+ .eh_host_reset_handler = fc_eh_host_reset,
+ .slave_alloc = fc_slave_alloc,
+ .change_queue_depth = fc_change_queue_depth,
+ .change_queue_type = fc_change_queue_type,
+ .this_id = -1,
+ .cmd_per_lun = 3,
+ .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
+ .use_clustering = ENABLE_CLUSTERING,
+ .sg_tablesize = SG_ALL,
+ .max_sectors = 0xffff,
+};
static struct libfc_function_template fcoe_libfc_fcn_templ = {
.frame_send = fcoe_xmit,
@@ -153,102 +182,169 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
.ddp_done = fcoe_ddp_done,
.elsct_send = fcoe_elsct_send,
.get_lesb = fcoe_get_lesb,
+ .shost_template = &fcoe_shost_template,
+ .shost_config = fcoe_shost_config,
+ .set_fcvport_symbolic_name = fcoe_set_symbolic_name,
+ .set_fcvport_node_name = fcoe_set_node_name,
+ .set_fcvport_port_name = fcoe_set_port_name,
+ .set_fcfabric_max_npiv_vports = fcoe_set_max_npiv_vports,
+ .get_vport_ids = fcoe_get_vport_ids,
};
struct fc_function_template fcoe_transport_function = {
- .show_host_node_name = 1,
- .show_host_port_name = 1,
- .show_host_supported_classes = 1,
- .show_host_supported_fc4s = 1,
- .show_host_active_fc4s = 1,
- .show_host_maxframe_size = 1,
-
- .show_host_port_id = 1,
- .show_host_supported_speeds = 1,
- .get_host_speed = fc_get_host_speed,
- .show_host_speed = 1,
- .show_host_port_type = 1,
.get_host_port_state = fc_get_host_port_state,
.show_host_port_state = 1,
- .show_host_symbolic_name = 1,
.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
- .show_host_fabric_name = 1,
.show_starget_node_name = 1,
.show_starget_port_name = 1,
.show_starget_port_id = 1,
.set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
- .get_fc_host_stats = fc_get_host_stats,
- .issue_fc_host_lip = fcoe_reset,
+ .get_fcpinit_stats = fc_get_host_stats,
+ .issue_fcpinit_lip = fcoe_reset,
.terminate_rport_io = fc_rport_terminate_io,
- .vport_create = fcoe_vport_create,
- .vport_delete = fcoe_vport_destroy,
- .vport_disable = fcoe_vport_disable,
- .set_vport_symbolic_name = fcoe_set_vport_symbolic_name,
-
.bsg_request = fc_lport_bsg_request,
};
struct fc_function_template fcoe_vport_transport_function = {
- .show_host_node_name = 1,
- .show_host_port_name = 1,
- .show_host_supported_classes = 1,
- .show_host_supported_fc4s = 1,
- .show_host_active_fc4s = 1,
- .show_host_maxframe_size = 1,
-
- .show_host_port_id = 1,
- .show_host_supported_speeds = 1,
- .get_host_speed = fc_get_host_speed,
- .show_host_speed = 1,
- .show_host_port_type = 1,
.get_host_port_state = fc_get_host_port_state,
.show_host_port_state = 1,
- .show_host_symbolic_name = 1,
.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
- .show_host_fabric_name = 1,
.show_starget_node_name = 1,
.show_starget_port_name = 1,
.show_starget_port_id = 1,
.set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
- .get_fc_host_stats = fc_get_host_stats,
- .issue_fc_host_lip = fcoe_reset,
+ .get_fcpinit_stats = fc_get_host_stats,
+ .issue_fcpinit_lip = fcoe_reset,
.terminate_rport_io = fc_rport_terminate_io,
.bsg_request = fc_lport_bsg_request,
};
-static struct scsi_host_template fcoe_shost_template = {
- .module = THIS_MODULE,
- .name = "FCoE Driver",
- .proc_name = FCOE_NAME,
- .queuecommand = fc_queuecommand,
- .eh_abort_handler = fc_eh_abort,
- .eh_device_reset_handler = fc_eh_device_reset,
- .eh_host_reset_handler = fc_eh_host_reset,
- .slave_alloc = fc_slave_alloc,
- .change_queue_depth = fc_change_queue_depth,
- .change_queue_type = fc_change_queue_type,
- .this_id = -1,
- .cmd_per_lun = 3,
- .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
- .use_clustering = ENABLE_CLUSTERING,
- .sg_tablesize = SG_ALL,
- .max_sectors = 0xffff,
+struct fcport_function_template fcoe_fcport_fcn_tmpl = {
+ .show_fcport_maxframe_size = 1,
+ .show_fcport_supported_speeds = 1,
+ .show_fcport_supported_classes = 1,
+ .show_fcport_speed = 1,
+ .show_fcport_supported_fc4s = 1,
+ .show_fcport_active_fc4s = 1,
+ .show_fcport_serial_number = 1,
};
+struct fcfabric_function_template fcoe_fcfabric_fcn_tmpl = {
+ .vport_create = fcoe_vport_create,
+ .vport_delete = fcoe_vport_destroy,
+ .vport_disable = fcoe_vport_disable,
+
+ .show_fcfabric_fabric_name = 1,
+};
+
+struct fcvport_function_template fcoe_fcvport_fcn_tmpl = {
+ .show_fcvport_port_id = 1,
+ .show_fcvport_symbolic_name = 1,
+ .show_fcvport_node_name = 1,
+ .show_fcvport_port_name = 1,
+ .show_fcvport_port_type = 1,
+};
+
+static void fcoe_get_vport_ids(struct fc_lport *lport,
+ struct fc_vport_identifiers *ids)
+{
+ struct fcoe_port *port = lport_priv(lport);
+ struct fcoe_interface *fcoe = port->fcoe;
+ int vid = 0;
+
+ if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN)
+ vid = vlan_dev_vlan_id(fcoe->netdev);
+
+ ids->node_name = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
+ ids->port_name = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 2, vid);
+
+ /*
+ * TODO: This needs to be determined, not hard coded.
+ */
+ ids->roles = FC_PORT_ROLE_FCP_INITIATOR;
+
+ /*
+ * TODO: I don't know where these values should come from,
+ * guess that disable should be 0 and NPIV.
+ */
+ ids->disable = 0;
+ ids->vport_type = FC_PORTTYPE_NPIV;
+
+ snprintf(ids->symbolic_name, FC_SYMBOLIC_NAME_SIZE,
+ "%s v%s over %s", FCOE_NAME, FCOE_VERSION,
+ fcoe_netdev(lport)->name);
+}
+
+static void fcoe_set_max_npiv_vports(struct fc_lport *lport)
+{
+ fcfabric_max_npiv_vports(lport->fcfabric) = USHORT_MAX;
+}
+
+static void fcoe_set_symbolic_name(struct fc_lport *lport)
+{
+ snprintf(lport->fcvport->symbolic_name, FC_SYMBOLIC_NAME_SIZE,
+ "%s v%s over %s", FCOE_NAME, FCOE_VERSION,
+ fcoe_netdev(lport)->name);
+}
+
+static void fcoe_set_node_name(struct fc_lport *lport)
+{
+ struct fcoe_port *port = lport_priv(lport);
+ struct fcoe_interface *fcoe = port->fcoe;
+ int vid = 0;
+
+ /*
+ RWL - removed a if(!lport->vport) check, since this routine shoud
+ be used for all vports (real or virtual) I think it should be OK
+ */
+
+ /*
+ * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN:
+ * For WWNN, we use NAA 1 w/ bit 27-16 of word 0 as 0.
+ * For WWPN, we use NAA 2 w/ bit 27-16 of word 0 from VLAN ID
+ */
+ if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN)
+ vid = vlan_dev_vlan_id(fcoe->netdev);
+ fcvport_node_name(lport->fcvport) =
+ fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
+}
+
+static void fcoe_set_port_name(struct fc_lport *lport)
+{
+ struct fcoe_port *port = lport_priv(lport);
+ struct fcoe_interface *fcoe = port->fcoe;
+ int vid = 0;
+
+ /*
+ RWL - removed a if(!lport->vport) check, since this routine shoud
+ be used for all vports (real or virtual) I think it should be OK
+ */
+
+ /*
+ * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN:
+ * For WWNN, we use NAA 1 w/ bit 27-16 of word 0 as 0.
+ * For WWPN, we use NAA 2 w/ bit 27-16 of word 0 from VLAN ID
+ */
+ if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN)
+ vid = vlan_dev_vlan_id(fcoe->netdev);
+ fcvport_port_name(lport->fcvport) =
+ fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 2, vid);
+}
+
/**
* fcoe_interface_setup() - Setup a FCoE interface
* @fcoe: The new FCoE interface
@@ -517,8 +613,10 @@ static u8 *fcoe_get_src_mac(struct fc_lport *lport)
*/
static int fcoe_lport_config(struct fc_lport *lport)
{
+ lport->fcfabric_f = &fcoe_fcfabric_fcn_tmpl;
+ lport->fcvport_f = &fcoe_fcvport_fcn_tmpl;
+
lport->link_up = 0;
- lport->qfull = 0;
lport->max_retry_count = 3;
lport->max_rport_retry_count = 3;
lport->e_d_tov = 2 * 1000; /* FC-FS default */
@@ -582,10 +680,8 @@ static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
{
u32 mfs;
- u64 wwnn, wwpn;
struct fcoe_interface *fcoe;
struct fcoe_port *port;
- int vid = 0;
/* Setup lport private data to point to fcoe softc */
port = lport_priv(lport);
@@ -629,25 +725,12 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
port->fcoe_pending_queue_active = 0;
setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport);
- fcoe_link_speed_update(lport);
-
- if (!lport->vport) {
- /*
- * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN:
- * For WWNN, we use NAA 1 w/ bit 27-16 of word 0 as 0.
- * For WWPN, we use NAA 2 w/ bit 27-16 of word 0 from VLAN ID
- */
- if (netdev->priv_flags & IFF_802_1Q_VLAN)
- vid = vlan_dev_vlan_id(netdev);
-
- if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
- wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
- fc_set_wwnn(lport, wwnn);
- if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN))
- wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr,
- 2, vid);
- fc_set_wwpn(lport, wwpn);
- }
+ /*
+ * TODO: This is a bad to have a special case for the N_Port
+ * lport.
+ */
+ if (lport->fcport)
+ fcoe_link_speed_update(lport);
return 0;
}
@@ -656,42 +739,25 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
* fcoe_shost_config() - Set up the SCSI host associated with a local port
* @lport: The local port
* @shost: The SCSI host to associate with the local port
- * @dev: The device associated with the SCSI host
*
* Must be called after fcoe_lport_config() and fcoe_netdev_config()
*
* Returns: 0 for success
*/
-static int fcoe_shost_config(struct fc_lport *lport, struct Scsi_Host *shost,
- struct device *dev)
+static void fcoe_shost_config(struct fc_lport *lport, struct fc_fcp_internal *si)
{
- int rc = 0;
-
/* lport scsi host config */
- lport->host->max_lun = FCOE_MAX_LUN;
- lport->host->max_id = FCOE_MAX_FCP_TARGET;
- lport->host->max_channel = 0;
- if (lport->vport)
- lport->host->transportt = fcoe_vport_transport_template;
- else
- lport->host->transportt = fcoe_transport_template;
+ si->host->max_lun = FCOE_MAX_LUN;
+ si->host->max_id = FCOE_MAX_FCP_TARGET;
+ si->host->max_channel = 0;
- /* add the new host to the SCSI-ml */
- rc = scsi_add_host(lport->host, dev);
- if (rc) {
- FCOE_NETDEV_DBG(fcoe_netdev(lport), "fcoe_shost_config: "
- "error on scsi_add_host\n");
- return rc;
- }
+ /* RWL - Should this directly change the scsi_host? what is this val used for */
+ si->qfull = 0;
- if (!lport->vport)
- fc_host_max_npiv_vports(lport->host) = USHORT_MAX;
-
- snprintf(fc_host_symbolic_name(lport->host), FC_SYMBOLIC_NAME_SIZE,
- "%s v%s over %s", FCOE_NAME, FCOE_VERSION,
- fcoe_netdev(lport)->name);
-
- return 0;
+ if (!fc_fcvport_is_nport(&lport->fcvport->gendev, NULL))
+ si->host->transportt = fcoe_vport_transport_template;
+ else
+ si->host->transportt = fcoe_transport_template;
}
/**
@@ -812,8 +878,15 @@ static void fcoe_if_destroy(struct fc_lport *lport)
/* Cleanup the fc_lport */
fc_lport_destroy(lport);
+
+ /*
+ * TODO: It cannot be assumed that FCP was initiatlized.
+ */
fc_fcp_destroy(lport);
+ if (!lport->fcpinit)
+ printk(KERN_ERR "RWL: fcoe_if_destroy - NO fcpinit\n");
+
/* Stop the transmit retry timer */
del_timer_sync(&port->timer);
@@ -831,18 +904,17 @@ static void fcoe_if_destroy(struct fc_lport *lport)
/* Free queued packets for the per-CPU receive threads */
fcoe_percpu_clean(lport);
- /* Detach from the scsi-ml */
- fc_remove_host(lport->host);
- scsi_remove_host(lport->host);
-
/* There are no more rports or I/O, free the EM */
fc_exch_mgr_free(lport);
/* Free memory used by statistical counters */
fc_lport_free_stats(lport);
- /* Release the Scsi_Host */
- scsi_host_put(lport->host);
+ /*
+ * TODO: Where does the fcport get freed?
+ */
+
+ fc_lport_free(lport);
}
/**
@@ -883,6 +955,25 @@ static int fcoe_ddp_done(struct fc_lport *lport, u16 xid)
return 0;
}
+static struct fc_lport *fcoe_lport_create(struct fcoe_interface *fcoe)
+{
+ struct fc_lport *lport;
+ struct fcoe_port *port;
+
+ lport = fc_lport_alloc(sizeof(struct fcoe_port));
+ if (!lport)
+ return NULL;
+
+ port = lport_priv(lport);
+
+ port->lport = lport;
+ port->fcoe = fcoe;
+ INIT_WORK(&port->destroy_work, fcoe_destroy_work);
+
+ return lport;
+}
+
+
/**
* fcoe_if_create() - Create a FCoE instance on an interface
* @fcoe: The FCoE interface to create a local port on
@@ -893,53 +984,24 @@ static int fcoe_ddp_done(struct fc_lport *lport, u16 xid)
*
* Returns: The allocated fc_lport or an error pointer
*/
-static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
- struct device *parent, int npiv)
+static int fcoe_if_create(struct fc_lport *lport, struct fcoe_interface *fcoe,
+ struct device *parent, int npiv)
{
struct net_device *netdev = fcoe->netdev;
- struct fc_lport *lport = NULL;
- struct fcoe_port *port;
- struct Scsi_Host *shost;
- int rc;
+ int rc = 0;
/*
* parent is only a vport if npiv is 1,
* but we'll only use vport in that case so go ahead and set it
*/
- struct fc_vport *vport = dev_to_vport(parent);
FCOE_NETDEV_DBG(netdev, "Create Interface\n");
- if (!npiv) {
- lport = libfc_host_alloc(&fcoe_shost_template,
- sizeof(struct fcoe_port));
- } else {
- lport = libfc_vport_create(vport,
- sizeof(struct fcoe_port));
- }
- if (!lport) {
- FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
- rc = -ENOMEM;
- goto out;
- }
- shost = lport->host;
- port = lport_priv(lport);
- port->lport = lport;
- port->fcoe = fcoe;
- INIT_WORK(&port->destroy_work, fcoe_destroy_work);
-
/* configure a fc_lport including the exchange manager */
rc = fcoe_lport_config(lport);
if (rc) {
FCOE_NETDEV_DBG(netdev, "Could not configure lport for the "
"interface\n");
- goto out_host_put;
- }
-
- if (npiv) {
- FCOE_NETDEV_DBG(netdev, "Setting vport names, 0x%llX 0x%llX\n",
- vport->node_name, vport->port_name);
- fc_set_wwnn(lport, vport->node_name);
- fc_set_wwpn(lport, vport->port_name);
+ goto out;
}
/* configure lport network properties */
@@ -950,14 +1012,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
goto out_lp_destroy;
}
- /* configure lport scsi host properties */
- rc = fcoe_shost_config(lport, shost, parent);
- if (rc) {
- FCOE_NETDEV_DBG(netdev, "Could not configure shost for the "
- "interface\n");
- goto out_lp_destroy;
- }
-
/* Initialize the library */
rc = fcoe_libfc_config(lport, &fcoe_libfc_fcn_templ);
if (rc) {
@@ -987,14 +1041,13 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
}
fcoe_interface_get(fcoe);
- return lport;
+
+ return rc;
out_lp_destroy:
fc_exch_mgr_free(lport);
-out_host_put:
- scsi_host_put(lport->host);
out:
- return ERR_PTR(rc);
+ return rc;
}
/**
@@ -1717,6 +1770,7 @@ int fcoe_percpu_receive_thread(void *arg)
static void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
{
struct fcoe_port *port = lport_priv(lport);
+ struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
int rc;
spin_lock_bh(&port->fcoe_pending_queue.lock);
@@ -1748,13 +1802,13 @@ static void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
}
if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
- lport->qfull = 0;
+ si->qfull = 0;
if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
mod_timer(&port->timer, jiffies + 2);
port->fcoe_pending_queue_active = 0;
out:
if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
- lport->qfull = 1;
+ si->qfull = 1;
spin_unlock_bh(&port->fcoe_pending_queue.lock);
return;
}
@@ -1838,7 +1892,13 @@ static int fcoe_device_notification(struct notifier_block *notifier,
"from netdev netlink\n", event);
}
- fcoe_link_speed_update(lport);
+ /*
+ * TODO: This is bad to have a special case for
+ * the N_Port since it's the only vport/lport with
+ * a fcport.
+ */
+ if (lport->fcport)
+ fcoe_link_speed_update(lport);
if (link_possible && !fcoe_link_ok(lport))
fcoe_ctlr_link_up(&fcoe->ctlr);
@@ -2015,6 +2075,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
fcoe_interface_cleanup(fcoe);
rtnl_unlock();
fcoe_if_destroy(fcoe->ctlr.lp);
+
out_putdev:
dev_put(netdev);
out_nodev:
@@ -2047,7 +2108,12 @@ static void fcoe_destroy_work(struct work_struct *work)
*/
static int fcoe_create(const char *buffer, struct kernel_param *kp)
{
- int rc;
+ /*
+ * TODO: rc and error can probably be consolidated.
+ */
+ int rc = 0;
+ int error = 0;
+ struct fc_vport_identifiers ids;
struct fcoe_interface *fcoe;
struct fc_lport *lport;
struct net_device *netdev;
@@ -2084,8 +2150,31 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
goto out_putdev;
}
- lport = fcoe_if_create(fcoe, &netdev->dev, 0);
- if (IS_ERR(lport)) {
+ /*
+ * TODO: Check error conditions here and from the return of fc_fcport_add
+ */
+ lport = fcoe_lport_create(fcoe);
+ if (!lport) {
+ FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
+ rc = -ENOMEM;
+ /*
+ * TODO: This is probably very incorrect.
+ */
+ goto out;
+ }
+
+ lport->fcport = fc_fcport_add((struct device *)&netdev->dev.parent, &fcoe_fcport_fcn_tmpl);
+ if (!lport->fcport) {
+ printk(KERN_ERR "Failed to add a fcport\n");
+ goto out_free;
+ }
+
+ fc_lport_port_config(lport->fcport);
+
+ lport->fcport->maxframe_size = lport->mfs;
+
+ error = fcoe_if_create(lport, fcoe, &netdev->dev, 0);
+ if (error) {
printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
netdev->name);
rc = -EIO;
@@ -2096,6 +2185,24 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
/* Make this the "master" N_Port */
fcoe->ctlr.lp = lport;
+ /* replace individual set_*() routines below with a
+ * get_vport_identifiers routine, or don't require ids
+ * in fcvport_alloc().
+ */
+ fcoe_get_vport_ids(lport, &ids);
+ lport->fcvport = fc_fcvport_alloc(NULL, &ids, lport->fcvport_f, 0);
+ lport->fcvport->priv_data = lport;
+ fcvport_port_type(lport->fcvport) = FC_PORTTYPE_NPORT;
+
+ if (!lport->fcvport) {
+ /*
+ * RWL - TODO: remove the fcfabric. I don't think that it will
+ * come to that though. I think the fabric_add will move instead.
+ * Let's not worry about it now.
+ */
+ return rc;
+ }
+
/* add to lports list */
fcoe_hostlist_add(lport);
@@ -2117,6 +2224,7 @@ out_putdev:
out_nodev:
rtnl_unlock();
mutex_unlock(&fcoe_config_mutex);
+out:
return rc;
}
@@ -2134,19 +2242,21 @@ int fcoe_link_speed_update(struct fc_lport *lport)
struct net_device *netdev = port->fcoe->netdev;
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+ u32 link_supported_speeds = FC_PORTSPEED_UNKNOWN;
+
if (!dev_ethtool_get_settings(netdev, &ecmd)) {
- lport->link_supported_speeds &=
- ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full))
- lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
+ link_supported_speeds |= FC_PORTSPEED_1GBIT;
if (ecmd.supported & SUPPORTED_10000baseT_Full)
- lport->link_supported_speeds |=
- FC_PORTSPEED_10GBIT;
+ link_supported_speeds |= FC_PORTSPEED_10GBIT;
+
+ fcport_supported_speeds(lport->fcport) = link_supported_speeds;
+
if (ecmd.speed == SPEED_1000)
- lport->link_speed = FC_PORTSPEED_1GBIT;
+ fcport_speed(lport->fcport) = FC_PORTSPEED_1GBIT;
if (ecmd.speed == SPEED_10000)
- lport->link_speed = FC_PORTSPEED_10GBIT;
+ fcport_speed(lport->fcport) = FC_PORTSPEED_10GBIT;
return 0;
}
@@ -2252,7 +2362,8 @@ void fcoe_clean_pending_queue(struct fc_lport *lport)
*/
int fcoe_reset(struct Scsi_Host *shost)
{
- struct fc_lport *lport = shost_priv(shost);
+ struct fc_fcp_internal *si = shost_priv(shost);
+ struct fc_lport *lport = si->lport;
fc_lport_reset(lport);
return 0;
}
@@ -2501,24 +2612,53 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did,
*
* Returns: 0 for success
*/
-static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
+static int fcoe_vport_create(void *data, struct fc_fcvport *vport, bool disabled)
{
- struct Scsi_Host *shost = vport_to_shost(vport);
- struct fc_lport *n_port = shost_priv(shost);
- struct fcoe_port *port = lport_priv(n_port);
- struct fcoe_interface *fcoe = port->fcoe;
- struct net_device *netdev = fcoe->netdev;
+ struct fc_lport *lport;
+ struct fcoe_port *port;
+ struct fcoe_interface *fcoe;
+ struct net_device *netdev;
struct fc_lport *vn_port;
+ int error = 0;
+
+ lport = (struct fc_lport *)data;
+
+ port = lport_priv(lport);
+ fcoe = port->fcoe;
+ netdev = fcoe->netdev;
+
+ vn_port = fcoe_lport_create(fcoe);
+ if (!vn_port) {
+ FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
+ return -ENOMEM;
+ }
mutex_lock(&fcoe_config_mutex);
- vn_port = fcoe_if_create(fcoe, &vport->dev, 1);
+ error = fcoe_if_create(vn_port, fcoe, &vport->gendev, 1);
mutex_unlock(&fcoe_config_mutex);
- if (IS_ERR(vn_port)) {
- printk(KERN_ERR "fcoe: fcoe_vport_create(%s) failed\n",
- netdev->name);
+ /*
+ * TODO: Need to free the vn_port (lport) in this case.
+ */
+ if (error)
+ return error;
+
+ /*
+ * TODO: Check the failure case here.
+ */
+ error = libfc_vport_config(lport, vn_port, vport);
+ if (error)
return -EIO;
- }
+
+ if (IS_ERR(vn_port))
+ return -EIO;
+
+ /*
+ * TODO: This routine is not currently setting a unique
+ * name for the vports.
+ */
+ fcoe_set_symbolic_name(lport);
+
if (disabled) {
fc_vport_set_state(vport, FC_VPORT_DISABLED);
@@ -2527,6 +2667,7 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
fc_fabric_login(vn_port);
fc_vport_setlink(vn_port);
}
+
return 0;
}
@@ -2536,10 +2677,9 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
*
* Returns: 0 for success
*/
-static int fcoe_vport_destroy(struct fc_vport *vport)
+static int fcoe_vport_destroy(void *data, struct fc_fcvport *vport)
{
- struct Scsi_Host *shost = vport_to_shost(vport);
- struct fc_lport *n_port = shost_priv(shost);
+ struct fc_lport *n_port = data;
struct fc_lport *vn_port = vport->dd_data;
struct fcoe_port *port = lport_priv(vn_port);
@@ -2555,7 +2695,7 @@ static int fcoe_vport_destroy(struct fc_vport *vport)
* @vport: vport to bring online/offline
* @disable: should the vport be disabled?
*/
-static int fcoe_vport_disable(struct fc_vport *vport, bool disable)
+static int fcoe_vport_disable(struct fc_fcvport *vport, bool disable)
{
struct fc_lport *lport = vport->dd_data;
@@ -2579,20 +2719,20 @@ static int fcoe_vport_disable(struct fc_vport *vport, bool disable)
* sent to the name server. There is no response handler, so if it fails
* for some reason it will not be retried.
*/
-static void fcoe_set_vport_symbolic_name(struct fc_vport *vport)
+static void fcoe_set_vport_symbolic_name(struct fc_fcvport *vport)
{
struct fc_lport *lport = vport->dd_data;
struct fc_frame *fp;
size_t len;
-
- snprintf(fc_host_symbolic_name(lport->host), FC_SYMBOLIC_NAME_SIZE,
+
+ snprintf(fcvport_symbolic_name(lport->fcvport), FC_SYMBOLIC_NAME_SIZE,
"%s v%s over %s : %s", FCOE_NAME, FCOE_VERSION,
fcoe_netdev(lport)->name, vport->symbolic_name);
if (lport->state != LPORT_ST_READY)
return;
- len = strnlen(fc_host_symbolic_name(lport->host), 255);
+ len = strnlen(fcvport_symbolic_name(lport->fcvport), 255);
fp = fc_frame_alloc(lport,
sizeof(struct fc_ct_hdr) +
sizeof(struct fc_ns_rspn) + len);
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index a554672..2de3887 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -39,6 +39,7 @@
#include <scsi/fc/fc_encaps.h>
#include <scsi/fc/fc_fcoe.h>
+#include <scsi/fc.h>
#include <scsi/libfc.h>
#include <scsi/libfcoe.h>
@@ -76,8 +77,8 @@ do { \
#define LIBFCOE_FIP_DBG(fip, fmt, args...) \
LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING, \
- printk(KERN_INFO "host%d: fip: " fmt, \
- (fip)->lp->host->host_no, ##args);)
+ printk(KERN_INFO "fcport%d: fip: " fmt, \
+ (fip)->lp->fcport->id, ##args);)
/**
* fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid
@@ -229,7 +230,7 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
sol->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
sol->desc.wwnn.fd_desc.fip_dlen = sizeof(sol->desc.wwnn) / FIP_BPW;
- put_unaligned_be64(fip->lp->wwnn, &sol->desc.wwnn.fd_wwn);
+ put_unaligned_be64(fcvport_node_name(fip->lp->fcvport), &sol->desc.wwnn.fd_wwn);
fcoe_size = fcoe_ctlr_fcoe_size(fip);
sol->desc.size.fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
@@ -303,6 +304,7 @@ int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
int link_dropped;
LIBFCOE_FIP_DBG(fip, "link down.\n");
+
spin_lock_bh(&fip->lock);
fcoe_ctlr_reset(fip);
link_dropped = fip->link;
@@ -310,7 +312,6 @@ int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
fip->last_link = 0;
fip->state = FIP_ST_LINK_WAIT;
spin_unlock_bh(&fip->lock);
-
if (link_dropped)
fc_linkdown(fip->lp);
return link_dropped;
@@ -370,7 +371,6 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
kal->fip.fip_flags = htons(FIP_FL_FPMA);
if (fip->spma)
kal->fip.fip_flags |= htons(FIP_FL_SPMA);
-
kal->mac.fd_desc.fip_dtype = FIP_DT_MAC;
kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW;
memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
@@ -380,7 +380,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW;
memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
hton24(vn->fd_fc_id, lp->port_id);
- put_unaligned_be64(lp->wwpn, &vn->fd_wwpn);
+ put_unaligned_be64(fcvport_port_name(lp->fcvport), &vn->fd_wwpn);
}
skb_put(skb, len);
skb->protocol = htons(ETH_P_FIP);
@@ -568,6 +568,7 @@ EXPORT_SYMBOL(fcoe_ctlr_els_send);
*/
static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
{
+ struct fc_fcp_internal *si = fc_get_scsi_internal(fip->lp);
struct fcoe_fcf *fcf;
struct fcoe_fcf *next;
unsigned long sel_time = 0;
@@ -581,7 +582,7 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
fc_lport_get_stats(fip->lp)->MissDiscAdvCount++;
printk(KERN_INFO "libfcoe: host%d: Missing Discovery "
"Advertisement for fab %llx count %lld\n",
- fip->lp->host->host_no, fcf->fabric_name,
+ si->host->host_no, fcf->fabric_name,
fc_lport_get_stats(fip->lp)->MissDiscAdvCount);
}
if (time_after(jiffies, fcf->time + fcf->fka_period * 3 +
@@ -773,6 +774,8 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
}
mtu_valid = fcoe_ctlr_mtu_valid(fcf);
+
+
fcf->time = jiffies;
if (!found) {
LIBFCOE_FIP_DBG(fip, "New FCF for fab %llx map %x val %d\n",
@@ -806,6 +809,19 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
time_before(fip->sel_time, fip->timer.expires))
mod_timer(&fip->timer, fip->sel_time);
}
+
+ if (!found) {
+ spin_unlock_bh(&fip->lock);
+ /* RWL */
+ fip->lp->fcfport = fc_fcfport_add(fip->lp->fcport, fcf->switch_name);
+ if (!fip->lp->fcfport) {
+ fc_fcport_del(fip->lp->fcport);
+ goto out;
+ }
+
+ return;
+ }
+
out:
spin_unlock_bh(&fip->lock);
}
@@ -979,7 +995,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
return;
if (compare_ether_addr(vp->fd_mac,
fip->get_src_addr(lport)) == 0 &&
- get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn &&
+ get_unaligned_be64(&vp->fd_wwpn) == fcvport_port_name(lport->fcvport) &&
ntoh24(vp->fd_fc_id) == lport->port_id)
desc_mask &= ~BIT(FIP_DT_VN_ID);
break;
@@ -1159,18 +1175,18 @@ static void fcoe_ctlr_timeout(unsigned long arg)
if (sel != fcf) {
fcf = sel; /* the old FCF may have been freed */
if (sel) {
- printk(KERN_INFO "libfcoe: host%d: FIP selected "
+ printk(KERN_INFO "libfcoe: fcport%d: FIP selected "
"Fibre-Channel Forwarder MAC %pM\n",
- fip->lp->host->host_no, sel->fcf_mac);
+ fip->lp->fcport->id, sel->fcf_mac);
memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
fip->port_ka_time = jiffies +
msecs_to_jiffies(FIP_VN_KA_PERIOD);
fip->ctlr_ka_time = jiffies + sel->fka_period;
} else {
- printk(KERN_NOTICE "libfcoe: host%d: "
+ printk(KERN_NOTICE "libfcoe: fcport%d: "
"FIP Fibre-Channel Forwarder timed out. "
"Starting FCF discovery.\n",
- fip->lp->host->host_no);
+ fip->lp->fcport->id);
fip->reset_req = 1;
schedule_work(&fip->link_work);
}
@@ -1236,7 +1252,6 @@ static void fcoe_ctlr_link_work(struct work_struct *work)
fc_linkdown(fip->lp);
} else if (reset && link)
fc_lport_reset(fip->lp);
-
if (fip->send_ctlr_ka) {
fip->send_ctlr_ka = 0;
fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr);
@@ -1395,8 +1410,6 @@ int fcoe_libfc_config(struct fc_lport *lport,
{
/* Set the function pointers set by the LLDD */
memcpy(&lport->tt, tt, sizeof(*tt));
- if (fc_fcp_init(lport))
- return -ENOMEM;
fc_exch_init(lport);
fc_elsct_init(lport);
fc_lport_init(lport);
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index dd703fd..dd0344d 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -387,6 +387,7 @@ err:
static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
{
struct fc_lport *lport;
+ struct fc_fcp_internal *si;
struct fc_gpn_ft_resp *np;
char *bp;
size_t plen;
@@ -396,6 +397,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
struct fc_rport_priv *rdata;
lport = disc->lport;
+ si = fc_get_scsi_internal(lport);
disc->seq_count++;
/*
@@ -440,7 +442,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
ids.port_name = ntohll(np->fp_wwpn);
if (ids.port_id != lport->port_id &&
- ids.port_name != lport->wwpn) {
+ ids.port_name != fcvport_port_name(lport->fcvport)) {
rdata = lport->tt.rport_create(lport, ids.port_id);
if (rdata) {
rdata->ids.port_name = ids.port_name;
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 425f4dd..3cffbb3 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1922,11 +1922,13 @@ err:
static void fc_exch_rrq(struct fc_exch *ep)
{
struct fc_lport *lport;
+ struct fc_fcp_internal *si;
struct fc_els_rrq *rrq;
struct fc_frame *fp;
u32 did;
lport = ep->lp;
+ si = fc_get_scsi_internal(lport);
fp = fc_frame_alloc(lport, sizeof(*rrq));
if (!fp)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index d2da31e..2f89dde 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -66,26 +66,6 @@ struct kmem_cache *scsi_pkt_cachep;
#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status)
#define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual)
-/**
- * struct fc_fcp_internal - FCP layer internal data
- * @scsi_pkt_pool: Memory pool to draw FCP packets from
- * @scsi_queue_lock: Protects the scsi_pkt_queue
- * @scsi_pkt_queue: Current FCP packets
- * @last_can_queue_ramp_down_time: ramp down time
- * @last_can_queue_ramp_up_time: ramp up time
- * @max_can_queue: max can_queue size
- */
-struct fc_fcp_internal {
- mempool_t *scsi_pkt_pool;
- spinlock_t scsi_queue_lock;
- struct list_head scsi_pkt_queue;
- unsigned long last_can_queue_ramp_down_time;
- unsigned long last_can_queue_ramp_up_time;
- int max_can_queue;
-};
-
-#define fc_get_scsi_internal(x) ((struct fc_fcp_internal *)(x)->scsi_priv)
-
/*
* function prototypes
* FC scsi I/O related functions
@@ -351,13 +331,13 @@ static void fc_fcp_can_queue_ramp_up(struct fc_lport *lport)
si->last_can_queue_ramp_up_time = jiffies;
- can_queue = lport->host->can_queue << 1;
+ can_queue = si->host->can_queue << 1;
if (can_queue >= si->max_can_queue) {
can_queue = si->max_can_queue;
si->last_can_queue_ramp_down_time = 0;
}
- lport->host->can_queue = can_queue;
- shost_printk(KERN_ERR, lport->host, "libfc: increased "
+ si->host->can_queue = can_queue;
+ shost_printk(KERN_ERR, si->host, "libfc: increased "
"can_queue to %d.\n", can_queue);
}
@@ -385,12 +365,12 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
si->last_can_queue_ramp_down_time = jiffies;
- can_queue = lport->host->can_queue;
+ can_queue = si->host->can_queue;
can_queue >>= 1;
if (!can_queue)
can_queue = 1;
- lport->host->can_queue = can_queue;
- shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n"
+ si->host->can_queue = can_queue;
+ shost_printk(KERN_ERR, si->host, "libfc: Could not allocate frame.\n"
"Reducing can_queue to %d.\n", can_queue);
}
@@ -405,6 +385,7 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
size_t len)
{
+ struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
struct fc_frame *fp;
unsigned long flags;
@@ -413,9 +394,10 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
return fp;
/* error case */
- spin_lock_irqsave(lport->host->host_lock, flags);
+ spin_lock_irqsave(si->host->host_lock, flags);
fc_fcp_can_queue_ramp_down(lport);
- spin_unlock_irqrestore(lport->host->host_lock, flags);
+ spin_unlock_irqrestore(si->host->host_lock, flags);
+
return NULL;
}
@@ -484,6 +466,7 @@ crc_err:
printk(KERN_WARNING "libfc: CRC error on data "
"frame for port (%6x)\n",
lport->port_id);
+
/*
* Assume the frame is total garbage.
* We may have copied it over the good part
@@ -991,7 +974,7 @@ static void fc_fcp_cleanup_each_cmd(struct fc_lport *lport, unsigned int id,
struct scsi_cmnd *sc_cmd;
unsigned long flags;
- spin_lock_irqsave(&si->scsi_queue_lock, flags);
+ spin_lock_irqsave(si->host->host_lock, flags);
restart:
list_for_each_entry(fsp, &si->scsi_pkt_queue, list) {
sc_cmd = fsp->cmd;
@@ -1002,7 +985,7 @@ restart:
continue;
fc_fcp_pkt_hold(fsp);
- spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
+ spin_unlock_irqrestore(si->host->host_lock, flags);
if (!fc_fcp_lock_pkt(fsp)) {
fc_fcp_cleanup_cmd(fsp, error);
@@ -1011,14 +994,14 @@ restart:
}
fc_fcp_pkt_release(fsp);
- spin_lock_irqsave(&si->scsi_queue_lock, flags);
+ spin_lock_irqsave(si->host->host_lock, flags);
/*
* while we dropped the lock multiple pkts could
* have been released, so we have to start over.
*/
goto restart;
}
- spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
+ spin_unlock_irqrestore(si->host->host_lock, flags);
}
/**
@@ -1356,8 +1339,10 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
struct fc_frame *fp;
struct fc_rport *rport;
struct fc_rport_libfc_priv *rpriv;
+ struct fc_fcp_internal *si;
lport = fsp->lp;
+ si = fc_get_scsi_internal(lport);
rport = fsp->rport;
rpriv = rport->dd_data;
if (!fsp->seq_ptr || rpriv->rp_state != RPORT_ST_READY) {
@@ -1735,7 +1720,7 @@ static inline int fc_fcp_lport_queue_ready(struct fc_lport *lport)
{
/* lock ? */
return (lport->state == LPORT_ST_READY) &&
- lport->link_up && !lport->qfull;
+ lport->link_up && !fc_get_scsi_internal(lport)->qfull;
}
/**
@@ -1749,6 +1734,7 @@ static inline int fc_fcp_lport_queue_ready(struct fc_lport *lport)
int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
{
struct fc_lport *lport;
+ struct fc_fcp_internal *si;
struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
struct fc_fcp_pkt *fsp;
struct fc_rport_libfc_priv *rpriv;
@@ -1756,9 +1742,9 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
int rc = 0;
struct fcoe_dev_stats *stats;
- lport = shost_priv(sc_cmd->device->host);
- spin_unlock_irq(lport->host->host_lock);
-
+ si = shost_priv(sc_cmd->device->host);
+ lport = si->lport;
+ spin_unlock_irq(si->host->host_lock);
rval = fc_remote_port_chkready(rport);
if (rval) {
sc_cmd->result = rval;
@@ -1779,7 +1765,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
rpriv = rport->dd_data;
if (!fc_fcp_lport_queue_ready(lport)) {
- if (lport->qfull)
+ if (si->qfull)
fc_fcp_can_queue_ramp_down(lport);
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
@@ -1840,7 +1826,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
rc = SCSI_MLQUEUE_HOST_BUSY;
}
out:
- spin_lock_irq(lport->host->host_lock);
+ spin_lock_irq(si->host->host_lock);
return rc;
}
EXPORT_SYMBOL(fc_queuecommand);
@@ -1968,25 +1954,27 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
{
struct fc_fcp_pkt *fsp;
struct fc_lport *lport;
+ struct fc_fcp_internal *si;
int rc = FAILED;
unsigned long flags;
- lport = shost_priv(sc_cmd->device->host);
+ si = shost_priv(sc_cmd->device->host);
+ lport = si->lport;
if (lport->state != LPORT_ST_READY)
return rc;
else if (!lport->link_up)
return rc;
- spin_lock_irqsave(lport->host->host_lock, flags);
+ spin_lock_irqsave(si->host->host_lock, flags);
fsp = CMD_SP(sc_cmd);
if (!fsp) {
/* command completed while scsi eh was setting up */
- spin_unlock_irqrestore(lport->host->host_lock, flags);
+ spin_unlock_irqrestore(si->host->host_lock, flags);
return SUCCESS;
}
/* grab a ref so the fsp and sc_cmd cannot be relased from under us */
fc_fcp_pkt_hold(fsp);
- spin_unlock_irqrestore(lport->host->host_lock, flags);
+ spin_unlock_irqrestore(si->host->host_lock, flags);
if (fc_fcp_lock_pkt(fsp)) {
/* completed while we were waiting for timer to be deleted */
@@ -2013,6 +2001,7 @@ EXPORT_SYMBOL(fc_eh_abort);
int fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
{
struct fc_lport *lport;
+ struct fc_fcp_internal *si;
struct fc_fcp_pkt *fsp;
struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
int rc = FAILED;
@@ -2022,7 +2011,8 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
if (rval)
goto out;
- lport = shost_priv(sc_cmd->device->host);
+ si = shost_priv(sc_cmd->device->host);
+ lport = si->lport;
if (lport->state != LPORT_ST_READY)
return rc;
@@ -2062,7 +2052,8 @@ EXPORT_SYMBOL(fc_eh_device_reset);
int fc_eh_host_reset(struct scsi_cmnd *sc_cmd)
{
struct Scsi_Host *shost = sc_cmd->device->host;
- struct fc_lport *lport = shost_priv(shost);
+ struct fc_fcp_internal *si = shost_priv(shost);
+ struct fc_lport *lport = si->lport;
unsigned long wait_tmo;
FC_SCSI_DBG(lport, "Resetting host\n");
@@ -2167,7 +2158,12 @@ void fc_fcp_destroy(struct fc_lport *lport)
"port (%6x)\n", lport->port_id);
mempool_destroy(si->scsi_pkt_pool);
- kfree(si);
+
+ /* Detach from the scsi-ml */
+ fc_remove_host(si->host);
+ scsi_remove_host(si->host);
+ scsi_host_put(si->host);
+
lport->scsi_priv = NULL;
}
EXPORT_SYMBOL(fc_fcp_destroy);
@@ -2200,8 +2196,9 @@ void fc_destroy_fcp()
*/
int fc_fcp_init(struct fc_lport *lport)
{
- int rc;
+ struct Scsi_Host *shost;
struct fc_fcp_internal *si;
+ int rc = 0;
if (!lport->tt.fcp_cmd_send)
lport->tt.fcp_cmd_send = fc_fcp_cmd_send;
@@ -2212,23 +2209,48 @@ int fc_fcp_init(struct fc_lport *lport)
if (!lport->tt.fcp_abort_io)
lport->tt.fcp_abort_io = fc_fcp_abort_io;
- si = kzalloc(sizeof(struct fc_fcp_internal), GFP_KERNEL);
- if (!si)
- return -ENOMEM;
- lport->scsi_priv = si;
- si->max_can_queue = lport->host->can_queue;
+ shost = scsi_host_alloc(lport->tt.shost_template,
+ sizeof(struct fc_fcp_internal));
+ if (!shost) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ si = shost_priv(shost);
+ si->host = shost;
+ lport->scsi_priv = si;
+ si->lport = lport;
+
+ lport->fcpinit = shost_to_fcpinit(shost);
+ lport->fcfabric->shost = shost;
+
+ lport->tt.shost_config(lport, si);
+
+ /* add the new host to the SCSI-ml */
+ /*
+ * TODO: I don't think this is right and I'm not sure how to get the
+ * order right at this time. It should be vport/fcpinit/host.
+ */
+ rc = scsi_add_host(si->host, &lport->fcvport->gendev);
+ if (rc)
+ goto out_free_host;
+
+ si->max_can_queue = si->host->can_queue;
+
INIT_LIST_HEAD(&si->scsi_pkt_queue);
spin_lock_init(&si->scsi_queue_lock);
si->scsi_pkt_pool = mempool_create_slab_pool(2, scsi_pkt_cachep);
if (!si->scsi_pkt_pool) {
rc = -ENOMEM;
- goto free_internal;
+ goto out_free_host;
}
+
return 0;
-free_internal:
- kfree(si);
+out_free_host:
+ scsi_host_put(shost);
+out:
return rc;
}
EXPORT_SYMBOL(fc_fcp_init);
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
index a79c42d..e5ec03e 100644
--- a/drivers/scsi/libfc/fc_libfc.h
+++ b/drivers/scsi/libfc/fc_libfc.h
@@ -45,20 +45,20 @@ extern unsigned int fc_debug_logging;
#define FC_LPORT_DBG(lport, fmt, args...) \
FC_CHECK_LOGGING(FC_LPORT_LOGGING, \
- printk(KERN_INFO "host%u: lport %6x: " fmt, \
- (lport)->host->host_no, \
+ printk(KERN_INFO "fcport%u: lport %6x: " fmt, \
+ (lport)->fcport->id, \
(lport)->port_id, ##args))
-#define FC_DISC_DBG(disc, fmt, args...) \
- FC_CHECK_LOGGING(FC_DISC_LOGGING, \
- printk(KERN_INFO "host%u: disc: " fmt, \
- (disc)->lport->host->host_no, \
+#define FC_DISC_DBG(disc, fmt, args...) \
+ FC_CHECK_LOGGING(FC_DISC_LOGGING, \
+ printk(KERN_INFO "fcport%u: disc: " fmt, \
+ (disc)->lport->fcport->id, \
##args))
#define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \
FC_CHECK_LOGGING(FC_RPORT_LOGGING, \
- printk(KERN_INFO "host%u: rport %6x: " fmt, \
- (lport)->host->host_no, \
+ printk(KERN_INFO "fcport%u: rport %6x: " fmt, \
+ (lport)->fcport->id, \
(port_id), ##args))
#define FC_RPORT_DBG(rdata, fmt, args...) \
@@ -66,20 +66,20 @@ extern unsigned int fc_debug_logging;
#define FC_FCP_DBG(pkt, fmt, args...) \
FC_CHECK_LOGGING(FC_FCP_LOGGING, \
- printk(KERN_INFO "host%u: fcp: %6x: " fmt, \
- (pkt)->lp->host->host_no, \
+ printk(KERN_INFO "fcport%u: fcp: %6x: " fmt, \
+ (pkt)->lp->fcport->id, \
pkt->rport->port_id, ##args))
#define FC_EXCH_DBG(exch, fmt, args...) \
FC_CHECK_LOGGING(FC_EXCH_LOGGING, \
- printk(KERN_INFO "host%u: xid %4x: " fmt, \
- (exch)->lp->host->host_no, \
+ printk(KERN_INFO "fcport%u: xid %4x: " fmt, \
+ (exch)->lp->fcport->id, \
exch->xid, ##args))
#define FC_SCSI_DBG(lport, fmt, args...) \
FC_CHECK_LOGGING(FC_SCSI_LOGGING, \
- printk(KERN_INFO "host%u: scsi: " fmt, \
- (lport)->host->host_no, ##args))
+ printk(KERN_INFO "fcport%u: scsi: " fmt, \
+ (lport)->fcport->id, ##args))
/*
* Set up direct-data placement for this I/O request
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 9da4c15..0466553 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -245,48 +245,38 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
*/
void fc_get_host_port_state(struct Scsi_Host *shost)
{
- struct fc_lport *lport = shost_priv(shost);
+ struct fc_fcp_internal *si = shost_priv(shost);
+ struct fc_lport *lport = si->lport;
mutex_lock(&lport->lp_mutex);
if (!lport->link_up)
- fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+ fcpinit_port_state(shost) = FC_PORTSTATE_LINKDOWN;
else
switch (lport->state) {
case LPORT_ST_READY:
- fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+ fcpinit_port_state(shost) = FC_PORTSTATE_ONLINE;
break;
default:
- fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
+ fcpinit_port_state(shost) = FC_PORTSTATE_OFFLINE;
}
mutex_unlock(&lport->lp_mutex);
}
EXPORT_SYMBOL(fc_get_host_port_state);
/**
- * fc_get_host_speed() - Return the speed of the given Scsi_Host
- * @shost: The SCSI host whose port speed is to be determined
- */
-void fc_get_host_speed(struct Scsi_Host *shost)
-{
- struct fc_lport *lport = shost_priv(shost);
-
- fc_host_speed(shost) = lport->link_speed;
-}
-EXPORT_SYMBOL(fc_get_host_speed);
-
-/**
* fc_get_host_stats() - Return the Scsi_Host's statistics
* @shost: The SCSI host whose statistics are to be returned
*/
-struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
+struct fcpinit_statistics *fc_get_host_stats(struct Scsi_Host *shost)
{
- struct fc_host_statistics *fcoe_stats;
- struct fc_lport *lport = shost_priv(shost);
+ struct fcpinit_statistics *fcoe_stats;
+ struct fc_fcp_internal *si = shost_priv(shost);
+ struct fc_lport *lport = si->lport;
struct timespec v0, v1;
unsigned int cpu;
- fcoe_stats = &lport->host_stats;
- memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
+ fcoe_stats = &si->host_stats;
+ memset(fcoe_stats, 0, sizeof(struct fcpinit_statistics));
jiffies_to_timespec(jiffies, &v0);
jiffies_to_timespec(lport->boot_time, &v1);
@@ -335,8 +325,8 @@ static void fc_lport_flogi_fill(struct fc_lport *lport,
memset(flogi, 0, sizeof(*flogi));
flogi->fl_cmd = (u8) op;
- put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
- put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
+ put_unaligned_be64(fcvport_port_name(lport->fcvport), &flogi->fl_wwpn);
+ put_unaligned_be64(fcvport_node_name(lport->fcvport), &flogi->fl_wwnn);
sp = &flogi->fl_csp;
sp->sp_hi_ver = 0x20;
sp->sp_lo_ver = 0x20;
@@ -479,8 +469,8 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
rp->rnid.rnid_cmd = ELS_LS_ACC;
rp->rnid.rnid_fmt = fmt;
rp->rnid.rnid_cid_len = sizeof(rp->cid);
- rp->cid.rnid_wwpn = htonll(lport->wwpn);
- rp->cid.rnid_wwnn = htonll(lport->wwnn);
+ rp->cid.rnid_wwpn = htonll(fcvport_port_name(lport->fcvport));
+ rp->cid.rnid_wwnn = htonll(fcvport_node_name(lport->fcvport));
if (fmt == ELS_RNIDF_GEN) {
rp->rnid.rnid_sid_len = sizeof(rp->gen);
memcpy(&rp->gen, &lport->rnid_gen,
@@ -548,7 +538,6 @@ void __fc_linkup(struct fc_lport *lport)
{
if (!lport->link_up) {
lport->link_up = 1;
-
if (lport->state == LPORT_ST_RESET)
fc_lport_enter_flogi(lport);
}
@@ -560,8 +549,8 @@ void __fc_linkup(struct fc_lport *lport)
*/
void fc_linkup(struct fc_lport *lport)
{
- printk(KERN_INFO "host%d: libfc: Link up on port (%6x)\n",
- lport->host->host_no, lport->port_id);
+ printk(KERN_INFO "fcport%d: libfc: Link up on port (%6x)\n",
+ lport->fcport->id, lport->port_id);
mutex_lock(&lport->lp_mutex);
__fc_linkup(lport);
@@ -580,7 +569,8 @@ void __fc_linkdown(struct fc_lport *lport)
if (lport->link_up) {
lport->link_up = 0;
fc_lport_enter_reset(lport);
- lport->tt.fcp_cleanup(lport);
+ if (lport->tt.fcp_cleanup)
+ lport->tt.fcp_cleanup(lport);
}
}
@@ -590,8 +580,8 @@ void __fc_linkdown(struct fc_lport *lport)
*/
void fc_linkdown(struct fc_lport *lport)
{
- printk(KERN_INFO "host%d: libfc: Link down on port (%6x)\n",
- lport->host->host_no, lport->port_id);
+ printk(KERN_INFO "fcport%d: libfc: Link down on port (%6x)\n",
+ lport->fcport->id, lport->port_id);
mutex_lock(&lport->lp_mutex);
__fc_linkdown(lport);
@@ -640,7 +630,13 @@ int fc_lport_destroy(struct fc_lport *lport)
lport->tt.frame_send = fc_frame_drop;
mutex_unlock(&lport->lp_mutex);
- lport->tt.fcp_abort_io(lport);
+ /*
+ * TODO: What should we be checking here? The existence of fcpinit or
+ * the existence fcp_abort_io()?
+ */
+ if (lport->fcpinit)
+ lport->tt.fcp_abort_io(lport);
+
lport->tt.disc_stop_final(lport);
lport->tt.exch_mgr_reset(lport, 0, 0);
return 0;
@@ -691,9 +687,9 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
FC_LPORT_DBG(lport, "Discovery succeeded\n");
break;
case DISC_EV_FAILED:
- printk(KERN_ERR "host%d: libfc: "
+ printk(KERN_ERR "fcport%d: libfc: "
"Discovery failed for port (%6x)\n",
- lport->host->host_no, lport->port_id);
+ lport->fcport->id, lport->port_id);
mutex_lock(&lport->lp_mutex);
fc_lport_enter_reset(lport);
mutex_unlock(&lport->lp_mutex);
@@ -717,8 +713,8 @@ static void fc_lport_enter_ready(struct fc_lport *lport)
fc_lport_state(lport));
fc_lport_state_enter(lport, LPORT_ST_READY);
- if (lport->vport)
- fc_vport_set_state(lport->vport, FC_VPORT_ACTIVE);
+ if (!fc_fcvport_is_nport(&lport->fcvport->gendev, NULL))
+ fc_vport_set_state(lport->fcvport, FC_VPORT_ACTIVE);
fc_vports_linkchange(lport);
if (!lport->ptp_rdata)
@@ -738,10 +734,11 @@ static void fc_lport_set_port_id(struct fc_lport *lport, u32 port_id,
struct fc_frame *fp)
{
if (port_id)
- printk(KERN_INFO "host%d: Assigned Port ID %6x\n",
- lport->host->host_no, port_id);
+ printk(KERN_INFO "fcport%d: Assigned Port ID %6x\n",
+ lport->fcport->id, port_id);
lport->port_id = port_id;
+
if (lport->tt.lport_set_port_id)
lport->tt.lport_set_port_id(lport, port_id, fp);
}
@@ -783,10 +780,10 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
if (!flp)
goto out;
remote_wwpn = get_unaligned_be64(&flp->fl_wwpn);
- if (remote_wwpn == lport->wwpn) {
- printk(KERN_WARNING "host%d: libfc: Received FLOGI from port "
+ if (remote_wwpn == fcvport_port_name(lport->fcvport)) {
+ printk(KERN_WARNING "fcport%d: libfc: Received FLOGI from port "
"with same WWPN %llx\n",
- lport->host->host_no, remote_wwpn);
+ lport->fcport->id, remote_wwpn);
goto out;
}
FC_LPORT_DBG(lport, "FLOGI from port WWPN %llx\n", remote_wwpn);
@@ -797,7 +794,7 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
* But if so, both of us could end up with the same FID.
*/
local_fid = FC_LOCAL_PTP_FID_LO;
- if (remote_wwpn < lport->wwpn) {
+ if (remote_wwpn < fcvport_port_name(lport->fcvport)) {
local_fid = FC_LOCAL_PTP_FID_HI;
if (!remote_fid || remote_fid == local_fid)
remote_fid = FC_LOCAL_PTP_FID_LO;
@@ -940,7 +937,9 @@ static void fc_lport_reset_locked(struct fc_lport *lport)
lport->tt.disc_stop(lport);
lport->tt.exch_mgr_reset(lport, 0, 0);
- fc_host_fabric_name(lport->host) = 0;
+
+ if (lport->fcfabric)
+ fcfabric_fabric_name(lport->fcfabric) = 0;
if (lport->port_id)
fc_lport_set_port_id(lport, 0, NULL);
@@ -961,15 +960,16 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
if (lport->state == LPORT_ST_DISABLED || lport->state == LPORT_ST_LOGO)
return;
- if (lport->vport) {
+ if (!fc_fcvport_is_nport(&lport->fcvport->gendev, NULL)) {
if (lport->link_up)
- fc_vport_set_state(lport->vport, FC_VPORT_INITIALIZING);
+ fc_vport_set_state(lport->fcvport, FC_VPORT_INITIALIZING);
else
- fc_vport_set_state(lport->vport, FC_VPORT_LINKDOWN);
+ fc_vport_set_state(lport->fcvport, FC_VPORT_LINKDOWN);
}
fc_lport_state_enter(lport, LPORT_ST_RESET);
fc_vports_linkchange(lport);
fc_lport_reset_locked(lport);
+
if (lport->link_up)
fc_lport_enter_flogi(lport);
}
@@ -1216,7 +1216,7 @@ static void fc_lport_enter_ns(struct fc_lport *lport, enum fc_lport_state state)
size += sizeof(struct fc_ns_rn_id);
break;
case LPORT_ST_RSNN_NN:
- len = strnlen(fc_host_symbolic_name(lport->host), 255);
+ len = strnlen(fcvport_symbolic_name(lport->fcvport), 255);
/* if there is no symbolic name, skip to RFT_ID */
if (!len)
return fc_lport_enter_ns(lport, LPORT_ST_RFT_ID);
@@ -1224,7 +1224,7 @@ static void fc_lport_enter_ns(struct fc_lport *lport, enum fc_lport_state state)
size += sizeof(struct fc_ns_rsnn) + len;
break;
case LPORT_ST_RSPN_ID:
- len = strnlen(fc_host_symbolic_name(lport->host), 255);
+ len = strnlen(fcvport_symbolic_name(lport->fcvport), 255);
/* if there is no symbolic name, skip to RFT_ID */
if (!len)
return fc_lport_enter_ns(lport, LPORT_ST_RFT_ID);
@@ -1436,8 +1436,6 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
unsigned int e_d_tov;
u16 mfs;
- FC_LPORT_DBG(lport, "Received a FLOGI %s\n", fc_els_resp_type(fp));
-
if (fp == ERR_PTR(-FC_EX_CLOSED))
return;
@@ -1479,10 +1477,6 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
lport->e_d_tov = e_d_tov;
lport->r_a_tov = 2 * e_d_tov;
fc_lport_set_port_id(lport, did, fp);
- printk(KERN_INFO "host%d: libfc: "
- "Port (%6x) entered "
- "point-to-point mode\n",
- lport->host->host_no, did);
fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id),
get_unaligned_be64(
&flp->fl_wwpn),
@@ -1491,15 +1485,40 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
} else {
lport->e_d_tov = e_d_tov;
lport->r_a_tov = r_a_tov;
- fc_host_fabric_name(lport->host) =
- get_unaligned_be64(&flp->fl_wwnn);
+
+ /*
+ * TODO: There needs to be a lot more error handling here.
+ */
+ if (!lport->fcfabric) {
+ lport->fcfabric = fc_fcfabric_add(lport->fcfport,
+ lport->fcfabric_f);
+ if (!lport->fcfabric)
+ goto out;
+
+ lport->fcfabric->fcvport_f = lport->fcvport_f;
+ lport->tt.set_fcfabric_max_npiv_vports(lport);
+ fcfabric_fabric_name(lport->fcfabric) = get_unaligned_be64(&flp->fl_wwnn);
+ }
+
+ fc_fcvport_add(lport->fcvport, lport->fcfabric);
+
+ /* RWL - this seems redundant, doesn't it? */
fc_lport_set_port_id(lport, did, fp);
+ fcvport_port_id(lport->fcvport) = lport->port_id;
+
+/* TODO: How do I link the fcpinit to the fcvport?
+ lport->fcpinit = fc_fcpinit_add(lport->fcvport, 0);
+ if (!lport->fcpinit)
+ goto out;
+*/
+ if (fc_fcp_init(lport))
+ goto out;
+
fc_lport_enter_dns(lport);
}
}
- } else {
+ } else
FC_LPORT_DBG(lport, "Bad FLOGI response\n");
- }
out:
fc_frame_free(fp);
@@ -1529,10 +1548,10 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
return fc_lport_error(lport, fp);
if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp,
- lport->vport ? ELS_FDISC : ELS_FLOGI,
+ fc_fcvport_is_nport(&lport->fcvport->gendev, NULL) ? ELS_FLOGI : ELS_FDISC,
fc_lport_flogi_resp, lport,
- lport->vport ? 2 * lport->r_a_tov :
- lport->e_d_tov))
+ fc_fcvport_is_nport(&lport->fcvport->gendev, NULL) ? lport->e_d_tov :
+ 2 * lport->r_a_tov))
fc_lport_error(lport, NULL);
}
@@ -1547,6 +1566,12 @@ int fc_lport_config(struct fc_lport *lport)
fc_lport_state_enter(lport, LPORT_ST_DISABLED);
+ /*
+ * TODO: This is a bit goofy. We either need to
+ * use the fcport speeds and not have a lport copy
+ * or have a lport copy and have a get_fcport_*speed*()
+ * routine.
+ */
fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
fc_lport_add_fc4_type(lport, FC_TYPE_CT);
@@ -1554,6 +1579,27 @@ int fc_lport_config(struct fc_lport *lport)
}
EXPORT_SYMBOL(fc_lport_config);
+void fc_lport_port_config(struct fc_fcport *fcport)
+{
+
+ fcport_supported_fc4s(fcport)[2] = 1;
+ fcport_supported_fc4s(fcport)[7] = 1;
+ fcport_active_fc4s(fcport)[2] = 1;
+ fcport_active_fc4s(fcport)[7] = 1;
+
+ fcport_supported_classes(fcport) = FC_COS_CLASS3;
+ memset(fcport->supported_fc4s, 0,
+ sizeof(fcport->supported_fc4s));
+ fcport->supported_fc4s[2] = 1;
+ fcport->supported_fc4s[7] = 1;
+
+ memset(fcport->active_fc4s, 0,
+ sizeof(fcport->active_fc4s));
+ fcport->active_fc4s[2] = 1;
+ fcport->active_fc4s[7] = 1;
+}
+EXPORT_SYMBOL(fc_lport_port_config);
+
/**
* fc_lport_init() - Initialize the lport layer for a local port
* @lport: The local port to initialize the exchange layer for
@@ -1566,27 +1612,6 @@ int fc_lport_init(struct fc_lport *lport)
if (!lport->tt.lport_reset)
lport->tt.lport_reset = fc_lport_reset;
- fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
- fc_host_node_name(lport->host) = lport->wwnn;
- fc_host_port_name(lport->host) = lport->wwpn;
- fc_host_supported_classes(lport->host) = FC_COS_CLASS3;
- memset(fc_host_supported_fc4s(lport->host), 0,
- sizeof(fc_host_supported_fc4s(lport->host)));
- fc_host_supported_fc4s(lport->host)[2] = 1;
- fc_host_supported_fc4s(lport->host)[7] = 1;
-
- /* This value is also unchanging */
- memset(fc_host_active_fc4s(lport->host), 0,
- sizeof(fc_host_active_fc4s(lport->host)));
- fc_host_active_fc4s(lport->host)[2] = 1;
- fc_host_active_fc4s(lport->host)[7] = 1;
- fc_host_maxframe_size(lport->host) = lport->mfs;
- fc_host_supported_speeds(lport->host) = 0;
- if (lport->link_supported_speeds & FC_PORTSPEED_1GBIT)
- fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT;
- if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
- fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
-
return 0;
}
EXPORT_SYMBOL(fc_lport_init);
diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c
index 0e90f00..608f9eb 100644
--- a/drivers/scsi/libfc/fc_npiv.c
+++ b/drivers/scsi/libfc/fc_npiv.c
@@ -24,38 +24,38 @@
#include <scsi/libfc.h>
/**
- * fc_vport_create() - Create a new NPIV vport instance
+ * fc_vport_config() - Configure a new vport
* @vport: fc_vport structure from scsi_transport_fc
* @privsize: driver private data size to allocate along with the Scsi_Host
*/
-
-struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize)
+int libfc_vport_config(struct fc_lport *n_port, struct fc_lport *vn_port,
+ struct fc_fcvport *vport)
{
- struct Scsi_Host *shost = vport_to_shost(vport);
- struct fc_lport *n_port = shost_priv(shost);
- struct fc_lport *vn_port;
-
- vn_port = libfc_host_alloc(shost->hostt, privsize);
- if (!vn_port)
- goto err_out;
if (fc_exch_mgr_list_clone(n_port, vn_port))
- goto err_put;
+ return -ENOMEM;
- vn_port->vport = vport;
+// vn_port->vport = vport;
vport->dd_data = vn_port;
+ /*
+ * TODO: This is done a bit blindly, are there considerations
+ * befre making these associations?
+ */
+ vn_port->fcvport = vport;
+ vn_port->fcfabric = n_port->fcfabric;
+ vn_port->fcfport = n_port->fcfport;
+ vn_port->fcport = n_port->fcport;
+
+// FCOE_NETDEV_DBG(netdev, "Setting vport names, 0x%llX 0x%llX\n",
+// vport->node_name, vport->port_name);
+
mutex_lock(&n_port->lp_mutex);
list_add_tail(&vn_port->list, &n_port->vports);
mutex_unlock(&n_port->lp_mutex);
- return vn_port;
-
-err_put:
- scsi_host_put(vn_port->host);
-err_out:
- return NULL;
+ return 0;
}
-EXPORT_SYMBOL(libfc_vport_create);
+EXPORT_SYMBOL(libfc_vport_config);
/**
* fc_vport_id_lookup() - find NPIV lport that matches a given fabric ID
@@ -105,7 +105,7 @@ enum libfc_lport_mutex_class {
static void __fc_vport_setlink(struct fc_lport *n_port,
struct fc_lport *vn_port)
{
- struct fc_vport *vport = vn_port->vport;
+ struct fc_fcvport *vport = vn_port->fcvport;
if (vn_port->state == LPORT_ST_DISABLED)
return;
@@ -130,9 +130,15 @@ static void __fc_vport_setlink(struct fc_lport *n_port,
*/
void fc_vport_setlink(struct fc_lport *vn_port)
{
- struct fc_vport *vport = vn_port->vport;
- struct Scsi_Host *shost = vport_to_shost(vport);
- struct fc_lport *n_port = shost_priv(shost);
+ struct fc_fcvport *vport = fc_fcfabric_find_nport(vn_port->fcfabric);
+ struct fc_lport *n_port = vport->priv_data;
+
+ /*
+ * TODO: This is terrible. There needs to be a return code that is
+ * checked by the caller.
+ */
+ if (!n_port)
+ return;
mutex_lock(&n_port->lp_mutex);
mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 97923bb..29b9683 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -246,6 +246,7 @@ static void fc_rport_work(struct work_struct *work)
struct fc_rport_identifiers ids;
struct fc_rport *rport;
int restart = 0;
+ struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
mutex_lock(&rdata->rp_mutex);
event = rdata->event;
@@ -262,7 +263,7 @@ static void fc_rport_work(struct work_struct *work)
mutex_unlock(&rdata->rp_mutex);
if (!rport)
- rport = fc_remote_port_add(lport->host, 0, &ids);
+ rport = fc_remote_port_add(si->host, 0, &ids);
if (!rport) {
FC_RPORT_DBG(rdata, "Failed to add the rport\n");
lport->tt.rport_logoff(rdata);
@@ -1112,13 +1113,14 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,
{
struct fc_lport *lport = rdata->local_port;
+ struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
struct fc_frame *fp;
struct fc_exch *ep = fc_seq_exch(sp);
struct fc_els_rls *rls;
struct fc_els_rls_resp *rsp;
struct fc_els_lesb *lesb;
struct fc_seq_els_data rjt_data;
- struct fc_host_statistics *hst;
+ struct fcpinit_statistics *hst;
u32 f_ctl;
FC_RPORT_DBG(rdata, "Received RLS request while in state %s\n",
@@ -1146,8 +1148,8 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,
/* get LESB from LLD if it supports it */
lport->tt.get_lesb(lport, lesb);
} else {
- fc_get_host_stats(lport->host);
- hst = &lport->host_stats;
+ fc_get_host_stats(si->host);
+ hst = &si->host_stats;
lesb->lesb_link_fail = htonl(hst->link_failure_count);
lesb->lesb_sync_loss = htonl(hst->loss_of_sync_count);
lesb->lesb_sig_loss = htonl(hst->loss_of_signal_count);
@@ -1359,7 +1361,7 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
break;
case RPORT_ST_PLOGI:
FC_RPORT_DBG(rdata, "Received PLOGI in PLOGI state\n");
- if (rdata->ids.port_name < lport->wwpn) {
+ if (rdata->ids.port_name < fcvport_port_name(lport->fcvport)) {
mutex_unlock(&rdata->rp_mutex);
rjt_data.reason = ELS_RJT_INPROG;
rjt_data.explan = ELS_EXPL_NONE;
diff --git a/include/scsi/fc.h b/include/scsi/fc.h
index 7ca20fb..27e7f03 100644
--- a/include/scsi/fc.h
+++ b/include/scsi/fc.h
@@ -381,8 +381,7 @@ struct fc_fcfport *fc_fcfport_lookup(struct fc_fcport *fcport, const u64 name);
struct fc_fcvport *fc_fcvport_lookup(struct fc_fcfabric *fcfabric, const u32 id);
struct fc_fcport *fc_fcport_add(struct device *pdev,
- struct fcport_function_template *,
- int priv_size);
+ struct fcport_function_template *);
struct fc_fcfport *fc_fcfport_add(struct fc_fcport *fcport, const u64 name);
struct fc_fcfabric *fc_fcfabric_add(struct fc_fcfport *fcfport,
struct fcfabric_function_template *);
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index 9b4867c..d8e8904 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -72,8 +72,8 @@ static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
adisc = fc_frame_payload_get(fp, sizeof(*adisc));
memset(adisc, 0, sizeof(*adisc));
adisc->adisc_cmd = ELS_ADISC;
- put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
- put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
+ put_unaligned_be64(fcvport_port_name(lport->fcvport), &adisc->adisc_wwpn);
+ put_unaligned_be64(fcvport_node_name(lport->fcvport), &adisc->adisc_wwnn);
hton24(adisc->adisc_port_id, lport->port_id);
}
@@ -144,24 +144,24 @@ static inline int fc_ct_fill(struct fc_lport *lport,
case FC_NS_RNN_ID:
ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id));
hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id);
- put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn);
+ put_unaligned_be64(fcvport_node_name(lport->fcvport), &ct->payload.rn.fr_wwn);
break;
case FC_NS_RSPN_ID:
- len = strnlen(fc_host_symbolic_name(lport->host), 255);
+ len = strnlen(fcvport_symbolic_name(lport->fcvport), 255);
ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len);
hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id);
strncpy(ct->payload.spn.fr_name,
- fc_host_symbolic_name(lport->host), len);
+ fcvport_symbolic_name(lport->fcvport), len);
ct->payload.spn.fr_name_len = len;
break;
case FC_NS_RSNN_NN:
- len = strnlen(fc_host_symbolic_name(lport->host), 255);
+ len = strnlen(fcvport_symbolic_name(lport->fcvport), 255);
ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len);
- put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn);
+ put_unaligned_be64(fcvport_node_name(lport->fcvport), &ct->payload.snn.fr_wwn);
strncpy(ct->payload.snn.fr_name,
- fc_host_symbolic_name(lport->host), len);
+ fcvport_symbolic_name(lport->fcvport), len);
ct->payload.snn.fr_name_len = len;
break;
@@ -186,8 +186,8 @@ static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
plogi = fc_frame_payload_get(fp, sizeof(*plogi));
memset(plogi, 0, sizeof(*plogi));
plogi->fl_cmd = (u8) op;
- put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn);
- put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn);
+ put_unaligned_be64(fcvport_port_name(lport->fcvport), &plogi->fl_wwpn);
+ put_unaligned_be64(fcvport_node_name(lport->fcvport), &plogi->fl_wwnn);
csp = &plogi->fl_csp;
csp->sp_hi_ver = 0x20;
@@ -218,8 +218,8 @@ static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
flogi = fc_frame_payload_get(fp, sizeof(*flogi));
memset(flogi, 0, sizeof(*flogi));
flogi->fl_cmd = (u8) ELS_FLOGI;
- put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
- put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
+ put_unaligned_be64(fcvport_port_name(lport->fcvport), &flogi->fl_wwpn);
+ put_unaligned_be64(fcvport_node_name(lport->fcvport), &flogi->fl_wwnn);
sp = &flogi->fl_csp;
sp->sp_hi_ver = 0x20;
sp->sp_lo_ver = 0x20;
@@ -243,8 +243,8 @@ static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
fdisc = fc_frame_payload_get(fp, sizeof(*fdisc));
memset(fdisc, 0, sizeof(*fdisc));
fdisc->fl_cmd = (u8) ELS_FDISC;
- put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn);
- put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn);
+ put_unaligned_be64(fcvport_port_name(lport->fcvport), &fdisc->fl_wwpn);
+ put_unaligned_be64(fcvport_node_name(lport->fcvport), &fdisc->fl_wwnn);
sp = &fdisc->fl_csp;
sp->sp_hi_ver = 0x20;
sp->sp_lo_ver = 0x20;
@@ -265,7 +265,7 @@ static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
memset(logo, 0, sizeof(*logo));
logo->fl_cmd = ELS_LOGO;
hton24(logo->fl_n_port_id, lport->port_id);
- logo->fl_n_port_wwn = htonll(lport->wwpn);
+ logo->fl_n_port_wwn = htonll(fcvport_port_name(lport->fcvport));
}
/**
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 0919409..8cd0c63 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -24,6 +24,7 @@
#include <linux/if.h>
#include <linux/percpu.h>
+#include <scsi/fc.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_bsg_fc.h>
@@ -144,6 +145,7 @@ enum fc_rport_event {
};
struct fc_rport_priv;
+struct fc_fcp_internal;
/**
* struct fc_rport_operations - Operations for a remote port
@@ -688,6 +690,19 @@ struct libfc_function_template {
void (*fcp_abort_io)(struct fc_lport *);
/*
+ * Scsi_Host tempate if this initiator is for SCSI-FCP
+ *
+ * STATUS: REQUIRED (if doing SCSI-FCP)
+ */
+ struct scsi_host_template *shost_template;
+
+ /*
+ * Let the LLD configure the Scsi_Host if it
+ * wants to.
+ */
+ void (*shost_config)(struct fc_lport *, struct fc_fcp_internal *);
+
+ /*
* Receive a request for the discovery layer.
*
* STATUS: OPTIONAL
@@ -720,6 +735,14 @@ struct libfc_function_template {
* STATUS: OPTIONAL
*/
void (*disc_stop_final) (struct fc_lport *);
+
+ void (*set_fcvport_symbolic_name)(struct fc_lport *);
+ void (*set_fcvport_node_name)(struct fc_lport *);
+ void (*set_fcvport_port_name)(struct fc_lport *);
+ void (*set_fcfabric_max_npiv_vports)(struct fc_lport *);
+
+ void (*get_vport_ids)(struct fc_lport *,
+ struct fc_vport_identifiers *);
};
/**
@@ -799,30 +822,23 @@ struct fc_disc {
*/
struct fc_lport {
/* Associations */
- struct Scsi_Host *host;
struct list_head ema_list;
struct fc_rport_priv *dns_rdata;
struct fc_rport_priv *ptp_rdata;
- void *scsi_priv;
struct fc_disc disc;
/* Virtual port information */
struct list_head vports;
- struct fc_vport *vport;
/* Operational Information */
struct libfc_function_template tt;
u8 link_up;
- u8 qfull;
enum fc_lport_state state;
unsigned long boot_time;
- struct fc_host_statistics host_stats;
struct fcoe_dev_stats *dev_stats;
u8 retry_count;
/* Fabric information */
- u64 wwpn;
- u64 wwnn;
unsigned int service_params;
unsigned int e_d_tov;
unsigned int r_a_tov;
@@ -844,14 +860,54 @@ struct fc_lport {
unsigned int lso_max;
struct fc_ns_fts fcts;
+ /* sysfs representation */
+ struct fc_fcport *fcport;
+ struct fc_fcfport *fcfport;
+ struct fc_fcfabric *fcfabric;
+ struct fc_fcvport *fcvport;
+ struct fc_fcpinit *fcpinit;
+
/* Miscellaneous */
struct mutex lp_mutex;
struct list_head list;
struct delayed_work retry_work;
+ struct fcfabric_function_template *fcfabric_f;
+ struct fcvport_function_template *fcvport_f;
+
u32 port_id;
+
+ void *scsi_priv;
+};
+
+/**
+ * struct fc_fcp_internal - FCP layer internal data
+ * @scsi_pkt_pool: Memory pool to draw FCP packets from
+ * @scsi_pkt_queue: Current FCP packets
+ * @last_can_queue_ramp_down_time: ramp down time
+ * @last_can_queue_ramp_up_time: ramp up time
+ * @max_can_queue: max can_queue size
+ */
+struct fc_fcp_internal {
+ mempool_t *scsi_pkt_pool;
+ struct list_head scsi_pkt_queue;
+ spinlock_t scsi_queue_lock;
+ unsigned long last_can_queue_ramp_down_time;
+ unsigned long last_can_queue_ramp_up_time;
+ int max_can_queue;
+
+ /* Associations */
+ struct fc_lport *lport;
+ struct Scsi_Host *host;
+
+ /* Operational Information */
+ u8 qfull;
+ struct fcpinit_statistics host_stats;
};
+#define fc_get_scsi_internal(x) ((struct fc_fcp_internal *)(x)->scsi_priv)
+
+
/*
* FC_LPORT HELPER FUNCTIONS
*****************************/
@@ -866,26 +922,6 @@ static inline int fc_lport_test_ready(struct fc_lport *lport)
}
/**
- * fc_set_wwnn() - Set the World Wide Node Name of a local port
- * @lport: The local port whose WWNN is to be set
- * @wwnn: The new WWNN
- */
-static inline void fc_set_wwnn(struct fc_lport *lport, u64 wwnn)
-{
- lport->wwnn = wwnn;
-}
-
-/**
- * fc_set_wwpn() - Set the World Wide Port Name of a local port
- * @lport: The local port whose WWPN is to be set
- * @wwnn: The new WWPN
- */
-static inline void fc_set_wwpn(struct fc_lport *lport, u64 wwnn)
-{
- lport->wwpn = wwnn;
-}
-
-/**
* fc_lport_state_enter() - Change a local port's state
* @lport: The local port whose state is to change
* @state: The new state
@@ -938,26 +974,30 @@ static inline void *lport_priv(const struct fc_lport *lport)
}
/**
- * libfc_host_alloc() - Allocate a Scsi_Host with room for a local port and
- * LLD private data
- * @sht: The SCSI host template
- * @priv_size: Size of private data
- *
- * Returns: libfc lport
+ * fc_lport_free() - Free a local port
+ * @lport: The local port to be free'd
*/
-static inline struct fc_lport *
-libfc_host_alloc(struct scsi_host_template *sht, int priv_size)
+static inline void fc_lport_free(struct fc_lport *lport)
+{
+ printk(KERN_ERR "RWL: fc_lport_free: kfree(lport)\n");
+ kfree(lport);
+}
+
+static inline struct fc_lport *fc_lport_alloc(int priv_size)
{
struct fc_lport *lport;
- struct Scsi_Host *shost;
- shost = scsi_host_alloc(sht, sizeof(*lport) + priv_size);
- if (!shost)
+ printk(KERN_ERR "RWL: libfc_lport_alloc: kzalloc(lport)\n");
+ lport = kzalloc(sizeof(struct fc_lport) + priv_size, GFP_KERNEL);
+ if (!lport)
return NULL;
- lport = shost_priv(shost);
- lport->host = shost;
+
+ printk(KERN_ERR "RWL: libfc_lport_alloc - allocated lport = %p\n",
+ lport);
+
INIT_LIST_HEAD(&lport->ema_list);
INIT_LIST_HEAD(&lport->vports);
+
return lport;
}
@@ -987,7 +1027,7 @@ void fc_vports_linkchange(struct fc_lport *);
int fc_lport_config(struct fc_lport *);
int fc_lport_reset(struct fc_lport *);
int fc_set_mfs(struct fc_lport *, u32 mfs);
-struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize);
+int libfc_vport_config(struct fc_lport *n_port, struct fc_lport *vn_port, struct fc_fcvport *);
struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id);
int fc_lport_bsg_request(struct fc_bsg_job *);
@@ -1054,9 +1094,10 @@ void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id);
/*
* Functions for fc_functions_template
*/
-void fc_get_host_speed(struct Scsi_Host *);
void fc_get_host_port_state(struct Scsi_Host *);
void fc_set_rport_loss_tmo(struct fc_rport *, u32 timeout);
-struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *);
+struct fcpinit_statistics *fc_get_host_stats(struct Scsi_Host *);
+
+void fc_lport_port_config(struct fc_fcport *fcport);
#endif /* _LIBFC_H_ */
^ permalink raw reply related [flat|nested] 10+ messages in thread