On Tue, 2009-06-02 at 10:18 -0700, Joe Eykholt wrote:
> 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.
> 

Make sense to improve this API by having one less arg but how are we
going to reset all exchanges when a rport going away since currently in
that case we call this API twice to reset all exchanges for a going away
rport.

        lport->tt.exch_mgr_reset(lport, 0, port_id);
        lport->tt.exch_mgr_reset(lport, port_id, 0);

As I understand this could be fixed by fixing fc_exch_em_reset() to
check sid and did along with exchange esb_state checking and then call
this API only once with lport and port_id. This might require moving
exch_lock before making check for exch selection in fc_exch_em_reset to
check exch context in esb_stat.

This would change API and will also require changes to fnic also, so
this can be done in another patch as you said above.

> >                     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.
> 

Make sense to redo this another way suggested above for reasons
mentioned by you above, I started with em_list in my initial post with
intent to have just one common reset for shared oemp or non-shared
lp->emp but later realized that won't work for shared oemp as oemp
cannot be put on two lists with one list_head, so we can't have common
reset code that way for oemp. So I'll move above  oemp reset code to
fcoe.ko.

> 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.
> 

I think having reference count in libfc fc_exch_mgr will be more helpful
for fcoe.ko to get hold of same oemp across fcoe_softc and free the same
EM by reference count tracking, otherwise fcoe.ko has to allocate
another shared struct around oemp to easily keep track of fc_exch_mgr
reference count. 

I'll do that using kref in fc_exch_mgr as you suggested in other
response.

However to avoid more APIs to just hold or release EM, I could move
fc_exch_mgr to libfc.h and then have fcoe.ko directly update reference
count.

Thanks for review comments and glad to see someone on the list reviewing
patches carefully.

        Vasu  

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

Reply via email to