Fix for bad performance when mtu is increased.

Update the auto moderation behavior in the mlxen driver to match
the new LINUX OFED code.

Submitted by:	odeds
This commit is contained in:
Alfred Perlstein 2013-11-08 18:26:28 +00:00
parent 58f91ead4b
commit d3e98a133b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=257863
3 changed files with 43 additions and 63 deletions

View File

@ -366,13 +366,13 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
priv->sample_interval = coal->rate_sample_interval;
priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
priv->last_moder_time = MLX4_EN_AUTO_CONF;
if (priv->adaptive_rx_coal)
return 0;
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)
return err;
@ -418,6 +418,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
u32 rx_size, tx_size;
int port_up = 0;
int err = 0;
int i;
if (param->rx_jumbo_pending || param->rx_mini_pending)
return -EINVAL;
@ -456,6 +457,15 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
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:
mutex_unlock(&mdev->state_lock);
return err;

View File

@ -318,6 +318,9 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
cq = &priv->rx_cq[i];
cq->moder_cnt = priv->rx_frames;
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++) {
@ -333,11 +336,8 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH;
priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL;
priv->adaptive_rx_coal = 1;
priv->last_moder_time = MLX4_EN_AUTO_CONF;
priv->last_moder_jiffies = 0;
priv->last_moder_packets = 0;
priv->last_moder_tx_packets = 0;
priv->last_moder_bytes = 0;
}
static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
@ -349,43 +349,29 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
unsigned long avg_pkt_size;
unsigned long rx_packets;
unsigned long rx_bytes;
unsigned long tx_packets;
unsigned long tx_pkt_diff;
unsigned long rx_pkt_diff;
int moder_time;
int i, err;
int ring, err;
if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
return;
for (ring = 0; ring < priv->rx_ring_num; ring++) {
spin_lock(&priv->stats_lock);
rx_packets = priv->rx_ring[ring].packets;
rx_bytes = priv->rx_ring[ring].bytes;
spin_unlock(&priv->stats_lock);
spin_lock(&priv->stats_lock);
rx_packets = priv->dev->if_ipackets;
rx_bytes = priv->dev->if_ibytes;
tx_packets = priv->dev->if_opackets;
spin_unlock(&priv->stats_lock);
rx_pkt_diff = ((unsigned long) (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;
if (!priv->last_moder_jiffies || !period)
goto out;
tx_pkt_diff = ((unsigned long) (tx_packets -
priv->last_moder_tx_packets));
rx_pkt_diff = ((unsigned long) (rx_packets -
priv->last_moder_packets));
packets = max(tx_pkt_diff, rx_pkt_diff);
rate = packets * HZ / period;
avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
priv->last_moder_bytes)) / packets : 0;
/* Apply auto-moderation only when packet rate exceeds a rate that
* it matters */
if (rate > MLX4_EN_RX_RATE_THRESH) {
/* 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 {
/* 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 ||
avg_pkt_size < MLX4_EN_AVG_PKT_SMALL)
moder_time = priv->rx_usecs_low;
@ -396,38 +382,23 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
(priv->rx_usecs_high - priv->rx_usecs_low) /
(priv->pkt_rate_high - priv->pkt_rate_low) +
priv->rx_usecs_low;
} else {
moder_time = priv->rx_usecs_low;
}
} else {
/* When packet rate is low, use default moderation rather than
* 0 to prevent interrupt storms if traffic suddenly increases */
moder_time = priv->rx_usecs;
}
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 "
"[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n",
priv->last_moder_time, moder_time, period, packets,
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];
if (moder_time != priv->last_moder_time[ring]) {
priv->last_moder_time[ring] = moder_time;
cq = &priv->rx_cq[ring];
cq->moder_time = moder_time;
err = mlx4_en_set_cq_moder(priv, cq);
if (err) {
en_err(priv, "Failed modifying moderation for cq:%d\n", i);
break;
}
if (err)
en_err(priv, "Failed modifying moderation "
"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;
}

View File

@ -494,11 +494,11 @@ struct mlx4_en_priv {
struct mlx4_en_port_state port_state;
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_bytes;
unsigned long last_moder_bytes[MAX_RX_RINGS];
unsigned long last_moder_jiffies;
int last_moder_time;
int last_moder_time[MAX_RX_RINGS];
u16 rx_usecs;
u16 rx_frames;
u16 tx_usecs;
@ -568,7 +568,6 @@ enum mlx4_en_wol {
MLX4_EN_WOL_DO_MODIFY = (1ULL << 63),
};
int mlx4_en_transmit(struct net_device *dev, struct mbuf *mb);
void mlx4_en_qflush(struct net_device *dev);