mirror of
git://nv-tegra.nvidia.com/kernel/nvethernetrm.git
synced 2025-12-22 09:12:10 +03:00
osi: common: Add support for MGBE 2 step timestamp
- OSI DMA
-- During Trasnmit:
--- For EQOS/MGBE one steps PTP Reads TS and update
in TX done structure.
--- For MGBE 2 steps PTP or 1 step slave, update flags
TS_POLL and update pkt_id as unique ID to be used
for polling by OSD after Common interrupt handling.
packet_id = MSB 4 bits channel_number and LSB 6-bits,
local index of PTP TS FIFO.
-- On transmit complete
--- If TS is part of Tx done context set OSI_TXDONE_CX_TS
--- If TS is not part of Tx done context and delayed set
OSI_TXDONE_CX_TS_DELAY.
- OSI Core
-- On Common interrupt:
--- If MGBE_ISR_TSIS is set, read time stamp to internal
array from HW fifo, until it is completely read or array
is full.
--- Provide an IOCTL OSI_CMD_GET_TX_TS, to read TS for the
specified pkt_id from OSD via structure osi_core_tx_ts
--- Provide an IOCTL OSI_CMD_FREE_TS, to free TS for the
specified pkt_id from OSD path
Bug 200603265
Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
Signed-off-by: Rakesh Goyal <rgoyal@nvidia.com>
Change-Id: Ib3e02031393e40988074095e5a135bb4e839d7f4
Reviewed-on: https://git-master.nvidia.com/r/c/kernel/nvethernetrm/+/2543792
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: Krishna Thota <kthota@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
mobile promotions
parent
7b040ebf9d
commit
1a2c9a3d94
@@ -80,6 +80,7 @@ typedef my_lint_64 nvel64_t;
|
||||
#define OSI_MAC_TCR_CSC OSI_BIT(19)
|
||||
#define OSI_MAC_TCR_AV8021ASMEN OSI_BIT(28)
|
||||
#define OSI_MAC_TCR_SNAPTYPSEL_3 (OSI_BIT(16) | OSI_BIT(17))
|
||||
#define OSI_MAC_TCR_TXTSSMIS OSI_BIT(31)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@@ -205,6 +206,8 @@ typedef my_lint_64 nvel64_t;
|
||||
#define OSI_CMD_CONFIG_FPE 39U
|
||||
#define OSI_CMD_READ_REG 40U
|
||||
#define OSI_CMD_WRITE_REG 41U
|
||||
#define OSI_CMD_GET_TX_TS 42U
|
||||
#define OSI_CMD_FREE_TS 43U
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@@ -1025,6 +1028,24 @@ struct osi_macsec_irq_stats {
|
||||
};
|
||||
#endif /* MACSEC_SUPPORT */
|
||||
|
||||
/**
|
||||
* @brief Core time stamp data strcuture
|
||||
*/
|
||||
struct osi_core_tx_ts {
|
||||
/** Pointer to next item in the link */
|
||||
struct osi_core_tx_ts *next;
|
||||
/** Pointer to prev item in the link */
|
||||
struct osi_core_tx_ts *prev;
|
||||
/** Packet ID for corresponding timestamp */
|
||||
nveu32_t pkt_id;
|
||||
/** Time in seconds */
|
||||
nveu32_t sec;
|
||||
/** Time in nano seconds */
|
||||
nveu32_t nsec;
|
||||
/** Variable which says if pkt_id is in use or not */
|
||||
nveu32_t in_use;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief OSI Core data structure for runtime commands.
|
||||
*/
|
||||
@@ -1071,6 +1092,8 @@ struct osi_ioctl {
|
||||
struct osi_fpe_config fpe;
|
||||
/** PTP configuration settings */
|
||||
struct osi_ptp_config ptp_config;
|
||||
/** TX Timestamp structure */
|
||||
struct osi_core_tx_ts tx_ts;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2181,6 +2204,14 @@ nve32_t osi_get_hw_features(struct osi_core_priv_data *const osi_core,
|
||||
* Configuration FPE register and preemptable queue
|
||||
* fpe - FPE configuration structure
|
||||
*
|
||||
* - OSI_CMD_GET_TX_TS
|
||||
* Command to get TX timestamp for PTP packet
|
||||
* ts - OSI core timestamp structure
|
||||
*
|
||||
* - OSI_CMD_FREE_TS
|
||||
* Command to free old timestamp for PTP packet
|
||||
* chan - DMA channel number +1. 0 will be used for onestep
|
||||
*
|
||||
* @param[in] osi_core: OSI core private data structure.
|
||||
* @param[in] data: void pointer pointing to osi_ioctl
|
||||
*
|
||||
@@ -2365,6 +2396,14 @@ struct osi_core_priv_data *osi_get_core(void);
|
||||
* Configuration FPE register and preemptable queue
|
||||
* fpe - FPE configuration structure
|
||||
*
|
||||
* - OSI_CMD_GET_TX_TS
|
||||
* Command to get TX timestamp for PTP packet
|
||||
* ts - OSI core timestamp structure
|
||||
*
|
||||
* - OSI_CMD_FREE_TS
|
||||
* Command to free old timestamp for PTP packet
|
||||
* chan - DMA channel number +1. 0 will be used for onestep
|
||||
*
|
||||
* @param[in] osi_core: OSI core private data structure.
|
||||
* @param[in] data: void pointer pointing to osi_ioctl
|
||||
*
|
||||
|
||||
@@ -157,6 +157,8 @@
|
||||
#define OSI_TXDONE_CX_ERROR OSI_BIT(1)
|
||||
/** Flag to indicate the availability of time stamp */
|
||||
#define OSI_TXDONE_CX_TS OSI_BIT(2)
|
||||
/** Flag to indicate the delayed availability of time stamp */
|
||||
#define OSI_TXDONE_CX_TS_DELAYED OSI_BIT(3)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@@ -363,6 +365,8 @@ struct osi_tx_swcx {
|
||||
* is a paged buffer/linear buffer
|
||||
* Bit 1 PTP hwtime form timestamp registers */
|
||||
unsigned int flags;
|
||||
/** Packet id of packet for which TX timestamp needed */
|
||||
unsigned int pktid;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -410,6 +414,8 @@ struct osi_txdone_pkt_cx {
|
||||
/** TS captured for the tx packet and this is valid only when the PTP
|
||||
* bit is set in fields */
|
||||
nveul64_t ns;
|
||||
/** Passing packet id to map TX time to packet */
|
||||
unsigned int pktid;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,17 @@
|
||||
|
||||
#include <osi_common.h>
|
||||
|
||||
/**
|
||||
* @brief TX timestamp helper MACROS
|
||||
* @{
|
||||
*/
|
||||
#define CHAN_START_POSITION 6U
|
||||
#define PKT_ID_CNT ((nveu32_t)1 << CHAN_START_POSITION)
|
||||
/* First 6 bytes of idx and last 4 bytes of chan(+1 to avoid pkt_id to be 0) */
|
||||
#define GET_TX_TS_PKTID(idx, c) (((++(idx)) & (PKT_ID_CNT - 1U)) | \
|
||||
(((c) + 1U) << CHAN_START_POSITION))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
*@brief div_u64_rem - updates remainder and returns Quotient
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define INCLUDED_CORE_LOCAL_H
|
||||
|
||||
#include <osi_core.h>
|
||||
#include <local_common.h>
|
||||
|
||||
/**
|
||||
* @brief Maximum number of OSI core instances.
|
||||
@@ -37,6 +38,11 @@
|
||||
*/
|
||||
#define MAX_INTERFACE_OPS 2U
|
||||
|
||||
/**
|
||||
* @brief Maximum number of timestamps stored in OSI from HW FIFO.
|
||||
*/
|
||||
#define MAX_TX_TS_CNT (PKT_ID_CNT * OSI_MGBE_MAX_NUM_CHANS)
|
||||
|
||||
/**
|
||||
* interface core ops
|
||||
*/
|
||||
@@ -273,12 +279,16 @@ struct core_local {
|
||||
struct core_ops *ops_p;
|
||||
/** interface core local operations variable */
|
||||
struct if_core_ops *if_ops_p;
|
||||
/** structure to store tx time stamps */
|
||||
struct osi_core_tx_ts ts[MAX_TX_TS_CNT];
|
||||
/** Flag to represent initialization done or not */
|
||||
nveu32_t init_done;
|
||||
/** Flag to represent infterface initialization done or not */
|
||||
nveu32_t if_init_done;
|
||||
/** Magic number to validate osi core pointer */
|
||||
nveu64_t magic_num;
|
||||
/** This is the head node for PTP packet ID queue */
|
||||
struct osi_core_tx_ts tx_ts_head;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -2642,9 +2642,9 @@ static int mgbe_configure_mac(struct osi_core_priv_data *osi_core)
|
||||
/* Enable MAC nve32_terrupts */
|
||||
/* Read MAC IMR Register */
|
||||
value = osi_readla(osi_core, (nveu8_t *)osi_core->base + MGBE_MAC_IER);
|
||||
/* RGSMIIIM - RGMII/SMII nve32_terrupt Enable */
|
||||
/* RGSMIIIM - RGMII/SMII interrupt and TSIE Enable */
|
||||
/* TODO: LPI need to be enabled during EEE implementation */
|
||||
value |= MGBE_IMR_RGSMIIIE;
|
||||
value |= (MGBE_IMR_RGSMIIIE | MGBE_IMR_TSIE);
|
||||
osi_writela(osi_core, value, (nveu8_t *)osi_core->base + MGBE_MAC_IER);
|
||||
|
||||
/* Enable common interrupt at wrapper level */
|
||||
@@ -3193,6 +3193,28 @@ static void mgbe_handle_mac_fpe_intrs(struct osi_core_priv_data *osi_core)
|
||||
osi_core->base + MGBE_MAC_FPE_CTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get free timestamp index from TS array by validating in_use param
|
||||
*
|
||||
* @param[in] l_core: Core local private data structure.
|
||||
*
|
||||
* @retval Free timestamp index.
|
||||
*
|
||||
* @post If timestamp index is MAX_TX_TS_CNT, then its no free count index
|
||||
* is available.
|
||||
*/
|
||||
static inline nveu32_t get_free_ts_idx(struct core_local *l_core)
|
||||
{
|
||||
nveu32_t i;
|
||||
|
||||
for (i = 0; i < MAX_TX_TS_CNT; i++) {
|
||||
if (l_core->ts[i].in_use == OSI_NONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_handle_mac_intrs - Handle MAC interrupts
|
||||
*
|
||||
@@ -3207,8 +3229,9 @@ static void mgbe_handle_mac_fpe_intrs(struct osi_core_priv_data *osi_core)
|
||||
static void mgbe_handle_mac_intrs(struct osi_core_priv_data *osi_core,
|
||||
nveu32_t dma_isr)
|
||||
{
|
||||
unsigned int mac_isr = 0;
|
||||
unsigned int mac_ier = 0;
|
||||
struct core_local *l_core = (struct core_local *)osi_core;
|
||||
nveu32_t mac_isr = 0;
|
||||
nveu32_t mac_ier = 0;
|
||||
|
||||
mac_isr = osi_readla(osi_core,
|
||||
(unsigned char *)osi_core->base + MGBE_MAC_ISR);
|
||||
@@ -3225,6 +3248,43 @@ static void mgbe_handle_mac_intrs(struct osi_core_priv_data *osi_core,
|
||||
mac_isr &= ~MGBE_MAC_IMR_FPEIS;
|
||||
}
|
||||
|
||||
osi_writela(osi_core, mac_isr,
|
||||
(unsigned char *)osi_core->base + MGBE_MAC_ISR);
|
||||
if ((mac_isr & MGBE_ISR_TSIS) == MGBE_ISR_TSIS) {
|
||||
struct osi_core_tx_ts *head = &l_core->tx_ts_head;
|
||||
|
||||
/* TXTSC bit should get reset when all timestamp read */
|
||||
while (((osi_readla(osi_core, (nveu8_t *)osi_core->base +
|
||||
MGBE_MAC_TSS) &
|
||||
MGBE_MAC_TSS_TXTSC) == MGBE_MAC_TSS_TXTSC)) {
|
||||
nveu32_t i = get_free_ts_idx(l_core);
|
||||
|
||||
if (i == MAX_TX_TS_CNT) {
|
||||
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
||||
"TS queue is full\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
l_core->ts[i].nsec = osi_readla(osi_core,
|
||||
(nveu8_t *)osi_core->base +
|
||||
MGBE_MAC_TSNSSEC);
|
||||
|
||||
l_core->ts[i].in_use = OSI_ENABLE;
|
||||
l_core->ts[i].pkt_id = osi_readla(osi_core,
|
||||
(nveu8_t *)osi_core->base +
|
||||
MGBE_MAC_TSPKID);
|
||||
l_core->ts[i].sec = osi_readla(osi_core,
|
||||
(nveu8_t *)osi_core->base +
|
||||
MGBE_MAC_TSSEC);
|
||||
/* Add time stamp to end of list */
|
||||
l_core->ts[i].next = head->prev->next;
|
||||
head->prev->next = &l_core->ts[i];
|
||||
l_core->ts[i].prev = head->prev;
|
||||
head->prev = &l_core->ts[i];
|
||||
}
|
||||
}
|
||||
mac_isr &= ~MGBE_ISR_TSIS;
|
||||
|
||||
osi_writela(osi_core, mac_isr,
|
||||
(unsigned char *)osi_core->base + MGBE_MAC_ISR);
|
||||
/* TODO: Duplex/speed settigs - Its not same as EQOS for MGBE */
|
||||
|
||||
@@ -106,6 +106,10 @@
|
||||
#define MGBE_MAC_STSUR 0x0D10
|
||||
#define MGBE_MAC_STNSUR 0x0D14
|
||||
#define MGBE_MAC_TAR 0x0D18
|
||||
#define MGBE_MAC_TSS 0x0D20
|
||||
#define MGBE_MAC_TSNSSEC 0x0D30
|
||||
#define MGBE_MAC_TSSEC 0x0D34
|
||||
#define MGBE_MAC_TSPKID 0x0D38
|
||||
#define MGBE_MAC_PTO_CR 0x0DC0
|
||||
#define MGBE_MAC_PIDR0 0x0DC4
|
||||
#define MGBE_MAC_PIDR1 0x0DC8
|
||||
@@ -450,8 +454,10 @@
|
||||
OSI_BIT(25) | OSI_BIT(24))
|
||||
#define MGBE_MAC_RQC4R_PMCBCQ_SHIFT 24U
|
||||
#define MGBE_IMR_RGSMIIIE OSI_BIT(0)
|
||||
#define MGBE_IMR_TSIE OSI_BIT(12)
|
||||
#define MGBE_IMR_FPEIE OSI_BIT(15)
|
||||
#define MGBE_MAC_IMR_FPEIS OSI_BIT(16)
|
||||
#define MGBE_ISR_TSIS OSI_BIT(12)
|
||||
#define MGBE_DMA_ISR_MTLIS OSI_BIT(16)
|
||||
#define MGBE_DMA_ISR_MACIS OSI_BIT(17)
|
||||
#define MGBE_DMA_ISR_DCH0_DCH15_MASK 0xFFU
|
||||
@@ -662,6 +668,8 @@
|
||||
#define MGBE_MAC_SBD_INTR OSI_BIT(2)
|
||||
#define MGBE_MAC_EXT_CNF_DDS OSI_BIT(7)
|
||||
#define MGBE_MAC_EXT_CNF_EIPG 0x1U
|
||||
/* TX timestamp */
|
||||
#define MGBE_MAC_TSS_TXTSC OSI_BIT(15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@@ -122,6 +122,9 @@ struct osi_core_priv_data *osi_get_core(void)
|
||||
|
||||
g_core[i].magic_num = (nveu64_t)&g_core[i].osi_core;
|
||||
|
||||
g_core[i].tx_ts_head.prev = &g_core[i].tx_ts_head;
|
||||
g_core[i].tx_ts_head.next = &g_core[i].tx_ts_head;
|
||||
|
||||
return &g_core[i].osi_core;
|
||||
}
|
||||
|
||||
|
||||
84
osi/core/osi_hal.c
Executable file → Normal file
84
osi/core/osi_hal.c
Executable file → Normal file
@@ -1362,6 +1362,80 @@ static nve32_t config_fpe(struct osi_core_priv_data *osi_core,
|
||||
return l_core->ops_p->hw_config_fpe(osi_core, fpe);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free stale timestamps for channel
|
||||
*
|
||||
* Algorithm:
|
||||
* - Check for if any timestamp for input channel id
|
||||
* - if yes, reset node to 0x0 for reuse.
|
||||
*
|
||||
* @param[in] osi_core: OSI core private data structure.
|
||||
* @param[in] chan: 1 for DMA channel 0, 2 for dma channel 1,...
|
||||
* 0 is used for onestep.
|
||||
*/
|
||||
static inline void free_tx_ts(struct osi_core_priv_data *osi_core,
|
||||
nveu32_t chan)
|
||||
{
|
||||
struct core_local *l_core = (struct core_local *)osi_core;
|
||||
struct osi_core_tx_ts *head = &l_core->tx_ts_head;
|
||||
struct osi_core_tx_ts *temp = l_core->tx_ts_head.next;
|
||||
nveu32_t count = 0U;
|
||||
|
||||
while ((temp != head) && (count < MAX_TX_TS_CNT)) {
|
||||
if (((temp->pkt_id >> CHAN_START_POSITION) & chan) == chan) {
|
||||
temp->next->prev = temp->prev;
|
||||
temp->prev->next = temp->next;
|
||||
/* reset in_use for temp node from the link */
|
||||
temp->in_use = OSI_DISABLE;
|
||||
}
|
||||
count++;
|
||||
temp = temp->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parses internal ts structure array and update time stamp if packet
|
||||
* id matches.
|
||||
* Algorithm:
|
||||
* - Check for if any timestamp with packet ID in list and valid
|
||||
* - update sec and nsec in timestamp structure
|
||||
* - reset node to reuse for next call
|
||||
*
|
||||
* @param[in] osi_core: OSI core private data structure.
|
||||
* @param[in,out] ts: osi core ts structure, pkt_id is input and time is output.
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 any other failure.
|
||||
*/
|
||||
static inline nve32_t get_tx_ts(struct osi_core_priv_data *osi_core,
|
||||
struct osi_core_tx_ts *ts)
|
||||
{
|
||||
struct core_local *l_core = (struct core_local *)osi_core;
|
||||
struct osi_core_tx_ts *temp = l_core->tx_ts_head.next;
|
||||
struct osi_core_tx_ts *head = &l_core->tx_ts_head;
|
||||
nve32_t ret = -1;
|
||||
nveu32_t count = 0U;
|
||||
|
||||
while ((temp != head) && (count < MAX_TX_TS_CNT)) {
|
||||
if ((temp->pkt_id == ts->pkt_id) &&
|
||||
(temp->in_use != OSI_NONE)) {
|
||||
ts->sec = temp->sec;
|
||||
ts->nsec = temp->nsec;
|
||||
/* remove temp node from the link */
|
||||
temp->next->prev = temp->prev;
|
||||
temp->prev->next = temp->next;
|
||||
/* Clear in_use fields */
|
||||
temp->in_use = OSI_DISABLE;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
nve32_t osi_hal_handle_ioctl(struct osi_core_priv_data *osi_core,
|
||||
struct osi_ioctl *data)
|
||||
{
|
||||
@@ -1561,6 +1635,16 @@ nve32_t osi_hal_handle_ioctl(struct osi_core_priv_data *osi_core,
|
||||
ret = ops_p->write_reg(osi_core, (nve32_t) data->arg1_u32,
|
||||
(nve32_t) data->arg2_u32);
|
||||
break;
|
||||
|
||||
case OSI_CMD_GET_TX_TS:
|
||||
ret = get_tx_ts(osi_core, &data->tx_ts);
|
||||
break;
|
||||
|
||||
case OSI_CMD_FREE_TS:
|
||||
free_tx_ts(osi_core, data->arg1_u32);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
OSI_CORE_ERR(OSI_NULL, OSI_LOG_ARG_INVALID,
|
||||
"CORE: Incorrect command\n",
|
||||
|
||||
@@ -123,6 +123,12 @@ struct dma_local {
|
||||
struct osi_dma_priv_data osi_dma;
|
||||
/** DMA channel operations */
|
||||
struct dma_chan_ops *ops_p;
|
||||
/**
|
||||
* PacketID for PTP TS.
|
||||
* MSB 4-bits of channel number and LSB 6-bits of local
|
||||
* index(PKT_ID_CNT).
|
||||
*/
|
||||
nveu32_t pkt_id;
|
||||
/** Flag to represent OSI DMA software init done */
|
||||
nveu32_t init_done;
|
||||
/** Holds the MAC version of MAC controller */
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "hw_desc.h"
|
||||
#include "../osi/common/common.h"
|
||||
#include "mgbe_dma.h"
|
||||
#include "local_common.h"
|
||||
|
||||
static struct desc_ops d_ops[MAX_MAC_IP_TYPES];
|
||||
|
||||
@@ -507,102 +508,6 @@ static inline nve32_t validate_tx_completions_arg(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll_for_ts_update - Poll for TXTSC bit set for timestamp capture
|
||||
*
|
||||
* Algorithm: This routine will be invoked by get_mac_tx_timestamp to poll
|
||||
* on TXTSC bit to get set or timedout.
|
||||
*
|
||||
* @param[in] addr: Base address
|
||||
* @param[in] chan: Current counter value
|
||||
*
|
||||
* @retval -1 on failure
|
||||
* @retval 0 on success
|
||||
*/
|
||||
static inline int poll_for_ts_update(struct osi_dma_priv_data *osi_dma,
|
||||
unsigned int *count)
|
||||
{
|
||||
unsigned int retry = OSI_POLL_COUNT;
|
||||
unsigned int val = 0U;
|
||||
|
||||
while (*count < retry) {
|
||||
/* Read and Check TXTSC in MAC_Timestamp_Control register */
|
||||
val = osi_readl((unsigned char *)osi_dma->base +
|
||||
MGBE_MAC_TSS);
|
||||
if ((val & MGBE_MAC_TSS_TXTSC) == MGBE_MAC_TSS_TXTSC) {
|
||||
return 0;
|
||||
}
|
||||
(*count)++;
|
||||
osi_dma->osd_ops.udelay(OSI_DELAY_1US);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get_mac_tx_timestamp - get TX timestamp from timestamp capture
|
||||
* registers
|
||||
*
|
||||
* Algorithm: This routine will be invoked on TX_DONE interrupt and if hw
|
||||
* timestamp capture enabled for that descriptor. SW will check for Packet
|
||||
* id maching with dma channel number as for same DMA all tx are FIFO. If match
|
||||
* update hwtimestamp into local variables.
|
||||
*
|
||||
* @param[in] osi: OSI private data structure.
|
||||
* @param[in] tx_desc: Pointer to tranmit descriptor.
|
||||
* @param[out] txdone_pkt_cx: Pointer to txdone packet descriptor to be filled
|
||||
* @param[in] chan: Rx channel number.
|
||||
*
|
||||
*/
|
||||
static void get_mac_tx_timestamp(struct osi_dma_priv_data *osi_dma,
|
||||
struct osi_tx_desc *tx_desc,
|
||||
struct osi_txdone_pkt_cx *txdone_pkt_cx,
|
||||
unsigned int chan)
|
||||
{
|
||||
unsigned char *addr = (unsigned char *)osi_dma->base;
|
||||
int ret = -1;
|
||||
int found = 1;
|
||||
unsigned int count = 0;
|
||||
unsigned long long var = 0;
|
||||
|
||||
ret = poll_for_ts_update(osi_dma, &count);
|
||||
if (ret < 0) {
|
||||
OSI_DMA_ERR(OSI_NULL, OSI_LOG_ARG_HW_FAIL,
|
||||
"timestamp done failed\n", 0ULL);
|
||||
found = 0;
|
||||
}
|
||||
|
||||
/* check if pkt id is also correct for pkt. current implemtation
|
||||
* use dma channel index as pktid, we will use pktid from index 0 to
|
||||
* max DMA channels -1 */
|
||||
while (found == 1) {
|
||||
if (((osi_readl(addr + MGBE_MAC_TS_PID) &
|
||||
MGBE_MAC_TS_PID_MASK) == chan)) {
|
||||
txdone_pkt_cx->flags |= OSI_TXDONE_CX_TS;
|
||||
txdone_pkt_cx->ns = osi_readl(addr + MGBE_MAC_TS_NSEC);
|
||||
txdone_pkt_cx->ns &= MGBE_MAC_TS_NSEC_MASK;
|
||||
var = osi_readl(addr + MGBE_MAC_TS_SEC);
|
||||
if (OSI_NSEC_PER_SEC > (OSI_ULLONG_MAX / var)) {
|
||||
/* Will not hit this case */
|
||||
} else if ((OSI_ULLONG_MAX - (var * OSI_NSEC_PER_SEC)) <
|
||||
txdone_pkt_cx->ns) {
|
||||
/* Will not hit this case */
|
||||
} else {
|
||||
txdone_pkt_cx->ns += var * OSI_NSEC_PER_SEC;
|
||||
}
|
||||
|
||||
found = 0;
|
||||
} else {
|
||||
OSI_DMA_INFO(OSI_NULL, OSI_LOG_ARG_HW_FAIL,
|
||||
"packet ID mismatch \n", 0ULL);
|
||||
ret = poll_for_ts_update(osi_dma, &count);
|
||||
if (ret < 0) {
|
||||
found = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief is_ptp_twostep_or_slave_mode - check for dut in ptp 2step or slave
|
||||
* mode
|
||||
@@ -697,10 +602,12 @@ int osi_process_tx_completions(struct osi_dma_priv_data *osi_dma,
|
||||
} else if (((tx_swcx->flags & OSI_PKT_CX_PTP) ==
|
||||
OSI_PKT_CX_PTP) &&
|
||||
// if not master in onestep mode
|
||||
/* TODO: Is this check needed and can be removed ? */
|
||||
(is_ptp_twostep_or_slave_mode(osi_dma->ptp_flag) ==
|
||||
OSI_ENABLE) &&
|
||||
((tx_desc->tdes3 & TDES3_CTXT) == 0U)) {
|
||||
get_mac_tx_timestamp(osi_dma, tx_desc, txdone_pkt_cx, chan);
|
||||
txdone_pkt_cx->pktid = tx_swcx->pktid;
|
||||
txdone_pkt_cx->flags |= OSI_TXDONE_CX_TS_DELAYED;
|
||||
} else {
|
||||
/* Do nothing here */
|
||||
}
|
||||
@@ -993,6 +900,7 @@ nve32_t hw_transmit(struct osi_dma_priv_data *osi_dma,
|
||||
struct dma_chan_ops *ops,
|
||||
nveu32_t chan)
|
||||
{
|
||||
struct dma_local *l_dma = (struct dma_local *)osi_dma;
|
||||
struct osi_tx_pkt_cx *tx_pkt_cx = OSI_NULL;
|
||||
struct osi_tx_desc *first_desc = OSI_NULL;
|
||||
struct osi_tx_desc *last_desc = OSI_NULL;
|
||||
@@ -1000,6 +908,7 @@ nve32_t hw_transmit(struct osi_dma_priv_data *osi_dma,
|
||||
struct osi_tx_swcx *tx_swcx = OSI_NULL;
|
||||
struct osi_tx_desc *cx_desc = OSI_NULL;
|
||||
nve32_t cntx_desc_consumed;
|
||||
nveu32_t pkt_id = 0x0U;
|
||||
nveu32_t desc_cnt = 0U;
|
||||
nveu64_t tailptr, tmp;
|
||||
nveu32_t entry = 0U;
|
||||
@@ -1043,8 +952,15 @@ nve32_t hw_transmit(struct osi_dma_priv_data *osi_dma,
|
||||
(osi_dma->mac == OSI_MAC_HW_MGBE)) {
|
||||
/* mark packet id valid */
|
||||
tx_desc->tdes3 |= TDES3_PIDV;
|
||||
/* Packet id */
|
||||
tx_desc->tdes0 = chan;
|
||||
if ((osi_dma->ptp_flag & OSI_PTP_SYNC_ONESTEP) ==
|
||||
OSI_PTP_SYNC_ONESTEP) {
|
||||
/* packet ID for Onestep is 0x0 always */
|
||||
pkt_id = OSI_NONE;
|
||||
} else {
|
||||
pkt_id = GET_TX_TS_PKTID(l_dma->pkt_id, chan);
|
||||
}
|
||||
/* update packet id */
|
||||
tx_desc->tdes0 = pkt_id;
|
||||
}
|
||||
INCR_TX_DESC_INDEX(entry, 1U);
|
||||
|
||||
@@ -1058,6 +974,13 @@ nve32_t hw_transmit(struct osi_dma_priv_data *osi_dma,
|
||||
|
||||
/* Fill first descriptor */
|
||||
fill_first_desc(tx_ring, tx_pkt_cx, tx_desc, tx_swcx, osi_dma->ptp_flag);
|
||||
if (((tx_pkt_cx->flags & OSI_PKT_CX_PTP) == OSI_PKT_CX_PTP) &&
|
||||
(osi_dma->mac == OSI_MAC_HW_MGBE)) {
|
||||
/* save packet id for first desc, time stamp will be with
|
||||
* first FD only
|
||||
*/
|
||||
tx_swcx->pktid = pkt_id;
|
||||
}
|
||||
|
||||
INCR_TX_DESC_INDEX(entry, 1U);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user