* [RFC PATCH 0/6] Work In Progress: FC sysfs
@ 2010-01-27 23:24 Robert Love
2010-01-27 23:24 ` [RFC PATCH 1/6] libfc: Remove unused fc_get_host_port_type Robert Love
` (6 more replies)
0 siblings, 7 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 series is the beginning of a FC sysfs reorganization. The new layout
as suggested in this post, http://marc.info/?l=linux-scsi&m=124404278711785&w=2,
creates more sysfs objects to expose FC session information and
decouples the FC sysfs layout from SCSI until FC attaches to the SCSI
mid-layer.
The first four patches in this series are just preparation patches
that have not been merged. They can mostly be ignored. The fifth patch
introduces FC sysfs and the last patch modifies libfc, libfcoe and fcoe
to use the new FC sysfs interface.
These patches move code out of scsi_transport_fc.[ch] and into individual
files for each of the new sysfs objects. Compilation creates a new
fc_sysfs.ko module. I'm not sure if this is a good overall approach, but
I wanted to make sure that I didn't overlook any relationships as I made
changes. This results in a patch that doesn't show a good progression of
changes, rather a big change combined with code moving from file(s) to
other file(s). This can be addressed when the patch series is further along
in development.
To review, it might be easier to apply the patches and look at
drivers/scsi/fc/ and include/scsi/fc.h.
Functionally both real and NPIV port creation and deletion is working under
libfc/fcoe, with most if not all attributes showing correct values. I did
not spend much time on error handling or cleanliness, these are things
that I'd prefer to address once I'm further along.
These patches create the following sysfs layout-
Device tree:
/sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
LDM tree:
/sys/class/fcport/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
Each object has redistributed attributes:
#ls /sys/devices/virtual/net/eth3.101/fcport1/
active_fc4s device fcfport_2001000deca31e81 maxframe_size power serial_number speed subsystem supported_classes supported_fc4s supported_speeds uevent
# ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/
fcfabric_0 power uevent
# ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/
fabric_name fcvport_0 fcvport_1 max_npiv_vports npiv_vports_inuse power uevent vport_create vport_delete
# ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/
host6 node_name port_id port_name port_type power roles symbolic_name uevent vport_last_state vport_state vport_type
# ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/
bsg fcpinit power rport-6:0-0 rport-6:0-2 scsi_host subsystem uevent
# ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/
host6
# ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
device issue_lip port_state power statistics subsystem tgtid_bind_type uevent
VN_Ports ports show up just like N_Ports: (notice fcvport_1, not fcvport_0)
# ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_1/
host7 node_name port_id port_name port_type power roles symbolic_name uevent vport_last_state vport_state vport_type
My open questions are:
1) How is the FC4 choice made?
If FC sysfs allows an FC HBA to support other FC4 types, then how and
when is the selection made? It seems that this decision would either
need to be hard-coded or provided by the user. fcoe.ko requires user
action to start a connection. It would be easy for us to also require
a FC4 selection (maybe it defaults to SCSI-FCP (init)). HW adapters
generally FLOGI on link up and do not require user interaction. How
would this decision be made?
2) How do I reorder fc_host and scsi_host?
Previously the fc_host is attached as a child of the scsi_host. The
new layout has the scsi_host as a child of fcpinit. These patches
have the fcpinit object created by the scsi transport and attribute
container code. I'm not sure if/how to re-order these objects, it
might require changes to the scsi transport and AC code.
3) What do I do about remote_ports?
Currently the remote_ports are created by the scsi transport and AC
code which places them as children of the fc_host. I believe this
problem is essentially the same as #2, but with remote ports instead
of the fc_host.
4) What should the FC sysfs objects be?
Should they be class objects? I just made them of type 'struct device'
to keep them as flexible as possible. I made the fcport a class object
so that it could be anchored at /sys/class/.
(last minute note: I just saw in the link referenced above, that the
objects were referred to as classes. I missed that initiatlly, is
there no concern about adding too many classes to /sys?)
5) How should the FC sysfs objects be named?
Currently I have two styles. The fcport, fcfabric and fcvport objects
are all enumerated. The fcfport is given a name from its WWPN/WWNN.
It's pretty ugly as is, and the naming needs more consideration.
I don't really like N_Ports being referred to as vports in sysfs either.
6) What about complicated relationships between objects?
Right now this layout cannot elegantly support multiple physical
ports connected to the same F_Port. Each port will have it's own
sysfs directory tree and the two trees will not converge even if
they share the same F_Port/fabric/etc... vports under a physical
port will show up under the physical port's sysfs directory tree.
7) Should vport_create/destroy be under fcfabric or fcport?
I've currently put the vport_create/destroy attributes under the
fcfabric. I think this is fine for now, since there are no
complicated object relationships being presented. There's a one to
one relationship between a fcport and a fcfabric so it's fairly
easy to go back to the fcport, which is needed to be passed to the
LLD so it can create a vport. If there were more than one fcport
per fcfabric it would complicate this. Should the
vport_create/destroy be moved to be attributes of the fcport instead
to avoid a potential lookup if things get more complicated in the
future?
8) Should the fcfport and fcfabric be consolidated?
The fcfport doesn't show much other than its name. The fcfabric
doesn't have many attributes either. Most of its attributes are
vport related. I could see adding some FIP information to the
fcfport, but I'm not sure we need two objects here, especially if
the vport attributes need to be moved to the fcport.
9) Is this change worth all of the changes that will need to happen?
This is probably the most difficult question. I view this change as
positive overall, but it's very heavy lifting. Not only does the
FC transport need an overhaul, but it looks like the scsi transport
and AC code might need some additions. Every HBA will need to be
modified and every HBA's HBAAPI vendor library will need to change
too. (I hope this would be a catalyst to move to an OS library that
everyone shares)
I'd like to hear other opinions about this because this really is
going to be something that all HBAs will need to be involved in.
---
Robert Love (6):
libfc, libfcoe, fcoe: Make use of FC sysfs
fc_sysfs: Rearrange the FC transport to create FC sysfs
libfc: Move the port_id into lport
fcoe: move link speed checking into its own routine
libfc: Remove extra pointer check
libfc: Remove unused fc_get_host_port_type
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/fcoe/fcoe.c | 558 ++++++++++-----
drivers/scsi/fcoe/libfcoe.c | 55 +
drivers/scsi/libfc/fc_disc.c | 6
drivers/scsi/libfc/fc_elsct.c | 2
drivers/scsi/libfc/fc_exch.c | 4
drivers/scsi/libfc/fc_fcp.c | 145 ++--
drivers/scsi/libfc/fc_libfc.h | 32 -
drivers/scsi/libfc/fc_lport.c | 208 +++---
drivers/scsi/libfc/fc_npiv.c | 56 +-
drivers/scsi/libfc/fc_rport.c | 12
drivers/scsi/scsi_transport_fc.c | 1411 ++++++--------------------------------
include/scsi/fc.h | 460 ++++++++++++
include/scsi/fc_encode.h | 48 +
include/scsi/libfc.h | 130 ++--
include/scsi/scsi_transport_fc.h | 329 ++-------
25 files changed, 2893 insertions(+), 1936 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
--
//Rob
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC PATCH 1/6] libfc: Remove unused fc_get_host_port_type
2010-01-27 23:24 [RFC PATCH 0/6] Work In Progress: FC sysfs Robert Love
@ 2010-01-27 23:24 ` Robert Love
2010-01-27 23:24 ` [RFC PATCH 2/6] libfc: Remove extra pointer check Robert Love
` (5 subsequent siblings)
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
Remove an unused routine.
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_lport.c | 11 -----------
include/scsi/libfc.h | 1 -
2 files changed, 0 insertions(+), 12 deletions(-)
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 7ec8ce7..d35fc49 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -240,17 +240,6 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
}
/**
- * fc_get_host_port_type() - Return the port type of the given Scsi_Host
- * @shost: The SCSI host whose port type is to be determined
- */
-void fc_get_host_port_type(struct Scsi_Host *shost)
-{
- /* TODO - currently just NPORT */
- fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
-}
-EXPORT_SYMBOL(fc_get_host_port_type);
-
-/**
* fc_get_host_port_state() - Return the port state of the given Scsi_Host
* @shost: The SCSI host whose port state is to be determined
*/
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 4b912ee..e31150a 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -1053,7 +1053,6 @@ 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_type(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 *);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH 2/6] libfc: Remove extra pointer check
2010-01-27 23:24 [RFC PATCH 0/6] Work In Progress: FC sysfs Robert Love
2010-01-27 23:24 ` [RFC PATCH 1/6] libfc: Remove unused fc_get_host_port_type Robert Love
@ 2010-01-27 23:24 ` Robert Love
2010-01-27 23:24 ` [RFC PATCH 3/6] fcoe: move link speed checking into its own routine Robert Love
` (4 subsequent siblings)
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
The fcf pointer is checked immediately after this call making this
call redundant. Remote the first check.
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/libfcoe.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 511cb6b..5dae90e 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -941,8 +941,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
u32 desc_mask;
LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
- if (!fcf)
- return;
+
if (!fcf || !fc_host_port_id(lport->host))
return;
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH 3/6] fcoe: move link speed checking into its own routine
2010-01-27 23:24 [RFC PATCH 0/6] Work In Progress: FC sysfs Robert Love
2010-01-27 23:24 ` [RFC PATCH 1/6] libfc: Remove unused fc_get_host_port_type Robert Love
2010-01-27 23:24 ` [RFC PATCH 2/6] libfc: Remove extra pointer check Robert Love
@ 2010-01-27 23:24 ` Robert Love
2010-01-27 23:24 ` [RFC PATCH 4/6] libfc: Move the port_id into lport Robert Love
` (3 subsequent siblings)
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
It doesn't make sense to update the link speed in the is_link_ok()
routine. Move it to it's own routine and acquire the device speed
when we're configuring the device initially as well as if there are
any netdev events received.
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 42 +++++++++++++++++++++++++++++-------------
1 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 10be9f3..a719994 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -73,6 +73,7 @@ static int fcoe_rcv(struct sk_buff *, struct net_device *,
static int fcoe_percpu_receive_thread(void *);
static void fcoe_clean_pending_queue(struct fc_lport *);
static void fcoe_percpu_clean(struct fc_lport *);
+static int fcoe_link_speed_update(struct fc_lport *);
static int fcoe_link_ok(struct fc_lport *);
static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
@@ -628,6 +629,8 @@ 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:
@@ -1834,6 +1837,9 @@ static int fcoe_device_notification(struct notifier_block *notifier,
FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
"from netdev netlink\n", event);
}
+
+ fcoe_link_speed_update(lport);
+
if (link_possible && !fcoe_link_ok(lport))
fcoe_ctlr_link_up(&fcoe->ctlr);
else if (fcoe_ctlr_link_down(&fcoe->ctlr)) {
@@ -2115,27 +2121,20 @@ out_nodev:
}
/**
- * fcoe_link_ok() - Check if the link is OK for a local port
- * @lport: The local port to check link on
- *
- * Any permanently-disqualifying conditions have been previously checked.
- * This also updates the speed setting, which may change with link for 100/1000.
+ * fcoe_link_speed_update() - Update the supported and actual link speeds
+ * @lport: The local port to update speeds for
*
- * This function should probably be checking for PAUSE support at some point
- * in the future. Currently Per-priority-pause is not determinable using
- * ethtool, so we shouldn't be restrictive until that problem is resolved.
- *
- * Returns: 0 if link is OK for use by FCoE.
+ * Returns: 0 if the ethtool query was successful
+ * -1 if the ethtool query failed
*
*/
-int fcoe_link_ok(struct fc_lport *lport)
+int fcoe_link_speed_update(struct fc_lport *lport)
{
struct fcoe_port *port = lport_priv(lport);
struct net_device *netdev = port->fcoe->netdev;
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
- if ((netdev->flags & IFF_UP) && netif_carrier_ok(netdev) &&
- (!dev_ethtool_get_settings(netdev, &ecmd))) {
+ if (!dev_ethtool_get_settings(netdev, &ecmd)) {
lport->link_supported_speeds &=
~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
@@ -2155,6 +2154,23 @@ int fcoe_link_ok(struct fc_lport *lport)
}
/**
+ * fcoe_link_ok() - Check if the link is OK for a local port
+ * @lport: The local port to check link on
+ *
+ * Returns: 0 if link is UP and OK, -1 if not
+ *
+ */
+int fcoe_link_ok(struct fc_lport *lport)
+{
+ struct fcoe_port *port = lport_priv(lport);
+ struct net_device *netdev = port->fcoe->netdev;
+
+ if ((netdev->flags & IFF_UP) && netif_carrier_ok(netdev))
+ return 0;
+ return -1;
+}
+
+/**
* fcoe_percpu_clean() - Clear all pending skbs for an local port
* @lport: The local port whose skbs are to be cleared
*
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH 4/6] libfc: Move the port_id into lport
2010-01-27 23:24 [RFC PATCH 0/6] Work In Progress: FC sysfs Robert Love
` (2 preceding siblings ...)
2010-01-27 23:24 ` [RFC PATCH 3/6] fcoe: move link speed checking into its own routine Robert Love
@ 2010-01-27 23:24 ` Robert Love
2010-01-27 23:24 ` [RFC PATCH 5/6] fc_sysfs: Rearrange the FC transport to create FC sysfs Robert Love
` (2 subsequent siblings)
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 probably isn't complete. libfc was relying
too much on members of the fc_host. Since the later
patches in this series reduce libfc's dependecy on the
scsi-ml I had to duplicate some of the fc_host
information in the lport.
port_id was one member that I duplicated in the fc_lport,
but I think this patch should be broader and clearly
separate the operational data (i.e. the stuff in lport)
from the presentation layer.
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/libfcoe.c | 9 ++++-----
drivers/scsi/libfc/fc_disc.c | 2 +-
drivers/scsi/libfc/fc_elsct.c | 2 +-
drivers/scsi/libfc/fc_exch.c | 2 +-
drivers/scsi/libfc/fc_fcp.c | 15 +++++++--------
drivers/scsi/libfc/fc_libfc.h | 2 +-
drivers/scsi/libfc/fc_lport.c | 14 +++++++-------
drivers/scsi/libfc/fc_npiv.c | 4 ++--
include/scsi/fc_encode.h | 18 +++++++-----------
include/scsi/libfc.h | 2 ++
10 files changed, 33 insertions(+), 37 deletions(-)
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 5dae90e..a554672 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -348,7 +348,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
fcf = fip->sel_fcf;
lp = fip->lp;
- if (!fcf || !fc_host_port_id(lp->host))
+ if (!fcf || !lp->port_id)
return;
len = sizeof(*kal) + ports * sizeof(*vn);
@@ -379,7 +379,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
vn->fd_desc.fip_dtype = FIP_DT_VN_ID;
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, fc_host_port_id(lp->host));
+ hton24(vn->fd_fc_id, lp->port_id);
put_unaligned_be64(lp->wwpn, &vn->fd_wwpn);
}
skb_put(skb, len);
@@ -942,7 +942,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
- if (!fcf || !fc_host_port_id(lport->host))
+ if (!fcf || !lport->port_id)
return;
/*
@@ -980,8 +980,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
if (compare_ether_addr(vp->fd_mac,
fip->get_src_addr(lport)) == 0 &&
get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn &&
- ntoh24(vp->fd_fc_id) ==
- fc_host_port_id(lport->host))
+ ntoh24(vp->fd_fc_id) == lport->port_id)
desc_mask &= ~BIT(FIP_DT_VN_ID);
break;
default:
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 9b0a519..dd703fd 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -439,7 +439,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
ids.port_id = ntoh24(np->fp_fid);
ids.port_name = ntohll(np->fp_wwpn);
- if (ids.port_id != fc_host_port_id(lport->host) &&
+ if (ids.port_id != lport->port_id &&
ids.port_name != lport->wwpn) {
rdata = lport->tt.rport_create(lport, ids.port_id);
if (rdata) {
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index 5374872..e9412b7 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -63,7 +63,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did,
return NULL;
}
- fc_fill_fc_hdr(fp, r_ctl, did, fc_host_port_id(lport->host), fh_type,
+ fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec);
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 7f43647..425f4dd 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1944,7 +1944,7 @@ static void fc_exch_rrq(struct fc_exch *ep)
did = ep->sid;
fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, did,
- fc_host_port_id(lport->host), FC_TYPE_ELS,
+ lport->port_id, FC_TYPE_ELS,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
if (fc_exch_seq_send(lport, fp, fc_exch_rrq_resp, NULL, ep,
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 6fde2fa..d2da31e 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -483,7 +483,7 @@ crc_err:
if (stats->InvalidCRCCount++ < 5)
printk(KERN_WARNING "libfc: CRC error on data "
"frame for port (%6x)\n",
- fc_host_port_id(lport->host));
+ lport->port_id);
/*
* Assume the frame is total garbage.
* We may have copied it over the good part
@@ -1099,7 +1099,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
rpriv = rport->dd_data;
fc_fill_fc_hdr(fp, FC_RCTL_DD_UNSOL_CMD, rport->port_id,
- fc_host_port_id(rpriv->local_port->host), FC_TYPE_FCP,
+ rpriv->local_port->port_id, FC_TYPE_FCP,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy,
@@ -1372,7 +1372,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
fr_seq(fp) = fsp->seq_ptr;
fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id,
- fc_host_port_id(rpriv->local_port->host), FC_TYPE_ELS,
+ rpriv->local_port->port_id, FC_TYPE_ELS,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC,
fc_fcp_rec_resp, fsp,
@@ -1630,7 +1630,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
srr->srr_rel_off = htonl(offset);
fc_fill_fc_hdr(fp, FC_RCTL_ELS4_REQ, rport->port_id,
- fc_host_port_id(rpriv->local_port->host), FC_TYPE_FCP,
+ rpriv->local_port->port_id, FC_TYPE_FCP,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL,
@@ -2075,12 +2075,11 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd)
if (fc_fcp_lport_queue_ready(lport)) {
shost_printk(KERN_INFO, shost, "libfc: Host reset succeeded "
- "on port (%6x)\n", fc_host_port_id(lport->host));
+ "on port (%6x)\n", lport->port_id);
return SUCCESS;
} else {
shost_printk(KERN_INFO, shost, "libfc: Host reset failed, "
- "port (%6x) is not ready.\n",
- fc_host_port_id(lport->host));
+ "port (%6x) is not ready.\n", lport->port_id);
return FAILED;
}
}
@@ -2165,7 +2164,7 @@ void fc_fcp_destroy(struct fc_lport *lport)
if (!list_empty(&si->scsi_pkt_queue))
printk(KERN_ERR "libfc: Leaked SCSI packets when destroying "
- "port (%6x)\n", fc_host_port_id(lport->host));
+ "port (%6x)\n", lport->port_id);
mempool_destroy(si->scsi_pkt_pool);
kfree(si);
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
index 741fd5c..a79c42d 100644
--- a/drivers/scsi/libfc/fc_libfc.h
+++ b/drivers/scsi/libfc/fc_libfc.h
@@ -47,7 +47,7 @@ extern unsigned int fc_debug_logging;
FC_CHECK_LOGGING(FC_LPORT_LOGGING, \
printk(KERN_INFO "host%u: lport %6x: " fmt, \
(lport)->host->host_no, \
- fc_host_port_id((lport)->host), ##args))
+ (lport)->port_id, ##args))
#define FC_DISC_DBG(disc, fmt, args...) \
FC_CHECK_LOGGING(FC_DISC_LOGGING, \
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index d35fc49..9da4c15 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -561,7 +561,7 @@ 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, fc_host_port_id(lport->host));
+ lport->host->host_no, lport->port_id);
mutex_lock(&lport->lp_mutex);
__fc_linkup(lport);
@@ -591,7 +591,7 @@ 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, fc_host_port_id(lport->host));
+ lport->host->host_no, lport->port_id);
mutex_lock(&lport->lp_mutex);
__fc_linkdown(lport);
@@ -693,7 +693,7 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
case DISC_EV_FAILED:
printk(KERN_ERR "host%d: libfc: "
"Discovery failed for port (%6x)\n",
- lport->host->host_no, fc_host_port_id(lport->host));
+ lport->host->host_no, lport->port_id);
mutex_lock(&lport->lp_mutex);
fc_lport_enter_reset(lport);
mutex_unlock(&lport->lp_mutex);
@@ -741,7 +741,7 @@ static void fc_lport_set_port_id(struct fc_lport *lport, u32 port_id,
printk(KERN_INFO "host%d: Assigned Port ID %6x\n",
lport->host->host_no, port_id);
- fc_host_port_id(lport->host) = port_id;
+ lport->port_id = port_id;
if (lport->tt.lport_set_port_id)
lport->tt.lport_set_port_id(lport, port_id, fp);
}
@@ -942,7 +942,7 @@ static void fc_lport_reset_locked(struct fc_lport *lport)
lport->tt.exch_mgr_reset(lport, 0, 0);
fc_host_fabric_name(lport->host) = 0;
- if (fc_host_port_id(lport->host))
+ if (lport->port_id)
fc_lport_set_port_id(lport, 0, NULL);
}
@@ -1687,7 +1687,7 @@ static int fc_lport_els_request(struct fc_bsg_job *job,
fh = fc_frame_header_get(fp);
fh->fh_r_ctl = FC_RCTL_ELS_REQ;
hton24(fh->fh_d_id, did);
- hton24(fh->fh_s_id, fc_host_port_id(lport->host));
+ hton24(fh->fh_s_id, lport->port_id);
fh->fh_type = FC_TYPE_ELS;
hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ |
FC_FC_END_SEQ | FC_FC_SEQ_INIT);
@@ -1747,7 +1747,7 @@ static int fc_lport_ct_request(struct fc_bsg_job *job,
fh = fc_frame_header_get(fp);
fh->fh_r_ctl = FC_RCTL_DD_UNSOL_CTL;
hton24(fh->fh_d_id, did);
- hton24(fh->fh_s_id, fc_host_port_id(lport->host));
+ hton24(fh->fh_s_id, lport->port_id);
fh->fh_type = FC_TYPE_CT;
hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ |
FC_FC_END_SEQ | FC_FC_SEQ_INIT);
diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c
index c68f6c7..0e90f00 100644
--- a/drivers/scsi/libfc/fc_npiv.c
+++ b/drivers/scsi/libfc/fc_npiv.c
@@ -69,12 +69,12 @@ struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id)
struct fc_lport *lport = NULL;
struct fc_lport *vn_port;
- if (fc_host_port_id(n_port->host) == port_id)
+ if (n_port->port_id == port_id)
return n_port;
mutex_lock(&n_port->lp_mutex);
list_for_each_entry(vn_port, &n_port->vports, list) {
- if (fc_host_port_id(vn_port->host) == port_id) {
+ if (vn_port->port_id == port_id) {
lport = vn_port;
break;
}
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index 8eb0a0f..9b4867c 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -74,7 +74,7 @@ static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
adisc->adisc_cmd = ELS_ADISC;
put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
- hton24(adisc->adisc_port_id, fc_host_port_id(lport->host));
+ hton24(adisc->adisc_port_id, lport->port_id);
}
/**
@@ -127,15 +127,13 @@ static inline int fc_ct_fill(struct fc_lport *lport,
case FC_NS_RFT_ID:
ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft));
- hton24(ct->payload.rft.fid.fp_fid,
- fc_host_port_id(lport->host));
+ hton24(ct->payload.rft.fid.fp_fid, lport->port_id);
ct->payload.rft.fts = lport->fcts;
break;
case FC_NS_RFF_ID:
ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id));
- hton24(ct->payload.rff.fr_fid.fp_fid,
- fc_host_port_id(lport->host));
+ hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id);
ct->payload.rff.fr_type = FC_TYPE_FCP;
if (lport->service_params & FCP_SPPF_INIT_FCN)
ct->payload.rff.fr_feat = FCP_FEAT_INIT;
@@ -145,16 +143,14 @@ 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,
- fc_host_port_id(lport->host));
+ hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id);
put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn);
break;
case FC_NS_RSPN_ID:
len = strnlen(fc_host_symbolic_name(lport->host), 255);
ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len);
- hton24(ct->payload.spn.fr_fid.fp_fid,
- fc_host_port_id(lport->host));
+ hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id);
strncpy(ct->payload.spn.fr_name,
fc_host_symbolic_name(lport->host), len);
ct->payload.spn.fr_name_len = len;
@@ -268,7 +264,7 @@ static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
logo = fc_frame_payload_get(fp, sizeof(*logo));
memset(logo, 0, sizeof(*logo));
logo->fl_cmd = ELS_LOGO;
- hton24(logo->fl_n_port_id, fc_host_port_id(lport->host));
+ hton24(logo->fl_n_port_id, lport->port_id);
logo->fl_n_port_wwn = htonll(lport->wwpn);
}
@@ -295,7 +291,7 @@ static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
rec = fc_frame_payload_get(fp, sizeof(*rec));
memset(rec, 0, sizeof(*rec));
rec->rec_cmd = ELS_REC;
- hton24(rec->rec_s_id, fc_host_port_id(lport->host));
+ hton24(rec->rec_s_id, lport->port_id);
rec->rec_ox_id = htons(ep->oxid);
rec->rec_rx_id = htons(ep->rxid);
}
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index e31150a..0919409 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -848,6 +848,8 @@ struct fc_lport {
struct mutex lp_mutex;
struct list_head list;
struct delayed_work retry_work;
+
+ u32 port_id;
};
/*
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [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
* Re: [RFC PATCH 0/6] Work In Progress: FC sysfs
2010-01-27 23:24 [RFC PATCH 0/6] Work In Progress: FC sysfs Robert Love
` (5 preceding siblings ...)
2010-01-27 23:24 ` [RFC PATCH 6/6] libfc, libfcoe, fcoe: Make use of " Robert Love
@ 2010-01-28 16:01 ` Hannes Reinecke
2010-01-29 19:31 ` Robert Love
6 siblings, 1 reply; 10+ messages in thread
From: Hannes Reinecke @ 2010-01-28 16:01 UTC (permalink / raw)
To: Robert Love; +Cc: linux-scsi, james.smart, giridhar.malavali
Robert Love wrote:
> This series is the beginning of a FC sysfs reorganization. The new layout
> as suggested in this post, http://marc.info/?l=linux-scsi&m=124404278711785&w=2,
> creates more sysfs objects to expose FC session information and
> decouples the FC sysfs layout from SCSI until FC attaches to the SCSI
> mid-layer.
>
> The first four patches in this series are just preparation patches
> that have not been merged. They can mostly be ignored. The fifth patch
> introduces FC sysfs and the last patch modifies libfc, libfcoe and fcoe
> to use the new FC sysfs interface.
>
> These patches move code out of scsi_transport_fc.[ch] and into individual
> files for each of the new sysfs objects. Compilation creates a new
> fc_sysfs.ko module. I'm not sure if this is a good overall approach, but
> I wanted to make sure that I didn't overlook any relationships as I made
> changes. This results in a patch that doesn't show a good progression of
> changes, rather a big change combined with code moving from file(s) to
> other file(s). This can be addressed when the patch series is further along
> in development.
>
> To review, it might be easier to apply the patches and look at
> drivers/scsi/fc/ and include/scsi/fc.h.
>
> Functionally both real and NPIV port creation and deletion is working under
> libfc/fcoe, with most if not all attributes showing correct values. I did
> not spend much time on error handling or cleanliness, these are things
> that I'd prefer to address once I'm further along.
>
> These patches create the following sysfs layout-
>
> Device tree:
> /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
>
> LDM tree:
> /sys/class/fcport/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
>
> Each object has redistributed attributes:
> #ls /sys/devices/virtual/net/eth3.101/fcport1/
> active_fc4s device fcfport_2001000deca31e81 maxframe_size power serial_number speed subsystem supported_classes supported_fc4s supported_speeds uevent
>
> # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/
> fcfabric_0 power uevent
>
Please don't.
Do _not_ use physical names in the path names; rather the logical names should be used.
So something like
/sys/devices/virtual/net/eth3.101/fcport1/fcfport-1:0/
would be preferred.
> # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/
> fabric_name fcvport_0 fcvport_1 max_npiv_vports npiv_vports_inuse power uevent vport_create vport_delete
>
Consistent numbering. Either use '_' as a separator always or for none.
This mix-up doesn't make sense.
And, why doesn't the fcfport doesn't show up under the fabric?
One would assume that the fcfport is part of the fabric, too.
And what about the remote ports? Do they not participate in the fabric?
If the 'fcfabric' element is _not_ the actual fabric I would get rid of it altogether as it'll only serve to confuse
the users. Like just has been happened with me :-)
> # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/
> host6 node_name port_id port_name port_type power roles symbolic_name uevent vport_last_state vport_state vport_type
>
> # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/
> bsg fcpinit power rport-6:0-0 rport-6:0-2 scsi_host subsystem uevent
>
See above. Why are the remote ports grouped under the 'host', and not under the fabric?
> # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/
> host6
>
fcpinit? What's this for?
> # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
> device issue_lip port_state power statistics subsystem tgtid_bind_type uevent
>
> VN_Ports ports show up just like N_Ports: (notice fcvport_1, not fcvport_0)
> # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_1/
> host7 node_name port_id port_name port_type power roles symbolic_name uevent vport_last_state vport_state vport_type
>
>
> My open questions are:
>
> 1) How is the FC4 choice made?
>
> If FC sysfs allows an FC HBA to support other FC4 types, then how and
> when is the selection made? It seems that this decision would either
> need to be hard-coded or provided by the user. fcoe.ko requires user
> action to start a connection. It would be easy for us to also require
> a FC4 selection (maybe it defaults to SCSI-FCP (init)). HW adapters
> generally FLOGI on link up and do not require user interaction. How
> would this decision be made?
>
I would consider FCP only currently. Other types would be handled by
different subsystems anyway (ie net), which again have a totally different
sysfs layout.
> 2) How do I reorder fc_host and scsi_host?
>
> Previously the fc_host is attached as a child of the scsi_host. The
> new layout has the scsi_host as a child of fcpinit. These patches
> have the fcpinit object created by the scsi transport and attribute
> container code. I'm not sure if/how to re-order these objects, it
> might require changes to the scsi transport and AC code.
>
Easiest would be to use the same counter, so that a fc_host preallocates
a scsi_host id, too. Not sure if that's possible, though.
Alternatively you could create a scsi_host, but _not_ register it with
sysfs. This way you would have a number preallocated, too.
And when restricting this layout to FCP we will allocate a scsi_host
anyway...
> 3) What do I do about remote_ports?
>
> Currently the remote_ports are created by the scsi transport and AC
> code which places them as children of the fc_host. I believe this
> problem is essentially the same as #2, but with remote ports instead
> of the fc_host.
>
We should try to avoid separate directories for objects which ultimatively
map onto the same device. IE it should be possible to gather _all_
information from walking up the devpath only, without having to recurse
on other side directories.
This way we can match on the various attributes from udev rules; with
separate directories this is impossible without a helper script.
I'm happy to mail my 'path_id' script around, just to get you an
idea where you end up with the separate directory approach :-)
> 4) What should the FC sysfs objects be?
>
> Should they be class objects? I just made them of type 'struct device'
> to keep them as flexible as possible. I made the fcport a class object
> so that it could be anchored at /sys/class/.
>
> (last minute note: I just saw in the link referenced above, that the
> objects were referred to as classes. I missed that initiatlly, is
> there no concern about adding too many classes to /sys?)
>
The 'class' and 'device' distinction is basically gone with the newer
sysfs code.
The elements in 'class' are just pointers into the 'device' structure.
> 5) How should the FC sysfs objects be named?
>
> Currently I have two styles. The fcport, fcfabric and fcvport objects
> are all enumerated. The fcfport is given a name from its WWPN/WWNN.
> It's pretty ugly as is, and the naming needs more consideration.
>
As mentioned above, yes, it is. Please use logical names.
> I don't really like N_Ports being referred to as vports in sysfs either.
>
> 6) What about complicated relationships between objects?
>
> Right now this layout cannot elegantly support multiple physical
> ports connected to the same F_Port. Each port will have it's own
> sysfs directory tree and the two trees will not converge even if
> they share the same F_Port/fabric/etc... vports under a physical
> port will show up under the physical port's sysfs directory tree.
>
> 7) Should vport_create/destroy be under fcfabric or fcport?
>
> I've currently put the vport_create/destroy attributes under the
> fcfabric. I think this is fine for now, since there are no
> complicated object relationships being presented. There's a one to
> one relationship between a fcport and a fcfabric so it's fairly
> easy to go back to the fcport, which is needed to be passed to the
> LLD so it can create a vport. If there were more than one fcport
> per fcfabric it would complicate this. Should the
> vport_create/destroy be moved to be attributes of the fcport instead
> to avoid a potential lookup if things get more complicated in the
> future?
>
Once the fcfabric is consolidated with fcfport they'll end up under
fcport anyway :-)
> 8) Should the fcfport and fcfabric be consolidated?
>
> The fcfport doesn't show much other than its name. The fcfabric
> doesn't have many attributes either. Most of its attributes are
> vport related. I could see adding some FIP information to the
> fcfport, but I'm not sure we need two objects here, especially if
> the vport attributes need to be moved to the fcport.
>
See above. Yes.
> 9) Is this change worth all of the changes that will need to happen?
>
> This is probably the most difficult question. I view this change as
> positive overall, but it's very heavy lifting. Not only does the
> FC transport need an overhaul, but it looks like the scsi transport
> and AC code might need some additions. Every HBA will need to be
> modified and every HBA's HBAAPI vendor library will need to change
> too. (I hope this would be a catalyst to move to an OS library that
> everyone shares)
>
> I'd like to hear other opinions about this because this really is
> going to be something that all HBAs will need to be involved in.
>
I think it's quite a valid goal.
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Markus Rex, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 0/6] Work In Progress: FC sysfs
2010-01-28 16:01 ` [RFC PATCH 0/6] Work In Progress: " Hannes Reinecke
@ 2010-01-29 19:31 ` Robert Love
2010-02-02 13:06 ` Christof Schmitt
0 siblings, 1 reply; 10+ messages in thread
From: Robert Love @ 2010-01-29 19:31 UTC (permalink / raw)
To: Hannes Reinecke
Cc: linux-scsi@vger.kernel.org, james.smart@emulex.com,
giridhar.malavali@qlogic.com
On Thu, 2010-01-28 at 08:01 -0800, Hannes Reinecke wrote:
> Robert Love wrote:
> > This series is the beginning of a FC sysfs reorganization. The new layout
> > as suggested in this post, http://marc.info/?l=linux-scsi&m=124404278711785&w=2,
> > creates more sysfs objects to expose FC session information and
> > decouples the FC sysfs layout from SCSI until FC attaches to the SCSI
> > mid-layer.
> >
> > The first four patches in this series are just preparation patches
> > that have not been merged. They can mostly be ignored. The fifth patch
> > introduces FC sysfs and the last patch modifies libfc, libfcoe and fcoe
> > to use the new FC sysfs interface.
> >
> > These patches move code out of scsi_transport_fc.[ch] and into individual
> > files for each of the new sysfs objects. Compilation creates a new
> > fc_sysfs.ko module. I'm not sure if this is a good overall approach, but
> > I wanted to make sure that I didn't overlook any relationships as I made
> > changes. This results in a patch that doesn't show a good progression of
> > changes, rather a big change combined with code moving from file(s) to
> > other file(s). This can be addressed when the patch series is further along
> > in development.
> >
> > To review, it might be easier to apply the patches and look at
> > drivers/scsi/fc/ and include/scsi/fc.h.
> >
> > Functionally both real and NPIV port creation and deletion is working under
> > libfc/fcoe, with most if not all attributes showing correct values. I did
> > not spend much time on error handling or cleanliness, these are things
> > that I'd prefer to address once I'm further along.
> >
> > These patches create the following sysfs layout-
> >
> > Device tree:
> > /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
> >
> > LDM tree:
> > /sys/class/fcport/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
> >
> > Each object has redistributed attributes:
> > #ls /sys/devices/virtual/net/eth3.101/fcport1/
> > active_fc4s device fcfport_2001000deca31e81 maxframe_size power serial_number speed subsystem supported_classes supported_fc4s supported_speeds uevent
> >
> > # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/
> > fcfabric_0 power uevent
> >
>
> Please don't.
> Do _not_ use physical names in the path names; rather the logical names should be used.
> So something like
> /sys/devices/virtual/net/eth3.101/fcport1/fcfport-1:0/
>
> would be preferred.
>
Did you put "1:0" to indicate that it's the 0th fcfport on the 1st
fcport? Isn't the the relationship of the fcfport0 being a child of the
fcport1 enough?
It seems to be redundant to me, but I might be missing something.
> > # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/
> > fabric_name fcvport_0 fcvport_1 max_npiv_vports npiv_vports_inuse power uevent vport_create vport_delete
> >
> Consistent numbering. Either use '_' as a separator always or for none.
> This mix-up doesn't make sense.
>
> And, why doesn't the fcfport doesn't show up under the fabric?
> One would assume that the fcfport is part of the fabric, too.
>
> And what about the remote ports? Do they not participate in the fabric?
>
> If the 'fcfabric' element is _not_ the actual fabric I would get rid of it altogether as it'll only serve to confuse
> the users. Like just has been happened with me :-)
>
Yeah, they should be under the fcfabric. This work is just incomplete in
that area.
> > # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/
> > host6 node_name port_id port_name port_type power roles symbolic_name uevent vport_last_state vport_state vport_type
> >
> > # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/
> > bsg fcpinit power rport-6:0-0 rport-6:0-2 scsi_host subsystem uevent
> >
> See above. Why are the remote ports grouped under the 'host', and not under the fabric?
>
> > # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/
> > host6
> >
> fcpinit? What's this for?
>
It had been suggested. I imagine having a fcptarg that hooks into stgt
at some point.
I don't have any attributes in mind for the fcpinit or fcptarg right
now. Also, I'm still allocating libfc's fcp private data with the
scsi_host, so fcpinit is pretty hollow right now. I might just leave it
as a placeholder for the short-term.
Whether fcpinit should exist or not is related to the open item below
regarding the FC4 decision. If there is eventually a fcpinit and fcptarg
there would need to be a mechanism to choose between the two.
> > # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_0/host6/fcpinit/host6/
> > device issue_lip port_state power statistics subsystem tgtid_bind_type uevent
> >
> > VN_Ports ports show up just like N_Ports: (notice fcvport_1, not fcvport_0)
> > # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/fcvport_1/
> > host7 node_name port_id port_name port_type power roles symbolic_name uevent vport_last_state vport_state vport_type
> >
>
> >
> > My open questions are:
> >
> > 1) How is the FC4 choice made?
> >
> > If FC sysfs allows an FC HBA to support other FC4 types, then how and
> > when is the selection made? It seems that this decision would either
> > need to be hard-coded or provided by the user. fcoe.ko requires user
> > action to start a connection. It would be easy for us to also require
> > a FC4 selection (maybe it defaults to SCSI-FCP (init)). HW adapters
> > generally FLOGI on link up and do not require user interaction. How
> > would this decision be made?
> >
> I would consider FCP only currently. Other types would be handled by
> different subsystems anyway (ie net), which again have a totally different
> sysfs layout.
>
> > 2) How do I reorder fc_host and scsi_host?
> >
> > Previously the fc_host is attached as a child of the scsi_host. The
> > new layout has the scsi_host as a child of fcpinit. These patches
> > have the fcpinit object created by the scsi transport and attribute
> > container code. I'm not sure if/how to re-order these objects, it
> > might require changes to the scsi transport and AC code.
> >
> Easiest would be to use the same counter, so that a fc_host preallocates
> a scsi_host id, too. Not sure if that's possible, though.
> Alternatively you could create a scsi_host, but _not_ register it with
> sysfs. This way you would have a number preallocated, too.
> And when restricting this layout to FCP we will allocate a scsi_host
> anyway...
>
I'll play around with this. Thanks for the suggestions.
> > 3) What do I do about remote_ports?
> >
> > Currently the remote_ports are created by the scsi transport and AC
> > code which places them as children of the fc_host. I believe this
> > problem is essentially the same as #2, but with remote ports instead
> > of the fc_host.
> >
> We should try to avoid separate directories for objects which ultimatively
> map onto the same device. IE it should be possible to gather _all_
> information from walking up the devpath only, without having to recurse
> on other side directories.
Sounds good.
> This way we can match on the various attributes from udev rules; with
> separate directories this is impossible without a helper script.
>
> I'm happy to mail my 'path_id' script around, just to get you an
> idea where you end up with the separate directory approach :-)
>
> > 4) What should the FC sysfs objects be?
> >
> > Should they be class objects? I just made them of type 'struct device'
> > to keep them as flexible as possible. I made the fcport a class object
> > so that it could be anchored at /sys/class/.
> >
> > (last minute note: I just saw in the link referenced above, that the
> > objects were referred to as classes. I missed that initiatlly, is
> > there no concern about adding too many classes to /sys?)
> >
> The 'class' and 'device' distinction is basically gone with the newer
> sysfs code.
> The elements in 'class' are just pointers into the 'device' structure.
>
> > 5) How should the FC sysfs objects be named?
> >
> > Currently I have two styles. The fcport, fcfabric and fcvport objects
> > are all enumerated. The fcfport is given a name from its WWPN/WWNN.
> > It's pretty ugly as is, and the naming needs more consideration.
> >
> As mentioned above, yes, it is. Please use logical names.
>
> > I don't really like N_Ports being referred to as vports in sysfs either.
> >
> > 6) What about complicated relationships between objects?
> >
> > Right now this layout cannot elegantly support multiple physical
> > ports connected to the same F_Port. Each port will have it's own
> > sysfs directory tree and the two trees will not converge even if
> > they share the same F_Port/fabric/etc... vports under a physical
> > port will show up under the physical port's sysfs directory tree.
> >
> > 7) Should vport_create/destroy be under fcfabric or fcport?
> >
> > I've currently put the vport_create/destroy attributes under the
> > fcfabric. I think this is fine for now, since there are no
> > complicated object relationships being presented. There's a one to
> > one relationship between a fcport and a fcfabric so it's fairly
> > easy to go back to the fcport, which is needed to be passed to the
> > LLD so it can create a vport. If there were more than one fcport
> > per fcfabric it would complicate this. Should the
> > vport_create/destroy be moved to be attributes of the fcport instead
> > to avoid a potential lookup if things get more complicated in the
> > future?
> >
> Once the fcfabric is consolidated with fcfport they'll end up under
> fcport anyway :-)
>
Yeah, consolidating these two should make getting to the fcport from the
fcfabric easier- just go to the parent.
However, I think #7 is just wrong. What's the patches do now is to
allocate the libfc per-instance data (the lport) with the vport (that
represents the N_Port). When the fcfabric is told to allocate a NPIV
port it just needs to look through its list of vports to find the N_Port
and pass it down to the LLD's vport_create function.
> > 8) Should the fcfport and fcfabric be consolidated?
> >
> > The fcfport doesn't show much other than its name. The fcfabric
> > doesn't have many attributes either. Most of its attributes are
> > vport related. I could see adding some FIP information to the
> > fcfport, but I'm not sure we need two objects here, especially if
> > the vport attributes need to be moved to the fcport.
> >
> See above. Yes.
>
> > 9) Is this change worth all of the changes that will need to happen?
> >
> > This is probably the most difficult question. I view this change as
> > positive overall, but it's very heavy lifting. Not only does the
> > FC transport need an overhaul, but it looks like the scsi transport
> > and AC code might need some additions. Every HBA will need to be
> > modified and every HBA's HBAAPI vendor library will need to change
> > too. (I hope this would be a catalyst to move to an OS library that
> > everyone shares)
> >
> > I'd like to hear other opinions about this because this really is
> > going to be something that all HBAs will need to be involved in.
> >
> I think it's quite a valid goal.
>
Thanks for the comments Hannes.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH 0/6] Work In Progress: FC sysfs
2010-01-29 19:31 ` Robert Love
@ 2010-02-02 13:06 ` Christof Schmitt
0 siblings, 0 replies; 10+ messages in thread
From: Christof Schmitt @ 2010-02-02 13:06 UTC (permalink / raw)
To: Robert Love
Cc: Hannes Reinecke, linux-scsi@vger.kernel.org,
james.smart@emulex.com, giridhar.malavali@qlogic.com
On Fri, Jan 29, 2010 at 11:31:06AM -0800, Robert Love wrote:
> On Thu, 2010-01-28 at 08:01 -0800, Hannes Reinecke wrote:
> > Robert Love wrote:
[...]
> > > # ls /sys/devices/virtual/net/eth3.101/fcport1/fcfport_2001000deca31e81/fcfabric_0/
> > > fabric_name fcvport_0 fcvport_1 max_npiv_vports npiv_vports_inuse power uevent vport_create vport_delete
> > >
> > Consistent numbering. Either use '_' as a separator always or for none.
> > This mix-up doesn't make sense.
> >
> > And, why doesn't the fcfport doesn't show up under the fabric?
> > One would assume that the fcfport is part of the fabric, too.
> >
> > And what about the remote ports? Do they not participate in the fabric?
> >
> > If the 'fcfabric' element is _not_ the actual fabric I would get rid of it altogether as it'll only serve to confuse
> > the users. Like just has been happened with me :-)
> >
> Yeah, they should be under the fcfabric. This work is just incomplete in
> that area.
Besides the fabric, FC also has the arbitrated loop and point-to-point
support. If there is a fcfabric element, would the "point-to-point
remote port" be placed under the fcfabric? Or might this be another
point for not having the fcfabric element?
[...]
> > > 9) Is this change worth all of the changes that will need to happen?
> > >
> > > This is probably the most difficult question. I view this change as
> > > positive overall, but it's very heavy lifting. Not only does the
> > > FC transport need an overhaul, but it looks like the scsi transport
> > > and AC code might need some additions. Every HBA will need to be
> > > modified and every HBA's HBAAPI vendor library will need to change
> > > too. (I hope this would be a catalyst to move to an OS library that
> > > everyone shares)
> > >
> > > I'd like to hear other opinions about this because this really is
> > > going to be something that all HBAs will need to be involved in.
The changes required for "all HBAs" also include the zfcp driver,
i am looking at this from zfcp's point of view. With zfcp, we only
support FCP/SCSI with point-to-point or fabric attached storage, so we
don't need as much flexibility as other HBAs.
I assume the LLD driver will report the available hardware resources
with fc_fcport_add, fc_fcpinit_add or whatever the entry points will
be called in the final version. Reporting the new FC elements instead
of FC host and SCSI host should be doable for zfcp.
--
Christof
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2010-02-02 13:06 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-27 23:24 [RFC PATCH 0/6] Work In Progress: FC sysfs Robert Love
2010-01-27 23:24 ` [RFC PATCH 1/6] libfc: Remove unused fc_get_host_port_type Robert Love
2010-01-27 23:24 ` [RFC PATCH 2/6] libfc: Remove extra pointer check Robert Love
2010-01-27 23:24 ` [RFC PATCH 3/6] fcoe: move link speed checking into its own routine Robert Love
2010-01-27 23:24 ` [RFC PATCH 4/6] libfc: Move the port_id into lport Robert Love
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 ` [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
2010-01-29 19:31 ` Robert Love
2010-02-02 13:06 ` Christof Schmitt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).