[SCSI] libfc: register FC4 features with the FC switch
authorJoe Eykholt <jeykholt@cisco.com>
Tue, 3 Nov 2009 19:49:27 +0000 (11:49 -0800)
committerJames Bottomley <James.Bottomley@suse.de>
Fri, 4 Dec 2009 18:01:20 +0000 (12:01 -0600)
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>
drivers/scsi/libfc/fc_lport.c
include/scsi/fc/fc_fcp.h
include/scsi/fc/fc_ns.h
include/scsi/fc_encode.h
include/scsi/libfc.h

index d3aec1959394377d7a760af620a8523bc1b4bcbf..1bcc5e11d2c05226bd78e61130dbf0454d93b534 100644 (file)
@@ -122,6 +122,7 @@ static const char *fc_lport_state_names[] = {
        [LPORT_ST_RSNN_NN] =  "RSNN_NN",
        [LPORT_ST_RSPN_ID] =  "RSPN_ID",
        [LPORT_ST_RFT_ID] =   "RFT_ID",
+       [LPORT_ST_RFF_ID] =   "RFF_ID",
        [LPORT_ST_SCR] =      "SCR",
        [LPORT_ST_READY] =    "Ready",
        [LPORT_ST_LOGO] =     "LOGO",
@@ -1034,6 +1035,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
                        case LPORT_ST_RSNN_NN:
                        case LPORT_ST_RSPN_ID:
                        case LPORT_ST_RFT_ID:
+                       case LPORT_ST_RFF_ID:
                        case LPORT_ST_SCR:
                        case LPORT_ST_DNS:
                        case LPORT_ST_FLOGI:
@@ -1070,7 +1072,7 @@ static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp,
 
        mutex_lock(&lport->lp_mutex);
 
-       if (lport->state < LPORT_ST_RNN_ID || lport->state > LPORT_ST_RFT_ID) {
+       if (lport->state < LPORT_ST_RNN_ID || lport->state > LPORT_ST_RFF_ID) {
                FC_LPORT_DBG(lport, "Received a name server response, "
                             "but in state %s\n", fc_lport_state(lport));
                if (IS_ERR(fp))
@@ -1101,6 +1103,9 @@ static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp,
                        fc_lport_enter_ns(lport, LPORT_ST_RFT_ID);
                        break;
                case LPORT_ST_RFT_ID:
+                       fc_lport_enter_ns(lport, LPORT_ST_RFF_ID);
+                       break;
+               case LPORT_ST_RFF_ID:
                        fc_lport_enter_scr(lport);
                        break;
                default:
@@ -1235,6 +1240,10 @@ static void fc_lport_enter_ns(struct fc_lport *lport, enum fc_lport_state state)
                cmd = FC_NS_RFT_ID;
                size += sizeof(struct fc_ns_rft);
                break;
+       case LPORT_ST_RFF_ID:
+               cmd = FC_NS_RFF_ID;
+               size += sizeof(struct fc_ns_rff_id);
+               break;
        default:
                fc_lport_error(lport, NULL);
                return;
@@ -1317,6 +1326,7 @@ static void fc_lport_timeout(struct work_struct *work)
        case LPORT_ST_RSNN_NN:
        case LPORT_ST_RSPN_ID:
        case LPORT_ST_RFT_ID:
+       case LPORT_ST_RFF_ID:
                fc_lport_enter_ns(lport, lport->state);
                break;
        case LPORT_ST_SCR:
index 5d38f1989f37b90a14bafb9b8a0d501d63681773..29ecb0b02b09bbe42728c74f71ca2062c91c7271 100644 (file)
@@ -196,4 +196,10 @@ struct fcp_srr {
        __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_ */
index f4d354eb26b9bb4fb9da9d09fb9169e86a4ca0cd..e7d3ac497d7df6ea331ad7b3a25ad147ab6c13ad 100644 (file)
@@ -46,10 +46,11 @@ enum fc_ns_req {
        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 @@ struct fc_ns_rspn {
        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_ */
index ab2260cb149c4919b4111b880cd8937504d308c2..8eb0a0fc0a719062f616b9523818534ef57f6338 100644 (file)
@@ -32,6 +32,7 @@ struct fc_ct_req {
                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 @@ static inline int fc_ct_fill(struct fc_lport *lport,
                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,
index 67ce9fa1fee437c22410428066be2f6c81ea1601..2936fbae41e46569d895b6be2a956f43a3bcb6ab 100644 (file)
@@ -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 @@ enum fc_lport_state {
        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,