This is to allow same offload xid em instance to be shared
by all VN_PORTs/lport on a eth device.

Adds em instance pointer mp to fc_exch_mgr_alloc and reference
counting for a em instance by added em_user counter.

The fc_exch_mgr_alloc adds specified mp to em_list of lport
and bumps up em_user count, the fc_exch_mgr_free does inverse
of this to free an mp.

Removes unnecessary initialization of mp->total_exches.

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

 drivers/scsi/fcoe/fcoe.c     |    2 +-
 drivers/scsi/libfc/fc_exch.c |   27 +++++++++++++++++++++++----
 include/scsi/libfc.h         |    4 ++++
 3 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index e829630..fde0f29 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -328,7 +328,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 {
        BUG_ON(lp->emp);
 
-       lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
+       lp->emp = fc_exch_mgr_alloc(lp, NULL, FC_CLASS_3,
                                    FCOE_MIN_XID, FCOE_MAX_XID);
        if (!lp->emp)
                return -ENOMEM;
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index bf50fc2..c640886 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -68,6 +68,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 */
@@ -1688,12 +1689,25 @@ reject:
 }
 
 struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
+                                     struct fc_exch_mgr *mp,
                                      enum fc_class class,
                                      u16 min_xid, u16 max_xid)
 {
-       struct fc_exch_mgr *mp;
        size_t len;
 
+       /*
+        * if an existing em instance specified
+        * then skip allocating new em instance
+        */
+       if (mp) {
+               if (mp->min_xid != min_xid || mp->max_xid != max_xid ||
+                   mp->class != class) {
+                       FC_DBG("Existing em instance config mismatched\n");
+                       return NULL;
+               }
+               goto add_em;
+       }
+
        if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
                FC_DBG("Invalid min_xid 0x:%x and max_xid 0x:%x\n",
                       min_xid, max_xid);
@@ -1711,7 +1725,6 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
                return NULL;
 
        mp->class = class;
-       mp->total_exches = 0;
        mp->exches = (struct fc_exch **)(mp + 1);
        mp->lp = lp;
        /* adjust em exch xid range for offload */
@@ -1726,6 +1739,8 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
        if (!mp->ep_pool)
                goto free_mp;
 
+add_em:
+       mp->em_user++;
        /* add em to the em_list */
        list_add_tail(&mp->em_list, &lp->em_list);
        return mp;
@@ -1739,13 +1754,17 @@ EXPORT_SYMBOL(fc_exch_mgr_alloc);
 void fc_exch_mgr_free(struct fc_exch_mgr *mp)
 {
        WARN_ON(!mp);
+
+       /* remove em from the em_list */
+       list_del(&mp->em_list);
+       if (--mp->em_user)
+               return;
+
        /*
         * The total exch count must be zero
         * before freeing exchange manager.
         */
        WARN_ON(mp->total_exches != 0);
-       /* remove em from the em_list */
-       list_del(&mp->em_list);
        mempool_destroy(mp->ep_pool);
        kfree(mp);
 }
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index edfd9da..9ec2b25 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -911,6 +911,9 @@ int fc_exch_init(struct fc_lport *lp);
  * free, also allows exchange lookup for received
  * frame.
  *
+ * Caller may specify an existing EM instance to be
+ * added to the fc_lport in mp instead allocating new EM.
+ *
  * The class is used for initializing FC class of
  * allocated exchange from EM.
  *
@@ -926,6 +929,7 @@ int fc_exch_init(struct fc_lport *lp);
  * The em_idx to uniquely identify an EM instance.
  */
 struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
+                                     struct fc_exch_mgr *mp,
                                      enum fc_class class,
                                      u16 min_xid,
                                      u16 max_xid);

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

Reply via email to