Commit 6b4d8d9f authored by Alexander Guller's avatar Alexander Guller Committed by David S. Miller

mlx4_en: Adjusting moderation per each ring

Moderation is now done per ring and coalescing is enabled
by set_ring_param in ethtool.
Signed-off-by: default avatarAlexander Guller <alexg@mellanox.co.il>
Signed-off-by: default avatarYevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fe0af03c
...@@ -342,13 +342,13 @@ static int mlx4_en_set_coalesce(struct net_device *dev, ...@@ -342,13 +342,13 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
priv->rx_usecs_high = coal->rx_coalesce_usecs_high; priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
priv->sample_interval = coal->rate_sample_interval; priv->sample_interval = coal->rate_sample_interval;
priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce; priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
priv->last_moder_time = MLX4_EN_AUTO_CONF;
if (priv->adaptive_rx_coal) if (priv->adaptive_rx_coal)
return 0; return 0;
for (i = 0; i < priv->rx_ring_num; i++) { for (i = 0; i < priv->rx_ring_num; i++) {
priv->rx_cq[i].moder_cnt = priv->rx_frames; priv->rx_cq[i].moder_cnt = priv->rx_frames;
priv->rx_cq[i].moder_time = priv->rx_usecs; priv->rx_cq[i].moder_time = priv->rx_usecs;
priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]); err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
if (err) if (err)
return err; return err;
...@@ -394,6 +394,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev, ...@@ -394,6 +394,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
u32 rx_size, tx_size; u32 rx_size, tx_size;
int port_up = 0; int port_up = 0;
int err = 0; int err = 0;
int i;
if (param->rx_jumbo_pending || param->rx_mini_pending) if (param->rx_jumbo_pending || param->rx_mini_pending)
return -EINVAL; return -EINVAL;
...@@ -432,6 +433,15 @@ static int mlx4_en_set_ringparam(struct net_device *dev, ...@@ -432,6 +433,15 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
en_err(priv, "Failed starting port\n"); en_err(priv, "Failed starting port\n");
} }
for (i = 0; i < priv->rx_ring_num; i++) {
priv->rx_cq[i].moder_cnt = priv->rx_frames;
priv->rx_cq[i].moder_time = priv->rx_usecs;
priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
if (err)
goto out;
}
out: out:
mutex_unlock(&mdev->state_lock); mutex_unlock(&mdev->state_lock);
return err; return err;
......
...@@ -415,6 +415,9 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv) ...@@ -415,6 +415,9 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
cq = &priv->rx_cq[i]; cq = &priv->rx_cq[i];
cq->moder_cnt = priv->rx_frames; cq->moder_cnt = priv->rx_frames;
cq->moder_time = priv->rx_usecs; cq->moder_time = priv->rx_usecs;
priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
priv->last_moder_packets[i] = 0;
priv->last_moder_bytes[i] = 0;
} }
for (i = 0; i < priv->tx_ring_num; i++) { for (i = 0; i < priv->tx_ring_num; i++) {
...@@ -430,11 +433,8 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv) ...@@ -430,11 +433,8 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH; priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH;
priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL; priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL;
priv->adaptive_rx_coal = 1; priv->adaptive_rx_coal = 1;
priv->last_moder_time = MLX4_EN_AUTO_CONF;
priv->last_moder_jiffies = 0; priv->last_moder_jiffies = 0;
priv->last_moder_packets = 0;
priv->last_moder_tx_packets = 0; priv->last_moder_tx_packets = 0;
priv->last_moder_bytes = 0;
} }
static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv) static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
...@@ -446,43 +446,30 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv) ...@@ -446,43 +446,30 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
unsigned long avg_pkt_size; unsigned long avg_pkt_size;
unsigned long rx_packets; unsigned long rx_packets;
unsigned long rx_bytes; unsigned long rx_bytes;
unsigned long tx_packets;
unsigned long tx_pkt_diff;
unsigned long rx_pkt_diff; unsigned long rx_pkt_diff;
int moder_time; int moder_time;
int i, err; int ring, err;
if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ) if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
return; return;
spin_lock_bh(&priv->stats_lock); for (ring = 0; ring < priv->rx_ring_num; ring++) {
rx_packets = priv->stats.rx_packets; spin_lock_bh(&priv->stats_lock);
rx_bytes = priv->stats.rx_bytes; rx_packets = priv->rx_ring[ring].packets;
tx_packets = priv->stats.tx_packets; rx_bytes = priv->rx_ring[ring].bytes;
spin_unlock_bh(&priv->stats_lock); spin_unlock_bh(&priv->stats_lock);
if (!priv->last_moder_jiffies || !period) rx_pkt_diff = ((unsigned long) (rx_packets -
goto out; priv->last_moder_packets[ring]));
packets = rx_pkt_diff;
tx_pkt_diff = ((unsigned long) (tx_packets - rate = packets * HZ / period;
priv->last_moder_tx_packets)); avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
rx_pkt_diff = ((unsigned long) (rx_packets - priv->last_moder_bytes[ring])) / packets : 0;
priv->last_moder_packets));
packets = max(tx_pkt_diff, rx_pkt_diff); /* Apply auto-moderation only when packet rate
rate = packets * HZ / period; * exceeds a rate that it matters */
avg_pkt_size = packets ? ((unsigned long) (rx_bytes - if (rate > (MLX4_EN_RX_RATE_THRESH / priv->rx_ring_num) &&
priv->last_moder_bytes)) / packets : 0; avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
/* Apply auto-moderation only when packet rate exceeds a rate that
* it matters */
if (rate > MLX4_EN_RX_RATE_THRESH && avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
/* If tx and rx packet rates are not balanced, assume that
* traffic is mainly BW bound and apply maximum moderation.
* Otherwise, moderate according to packet rate */
if (2 * tx_pkt_diff > 3 * rx_pkt_diff ||
2 * rx_pkt_diff > 3 * tx_pkt_diff) {
moder_time = priv->rx_usecs_high;
} else {
if (rate < priv->pkt_rate_low) if (rate < priv->pkt_rate_low)
moder_time = priv->rx_usecs_low; moder_time = priv->rx_usecs_low;
else if (rate > priv->pkt_rate_high) else if (rate > priv->pkt_rate_high)
...@@ -492,36 +479,23 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv) ...@@ -492,36 +479,23 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
(priv->rx_usecs_high - priv->rx_usecs_low) / (priv->rx_usecs_high - priv->rx_usecs_low) /
(priv->pkt_rate_high - priv->pkt_rate_low) + (priv->pkt_rate_high - priv->pkt_rate_low) +
priv->rx_usecs_low; priv->rx_usecs_low;
} else {
moder_time = priv->rx_usecs_low;
} }
} else {
moder_time = priv->rx_usecs_low;
}
en_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n",
tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period);
en_dbg(INTR, priv, "Rx moder_time changed from:%d to %d period:%lu " if (moder_time != priv->last_moder_time[ring]) {
"[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n", priv->last_moder_time[ring] = moder_time;
priv->last_moder_time, moder_time, period, packets, cq = &priv->rx_cq[ring];
avg_pkt_size, rate);
if (moder_time != priv->last_moder_time) {
priv->last_moder_time = moder_time;
for (i = 0; i < priv->rx_ring_num; i++) {
cq = &priv->rx_cq[i];
cq->moder_time = moder_time; cq->moder_time = moder_time;
err = mlx4_en_set_cq_moder(priv, cq); err = mlx4_en_set_cq_moder(priv, cq);
if (err) { if (err)
en_err(priv, "Failed modifying moderation for cq:%d\n", i); en_err(priv, "Failed modifying moderation "
break; "for cq:%d\n", ring);
}
} }
priv->last_moder_packets[ring] = rx_packets;
priv->last_moder_bytes[ring] = rx_bytes;
} }
out:
priv->last_moder_packets = rx_packets;
priv->last_moder_tx_packets = tx_packets;
priv->last_moder_bytes = rx_bytes;
priv->last_moder_jiffies = jiffies; priv->last_moder_jiffies = jiffies;
} }
......
...@@ -426,11 +426,11 @@ struct mlx4_en_priv { ...@@ -426,11 +426,11 @@ struct mlx4_en_priv {
struct mlx4_en_port_state port_state; struct mlx4_en_port_state port_state;
spinlock_t stats_lock; spinlock_t stats_lock;
unsigned long last_moder_packets; unsigned long last_moder_packets[MAX_RX_RINGS];
unsigned long last_moder_tx_packets; unsigned long last_moder_tx_packets;
unsigned long last_moder_bytes; unsigned long last_moder_bytes[MAX_RX_RINGS];
unsigned long last_moder_jiffies; unsigned long last_moder_jiffies;
int last_moder_time; int last_moder_time[MAX_RX_RINGS];
u16 rx_usecs; u16 rx_usecs;
u16 rx_frames; u16 rx_frames;
u16 tx_usecs; u16 tx_usecs;
......
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