Merge remote-tracking branch 'scsi/for-next'
[deliverable/linux.git] / drivers / scsi / libfc / fc_rport.c
index 93f5961821452b50d0094413658c34bc37cbc9ec..97aeaddd600d42c03feb79f3fa11bf6a80ce3229 100644 (file)
@@ -457,6 +457,9 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
  */
 static int fc_rport_logoff(struct fc_rport_priv *rdata)
 {
+       struct fc_lport *lport = rdata->local_port;
+       u32 port_id = rdata->ids.port_id;
+
        mutex_lock(&rdata->rp_mutex);
 
        FC_RPORT_DBG(rdata, "Remove port\n");
@@ -466,6 +469,15 @@ static int fc_rport_logoff(struct fc_rport_priv *rdata)
                FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n");
                goto out;
        }
+       /*
+        * FC-LS states:
+        * To explicitly Logout, the initiating Nx_Port shall terminate
+        * other open Sequences that it initiated with the destination
+        * Nx_Port prior to performing Logout.
+        */
+       lport->tt.exch_mgr_reset(lport, 0, port_id);
+       lport->tt.exch_mgr_reset(lport, port_id, 0);
+
        fc_rport_enter_logo(rdata);
 
        /*
@@ -547,16 +559,24 @@ static void fc_rport_timeout(struct work_struct *work)
  */
 static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
 {
+       struct fc_lport *lport = rdata->local_port;
+
        FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n",
                     IS_ERR(fp) ? -PTR_ERR(fp) : 0,
                     fc_rport_state(rdata), rdata->retries);
 
        switch (rdata->rp_state) {
        case RPORT_ST_FLOGI:
-       case RPORT_ST_PLOGI:
                rdata->flags &= ~FC_RP_STARTED;
                fc_rport_enter_delete(rdata, RPORT_EV_FAILED);
                break;
+       case RPORT_ST_PLOGI:
+               if (lport->point_to_multipoint) {
+                       rdata->flags &= ~FC_RP_STARTED;
+                       fc_rport_enter_delete(rdata, RPORT_EV_FAILED);
+               } else
+                       fc_rport_enter_logo(rdata);
+               break;
        case RPORT_ST_RTV:
                fc_rport_enter_ready(rdata);
                break;
@@ -1877,7 +1897,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
        spp->spp_type_ext = rspp->spp_type_ext;
        spp->spp_flags = FC_SPP_RESP_ACK;
 
-       fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
+       fc_rport_enter_prli(rdata);
 
        fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
        lport->tt.frame_send(lport, fp);
@@ -1915,7 +1935,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)
                FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
                             fc_rport_state(rdata));
 
-               fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
+               fc_rport_enter_delete(rdata, RPORT_EV_STOP);
                mutex_unlock(&rdata->rp_mutex);
                kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
        } else
This page took 0.025644 seconds and 5 git commands to generate.