aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c44
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c330
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h90
-rw-r--r--include/linux/mlx4/device.h2
-rw-r--r--include/uapi/linux/ethtool.h1
-rw-r--r--net/core/ethtool.c1
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
1270static 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
1289static 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
1271const struct ethtool_ops mlx4_en_ethtool_ops = { 1313const 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;
153err_info: 153err_info:
154 vfree(ring->tx_info); 154 kvfree(ring->tx_info);
155 ring->tx_info = NULL; 155 ring->tx_info = NULL;
156err_ring: 156err_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)