net/mlx5e: Avoid accessing NULL pointer at ndo_select_queue
authorRana Shahout <ranas@mellanox.com>
Sun, 23 Aug 2015 13:12:14 +0000 (16:12 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 25 Aug 2015 20:45:09 +0000 (13:45 -0700)
To avoid multiply/division operations on the data path,
we hold a {channel, tc}==>txq mapping table.
We held this mapping table inside the channel object that is
being destroyed upon some configuration operations (e.g MTU change).
So in case ndo_select_queue occurs during such a configuration operation,
it may access a NULL channel pointer, resulting in kernel panic.
To fix this issue we moved the {channel, tc}==>txq mapping table
outside the channel object so that it will be available also
during such configuration operations.

Signed-off-by: Rana Shahout <ranas@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c

index 27ca4596775af4b29666b323b9e45e42378041f5..0983a208b299531e2ffb1ebc1aa6c710ed671a31 100644 (file)
@@ -405,7 +405,6 @@ struct mlx5e_channel {
        __be32                     mkey_be;
        u8                         num_tc;
        unsigned long              flags;
-       int                        tc_to_txq_map[MLX5E_MAX_NUM_TC];
 
        /* control */
        struct mlx5e_priv         *priv;
@@ -475,6 +474,7 @@ struct mlx5e_priv {
        /* priv data path fields - start */
        int                        default_vlan_prio;
        struct mlx5e_sq            **txq_to_sq_map;
+       int channeltc_to_txq_map[MLX5E_MAX_NUM_CHANNELS][MLX5E_MAX_NUM_TC];
        /* priv data path fields - end */
 
        unsigned long              state;
index 55166dd5b4ea5a16f77c91b6a2dc6cfb9a88b77e..59874d666cfff00dc92f23418039f599a6e42077 100644 (file)
@@ -949,13 +949,13 @@ static void mlx5e_close_sqs(struct mlx5e_channel *c)
                mlx5e_close_sq(&c->sq[tc]);
 }
 
-static void mlx5e_build_tc_to_txq_map(struct mlx5e_channel *c,
-                                     int num_channels)
+static void mlx5e_build_channeltc_to_txq_map(struct mlx5e_priv *priv, int ix)
 {
        int i;
 
        for (i = 0; i < MLX5E_MAX_NUM_TC; i++)
-               c->tc_to_txq_map[i] = c->ix + i * num_channels;
+               priv->channeltc_to_txq_map[ix][i] =
+                       ix + i * priv->params.num_channels;
 }
 
 static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
@@ -979,7 +979,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
        c->mkey_be  = cpu_to_be32(priv->mr.key);
        c->num_tc   = priv->params.num_tc;
 
-       mlx5e_build_tc_to_txq_map(c, priv->params.num_channels);
+       mlx5e_build_channeltc_to_txq_map(priv, ix);
 
        netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64);
 
index 64380bc0cd6a5df34b99531c0565718a4d2b207c..b73672f32e2c688169c4e37e44bcf0a5cbf065a7 100644 (file)
@@ -106,7 +106,7 @@ u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
                 priv->default_vlan_prio;
        int tc = netdev_get_prio_tc_map(dev, up);
 
-       return priv->channel[channel_ix]->tc_to_txq_map[tc];
+       return priv->channeltc_to_txq_map[channel_ix][tc];
 }
 
 static inline u16 mlx5e_get_inline_hdr_size(struct mlx5e_sq *sq,