[SCSI] bfa: Make changes to FCXP resource management.

- Made changes to split FCXP resources as request and response resources.
- The split will reduce the contention for FCXP resources in an open zone
  config.

Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h
index 12bfeed..91a8aa3 100644
--- a/drivers/scsi/bfa/bfa_cs.h
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -168,7 +168,7 @@
 /*
  * bfa_q_deq - dequeue an element from head of the queue
  */
-#define bfa_q_deq(_q, _qe) {						\
+#define bfa_q_deq(_q, _qe) do {						\
 	if (!list_empty(_q)) {						\
 		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\
 		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
@@ -177,7 +177,7 @@
 	} else {							\
 		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
 	}								\
-}
+} while (0)
 
 /*
  * bfa_q_deq_tail - dequeue an element from tail of the queue
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index eaac57e..3f71d50 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -1294,7 +1294,7 @@
 	u16	reqlen;
 	struct fchs_s	fchs;
 
-	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs, BFA_FALSE);
 	/*
 	 * Do not expect this failure -- expect remote node to retry
 	 */
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index ef0ec66..10c93bf0 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -511,12 +511,13 @@
 	struct bfa_fcxp_s	*fcxp;		/*  FCXP in use	*/
 	struct bfa_itnim_stats_s	stats;	/*  itn statistics	*/
 };
-#define bfa_fcs_fcxp_alloc(__fcs)	\
-	bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
-
-#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg) \
-	bfa_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg, \
-					NULL, 0, 0, NULL, NULL, NULL, NULL)
+#define bfa_fcs_fcxp_alloc(__fcs, __req)				\
+	bfa_fcxp_req_rsp_alloc(NULL, (__fcs)->bfa, 0, 0,		\
+			       NULL, NULL, NULL, NULL, __req)
+#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn,		\
+				__alloc_cbarg, __req)			\
+	bfa_fcxp_req_rsp_alloc_wait(__bfa, __wqe, __alloc_cbfn,		\
+		__alloc_cbarg, NULL, 0, 0, NULL, NULL, NULL, NULL, __req)
 
 static inline struct bfad_port_s *
 bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
index 9272840..59c062f 100644
--- a/drivers/scsi/bfa/bfa_fcs_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -426,11 +426,12 @@
 
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		itnim->stats.fcxp_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
-				    bfa_fcs_itnim_send_prli, itnim);
+				bfa_fcs_itnim_send_prli, itnim, BFA_TRUE);
 		return;
 	}
 	itnim->fcxp = fcxp;
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 5392df5..e566170 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -340,7 +340,7 @@
 	bfa_trc(port->fcs, rx_fchs->d_id);
 	bfa_trc(port->fcs, rx_fchs->s_id);
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -370,7 +370,7 @@
 	bfa_trc(port->fcs, rx_fchs->d_id);
 	bfa_trc(port->fcs, rx_fchs->s_id);
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -507,7 +507,7 @@
 	bfa_trc(port->fcs, rx_fchs->s_id);
 	bfa_trc(port->fcs, rx_fchs->d_id);
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -552,7 +552,7 @@
 	bfa_trc(port->fcs, rx_fchs->d_id);
 	bfa_trc(port->fcs, rx_len);
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -684,7 +684,7 @@
 	bfa_trc(port->fcs, rx_fchs->d_id);
 	bfa_trc(port->fcs, rx_fchs->s_id);
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -1696,10 +1696,11 @@
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-					bfa_fcs_lport_fdmi_send_rhba, fdmi);
+				bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE);
 		return;
 	}
 	fdmi->fcxp = fcxp;
@@ -1970,10 +1971,11 @@
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-					bfa_fcs_lport_fdmi_send_rprt, fdmi);
+				bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);
 		return;
 	}
 	fdmi->fcxp = fcxp;
@@ -2185,10 +2187,11 @@
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-					bfa_fcs_lport_fdmi_send_rpa, fdmi);
+				bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);
 		return;
 	}
 	fdmi->fcxp = fcxp;
@@ -2775,10 +2778,11 @@
 
 	bfa_trc(port->fcs, port->pid);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-					bfa_fcs_lport_ms_send_gmal, ms);
+				bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);
 		return;
 	}
 	ms->fcxp = fcxp;
@@ -2975,10 +2979,11 @@
 
 	bfa_trc(port->fcs, port->pid);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-					bfa_fcs_lport_ms_send_gfn, ms);
+				bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);
 		return;
 	}
 	ms->fcxp = fcxp;
@@ -3051,11 +3056,12 @@
 
 	bfa_trc(port->fcs, port->pid);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		port->stats.ms_plogi_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-					bfa_fcs_lport_ms_send_plogi, ms);
+				bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);
 		return;
 	}
 	ms->fcxp = fcxp;
@@ -3809,11 +3815,12 @@
 
 	bfa_trc(port->fcs, port->pid);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		port->stats.ns_plogi_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-					bfa_fcs_lport_ns_send_plogi, ns);
+				bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);
 		return;
 	}
 	ns->fcxp = fcxp;
@@ -3909,11 +3916,12 @@
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		port->stats.ns_rspnid_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-					bfa_fcs_lport_ns_send_rspn_id, ns);
+				bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);
 		return;
 	}
 	ns->fcxp = fcxp;
@@ -4010,11 +4018,12 @@
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		port->stats.ns_rftid_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-					bfa_fcs_lport_ns_send_rft_id, ns);
+				bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);
 		return;
 	}
 	ns->fcxp = fcxp;
@@ -4083,11 +4092,12 @@
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		port->stats.ns_rffid_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-					bfa_fcs_lport_ns_send_rff_id, ns);
+				bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);
 		return;
 	}
 	ns->fcxp = fcxp;
@@ -4166,11 +4176,12 @@
 
 	bfa_trc(port->fcs, port->pid);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		port->stats.ns_gidft_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-					bfa_fcs_lport_ns_send_gid_ft, ns);
+				bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);
 		return;
 	}
 	ns->fcxp = fcxp;
@@ -4419,11 +4430,12 @@
 	memset(symbl, 0, sizeof(symbl));
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp) {
 		port->stats.ns_rspnid_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				bfa_fcs_lport_ns_util_send_rspn_id, ns);
+			bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE);
 		return;
 	}
 
@@ -4631,10 +4643,11 @@
 	bfa_trc(port->fcs, port->pid);
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
-					bfa_fcs_lport_scn_send_scr, scn);
+				bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);
 		return;
 	}
 	scn->fcxp = fcxp;
@@ -4716,7 +4729,7 @@
 
 	bfa_trc(port->fcs, rx_fchs->s_id);
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index fa2df04..8efa3a3 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -1372,10 +1372,11 @@
 
 	bfa_trc(rport->fcs, rport->pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-					bfa_fcs_rport_send_plogi, rport);
+				bfa_fcs_rport_send_plogi, rport, BFA_TRUE);
 		return;
 	}
 	rport->fcxp = fcxp;
@@ -1492,10 +1493,11 @@
 	bfa_trc(rport->fcs, rport->pwwn);
 	bfa_trc(rport->fcs, rport->reply_oxid);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-					bfa_fcs_rport_send_plogiacc, rport);
+				bfa_fcs_rport_send_plogiacc, rport, BFA_FALSE);
 		return;
 	}
 	rport->fcxp = fcxp;
@@ -1524,10 +1526,11 @@
 
 	bfa_trc(rport->fcs, rport->pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-					bfa_fcs_rport_send_adisc, rport);
+				bfa_fcs_rport_send_adisc, rport, BFA_TRUE);
 		return;
 	}
 	rport->fcxp = fcxp;
@@ -1587,10 +1590,11 @@
 
 	bfa_trc(rport->fcs, rport->pid);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-					bfa_fcs_rport_send_nsdisc, rport);
+				bfa_fcs_rport_send_nsdisc, rport, BFA_TRUE);
 		return;
 	}
 	rport->fcxp = fcxp;
@@ -1743,10 +1747,11 @@
 
 	port = rport->port;
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-					bfa_fcs_rport_send_logo, rport);
+				bfa_fcs_rport_send_logo, rport, BFA_FALSE);
 		return;
 	}
 	rport->fcxp = fcxp;
@@ -1780,7 +1785,7 @@
 
 	port = rport->port;
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -1851,7 +1856,7 @@
 		bfa_fcs_itnim_is_initiator(rport->itnim);
 	}
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -1888,7 +1893,7 @@
 
 	speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -1922,7 +1927,7 @@
 	 */
 	if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
 
-		fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+		fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 		if (!fcxp)
 			return;
 
@@ -2511,7 +2516,7 @@
 
 	bfa_trc(rport->fcs, rport->pid);
 
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 	len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
@@ -2537,7 +2542,7 @@
 
 	bfa_trc(rport->fcs, rx_fchs->s_id);
 
-	fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
+	fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);
 	if (!fcxp)
 		return;
 
@@ -2943,10 +2948,11 @@
 
 	bfa_trc(rport->fcs, rport->pwwn);
 
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced :
+	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 	if (!fcxp) {
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
-					bfa_fcs_rpf_send_rpsc2, rpf);
+				bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);
 		return;
 	}
 	rpf->fcxp = fcxp;
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 2e856e6..849eac9 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -440,9 +440,11 @@
 	fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
 	memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
 
-	INIT_LIST_HEAD(&mod->fcxp_free_q);
+	INIT_LIST_HEAD(&mod->fcxp_req_free_q);
+	INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);
 	INIT_LIST_HEAD(&mod->fcxp_active_q);
-	INIT_LIST_HEAD(&mod->fcxp_unused_q);
+	INIT_LIST_HEAD(&mod->fcxp_req_unused_q);
+	INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);
 
 	mod->fcxp_list = fcxp;
 
@@ -450,7 +452,14 @@
 		fcxp->fcxp_mod = mod;
 		fcxp->fcxp_tag = i;
 
-		list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+		if (i < (mod->num_fcxps / 2)) {
+			list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
+			fcxp->req_rsp = BFA_TRUE;
+		} else {
+			list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
+			fcxp->req_rsp = BFA_FALSE;
+		}
+
 		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
 		fcxp->reqq_waiting = BFA_FALSE;
 
@@ -514,7 +523,8 @@
 	if (!cfg->drvcfg.min_cfg)
 		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
 
-	INIT_LIST_HEAD(&mod->wait_q);
+	INIT_LIST_HEAD(&mod->req_wait_q);
+	INIT_LIST_HEAD(&mod->rsp_wait_q);
 
 	claim_fcxps_mem(mod);
 }
@@ -542,7 +552,8 @@
 	struct list_head	      *qe, *qen;
 
 	/* Enqueue unused fcxp resources to free_q */
-	list_splice_tail_init(&mod->fcxp_unused_q, &mod->fcxp_free_q);
+	list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);
+	list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);
 
 	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
 		fcxp = (struct bfa_fcxp_s *) qe;
@@ -559,11 +570,14 @@
 }
 
 static struct bfa_fcxp_s *
-bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
+bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)
 {
 	struct bfa_fcxp_s *fcxp;
 
-	bfa_q_deq(&fm->fcxp_free_q, &fcxp);
+	if (req)
+		bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);
+	else
+		bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);
 
 	if (fcxp)
 		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
@@ -642,7 +656,11 @@
 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 	struct bfa_fcxp_wqe_s *wqe;
 
-	bfa_q_deq(&mod->wait_q, &wqe);
+	if (fcxp->req_rsp)
+		bfa_q_deq(&mod->req_wait_q, &wqe);
+	else
+		bfa_q_deq(&mod->rsp_wait_q, &wqe);
+
 	if (wqe) {
 		bfa_trc(mod->bfa, fcxp->fcxp_tag);
 
@@ -657,7 +675,11 @@
 
 	WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
 	list_del(&fcxp->qe);
-	list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+
+	if (fcxp->req_rsp)
+		list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
+	else
+		list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
 }
 
 static void
@@ -900,21 +922,23 @@
  *				Address (given the sge index).
  * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG
  *				len (given the sge index).
+ * @param[in]	req		Allocated FCXP is used to send req or rsp?
+ *				request - BFA_TRUE, response - BFA_FALSE
  *
  * @return FCXP instance. NULL on failure.
  */
 struct bfa_fcxp_s *
-bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
-	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
-	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
-	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
-	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
+		int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+		bfa_fcxp_get_sglen_t req_sglen_cbfn,
+		bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+		bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
 {
 	struct bfa_fcxp_s *fcxp = NULL;
 
 	WARN_ON(bfa == NULL);
 
-	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
+	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);
 	if (fcxp == NULL)
 		return NULL;
 
@@ -1071,17 +1095,20 @@
 }
 
 void
-bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
 	       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
 	       void *caller, int nreq_sgles,
 	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
 	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
 	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
-	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
 {
 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 
-	WARN_ON(!list_empty(&mod->fcxp_free_q));
+	if (req)
+		WARN_ON(!list_empty(&mod->fcxp_req_free_q));
+	else
+		WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
 
 	wqe->alloc_cbfn = alloc_cbfn;
 	wqe->alloc_cbarg = alloc_cbarg;
@@ -1094,7 +1121,10 @@
 	wqe->rsp_sga_cbfn = rsp_sga_cbfn;
 	wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
 
-	list_add_tail(&wqe->qe, &mod->wait_q);
+	if (req)
+		list_add_tail(&wqe->qe, &mod->req_wait_q);
+	else
+		list_add_tail(&wqe->qe, &mod->rsp_wait_q);
 }
 
 void
@@ -1102,7 +1132,8 @@
 {
 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 
-	WARN_ON(!bfa_q_is_on_q(&mod->wait_q, wqe));
+	WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
+		!bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
 	list_del(&wqe->qe);
 }
 
@@ -1153,8 +1184,13 @@
 	int	i;
 
 	for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
-		bfa_q_deq_tail(&mod->fcxp_free_q, &qe);
-		list_add_tail(qe, &mod->fcxp_unused_q);
+		if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
+			bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
+			list_add_tail(qe, &mod->fcxp_req_unused_q);
+		} else {
+			bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
+			list_add_tail(qe, &mod->fcxp_rsp_unused_q);
+		}
 	}
 }
 
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index f300675..4da2b58 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -97,10 +97,13 @@
 	struct bfa_s      *bfa;		/* backpointer to BFA */
 	struct bfa_fcxp_s *fcxp_list;	/* array of FCXPs */
 	u16	num_fcxps;	/* max num FCXP requests */
-	struct list_head  fcxp_free_q;	/* free FCXPs */
-	struct list_head  fcxp_active_q;	/* active FCXPs */
-	struct list_head  wait_q;		/* wait queue for free fcxp */
-	struct list_head fcxp_unused_q; /* unused fcxps */
+	struct list_head fcxp_req_free_q; /* free FCXPs used for sending req */
+	struct list_head fcxp_rsp_free_q; /* free FCXPs used for sending req */
+	struct list_head fcxp_active_q;	/* active FCXPs */
+	struct list_head req_wait_q;	/* wait queue for free req_fcxp */
+	struct list_head rsp_wait_q;	/* wait queue for free rsp_fcxp */
+	struct list_head fcxp_req_unused_q;	/* unused req_fcxps */
+	struct list_head fcxp_rsp_unused_q;	/* unused rsp_fcxps */
 	u32	req_pld_sz;
 	u32	rsp_pld_sz;
 	struct bfa_mem_dma_s dma_seg[BFA_FCXP_DMA_SEGS];
@@ -197,6 +200,7 @@
 	struct bfa_cb_qe_s    hcb_qe;	/*  comp: callback qelem */
 	struct bfa_reqq_wait_s	reqq_wqe;
 	bfa_boolean_t	reqq_waiting;
+	bfa_boolean_t	req_rsp;	/* Used to track req/rsp fcxp */
 };
 
 struct bfa_fcxp_wqe_s {
@@ -586,20 +590,22 @@
 /*
  * bfa fcxp API functions
  */
-struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
+struct bfa_fcxp_s *bfa_fcxp_req_rsp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
 				  int nreq_sgles, int nrsp_sgles,
 				  bfa_fcxp_get_sgaddr_t get_req_sga,
 				  bfa_fcxp_get_sglen_t get_req_sglen,
 				  bfa_fcxp_get_sgaddr_t get_rsp_sga,
-				  bfa_fcxp_get_sglen_t get_rsp_sglen);
-void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+				  bfa_fcxp_get_sglen_t get_rsp_sglen,
+				  bfa_boolean_t req);
+void bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
 				bfa_fcxp_alloc_cbfn_t alloc_cbfn,
 				void *cbarg, void *bfad_fcxp,
 				int nreq_sgles, int nrsp_sgles,
 				bfa_fcxp_get_sgaddr_t get_req_sga,
 				bfa_fcxp_get_sglen_t get_req_sglen,
 				bfa_fcxp_get_sgaddr_t get_rsp_sga,
-				bfa_fcxp_get_sglen_t get_rsp_sglen);
+				bfa_fcxp_get_sglen_t get_rsp_sglen,
+				bfa_boolean_t req);
 void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
 			    struct bfa_fcxp_wqe_s *wqe);
 void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index d9463d8..0db9055 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -2955,13 +2955,13 @@
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 
 	/* Allocate bfa_fcxp structure */
-	hal_fcxp = bfa_fcxp_alloc(drv_fcxp, &bfad->bfa,
+	hal_fcxp = bfa_fcxp_req_rsp_alloc(drv_fcxp, &bfad->bfa,
 				  drv_fcxp->num_req_sgles,
 				  drv_fcxp->num_rsp_sgles,
 				  bfad_fcxp_get_req_sgaddr_cb,
 				  bfad_fcxp_get_req_sglen_cb,
 				  bfad_fcxp_get_rsp_sgaddr_cb,
-				  bfad_fcxp_get_rsp_sglen_cb);
+				  bfad_fcxp_get_rsp_sglen_cb, BFA_TRUE);
 	if (!hal_fcxp) {
 		bfa_trc(bfad, 0);
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);