mirror of https://gitee.com/openkylin/linux.git
mlx4: fix potential divide by 0 in mlx4_en_auto_moderation()
1) In the case where rate == priv->pkt_rate_low == priv->pkt_rate_high, mlx4_en_auto_moderation() does a divide by zero. 2) We want to properly change the moderation parameters if rx_frames was changed (like in ethtool -C eth0 rx-frames 16) Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1786dbf370
commit
f5a5772337
|
@ -1382,6 +1382,7 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
|
|||
static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
|
||||
{
|
||||
unsigned long period = (unsigned long) (jiffies - priv->last_moder_jiffies);
|
||||
u32 pkt_rate_high, pkt_rate_low;
|
||||
struct mlx4_en_cq *cq;
|
||||
unsigned long packets;
|
||||
unsigned long rate;
|
||||
|
@ -1395,37 +1396,40 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
|
|||
if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
|
||||
return;
|
||||
|
||||
pkt_rate_low = READ_ONCE(priv->pkt_rate_low);
|
||||
pkt_rate_high = READ_ONCE(priv->pkt_rate_high);
|
||||
|
||||
for (ring = 0; ring < priv->rx_ring_num; ring++) {
|
||||
rx_packets = READ_ONCE(priv->rx_ring[ring]->packets);
|
||||
rx_bytes = READ_ONCE(priv->rx_ring[ring]->bytes);
|
||||
|
||||
rx_pkt_diff = ((unsigned long) (rx_packets -
|
||||
priv->last_moder_packets[ring]));
|
||||
rx_pkt_diff = rx_packets - priv->last_moder_packets[ring];
|
||||
packets = rx_pkt_diff;
|
||||
rate = packets * HZ / period;
|
||||
avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
|
||||
priv->last_moder_bytes[ring])) / packets : 0;
|
||||
avg_pkt_size = packets ? (rx_bytes -
|
||||
priv->last_moder_bytes[ring]) / packets : 0;
|
||||
|
||||
/* Apply auto-moderation only when packet rate
|
||||
* exceeds a rate that it matters */
|
||||
if (rate > (MLX4_EN_RX_RATE_THRESH / priv->rx_ring_num) &&
|
||||
avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
|
||||
if (rate < priv->pkt_rate_low)
|
||||
if (rate <= pkt_rate_low)
|
||||
moder_time = priv->rx_usecs_low;
|
||||
else if (rate > priv->pkt_rate_high)
|
||||
else if (rate >= pkt_rate_high)
|
||||
moder_time = priv->rx_usecs_high;
|
||||
else
|
||||
moder_time = (rate - priv->pkt_rate_low) *
|
||||
moder_time = (rate - pkt_rate_low) *
|
||||
(priv->rx_usecs_high - priv->rx_usecs_low) /
|
||||
(priv->pkt_rate_high - priv->pkt_rate_low) +
|
||||
(pkt_rate_high - pkt_rate_low) +
|
||||
priv->rx_usecs_low;
|
||||
} else {
|
||||
moder_time = priv->rx_usecs_low;
|
||||
}
|
||||
|
||||
if (moder_time != priv->last_moder_time[ring]) {
|
||||
cq = priv->rx_cq[ring];
|
||||
if (moder_time != priv->last_moder_time[ring] ||
|
||||
cq->moder_cnt != priv->rx_frames) {
|
||||
priv->last_moder_time[ring] = moder_time;
|
||||
cq = priv->rx_cq[ring];
|
||||
cq->moder_time = moder_time;
|
||||
cq->moder_cnt = priv->rx_frames;
|
||||
err = mlx4_en_set_cq_moder(priv, cq);
|
||||
|
|
Loading…
Reference in New Issue