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
