goto out_netdev_cleanup;
        }
 
-       /* lport exch manager allocation */
-       rc = fcoe_em_config(lp);
+       /* Initialize the library */
+       rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
        if (rc) {
-               FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the "
+               FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
                                "interface\n");
-               goto out_netdev_cleanup;
+               goto out_lp_destroy;
        }
 
-       /* Initialize the library */
-       rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
+       /* lport exch manager allocation */
+       rc = fcoe_em_config(lp);
        if (rc) {
-               FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
+               FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the "
                                "interface\n");
                goto out_lp_destroy;
        }
 
  */
 struct fc_exch_mgr {
        enum fc_class   class;          /* default class for sequences */
+       struct kref     kref;           /* exchange mgr reference count */
        spinlock_t      em_lock;        /* exchange manager lock,
                                           must be taken before ex_lock */
        u16             last_xid;       /* last allocated exchange ID */
 };
 #define        fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
 
+struct fc_exch_mgr_anchor {
+       struct list_head ema_list;
+       struct fc_exch_mgr *mp;
+       bool (*match)(struct fc_frame *);
+};
+
 static void fc_exch_rrq(struct fc_exch *);
 static void fc_seq_ls_acc(struct fc_seq *);
 static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason,
        fc_frame_free(fp);
 }
 
+struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
+                                          struct fc_exch_mgr *mp,
+                                          bool (*match)(struct fc_frame *))
+{
+       struct fc_exch_mgr_anchor *ema;
+
+       ema = kmalloc(sizeof(*ema), GFP_ATOMIC);
+       if (!ema)
+               return ema;
+
+       ema->mp = mp;
+       ema->match = match;
+       /* add EM anchor to EM anchors list */
+       list_add_tail(&ema->ema_list, &lport->ema_list);
+       kref_get(&mp->kref);
+       return ema;
+}
+EXPORT_SYMBOL(fc_exch_mgr_add);
+
+static void fc_exch_mgr_destroy(struct kref *kref)
+{
+       struct fc_exch_mgr *mp = container_of(kref, struct fc_exch_mgr, kref);
+
+       /*
+        * The total exch count must be zero
+        * before freeing exchange manager.
+        */
+       WARN_ON(mp->total_exches != 0);
+       mempool_destroy(mp->ep_pool);
+       kfree(mp);
+}
+
+void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema)
+{
+       /* remove EM anchor from EM anchors list */
+       list_del(&ema->ema_list);
+       kref_put(&ema->mp->kref, fc_exch_mgr_destroy);
+       kfree(ema);
+}
+EXPORT_SYMBOL(fc_exch_mgr_del);
+
 struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
                                      enum fc_class class,
                                      u16 min_xid, u16 max_xid)
 
  */
 
 struct fc_exch_mgr;
+struct fc_exch_mgr_anchor;
 
 /*
  * Sequence.
        /* Associations */
        struct Scsi_Host        *host;
        struct fc_exch_mgr      *emp;
+       struct list_head        ema_list;
        struct fc_rport         *dns_rp;
        struct fc_rport         *ptp_rp;
        void                    *scsi_priv;
  */
 int fc_exch_init(struct fc_lport *lp);
 
+/*
+ * Adds Exchange Manager (EM) mp to lport.
+ *
+ * Adds specified mp to lport using struct fc_exch_mgr_anchor,
+ * the struct fc_exch_mgr_anchor allows same EM sharing by
+ * more than one lport with their specified match function,
+ * the match function is used in allocating exchange from
+ * added mp.
+ */
+struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
+                                          struct fc_exch_mgr *mp,
+                                          bool (*match)(struct fc_frame *));
+
+/*
+ * Deletes Exchange Manager (EM) from lport by removing
+ * its anchor ema from lport.
+ *
+ * If removed anchor ema was the last user of its associated EM
+ * then also destroys associated EM.
+ */
+void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema);
+
 /*
  * Allocates an Exchange Manager (EM).
  *