Adds fcoe_exch_get to allocate exchange in fcoe.ko from either oemp
or default lp->emp, the fcoe_exch_get is initialized to
fcoe_libfc_fcn_templ.exch_get which gets called by libfc to allocate
a new exchange.

Added fcoe_exch_get allocates a exch from oemp for
for read types IOs and if succeeded then sets up DDP by calling
fc_fcp_ddp_setup, otherwise allocates exchange from other default
local port em.

Adds fcoe_exch_recv to select a EM instance for a incoming frame
and then pass received frame to libfc fc_exch_recv with selected EM
based on incoming frame oxid.

Signed-off-by: Vasu Dev <[email protected]>
---

 drivers/scsi/fcoe/fcoe.c     |   55 ++++++++++++++++++++++++++++++++++++++++--
 drivers/scsi/libfc/fc_exch.c |    2 --
 2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 536b734..d197c2b 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -559,6 +559,54 @@ 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);
+
+       if (oxid < lp->lro_xid) {
+               if (ntoh24(fh->fh_f_ctl) & 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 exchange 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;
+
+       if (fc_fcp_is_read(fr_fsp(fp))) {
+               ep = fc_exch_alloc(lp, fc->oemp);
+               if (ep)
+                       fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
+               else
+                       ep = fc_exch_alloc(lp, lp->emp);
+       } else
+               ep = fc_exch_alloc(lp, lp->emp);
+
+       return ep;
+}
+
 /*
  * fcoe_ddp_setup - calls LLD's ddp_setup through net_device
  * @lp:        the corresponding fc_lport
@@ -665,6 +713,9 @@ static int fcoe_if_create(struct net_device *netdev)
                goto out_netdev_cleanup;
        }
 
+       /* 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) {
@@ -1346,7 +1397,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) {
@@ -1367,7 +1418,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;
 }
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 2b9e2af..fedd0cc 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1807,8 +1807,6 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
        fc_exch_setup_hdr(ep, fp, ep->f_ctl);
        sp->cnt++;
 
-       fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
-
        if (unlikely(lp->tt.frame_send(lp, fp)))
                goto err;
 

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

Reply via email to