1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-13 10:02:38 +00:00

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->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;
@ -418,6 +418,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;
@ -456,6 +457,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;

View File

@ -318,6 +318,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++) {
@ -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->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)
@ -349,43 +349,29 @@ 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;
for (ring = 0; ring < priv->rx_ring_num; ring++) {
spin_lock(&priv->stats_lock); spin_lock(&priv->stats_lock);
rx_packets = priv->dev->if_ipackets; rx_packets = priv->rx_ring[ring].packets;
rx_bytes = priv->dev->if_ibytes; rx_bytes = priv->rx_ring[ring].bytes;
tx_packets = priv->dev->if_opackets;
spin_unlock(&priv->stats_lock); spin_unlock(&priv->stats_lock);
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 - rx_pkt_diff = ((unsigned long) (rx_packets -
priv->last_moder_packets)); priv->last_moder_packets[ring]));
packets = max(tx_pkt_diff, rx_pkt_diff); packets = rx_pkt_diff;
rate = packets * HZ / period; rate = packets * HZ / period;
avg_pkt_size = packets ? ((unsigned long) (rx_bytes - avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
priv->last_moder_bytes)) / packets : 0; priv->last_moder_bytes[ring])) / packets : 0;
/* Apply auto-moderation only when packet rate exceeds a rate that /* Apply auto-moderation only when packet rate
* it matters */ * exceeds a rate that it matters */
if (rate > MLX4_EN_RX_RATE_THRESH) { if (rate > (MLX4_EN_RX_RATE_THRESH / priv->rx_ring_num) &&
/* If tx and rx packet rates are not balanced, assume that avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
* 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 ||
avg_pkt_size < MLX4_EN_AVG_PKT_SMALL) avg_pkt_size < MLX4_EN_AVG_PKT_SMALL)
moder_time = priv->rx_usecs_low; 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->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 { } else {
/* When packet rate is low, use default moderation rather than moder_time = priv->rx_usecs_low;
* 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", if (moder_time != priv->last_moder_time[ring]) {
tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period); priv->last_moder_time[ring] = moder_time;
cq = &priv->rx_cq[ring];
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];
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;
} }

View File

@ -494,11 +494,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;
@ -568,7 +568,6 @@ enum mlx4_en_wol {
MLX4_EN_WOL_DO_MODIFY = (1ULL << 63), MLX4_EN_WOL_DO_MODIFY = (1ULL << 63),
}; };
int mlx4_en_transmit(struct net_device *dev, struct mbuf *mb); int mlx4_en_transmit(struct net_device *dev, struct mbuf *mb);
void mlx4_en_qflush(struct net_device *dev); void mlx4_en_qflush(struct net_device *dev);