/** * i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp * @pf: Board private structure * * Read the value of the Tx timestamp from the registers, convert it into a * value consumable by the stack, and store that result into the shhwtstamps * struct before returning it up the stack. **/ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf) { struct skb_shared_hwtstamps shhwtstamps; struct sk_buff *skb = pf->ptp_tx_skb; struct i40e_hw *hw = &pf->hw; u32 hi, lo; u64 ns; if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_tx) return; /* don't attempt to timestamp if we don't have an skb */ if (!pf->ptp_tx_skb) return; lo = rd32(hw, I40E_PRTTSYN_TXTIME_L); hi = rd32(hw, I40E_PRTTSYN_TXTIME_H); ns = (((u64)hi) << 32) | lo; i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns); /* Clear the bit lock as soon as possible after reading the register, * and prior to notifying the stack via skb_tstamp_tx(). Otherwise * applications might wake up and attempt to request another transmit * timestamp prior to the bit lock being cleared. */ pf->ptp_tx_skb = NULL; clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state); /* Notify the stack and free the skb after we've unlocked */ skb_tstamp_tx(skb, &shhwtstamps); dev_kfree_skb_any(skb); }
/** * i40e_ptp_rx_hwtstamp - Utility function which checks for an Rx timestamp * @pf: Board private structure * @skb: Particular skb to send timestamp with * @index: Index into the receive timestamp registers for the timestamp * * The XL710 receives a notification in the receive descriptor with an offset * into the set of RXTIME registers where the timestamp is for that skb. This * function goes and fetches the receive timestamp from that offset, if a valid * one exists. The RXTIME registers are in ns, so we must convert the result * first. **/ void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index) { u32 prttsyn_stat, hi, lo; struct i40e_hw *hw; u64 ns; /* Since we cannot turn off the Rx timestamp logic if the device is * doing Tx timestamping, check if Rx timestamping is configured. */ if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_rx) return; hw = &pf->hw; prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1); if (!(prttsyn_stat & BIT(index))) return; lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index)); hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index)); ns = (((u64)hi) << 32) | lo; i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns); }
/** * i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp * @pf: Board private structure * * Read the value of the Tx timestamp from the registers, convert it into a * value consumable by the stack, and store that result into the shhwtstamps * struct before returning it up the stack. **/ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf) { struct skb_shared_hwtstamps shhwtstamps; struct i40e_hw *hw = &pf->hw; u32 hi, lo; u64 ns; if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_tx) return; /* don't attempt to timestamp if we don't have an skb */ if (!pf->ptp_tx_skb) return; lo = rd32(hw, I40E_PRTTSYN_TXTIME_L); hi = rd32(hw, I40E_PRTTSYN_TXTIME_H); ns = (((u64)hi) << 32) | lo; i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns); skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps); dev_kfree_skb_any(pf->ptp_tx_skb); pf->ptp_tx_skb = NULL; clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state); }
/** * i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp * @pf: Board private structure * * Read the value of the Tx timestamp from the registers, convert it into a * value consumable by the stack, and store that result into the shhwtstamps * struct before returning it up the stack. **/ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf) { struct skb_shared_hwtstamps shhwtstamps; struct i40e_hw *hw = &pf->hw; u32 hi, lo; u64 ns; lo = rd32(hw, I40E_PRTTSYN_TXTIME_L); hi = rd32(hw, I40E_PRTTSYN_TXTIME_H); ns = (((u64)hi) << 32) | lo; i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns); skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps); dev_kfree_skb_any(pf->ptp_tx_skb); pf->ptp_tx_skb = NULL; clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state); }
/** * i40e_ptp_rx_hwtstamp - Utility function which checks for an Rx timestamp * @pf: Board private structure * @skb: Particular skb to send timestamp with * @index: Index into the receive timestamp registers for the timestamp * * The XL710 receives a notification in the receive descriptor with an offset * into the set of RXTIME registers where the timestamp is for that skb. This * function goes and fetches the receive timestamp from that offset, if a valid * one exists. The RXTIME registers are in ns, so we must convert the result * first. **/ void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index) { u32 prttsyn_stat, hi, lo; struct i40e_hw *hw; u64 ns; /* Since we cannot turn off the Rx timestamp logic if the device is * doing Tx timestamping, check if Rx timestamping is configured. */ if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_rx) return; hw = &pf->hw; spin_lock_bh(&pf->ptp_rx_lock); /* Get current Rx events and update latch times */ prttsyn_stat = i40e_ptp_get_rx_events(pf); /* TODO: Should we warn about missing Rx timestamp event? */ if (!(prttsyn_stat & BIT(index))) { spin_unlock_bh(&pf->ptp_rx_lock); return; } /* Clear the latched event since we're about to read its register */ pf->latch_event_flags &= ~BIT(index); lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index)); hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index)); spin_unlock_bh(&pf->ptp_rx_lock); ns = (((u64)hi) << 32) | lo; i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns); }