diff options
author | alfred <alfred@FreeBSD.org> | 2013-11-08 22:29:07 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2013-11-08 22:29:07 +0000 |
commit | 204a78e2fcfb13aed43b7cd2006d6ddace4de688 (patch) | |
tree | 4f535886b316d4d78cd5a8c6a356b78b0375f6dc /sys | |
parent | 8964c3a79b724ffa28a2ade2c6c712bd3572ef8e (diff) | |
download | FreeBSD-src-204a78e2fcfb13aed43b7cd2006d6ddace4de688.zip FreeBSD-src-204a78e2fcfb13aed43b7cd2006d6ddace4de688.tar.gz |
MFC: r257862, r257863, r257864
r257862:
Use explicit long cast to avoid overflow in bitopts.
This was causing problems with the buddy allocator inside of
ofed.
r257863:
Fix for bad performance when mtu is increased.
Update the auto moderation behavior in the mlxen driver to match
the new LINUX OFED code.
r257864:
Do not use a sleep lock when protecting the driver flags.
This was causing a locking issue with lagg.
Approved by: re
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ofed/drivers/net/mlx4/en_ethtool.c | 12 | ||||
-rw-r--r-- | sys/ofed/drivers/net/mlx4/en_netdev.c | 97 | ||||
-rw-r--r-- | sys/ofed/drivers/net/mlx4/mlx4_en.h | 8 | ||||
-rw-r--r-- | sys/ofed/include/linux/bitops.h | 6 |
4 files changed, 53 insertions, 70 deletions
diff --git a/sys/ofed/drivers/net/mlx4/en_ethtool.c b/sys/ofed/drivers/net/mlx4/en_ethtool.c index f5b21d0..9279944 100644 --- a/sys/ofed/drivers/net/mlx4/en_ethtool.c +++ b/sys/ofed/drivers/net/mlx4/en_ethtool.c @@ -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; diff --git a/sys/ofed/drivers/net/mlx4/en_netdev.c b/sys/ofed/drivers/net/mlx4/en_netdev.c index fd7a189..dab792d 100644 --- a/sys/ofed/drivers/net/mlx4/en_netdev.c +++ b/sys/ofed/drivers/net/mlx4/en_netdev.c @@ -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; - - 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); - - 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 { + 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); + + 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; + + /* 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; } @@ -948,6 +919,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev) mtx_destroy(&priv->stats_lock.m); mtx_destroy(&priv->vlan_lock.m); + mtx_destroy(&priv->ioctl_lock.m); kfree(priv); if_free(dev); } @@ -1116,9 +1088,9 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data) break; case SIOCADDMULTI: case SIOCDELMULTI: - mutex_lock(&mdev->state_lock); + spin_lock(&priv->ioctl_lock); mlx4_en_set_multicast(dev); - mutex_unlock(&mdev->state_lock); + spin_unlock(&priv->ioctl_lock); break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: @@ -1539,6 +1511,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->msg_enable = MLX4_EN_MSG_LEVEL; priv->ip_reasm = priv->mdev->profile.ip_reasm; mtx_init(&priv->stats_lock.m, "mlx4 stats", NULL, MTX_DEF); + mtx_init(&priv->ioctl_lock.m, "mlx4 ioctl", NULL, MTX_DEF); mtx_init(&priv->vlan_lock.m, "mlx4 vlan", NULL, MTX_DEF); INIT_WORK(&priv->mcast_task, mlx4_en_do_set_multicast); INIT_WORK(&priv->watchdog_task, mlx4_en_restart); diff --git a/sys/ofed/drivers/net/mlx4/mlx4_en.h b/sys/ofed/drivers/net/mlx4/mlx4_en.h index f3f71c7..7f3c352 100644 --- a/sys/ofed/drivers/net/mlx4/mlx4_en.h +++ b/sys/ofed/drivers/net/mlx4/mlx4_en.h @@ -493,12 +493,13 @@ struct mlx4_en_priv { spinlock_t vlan_lock; struct mlx4_en_port_state port_state; spinlock_t stats_lock; + spinlock_t ioctl_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 +569,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); diff --git a/sys/ofed/include/linux/bitops.h b/sys/ofed/include/linux/bitops.h index 4ada708..bac688a 100644 --- a/sys/ofed/include/linux/bitops.h +++ b/sys/ofed/include/linux/bitops.h @@ -286,14 +286,14 @@ bitmap_empty(unsigned long *addr, int size) #define NBLONG (NBBY * sizeof(long)) #define set_bit(i, a) \ - atomic_set_long(&((volatile long *)(a))[(i)/NBLONG], 1 << (i) % NBLONG) + atomic_set_long(&((volatile long *)(a))[(i)/NBLONG], 1UL << (i) % NBLONG) #define clear_bit(i, a) \ - atomic_clear_long(&((volatile long *)(a))[(i)/NBLONG], 1 << (i) % NBLONG) + atomic_clear_long(&((volatile long *)(a))[(i)/NBLONG], 1UL << (i) % NBLONG) #define test_bit(i, a) \ !!(atomic_load_acq_long(&((volatile long *)(a))[(i)/NBLONG]) & \ - 1 << ((i) % NBLONG)) + 1UL << ((i) % NBLONG)) static inline long test_and_clear_bit(long bit, long *var) |