Commit 800db2d1 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski

net: enetc: ensure we always have a minimum number of TXQs for stack

Currently it can happen that an mqprio qdisc is installed with num_tc 8,
and this will reserve 8 (out of 8) TXQs for the network stack. Then we
can attach an XDP program, and this will crop 2 TXQs, leaving just 6 for
mqprio. That's not what the user requested, and we should fail it.

On the other hand, if mqprio isn't requested, we still give the 8 TXQs
to the network stack (with hashing among a single traffic class), but
then, cropping 2 TXQs for XDP is fine, because the user didn't
explicitly ask for any number of TXQs, so no expectations are violated.

Simply put, the logic that mqprio should impose a minimum number of TXQs
for the network never existed. Let's say (more or less arbitrarily) that
without mqprio, the driver expects a minimum number of TXQs equal to the
number of CPUs (on NXP LS1028A, that is either 1, or 2). And with mqprio,
mqprio gives the minimum required number of TXQs.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 4ea1dd74
...@@ -2626,6 +2626,7 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) ...@@ -2626,6 +2626,7 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
if (!num_tc) { if (!num_tc) {
netdev_reset_tc(ndev); netdev_reset_tc(ndev);
netif_set_real_num_tx_queues(ndev, num_stack_tx_queues); netif_set_real_num_tx_queues(ndev, num_stack_tx_queues);
priv->min_num_stack_tx_queues = num_possible_cpus();
/* Reset all ring priorities to 0 */ /* Reset all ring priorities to 0 */
for (i = 0; i < priv->num_tx_rings; i++) { for (i = 0; i < priv->num_tx_rings; i++) {
...@@ -2656,6 +2657,7 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) ...@@ -2656,6 +2657,7 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
/* Reset the number of netdev queues based on the TC count */ /* Reset the number of netdev queues based on the TC count */
netif_set_real_num_tx_queues(ndev, num_tc); netif_set_real_num_tx_queues(ndev, num_tc);
priv->min_num_stack_tx_queues = num_tc;
netdev_set_num_tc(ndev, num_tc); netdev_set_num_tc(ndev, num_tc);
...@@ -2702,9 +2704,20 @@ static int enetc_reconfigure_xdp_cb(struct enetc_ndev_priv *priv, void *ctx) ...@@ -2702,9 +2704,20 @@ static int enetc_reconfigure_xdp_cb(struct enetc_ndev_priv *priv, void *ctx)
static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog, static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
int num_xdp_tx_queues = prog ? num_possible_cpus() : 0;
struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_ndev_priv *priv = netdev_priv(ndev);
bool extended; bool extended;
if (priv->min_num_stack_tx_queues + num_xdp_tx_queues >
priv->num_tx_rings) {
NL_SET_ERR_MSG_FMT_MOD(extack,
"Reserving %d XDP TXQs does not leave a minimum of %d TXQs for network stack (total %d available)",
num_xdp_tx_queues,
priv->min_num_stack_tx_queues,
priv->num_tx_rings);
return -EBUSY;
}
extended = !!(priv->active_offloads & ENETC_F_RX_TSTAMP); extended = !!(priv->active_offloads & ENETC_F_RX_TSTAMP);
/* The buffer layout is changing, so we need to drain the old /* The buffer layout is changing, so we need to drain the old
...@@ -2989,6 +3002,7 @@ int enetc_alloc_msix(struct enetc_ndev_priv *priv) ...@@ -2989,6 +3002,7 @@ int enetc_alloc_msix(struct enetc_ndev_priv *priv)
if (err) if (err)
goto fail; goto fail;
priv->min_num_stack_tx_queues = num_possible_cpus();
first_xdp_tx_ring = priv->num_tx_rings - num_possible_cpus(); first_xdp_tx_ring = priv->num_tx_rings - num_possible_cpus();
priv->xdp_tx_ring = &priv->tx_ring[first_xdp_tx_ring]; priv->xdp_tx_ring = &priv->tx_ring[first_xdp_tx_ring];
......
...@@ -369,6 +369,9 @@ struct enetc_ndev_priv { ...@@ -369,6 +369,9 @@ struct enetc_ndev_priv {
struct psfp_cap psfp_cap; struct psfp_cap psfp_cap;
/* Minimum number of TX queues required by the network stack */
unsigned int min_num_stack_tx_queues;
struct phylink *phylink; struct phylink *phylink;
int ic_mode; int ic_mode;
u32 tx_ictt; u32 tx_ictt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment