/** * i40e_ptp_init - Initialize the 1588 support after device probe or reset * @pf: Board private structure * * This function sets device up for 1588 support. The first time it is run, it * will create a PHC clock device. It does not create a clock device if one * already exists. It also reconfigures the device after a reset. **/ void i40e_ptp_init(struct i40e_pf *pf) { struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev; struct i40e_hw *hw = &pf->hw; u32 pf_id; long err; /* Only one PF is assigned to control 1588 logic per port. Do not * enable any support for PFs not assigned via PRTTSYN_CTL0.PF_ID */ pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >> I40E_PRTTSYN_CTL0_PF_ID_SHIFT; if (hw->pf_id != pf_id) { pf->flags &= ~I40E_FLAG_PTP; dev_info(&pf->pdev->dev, "%s: PTP not supported on %s\n", __func__, netdev->name); return; } /* we have to initialize the lock first, since we can't control * when the user will enter the PHC device entry points */ spin_lock_init(&pf->tmreg_lock); /* ensure we have a clock device */ err = i40e_ptp_create_clock(pf); if (err) { pf->ptp_clock = NULL; dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n", __func__); } else { struct timespec64 ts; u32 regval; dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__, netdev->name); pf->flags |= I40E_FLAG_PTP; /* Ensure the clocks are running. */ regval = rd32(hw, I40E_PRTTSYN_CTL0); regval |= I40E_PRTTSYN_CTL0_TSYNENA_MASK; wr32(hw, I40E_PRTTSYN_CTL0, regval); regval = rd32(hw, I40E_PRTTSYN_CTL1); regval |= I40E_PRTTSYN_CTL1_TSYNENA_MASK; wr32(hw, I40E_PRTTSYN_CTL1, regval); /* Set the increment value per clock tick. */ i40e_ptp_set_increment(pf); /* reset timestamping mode */ i40e_ptp_set_timestamp_mode(pf, &pf->tstamp_config); /* Set the clock value. */ ts = ktime_to_timespec64(ktime_get_real()); i40e_ptp_settime(&pf->ptp_caps, &ts); } }
/* * Convert ktime to rtc_time */ struct rtc_time rtc_ktime_to_tm(ktime_t kt) { struct timespec64 ts; struct rtc_time ret; ts = ktime_to_timespec64(kt); /* Round up any ns */ if (ts.tv_nsec) ts.tv_sec++; rtc_time64_to_tm(ts.tv_sec, &ret); return ret; }
/** * igb_ptp_reset - Re-enable the adapter for PTP following a reset. * @adapter: Board private structure. * * This function handles the reset work required to re-enable the PTP device. **/ void igb_ptp_reset(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; unsigned long flags; /* reset the tstamp_config */ igb_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); spin_lock_irqsave(&adapter->tmreg_lock, flags); switch (adapter->hw.mac.type) { case e1000_82576: /* Dial the nominal frequency. */ wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); break; case e1000_82580: case e1000_i354: case e1000_i350: case e1000_i210: case e1000_i211: wr32(E1000_TSAUXC, 0x0); wr32(E1000_TSSDP, 0x0); wr32(E1000_TSIM, TSYNC_INTERRUPTS | (adapter->pps_sys_wrap_on ? TSINTR_SYS_WRAP : 0)); wr32(E1000_IMS, E1000_IMS_TS); break; default: /* No work to do. */ goto out; } /* Re-initialize the timer. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { struct timespec64 ts = ktime_to_timespec64(ktime_get_real()); igb_ptp_write_i210(adapter, &ts); } else { timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); } out: spin_unlock_irqrestore(&adapter->tmreg_lock, flags); wrfl(); if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK) schedule_delayed_work(&adapter->ptp_overflow_work, IGB_SYSTIM_OVERFLOW_PERIOD); }
/** * igb_ptp_reset - Re-enable the adapter for PTP following a reset. * @adapter: Board private structure. * * This function handles the reset work required to re-enable the PTP device. **/ void igb_ptp_reset(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; unsigned long flags; if (!(adapter->flags & IGB_FLAG_PTP)) return; /* reset the tstamp_config */ igb_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); spin_lock_irqsave(&adapter->tmreg_lock, flags); switch (adapter->hw.mac.type) { case e1000_82576: /* Dial the nominal frequency. */ E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); break; case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); E1000_WRITE_REG(hw, E1000_TSSDP, 0x0); E1000_WRITE_REG(hw, E1000_TSIM, TSYNC_INTERRUPTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); break; default: /* No work to do. */ goto out; } /* Re-initialize the timer. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { struct timespec64 ts64 = ktime_to_timespec64(ktime_get_real()); igb_ptp_write_i210(adapter, &ts64); } else { timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); } out: spin_unlock_irqrestore(&adapter->tmreg_lock, flags); }
/** * i40e_ptp_create_clock - Create PTP clock device for userspace * @pf: Board private structure * * This function creates a new PTP clock device. It only creates one if we * don't already have one, so it is safe to call. Will return error if it * can't create one, but success if we already have a device. Should be used * by i40e_ptp_init to create clock initially, and prevent global resets from * creating new clock devices. **/ static long i40e_ptp_create_clock(struct i40e_pf *pf) { /* no need to create a clock device if we already have one */ if (!IS_ERR_OR_NULL(pf->ptp_clock)) return 0; strlcpy(pf->ptp_caps.name, i40e_driver_name, sizeof(pf->ptp_caps.name) - 1); pf->ptp_caps.owner = THIS_MODULE; pf->ptp_caps.max_adj = 999999999; pf->ptp_caps.n_ext_ts = 0; pf->ptp_caps.pps = 0; pf->ptp_caps.adjfreq = i40e_ptp_adjfreq; pf->ptp_caps.adjtime = i40e_ptp_adjtime; pf->ptp_caps.gettimex64 = i40e_ptp_gettimex; pf->ptp_caps.settime64 = i40e_ptp_settime; pf->ptp_caps.enable = i40e_ptp_feature_enable; /* Attempt to register the clock before enabling the hardware. */ pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev); if (IS_ERR(pf->ptp_clock)) return PTR_ERR(pf->ptp_clock); /* clear the hwtstamp settings here during clock create, instead of * during regular init, so that we can maintain settings across a * reset or suspend. */ pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF; /* Set the previous "reset" time to the current Kernel clock time */ pf->ptp_prev_hw_time = ktime_to_timespec64(ktime_get_real()); pf->ptp_reset_start = ktime_get(); return 0; }
static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode) { struct restart_block *restart; hrtimer_init_sleeper(t, current); do { set_current_state(TASK_INTERRUPTIBLE); hrtimer_start_expires(&t->timer, mode); if (likely(t->task)) freezable_schedule(); hrtimer_cancel(&t->timer); mode = HRTIMER_MODE_ABS; } while (t->task && !signal_pending(current)); __set_current_state(TASK_RUNNING); if (!t->task) return 0; restart = ¤t->restart_block; if (restart->nanosleep.type != TT_NONE) { ktime_t rem = hrtimer_expires_remaining(&t->timer); struct timespec64 rmt; if (rem <= 0) return 0; rmt = ktime_to_timespec64(rem); return nanosleep_copyout(restart, &rmt); } return -ERESTART_RESTARTBLOCK; }
long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) { struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); struct ptp_sys_offset_extended *extoff = NULL; struct ptp_sys_offset_precise precise_offset; struct system_device_crosststamp xtstamp; struct ptp_clock_info *ops = ptp->info; struct ptp_sys_offset *sysoff = NULL; struct ptp_system_timestamp sts; struct ptp_clock_request req; struct ptp_clock_caps caps; struct ptp_clock_time *pct; unsigned int i, pin_index; struct ptp_pin_desc pd; struct timespec64 ts; int enable, err = 0; switch (cmd) { case PTP_CLOCK_GETCAPS: memset(&caps, 0, sizeof(caps)); caps.max_adj = ptp->info->max_adj; caps.n_alarm = ptp->info->n_alarm; caps.n_ext_ts = ptp->info->n_ext_ts; caps.n_per_out = ptp->info->n_per_out; caps.pps = ptp->info->pps; caps.n_pins = ptp->info->n_pins; caps.cross_timestamping = ptp->info->getcrosststamp != NULL; if (copy_to_user((void __user *)arg, &caps, sizeof(caps))) err = -EFAULT; break; case PTP_EXTTS_REQUEST: if (copy_from_user(&req.extts, (void __user *)arg, sizeof(req.extts))) { err = -EFAULT; break; } if (req.extts.index >= ops->n_ext_ts) { err = -EINVAL; break; } req.type = PTP_CLK_REQ_EXTTS; enable = req.extts.flags & PTP_ENABLE_FEATURE ? 1 : 0; err = ops->enable(ops, &req, enable); break; case PTP_PEROUT_REQUEST: if (copy_from_user(&req.perout, (void __user *)arg, sizeof(req.perout))) { err = -EFAULT; break; } if (req.perout.index >= ops->n_per_out) { err = -EINVAL; break; } req.type = PTP_CLK_REQ_PEROUT; enable = req.perout.period.sec || req.perout.period.nsec; err = ops->enable(ops, &req, enable); break; case PTP_ENABLE_PPS: if (!capable(CAP_SYS_TIME)) return -EPERM; req.type = PTP_CLK_REQ_PPS; enable = arg ? 1 : 0; err = ops->enable(ops, &req, enable); break; case PTP_SYS_OFFSET_PRECISE: if (!ptp->info->getcrosststamp) { err = -EOPNOTSUPP; break; } err = ptp->info->getcrosststamp(ptp->info, &xtstamp); if (err) break; memset(&precise_offset, 0, sizeof(precise_offset)); ts = ktime_to_timespec64(xtstamp.device); precise_offset.device.sec = ts.tv_sec; precise_offset.device.nsec = ts.tv_nsec; ts = ktime_to_timespec64(xtstamp.sys_realtime); precise_offset.sys_realtime.sec = ts.tv_sec; precise_offset.sys_realtime.nsec = ts.tv_nsec; ts = ktime_to_timespec64(xtstamp.sys_monoraw); precise_offset.sys_monoraw.sec = ts.tv_sec; precise_offset.sys_monoraw.nsec = ts.tv_nsec; if (copy_to_user((void __user *)arg, &precise_offset, sizeof(precise_offset))) err = -EFAULT; break; case PTP_SYS_OFFSET_EXTENDED: if (!ptp->info->gettimex64) { err = -EOPNOTSUPP; break; } extoff = memdup_user((void __user *)arg, sizeof(*extoff)); if (IS_ERR(extoff)) { err = PTR_ERR(extoff); extoff = NULL; break; } if (extoff->n_samples > PTP_MAX_SAMPLES || extoff->rsv[0] || extoff->rsv[1] || extoff->rsv[2]) { err = -EINVAL; break; } for (i = 0; i < extoff->n_samples; i++) { err = ptp->info->gettimex64(ptp->info, &ts, &sts); if (err) goto out; extoff->ts[i][0].sec = sts.pre_ts.tv_sec; extoff->ts[i][0].nsec = sts.pre_ts.tv_nsec; extoff->ts[i][1].sec = ts.tv_sec; extoff->ts[i][1].nsec = ts.tv_nsec; extoff->ts[i][2].sec = sts.post_ts.tv_sec; extoff->ts[i][2].nsec = sts.post_ts.tv_nsec; } if (copy_to_user((void __user *)arg, extoff, sizeof(*extoff))) err = -EFAULT; break; case PTP_SYS_OFFSET: sysoff = memdup_user((void __user *)arg, sizeof(*sysoff)); if (IS_ERR(sysoff)) { err = PTR_ERR(sysoff); sysoff = NULL; break; } if (sysoff->n_samples > PTP_MAX_SAMPLES) { err = -EINVAL; break; } pct = &sysoff->ts[0]; for (i = 0; i < sysoff->n_samples; i++) { ktime_get_real_ts64(&ts); pct->sec = ts.tv_sec; pct->nsec = ts.tv_nsec; pct++; if (ops->gettimex64) err = ops->gettimex64(ops, &ts, NULL); else err = ops->gettime64(ops, &ts); if (err) goto out; pct->sec = ts.tv_sec; pct->nsec = ts.tv_nsec; pct++; } ktime_get_real_ts64(&ts); pct->sec = ts.tv_sec; pct->nsec = ts.tv_nsec; if (copy_to_user((void __user *)arg, sysoff, sizeof(*sysoff))) err = -EFAULT; break; case PTP_PIN_GETFUNC: if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) { err = -EFAULT; break; } pin_index = pd.index; if (pin_index >= ops->n_pins) { err = -EINVAL; break; } pin_index = array_index_nospec(pin_index, ops->n_pins); if (mutex_lock_interruptible(&ptp->pincfg_mux)) return -ERESTARTSYS; pd = ops->pin_config[pin_index]; mutex_unlock(&ptp->pincfg_mux); if (!err && copy_to_user((void __user *)arg, &pd, sizeof(pd))) err = -EFAULT; break; case PTP_PIN_SETFUNC: if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) { err = -EFAULT; break; } pin_index = pd.index; if (pin_index >= ops->n_pins) { err = -EINVAL; break; } pin_index = array_index_nospec(pin_index, ops->n_pins); if (mutex_lock_interruptible(&ptp->pincfg_mux)) return -ERESTARTSYS; err = ptp_set_pinfunc(ptp, pin_index, pd.func, pd.chan); mutex_unlock(&ptp->pincfg_mux); break; default: err = -ENOTTY; break; } out: kfree(extoff); kfree(sysoff); return err; }
/* This is an inline function, we don't really care about a long * list of arguments */ static inline int __build_packet_message(struct nfnl_log_net *log, struct nfulnl_instance *inst, const struct sk_buff *skb, unsigned int data_len, u_int8_t pf, unsigned int hooknum, const struct net_device *indev, const struct net_device *outdev, const char *prefix, unsigned int plen, const struct nfnl_ct_hook *nfnl_ct, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { struct nfulnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; sk_buff_data_t old_tail = inst->skb->tail; struct sock *sk; const unsigned char *hwhdrp; nlh = nlmsg_put(inst->skb, 0, 0, nfnl_msg_type(NFNL_SUBSYS_ULOG, NFULNL_MSG_PACKET), sizeof(struct nfgenmsg), 0); if (!nlh) return -1; nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = pf; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = htons(inst->group_num); memset(&pmsg, 0, sizeof(pmsg)); pmsg.hw_protocol = skb->protocol; pmsg.hook = hooknum; if (nla_put(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg)) goto nla_put_failure; if (prefix && nla_put(inst->skb, NFULA_PREFIX, plen, prefix)) goto nla_put_failure; if (indev) { #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(indev->ifindex))) goto nla_put_failure; #else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical input device, we need to * look for bridge group (when called from * netfilter_bridge) */ if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, htonl(indev->ifindex)) || /* this is the bridge group "brX" */ /* rcu_read_lock()ed by nf_hook_thresh or * nf_log_packet. */ nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(br_port_get_rcu(indev)->br->dev->ifindex))) goto nla_put_failure; } else { struct net_device *physindev; /* Case 2: indev is bridge group, we need to look for * physical device (when called from ipv4) */ if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(indev->ifindex))) goto nla_put_failure; physindev = nf_bridge_get_physindev(skb); if (physindev && nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, htonl(physindev->ifindex))) goto nla_put_failure; } #endif } if (outdev) { #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) goto nla_put_failure; #else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical output device, we need to * look for bridge group (when called from * netfilter_bridge) */ if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, htonl(outdev->ifindex)) || /* this is the bridge group "brX" */ /* rcu_read_lock()ed by nf_hook_thresh or * nf_log_packet. */ nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(br_port_get_rcu(outdev)->br->dev->ifindex))) goto nla_put_failure; } else { struct net_device *physoutdev; /* Case 2: indev is a bridge group, we need to look * for physical device (when called from ipv4) */ if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) goto nla_put_failure; physoutdev = nf_bridge_get_physoutdev(skb); if (physoutdev && nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, htonl(physoutdev->ifindex))) goto nla_put_failure; } #endif } if (skb->mark && nla_put_be32(inst->skb, NFULA_MARK, htonl(skb->mark))) goto nla_put_failure; if (indev && skb->dev && skb->mac_header != skb->network_header) { struct nfulnl_msg_packet_hw phw; int len; memset(&phw, 0, sizeof(phw)); len = dev_parse_header(skb, phw.hw_addr); if (len > 0) { phw.hw_addrlen = htons(len); if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw)) goto nla_put_failure; } } if (indev && skb_mac_header_was_set(skb)) { if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || nla_put_be16(inst->skb, NFULA_HWLEN, htons(skb->dev->hard_header_len))) goto nla_put_failure; hwhdrp = skb_mac_header(skb); if (skb->dev->type == ARPHRD_SIT) hwhdrp -= ETH_HLEN; if (hwhdrp >= skb->head && nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, hwhdrp)) goto nla_put_failure; } if (skb->tstamp) { struct nfulnl_msg_packet_timestamp ts; struct timespec64 kts = ktime_to_timespec64(skb->tstamp); ts.sec = cpu_to_be64(kts.tv_sec); ts.usec = cpu_to_be64(kts.tv_nsec / NSEC_PER_USEC); if (nla_put(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts)) goto nla_put_failure; } /* UID */ sk = skb->sk; if (sk && sk_fullsock(sk)) { read_lock_bh(&sk->sk_callback_lock); if (sk->sk_socket && sk->sk_socket->file) { struct file *file = sk->sk_socket->file; const struct cred *cred = file->f_cred; struct user_namespace *user_ns = inst->peer_user_ns; __be32 uid = htonl(from_kuid_munged(user_ns, cred->fsuid)); __be32 gid = htonl(from_kgid_munged(user_ns, cred->fsgid)); read_unlock_bh(&sk->sk_callback_lock); if (nla_put_be32(inst->skb, NFULA_UID, uid) || nla_put_be32(inst->skb, NFULA_GID, gid)) goto nla_put_failure; } else read_unlock_bh(&sk->sk_callback_lock); } /* local sequence number */ if ((inst->flags & NFULNL_CFG_F_SEQ) && nla_put_be32(inst->skb, NFULA_SEQ, htonl(inst->seq++))) goto nla_put_failure; /* global sequence number */ if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) && nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL, htonl(atomic_inc_return(&log->global_seq)))) goto nla_put_failure; if (ct && nfnl_ct->build(inst->skb, ct, ctinfo, NFULA_CT, NFULA_CT_INFO) < 0) goto nla_put_failure; if (data_len) { struct nlattr *nla; int size = nla_attr_size(data_len); if (skb_tailroom(inst->skb) < nla_total_size(data_len)) goto nla_put_failure; nla = skb_put(inst->skb, nla_total_size(data_len)); nla->nla_type = NFULA_PAYLOAD; nla->nla_len = size; if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) BUG(); } nlh->nlmsg_len = inst->skb->tail - old_tail; return 0; nla_put_failure: PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n"); return -1; }
void igb_ptp_init(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; #ifdef HAVE_PTP_1588_CLOCK_PINS int i; #endif /* HAVE_PTP_1588_CLOCK_PINS */ switch (hw->mac.type) { case e1000_82576: snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 999999881; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576; adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; #ifdef HAVE_PTP_CLOCK_INFO_GETTIME64 adapter->ptp_caps.gettime64 = igb_ptp_gettime64_82576; adapter->ptp_caps.settime64 = igb_ptp_settime64_82576; #else adapter->ptp_caps.gettime = igb_ptp_gettime_82576; adapter->ptp_caps.settime = igb_ptp_settime_82576; #endif adapter->ptp_caps.enable = igb_ptp_feature_enable; adapter->cc.read = igb_ptp_read_82576; adapter->cc.mask = CLOCKSOURCE_MASK(64); adapter->cc.mult = 1; adapter->cc.shift = IGB_82576_TSYNC_SHIFT; /* Dial the nominal frequency. */ E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); break; case e1000_82580: case e1000_i350: case e1000_i354: snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 62499999; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; #ifdef HAVE_PTP_CLOCK_INFO_GETTIME64 adapter->ptp_caps.gettime64 = igb_ptp_gettime64_82576; adapter->ptp_caps.settime64 = igb_ptp_settime64_82576; #else adapter->ptp_caps.gettime = igb_ptp_gettime_82576; adapter->ptp_caps.settime = igb_ptp_settime_82576; #endif adapter->ptp_caps.enable = igb_ptp_feature_enable; adapter->cc.read = igb_ptp_read_82580; adapter->cc.mask = CLOCKSOURCE_MASK(IGB_NBITS_82580); adapter->cc.mult = 1; adapter->cc.shift = 0; /* Enable the timer functions by clearing bit 31. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); break; case e1000_i210: case e1000_i211: #ifdef HAVE_PTP_1588_CLOCK_PINS for (i = 0; i < IGB_N_SDP; i++) { struct ptp_pin_desc *ppd = &adapter->sdp_config[i]; snprintf(ppd->name, sizeof(ppd->name), "SDP%d", i); ppd->index = i; ppd->func = PTP_PF_NONE; } #endif /* HAVE_PTP_1588_CLOCK_PINS */ snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 62499999; adapter->ptp_caps.n_ext_ts = IGB_N_EXTTS; adapter->ptp_caps.n_per_out = IGB_N_PEROUT; #ifdef HAVE_PTP_1588_CLOCK_PINS adapter->ptp_caps.n_pins = IGB_N_SDP; #endif /* HAVE_PTP_1588_CLOCK_PINS */ adapter->ptp_caps.pps = 1; #ifdef HAVE_PTP_1588_CLOCK_PINS adapter->ptp_caps.pin_config = adapter->sdp_config; #endif /* HAVE_PTP_1588_CLOCK_PINS */ adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210; #ifdef HAVE_PTP_CLOCK_INFO_GETTIME64 adapter->ptp_caps.gettime64 = igb_ptp_gettime64_i210; adapter->ptp_caps.settime64 = igb_ptp_settime64_i210; #else adapter->ptp_caps.gettime = igb_ptp_gettime_i210; adapter->ptp_caps.settime = igb_ptp_settime_i210; #endif adapter->ptp_caps.enable = igb_ptp_feature_enable_i210; #ifdef HAVE_PTP_1588_CLOCK_PINS adapter->ptp_caps.verify = igb_ptp_verify_pin; #endif /* HAVE_PTP_1588_CLOCK_PINS */ /* Enable the timer functions by clearing bit 31. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); break; default: adapter->ptp_clock = NULL; return; } E1000_WRITE_FLUSH(hw); spin_lock_init(&adapter->tmreg_lock); INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work); /* Initialize the clock and overflow work for devices that need it. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { struct timespec64 ts = ktime_to_timespec64(ktime_get_real()); igb_ptp_settime64_i210(&adapter->ptp_caps, &ts); } else { timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); INIT_DELAYED_WORK(&adapter->ptp_overflow_work, igb_ptp_overflow_check_82576); schedule_delayed_work(&adapter->ptp_overflow_work, IGB_SYSTIM_OVERFLOW_PERIOD); } /* Initialize the time sync interrupts for devices that support it. */ if (hw->mac.type >= e1000_82580) { E1000_WRITE_REG(hw, E1000_TSIM, TSYNC_INTERRUPTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); } adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF; adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, &adapter->pdev->dev); if (IS_ERR(adapter->ptp_clock)) { adapter->ptp_clock = NULL; dev_err(&adapter->pdev->dev, "ptp_clock_register failed\n"); } else { dev_info(&adapter->pdev->dev, "added PHC on %s\n", adapter->netdev->name); adapter->flags |= IGB_FLAG_PTP; } }