Adds pointer lp->oemp to lport to allow multiple lport to share
offload em instance using this pointer.

Modifies fc_exch_mgr_reset to reset both lp->emp and lp->oemp.

I used p suffix in naming to have new names aligned with existing
names e.g. lp->emp, lp, mp etc.

Adds APIs fc_exch_mgr_inc and fc_exch_mgr_dec to update added
em usage counter em_user.

The fc_exch_mgr_free decrements em_user counter and frees em when
em_user counter reaches to zero.

New em allocation increments em_user counter and this will be
incremented for shared em instance use across lports on a eth
a device in later patches of this series.

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

 drivers/scsi/fcoe/fcoe.c     |    1 +
 drivers/scsi/libfc/fc_exch.c |   45 +++++++++++++++++++++++++++++++++++-------
 include/scsi/libfc.h         |   12 +++++++++++
 3 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 8870948..ab238fb 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -427,6 +427,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 {
        BUG_ON(lp->emp);
 
+       lp->oemp = NULL;
        lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
                                    FCOE_MIN_XID, FCOE_MAX_XID);
        if (!lp->emp)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index bbabd2c..bd6836b 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -57,6 +57,7 @@ struct fc_exch_mgr {
        enum fc_class   class;          /* default class for sequences */
        spinlock_t      em_lock;        /* exchange manager lock,
                                           must be taken before ex_lock */
+       u16             em_user;        /* exchange manager user count */
        u16             last_xid;       /* last allocated exchange ID */
        u16             min_xid;        /* min exchange ID */
        u16             max_xid;        /* max exchange ID */
@@ -1404,21 +1405,17 @@ static void fc_exch_reset(struct fc_exch *ep)
                resp(sp, ERR_PTR(-FC_EX_CLOSED), arg);
 }
 
-/*
- * Reset an exchange manager, releasing all sequences and exchanges.
- * If sid is non-zero, reset only exchanges we source from that FID.
- * If did is non-zero, reset only exchanges destined to that FID.
- */
-void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
+static void fc_exch_em_reset(struct fc_lport *lp, struct fc_exch_mgr *mp,
+                            u32 sid, u32 did)
 {
        struct fc_exch *ep;
        struct fc_exch *next;
-       struct fc_exch_mgr *mp = lp->emp;
 
        spin_lock_bh(&mp->em_lock);
 restart:
        list_for_each_entry_safe(ep, next, &mp->ex_list, ex_list) {
-               if ((sid == 0 || sid == ep->sid) &&
+               if ((lp == ep->lp) &&
+                   (sid == 0 || sid == ep->sid) &&
                    (did == 0 || did == ep->did)) {
                        fc_exch_hold(ep);
                        spin_unlock_bh(&mp->em_lock);
@@ -1437,6 +1434,18 @@ restart:
        }
        spin_unlock_bh(&mp->em_lock);
 }
+
+/*
+ * Reset exchange managers, releasing all sequences and exchanges.
+ * If sid is non-zero, reset only exchanges we source from that FID.
+ * If did is non-zero, reset only exchanges destined to that FID.
+ */
+void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
+{
+       fc_exch_em_reset(lp, lp->emp, sid, did);
+       if (lp->oemp)
+               fc_exch_em_reset(lp, lp->oemp, sid, did);
+}
 EXPORT_SYMBOL(fc_exch_mgr_reset);
 
 /*
@@ -1674,6 +1683,18 @@ reject:
        fc_frame_free(fp);
 }
 
+void fc_exch_mgr_inc(struct fc_exch_mgr *mp)
+{
+       mp->em_user++;
+}
+EXPORT_SYMBOL(fc_exch_mgr_inc);
+
+int fc_exch_mgr_dec(struct fc_exch_mgr *mp)
+{
+       return --mp->em_user;
+}
+EXPORT_SYMBOL(fc_exch_mgr_dec);
+
 struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
                                      enum fc_class class,
                                      u16 min_xid, u16 max_xid)
@@ -1713,6 +1734,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
        if (!mp->ep_pool)
                goto free_mp;
 
+       fc_exch_mgr_inc(mp);
        return mp;
 
 free_mp:
@@ -1724,6 +1746,13 @@ EXPORT_SYMBOL(fc_exch_mgr_alloc);
 void fc_exch_mgr_free(struct fc_exch_mgr *mp)
 {
        WARN_ON(!mp);
+
+       /*
+        * if still in use  then return
+        */
+       if (fc_exch_mgr_dec(mp))
+               return;
+
        /*
         * The total exch count must be zero
         * before freeing exchange manager.
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index dde73cf..967f6f6 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -705,6 +705,8 @@ struct fc_lport {
        /* Associations */
        struct Scsi_Host        *host;
        struct fc_exch_mgr      *emp;
+       struct fc_exch_mgr      *oemp;
+       struct list_head        em_list;
        struct fc_rport         *dns_rp;
        struct fc_rport         *ptp_rp;
        void                    *scsi_priv;
@@ -960,6 +962,16 @@ int fc_elsct_init(struct fc_lport *lp);
 int fc_exch_init(struct fc_lport *lp);
 
 /*
+ * Increments usages count of an Exchange Manager.
+ */
+void fc_exch_mgr_inc(struct fc_exch_mgr *mp);
+
+/*
+ * Decrements usages count of an Exchange Manager.
+ */
+int fc_exch_mgr_dec(struct fc_exch_mgr *mp);
+
+/*
  * Allocates an Exchange Manager (EM).
  *
  * The EM manages exchanges for their allocation and

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

Reply via email to