From 863981e96738983919de841ec669e157e6bdaeb0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Sun, 11 Sep 2016 04:34:46 -0300 Subject: Linux-libre 4.7.1-gnu --- drivers/net/ethernet/intel/fm10k/fm10k_ptp.c | 462 --------------------------- 1 file changed, 462 deletions(-) delete mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_ptp.c (limited to 'drivers/net/ethernet/intel/fm10k/fm10k_ptp.c') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c b/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c deleted file mode 100644 index b4945e8ab..000000000 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c +++ /dev/null @@ -1,462 +0,0 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include -#include - -#include "fm10k.h" - -#define FM10K_TS_TX_TIMEOUT (HZ * 15) - -void fm10k_systime_to_hwtstamp(struct fm10k_intfc *interface, - struct skb_shared_hwtstamps *hwtstamp, - u64 systime) -{ - unsigned long flags; - - read_lock_irqsave(&interface->systime_lock, flags); - systime += interface->ptp_adjust; - read_unlock_irqrestore(&interface->systime_lock, flags); - - hwtstamp->hwtstamp = ns_to_ktime(systime); -} - -static struct sk_buff *fm10k_ts_tx_skb(struct fm10k_intfc *interface, - __le16 dglort) -{ - struct sk_buff_head *list = &interface->ts_tx_skb_queue; - struct sk_buff *skb; - - skb_queue_walk(list, skb) { - if (FM10K_CB(skb)->fi.w.dglort == dglort) - return skb; - } - - return NULL; -} - -void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb) -{ - struct sk_buff_head *list = &interface->ts_tx_skb_queue; - struct sk_buff *clone; - unsigned long flags; - - /* create clone for us to return on the Tx path */ - clone = skb_clone_sk(skb); - if (!clone) - return; - - FM10K_CB(clone)->ts_tx_timeout = jiffies + FM10K_TS_TX_TIMEOUT; - spin_lock_irqsave(&list->lock, flags); - - /* attempt to locate any buffers with the same dglort, - * if none are present then insert skb in tail of list - */ - skb = fm10k_ts_tx_skb(interface, FM10K_CB(clone)->fi.w.dglort); - if (!skb) { - skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS; - __skb_queue_tail(list, clone); - } - - spin_unlock_irqrestore(&list->lock, flags); - - /* if list is already has one then we just free the clone */ - if (skb) - dev_kfree_skb(clone); -} - -void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort, - u64 systime) -{ - struct skb_shared_hwtstamps shhwtstamps; - struct sk_buff_head *list = &interface->ts_tx_skb_queue; - struct sk_buff *skb; - unsigned long flags; - - spin_lock_irqsave(&list->lock, flags); - - /* attempt to locate and pull the sk_buff out of the list */ - skb = fm10k_ts_tx_skb(interface, dglort); - if (skb) - __skb_unlink(skb, list); - - spin_unlock_irqrestore(&list->lock, flags); - - /* if not found do nothing */ - if (!skb) - return; - - /* timestamp the sk_buff and free out copy */ - fm10k_systime_to_hwtstamp(interface, &shhwtstamps, systime); - skb_tstamp_tx(skb, &shhwtstamps); - dev_kfree_skb_any(skb); -} - -void fm10k_ts_tx_subtask(struct fm10k_intfc *interface) -{ - struct sk_buff_head *list = &interface->ts_tx_skb_queue; - struct sk_buff *skb, *tmp; - unsigned long flags; - - /* If we're down or resetting, just bail */ - if (test_bit(__FM10K_DOWN, &interface->state) || - test_bit(__FM10K_RESETTING, &interface->state)) - return; - - spin_lock_irqsave(&list->lock, flags); - - /* walk though the list and flush any expired timestamp packets */ - skb_queue_walk_safe(list, skb, tmp) { - if (!time_is_after_jiffies(FM10K_CB(skb)->ts_tx_timeout)) - continue; - __skb_unlink(skb, list); - kfree_skb(skb); - interface->tx_hwtstamp_timeouts++; - } - - spin_unlock_irqrestore(&list->lock, flags); -} - -static u64 fm10k_systime_read(struct fm10k_intfc *interface) -{ - struct fm10k_hw *hw = &interface->hw; - - return hw->mac.ops.read_systime(hw); -} - -void fm10k_ts_reset(struct fm10k_intfc *interface) -{ - s64 ns = ktime_to_ns(ktime_get_real()); - unsigned long flags; - - /* reinitialize the clock */ - write_lock_irqsave(&interface->systime_lock, flags); - interface->ptp_adjust = fm10k_systime_read(interface) - ns; - write_unlock_irqrestore(&interface->systime_lock, flags); -} - -void fm10k_ts_init(struct fm10k_intfc *interface) -{ - /* Initialize lock protecting systime access */ - rwlock_init(&interface->systime_lock); - - /* Initialize skb queue for pending timestamp requests */ - skb_queue_head_init(&interface->ts_tx_skb_queue); - - /* reset the clock to current kernel time */ - fm10k_ts_reset(interface); -} - -/** - * fm10k_get_ts_config - get current hardware timestamping configuration - * @netdev: network interface device structure - * @ifreq: ioctl data - * - * This function returns the current timestamping settings. Rather than - * attempt to deconstruct registers to fill in the values, simply keep a copy - * of the old settings around, and return a copy when requested. - */ -int fm10k_get_ts_config(struct net_device *netdev, struct ifreq *ifr) -{ - struct fm10k_intfc *interface = netdev_priv(netdev); - struct hwtstamp_config *config = &interface->ts_config; - - return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? - -EFAULT : 0; -} - -/** - * fm10k_set_ts_config - control hardware time stamping - * @netdev: network interface device structure - * @ifreq: ioctl data - * - * Outgoing time stamping can be enabled and disabled. Play nice and - * disable it when requested, although it shouldn't cause any overhead - * when no packet needs it. At most one packet in the queue may be - * marked for time stamping, otherwise it would be impossible to tell - * for sure to which packet the hardware time stamp belongs. - * - * Incoming time stamping has to be configured via the hardware - * filters. Not all combinations are supported, in particular event - * type has to be specified. Matching the kind of event packet is - * not supported, with the exception of "all V2 events regardless of - * level 2 or 4". - * - * Since hardware always timestamps Path delay packets when timestamping V2 - * packets, regardless of the type specified in the register, only use V2 - * Event mode. This more accurately tells the user what the hardware is going - * to do anyways. - */ -int fm10k_set_ts_config(struct net_device *netdev, struct ifreq *ifr) -{ - struct fm10k_intfc *interface = netdev_priv(netdev); - struct hwtstamp_config ts_config; - - if (copy_from_user(&ts_config, ifr->ifr_data, sizeof(ts_config))) - return -EFAULT; - - /* reserved for future extensions */ - if (ts_config.flags) - return -EINVAL; - - switch (ts_config.tx_type) { - case HWTSTAMP_TX_OFF: - break; - case HWTSTAMP_TX_ON: - /* we likely need some check here to see if this is supported */ - break; - default: - return -ERANGE; - } - - switch (ts_config.rx_filter) { - case HWTSTAMP_FILTER_NONE: - interface->flags &= ~FM10K_FLAG_RX_TS_ENABLED; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - case HWTSTAMP_FILTER_ALL: - interface->flags |= FM10K_FLAG_RX_TS_ENABLED; - ts_config.rx_filter = HWTSTAMP_FILTER_ALL; - break; - default: - return -ERANGE; - } - - /* save these settings for future reference */ - interface->ts_config = ts_config; - - return copy_to_user(ifr->ifr_data, &ts_config, sizeof(ts_config)) ? - -EFAULT : 0; -} - -static int fm10k_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -{ - struct fm10k_intfc *interface; - struct fm10k_hw *hw; - int err; - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - hw = &interface->hw; - - err = hw->mac.ops.adjust_systime(hw, ppb); - - /* the only error we should see is if the value is out of range */ - return (err == FM10K_ERR_PARAM) ? -ERANGE : err; -} - -static int fm10k_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - struct fm10k_intfc *interface; - unsigned long flags; - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - - write_lock_irqsave(&interface->systime_lock, flags); - interface->ptp_adjust += delta; - write_unlock_irqrestore(&interface->systime_lock, flags); - - return 0; -} - -static int fm10k_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) -{ - struct fm10k_intfc *interface; - unsigned long flags; - u64 now; - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - - read_lock_irqsave(&interface->systime_lock, flags); - now = fm10k_systime_read(interface) + interface->ptp_adjust; - read_unlock_irqrestore(&interface->systime_lock, flags); - - *ts = ns_to_timespec64(now); - - return 0; -} - -static int fm10k_ptp_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts) -{ - struct fm10k_intfc *interface; - unsigned long flags; - u64 ns = timespec64_to_ns(ts); - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - - write_lock_irqsave(&interface->systime_lock, flags); - interface->ptp_adjust = fm10k_systime_read(interface) - ns; - write_unlock_irqrestore(&interface->systime_lock, flags); - - return 0; -} - -static int fm10k_ptp_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, - int __always_unused on) -{ - struct ptp_clock_time *t = &rq->perout.period; - struct fm10k_intfc *interface; - struct fm10k_hw *hw; - u64 period; - u32 step; - - /* we can only support periodic output */ - if (rq->type != PTP_CLK_REQ_PEROUT) - return -EINVAL; - - /* verify the requested channel is there */ - if (rq->perout.index >= ptp->n_per_out) - return -EINVAL; - - /* we cannot enforce start time as there is no - * mechanism for that in the hardware, we can only control - * the period. - */ - - /* we cannot support periods greater than 4 seconds due to reg limit */ - if (t->sec > 4 || t->sec < 0) - return -ERANGE; - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - hw = &interface->hw; - - /* we simply cannot support the operation if we don't have BAR4 */ - if (!hw->sw_addr) - return -ENOTSUPP; - - /* convert to unsigned 64b ns, verify we can put it in a 32b register */ - period = t->sec * 1000000000LL + t->nsec; - - /* determine the minimum size for period */ - step = 2 * (fm10k_read_reg(hw, FM10K_SYSTIME_CFG) & - FM10K_SYSTIME_CFG_STEP_MASK); - - /* verify the value is in range supported by hardware */ - if ((period && (period < step)) || (period > U32_MAX)) - return -ERANGE; - - /* notify hardware of request to being sending pulses */ - fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_PULSE(rq->perout.index), - (u32)period); - - return 0; -} - -static struct ptp_pin_desc fm10k_ptp_pd[2] = { - { - .name = "IEEE1588_PULSE0", - .index = 0, - .func = PTP_PF_PEROUT, - .chan = 0 - }, - { - .name = "IEEE1588_PULSE1", - .index = 1, - .func = PTP_PF_PEROUT, - .chan = 1 - } -}; - -static int fm10k_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin, - enum ptp_pin_function func, unsigned int chan) -{ - /* verify the requested pin is there */ - if (pin >= ptp->n_pins || !ptp->pin_config) - return -EINVAL; - - /* enforce locked channels, no changing them */ - if (chan != ptp->pin_config[pin].chan) - return -EINVAL; - - /* we want to keep the functions locked as well */ - if (func != ptp->pin_config[pin].func) - return -EINVAL; - - return 0; -} - -void fm10k_ptp_register(struct fm10k_intfc *interface) -{ - struct ptp_clock_info *ptp_caps = &interface->ptp_caps; - struct device *dev = &interface->pdev->dev; - struct ptp_clock *ptp_clock; - - snprintf(ptp_caps->name, sizeof(ptp_caps->name), - "%s", interface->netdev->name); - ptp_caps->owner = THIS_MODULE; - /* This math is simply the inverse of the math in - * fm10k_adjust_systime_pf applied to an adjustment value - * of 2^30 - 1 which is the maximum value of the register: - * max_ppb == ((2^30 - 1) * 5^9) / 2^31 - */ - ptp_caps->max_adj = 976562; - ptp_caps->adjfreq = fm10k_ptp_adjfreq; - ptp_caps->adjtime = fm10k_ptp_adjtime; - ptp_caps->gettime64 = fm10k_ptp_gettime; - ptp_caps->settime64 = fm10k_ptp_settime; - - /* provide pins if BAR4 is accessible */ - if (interface->sw_addr) { - /* enable periodic outputs */ - ptp_caps->n_per_out = 2; - ptp_caps->enable = fm10k_ptp_enable; - - /* enable clock pins */ - ptp_caps->verify = fm10k_ptp_verify; - ptp_caps->n_pins = 2; - ptp_caps->pin_config = fm10k_ptp_pd; - } - - ptp_clock = ptp_clock_register(ptp_caps, dev); - if (IS_ERR(ptp_clock)) { - ptp_clock = NULL; - dev_err(dev, "ptp_clock_register failed\n"); - } else { - dev_info(dev, "registered PHC device %s\n", ptp_caps->name); - } - - interface->ptp_clock = ptp_clock; -} - -void fm10k_ptp_unregister(struct fm10k_intfc *interface) -{ - struct ptp_clock *ptp_clock = interface->ptp_clock; - struct device *dev = &interface->pdev->dev; - - if (!ptp_clock) - return; - - interface->ptp_clock = NULL; - - ptp_clock_unregister(ptp_clock); - dev_info(dev, "removed PHC %s\n", interface->ptp_caps.name); -} -- cgit v1.2.3-54-g00ecf