Vasu Dev wrote:
> 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.
It could just look for other users like it does at create(), and
don't use refcounts.
> 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.
I forgot fc_exch_mgr() was private, and I think it's nice to keep it that
way. If you want to use the refcounts, let's put them in fc_exch.c only,
and add get/set ops.
> Thanks for review comments and glad to see someone on the list reviewing
> patches carefully.
You're welcome. I have a large set of patches I'll send out soon. Hopefully
someone will look at those, too!
Joe
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel