From: Vasu Dev <[email protected]>

VN_Ports may share the same EM in the case of NPIV or
vlans. In those cases there would only be one EM per
physical port, but multiple lport instances. There would
be at least one EM for the port that would be shared across
all lports associated with the port.

A reference count is added to keep track of how many lports
are using the EMs.

This patch also removes unnecessary initialization of
mp->total_exches.

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

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

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 9fe1ead..e4ba631 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -416,7 +416,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 08ad41f..d429e8b 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 */
@@ -1732,13 +1733,26 @@ 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 (max_xid <= min_xid || min_xid == 0 || max_xid == FC_XID_UNKNOWN) {
+       /*
+        * 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_EM_DBG(mp, "Configuration 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);
                return NULL;
@@ -1756,7 +1770,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 */
@@ -1781,6 +1794,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;
@@ -1794,13 +1809,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 712fcaf..68f7a61 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -910,6 +910,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.
  *
@@ -925,6 +928,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