[Open-FCoE] [RFC PATCH 6/6] fcoe: adds exch_get function in fcoe to use offload em instance oemp

Vasu Dev vasu.dev at intel.com
Wed Apr 29 15:15:24 UTC 2009


Adds fcoe_exch_get to allocate and setup ddp for read types IOs,
the exch_get gets called by libfc to allocate a new exchange from EM
block of libfc.

Added fcoe_exch_get allocated exchange from other default em for all
other types of IO.

Adds fcoe_exch_recv to select a EM instance for a incoming frame
and then pass received frame to libfc fc_exch_recv, the selected EM
could be offload EM instance or default lp->emp based on xid of
incoming frame.

Signed-off-by: Vasu Dev <vasu.dev at intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   60 ++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 6fe1662..504f42b 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -469,6 +469,59 @@ static int fcoe_if_destroy(struct net_device *netdev)
 	return 0;
 }
 
+/**
+ * fcoe_exch_recv() - receive a incoming frame
+ * @lp:	the associated local port
+ * @fp: received fc_frame
+ *
+ * Locates exchange manager instance for received frame
+ * and pass it up to libfc using fc_exch_recv api.
+ */
+static void fcoe_exch_recv(struct fc_lport *lp, struct fc_frame *fp)
+{
+	struct fcoe_softc *fc = lport_priv(lp);
+	struct fc_frame_header *fh = fc_frame_header_get(fp);
+	u16 oxid = ntohs(fh->fh_ox_id);
+	u32 ctx;
+
+	if (lp->lro_enabled && (oxid <= lp->lro_xid)) {
+		ctx = ntoh24(fh->fh_f_ctl) & (FC_FC_EX_CTX | FC_FC_SEQ_CTX);
+		if (ctx == FC_FC_EX_CTX) {
+			fc_exch_recv(lp, fc->oemp, fp);
+			return;
+		}
+	}
+	fc_exch_recv(lp, lp->emp, fp);
+}
+
+/**
+ * fcoe_exch_get() - allocates an exchange
+ * @lp:	the associated local port
+ * @fp: the fc_frame to be transmitted
+ *
+ * Allocates exchange from fc->oemp for offload eligible IOs
+ * otherwise allocates from other em instance.
+ */
+static struct fc_exch *fcoe_exch_get(struct fc_lport *lp, struct fc_frame *fp)
+{
+	struct fcoe_softc *fc = lport_priv(lp);
+	struct fc_exch *ep = NULL;
+
+	if (fc_fcp_is_read(fr_fsp(fp)))
+		ep = fc_exch_alloc(fc->oemp);
+
+	/*
+	 * if valid ep allocated from fc->ofemp
+	 * then set up ddp here, else allocate
+	 * ep from other em.
+	 */
+	if (ep)
+		fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
+	else
+		ep = fc_exch_alloc(lp->emp);
+	return ep;
+}
+
 /*
  * fcoe_ddp_setup - calls LLD's ddp_setup through net_device
  * @lp:	the corresponding fc_lport
@@ -630,6 +683,9 @@ static int fcoe_if_create(struct net_device *netdev)
 		goto out_host_put;
 	}
 
+	/* set exch_get if lro enabled */
+	if (lp->lro_enabled)
+		fcoe_libfc_fcn_templ.exch_get = fcoe_exch_get;
 	/* Initialize the library */
 	rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
 	if (rc) {
@@ -1303,7 +1359,7 @@ int fcoe_percpu_receive_thread(void *arg)
 		fh = fc_frame_header_get(fp);
 		if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
 		    fh->fh_type == FC_TYPE_FCP) {
-			fc_exch_recv(lp, lp->emp, fp);
+			fcoe_exch_recv(lp, fp);
 			continue;
 		}
 		if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
@@ -1324,7 +1380,7 @@ int fcoe_percpu_receive_thread(void *arg)
 			fc_frame_free(fp);
 			continue;
 		}
-		fc_exch_recv(lp, lp->emp, fp);
+		fcoe_exch_recv(lp, fp);
 	}
 	return 0;
 }




More information about the devel mailing list