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 <[email protected]>
---

 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;
 }

_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to