diff options
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 44 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_tx.c | 330 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 90 | ||||
| -rw-r--r-- | include/linux/mlx4/device.h | 2 | ||||
| -rw-r--r-- | include/uapi/linux/ethtool.h | 1 | ||||
| -rw-r--r-- | net/core/ethtool.c | 1 |
6 files changed, 290 insertions, 178 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 42c9f8b09a6e..ae83da9cd18a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | |||
| @@ -1267,6 +1267,48 @@ static u32 mlx4_en_get_priv_flags(struct net_device *dev) | |||
| 1267 | return priv->pflags; | 1267 | return priv->pflags; |
| 1268 | } | 1268 | } |
| 1269 | 1269 | ||
| 1270 | static int mlx4_en_get_tunable(struct net_device *dev, | ||
| 1271 | const struct ethtool_tunable *tuna, | ||
| 1272 | void *data) | ||
| 1273 | { | ||
| 1274 | const struct mlx4_en_priv *priv = netdev_priv(dev); | ||
| 1275 | int ret = 0; | ||
| 1276 | |||
| 1277 | switch (tuna->id) { | ||
| 1278 | case ETHTOOL_TX_COPYBREAK: | ||
| 1279 | *(u32 *)data = priv->prof->inline_thold; | ||
| 1280 | break; | ||
| 1281 | default: | ||
| 1282 | ret = -EINVAL; | ||
| 1283 | break; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | return ret; | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | static int mlx4_en_set_tunable(struct net_device *dev, | ||
| 1290 | const struct ethtool_tunable *tuna, | ||
| 1291 | const void *data) | ||
| 1292 | { | ||
| 1293 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
| 1294 | int val, ret = 0; | ||
| 1295 | |||
| 1296 | switch (tuna->id) { | ||
| 1297 | case ETHTOOL_TX_COPYBREAK: | ||
| 1298 | val = *(u32 *)data; | ||
| 1299 | if (val < MIN_PKT_LEN || val > MAX_INLINE) | ||
| 1300 | ret = -EINVAL; | ||
| 1301 | else | ||
| 1302 | priv->prof->inline_thold = val; | ||
| 1303 | break; | ||
| 1304 | default: | ||
| 1305 | ret = -EINVAL; | ||
| 1306 | break; | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | return ret; | ||
| 1310 | } | ||
| 1311 | |||
| 1270 | 1312 | ||
| 1271 | const struct ethtool_ops mlx4_en_ethtool_ops = { | 1313 | const struct ethtool_ops mlx4_en_ethtool_ops = { |
| 1272 | .get_drvinfo = mlx4_en_get_drvinfo, | 1314 | .get_drvinfo = mlx4_en_get_drvinfo, |
| @@ -1297,6 +1339,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { | |||
| 1297 | .get_ts_info = mlx4_en_get_ts_info, | 1339 | .get_ts_info = mlx4_en_get_ts_info, |
| 1298 | .set_priv_flags = mlx4_en_set_priv_flags, | 1340 | .set_priv_flags = mlx4_en_set_priv_flags, |
| 1299 | .get_priv_flags = mlx4_en_get_priv_flags, | 1341 | .get_priv_flags = mlx4_en_get_priv_flags, |
| 1342 | .get_tunable = mlx4_en_get_tunable, | ||
| 1343 | .set_tunable = mlx4_en_set_tunable, | ||
| 1300 | }; | 1344 | }; |
| 1301 | 1345 | ||
| 1302 | 1346 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 0c501253fdab..92a7cf46d9af 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/mlx4/qp.h> | 37 | #include <linux/mlx4/qp.h> |
| 38 | #include <linux/skbuff.h> | 38 | #include <linux/skbuff.h> |
| 39 | #include <linux/if_vlan.h> | 39 | #include <linux/if_vlan.h> |
| 40 | #include <linux/prefetch.h> | ||
| 40 | #include <linux/vmalloc.h> | 41 | #include <linux/vmalloc.h> |
| 41 | #include <linux/tcp.h> | 42 | #include <linux/tcp.h> |
| 42 | #include <linux/ip.h> | 43 | #include <linux/ip.h> |
| @@ -65,10 +66,9 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, | |||
| 65 | ring->size = size; | 66 | ring->size = size; |
| 66 | ring->size_mask = size - 1; | 67 | ring->size_mask = size - 1; |
| 67 | ring->stride = stride; | 68 | ring->stride = stride; |
| 68 | ring->inline_thold = priv->prof->inline_thold; | ||
| 69 | 69 | ||
| 70 | tmp = size * sizeof(struct mlx4_en_tx_info); | 70 | tmp = size * sizeof(struct mlx4_en_tx_info); |
| 71 | ring->tx_info = vmalloc_node(tmp, node); | 71 | ring->tx_info = kmalloc_node(tmp, GFP_KERNEL | __GFP_NOWARN, node); |
| 72 | if (!ring->tx_info) { | 72 | if (!ring->tx_info) { |
| 73 | ring->tx_info = vmalloc(tmp); | 73 | ring->tx_info = vmalloc(tmp); |
| 74 | if (!ring->tx_info) { | 74 | if (!ring->tx_info) { |
| @@ -151,7 +151,7 @@ err_bounce: | |||
| 151 | kfree(ring->bounce_buf); | 151 | kfree(ring->bounce_buf); |
| 152 | ring->bounce_buf = NULL; | 152 | ring->bounce_buf = NULL; |
| 153 | err_info: | 153 | err_info: |
| 154 | vfree(ring->tx_info); | 154 | kvfree(ring->tx_info); |
| 155 | ring->tx_info = NULL; | 155 | ring->tx_info = NULL; |
| 156 | err_ring: | 156 | err_ring: |
| 157 | kfree(ring); | 157 | kfree(ring); |
| @@ -174,7 +174,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, | |||
| 174 | mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); | 174 | mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); |
| 175 | kfree(ring->bounce_buf); | 175 | kfree(ring->bounce_buf); |
| 176 | ring->bounce_buf = NULL; | 176 | ring->bounce_buf = NULL; |
| 177 | vfree(ring->tx_info); | 177 | kvfree(ring->tx_info); |
| 178 | ring->tx_info = NULL; | 178 | ring->tx_info = NULL; |
| 179 | kfree(ring); | 179 | kfree(ring); |
| 180 | *pring = NULL; | 180 | *pring = NULL; |
| @@ -191,12 +191,12 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv, | |||
| 191 | ring->prod = 0; | 191 | ring->prod = 0; |
| 192 | ring->cons = 0xffffffff; | 192 | ring->cons = 0xffffffff; |
| 193 | ring->last_nr_txbb = 1; | 193 | ring->last_nr_txbb = 1; |
| 194 | ring->poll_cnt = 0; | ||
| 195 | memset(ring->tx_info, 0, ring->size * sizeof(struct mlx4_en_tx_info)); | 194 | memset(ring->tx_info, 0, ring->size * sizeof(struct mlx4_en_tx_info)); |
| 196 | memset(ring->buf, 0, ring->buf_size); | 195 | memset(ring->buf, 0, ring->buf_size); |
| 197 | 196 | ||
| 198 | ring->qp_state = MLX4_QP_STATE_RST; | 197 | ring->qp_state = MLX4_QP_STATE_RST; |
| 199 | ring->doorbell_qpn = ring->qp.qpn << 8; | 198 | ring->doorbell_qpn = cpu_to_be32(ring->qp.qpn << 8); |
| 199 | ring->mr_key = cpu_to_be32(mdev->mr.key); | ||
| 200 | 200 | ||
| 201 | mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn, | 201 | mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn, |
| 202 | ring->cqn, user_prio, &ring->context); | 202 | ring->cqn, user_prio, &ring->context); |
| @@ -259,38 +259,45 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv, | |||
| 259 | struct mlx4_en_tx_ring *ring, | 259 | struct mlx4_en_tx_ring *ring, |
| 260 | int index, u8 owner, u64 timestamp) | 260 | int index, u8 owner, u64 timestamp) |
| 261 | { | 261 | { |
| 262 | struct mlx4_en_dev *mdev = priv->mdev; | ||
| 263 | struct mlx4_en_tx_info *tx_info = &ring->tx_info[index]; | 262 | struct mlx4_en_tx_info *tx_info = &ring->tx_info[index]; |
| 264 | struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE; | 263 | struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE; |
| 265 | struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset; | 264 | struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset; |
| 266 | struct sk_buff *skb = tx_info->skb; | ||
| 267 | struct skb_frag_struct *frag; | ||
| 268 | void *end = ring->buf + ring->buf_size; | 265 | void *end = ring->buf + ring->buf_size; |
| 269 | int frags = skb_shinfo(skb)->nr_frags; | 266 | struct sk_buff *skb = tx_info->skb; |
| 267 | int nr_maps = tx_info->nr_maps; | ||
| 270 | int i; | 268 | int i; |
| 271 | struct skb_shared_hwtstamps hwts; | ||
| 272 | 269 | ||
| 273 | if (timestamp) { | 270 | /* We do not touch skb here, so prefetch skb->users location |
| 274 | mlx4_en_fill_hwtstamps(mdev, &hwts, timestamp); | 271 | * to speedup consume_skb() |
| 272 | */ | ||
| 273 | prefetchw(&skb->users); | ||
| 274 | |||
| 275 | if (unlikely(timestamp)) { | ||
| 276 | struct skb_shared_hwtstamps hwts; | ||
| 277 | |||
| 278 | mlx4_en_fill_hwtstamps(priv->mdev, &hwts, timestamp); | ||
| 275 | skb_tstamp_tx(skb, &hwts); | 279 | skb_tstamp_tx(skb, &hwts); |
| 276 | } | 280 | } |
| 277 | 281 | ||
| 278 | /* Optimize the common case when there are no wraparounds */ | 282 | /* Optimize the common case when there are no wraparounds */ |
| 279 | if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) { | 283 | if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) { |
| 280 | if (!tx_info->inl) { | 284 | if (!tx_info->inl) { |
| 281 | if (tx_info->linear) { | 285 | if (tx_info->linear) |
