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 38 /* mlx4_en_read_clock - read raw cycle counter (to be used by time counter) 39 */ 40 static cycle_t mlx4_en_read_clock(const struct cyclecounter *tc) 41 { 42 struct mlx4_en_dev *mdev = 43 container_of(tc, struct mlx4_en_dev, cycles); 44 struct mlx4_dev *dev = mdev->dev; 45 46 return mlx4_read_clock(dev) & tc->mask; 47 } 48 49 u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe) 50 { 51 u64 hi, lo; 52 struct mlx4_ts_cqe *ts_cqe = (struct mlx4_ts_cqe *)cqe; 53 54 lo = (u64)be16_to_cpu(ts_cqe->timestamp_lo); 55 hi = ((u64)be32_to_cpu(ts_cqe->timestamp_hi) + !lo) << 16; 56 57 return hi | lo; 58 } 59 60 void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev, 61 struct skb_shared_hwtstamps *hwts, 62 u64 timestamp) 63 { 64 unsigned long flags; 65 u64 nsec; 66 67 read_lock_irqsave(&mdev->clock_lock, flags); 68 nsec = timecounter_cyc2time(&mdev->clock, timestamp); 69 read_unlock_irqrestore(&mdev->clock_lock, flags); 70 71 memset(hwts, 0, sizeof(struct skb_shared_hwtstamps)); 72 hwts->hwtstamp = ns_to_ktime(nsec); 73 } 74 75 /** 76 * mlx4_en_remove_timestamp - disable PTP device 77 * @mdev: board private structure 78 * 79 * Stop the PTP support. 80 **/ 81 void mlx4_en_remove_timestamp(struct mlx4_en_dev *mdev) 82 { 83 if (mdev->ptp_clock) { 84 ptp_clock_unregister(mdev->ptp_clock); 85 mdev->ptp_clock = NULL; 86 mlx4_info(mdev, "removed PHC\n"); 87 } 88 } 89 90 void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev) 91 { 92 bool timeout = time_is_before_jiffies(mdev->last_overflow_check + 93 mdev->overflow_period); 94 unsigned long flags; 95 96 if (timeout) { 97 write_lock_irqsave(&mdev->clock_lock, flags); 98 timecounter_read(&mdev->clock); 99 write_unlock_irqrestore(&mdev->clock_lock, flags); 100 mdev->last_overflow_check = jiffies; 101 } 102 } 103 104 /** 105 * mlx4_en_phc_adjfreq - adjust the frequency of the hardware clock 106 * @ptp: ptp clock structure 107 * @delta: Desired frequency change in parts per billion 108 * 109 * Adjust the frequency of the PHC cycle counter by the indicated delta from 110 * the base frequency. 111 **/ 112 static int mlx4_en_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) 113 { 114 u64 adj; 115 u32 diff, mult; 116 int neg_adj = 0; 117 unsigned long flags; 118 struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev, 119 ptp_clock_info); 120 121 if (delta < 0) { 122 neg_adj = 1; 123 delta = -delta; 124 } 125 mult = mdev->nominal_c_mult; 126 adj = mult; 127 adj *= delta; 128 diff = div_u64(adj, 1000000000ULL); 129 130 write_lock_irqsave(&mdev->clock_lock, flags); 131 timecounter_read(&mdev->clock); 132 mdev->cycles.mult = neg_adj ? mult - diff : mult + diff; 133 write_unlock_irqrestore(&mdev->clock_lock, flags); 134 135 return 0; 136 } 137 138 /** 139 * mlx4_en_phc_adjtime - Shift the time of the hardware clock 140 * @ptp: ptp clock structure 141 * @delta: Desired change in nanoseconds 142 * 143 * Adjust the timer by resetting the timecounter structure. 144 **/ 145 static int mlx4_en_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) 146 { 147 struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev, 148 ptp_clock_info); 149 unsigned long flags; 150 s64 now; 151 152 write_lock_irqsave(&mdev->clock_lock, flags); 153 now = timecounter_read(&mdev->clock); 154 now += delta; 155 timecounter_init(&mdev->clock, &mdev->cycles, now); 156 write_unlock_irqrestore(&mdev->clock_lock, flags); 157 158 return 0; 159 } 160 161 /** 162 * mlx4_en_phc_gettime - Reads the current time from the hardware clock 163 * @ptp: ptp clock structure 164 * @ts: timespec structure to hold the current time value 165 * 166 * Read the timecounter and return the correct value in ns after converting 167 * it into a struct timespec. 168 **/ 169 static int mlx4_en_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts) 170 { 171 struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev, 172 ptp_clock_info); 173 unsigned long flags; 174 u32 remainder; 175 u64 ns; 176 177 write_lock_irqsave(&mdev->clock_lock, flags); 178 ns = timecounter_read(&mdev->clock); 179 write_unlock_irqrestore(&mdev->clock_lock, flags); 180 181 ts->tv_sec = div_u64_rem(ns, NSEC_PER_SEC, &remainder); 182 ts->tv_nsec = remainder; 183 184 return 0; 185 } 186 187 /** 188 * mlx4_en_phc_settime - Set the current time on the hardware clock 189 * @ptp: ptp clock structure 190 * @ts: timespec containing the new time for the cycle counter 191 * 192 * Reset the timecounter to use a new base value instead of the kernel 193 * wall timer value. 194 **/ 195 static int mlx4_en_phc_settime(struct ptp_clock_info *ptp, 196 const struct timespec *ts) 197 { 198 struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev, 199 ptp_clock_info); 200 u64 ns = timespec_to_ns(ts); 201 unsigned long flags; 202 203 /* reset the timecounter */ 204 write_lock_irqsave(&mdev->clock_lock, flags); 205 timecounter_init(&mdev->clock, &mdev->cycles, ns); 206 write_unlock_irqrestore(&mdev->clock_lock, flags); 207 208 return 0; 209 } 210 211 /** 212 * mlx4_en_phc_enable - enable or disable an ancillary feature 213 * @ptp: ptp clock structure 214 * @request: Desired resource to enable or disable 215 * @on: Caller passes one to enable or zero to disable 216 * 217 * Enable (or disable) ancillary features of the PHC subsystem. 218 * Currently, no ancillary features are supported. 219 **/ 220 static int mlx4_en_phc_enable(struct ptp_clock_info __always_unused *ptp, 221 struct ptp_clock_request __always_unused *request, 222 int __always_unused on) 223 { 224 return -EOPNOTSUPP; 225 } 226 227 static const struct ptp_clock_info mlx4_en_ptp_clock_info = { 228 .owner = THIS_MODULE, 229 .max_adj = 100000000, 230 .n_alarm = 0, 231 .n_ext_ts = 0, 232 .n_per_out = 0, 233 .n_pins = 0, 234 .pps = 0, 235 .adjfreq = mlx4_en_phc_adjfreq, 236 .adjtime = mlx4_en_phc_adjtime, 237 .gettime = mlx4_en_phc_gettime, 238 .settime = mlx4_en_phc_settime, 239 .enable = mlx4_en_phc_enable, 240 }; 241 242 void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) 243 { 244 struct mlx4_dev *dev = mdev->dev; 245 unsigned long flags; 246 u64 ns; 247 248 rwlock_init(&mdev->clock_lock); 249 250 memset(&mdev->cycles, 0, sizeof(mdev->cycles)); 251 mdev->cycles.read = mlx4_en_read_clock; 252 mdev->cycles.mask = CLOCKSOURCE_MASK(48); 253 /* Using shift to make calculation more accurate. Since current HW 254 * clock frequency is 427 MHz, and cycles are given using a 48 bits 255 * register, the biggest shift when calculating using u64, is 14 256 * (max_cycles * multiplier < 2^64) 257 */ 258 mdev->cycles.shift = 14; 259 mdev->cycles.mult = 260 clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift); 261 mdev->nominal_c_mult = mdev->cycles.mult; 262 263 write_lock_irqsave(&mdev->clock_lock, flags); 264 timecounter_init(&mdev->clock, &mdev->cycles, 265 ktime_to_ns(ktime_get_real())); 266 write_unlock_irqrestore(&mdev->clock_lock, flags); 267 268 /* Calculate period in seconds to call the overflow watchdog - to make 269 * sure counter is checked at least once every wrap around. 270 */ 271 ns = cyclecounter_cyc2ns(&mdev->cycles, mdev->cycles.mask); 272 do_div(ns, NSEC_PER_SEC / 2 / HZ); 273 mdev->overflow_period = ns; 274 275 /* Configure the PHC */ 276 mdev->ptp_clock_info = mlx4_en_ptp_clock_info; 277 snprintf(mdev->ptp_clock_info.name, 16, "mlx4 ptp"); 278 279 mdev->ptp_clock = ptp_clock_register(&mdev->ptp_clock_info, 280 &mdev->pdev->dev); 281 if (IS_ERR(mdev->ptp_clock)) { 282 mdev->ptp_clock = NULL; 283 mlx4_err(mdev, "ptp_clock_register failed\n"); 284 } else { 285 mlx4_info(mdev, "registered PHC clock\n"); 286 } 287 288 } 289