[dpdk-dev] [PATCH] net/ixgbe: fix reconfiguration of rx queues
Ananyev, Konstantin
konstantin.ananyev at intel.com
Tue Jan 30 14:14:12 CET 2018
> > >
> > > From: "Charles (Chas) Williams" <chas3 at att.com>
> > >
> > > .dev_configure() may be called again after RX queues have been setup.
> > > This has the effect of clearing whatever setting the RX queues made for
> > > rx_bulk_alloc_allowed or rx_vec_allowed. Only reset this configuration
> > > is there aren't any currently allocated queues.
> > >
> > > Fixes: 01fa1d6215fa ("ixgbe: unify Rx setup")
> > >
> > > Signed-off-by: Chas Williams <chas3 at att.com>
> > > ---
> > > drivers/net/ixgbe/ixgbe_ethdev.c | 18 ++++++++++++++++--
> > > 1 file changed, 16 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
> > > index 37eb668..b39249a 100644
> > > --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> > > +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> > > @@ -2348,6 +2348,7 @@ ixgbe_dev_configure(struct rte_eth_dev *dev)
> > > struct ixgbe_adapter *adapter =
> > > (struct ixgbe_adapter *)dev->data->dev_private;
> > > int ret;
> > > + uint16_t i;
> > >
> > > PMD_INIT_FUNC_TRACE();
> > > /* multipe queue mode checking */
> > > @@ -2363,11 +2364,17 @@ ixgbe_dev_configure(struct rte_eth_dev *dev)
> > >
> > > /*
> > > * Initialize to TRUE. If any of Rx queues doesn't meet the bulk
> > > - * allocation or vector Rx preconditions we will reset it.
> > > + * allocation or vector Rx preconditions we will reset it. We
> > > + * can only do this is there aren't any existing RX queues.
> > > */
> > > + for (i = 0; i < dev->data->nb_rx_queues; i++) {
> > > + if (dev->data->rx_queues[i])
> > > + goto out;
> > > + }
> > I don't see why this is needed.
> > It surely should be possible to reconfigure device with different
> > number of queues.
> > Konstantin
> >
> > Yes, you can add new queues but you shouldn't reset the bulk and vec settings
> > that have already been chosen by the previously allocated queues.
> Why is that? Might be in new queue setup user will change settings?
>
> There is no requirement that the user allocates all the RX queues in the same way.
> Some could have a different numbers of descs which is one of the checks in
> check_rx_burst_bulk_alloc_preconditions()
Exactly. That's why after dev_configure() user has to call queue_setup() for *all*
queues he plans to use.
>
>
>
> > If those queues
> > set rx_bulk_alloc_allowed to be false, then this is going to cause an issue with queue
> > release later on.
>
> Could you be a bit more specific here:
> What you think will be broken in ixgbe_rx_queue_release() in that case?
>
> Sorry, I mispoke. It's this function, ixgbe_reset_rx_queue(),
>
> /*
> * By default, the Rx queue setup function allocates enough memory for
> * IXGBE_MAX_RING_DESC. The Rx Burst bulk allocation function requires
> * extra memory at the end of the descriptor ring to be zero'd out.
> */
> if (adapter->rx_bulk_alloc_allowed)
> /* zero out extra memory */
> len += RTE_PMD_IXGBE_RX_MAX_BURST;
>
> /*
> * Zero out HW ring memory. Zero out extra memory at the end of
> * the H/W ring so look-ahead logic in Rx Burst bulk alloc function
> * reads extra memory as zeros.
> */
> for (i = 0; i < len; i++) {
> rxq->rx_ring[i] = zeroed_desc;
> }
>
> So you potentially write past the rx_ring[] you allocated.
We always allocate rx_ring[] to maximum possible size plus space for fake descriptors:
drivers/net/ixgbe/ixgbe_rxtx.h:
#define RX_RING_SZ ((IXGBE_MAX_RING_DESC + RTE_PMD_IXGBE_RX_MAX_BURST) * \
sizeof(union ixgbe_adv_rx_desc))
then at ixgbe_dev_rx_queue_setup(...):
/*
* Allocate RX ring hardware descriptors. A memzone large enough to
* handle the maximum ring size is allocated in order to allow for
* resizing in later calls to the queue setup function.
*/
rz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx,
RX_RING_SZ, IXGBE_ALIGN, socket_id);
...
rxq->rx_ring = (union ixgbe_adv_rx_desc *) rz->addr;
>
> You can't change rx_bulk_alloc_allowed once it has been set and you have allocated queues.
> In fact, you can't really let some later queue change this setting after the first queue decides
> what itshould be.
See above.
>
>
>
> > This breaks:
> >
> > rte_eth_dev_configure(..., 1, 1, ...);
> > rx_queue_setup(1)
> > [rx_queue_setup decides that it can't support rx_bulk_alloc_allowed]
> > ..
> >
> > Later, you want to add some more queues, you call
> >
> > eth_eth_dev_configure(..., 2, 2, ...);
>
> After you call dev_configure, you'll have to do queue_setup() for all your queues.
> dev_configure() can changes some global device settings, so each queue has to be
> reconfigured.
> In your example It should be:
> eth_eth_dev_configure(..., 2, 2, ...);
> rx_queue_setup(...,0, ...);
> rx_queue_setup(...,1, ...);
>
> Konstantin
>
>
> Nothing in the API says this must happen. If there where true, shouldn't rte_eth_dev_configure()
> automatically drop any existing queues?
One of the fists things that ixgbe_dev_rx_queue_setup() - calls ixgbe_rx_queue_release().
In theory that probably could be moved to rte_eth_dev_configure(), but I think current model is ok too.
>There is existing code that doesn't do this.
Then I think it is a bug in that code.
> Show me
> in the API where I am required to setup all my queues _again_ after calling rte_eth_dev_configure()
If you think the documentation doesn't explain that properly - feel free to raise a bug agains doc
and/or provide a patch for it.
As I explained above - dev_configure() might change some global settings
(max_rx_pkt, flow-director settings, etc.) that would affect each queue in that device.
So queue_setup() is necessary after dev_configure() to make sure it will operate properly.
Konstantin
>
>
> > rx_queue_setup(2)
> > [rx_queue_setup hopefully makes the same choice as rxqid = 1?]
> > ...
> >
> > Is one supposed to release all queues before calling rte_eth_dev_configure()? If
> > that is true, it seems like the change_mtu examples I see are possibly wrong. As
> > suggested in kenrel_nic_interface.rst:
> >
> >
> > ret = rte_eth_dev_configure(port_id, 1, 1, &conf);
> > if (ret < 0) {
> > RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id);
> > return ret;
> > }
> >
> > /* Restart specific port */
> >
> > ret = rte_eth_dev_start(port_id);
> > if (ret < 0) {
> > RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id);
> > return ret;
> > }
> >
> > This is will obviously reset the rx_bulk_alloc_allowed and not reallocated the RX queues.
> >
> >
> > > adapter->rx_bulk_alloc_allowed = true;
> > > adapter->rx_vec_allowed = true;
> > >
> > > +out:
> > > return 0;
> > > }
> > >
> > > @@ -4959,6 +4966,7 @@ ixgbevf_dev_configure(struct rte_eth_dev *dev)
> > > struct rte_eth_conf *conf = &dev->data->dev_conf;
> > > struct ixgbe_adapter *adapter =
> > > (struct ixgbe_adapter *)dev->data->dev_private;
> > > + uint16_t i;
> > >
> > > PMD_INIT_LOG(DEBUG, "Configured Virtual Function port id: %d",
> > > dev->data->port_id);
> > > @@ -4981,11 +4989,17 @@ ixgbevf_dev_configure(struct rte_eth_dev *dev)
> > >
> > > /*
> > > * Initialize to TRUE. If any of Rx queues doesn't meet the bulk
> > > - * allocation or vector Rx preconditions we will reset it.
> > > + * allocation or vector Rx preconditions we will reset it. We
> > > + * can only do this is there aren't any existing RX queues.
> > > */
> > > + for (i = 0; i < dev->data->nb_rx_queues; i++) {
> > > + if (dev->data->rx_queues[i])
> > > + goto out;
> > > + }
> > > adapter->rx_bulk_alloc_allowed = true;
> > > adapter->rx_vec_allowed = true;
> > >
> > > +out:
> > > return 0;
> > > }
> > >
> > > --
> > > 2.9.5
More information about the dev
mailing list