[SCSI] libfc: register FC4 features with the FC switch

Customers and certification tests have pointed out that we don't
show up on the switch management software as an initiator.

On some MDS switches 'show fcns database' command shows libfc
initiators as 'fcp' not 'fcp:init' like other initiators.

On others switches, I think the switch gets the features by doing a PRLI,
but it may be only certain models or under certain configurations.

Fix this by registering our FC4 features with the RFF_ID CT request
after local port login and after the RFT_ID.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
diff --git a/include/scsi/fc/fc_fcp.h b/include/scsi/fc/fc_fcp.h
index 5d38f19..29ecb0b 100644
--- a/include/scsi/fc/fc_fcp.h
+++ b/include/scsi/fc/fc_fcp.h
@@ -196,4 +196,10 @@
 	__u8		srr_resvd2[3];	/* reserved */
 };
 
+/*
+ * Feature bits in name server FC-4 Features object.
+ */
+#define	FCP_FEAT_TARG	(1 << 0)	/* target function supported */
+#define	FCP_FEAT_INIT	(1 << 1)	/* initiator function supported */
+
 #endif /* _FC_FCP_H_ */
diff --git a/include/scsi/fc/fc_ns.h b/include/scsi/fc/fc_ns.h
index f4d354e..e7d3ac4 100644
--- a/include/scsi/fc/fc_ns.h
+++ b/include/scsi/fc/fc_ns.h
@@ -46,10 +46,11 @@
 	FC_NS_GID_FT =	0x0171,		/* get IDs by FC4 type */
 	FC_NS_GPN_FT =	0x0172,		/* get port names by FC4 type */
 	FC_NS_GID_PT =	0x01a1,		/* get IDs by port type */
-	FC_NS_RFT_ID =	0x0217,		/* reg FC4 type for ID */
 	FC_NS_RPN_ID =	0x0212,		/* reg port name for ID */
 	FC_NS_RNN_ID =	0x0213,		/* reg node name for ID */
+	FC_NS_RFT_ID =	0x0217,		/* reg FC4 type for ID */
 	FC_NS_RSPN_ID =	0x0218,		/* reg symbolic port name */
+	FC_NS_RFF_ID =	0x021f,		/* reg FC4 Features for ID */
 	FC_NS_RSNN_NN =	0x0239,		/* reg symbolic node name */
 };
 
@@ -178,4 +179,14 @@
 	char		fr_name[];
 } __attribute__((__packed__));
 
+/*
+ * RFF_ID request - register FC-4 Features for ID.
+ */
+struct fc_ns_rff_id {
+	struct fc_ns_fid fr_fid;	/* port ID object */
+	__u8		fr_resvd[2];
+	__u8		fr_feat;	/* FC-4 Feature bits */
+	__u8		fr_type;	/* FC-4 type */
+} __attribute__((__packed__));
+
 #endif /* _FC_NS_H_ */
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index ab2260c..8eb0a0f 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -32,6 +32,7 @@
 		struct fc_ns_gid_ft gid;
 		struct fc_ns_rn_id  rn;
 		struct fc_ns_rft rft;
+		struct fc_ns_rff_id rff;
 		struct fc_ns_fid fid;
 		struct fc_ns_rsnn snn;
 		struct fc_ns_rspn spn;
@@ -131,6 +132,17 @@
 		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));
+		ct->payload.rff.fr_type = FC_TYPE_FCP;
+		if (lport->service_params & FCP_SPPF_INIT_FCN)
+			ct->payload.rff.fr_feat = FCP_FEAT_INIT;
+		if (lport->service_params & FCP_SPPF_TARG_FCN)
+			ct->payload.rff.fr_feat |= FCP_FEAT_TARG;
+		break;
+
 	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,
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 67ce9fa..2936fba 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -62,6 +62,7 @@
  * @LPORT_ST_DNS:      Waiting for name server remote port to become ready
  * @LPORT_ST_RPN_ID:   Register port name by ID (RPN_ID) sent
  * @LPORT_ST_RFT_ID:   Register Fibre Channel types by ID (RFT_ID) sent
+ * @LPORT_ST_RFF_ID:   Register FC-4 Features by ID (RFF_ID) sent
  * @LPORT_ST_SCR:      State Change Register (SCR) sent
  * @LPORT_ST_READY:    Ready for use
  * @LPORT_ST_LOGO:     Local port logout (LOGO) sent
@@ -75,6 +76,7 @@
 	LPORT_ST_RSNN_NN,
 	LPORT_ST_RSPN_ID,
 	LPORT_ST_RFT_ID,
+	LPORT_ST_RFF_ID,
 	LPORT_ST_SCR,
 	LPORT_ST_READY,
 	LPORT_ST_LOGO,