> >>>>>
> >>>>>> Currently, there is a hard limitation on the PMD power management
> >>>>>> support that only allows it to support a single queue per lcore. This 
> >>>>>> is
> >>>>>> not ideal as most DPDK use cases will poll multiple queues per core.
> >>>>>>
> >>>>>> The PMD power management mechanism relies on ethdev Rx callbacks, so it
> >>>>>> is very difficult to implement such support because callbacks are
> >>>>>> effectively stateless and have no visibility into what the other ethdev
> >>>>>> devices are doing. This places limitations on what we can do within the
> >>>>>> framework of Rx callbacks, but the basics of this implementation are as
> >>>>>> follows:
> >>>>>>
> >>>>>> - Replace per-queue structures with per-lcore ones, so that any device
> >>>>>>      polled from the same lcore can share data
> >>>>>> - Any queue that is going to be polled from a specific lcore has to be
> >>>>>>      added to the list of queues to poll, so that the callback is 
> >>>>>> aware of
> >>>>>>      other queues being polled by the same lcore
> >>>>>> - Both the empty poll counter and the actual power saving mechanism is
> >>>>>>      shared between all queues polled on a particular lcore, and is 
> >>>>>> only
> >>>>>>      activated when all queues in the list were polled and were 
> >>>>>> determined
> >>>>>>      to have no traffic.
> >>>>>> - The limitation on UMWAIT-based polling is not removed because UMWAIT
> >>>>>>      is incapable of monitoring more than one address.
> >>>>>>
> >>>>>> Also, while we're at it, update and improve the docs.
> >>>>>>
> >>>>>> Signed-off-by: Anatoly Burakov <anatoly.bura...@intel.com>
> >>>>>> ---
> >>>>>>
> >>>>>> Notes:
> >>>>>>        v6:
> >>>>>>        - Track each individual queue sleep status (Konstantin)
> >>>>>>        - Fix segfault (Dave)
> >>>>>>
> >>>>>>        v5:
> >>>>>>        - Remove the "power save queue" API and replace it with 
> >>>>>> mechanism suggested by
> >>>>>>          Konstantin
> >>>>>>
> >>>>>>        v3:
> >>>>>>        - Move the list of supported NICs to NIC feature table
> >>>>>>
> >>>>>>        v2:
> >>>>>>        - Use a TAILQ for queues instead of a static array
> >>>>>>        - Address feedback from Konstantin
> >>>>>>        - Add additional checks for stopped queues
> >>>>>>
> >>>>
> >>>> <snip>
> >>>>
> >>>>> ....
> >>>>>> +static inline void
> >>>>>> +queue_reset(struct pmd_core_cfg *cfg, struct queue_list_entry *qcfg)
> >>>>>> +{
> >>>>>> +     const bool is_ready_to_sleep = qcfg->n_empty_polls > 
> >>>>>> EMPTYPOLL_MAX;
> >>>>>> +
> >>>>>> +     /* reset empty poll counter for this queue */
> >>>>>> +     qcfg->n_empty_polls = 0;
> >>>>>> +     /* reset the queue sleep counter as well */
> >>>>>> +     qcfg->n_sleeps = 0;
> >>>>>> +     /* remove the queue from list of cores ready to sleep */
> >>>>>> +     if (is_ready_to_sleep)
> >>>>>> +             cfg->n_queues_ready_to_sleep--;
> >>>>>> +     /*
> >>>>>> +      * no need change the lcore sleep target counter because this 
> >>>>>> lcore will
> >>>>>> +      * reach the n_sleeps anyway, and the other cores are already 
> >>>>>> counted so
> >>>>>> +      * there's no need to do anything else.
> >>>>>> +      */
> >>>>>> +}
> >>>>>> +
> >>>>>> +static inline bool
> >>>>>> +queue_can_sleep(struct pmd_core_cfg *cfg, struct queue_list_entry 
> >>>>>> *qcfg)
> >>>>>> +{
> >>>>>> +     /* this function is called - that means we have an empty poll */
> >>>>>> +     qcfg->n_empty_polls++;
> >>>>>> +
> >>>>>> +     /* if we haven't reached threshold for empty polls, we can't 
> >>>>>> sleep */
> >>>>>> +     if (qcfg->n_empty_polls <= EMPTYPOLL_MAX)
> >>>>>> +             return false;
> >>>>>> +
> >>>>>> +     /*
> >>>>>> +      * we've reached a point where we are able to sleep, but we 
> >>>>>> still need
> >>>>>> +      * to check if this queue has already been marked for sleeping.
> >>>>>> +      */
> >>>>>> +     if (qcfg->n_sleeps == cfg->sleep_target)
> >>>>>> +             return true;
> >>>>>> +
> >>>>>> +     /* mark this queue as ready for sleep */
> >>>>>> +     qcfg->n_sleeps = cfg->sleep_target;
> >>>>>> +     cfg->n_queues_ready_to_sleep++;
> >>>>>
> >>>>> So, assuming there is no incoming traffic, should it be:
> >>>>> 1) poll_all_queues(times=EMPTYPOLL_MAX); sleep; 
> >>>>> poll_all_queues(times=1); sleep; poll_all_queues(times=1); sleep; ...
> >>>>> OR
> >>>>> 2) poll_all_queues(times=EMPTYPOLL_MAX); sleep; poll_all_queues(times= 
> >>>>> EMPTYPOLL_MAX); sleep; poll_all_queues(times=
> >>>> EMPTYPOLL_MAX); sleep; ...
> >>>>> ?
> >>>>>
> >>>>> My initial thought was 2) but might be the intention is 1)?
> >>>>
> >>>>
> >>>> The intent is 1), not 2). There's no need to wait for more empty polls
> >>>> once we pass the threshold - we keep sleeping until there's traffic.
> >>>>
> >>>
> >>> Ok, then:
> >>> Acked-by: Konstantin Ananyev <konstantin.anan...@intel.com>
> >>>
> >>> Probably worth to put extra explanation here on in the doc,
> >>> to help people avoid wrong assumptions😉
> >>>
> >>
> >> I don't see value in going into such details. What would be the point?
> >> Like, what difference would this information make to anyone?
> >
> > I thought it is obvious: if you put extra explanation into the code,
> > then it would be easier for anyone who reads it 
> > (reviewers/maintainers/users)
> > to understand what it supposed to do.
> >
> 
> You're suggesting to put this *in the doc*, which implies that *the
> user* will find this information useful. I'm OK with adding this info as
> a comment somewhere perhaps, but why put it in the doc?

I don't really mind where you'll put it, either extra comments in that file,
or few lines in the doc - both are ok to me.



Reply via email to