2 * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
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:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
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.
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
34 #include <linux/mlx4/device.h>
38 int mlx4_en_timestamp_config(struct net_device
*dev
, int tx_type
, int rx_filter
)
40 struct mlx4_en_priv
*priv
= netdev_priv(dev
);
41 struct mlx4_en_dev
*mdev
= priv
->mdev
;
45 mutex_lock(&mdev
->state_lock
);
48 mlx4_en_stop_port(dev
, 1);
51 mlx4_en_free_resources(priv
);
53 en_warn(priv
, "Changing Time Stamp configuration\n");
55 priv
->hwtstamp_config
.tx_type
= tx_type
;
56 priv
->hwtstamp_config
.rx_filter
= rx_filter
;
58 if (rx_filter
!= HWTSTAMP_FILTER_NONE
)
59 dev
->features
&= ~NETIF_F_HW_VLAN_CTAG_RX
;
61 dev
->features
|= NETIF_F_HW_VLAN_CTAG_RX
;
63 err
= mlx4_en_alloc_resources(priv
);
65 en_err(priv
, "Failed reallocating port resources\n");
69 err
= mlx4_en_start_port(dev
);
71 en_err(priv
, "Failed starting port\n");
75 mutex_unlock(&mdev
->state_lock
);
76 netdev_features_change(dev
);
80 /* mlx4_en_read_clock - read raw cycle counter (to be used by time counter)
82 static cycle_t
mlx4_en_read_clock(const struct cyclecounter
*tc
)
84 struct mlx4_en_dev
*mdev
=
85 container_of(tc
, struct mlx4_en_dev
, cycles
);
86 struct mlx4_dev
*dev
= mdev
->dev
;
88 return mlx4_read_clock(dev
) & tc
->mask
;
91 u64
mlx4_en_get_cqe_ts(struct mlx4_cqe
*cqe
)
94 struct mlx4_ts_cqe
*ts_cqe
= (struct mlx4_ts_cqe
*)cqe
;
96 lo
= (u64
)be16_to_cpu(ts_cqe
->timestamp_lo
);
97 hi
= ((u64
)be32_to_cpu(ts_cqe
->timestamp_hi
) + !lo
) << 16;
102 void mlx4_en_fill_hwtstamps(struct mlx4_en_dev
*mdev
,
103 struct skb_shared_hwtstamps
*hwts
,
108 nsec
= timecounter_cyc2time(&mdev
->clock
, timestamp
);
110 memset(hwts
, 0, sizeof(struct skb_shared_hwtstamps
));
111 hwts
->hwtstamp
= ns_to_ktime(nsec
);
114 void mlx4_en_init_timestamp(struct mlx4_en_dev
*mdev
)
116 struct mlx4_dev
*dev
= mdev
->dev
;
119 memset(&mdev
->cycles
, 0, sizeof(mdev
->cycles
));
120 mdev
->cycles
.read
= mlx4_en_read_clock
;
121 mdev
->cycles
.mask
= CLOCKSOURCE_MASK(48);
122 /* Using shift to make calculation more accurate. Since current HW
123 * clock frequency is 427 MHz, and cycles are given using a 48 bits
124 * register, the biggest shift when calculating using u64, is 14
125 * (max_cycles * multiplier < 2^64)
127 mdev
->cycles
.shift
= 14;
129 clocksource_khz2mult(1000 * dev
->caps
.hca_core_clock
, mdev
->cycles
.shift
);
131 timecounter_init(&mdev
->clock
, &mdev
->cycles
,
132 ktime_to_ns(ktime_get_real()));
134 /* Calculate period in seconds to call the overflow watchdog - to make
135 * sure counter is checked at least once every wrap around.
137 ns
= cyclecounter_cyc2ns(&mdev
->cycles
, mdev
->cycles
.mask
);
138 do_div(ns
, NSEC_PER_SEC
/ 2 / HZ
);
139 mdev
->overflow_period
= ns
;
142 void mlx4_en_ptp_overflow_check(struct mlx4_en_dev
*mdev
)
144 bool timeout
= time_is_before_jiffies(mdev
->last_overflow_check
+
145 mdev
->overflow_period
);
148 timecounter_read(&mdev
->clock
);
149 mdev
->last_overflow_check
= jiffies
;