[SCSI] bfa: Changes to support vport disable and enable operations.

Made changes to FCS lport, vport state machines to support vport
enable / disable operations.

Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 1d6be8c..a0c6f96 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -74,6 +74,7 @@
 	BFA_FCS_PORT_SM_OFFLINE = 3,
 	BFA_FCS_PORT_SM_DELETE = 4,
 	BFA_FCS_PORT_SM_DELRPORT = 5,
+	BFA_FCS_PORT_SM_STOP = 6,
 };
 
 static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
@@ -86,6 +87,8 @@
 					enum bfa_fcs_lport_event event);
 static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
 					enum bfa_fcs_lport_event event);
+static void	bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
 
 static void
 bfa_fcs_lport_sm_uninit(
@@ -123,6 +126,12 @@
 		bfa_fcs_lport_deleted(port);
 		break;
 
+	case BFA_FCS_PORT_SM_STOP:
+		/* If vport - send completion call back */
+		if (port->vport)
+			bfa_fcs_vport_stop_comp(port->vport);
+		break;
+
 	case BFA_FCS_PORT_SM_OFFLINE:
 		break;
 
@@ -148,6 +157,23 @@
 		bfa_fcs_lport_offline_actions(port);
 		break;
 
+	case BFA_FCS_PORT_SM_STOP:
+		__port_action[port->fabric->fab_type].offline(port);
+
+		if (port->num_rports == 0) {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+			/* If vport - send completion call back */
+			if (port->vport)
+				bfa_fcs_vport_stop_comp(port->vport);
+		} else {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
+			list_for_each_safe(qe, qen, &port->rport_q) {
+				rport = (struct bfa_fcs_rport_s *) qe;
+				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+			}
+		}
+		break;
+
 	case BFA_FCS_PORT_SM_DELETE:
 
 		__port_action[port->fabric->fab_type].offline(port);
@@ -189,6 +215,21 @@
 		bfa_fcs_lport_online_actions(port);
 		break;
 
+	case BFA_FCS_PORT_SM_STOP:
+		if (port->num_rports == 0) {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+			/* If vport - send completion call back */
+			if (port->vport)
+				bfa_fcs_vport_stop_comp(port->vport);
+		} else {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
+			list_for_each_safe(qe, qen, &port->rport_q) {
+				rport = (struct bfa_fcs_rport_s *) qe;
+				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+			}
+		}
+		break;
+
 	case BFA_FCS_PORT_SM_DELETE:
 		if (port->num_rports == 0) {
 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
@@ -212,6 +253,28 @@
 }
 
 static void
+bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
+			  enum bfa_fcs_lport_event event)
+{
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_PORT_SM_DELRPORT:
+		if (port->num_rports == 0) {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+			/* If vport - send completion call back */
+			if (port->vport)
+				bfa_fcs_vport_stop_comp(port->vport);
+		}
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
 bfa_fcs_lport_sm_deleting(
 	struct bfa_fcs_lport_s *port,
 	enum bfa_fcs_lport_event event)
@@ -1672,7 +1735,7 @@
 	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
 	templen = fc_roundup(templen, sizeof(u32));
 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
-	len += templen;;
+	len += templen;
 	count++;
 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
 			     sizeof(templen));
@@ -4918,6 +4981,7 @@
 	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
 	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/
 	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
+	BFA_FCS_VPORT_SM_STOPCOMP = 14,	/* vport delete completion */
 };
 
 static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
@@ -4940,6 +5004,10 @@
 				      enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
 				      enum bfa_fcs_vport_event event);
+static void	bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
+static void	bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
 
 static struct bfa_sm_table_s  vport_sm_table[] = {
 	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
@@ -5042,6 +5110,11 @@
 		bfa_fcs_vport_do_fdisc(vport);
 		break;
 
+	case BFA_FCS_VPORT_SM_STOP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
+		break;
+
 	case BFA_FCS_VPORT_SM_OFFLINE:
 		/*
 		 * This can happen if the vport couldn't be initialzied
@@ -5155,6 +5228,11 @@
 		bfa_fcs_lport_delete(&vport->lport);
 		break;
 
+	case BFA_FCS_VPORT_SM_STOP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
+		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
+		break;
+
 	case BFA_FCS_VPORT_SM_OFFLINE:
 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
@@ -5167,6 +5245,32 @@
 }
 
 /*
+ * Vport is being stopped - awaiting lport stop completion to send
+ * LOGO to fabric.
+ */
+static void
+bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
+			  enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_STOPCOMP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
+		bfa_fcs_vport_do_logo(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/*
  * Vport is being deleted - awaiting lport delete completion to send
  * LOGO to fabric.
  */
@@ -5236,6 +5340,10 @@
 		bfa_fcs_vport_free(vport);
 		break;
 
+	case BFA_FCS_VPORT_SM_STOPCOMP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+		break;
+
 	case BFA_FCS_VPORT_SM_DELETE:
 		break;
 
@@ -5245,6 +5353,34 @@
 }
 
 /*
+ * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
+ * is done.
+ */
+static void
+bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
+			       enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case BFA_FCS_VPORT_SM_RSP_OK:
+	case BFA_FCS_VPORT_SM_RSP_ERROR:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/*
  * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
  * is done.
  */
@@ -5422,6 +5558,15 @@
 }
 
 /*
+ * Stop completion callback from associated lport
+ */
+void
+bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
+}
+
+/*
  * Delete completion callback from associated lport
  */
 void