Commit 7ccdd084 authored by Rana Shahout's avatar Rana Shahout Committed by David S. Miller

net/mlx5e: Fix select queue callback

The default fallback function used by mlx5e select queue can return
any TX queues in range [0..dev->num_real_tx_queues).

The current implementation assumes that the fallback function returns
a number in the range [0.. number of channels).  Actually
dev->num_real_tx_queues = (number of channels) * dev->num_tc;
which is more than the expected range if num_tc is configured and could
lead to crashes.

To fix this we test if num_tc is not configured we can safely return the
fallback suggestion, if not we will reciprocal_scale the fallback
result and normalize it to the desired range.

Fixes: 08fb1dac ('net/mlx5e: Support DCBNL IEEE ETS')
Signed-off-by: default avatarRana Shahout <ranas@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Reported-by: default avatarDoug Ledford <dledford@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e3a19b53
...@@ -1707,8 +1707,11 @@ static void mlx5e_netdev_set_tcs(struct net_device *netdev) ...@@ -1707,8 +1707,11 @@ static void mlx5e_netdev_set_tcs(struct net_device *netdev)
netdev_set_num_tc(netdev, ntc); netdev_set_num_tc(netdev, ntc);
/* Map netdev TCs to offset 0
* We have our own UP to TXQ mapping for QoS
*/
for (tc = 0; tc < ntc; tc++) for (tc = 0; tc < ntc; tc++)
netdev_set_tc_queue(netdev, tc, nch, tc * nch); netdev_set_tc_queue(netdev, tc, nch, 0);
} }
int mlx5e_open_locked(struct net_device *netdev) int mlx5e_open_locked(struct net_device *netdev)
......
...@@ -110,8 +110,20 @@ u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb, ...@@ -110,8 +110,20 @@ u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
{ {
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
int channel_ix = fallback(dev, skb); int channel_ix = fallback(dev, skb);
int up = (netdev_get_num_tc(dev) && skb_vlan_tag_present(skb)) ? int up = 0;
skb->vlan_tci >> VLAN_PRIO_SHIFT : 0;
if (!netdev_get_num_tc(dev))
return channel_ix;
if (skb_vlan_tag_present(skb))
up = skb->vlan_tci >> VLAN_PRIO_SHIFT;
/* channel_ix can be larger than num_channels since
* dev->num_real_tx_queues = num_channels * num_tc
*/
if (channel_ix >= priv->params.num_channels)
channel_ix = reciprocal_scale(channel_ix,
priv->params.num_channels);
return priv->channeltc_to_txq_map[channel_ix][up]; return priv->channeltc_to_txq_map[channel_ix][up];
} }
......
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