mlx4_en: Multiqueue support
Subsystems (2)
PATCH v2 9/9 mlx4_en: Multiqueue support
Added a function that performs hashing on the TX traffic. The hashing is only done for TCP or UDP packets, all other packets are sent to a default queue.
We use an indirection table with an entry for each hash result. For each entry in the table, we hold statistics regarding the stream that corresponds to that entry. Packets are then directed to a TX queue according to stream's pattern.
A ring is opened for each queue.
--- drivers/net/mlx4/en_netdev.c | 16 +++++++++- drivers/net/mlx4/en_params.c | 9 +---- drivers/net/mlx4/en_tx.c | 64 ++++++++++++++++++++++++++++++++--------- drivers/net/mlx4/mlx4_en.h | 17 ++++++++++- 4 files changed, 81 insertions(+), 25 deletions(-)
drivers/net/mlx4/en_netdev.c +14 -2
@@ -645,6 +645,16 @@ int mlx4_en_start_port(struct net_device *dev) ++tx_index; } +for (i =0 ; i <MLX4_EN_TX_HASH_SIZE ; i++) { +memset (&priv->tx_hash[i],0 ,sizeof (struct mlx4_en_tx_hash_entry )); +/* +* Initially, all streams are assigned to the rings +* that should handle the small packages streams, (the lower ring +* indixes) then moved according the stream charasteristics. +*/ + priv->tx_hash[i].ring = i & (MLX4_EN_NUM_HASH_RINGS /2 -1 ); + } +/* Configure port */ err = mlx4_SET_PORT_general(mdev->dev, priv->port, priv->rx_skb_size + ETH_FCS_LEN,
@@ -949,6 +959,7 @@ static const struct net_device_ops mlx4_netdev_ops = { .ndo_open = mlx4_en_open, .ndo_stop = mlx4_en_close, .ndo_start_xmit = mlx4_en_xmit, + .ndo_select_queue = mlx4_en_select_queue, .ndo_get_stats = mlx4_en_get_stats, .ndo_set_multicast_list = mlx4_en_set_multicast, .ndo_set_mac_address = mlx4_en_set_mac,
@@ -970,7 +981,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,int i;int err; - dev =alloc_etherdev (sizeof (struct mlx4_en_priv )); + dev =alloc_etherdev_mq (sizeof (struct mlx4_en_priv ), prof->tx_ring_num);if (dev ==NULL ) {mlx4_err (mdev,"Net device allocation failed\n" );return -ENOMEM ;
@@ -1033,7 +1044,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->allocated =1 ;/* Populate Tx priority mappings */ -mlx4_en_set_prio_map (priv, priv->tx_prio_map, prof->tx_ring_num); +mlx4_en_set_prio_map (priv, priv->tx_prio_map, + prof->tx_ring_num -MLX4_EN_NUM_HASH_RINGS );/* * Initialize netdev entry points
drivers/net/mlx4/en_params.c +2 -7
@@ -80,13 +80,8 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->prof[i].tx_ppp = pfctx; params->prof[i].tx_ring_size =MLX4_EN_DEF_TX_RING_SIZE ; params->prof[i].rx_ring_size =MLX4_EN_DEF_RX_RING_SIZE ; - } -if (pfcrx || pfctx) { - params->prof[1 ].tx_ring_num =MLX4_EN_TX_RING_NUM ; - params->prof[2 ].tx_ring_num =MLX4_EN_TX_RING_NUM ; - }else { - params->prof[1 ].tx_ring_num =1 ; - params->prof[2 ].tx_ring_num =1 ; + params->prof[i].tx_ring_num =MLX4_EN_NUM_HASH_RINGS +1 + + (!!pfcrx) *MLX4_EN_NUM_PPP_RINGS ; }return 0 ;
drivers/net/mlx4/en_tx.c +50 -14
107 lines not on this page · raw message
drivers/net/mlx4/mlx4_en.h +15 -2
@@ -119,8 +119,12 @@ enum {#define MLX4_EN_MIN_RX_SIZE (MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES)#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE) -#define MLX4_EN_TX_RING_NUM 9 -#define MLX4_EN_DEF_TX_RING_SIZE 1024 +#define MLX4_EN_SMALL_PKT_SIZE 128 +#define MLX4_EN_TX_HASH_SIZE 256 +#define MLX4_EN_TX_HASH_MASK (MLX4_EN_TX_HASH_SIZE - 1) +#define MLX4_EN_NUM_HASH_RINGS 8 +#define MLX4_EN_NUM_PPP_RINGS 8 +#define MLX4_EN_DEF_TX_RING_SIZE 512#define MLX4_EN_DEF_RX_RING_SIZE 1024/* Target number of bytes to coalesce with interrupt moderation */
@@ -416,6 +420,13 @@ struct mlx4_en_frag_info { }; +struct mlx4_en_tx_hash_entry { +u8 cnt; +unsigned int small_pkts; +unsigned int big_pkts; +u16 ring; +}; +struct mlx4_en_priv {struct mlx4_en_dev *mdev;struct mlx4_en_port_profile *prof;
@@ -471,6 +482,7 @@ struct mlx4_en_priv {struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS ];struct mlx4_en_cq tx_cq[MAX_TX_RINGS ];struct mlx4_en_cq rx_cq[MAX_RX_RINGS ]; +struct mlx4_en_tx_hash_entry tx_hash[MLX4_EN_TX_HASH_SIZE ];struct work_struct mcast_task;struct work_struct mac_task;struct delayed_work refill_task;
@@ -508,6 +520,7 @@ int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);void mlx4_en_poll_tx_cq (unsigned long data);void mlx4_en_tx_irq (struct mlx4_cq *mcq);int mlx4_en_xmit (struct sk_buff *skb,struct net_device *dev); +u16 mlx4_en_select_queue (struct net_device *dev,struct sk_buff *skb);int mlx4_en_create_tx_ring (struct mlx4_en_priv *priv,struct mlx4_en_tx_ring *ring,u32 size,u16 stride);
Signature · 1 line
1.5.4
David Miller
maintainerFrom: Yevgeny Petrilin <[email protected]>
Date: Mon, 29 Dec 2008 11:57:09 +0200
Quoted 10 lines
Added a function that performs hashing on the TX traffic. The hashing is only done for TCP or UDP packets, all other packets are sent to a default queue.
We use an indirection table with an entry for each hash result. For each entry in the table, we hold statistics regarding the stream that corresponds to that entry. Packets are then directed to a TX queue according to stream's pattern.
A ring is opened for each queue.Signed-off-by Yevgeny Petrilin <[email protected]>
You are not supposed to provide a driver private function to hash the traffic.
The generic code already hashes traffic for you, and whatever it doesn't handle currently will be handled in the future. The generic code is where gaps should be filled in.
The override function pointer is only for wireless which has special needs in queue selection that have nothing to do with flow seperation.
Please resubmit this without your private hashing function.
Thank you.
Quoted 11 lines · David Miller
You are not supposed to provide a driver private function to hash the traffic.
The generic code already hashes traffic for you, and whatever it doesn't handle currently will be handled in the future. The generic code is where gaps should be filled in.
The override function pointer is only for wireless which has special needs in queue selection that have nothing to do with flow seperation.
The generic hash function (simple_tx_hash) doesn't consider Vlan priority when making the hash. When working in Per Priority Pause mode, packets with different Vlan priority should be sent from a different transmit queue. How can we ensure this without using private hashing function?
Thank you,
Yevgeny.
David Miller
maintainerFrom: Yevgeny Petrilin <[email protected]>
Date: Tue, 30 Dec 2008 18:54:58 +0200
Quoted 2 lines
The generic hash function (
simple_tx_hash) doesn't consider Vlan priority when making the hash.
Then fix it to take VLAN into account.