[SCSI] libfc: Honor LS_ACC response codes for PRLI
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>
Fri, 11 Jun 2010 23:43:54 +0000 (16:43 -0700)
committerJames Bottomley <James.Bottomley@suse.de>
Tue, 27 Jul 2010 17:01:45 +0000 (12:01 -0500)
As per FC-LS Rev 1.62 table 46, response codes are handled as follows:

1. If the Req executed is true, PRLI is accepted.
2. If Req executed is not set,  if resp code is 5,
   PRLI is not retried and port is logged out.
3. If resp code is anything apart from 1 or 5, PRLI is retired
   upto max retry count.

Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/libfc/fc_rport.c

index 3ee497a0516859b549de0f5ca71bdddf607371dc..e33c5c7961a27ac93a450ded6cd0683f1e249225 100644 (file)
@@ -698,6 +698,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
        u32 roles = FC_RPORT_ROLE_UNKNOWN;
        u32 fcp_parm = 0;
        u8 op;
+       u8 resp_code = 0;
 
        mutex_lock(&rdata->rp_mutex);
 
@@ -722,11 +723,25 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
        op = fc_frame_payload_op(fp);
        if (op == ELS_LS_ACC) {
                pp = fc_frame_payload_get(fp, sizeof(*pp));
-               if (pp && pp->prli.prli_spp_len >= sizeof(pp->spp)) {
-                       fcp_parm = ntohl(pp->spp.spp_params);
-                       if (fcp_parm & FCP_SPPF_RETRY)
-                               rdata->flags |= FC_RP_FLAGS_RETRY;
+               if (!pp)
+                       goto out;
+
+               resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
+               FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
+                            pp->spp.spp_flags);
+               if (resp_code != FC_SPP_RESP_ACK) {
+                       if (resp_code == FC_SPP_RESP_CONF)
+                               fc_rport_error(rdata, fp);
+                       else
+                               fc_rport_error_retry(rdata, fp);
+                       goto out;
                }
+               if (pp->prli.prli_spp_len < sizeof(pp->spp))
+                       goto out;
+
+               fcp_parm = ntohl(pp->spp.spp_params);
+               if (fcp_parm & FCP_SPPF_RETRY)
+                       rdata->flags |= FC_RP_FLAGS_RETRY;
 
                rdata->supported_classes = FC_COS_CLASS3;
                if (fcp_parm & FCP_SPPF_INIT_FCN)