Commit 3af760e4 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'fix-circular-dependency-between-sja1105-and-tag_sja1105'

Vladimir Oltean says:

====================
Fix circular dependency between sja1105 and tag_sja1105

As discussed here:
https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/
DSA tagging protocols cannot use symbols exported by switch drivers.

Eliminate the two instances of that from tag_sja1105, and that allows us
to have a working setup with modules again.
====================

Re-applying to net, this was mistakenly applied to net-next,
see first Link.

Link: https://lore.kernel.org/r/20211012114044.2526146-1-vladimir.oltean@nxp.com/
Link: https://lore.kernel.org/r/20210922143726.2431036-1-vladimir.oltean@nxp.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 43a4b4db 4ac0567e
...@@ -3117,7 +3117,7 @@ static void sja1105_teardown(struct dsa_switch *ds) ...@@ -3117,7 +3117,7 @@ static void sja1105_teardown(struct dsa_switch *ds)
sja1105_static_config_free(&priv->static_config); sja1105_static_config_free(&priv->static_config);
} }
const struct dsa_switch_ops sja1105_switch_ops = { static const struct dsa_switch_ops sja1105_switch_ops = {
.get_tag_protocol = sja1105_get_tag_protocol, .get_tag_protocol = sja1105_get_tag_protocol,
.setup = sja1105_setup, .setup = sja1105_setup,
.teardown = sja1105_teardown, .teardown = sja1105_teardown,
...@@ -3166,7 +3166,6 @@ const struct dsa_switch_ops sja1105_switch_ops = { ...@@ -3166,7 +3166,6 @@ const struct dsa_switch_ops sja1105_switch_ops = {
.port_bridge_tx_fwd_offload = dsa_tag_8021q_bridge_tx_fwd_offload, .port_bridge_tx_fwd_offload = dsa_tag_8021q_bridge_tx_fwd_offload,
.port_bridge_tx_fwd_unoffload = dsa_tag_8021q_bridge_tx_fwd_unoffload, .port_bridge_tx_fwd_unoffload = dsa_tag_8021q_bridge_tx_fwd_unoffload,
}; };
EXPORT_SYMBOL_GPL(sja1105_switch_ops);
static const struct of_device_id sja1105_dt_ids[]; static const struct of_device_id sja1105_dt_ids[];
......
...@@ -64,6 +64,7 @@ enum sja1105_ptp_clk_mode { ...@@ -64,6 +64,7 @@ enum sja1105_ptp_clk_mode {
static int sja1105_change_rxtstamping(struct sja1105_private *priv, static int sja1105_change_rxtstamping(struct sja1105_private *priv,
bool on) bool on)
{ {
struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
struct sja1105_ptp_data *ptp_data = &priv->ptp_data; struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
struct sja1105_general_params_entry *general_params; struct sja1105_general_params_entry *general_params;
struct sja1105_table *table; struct sja1105_table *table;
...@@ -79,7 +80,7 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv, ...@@ -79,7 +80,7 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv,
priv->tagger_data.stampable_skb = NULL; priv->tagger_data.stampable_skb = NULL;
} }
ptp_cancel_worker_sync(ptp_data->clock); ptp_cancel_worker_sync(ptp_data->clock);
skb_queue_purge(&ptp_data->skb_txtstamp_queue); skb_queue_purge(&tagger_data->skb_txtstamp_queue);
skb_queue_purge(&ptp_data->skb_rxtstamp_queue); skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING); return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING);
...@@ -452,40 +453,6 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port, ...@@ -452,40 +453,6 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
return priv->info->rxtstamp(ds, port, skb); 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);
}
EXPORT_SYMBOL_GPL(sja1110_process_meta_tstamp);
/* In addition to cloning the skb which is done by the common /* 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 * sja1105_port_txtstamp, we need to generate a timestamp ID and save the
* packet to the TX timestamping queue. * packet to the TX timestamping queue.
...@@ -494,7 +461,6 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb) ...@@ -494,7 +461,6 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{ {
struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone; struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone;
struct sja1105_private *priv = ds->priv; struct sja1105_private *priv = ds->priv;
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
struct sja1105_port *sp = &priv->ports[port]; struct sja1105_port *sp = &priv->ports[port];
u8 ts_id; u8 ts_id;
...@@ -510,7 +476,7 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb) ...@@ -510,7 +476,7 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
spin_unlock(&sp->data->meta_lock); spin_unlock(&sp->data->meta_lock);
skb_queue_tail(&ptp_data->skb_txtstamp_queue, clone); skb_queue_tail(&sp->data->skb_txtstamp_queue, clone);
} }
/* Called from dsa_skb_tx_timestamp. This callback is just to clone /* Called from dsa_skb_tx_timestamp. This callback is just to clone
...@@ -953,7 +919,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds) ...@@ -953,7 +919,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
/* Only used on SJA1105 */ /* Only used on SJA1105 */
skb_queue_head_init(&ptp_data->skb_rxtstamp_queue); skb_queue_head_init(&ptp_data->skb_rxtstamp_queue);
/* Only used on SJA1110 */ /* Only used on SJA1110 */
skb_queue_head_init(&ptp_data->skb_txtstamp_queue); skb_queue_head_init(&tagger_data->skb_txtstamp_queue);
spin_lock_init(&tagger_data->meta_lock); spin_lock_init(&tagger_data->meta_lock);
ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev); ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev);
...@@ -971,6 +937,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds) ...@@ -971,6 +937,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
void sja1105_ptp_clock_unregister(struct dsa_switch *ds) void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
{ {
struct sja1105_private *priv = ds->priv; struct sja1105_private *priv = ds->priv;
struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
struct sja1105_ptp_data *ptp_data = &priv->ptp_data; struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
if (IS_ERR_OR_NULL(ptp_data->clock)) if (IS_ERR_OR_NULL(ptp_data->clock))
...@@ -978,7 +945,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds) ...@@ -978,7 +945,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
del_timer_sync(&ptp_data->extts_timer); del_timer_sync(&ptp_data->extts_timer);
ptp_cancel_worker_sync(ptp_data->clock); ptp_cancel_worker_sync(ptp_data->clock);
skb_queue_purge(&ptp_data->skb_txtstamp_queue); skb_queue_purge(&tagger_data->skb_txtstamp_queue);
skb_queue_purge(&ptp_data->skb_rxtstamp_queue); skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
ptp_clock_unregister(ptp_data->clock); ptp_clock_unregister(ptp_data->clock);
ptp_data->clock = NULL; ptp_data->clock = NULL;
......
...@@ -8,21 +8,6 @@ ...@@ -8,21 +8,6 @@
#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) #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 /* Calculate the first base_time in the future that satisfies this
* relationship: * relationship:
* *
...@@ -77,10 +62,6 @@ struct sja1105_ptp_data { ...@@ -77,10 +62,6 @@ struct sja1105_ptp_data {
struct timer_list extts_timer; struct timer_list extts_timer;
/* Used only on SJA1105 to reconstruct partial timestamps */ /* Used only on SJA1105 to reconstruct partial timestamps */
struct sk_buff_head skb_rxtstamp_queue; 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_info caps;
struct ptp_clock *clock; struct ptp_clock *clock;
struct sja1105_ptp_cmd cmd; struct sja1105_ptp_cmd cmd;
......
...@@ -48,6 +48,10 @@ struct sja1105_tagger_data { ...@@ -48,6 +48,10 @@ struct sja1105_tagger_data {
spinlock_t meta_lock; spinlock_t meta_lock;
unsigned long state; unsigned long state;
u8 ts_id; u8 ts_id;
/* Used on SJA1110 where meta frames are generated only for
* 2-step TX timestamps
*/
struct sk_buff_head skb_txtstamp_queue;
}; };
struct sja1105_skb_cb { struct sja1105_skb_cb {
...@@ -69,42 +73,24 @@ struct sja1105_port { ...@@ -69,42 +73,24 @@ struct sja1105_port {
bool hwts_tx_en; bool hwts_tx_en;
}; };
enum sja1110_meta_tstamp { /* Timestamps are in units of 8 ns clock ticks (equivalent to
SJA1110_META_TSTAMP_TX = 0, * a fixed 125 MHz clock).
SJA1110_META_TSTAMP_RX = 1, */
}; #define SJA1105_TICK_NS 8
#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP)
void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id,
enum sja1110_meta_tstamp dir, u64 tstamp);
#else
static inline void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, static inline s64 ns_to_sja1105_ticks(s64 ns)
u8 ts_id, enum sja1110_meta_tstamp dir,
u64 tstamp)
{ {
return ns / SJA1105_TICK_NS;
} }
#endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */ static inline s64 sja1105_ticks_to_ns(s64 ticks)
#if IS_ENABLED(CONFIG_NET_DSA_SJA1105)
extern const struct dsa_switch_ops sja1105_switch_ops;
static inline bool dsa_port_is_sja1105(struct dsa_port *dp)
{ {
return dp->ds->ops == &sja1105_switch_ops; return ticks * SJA1105_TICK_NS;
} }
#else
static inline bool dsa_port_is_sja1105(struct dsa_port *dp) static inline bool dsa_port_is_sja1105(struct dsa_port *dp)
{ {
return false; return true;
} }
#endif
#endif /* _NET_DSA_SJA1105_H */ #endif /* _NET_DSA_SJA1105_H */
...@@ -138,7 +138,6 @@ config NET_DSA_TAG_LAN9303 ...@@ -138,7 +138,6 @@ config NET_DSA_TAG_LAN9303
config NET_DSA_TAG_SJA1105 config NET_DSA_TAG_SJA1105
tristate "Tag driver for NXP SJA1105 switches" tristate "Tag driver for NXP SJA1105 switches"
depends on NET_DSA_SJA1105 || !NET_DSA_SJA1105
select PACKING select PACKING
help help
Say Y or M if you want to enable support for tagging frames with the Say Y or M if you want to enable support for tagging frames with the
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/dsa/sja1105.h> #include <linux/dsa/sja1105.h>
#include <linux/dsa/8021q.h> #include <linux/dsa/8021q.h>
#include <linux/skbuff.h>
#include <linux/packing.h> #include <linux/packing.h>
#include "dsa_priv.h" #include "dsa_priv.h"
...@@ -53,6 +54,11 @@ ...@@ -53,6 +54,11 @@
#define SJA1110_TX_TRAILER_LEN 4 #define SJA1110_TX_TRAILER_LEN 4
#define SJA1110_MAX_PADDING_LEN 15 #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 */ /* 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) static inline bool sja1105_is_link_local(const struct sk_buff *skb)
{ {
...@@ -520,6 +526,43 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, ...@@ -520,6 +526,43 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
is_meta); 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 sk_buff *skb, *skb_tmp, *skb_match = NULL;
struct dsa_port *dp = dsa_to_port(ds, port);
struct skb_shared_hwtstamps shwt = {0};
struct sja1105_port *sp = dp->priv;
if (!dsa_port_is_sja1105(dp))
return;
/* We don't care about RX timestamps on the CPU port */
if (dir == SJA1110_META_TSTAMP_RX)
return;
spin_lock(&sp->data->skb_txtstamp_queue.lock);
skb_queue_walk_safe(&sp->data->skb_txtstamp_queue, skb, skb_tmp) {
if (SJA1105_SKB_CB(skb)->ts_id != ts_id)
continue;
__skb_unlink(skb, &sp->data->skb_txtstamp_queue);
skb_match = skb;
break;
}
spin_unlock(&sp->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) 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; u8 *buf = dsa_etype_header_pos_rx(skb) + SJA1110_HEADER_LEN;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment