linux/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c
<<
>>
Prefs
   1/* Intel Ethernet Switch Host Interface Driver
   2 * Copyright(c) 2013 - 2015 Intel Corporation.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * The full GNU General Public License is included in this distribution in
  14 * the file called "COPYING".
  15 *
  16 * Contact Information:
  17 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
  18 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  19 */
  20
  21#include <linux/ptp_classify.h>
  22#include <linux/ptp_clock_kernel.h>
  23
  24#include "fm10k.h"
  25
  26#define FM10K_TS_TX_TIMEOUT             (HZ * 15)
  27
  28void fm10k_systime_to_hwtstamp(struct fm10k_intfc *interface,
  29                               struct skb_shared_hwtstamps *hwtstamp,
  30                               u64 systime)
  31{
  32        unsigned long flags;
  33
  34        read_lock_irqsave(&interface->systime_lock, flags);
  35        systime += interface->ptp_adjust;
  36        read_unlock_irqrestore(&interface->systime_lock, flags);
  37
  38        hwtstamp->hwtstamp = ns_to_ktime(systime);
  39}
  40
  41static struct sk_buff *fm10k_ts_tx_skb(struct fm10k_intfc *interface,
  42                                       __le16 dglort)
  43{
  44        struct sk_buff_head *list = &interface->ts_tx_skb_queue;
  45        struct sk_buff *skb;
  46
  47        skb_queue_walk(list, skb) {
  48                if (FM10K_CB(skb)->fi.w.dglort == dglort)
  49                        return skb;
  50        }
  51
  52        return NULL;
  53}
  54
  55void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb)
  56{
  57        struct sk_buff_head *list = &interface->ts_tx_skb_queue;
  58        struct sk_buff *clone;
  59        unsigned long flags;
  60
  61        /* create clone for us to return on the Tx path */
  62        clone = skb_clone_sk(skb);
  63        if (!clone)
  64                return;
  65
  66        FM10K_CB(clone)->ts_tx_timeout = jiffies + FM10K_TS_TX_TIMEOUT;
  67        spin_lock_irqsave(&list->lock, flags);
  68
  69        /* attempt to locate any buffers with the same dglort,
  70         * if none are present then insert skb in tail of list
  71         */
  72        skb = fm10k_ts_tx_skb(interface, FM10K_CB(clone)->fi.w.dglort);
  73        if (!skb)
  74                __skb_queue_tail(list, clone);
  75
  76        spin_unlock_irqrestore(&list->lock, flags);
  77
  78        /* if list is already has one then we just free the clone */
  79        if (skb)
  80                kfree_skb(skb);
  81        else
  82                skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
  83}
  84
  85void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort,
  86                          u64 systime)
  87{
  88        struct skb_shared_hwtstamps shhwtstamps;
  89        struct sk_buff_head *list = &interface->ts_tx_skb_queue;
  90        struct sk_buff *skb;
  91        unsigned long flags;
  92
  93        spin_lock_irqsave(&list->lock, flags);
  94
  95        /* attempt to locate and pull the sk_buff out of the list */
  96        skb = fm10k_ts_tx_skb(interface, dglort);
  97        if (skb)
  98                __skb_unlink(skb, list);
  99
 100        spin_unlock_irqrestore(&list->lock, flags);
 101
 102        /* if not found do nothing */
 103        if (!skb)
 104                return;
 105
 106        /* timestamp the sk_buff and return it to the socket */
 107        fm10k_systime_to_hwtstamp(interface, &shhwtstamps, systime);
 108        skb_complete_tx_timestamp(skb, &shhwtstamps);
 109}
 110
 111void fm10k_ts_tx_subtask(struct fm10k_intfc *interface)
 112{
 113        struct sk_buff_head *list = &interface->ts_tx_skb_queue;
 114        struct sk_buff *skb, *tmp;
 115        unsigned long flags;
 116
 117        /* If we're down or resetting, just bail */
 118        if (test_bit(__FM10K_DOWN, &interface->state) ||
 119            test_bit(__FM10K_RESETTING, &interface->state))
 120                return;
 121
 122        spin_lock_irqsave(&list->lock, flags);
 123
 124        /* walk though the list and flush any expired timestamp packets */
 125        skb_queue_walk_safe(list, skb, tmp) {
 126                if (!time_is_after_jiffies(FM10K_CB(skb)->ts_tx_timeout))
 127                        continue;
 128                __skb_unlink(skb, list);
 129                kfree_skb(skb);
 130                interface->tx_hwtstamp_timeouts++;
 131        }
 132
 133        spin_unlock_irqrestore(&list->lock, flags);
 134}
 135
 136static u64 fm10k_systime_read(struct fm10k_intfc *interface)
 137{
 138        struct fm10k_hw *hw = &interface->hw;
 139
 140        return hw->mac.ops.read_systime(hw);
 141}
 142
 143void fm10k_ts_reset(struct fm10k_intfc *interface)
 144{
 145        s64 ns = ktime_to_ns(ktime_get_real());
 146        unsigned long flags;
 147
 148        /* reinitialize the clock */
 149        write_lock_irqsave(&interface->systime_lock, flags);
 150        interface->ptp_adjust = fm10k_systime_read(interface) - ns;
 151        write_unlock_irqrestore(&interface->systime_lock, flags);
 152}
 153
 154void fm10k_ts_init(struct fm10k_intfc *interface)
 155{
 156        /* Initialize lock protecting systime access */
 157        rwlock_init(&interface->systime_lock);
 158
 159        /* Initialize skb queue for pending timestamp requests */
 160        skb_queue_head_init(&interface->ts_tx_skb_queue);
 161
 162        /* reset the clock to current kernel time */
 163        fm10k_ts_reset(interface);
 164}
 165
 166/**
 167 * fm10k_get_ts_config - get current hardware timestamping configuration
 168 * @netdev: network interface device structure
 169 * @ifreq: ioctl data
 170 *
 171 * This function returns the current timestamping settings. Rather than
 172 * attempt to deconstruct registers to fill in the values, simply keep a copy
 173 * of the old settings around, and return a copy when requested.
 174 */
 175int fm10k_get_ts_config(struct net_device *netdev, struct ifreq *ifr)
 176{
 177        struct fm10k_intfc *interface = netdev_priv(netdev);
 178        struct hwtstamp_config *config = &interface->ts_config;
 179
 180        return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
 181                -EFAULT : 0;
 182}
 183
 184/**
 185 * fm10k_set_ts_config - control hardware time stamping
 186 * @netdev: network interface device structure
 187 * @ifreq: ioctl data
 188 *
 189 * Outgoing time stamping can be enabled and disabled. Play nice and
 190 * disable it when requested, although it shouldn't cause any overhead
 191 * when no packet needs it. At most one packet in the queue may be
 192 * marked for time stamping, otherwise it would be impossible to tell
 193 * for sure to which packet the hardware time stamp belongs.
 194 *
 195 * Incoming time stamping has to be configured via the hardware
 196 * filters. Not all combinations are supported, in particular event
 197 * type has to be specified. Matching the kind of event packet is
 198 * not supported, with the exception of "all V2 events regardless of
 199 * level 2 or 4".
 200 *
 201 * Since hardware always timestamps Path delay packets when timestamping V2
 202 * packets, regardless of the type specified in the register, only use V2
 203 * Event mode. This more accurately tells the user what the hardware is going
 204 * to do anyways.
 205 */
 206int fm10k_set_ts_config(struct net_device *netdev, struct ifreq *ifr)
 207{
 208        struct fm10k_intfc *interface = netdev_priv(netdev);
 209        struct hwtstamp_config ts_config;
 210
 211        if (copy_from_user(&ts_config, ifr->ifr_data, sizeof(ts_config)))
 212                return -EFAULT;
 213
 214        /* reserved for future extensions */
 215        if (ts_config.flags)
 216                return -EINVAL;
 217
 218        switch (ts_config.tx_type) {
 219        case HWTSTAMP_TX_OFF:
 220                break;
 221        case HWTSTAMP_TX_ON:
 222                /* we likely need some check here to see if this is supported */
 223                break;
 224        default:
 225                return -ERANGE;
 226        }
 227
 228        switch (ts_config.rx_filter) {
 229        case HWTSTAMP_FILTER_NONE:
 230                interface->flags &= ~FM10K_FLAG_RX_TS_ENABLED;
 231                break;
 232        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
 233        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
 234        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
 235        case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
 236        case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
 237        case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
 238        case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
 239        case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
 240        case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
 241        case HWTSTAMP_FILTER_PTP_V2_EVENT:
 242        case HWTSTAMP_FILTER_PTP_V2_SYNC:
 243        case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 244        case HWTSTAMP_FILTER_ALL:
 245                interface->flags |= FM10K_FLAG_RX_TS_ENABLED;
 246                ts_config.rx_filter = HWTSTAMP_FILTER_ALL;
 247                break;
 248        default:
 249                return -ERANGE;
 250        }
 251
 252        /* save these settings for future reference */
 253        interface->ts_config = ts_config;
 254
 255        return copy_to_user(ifr->ifr_data, &ts_config, sizeof(ts_config)) ?
 256                -EFAULT : 0;
 257}
 258
 259static int fm10k_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
 260{
 261        struct fm10k_intfc *interface;
 262        struct fm10k_hw *hw;
 263        int err;
 264
 265        interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
 266        hw = &interface->hw;
 267
 268        err = hw->mac.ops.adjust_systime(hw, ppb);
 269
 270        /* the only error we should see is if the value is out of range */
 271        return (err == FM10K_ERR_PARAM) ? -ERANGE : err;
 272}
 273
 274static int fm10k_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
 275{
 276        struct fm10k_intfc *interface;
 277        unsigned long flags;
 278
 279        interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
 280
 281        write_lock_irqsave(&interface->systime_lock, flags);
 282        interface->ptp_adjust += delta;
 283        write_unlock_irqrestore(&interface->systime_lock, flags);
 284
 285        return 0;
 286}
 287
 288static int fm10k_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
 289{
 290        struct fm10k_intfc *interface;
 291        unsigned long flags;
 292        u64 now;
 293
 294        interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
 295
 296        read_lock_irqsave(&interface->systime_lock, flags);
 297        now = fm10k_systime_read(interface) + interface->ptp_adjust;
 298        read_unlock_irqrestore(&interface->systime_lock, flags);
 299
 300        *ts = ns_to_timespec64(now);
 301
 302        return 0;
 303}
 304
 305static int fm10k_ptp_settime(struct ptp_clock_info *ptp,
 306                             const struct timespec64 *ts)
 307{
 308        struct fm10k_intfc *interface;
 309        unsigned long flags;
 310        u64 ns = timespec64_to_ns(ts);
 311
 312        interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
 313
 314        write_lock_irqsave(&interface->systime_lock, flags);
 315        interface->ptp_adjust = fm10k_systime_read(interface) - ns;
 316        write_unlock_irqrestore(&interface->systime_lock, flags);
 317
 318        return 0;
 319}
 320
 321static int fm10k_ptp_enable(struct ptp_clock_info *ptp,
 322                            struct ptp_clock_request *rq,
 323                            int __always_unused on)
 324{
 325        struct ptp_clock_time *t = &rq->perout.period;
 326        struct fm10k_intfc *interface;
 327        struct fm10k_hw *hw;
 328        u64 period;
 329        u32 step;
 330
 331        /* we can only support periodic output */
 332        if (rq->type != PTP_CLK_REQ_PEROUT)
 333                return -EINVAL;
 334
 335        /* verify the requested channel is there */
 336        if (rq->perout.index >= ptp->n_per_out)
 337                return -EINVAL;
 338
 339        /* we cannot enforce start time as there is no
 340         * mechanism for that in the hardware, we can only control
 341         * the period.
 342         */
 343
 344        /* we cannot support periods greater than 4 seconds due to reg limit */
 345        if (t->sec > 4 || t->sec < 0)
 346                return -ERANGE;
 347
 348        interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
 349        hw = &interface->hw;
 350
 351        /* we simply cannot support the operation if we don't have BAR4 */
 352        if (!hw->sw_addr)
 353                return -ENOTSUPP;
 354
 355        /* convert to unsigned 64b ns, verify we can put it in a 32b register */
 356        period = t->sec * 1000000000LL + t->nsec;
 357
 358        /* determine the minimum size for period */
 359        step = 2 * (fm10k_read_reg(hw, FM10K_SYSTIME_CFG) &
 360                    FM10K_SYSTIME_CFG_STEP_MASK);
 361
 362        /* verify the value is in range supported by hardware */
 363        if ((period && (period < step)) || (period > U32_MAX))
 364                return -ERANGE;
 365
 366        /* notify hardware of request to being sending pulses */
 367        fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_PULSE(rq->perout.index),
 368                           (u32)period);
 369
 370        return 0;
 371}
 372
 373static struct ptp_pin_desc fm10k_ptp_pd[2] = {
 374        {
 375                .name = "IEEE1588_PULSE0",
 376                .index = 0,
 377                .func = PTP_PF_PEROUT,
 378                .chan = 0
 379        },
 380        {
 381                .name = "IEEE1588_PULSE1",
 382                .index = 1,
 383                .func = PTP_PF_PEROUT,
 384                .chan = 1
 385        }
 386};
 387
 388static int fm10k_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
 389                            enum ptp_pin_function func, unsigned int chan)
 390{
 391        /* verify the requested pin is there */
 392        if (pin >= ptp->n_pins || !ptp->pin_config)
 393                return -EINVAL;
 394
 395        /* enforce locked channels, no changing them */
 396        if (chan != ptp->pin_config[pin].chan)
 397                return -EINVAL;
 398
 399        /* we want to keep the functions locked as well */
 400        if (func != ptp->pin_config[pin].func)
 401                return -EINVAL;
 402
 403        return 0;
 404}
 405
 406void fm10k_ptp_register(struct fm10k_intfc *interface)
 407{
 408        struct ptp_clock_info *ptp_caps = &interface->ptp_caps;
 409        struct device *dev = &interface->pdev->dev;
 410        struct ptp_clock *ptp_clock;
 411
 412        snprintf(ptp_caps->name, sizeof(ptp_caps->name),
 413                 "%s", interface->netdev->name);
 414        ptp_caps->owner         = THIS_MODULE;
 415        /* This math is simply the inverse of the math in
 416         * fm10k_adjust_systime_pf applied to an adjustment value
 417         * of 2^30 - 1 which is the maximum value of the register:
 418         *      max_ppb == ((2^30 - 1) * 5^9) / 2^31
 419         */
 420        ptp_caps->max_adj       = 976562;
 421        ptp_caps->adjfreq       = fm10k_ptp_adjfreq;
 422        ptp_caps->adjtime       = fm10k_ptp_adjtime;
 423        ptp_caps->gettime64     = fm10k_ptp_gettime;
 424        ptp_caps->settime64     = fm10k_ptp_settime;
 425
 426        /* provide pins if BAR4 is accessible */
 427        if (interface->sw_addr) {
 428                /* enable periodic outputs */
 429                ptp_caps->n_per_out = 2;
 430                ptp_caps->enable        = fm10k_ptp_enable;
 431
 432                /* enable clock pins */
 433                ptp_caps->verify        = fm10k_ptp_verify;
 434                ptp_caps->n_pins = 2;
 435                ptp_caps->pin_config = fm10k_ptp_pd;
 436        }
 437
 438        ptp_clock = ptp_clock_register(ptp_caps, dev);
 439        if (IS_ERR(ptp_clock)) {
 440                ptp_clock = NULL;
 441                dev_err(dev, "ptp_clock_register failed\n");
 442        } else {
 443                dev_info(dev, "registered PHC device %s\n", ptp_caps->name);
 444        }
 445
 446        interface->ptp_clock = ptp_clock;
 447}
 448
 449void fm10k_ptp_unregister(struct fm10k_intfc *interface)
 450{
 451        struct ptp_clock *ptp_clock = interface->ptp_clock;
 452        struct device *dev = &interface->pdev->dev;
 453
 454        if (!ptp_clock)
 455                return;
 456
 457        interface->ptp_clock = NULL;
 458
 459        ptp_clock_unregister(ptp_clock);
 460        dev_info(dev, "removed PHC %s\n", interface->ptp_caps.name);
 461}
 462