[SCSI] bfa: Add dynamic diagnostic port support

D-Port is a new port type created with the intention of running link
level diagnostic tests like loopback, traffic test. In static D-port
mode, user configures the port to D-port mode and starts the test, but
in dynamic D-port, once the Brocade switch port is configured to
D-port, it will reject the regular FLOGI from HBA with reason that it is
in D-port mode. So based on the reason code HBA port will turn itself into
D-port and start diagnostic test.

Signed-off-by: Sudarsana Reddy Kalluru <skalluru@brocade.com>
Signed-off-by: Vijaya Mohan Guvva <vmohan@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index bda1500..f31acfa 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -1785,7 +1785,29 @@
 }
 
 int
-bfad_iocmd_diag_cfg_dport(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
+bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd)
+{
+	struct bfa_bsg_dport_enable_s *iocmd =
+				(struct bfa_bsg_dport_enable_s *)pcmd;
+	unsigned long	flags;
+	struct bfad_hal_comp fcomp;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_dport_enable(&bfad->bfa, iocmd->lpcnt,
+					iocmd->pat, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		bfa_trc(bfad, iocmd->status);
+	else {
+		wait_for_completion(&fcomp.comp);
+		iocmd->status = fcomp.status;
+	}
+	return 0;
+}
+
+int
+bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd)
 {
 	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
 	unsigned long	flags;
@@ -1793,43 +1815,57 @@
 
 	init_completion(&fcomp.comp);
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	if (cmd == IOCMD_DIAG_DPORT_ENABLE)
-		iocmd->status = bfa_dport_enable(&bfad->bfa,
-					bfad_hcb_comp, &fcomp);
-	else if (cmd == IOCMD_DIAG_DPORT_DISABLE)
-		iocmd->status = bfa_dport_disable(&bfad->bfa,
-					bfad_hcb_comp, &fcomp);
-	else {
-		bfa_trc(bfad, 0);
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		return -EINVAL;
-	}
+	iocmd->status = bfa_dport_disable(&bfad->bfa, bfad_hcb_comp, &fcomp);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
 	if (iocmd->status != BFA_STATUS_OK)
 		bfa_trc(bfad, iocmd->status);
 	else {
 		wait_for_completion(&fcomp.comp);
 		iocmd->status = fcomp.status;
 	}
+	return 0;
+}
+
+int
+bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd)
+{
+	struct bfa_bsg_dport_enable_s *iocmd =
+				(struct bfa_bsg_dport_enable_s *)pcmd;
+	unsigned long   flags;
+	struct bfad_hal_comp fcomp;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_dport_start(&bfad->bfa, iocmd->lpcnt,
+					iocmd->pat, bfad_hcb_comp,
+					&fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (iocmd->status != BFA_STATUS_OK) {
+		bfa_trc(bfad, iocmd->status);
+	} else {
+		wait_for_completion(&fcomp.comp);
+		iocmd->status = fcomp.status;
+	}
 
 	return 0;
 }
 
 int
-bfad_iocmd_diag_dport_get_state(struct bfad_s *bfad, void *pcmd)
+bfad_iocmd_diag_dport_show(struct bfad_s *bfad, void *pcmd)
 {
-	struct bfa_bsg_diag_dport_get_state_s *iocmd =
-			(struct bfa_bsg_diag_dport_get_state_s *)pcmd;
-	unsigned long	flags;
+	struct bfa_bsg_diag_dport_show_s *iocmd =
+				(struct bfa_bsg_diag_dport_show_s *)pcmd;
+	unsigned long   flags;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	iocmd->status = bfa_dport_get_state(&bfad->bfa, &iocmd->state);
+	iocmd->status = bfa_dport_show(&bfad->bfa, &iocmd->result);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	return 0;
 }
 
+
 int
 bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
 {
@@ -2934,11 +2970,16 @@
 		rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
 		break;
 	case IOCMD_DIAG_DPORT_ENABLE:
-	case IOCMD_DIAG_DPORT_DISABLE:
-		rc = bfad_iocmd_diag_cfg_dport(bfad, cmd, iocmd);
+		rc = bfad_iocmd_diag_dport_enable(bfad, iocmd);
 		break;
-	case IOCMD_DIAG_DPORT_GET_STATE:
-		rc = bfad_iocmd_diag_dport_get_state(bfad, iocmd);
+	case IOCMD_DIAG_DPORT_DISABLE:
+		rc = bfad_iocmd_diag_dport_disable(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_DPORT_SHOW:
+		rc = bfad_iocmd_diag_dport_show(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_DPORT_START:
+		rc = bfad_iocmd_diag_dport_start(bfad, iocmd);
 		break;
 	case IOCMD_PHY_GET_ATTR:
 		rc = bfad_iocmd_phy_get_attr(bfad, iocmd);