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
