mirror of
git://nv-tegra.nvidia.com/kernel/nvethernetrm.git
synced 2025-12-23 18:15:29 +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_CSC OSI_BIT(19)
|
||||||
#define OSI_MAC_TCR_AV8021ASMEN OSI_BIT(28)
|
#define OSI_MAC_TCR_AV8021ASMEN OSI_BIT(28)
|
||||||
#define OSI_MAC_TCR_SNAPTYPSEL_3 (OSI_BIT(16) | OSI_BIT(17))
|
#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_CONFIG_FPE 39U
|
||||||
#define OSI_CMD_READ_REG 40U
|
#define OSI_CMD_READ_REG 40U
|
||||||
#define OSI_CMD_WRITE_REG 41U
|
#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 */
|
#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.
|
* @brief OSI Core data structure for runtime commands.
|
||||||
*/
|
*/
|
||||||
@@ -1071,6 +1092,8 @@ struct osi_ioctl {
|
|||||||
struct osi_fpe_config fpe;
|
struct osi_fpe_config fpe;
|
||||||
/** PTP configuration settings */
|
/** PTP configuration settings */
|
||||||
struct osi_ptp_config ptp_config;
|
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
|
* Configuration FPE register and preemptable queue
|
||||||
* fpe - FPE configuration structure
|
* 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] osi_core: OSI core private data structure.
|
||||||
* @param[in] data: void pointer pointing to osi_ioctl
|
* @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
|
* Configuration FPE register and preemptable queue
|
||||||
* fpe - FPE configuration structure
|
* 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] osi_core: OSI core private data structure.
|
||||||
* @param[in] data: void pointer pointing to osi_ioctl
|
* @param[in] data: void pointer pointing to osi_ioctl
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -157,6 +157,8 @@
|
|||||||
#define OSI_TXDONE_CX_ERROR OSI_BIT(1)
|
#define OSI_TXDONE_CX_ERROR OSI_BIT(1)
|
||||||
/** Flag to indicate the availability of time stamp */
|
/** Flag to indicate the availability of time stamp */
|
||||||
#define OSI_TXDONE_CX_TS OSI_BIT(2)
|
#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
|
* is a paged buffer/linear buffer
|
||||||
* Bit 1 PTP hwtime form timestamp registers */
|
* Bit 1 PTP hwtime form timestamp registers */
|
||||||
unsigned int flags;
|
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
|
/** TS captured for the tx packet and this is valid only when the PTP
|
||||||
* bit is set in fields */
|
* bit is set in fields */
|
||||||
nveul64_t ns;
|
nveul64_t ns;
|
||||||
|
/** Passing packet id to map TX time to packet */
|
||||||
|
unsigned int pktid;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -25,6 +25,17 @@
|
|||||||
|
|
||||||
#include <osi_common.h>
|
#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
|
*@brief div_u64_rem - updates remainder and returns Quotient
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#define INCLUDED_CORE_LOCAL_H
|
#define INCLUDED_CORE_LOCAL_H
|
||||||
|
|
||||||
#include <osi_core.h>
|
#include <osi_core.h>
|
||||||
|
#include <local_common.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maximum number of OSI core instances.
|
* @brief Maximum number of OSI core instances.
|
||||||
@@ -37,6 +38,11 @@
|
|||||||
*/
|
*/
|
||||||
#define MAX_INTERFACE_OPS 2U
|
#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
|
* interface core ops
|
||||||
*/
|
*/
|
||||||
@@ -273,12 +279,16 @@ struct core_local {
|
|||||||
struct core_ops *ops_p;
|
struct core_ops *ops_p;
|
||||||
/** interface core local operations variable */
|
/** interface core local operations variable */
|
||||||
struct if_core_ops *if_ops_p;
|
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 */
|
/** Flag to represent initialization done or not */
|
||||||
nveu32_t init_done;
|
nveu32_t init_done;
|
||||||
/** Flag to represent infterface initialization done or not */
|
/** Flag to represent infterface initialization done or not */
|
||||||
nveu32_t if_init_done;
|
nveu32_t if_init_done;
|
||||||
/** Magic number to validate osi core pointer */
|
/** Magic number to validate osi core pointer */
|
||||||
nveu64_t magic_num;
|
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 */
|
/* Enable MAC nve32_terrupts */
|
||||||
/* Read MAC IMR Register */
|
/* Read MAC IMR Register */
|
||||||
value = osi_readla(osi_core, (nveu8_t *)osi_core->base + MGBE_MAC_IER);
|
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 */
|
/* 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);
|
osi_writela(osi_core, value, (nveu8_t *)osi_core->base + MGBE_MAC_IER);
|
||||||
|
|
||||||
/* Enable common interrupt at wrapper level */
|
/* 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);
|
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
|
* @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,
|
static void mgbe_handle_mac_intrs(struct osi_core_priv_data *osi_core,
|
||||||
nveu32_t dma_isr)
|
nveu32_t dma_isr)
|
||||||
{
|
{
|
||||||
unsigned int mac_isr = 0;
|
struct core_local *l_core = (struct core_local *)osi_core;
|
||||||
unsigned int mac_ier = 0;
|
nveu32_t mac_isr = 0;
|
||||||
|
nveu32_t mac_ier = 0;
|
||||||
|
|
||||||
mac_isr = osi_readla(osi_core,
|
mac_isr = osi_readla(osi_core,
|
||||||
(unsigned char *)osi_core->base + MGBE_MAC_ISR);
|
(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;
|
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,
|
osi_writela(osi_core, mac_isr,
|
||||||
(unsigned char *)osi_core->base + MGBE_MAC_ISR);
|
(unsigned char *)osi_core->base + MGBE_MAC_ISR);
|
||||||
/* TODO: Duplex/speed settigs - Its not same as EQOS for MGBE */
|
/* TODO: Duplex/speed settigs - Its not same as EQOS for MGBE */
|
||||||
|
|||||||
@@ -106,6 +106,10 @@
|
|||||||
#define MGBE_MAC_STSUR 0x0D10
|
#define MGBE_MAC_STSUR 0x0D10
|
||||||
#define MGBE_MAC_STNSUR 0x0D14
|
#define MGBE_MAC_STNSUR 0x0D14
|
||||||
#define MGBE_MAC_TAR 0x0D18
|
#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_PTO_CR 0x0DC0
|
||||||
#define MGBE_MAC_PIDR0 0x0DC4
|
#define MGBE_MAC_PIDR0 0x0DC4
|
||||||
#define MGBE_MAC_PIDR1 0x0DC8
|
#define MGBE_MAC_PIDR1 0x0DC8
|
||||||
@@ -450,8 +454,10 @@
|
|||||||
OSI_BIT(25) | OSI_BIT(24))
|
OSI_BIT(25) | OSI_BIT(24))
|
||||||
#define MGBE_MAC_RQC4R_PMCBCQ_SHIFT 24U
|
#define MGBE_MAC_RQC4R_PMCBCQ_SHIFT 24U
|
||||||
#define MGBE_IMR_RGSMIIIE OSI_BIT(0)
|
#define MGBE_IMR_RGSMIIIE OSI_BIT(0)
|
||||||
|
#define MGBE_IMR_TSIE OSI_BIT(12)
|
||||||
#define MGBE_IMR_FPEIE OSI_BIT(15)
|
#define MGBE_IMR_FPEIE OSI_BIT(15)
|
||||||
#define MGBE_MAC_IMR_FPEIS OSI_BIT(16)
|
#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_MTLIS OSI_BIT(16)
|
||||||
#define MGBE_DMA_ISR_MACIS OSI_BIT(17)
|
#define MGBE_DMA_ISR_MACIS OSI_BIT(17)
|
||||||
#define MGBE_DMA_ISR_DCH0_DCH15_MASK 0xFFU
|
#define MGBE_DMA_ISR_DCH0_DCH15_MASK 0xFFU
|
||||||
@@ -662,6 +668,8 @@
|
|||||||
#define MGBE_MAC_SBD_INTR OSI_BIT(2)
|
#define MGBE_MAC_SBD_INTR OSI_BIT(2)
|
||||||
#define MGBE_MAC_EXT_CNF_DDS OSI_BIT(7)
|
#define MGBE_MAC_EXT_CNF_DDS OSI_BIT(7)
|
||||||
#define MGBE_MAC_EXT_CNF_EIPG 0x1U
|
#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].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;
|
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);
|
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,
|
nve32_t osi_hal_handle_ioctl(struct osi_core_priv_data *osi_core,
|
||||||
struct osi_ioctl *data)
|
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,
|
ret = ops_p->write_reg(osi_core, (nve32_t) data->arg1_u32,
|
||||||
(nve32_t) data->arg2_u32);
|
(nve32_t) data->arg2_u32);
|
||||||
break;
|
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:
|
default:
|
||||||
OSI_CORE_ERR(OSI_NULL, OSI_LOG_ARG_INVALID,
|
OSI_CORE_ERR(OSI_NULL, OSI_LOG_ARG_INVALID,
|
||||||
"CORE: Incorrect command\n",
|
"CORE: Incorrect command\n",
|
||||||
|
|||||||
@@ -123,6 +123,12 @@ struct dma_local {
|
|||||||
struct osi_dma_priv_data osi_dma;
|
struct osi_dma_priv_data osi_dma;
|
||||||
/** DMA channel operations */
|
/** DMA channel operations */
|
||||||
struct dma_chan_ops *ops_p;
|
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 */
|
/** Flag to represent OSI DMA software init done */
|
||||||
nveu32_t init_done;
|
nveu32_t init_done;
|
||||||
/** Holds the MAC version of MAC controller */
|
/** Holds the MAC version of MAC controller */
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "hw_desc.h"
|
#include "hw_desc.h"
|
||||||
#include "../osi/common/common.h"
|
#include "../osi/common/common.h"
|
||||||
#include "mgbe_dma.h"
|
#include "mgbe_dma.h"
|
||||||
|
#include "local_common.h"
|
||||||
|
|
||||||
static struct desc_ops d_ops[MAX_MAC_IP_TYPES];
|
static struct desc_ops d_ops[MAX_MAC_IP_TYPES];
|
||||||
|
|
||||||
@@ -507,102 +508,6 @@ static inline nve32_t validate_tx_completions_arg(
|
|||||||
return 0;
|
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
|
* @brief is_ptp_twostep_or_slave_mode - check for dut in ptp 2step or slave
|
||||||
* mode
|
* 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) ==
|
} else if (((tx_swcx->flags & OSI_PKT_CX_PTP) ==
|
||||||
OSI_PKT_CX_PTP) &&
|
OSI_PKT_CX_PTP) &&
|
||||||
// if not master in onestep mode
|
// 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) ==
|
(is_ptp_twostep_or_slave_mode(osi_dma->ptp_flag) ==
|
||||||
OSI_ENABLE) &&
|
OSI_ENABLE) &&
|
||||||
((tx_desc->tdes3 & TDES3_CTXT) == 0U)) {
|
((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 {
|
} else {
|
||||||
/* Do nothing here */
|
/* Do nothing here */
|
||||||
}
|
}
|
||||||
@@ -993,6 +900,7 @@ nve32_t hw_transmit(struct osi_dma_priv_data *osi_dma,
|
|||||||
struct dma_chan_ops *ops,
|
struct dma_chan_ops *ops,
|
||||||
nveu32_t chan)
|
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_pkt_cx *tx_pkt_cx = OSI_NULL;
|
||||||
struct osi_tx_desc *first_desc = OSI_NULL;
|
struct osi_tx_desc *first_desc = OSI_NULL;
|
||||||
struct osi_tx_desc *last_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_swcx *tx_swcx = OSI_NULL;
|
||||||
struct osi_tx_desc *cx_desc = OSI_NULL;
|
struct osi_tx_desc *cx_desc = OSI_NULL;
|
||||||
nve32_t cntx_desc_consumed;
|
nve32_t cntx_desc_consumed;
|
||||||
|
nveu32_t pkt_id = 0x0U;
|
||||||
nveu32_t desc_cnt = 0U;
|
nveu32_t desc_cnt = 0U;
|
||||||
nveu64_t tailptr, tmp;
|
nveu64_t tailptr, tmp;
|
||||||
nveu32_t entry = 0U;
|
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)) {
|
(osi_dma->mac == OSI_MAC_HW_MGBE)) {
|
||||||
/* mark packet id valid */
|
/* mark packet id valid */
|
||||||
tx_desc->tdes3 |= TDES3_PIDV;
|
tx_desc->tdes3 |= TDES3_PIDV;
|
||||||
/* Packet id */
|
if ((osi_dma->ptp_flag & OSI_PTP_SYNC_ONESTEP) ==
|
||||||
tx_desc->tdes0 = chan;
|
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);
|
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 descriptor */
|
||||||
fill_first_desc(tx_ring, tx_pkt_cx, tx_desc, tx_swcx, osi_dma->ptp_flag);
|
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);
|
INCR_TX_DESC_INDEX(entry, 1U);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user