In order to get the switch to generate a timestamp for a transmitted
packet, we need to set the TS bit in the BRCM tag. The switch will then
create a status frame, which gets send back to the cpu.
In b53_port_txtstamp() we put the skb into a waiting position.
When a status frame is received, we extract the timestamp and put the time
according to our timecounter into the waiting skb. When
TX_TSTAMP_TIMEOUT is reached and we have no means to correctly get back
a full timestamp, we cancel the process.
As the status frame doesn't contain a reference to the original packet,
only one packet with timestamp request can be sent at a time.
Signed-off-by: Martin Kaistra <martin.kaistra@xxxxxxxxxxxxx>
---
+static long b53_hwtstamp_work(struct ptp_clock_info *ptp)
+{
+ struct b53_device *dev =
+ container_of(ptp, struct b53_device, ptp_clock_info);
+ struct dsa_switch *ds = dev->ds;
+ int i;
+
+ for (i = 0; i < ds->num_ports; i++) {
+ struct b53_port_hwtstamp *ps;
+
+ if (!dsa_is_user_port(ds, i))
+ continue;
#endif
diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
index 85dc47c22008..53cd0345df1b 100644
--- a/net/dsa/tag_brcm.c
+++ b/net/dsa/tag_brcm.c
@@ -8,6 +8,7 @@
#include <linux/dsa/brcm.h>
#include <linux/etherdevice.h>
#include <linux/list.h>
+#include <linux/ptp_classify.h>
#include <linux/slab.h>
#include <linux/dsa/b53.h>
@@ -85,9 +86,14 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
unsigned int offset)
{
struct dsa_port *dp = dsa_slave_to_port(dev);
+ struct b53_device *b53_dev = dp->ds->priv;
+ unsigned int type = ptp_classify_raw(skb);
u16 queue = skb_get_queue_mapping(skb);
+ struct b53_port_hwtstamp *ps;
u8 *brcm_tag;
+ ps = &b53_dev->ports[dp->index].port_hwtstamp;
+
/* Frames with this tag have one of these two layouts:
* -----------------------------------
* | MAC DA | MAC SA | 4b tag | Type | DSA_TAG_PROTO_BRCM
@@ -143,6 +181,9 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
unsigned int offset,
int *tag_len)
{
+ struct b53_port_hwtstamp *ps;
+ struct b53_device *b53_dev;
+ struct dsa_port *dp;
int source_port;
u8 *brcm_tag;
u32 tstamp;
@@ -174,6 +215,16 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
if (!skb->dev)
return NULL;
+ /* Check whether this is a status frame */
+ if (*tag_len == 8 && brcm_tag[3] & 0x20) {