mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 07:22:33 +00:00
203 lines
5.5 KiB
Diff
203 lines
5.5 KiB
Diff
|
From dd8b8f6baf4917124ed268022f7ce4a08d35cc89 Mon Sep 17 00:00:00 2001
|
||
|
From: Yangbo Lu <yangbo.lu@nxp.com>
|
||
|
Date: Wed, 20 Nov 2019 16:23:15 +0800
|
||
|
Subject: [PATCH] net: mscc: ocelot: convert to use ocelot_get_txtstamp()
|
||
|
|
||
|
The method getting TX timestamp by reading timestamp FIFO and
|
||
|
matching skbs list is common for DSA Felix driver too.
|
||
|
So move code out of ocelot_board.c, convert to use
|
||
|
ocelot_get_txtstamp() function and export it.
|
||
|
|
||
|
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
|
||
|
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||
|
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||
|
---
|
||
|
drivers/net/ethernet/mscc/ocelot.c | 62 ++++++++++++++++++++++++++++++--
|
||
|
drivers/net/ethernet/mscc/ocelot.h | 6 ----
|
||
|
drivers/net/ethernet/mscc/ocelot_board.c | 53 +--------------------------
|
||
|
include/soc/mscc/ocelot.h | 9 ++++-
|
||
|
4 files changed, 69 insertions(+), 61 deletions(-)
|
||
|
|
||
|
--- a/drivers/net/ethernet/mscc/ocelot.c
|
||
|
+++ b/drivers/net/ethernet/mscc/ocelot.c
|
||
|
@@ -661,7 +661,8 @@ out:
|
||
|
return NETDEV_TX_OK;
|
||
|
}
|
||
|
|
||
|
-void ocelot_get_hwtimestamp(struct ocelot *ocelot, struct timespec64 *ts)
|
||
|
+static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
|
||
|
+ struct timespec64 *ts)
|
||
|
{
|
||
|
unsigned long flags;
|
||
|
u32 val;
|
||
|
@@ -686,7 +687,64 @@ void ocelot_get_hwtimestamp(struct ocelo
|
||
|
|
||
|
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
|
||
|
}
|
||
|
-EXPORT_SYMBOL(ocelot_get_hwtimestamp);
|
||
|
+
|
||
|
+void ocelot_get_txtstamp(struct ocelot *ocelot)
|
||
|
+{
|
||
|
+ int budget = OCELOT_PTP_QUEUE_SZ;
|
||
|
+
|
||
|
+ while (budget--) {
|
||
|
+ struct skb_shared_hwtstamps shhwtstamps;
|
||
|
+ struct list_head *pos, *tmp;
|
||
|
+ struct sk_buff *skb = NULL;
|
||
|
+ struct ocelot_skb *entry;
|
||
|
+ struct ocelot_port *port;
|
||
|
+ struct timespec64 ts;
|
||
|
+ u32 val, id, txport;
|
||
|
+
|
||
|
+ val = ocelot_read(ocelot, SYS_PTP_STATUS);
|
||
|
+
|
||
|
+ /* Check if a timestamp can be retrieved */
|
||
|
+ if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
|
||
|
+ break;
|
||
|
+
|
||
|
+ WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);
|
||
|
+
|
||
|
+ /* Retrieve the ts ID and Tx port */
|
||
|
+ id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
|
||
|
+ txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
|
||
|
+
|
||
|
+ /* Retrieve its associated skb */
|
||
|
+ port = ocelot->ports[txport];
|
||
|
+
|
||
|
+ list_for_each_safe(pos, tmp, &port->skbs) {
|
||
|
+ entry = list_entry(pos, struct ocelot_skb, head);
|
||
|
+ if (entry->id != id)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ skb = entry->skb;
|
||
|
+
|
||
|
+ list_del(pos);
|
||
|
+ kfree(entry);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Next ts */
|
||
|
+ ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
|
||
|
+
|
||
|
+ if (unlikely(!skb))
|
||
|
+ continue;
|
||
|
+
|
||
|
+ /* Get the h/w timestamp */
|
||
|
+ ocelot_get_hwtimestamp(ocelot, &ts);
|
||
|
+
|
||
|
+ /* Set the timestamp into the skb */
|
||
|
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
|
||
|
+ shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
|
||
|
+ skb_tstamp_tx(skb, &shhwtstamps);
|
||
|
+
|
||
|
+ dev_kfree_skb_any(skb);
|
||
|
+ }
|
||
|
+}
|
||
|
+EXPORT_SYMBOL(ocelot_get_txtstamp);
|
||
|
|
||
|
static int ocelot_mc_unsync(struct net_device *dev, const unsigned char *addr)
|
||
|
{
|
||
|
--- a/drivers/net/ethernet/mscc/ocelot.h
|
||
|
+++ b/drivers/net/ethernet/mscc/ocelot.h
|
||
|
@@ -74,12 +74,6 @@ struct ocelot_port_private {
|
||
|
struct ocelot_port_tc tc;
|
||
|
};
|
||
|
|
||
|
-struct ocelot_skb {
|
||
|
- struct list_head head;
|
||
|
- struct sk_buff *skb;
|
||
|
- u8 id;
|
||
|
-};
|
||
|
-
|
||
|
u32 ocelot_port_readl(struct ocelot_port *port, u32 reg);
|
||
|
void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg);
|
||
|
|
||
|
--- a/drivers/net/ethernet/mscc/ocelot_board.c
|
||
|
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
|
||
|
@@ -198,60 +198,9 @@ static irqreturn_t ocelot_xtr_irq_handle
|
||
|
|
||
|
static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
|
||
|
{
|
||
|
- int budget = OCELOT_PTP_QUEUE_SZ;
|
||
|
struct ocelot *ocelot = arg;
|
||
|
|
||
|
- while (budget--) {
|
||
|
- struct skb_shared_hwtstamps shhwtstamps;
|
||
|
- struct list_head *pos, *tmp;
|
||
|
- struct sk_buff *skb = NULL;
|
||
|
- struct ocelot_skb *entry;
|
||
|
- struct ocelot_port *port;
|
||
|
- struct timespec64 ts;
|
||
|
- u32 val, id, txport;
|
||
|
-
|
||
|
- val = ocelot_read(ocelot, SYS_PTP_STATUS);
|
||
|
-
|
||
|
- /* Check if a timestamp can be retrieved */
|
||
|
- if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
|
||
|
- break;
|
||
|
-
|
||
|
- WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);
|
||
|
-
|
||
|
- /* Retrieve the ts ID and Tx port */
|
||
|
- id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
|
||
|
- txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
|
||
|
-
|
||
|
- /* Retrieve its associated skb */
|
||
|
- port = ocelot->ports[txport];
|
||
|
-
|
||
|
- list_for_each_safe(pos, tmp, &port->skbs) {
|
||
|
- entry = list_entry(pos, struct ocelot_skb, head);
|
||
|
- if (entry->id != id)
|
||
|
- continue;
|
||
|
-
|
||
|
- skb = entry->skb;
|
||
|
-
|
||
|
- list_del(pos);
|
||
|
- kfree(entry);
|
||
|
- }
|
||
|
-
|
||
|
- /* Next ts */
|
||
|
- ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
|
||
|
-
|
||
|
- if (unlikely(!skb))
|
||
|
- continue;
|
||
|
-
|
||
|
- /* Get the h/w timestamp */
|
||
|
- ocelot_get_hwtimestamp(ocelot, &ts);
|
||
|
-
|
||
|
- /* Set the timestamp into the skb */
|
||
|
- memset(&shhwtstamps, 0, sizeof(shhwtstamps));
|
||
|
- shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
|
||
|
- skb_tstamp_tx(skb, &shhwtstamps);
|
||
|
-
|
||
|
- dev_kfree_skb_any(skb);
|
||
|
- }
|
||
|
+ ocelot_get_txtstamp(ocelot);
|
||
|
|
||
|
return IRQ_HANDLED;
|
||
|
}
|
||
|
--- a/include/soc/mscc/ocelot.h
|
||
|
+++ b/include/soc/mscc/ocelot.h
|
||
|
@@ -406,6 +406,13 @@ struct ocelot_ops {
|
||
|
int (*reset)(struct ocelot *ocelot);
|
||
|
};
|
||
|
|
||
|
+struct ocelot_skb {
|
||
|
+ struct list_head head;
|
||
|
+ struct sk_buff *skb;
|
||
|
+ u8 id;
|
||
|
+};
|
||
|
+
|
||
|
+
|
||
|
struct ocelot_port {
|
||
|
struct ocelot *ocelot;
|
||
|
|
||
|
@@ -536,6 +543,6 @@ int ocelot_vlan_del(struct ocelot *ocelo
|
||
|
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr);
|
||
|
int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr);
|
||
|
int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts);
|
||
|
-void ocelot_get_hwtimestamp(struct ocelot *ocelot, struct timespec64 *ts);
|
||
|
+void ocelot_get_txtstamp(struct ocelot *ocelot);
|
||
|
|
||
|
#endif
|