mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 02:36:02 +00:00
Revert "net: dsa: move sja1110_process_meta_tstamp inside the tagging protocol driver"
This reverts commit 6d709cadfd
.
The above change was done to avoid calling symbols exported by the
switch driver from the tagging protocol driver.
With the tagger-owned storage model, we have a new option on our hands,
and that is for the switch driver to provide a data consumer handler in
the form of a function pointer inside the ->connect_tag_protocol()
method. Having a function pointer avoids the problems of the exported
symbols approach.
By creating a handler for metadata frames holding TX timestamps on
SJA1110, we are able to eliminate an skb queue from the tagger data, and
replace it with a simple, and stateless, function pointer. This skb
queue is now handled exclusively by sja1105_ptp.c, which makes the code
easier to follow, as it used to be before the reverted patch.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c79e84866d
commit
fcbf979a5b
@ -2714,6 +2714,7 @@ static int sja1105_connect_tag_protocol(struct dsa_switch *ds,
|
||||
case DSA_TAG_PROTO_SJA1105:
|
||||
tagger_data = sja1105_tagger_data(ds);
|
||||
tagger_data->xmit_work_fn = sja1105_port_deferred_xmit;
|
||||
tagger_data->meta_tstamp_handler = sja1110_process_meta_tstamp;
|
||||
return 0;
|
||||
default:
|
||||
return -EPROTONOSUPPORT;
|
||||
|
@ -80,7 +80,7 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv,
|
||||
tagger_data->stampable_skb = NULL;
|
||||
}
|
||||
ptp_cancel_worker_sync(ptp_data->clock);
|
||||
skb_queue_purge(&tagger_data->skb_txtstamp_queue);
|
||||
skb_queue_purge(&ptp_data->skb_txtstamp_queue);
|
||||
skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
|
||||
|
||||
return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING);
|
||||
@ -456,15 +456,48 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
|
||||
return priv->info->rxtstamp(ds, port, skb);
|
||||
}
|
||||
|
||||
void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id,
|
||||
enum sja1110_meta_tstamp dir, u64 tstamp)
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
|
||||
struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
|
||||
struct skb_shared_hwtstamps shwt = {0};
|
||||
|
||||
/* We don't care about RX timestamps on the CPU port */
|
||||
if (dir == SJA1110_META_TSTAMP_RX)
|
||||
return;
|
||||
|
||||
spin_lock(&ptp_data->skb_txtstamp_queue.lock);
|
||||
|
||||
skb_queue_walk_safe(&ptp_data->skb_txtstamp_queue, skb, skb_tmp) {
|
||||
if (SJA1105_SKB_CB(skb)->ts_id != ts_id)
|
||||
continue;
|
||||
|
||||
__skb_unlink(skb, &ptp_data->skb_txtstamp_queue);
|
||||
skb_match = skb;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock(&ptp_data->skb_txtstamp_queue.lock);
|
||||
|
||||
if (WARN_ON(!skb_match))
|
||||
return;
|
||||
|
||||
shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp));
|
||||
skb_complete_tx_timestamp(skb_match, &shwt);
|
||||
}
|
||||
|
||||
/* In addition to cloning the skb which is done by the common
|
||||
* sja1105_port_txtstamp, we need to generate a timestamp ID and save the
|
||||
* packet to the TX timestamping queue.
|
||||
*/
|
||||
void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
|
||||
{
|
||||
struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
|
||||
struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone;
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
|
||||
u8 ts_id;
|
||||
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
@ -479,7 +512,7 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
|
||||
|
||||
spin_unlock(&priv->ts_id_lock);
|
||||
|
||||
skb_queue_tail(&tagger_data->skb_txtstamp_queue, clone);
|
||||
skb_queue_tail(&ptp_data->skb_txtstamp_queue, clone);
|
||||
}
|
||||
|
||||
/* Called from dsa_skb_tx_timestamp. This callback is just to clone
|
||||
@ -919,6 +952,8 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
|
||||
|
||||
/* Only used on SJA1105 */
|
||||
skb_queue_head_init(&ptp_data->skb_rxtstamp_queue);
|
||||
/* Only used on SJA1110 */
|
||||
skb_queue_head_init(&ptp_data->skb_txtstamp_queue);
|
||||
|
||||
ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev);
|
||||
if (IS_ERR_OR_NULL(ptp_data->clock))
|
||||
@ -934,7 +969,6 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
|
||||
|
||||
void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
|
||||
{
|
||||
struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
|
||||
|
||||
@ -943,7 +977,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
|
||||
|
||||
del_timer_sync(&ptp_data->extts_timer);
|
||||
ptp_cancel_worker_sync(ptp_data->clock);
|
||||
skb_queue_purge(&tagger_data->skb_txtstamp_queue);
|
||||
skb_queue_purge(&ptp_data->skb_txtstamp_queue);
|
||||
skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
|
||||
ptp_clock_unregister(ptp_data->clock);
|
||||
ptp_data->clock = NULL;
|
||||
|
@ -8,6 +8,21 @@
|
||||
|
||||
#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP)
|
||||
|
||||
/* Timestamps are in units of 8 ns clock ticks (equivalent to
|
||||
* a fixed 125 MHz clock).
|
||||
*/
|
||||
#define SJA1105_TICK_NS 8
|
||||
|
||||
static inline s64 ns_to_sja1105_ticks(s64 ns)
|
||||
{
|
||||
return ns / SJA1105_TICK_NS;
|
||||
}
|
||||
|
||||
static inline s64 sja1105_ticks_to_ns(s64 ticks)
|
||||
{
|
||||
return ticks * SJA1105_TICK_NS;
|
||||
}
|
||||
|
||||
/* Calculate the first base_time in the future that satisfies this
|
||||
* relationship:
|
||||
*
|
||||
@ -62,6 +77,10 @@ struct sja1105_ptp_data {
|
||||
struct timer_list extts_timer;
|
||||
/* Used only on SJA1105 to reconstruct partial timestamps */
|
||||
struct sk_buff_head skb_rxtstamp_queue;
|
||||
/* Used on SJA1110 where meta frames are generated only for
|
||||
* 2-step TX timestamps
|
||||
*/
|
||||
struct sk_buff_head skb_txtstamp_queue;
|
||||
struct ptp_clock_info caps;
|
||||
struct ptp_clock *clock;
|
||||
struct sja1105_ptp_cmd cmd;
|
||||
@ -112,6 +131,9 @@ bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb);
|
||||
bool sja1110_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb);
|
||||
void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb);
|
||||
|
||||
void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id,
|
||||
enum sja1110_meta_tstamp dir, u64 tstamp);
|
||||
|
||||
#else
|
||||
|
||||
struct sja1105_ptp_cmd;
|
||||
@ -178,6 +200,8 @@ static inline int sja1105_ptp_commit(struct dsa_switch *ds,
|
||||
#define sja1110_rxtstamp NULL
|
||||
#define sja1110_txtstamp NULL
|
||||
|
||||
#define sja1110_process_meta_tstamp NULL
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */
|
||||
|
||||
#endif /* _SJA1105_PTP_H */
|
||||
|
@ -37,6 +37,11 @@
|
||||
|
||||
#define SJA1105_HWTS_RX_EN 0
|
||||
|
||||
enum sja1110_meta_tstamp {
|
||||
SJA1110_META_TSTAMP_TX = 0,
|
||||
SJA1110_META_TSTAMP_RX = 1,
|
||||
};
|
||||
|
||||
struct sja1105_deferred_xmit_work {
|
||||
struct dsa_port *dp;
|
||||
struct sk_buff *skb;
|
||||
@ -51,12 +56,10 @@ struct sja1105_tagger_data {
|
||||
*/
|
||||
spinlock_t meta_lock;
|
||||
unsigned long state;
|
||||
/* Used on SJA1110 where meta frames are generated only for
|
||||
* 2-step TX timestamps
|
||||
*/
|
||||
struct sk_buff_head skb_txtstamp_queue;
|
||||
struct kthread_worker *xmit_worker;
|
||||
void (*xmit_work_fn)(struct kthread_work *work);
|
||||
void (*meta_tstamp_handler)(struct dsa_switch *ds, int port, u8 ts_id,
|
||||
enum sja1110_meta_tstamp dir, u64 tstamp);
|
||||
};
|
||||
|
||||
struct sja1105_skb_cb {
|
||||
@ -69,21 +72,6 @@ struct sja1105_skb_cb {
|
||||
#define SJA1105_SKB_CB(skb) \
|
||||
((struct sja1105_skb_cb *)((skb)->cb))
|
||||
|
||||
/* Timestamps are in units of 8 ns clock ticks (equivalent to
|
||||
* a fixed 125 MHz clock).
|
||||
*/
|
||||
#define SJA1105_TICK_NS 8
|
||||
|
||||
static inline s64 ns_to_sja1105_ticks(s64 ns)
|
||||
{
|
||||
return ns / SJA1105_TICK_NS;
|
||||
}
|
||||
|
||||
static inline s64 sja1105_ticks_to_ns(s64 ticks)
|
||||
{
|
||||
return ticks * SJA1105_TICK_NS;
|
||||
}
|
||||
|
||||
static inline struct sja1105_tagger_data *
|
||||
sja1105_tagger_data(struct dsa_switch *ds)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/dsa/sja1105.h>
|
||||
#include <linux/dsa/8021q.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/packing.h>
|
||||
#include "dsa_priv.h"
|
||||
|
||||
@ -54,11 +53,6 @@
|
||||
#define SJA1110_TX_TRAILER_LEN 4
|
||||
#define SJA1110_MAX_PADDING_LEN 15
|
||||
|
||||
enum sja1110_meta_tstamp {
|
||||
SJA1110_META_TSTAMP_TX = 0,
|
||||
SJA1110_META_TSTAMP_RX = 1,
|
||||
};
|
||||
|
||||
/* Similar to is_link_local_ether_addr(hdr->h_dest) but also covers PTP */
|
||||
static inline bool sja1105_is_link_local(const struct sk_buff *skb)
|
||||
{
|
||||
@ -539,44 +533,12 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
|
||||
is_meta);
|
||||
}
|
||||
|
||||
static void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port,
|
||||
u8 ts_id, enum sja1110_meta_tstamp dir,
|
||||
u64 tstamp)
|
||||
{
|
||||
struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
|
||||
struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
|
||||
struct skb_shared_hwtstamps shwt = {0};
|
||||
|
||||
/* We don't care about RX timestamps on the CPU port */
|
||||
if (dir == SJA1110_META_TSTAMP_RX)
|
||||
return;
|
||||
|
||||
spin_lock(&tagger_data->skb_txtstamp_queue.lock);
|
||||
|
||||
skb_queue_walk_safe(&tagger_data->skb_txtstamp_queue, skb, skb_tmp) {
|
||||
if (SJA1105_SKB_CB(skb)->ts_id != ts_id)
|
||||
continue;
|
||||
|
||||
__skb_unlink(skb, &tagger_data->skb_txtstamp_queue);
|
||||
skb_match = skb;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock(&tagger_data->skb_txtstamp_queue.lock);
|
||||
|
||||
if (WARN_ON(!skb_match))
|
||||
return;
|
||||
|
||||
shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp));
|
||||
skb_complete_tx_timestamp(skb_match, &shwt);
|
||||
}
|
||||
|
||||
static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)
|
||||
{
|
||||
u8 *buf = dsa_etype_header_pos_rx(skb) + SJA1110_HEADER_LEN;
|
||||
int switch_id = SJA1110_RX_HEADER_SWITCH_ID(rx_header);
|
||||
int n_ts = SJA1110_RX_HEADER_N_TS(rx_header);
|
||||
struct sja1105_tagger_data *tagger_data;
|
||||
struct net_device *master = skb->dev;
|
||||
struct dsa_port *cpu_dp;
|
||||
struct dsa_switch *ds;
|
||||
@ -590,6 +552,10 @@ static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tagger_data = sja1105_tagger_data(ds);
|
||||
if (!tagger_data->meta_tstamp_handler)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i <= n_ts; i++) {
|
||||
u8 ts_id, source_port, dir;
|
||||
u64 tstamp;
|
||||
@ -599,8 +565,8 @@ static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)
|
||||
dir = (buf[1] & BIT(3)) >> 3;
|
||||
tstamp = be64_to_cpu(*(__be64 *)(buf + 2));
|
||||
|
||||
sja1110_process_meta_tstamp(ds, source_port, ts_id, dir,
|
||||
tstamp);
|
||||
tagger_data->meta_tstamp_handler(ds, source_port, ts_id, dir,
|
||||
tstamp);
|
||||
|
||||
buf += SJA1110_META_TSTAMP_SIZE;
|
||||
}
|
||||
@ -767,8 +733,6 @@ static int sja1105_connect(struct dsa_switch_tree *dst)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Only used on SJA1110 */
|
||||
skb_queue_head_init(&tagger_data->skb_txtstamp_queue);
|
||||
spin_lock_init(&tagger_data->meta_lock);
|
||||
|
||||
xmit_worker = kthread_create_worker(0, "dsa%d:%d_xmit",
|
||||
|
Loading…
Reference in New Issue
Block a user