Vasu Dev wrote:
> 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)) {
BTW, I was also thinking that passing both sid and did to the
fc_exch_mgr_reset should be eliminated. We only need to pass one
fc_id, and the local port fc_id is implied. We reset all
exchanges that match the local port and the specified fc_id (or, if
zero is specified, any at all). I can submit a separate patch for
that later.
> 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);
This is OK, but another way to do this is to have the fcoe LLD implement
the transport pointer for fc_exch_mgr_reset() and call fc_exch_mgr_reset()
for both EMs.
That way, other LLDs that don't offload, or offload differently,
wouldn't be exposed to oemp. Oemp could just be in fcoe_softc, and not
in the local port.
Also, since the fcoe driver knows how many users have the same oemp, you
don't need a refcount at all (although that's not so bad). The refcount
could be entirely managed in fcoe, eliminating the incr/decr interfaces.
> /*
> @@ -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
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel