aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox
diff options
context:
space:
mode:
authorAmir Vadai <amirv@mellanox.com>2013-04-23 02:06:49 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-24 16:30:14 -0400
commitec693d47010e8302e61e0bdf3f47496c5610641a (patch)
tree8fbcfe632cb618318dcb1c9a9050afd025462b0a /drivers/net/ethernet/mellanox
parentddd8a6c12d7e494902a9435a9a7a543ef730b2d8 (diff)
net/mlx4_en: Add HW timestamping (TS) support
The patch allows to enable/disable HW timestamping for incoming and/or outgoing packets. It adds and initializes all structs and callbacks needed by kernel TS API. To enable/disable HW timestamping appropriate ioctl should be used. Currently HWTSTAMP_FILTER_ALL/NONE and HWTSAMP_TX_ON/OFF only are supported. When enabling TS on receive flow - VLAN stripping will be disabled. Also were made all relevant changes in RX/TX flows to consider TS request and plant HW timestamps into relevant structures. mlx4_ib was fixed to compile with new mlx4_cq_alloc() signature. Signed-off-by: Eugenia Emantayev <eugenia@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/Makefile2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cq.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_clock.c132
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_cq.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c30
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c75
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_resources.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c29
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c29
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h21
12 files changed, 353 insertions, 15 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/Makefile b/drivers/net/ethernet/mellanox/mlx4/Makefile
index 293127d28b33..3e9c70f15b42 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx4/Makefile
@@ -6,5 +6,5 @@ mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
6obj-$(CONFIG_MLX4_EN) += mlx4_en.o 6obj-$(CONFIG_MLX4_EN) += mlx4_en.o
7 7
8mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \ 8mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \
9 en_resources.o en_netdev.o en_selftest.o 9 en_resources.o en_netdev.o en_selftest.o en_clock.o
10mlx4_en-$(CONFIG_MLX4_EN_DCB) += en_dcb_nl.o 10mlx4_en-$(CONFIG_MLX4_EN_DCB) += en_dcb_nl.o
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
index 0706623cfb96..004e4231af67 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
@@ -240,9 +240,10 @@ static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
240 __mlx4_cq_free_icm(dev, cqn); 240 __mlx4_cq_free_icm(dev, cqn);
241} 241}
242 242
243int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, 243int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
244 struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq, 244 struct mlx4_mtt *mtt, struct mlx4_uar *uar, u64 db_rec,
245 unsigned vector, int collapsed) 245 struct mlx4_cq *cq, unsigned vector, int collapsed,
246 int timestamp_en)
246{ 247{
247 struct mlx4_priv *priv = mlx4_priv(dev); 248 struct mlx4_priv *priv = mlx4_priv(dev);
248 struct mlx4_cq_table *cq_table = &priv->cq_table; 249 struct mlx4_cq_table *cq_table = &priv->cq_table;
@@ -276,6 +277,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
276 memset(cq_context, 0, sizeof *cq_context); 277 memset(cq_context, 0, sizeof *cq_context);
277 278
278 cq_context->flags = cpu_to_be32(!!collapsed << 18); 279 cq_context->flags = cpu_to_be32(!!collapsed << 18);
280 if (timestamp_en)
281 cq_context->flags |= cpu_to_be32(1 << 19);
282
279 cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index); 283 cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
280 cq_context->comp_eqn = priv->eq_table.eq[vector].eqn; 284 cq_context->comp_eqn = priv->eq_table.eq[vector].eqn;
281 cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; 285 cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
new file mode 100644
index 000000000000..501c72f1fbeb
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
@@ -0,0 +1,132 @@
1/*
2 * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 *
32 */
33
34#include <linux/mlx4/device.h>
35
36#include "mlx4_en.h"
37
38int mlx4_en_timestamp_config(struct net_device *dev, int tx_type, int rx_filter)
39{
40 struct mlx4_en_priv *priv = netdev_priv(dev);
41 struct mlx4_en_dev *mdev = priv->mdev;
42 int port_up = 0;
43 int err = 0;
44
45 mutex_lock(&mdev->state_lock);
46 if (priv->port_up) {
47 port_up = 1;
48 mlx4_en_stop_port(dev, 1);
49 }
50
51 mlx4_en_free_resources(priv);
52
53 en_warn(priv, "Changing Time Stamp configuration\n");
54
55 priv->hwtstamp_config.tx_type = tx_type;
56 priv->hwtstamp_config.rx_filter = rx_filter;
57
58 if (rx_filter != HWTSTAMP_FILTER_NONE)
59 dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
60 else
61 dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
62
63 err = mlx4_en_alloc_resources(priv);
64 if (err) {
65 en_err(priv, "Failed reallocating port resources\n");
66 goto out;
67 }
68 if (port_up) {
69 err = mlx4_en_start_port(dev);
70 if (err)
71 en_err(priv, "Failed starting port\n");
72 }
73
74out:
75 mutex_unlock(&mdev->state_lock);
76 netdev_features_change(dev);
77 return err;
78}
79
80/* mlx4_en_read_clock - read raw cycle counter (to be used by time counter)
81 */
82static cycle_t mlx4_en_read_clock(const struct cyclecounter *tc)
83{
84 struct mlx4_en_dev *mdev =
85 container_of(tc, struct mlx4_en_dev, cycles);
86 struct mlx4_dev *dev = mdev->dev;
87
88 return mlx4_read_clock(dev) & tc->mask;
89}
90
91u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe)
92{
93 u64 hi, lo;
94 struct mlx4_ts_cqe *ts_cqe = (struct mlx4_ts_cqe *)cqe;
95
96 lo = (u64)be16_to_cpu(ts_cqe->timestamp_lo);
97 hi = ((u64)be32_to_cpu(ts_cqe->timestamp_hi) + !lo) << 16;
98
99 return hi | lo;
100}
101
102void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev,
103 struct skb_shared_hwtstamps *hwts,
104 u64 timestamp)
105{
106 u64 nsec;
107
108 nsec = timecounter_cyc2time(&mdev->clock, timestamp);
109
110 memset(hwts, 0, sizeof(struct skb_shared_hwtstamps));
111 hwts->hwtstamp = ns_to_ktime(nsec);
112}
113
114void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
115{
116 struct mlx4_dev *dev = mdev->dev;
117
118 memset(&mdev->cycles, 0, sizeof(mdev->cycles));
119 mdev->cycles.read = mlx4_en_read_clock;
120 mdev->cycles.mask = CLOCKSOURCE_MASK(48);
121 /* Using shift to make calculation more accurate. Since current HW
122 * clock frequency is 427 MHz, and cycles are given using a 48 bits
123 * register, the biggest shift when calculating using u64, is 14
124 * (max_cycles * multiplier < 2^64)
125 */
126 mdev->cycles.shift = 14;
127 mdev->cycles.mult =
128 clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift);
129
130 timecounter_init(&mdev->clock, &mdev->cycles,
131 ktime_to_ns(ktime_get_real()));
132}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index b8d0854a7ad1..1e6c594d6d04 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -77,6 +77,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
77 struct mlx4_en_dev *mdev = priv->mdev; 77 struct mlx4_en_dev *mdev = priv->mdev;
78 int err = 0; 78 int err = 0;
79 char name[25]; 79 char name[25];
80 int timestamp_en = 0;
80 struct cpu_rmap *rmap = 81 struct cpu_rmap *rmap =
81#ifdef CONFIG_RFS_ACCEL 82#ifdef CONFIG_RFS_ACCEL
82 priv->dev->rx_cpu_rmap; 83 priv->dev->rx_cpu_rmap;
@@ -123,8 +124,13 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
123 if (!cq->is_tx) 124 if (!cq->is_tx)
124 cq->size = priv->rx_ring[cq->ring].actual_size; 125 cq->size = priv->rx_ring[cq->ring].actual_size;
125 126
126 err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar, 127 if ((cq->is_tx && priv->hwtstamp_config.tx_type) ||
127 cq->wqres.db.dma, &cq->mcq, cq->vector, 0); 128 (!cq->is_tx && priv->hwtstamp_config.rx_filter))
129 timestamp_en = 1;
130
131 err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt,
132 &mdev->priv_uar, cq->wqres.db.dma, &cq->mcq,
133 cq->vector, 0, timestamp_en);
128 if (err) 134 if (err)
129 return err; 135 return err;
130 136
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 00f25b5f297f..bcf4d118e98c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -1147,6 +1147,35 @@ out:
1147 return err; 1147 return err;
1148} 1148}
1149 1149
1150static int mlx4_en_get_ts_info(struct net_device *dev,
1151 struct ethtool_ts_info *info)
1152{
1153 struct mlx4_en_priv *priv = netdev_priv(dev);
1154 struct mlx4_en_dev *mdev = priv->mdev;
1155 int ret;
1156
1157 ret = ethtool_op_get_ts_info(dev, info);
1158 if (ret)
1159 return ret;
1160
1161 if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
1162 info->so_timestamping |=
1163 SOF_TIMESTAMPING_TX_HARDWARE |
1164 SOF_TIMESTAMPING_RX_HARDWARE |
1165 SOF_TIMESTAMPING_RAW_HARDWARE;
1166
1167 info->tx_types =
1168 (1 << HWTSTAMP_TX_OFF) |
1169 (1 << HWTSTAMP_TX_ON);
1170
1171 info->rx_filters =
1172 (1 << HWTSTAMP_FILTER_NONE) |
1173 (1 << HWTSTAMP_FILTER_ALL);
1174 }
1175
1176 return ret;
1177}
1178
1150const struct ethtool_ops mlx4_en_ethtool_ops = { 1179const struct ethtool_ops mlx4_en_ethtool_ops = {
1151 .get_drvinfo = mlx4_en_get_drvinfo, 1180 .get_drvinfo = mlx4_en_get_drvinfo,
1152 .get_settings = mlx4_en_get_settings, 1181 .get_settings = mlx4_en_get_settings,
@@ -1173,6 +1202,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
1173 .set_rxfh_indir = mlx4_en_set_rxfh_indir, 1202 .set_rxfh_indir = mlx4_en_set_rxfh_indir,
1174 .get_channels = mlx4_en_get_channels, 1203 .get_channels = mlx4_en_get_channels,
1175 .set_channels = mlx4_en_set_channels, 1204 .set_channels = mlx4_en_set_channels,
1205 .get_ts_info = mlx4_en_get_ts_info,
1176}; 1206};
1177 1207
1178 1208
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index fc27800e9c38..a5c9df07a7d0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -300,6 +300,11 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
300 if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) 300 if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i]))
301 mdev->pndev[i] = NULL; 301 mdev->pndev[i] = NULL;
302 } 302 }
303
304 /* Initialize time stamp mechanism */
305 if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
306 mlx4_en_init_timestamp(mdev);
307
303 return mdev; 308 return mdev;
304 309
305err_mr: 310err_mr:
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index e7e27842d8d4..4cb9f3203973 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1916,6 +1916,75 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
1916 return 0; 1916 return 0;
1917} 1917}
1918 1918
1919static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
1920{
1921 struct mlx4_en_priv *priv = netdev_priv(dev);
1922 struct mlx4_en_dev *mdev = priv->mdev;
1923 struct hwtstamp_config config;
1924
1925 if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
1926 return -EFAULT;
1927
1928 /* reserved for future extensions */
1929 if (config.flags)
1930 return -EINVAL;
1931
1932 /* device doesn't support time stamping */
1933 if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS))
1934 return -EINVAL;
1935
1936 /* TX HW timestamp */
1937 switch (config.tx_type) {
1938 case HWTSTAMP_TX_OFF:
1939 case HWTSTAMP_TX_ON:
1940 break;
1941 default:
1942 return -ERANGE;
1943 }
1944
1945 /* RX HW timestamp */
1946 switch (config.rx_filter) {
1947 case HWTSTAMP_FILTER_NONE:
1948 break;
1949 case HWTSTAMP_FILTER_ALL:
1950 case HWTSTAMP_FILTER_SOME:
1951 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
1952 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
1953 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
1954 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
1955 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
1956 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
1957 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
1958 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
1959 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
1960 case HWTSTAMP_FILTER_PTP_V2_EVENT:
1961 case HWTSTAMP_FILTER_PTP_V2_SYNC:
1962 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
1963 config.rx_filter = HWTSTAMP_FILTER_ALL;
1964 break;
1965 default:
1966 return -ERANGE;
1967 }
1968
1969 if (mlx4_en_timestamp_config(dev, config.tx_type, config.rx_filter)) {
1970 config.tx_type = HWTSTAMP_TX_OFF;
1971 config.rx_filter = HWTSTAMP_FILTER_NONE;
1972 }
1973
1974 return copy_to_user(ifr->ifr_data, &config,
1975 sizeof(config)) ? -EFAULT : 0;
1976}
1977
1978static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1979{
1980 switch (cmd) {
1981 case SIOCSHWTSTAMP:
1982 return mlx4_en_hwtstamp_ioctl(dev, ifr);
1983 default:
1984 return -EOPNOTSUPP;
1985 }
1986}
1987
1919static int mlx4_en_set_features(struct net_device *netdev, 1988static int mlx4_en_set_features(struct net_device *netdev,
1920 netdev_features_t features) 1989 netdev_features_t features)
1921{ 1990{
@@ -1943,6 +2012,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
1943 .ndo_set_mac_address = mlx4_en_set_mac, 2012 .ndo_set_mac_address = mlx4_en_set_mac,
1944 .ndo_validate_addr = eth_validate_addr, 2013 .ndo_validate_addr = eth_validate_addr,
1945 .ndo_change_mtu = mlx4_en_change_mtu, 2014 .ndo_change_mtu = mlx4_en_change_mtu,
2015 .ndo_do_ioctl = mlx4_en_ioctl,
1946 .ndo_tx_timeout = mlx4_en_tx_timeout, 2016 .ndo_tx_timeout = mlx4_en_tx_timeout,
1947 .ndo_vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid, 2017 .ndo_vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid,
1948 .ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid, 2018 .ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid,
@@ -2054,6 +2124,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
2054 spin_lock_init(&priv->filters_lock); 2124 spin_lock_init(&priv->filters_lock);
2055#endif 2125#endif
2056 2126
2127 /* Initialize time stamping config */
2128 priv->hwtstamp_config.flags = 0;
2129 priv->hwtstamp_config.tx_type = HWTSTAMP_TX_OFF;
2130 priv->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
2131
2057 /* Allocate page for receive rings */ 2132 /* Allocate page for receive rings */
2058 err = mlx4_alloc_hwq_res(mdev->dev, &priv->res, 2133 err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
2059 MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE); 2134 MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
index 10c24c784b70..91f2b2c43c12 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
@@ -42,6 +42,7 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
42 int user_prio, struct mlx4_qp_context *context) 42 int user_prio, struct mlx4_qp_context *context)
43{ 43{
44 struct mlx4_en_dev *mdev = priv->mdev; 44 struct mlx4_en_dev *mdev = priv->mdev;
45 struct net_device *dev = priv->dev;
45 46
46 memset(context, 0, sizeof *context); 47 memset(context, 0, sizeof *context);
47 context->flags = cpu_to_be32(7 << 16 | rss << MLX4_RSS_QPC_FLAG_OFFSET); 48 context->flags = cpu_to_be32(7 << 16 | rss << MLX4_RSS_QPC_FLAG_OFFSET);
@@ -65,6 +66,8 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
65 context->cqn_send = cpu_to_be32(cqn); 66 context->cqn_send = cpu_to_be32(cqn);
66 context->cqn_recv = cpu_to_be32(cqn); 67 context->cqn_recv = cpu_to_be32(cqn);
67 context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2); 68 context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
69 if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX))
70 context->param3 |= cpu_to_be32(1 << 30);
68} 71}
69 72
70 73
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 4006f8857cb5..02aee1ebd203 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -320,6 +320,8 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
320 } 320 }
321 ring->buf = ring->wqres.buf.direct.buf; 321 ring->buf = ring->wqres.buf.direct.buf;
322 322
323 ring->hwtstamp_rx_filter = priv->hwtstamp_config.rx_filter;
324
323 return 0; 325 return 0;
324 326
325err_hwq: 327err_hwq:
@@ -554,6 +556,7 @@ static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
554int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) 556int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
555{ 557{
556 struct mlx4_en_priv *priv = netdev_priv(dev); 558 struct mlx4_en_priv *priv = netdev_priv(dev);
559 struct mlx4_en_dev *mdev = priv->mdev;
557 struct mlx4_cqe *cqe; 560 struct mlx4_cqe *cqe;
558 struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring]; 561 struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
559 struct mlx4_en_rx_alloc *frags; 562 struct mlx4_en_rx_alloc *frags;
@@ -565,6 +568,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
565 int polled = 0; 568 int polled = 0;
566 int ip_summed; 569 int ip_summed;
567 int factor = priv->cqe_factor; 570 int factor = priv->cqe_factor;
571 u64 timestamp;
568 572
569 if (!priv->port_up) 573 if (!priv->port_up)
570 return 0; 574 return 0;
@@ -669,8 +673,9 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
669 gro_skb->data_len = length; 673 gro_skb->data_len = length;
670 gro_skb->ip_summed = CHECKSUM_UNNECESSARY; 674 gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
671 675
672 if (cqe->vlan_my_qpn & 676 if ((cqe->vlan_my_qpn &
673 cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) { 677 cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) &&
678 (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
674 u16 vid = be16_to_cpu(cqe->sl_vid); 679 u16 vid = be16_to_cpu(cqe->sl_vid);
675 680
676 __vlan_hwaccel_put_tag(gro_skb, htons(ETH_P_8021Q), vid); 681 __vlan_hwaccel_put_tag(gro_skb, htons(ETH_P_8021Q), vid);
@@ -680,8 +685,15 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
680 gro_skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid); 685 gro_skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid);
681 686
682 skb_record_rx_queue(gro_skb, cq->ring); 687 skb_record_rx_queue(gro_skb, cq->ring);
683 napi_gro_frags(&cq->napi);
684 688
689 if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) {
690 timestamp = mlx4_en_get_cqe_ts(cqe);
691 mlx4_en_fill_hwtstamps(mdev,
692 skb_hwtstamps(gro_skb),
693 timestamp);
694 }
695
696 napi_gro_frags(&cq->napi);
685 goto next; 697 goto next;
686 } 698 }
687 699
@@ -714,10 +726,17 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
714 if (dev->features & NETIF_F_RXHASH) 726 if (dev->features & NETIF_F_RXHASH)
715 skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid); 727 skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid);
716 728
717 if (be32_to_cpu(cqe->vlan_my_qpn) & 729 if ((be32_to_cpu(cqe->vlan_my_qpn) &
718 MLX4_CQE_VLAN_PRESENT_MASK) 730 MLX4_CQE_VLAN_PRESENT_MASK) &&
731 (dev->features & NETIF_F_HW_VLAN_CTAG_RX))
719 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), be16_to_cpu(cqe->sl_vid)); 732 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), be16_to_cpu(cqe->sl_vid));
720 733
734 if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) {
735 timestamp = mlx4_en_get_cqe_ts(cqe);
736 mlx4_en_fill_hwtstamps(mdev, skb_hwtstamps(skb),
737 timestamp);
738 }
739
721 /* Push it up the stack */ 740 /* Push it up the stack */
722 netif_receive_skb(skb); 741 netif_receive_skb(skb);
723 742
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 49308cc65ee7..b0a2d2b96e43 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -118,6 +118,8 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
118 } else 118 } else
119 ring->bf_enabled = true; 119 ring->bf_enabled = true;
120 120
121 ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type;
122
121 return 0; 123 return 0;
122 124
123err_map: 125err_map:
@@ -192,8 +194,9 @@ void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
192 194
193static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv, 195static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
194 struct mlx4_en_tx_ring *ring, 196 struct mlx4_en_tx_ring *ring,
195 int index, u8 owner) 197 int index, u8 owner, u64 timestamp)
196{ 198{
199 struct mlx4_en_dev *mdev = priv->mdev;
197 struct mlx4_en_tx_info *tx_info = &ring->tx_info[index]; 200 struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
198 struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE; 201 struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
199 struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset; 202 struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset;
@@ -204,6 +207,12 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
204 int i; 207 int i;
205 __be32 *ptr = (__be32 *)tx_desc; 208 __be32 *ptr = (__be32 *)tx_desc;
206 __be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT)); 209 __be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
210 struct skb_shared_hwtstamps hwts;
211
212 if (timestamp) {
213 mlx4_en_fill_hwtstamps(mdev, &hwts, timestamp);
214 skb_tstamp_tx(skb, &hwts);
215 }
207 216
208 /* Optimize the common case when there are no wraparounds */ 217 /* Optimize the common case when there are no wraparounds */
209 if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) { 218 if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) {
@@ -289,7 +298,7 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
289 while (ring->cons != ring->prod) { 298 while (ring->cons != ring->prod) {
290 ring->last_nr_txbb = mlx4_en_free_tx_desc(priv, ring, 299 ring->last_nr_txbb = mlx4_en_free_tx_desc(priv, ring,
291 ring->cons & ring->size_mask, 300 ring->cons & ring->size_mask,
292 !!(ring->cons & ring->size)); 301 !!(ring->cons & ring->size), 0);
293 ring->cons += ring->last_nr_txbb; 302 ring->cons += ring->last_nr_txbb;
294 cnt++; 303 cnt++;
295 } 304 }
@@ -318,6 +327,7 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
318 u32 packets = 0; 327 u32 packets = 0;
319 u32 bytes = 0; 328 u32 bytes = 0;
320 int factor = priv->cqe_factor; 329 int factor = priv->cqe_factor;
330 u64 timestamp = 0;
321 331
322 if (!priv->port_up) 332 if (!priv->port_up)
323 return; 333 return;
@@ -341,11 +351,14 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
341 do { 351 do {
342 txbbs_skipped += ring->last_nr_txbb; 352 txbbs_skipped += ring->last_nr_txbb;
343 ring_index = (ring_index + ring->last_nr_txbb) & size_mask; 353 ring_index = (ring_index + ring->last_nr_txbb) & size_mask;
354 if (ring->tx_info[ring_index].ts_requested)
355 timestamp = mlx4_en_get_cqe_ts(cqe);
356
344 /* free next descriptor */ 357 /* free next descriptor */
345 ring->last_nr_txbb = mlx4_en_free_tx_desc( 358 ring->last_nr_txbb = mlx4_en_free_tx_desc(
346 priv, ring, ring_index, 359 priv, ring, ring_index,
347 !!((ring->cons + txbbs_skipped) & 360 !!((ring->cons + txbbs_skipped) &
348 ring->size)); 361 ring->size), timestamp);
349 packets++; 362 packets++;
350 bytes += ring->tx_info[ring_index].nr_bytes; 363 bytes += ring->tx_info[ring_index].nr_bytes;
351 } while (ring_index != new_index); 364 } while (ring_index != new_index);
@@ -629,6 +642,16 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
629 tx_info->skb = skb; 642 tx_info->skb = skb;
630 tx_info->nr_txbb = nr_txbb; 643 tx_info->nr_txbb = nr_txbb;
631 644
645 /*
646 * For timestamping add flag to skb_shinfo and
647 * set flag for further reference
648 */
649 if (ring->hwtstamp_tx_type == HWTSTAMP_TX_ON &&
650 skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
651 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
652 tx_info->ts_requested = 1;
653 }
654
632 /* Prepare ctrl segement apart opcode+ownership, which depends on 655 /* Prepare ctrl segement apart opcode+ownership, which depends on
633 * whether LSO is used */ 656 * whether LSO is used */
634 tx_desc->ctrl.vlan_tag = cpu_to_be16(vlan_tag); 657 tx_desc->ctrl.vlan_tag = cpu_to_be16(vlan_tag);
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index e81840faa6c6..0d32a82458bf 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1228,6 +1228,28 @@ static void unmap_bf_area(struct mlx4_dev *dev)
1228 io_mapping_free(mlx4_priv(dev)->bf_mapping); 1228 io_mapping_free(mlx4_priv(dev)->bf_mapping);
1229} 1229}
1230 1230
1231cycle_t mlx4_read_clock(struct mlx4_dev *dev)
1232{
1233 u32 clockhi, clocklo, clockhi1;
1234 cycle_t cycles;
1235 int i;
1236 struct mlx4_priv *priv = mlx4_priv(dev);
1237
1238 for (i = 0; i < 10; i++) {
1239 clockhi = swab32(readl(priv->clock_mapping));
1240 clocklo = swab32(readl(priv->clock_mapping + 4));
1241 clockhi1 = swab32(readl(priv->clock_mapping));
1242 if (clockhi == clockhi1)
1243 break;
1244 }
1245
1246 cycles = (u64) clockhi << 32 | (u64) clocklo;
1247
1248 return cycles;
1249}
1250EXPORT_SYMBOL_GPL(mlx4_read_clock);
1251
1252
1231static int map_internal_clock(struct mlx4_dev *dev) 1253static int map_internal_clock(struct mlx4_dev *dev)
1232{ 1254{
1233 struct mlx4_priv *priv = mlx4_priv(dev); 1255 struct mlx4_priv *priv = mlx4_priv(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index d4cb5d3b28a2..85b0754ec8ac 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -40,6 +40,7 @@
40#include <linux/mutex.h> 40#include <linux/mutex.h>
41#include <linux/netdevice.h> 41#include <linux/netdevice.h>
42#include <linux/if_vlan.h> 42#include <linux/if_vlan.h>
43#include <linux/net_tstamp.h>
43#ifdef CONFIG_MLX4_EN_DCB 44#ifdef CONFIG_MLX4_EN_DCB
44#include <linux/dcbnl.h> 45#include <linux/dcbnl.h>
45#endif 46#endif
@@ -207,6 +208,7 @@ struct mlx4_en_tx_info {
207 u8 linear; 208 u8 linear;
208 u8 data_offset; 209 u8 data_offset;
209 u8 inl; 210 u8 inl;
211 u8 ts_requested;
210}; 212};
211 213
212 214
@@ -262,6 +264,7 @@ struct mlx4_en_tx_ring {
262 struct mlx4_bf bf; 264 struct mlx4_bf bf;
263 bool bf_enabled; 265 bool bf_enabled;
264 struct netdev_queue *tx_queue; 266 struct netdev_queue *tx_queue;
267 int hwtstamp_tx_type;
265}; 268};
266 269
267struct mlx4_en_rx_desc { 270struct mlx4_en_rx_desc {
@@ -288,6 +291,7 @@ struct mlx4_en_rx_ring {
288 unsigned long packets; 291 unsigned long packets;
289 unsigned long csum_ok; 292 unsigned long csum_ok;
290 unsigned long csum_none; 293 unsigned long csum_none;
294 int hwtstamp_rx_filter;
291}; 295};
292 296
293struct mlx4_en_cq { 297struct mlx4_en_cq {
@@ -348,6 +352,9 @@ struct mlx4_en_dev {
348 u32 priv_pdn; 352 u32 priv_pdn;
349 spinlock_t uar_lock; 353 spinlock_t uar_lock;
350 u8 mac_removed[MLX4_MAX_PORTS + 1]; 354 u8 mac_removed[MLX4_MAX_PORTS + 1];
355 struct cyclecounter cycles;
356 struct timecounter clock;
357 unsigned long last_overflow_check;
351}; 358};
352 359
353 360
@@ -525,6 +532,7 @@ struct mlx4_en_priv {
525 struct device *ddev; 532 struct device *ddev;
526 int base_tx_qpn; 533 int base_tx_qpn;
527 struct hlist_head mac_hash[MLX4_EN_MAC_HASH_SIZE]; 534 struct hlist_head mac_hash[MLX4_EN_MAC_HASH_SIZE];
535 struct hwtstamp_config hwtstamp_config;
528 536
529#ifdef CONFIG_MLX4_EN_DCB 537#ifdef CONFIG_MLX4_EN_DCB
530 struct ieee_ets ets; 538 struct ieee_ets ets;
@@ -639,7 +647,18 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
639u64 mlx4_en_mac_to_u64(u8 *addr); 647u64 mlx4_en_mac_to_u64(u8 *addr);
640 648
641/* 649/*
642 * Globals 650 * Functions for time stamping
651 */
652u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe);
653void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev,
654 struct skb_shared_hwtstamps *hwts,
655 u64 timestamp);
656void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev);
657int mlx4_en_timestamp_config(struct net_device *dev,
658 int tx_type,
659 int rx_filter);
660
661/* Globals
643 */ 662 */
644extern const struct ethtool_ops mlx4_en_ethtool_ops; 663extern const struct ethtool_ops mlx4_en_ethtool_ops;
645 664