-
Notifications
You must be signed in to change notification settings - Fork 1.7k
arch/arm/stm32: hardware TX timestamping via SO_TIMESTAMPING #20148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
daniel-p-carvalho
wants to merge
2
commits into
apache:master
Choose a base branch
from
daniel-p-carvalho:feat/ptp-hw-timestamp-sync
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+154
−8
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -417,7 +417,7 @@ | |
| */ | ||
|
|
||
| #ifdef CONFIG_NET_PROMISCUOUS | ||
| # define MACFFR_SET_BITS (ETH_MACFFR_PCF_PAUSE | ETH_MACFFR_PM) | ||
| # define MACFFR_SET_BITS (ETH_MACFFR_PCF_ALL | ETH_MACFFR_PM) | ||
| #else | ||
| # define MACFFR_SET_BITS (ETH_MACFFR_PCF_PAUSE) | ||
| #endif | ||
|
|
@@ -635,6 +635,13 @@ struct stm32_ethmac_s | |
| uint32_t rxtimelow; /* Received packet timestamp subsecond */ | ||
| uint32_t rxtimehigh; /* Received packet timestamp seconds */ | ||
| #endif | ||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| struct iob_queue_s tx_tstampq; /* Pending TX timestamp loopback packets */ | ||
|
|
||
| /* Per-descriptor TX clone */ | ||
|
|
||
| struct iob_s *tx_meta[CONFIG_STM32_ETH_NTXDESC]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. txmeta |
||
| #endif | ||
| #if defined(CONFIG_STM32_ETH_PTP) && defined(CONFIG_PTP_CLOCK) | ||
| struct ptp_lowerhalf_s ptp_lower; /* PTP hardware clock lower half */ | ||
| #endif | ||
|
|
@@ -709,6 +716,9 @@ static int stm32_recvframe(struct stm32_ethmac_s *priv); | |
| static void stm32_receive(struct stm32_ethmac_s *priv); | ||
| static void stm32_freeframe(struct stm32_ethmac_s *priv); | ||
| static void stm32_txdone(struct stm32_ethmac_s *priv); | ||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| static void stm32_tx_tstamp_flush(struct stm32_ethmac_s *priv); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. stm32_txtstamp_flush |
||
| #endif | ||
|
|
||
| static void stm32_interrupt_work(void *arg); | ||
| static int stm32_interrupt(int irq, void *context, void *arg); | ||
|
|
@@ -798,6 +808,14 @@ static void stm32_eth_ptp_convert_rxtime(struct stm32_ethmac_s *priv); | |
| * Private Functions | ||
| ****************************************************************************/ | ||
|
|
||
| #ifdef CONFIG_STM32_ETH_PTP | ||
| static inline void ptp_to_timespec(uint64_t timestamp, struct timespec *ts) | ||
| { | ||
| ts->tv_sec = (timestamp >> 32); | ||
| ts->tv_nsec = ((uint32_t)timestamp * (uint64_t)NSEC_PER_SEC) >> 32; | ||
| } | ||
| #endif | ||
|
|
||
| /**************************************************************************** | ||
| * Name: stm32_getreg | ||
| * | ||
|
|
@@ -1162,6 +1180,29 @@ static int stm32_transmit(struct stm32_ethmac_s *priv) | |
|
|
||
| txdesc->tdes0 |= (ETH_TDES0_FS | ETH_TDES0_LS | ETH_TDES0_IC); | ||
|
|
||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| { | ||
| uint32_t txindex = txdesc - g_txtable; | ||
|
|
||
| priv->tx_meta[txindex] = NULL; | ||
| if (priv->dev.d_iob != NULL && priv->dev.d_iob->io_conn != NULL) | ||
| { | ||
| struct iob_s *clone = netdev_iob_clone(&priv->dev, false); | ||
|
|
||
| if (clone != NULL) | ||
| { | ||
| clone->io_conn = priv->dev.d_iob->io_conn; | ||
| priv->tx_meta[txindex] = clone; | ||
| txdesc->tdes0 |= ETH_TDES0_TTSE; | ||
| } | ||
| else | ||
| { | ||
| nerr("ERROR: Failed to clone IOB for TX timestamp\n"); | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| /* Set frame size */ | ||
|
|
||
| DEBUGASSERT(priv->dev.d_len <= CONFIG_STM32_ETH_BUFSIZE); | ||
|
|
@@ -1700,6 +1741,46 @@ static int stm32_recvframe(struct stm32_ethmac_s *priv) | |
| return -EAGAIN; | ||
| } | ||
|
|
||
| /**************************************************************************** | ||
| * Function: stm32_tx_tstamp_flush | ||
| * | ||
| * Description: | ||
| * Deliver pending TX hardware timestamp loopback packets to the network | ||
| * stack. | ||
| * | ||
| * Input Parameters: | ||
| * priv - Reference to the driver state structure | ||
| * | ||
| * Returned Value: | ||
| * None | ||
| * | ||
| * Assumptions: | ||
| * The network is locked. | ||
| * | ||
| ****************************************************************************/ | ||
|
|
||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| static void stm32_tx_tstamp_flush(struct stm32_ethmac_s *priv) | ||
| { | ||
| struct net_driver_s *dev = &priv->dev; | ||
|
|
||
| while (!IOB_QEMPTY(&priv->tx_tstampq)) | ||
| { | ||
| struct iob_s *iob = iob_remove_queue(&priv->tx_tstampq); | ||
|
|
||
| dev->d_iob = iob; | ||
| dev->d_len = iob->io_pktlen; | ||
| #ifdef CONFIG_NET_PKT | ||
| pkt_input(dev); | ||
| #endif | ||
| dev->d_iob = NULL; | ||
| dev->d_len = 0; | ||
| iob->io_conn = NULL; | ||
| iob_free_chain(iob); | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| /**************************************************************************** | ||
| * Function: stm32_receive | ||
| * | ||
|
|
@@ -1721,6 +1802,12 @@ static void stm32_receive(struct stm32_ethmac_s *priv) | |
| { | ||
| struct net_driver_s *dev = &priv->dev; | ||
|
|
||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| /* Return any TX hardware timestamp loopback packets first */ | ||
|
|
||
| stm32_tx_tstamp_flush(priv); | ||
| #endif | ||
|
|
||
| /* Loop while while stm32_recvframe() successfully retrieves valid | ||
| * Ethernet frames. | ||
| */ | ||
|
|
@@ -1833,7 +1920,18 @@ static void stm32_receive(struct stm32_ethmac_s *priv) | |
| else | ||
| #endif | ||
| { | ||
| nerr("ERROR: Dropped, Unknown type: %04x\n", BUF->type); | ||
| #ifdef CONFIG_NET_PKT | ||
| /* Frames that packet sockets consume directly (PTP, Ethertype | ||
| * 0x88f7, and IPv6) were already delivered via pkt_input() | ||
| * above, so they are not "unknown" and must not be logged as | ||
| * dropped. | ||
| */ | ||
|
|
||
| if (BUF->type != HTONS(0x88f7) && BUF->type != HTONS(ETHTYPE_IP6)) | ||
| #endif | ||
| { | ||
| nerr("ERROR: Dropped, Unknown type: %04x\n", BUF->type); | ||
| } | ||
| } | ||
|
|
||
| /* We are finished with the RX buffer. NOTE: If the buffer is | ||
|
|
@@ -1912,6 +2010,29 @@ static void stm32_freeframe(struct stm32_ethmac_s *priv) | |
|
|
||
| if ((txdesc->tdes0 & ETH_TDES0_LS) != 0) | ||
| { | ||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| uint32_t tail = txdesc - g_txtable; | ||
| struct iob_s *clone = priv->tx_meta[tail]; | ||
|
|
||
| priv->tx_meta[tail] = NULL; | ||
| if (clone != NULL) | ||
| { | ||
| if ((txdesc->tdes0 & ETH_TDES0_TTSS) != 0) | ||
| { | ||
| uint64_t hw_time = ((uint64_t)txdesc->tdes7 << 32) | ||
| | ((txdesc->tdes6 & ETH_PTPTSLR_MASK) | ||
| << 1); | ||
|
|
||
| ptp_to_timespec(hw_time, &clone->io_time); | ||
| iob_add_queue(clone, &priv->tx_tstampq); | ||
| } | ||
| else | ||
| { | ||
| iob_free_chain(clone); | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| /* Yes.. Decrement the number of frames "in-flight". */ | ||
|
|
||
| priv->inflight--; | ||
|
|
@@ -1975,6 +2096,12 @@ static void stm32_txdone(struct stm32_ethmac_s *priv) | |
|
|
||
| stm32_freeframe(priv); | ||
|
|
||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| /* Deliver any pending TX hardware timestamp loopback packets */ | ||
|
|
||
| stm32_tx_tstamp_flush(priv); | ||
| #endif | ||
|
|
||
| /* If no further xmits are pending, then cancel the TX timeout */ | ||
|
|
||
| if (priv->inflight <= 0) | ||
|
|
@@ -2341,6 +2468,9 @@ static int stm32_ifdown(struct net_driver_s *dev) | |
| (struct stm32_ethmac_s *)dev->d_private; | ||
| irqstate_t flags; | ||
| int ret = OK; | ||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| int i; | ||
| #endif | ||
|
|
||
| ninfo("Taking the network down\n"); | ||
|
|
||
|
|
@@ -2378,6 +2508,20 @@ static int stm32_ifdown(struct net_driver_s *dev) | |
| "still assuming it's going down.\n"); | ||
| } | ||
|
|
||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_TX | ||
| /* Drain any pending TX timestamp loopback packets and clones */ | ||
|
|
||
| iob_free_queue(&priv->tx_tstampq); | ||
| for (i = 0; i < CONFIG_STM32_ETH_NTXDESC; i++) | ||
| { | ||
| if (priv->tx_meta[i] != NULL) | ||
| { | ||
| iob_free_chain(priv->tx_meta[i]); | ||
| priv->tx_meta[i] = NULL; | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| /* Mark the device "down" */ | ||
|
|
||
| priv->ifup = false; | ||
|
|
@@ -3981,12 +4125,6 @@ static uint64_t stm32_eth_ptp_gettime(void) | |
| } | ||
| #endif | ||
|
|
||
| static inline void ptp_to_timespec(uint64_t timestamp, struct timespec *ts) | ||
| { | ||
| ts->tv_sec = (timestamp >> 32); | ||
| ts->tv_nsec = ((uint32_t)timestamp * (uint64_t)NSEC_PER_SEC) >> 32; | ||
| } | ||
|
|
||
| /* Convert RX timestamp to CLOCK_REALTIME */ | ||
| #ifdef CONFIG_STM32_ETH_TIMESTAMP_RX | ||
| static void stm32_eth_ptp_convert_rxtime(struct stm32_ethmac_s *priv) | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
txtstampq