Commit deab6b1c authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski

net: dsa: tag_ocelot: break circular dependency with ocelot switch lib driver

As explained here:
https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/
DSA tagging protocol drivers cannot depend on symbols exported by switch
drivers, because this creates a circular dependency that breaks module
autoloading.

The tag_ocelot.c file depends on the ocelot_ptp_rew_op() function
exported by the common ocelot switch lib. This function looks at
OCELOT_SKB_CB(skb) and computes how to populate the REW_OP field of the
DSA tag, for PTP timestamping (the command: one-step/two-step, and the
TX timestamp identifier).

None of that requires deep insight into the driver, it is quite
stateless, as it only depends upon the skb->cb. So let's make it a
static inline function and put it in include/linux/dsa/ocelot.h, a
file that despite its name is used by the ocelot switch driver for
populating the injection header too - since commit 40d3f295 ("net:
mscc: ocelot: use common tag parsing code with DSA").

With that function declared as static inline, its body is expanded
inside each call site, so the dependency is broken and the DSA tagger
can be built without the switch library, upon which the felix driver
depends.

Fixes: 39e5308b ("net: mscc: ocelot: support PTP Sync one-step timestamping")
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ebb4c6a9
...@@ -601,23 +601,6 @@ static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port, ...@@ -601,23 +601,6 @@ static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
return 0; return 0;
} }
u32 ocelot_ptp_rew_op(struct sk_buff *skb)
{
struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone;
u8 ptp_cmd = OCELOT_SKB_CB(skb)->ptp_cmd;
u32 rew_op = 0;
if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP && clone) {
rew_op = ptp_cmd;
rew_op |= OCELOT_SKB_CB(clone)->ts_id << 3;
} else if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) {
rew_op = ptp_cmd;
}
return rew_op;
}
EXPORT_SYMBOL(ocelot_ptp_rew_op);
static bool ocelot_ptp_is_onestep_sync(struct sk_buff *skb, static bool ocelot_ptp_is_onestep_sync(struct sk_buff *skb,
unsigned int ptp_class) unsigned int ptp_class)
{ {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright 2020-2021 NXP * Copyright 2020-2021 NXP
*/ */
#include <linux/dsa/ocelot.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/of_net.h> #include <linux/of_net.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
......
...@@ -6,6 +6,26 @@ ...@@ -6,6 +6,26 @@
#define _NET_DSA_TAG_OCELOT_H #define _NET_DSA_TAG_OCELOT_H
#include <linux/packing.h> #include <linux/packing.h>
#include <linux/skbuff.h>
struct ocelot_skb_cb {
struct sk_buff *clone;
unsigned int ptp_class; /* valid only for clones */
u8 ptp_cmd;
u8 ts_id;
};
#define OCELOT_SKB_CB(skb) \
((struct ocelot_skb_cb *)((skb)->cb))
#define IFH_TAG_TYPE_C 0
#define IFH_TAG_TYPE_S 1
#define IFH_REW_OP_NOOP 0x0
#define IFH_REW_OP_DSCP 0x1
#define IFH_REW_OP_ONE_STEP_PTP 0x2
#define IFH_REW_OP_TWO_STEP_PTP 0x3
#define IFH_REW_OP_ORIGIN_PTP 0x5
#define OCELOT_TAG_LEN 16 #define OCELOT_TAG_LEN 16
#define OCELOT_SHORT_PREFIX_LEN 4 #define OCELOT_SHORT_PREFIX_LEN 4
...@@ -215,4 +235,21 @@ static inline void ocelot_ifh_set_vid(void *injection, u64 vid) ...@@ -215,4 +235,21 @@ static inline void ocelot_ifh_set_vid(void *injection, u64 vid)
packing(injection, &vid, 11, 0, OCELOT_TAG_LEN, PACK, 0); packing(injection, &vid, 11, 0, OCELOT_TAG_LEN, PACK, 0);
} }
/* Determine the PTP REW_OP to use for injecting the given skb */
static inline u32 ocelot_ptp_rew_op(struct sk_buff *skb)
{
struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone;
u8 ptp_cmd = OCELOT_SKB_CB(skb)->ptp_cmd;
u32 rew_op = 0;
if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP && clone) {
rew_op = ptp_cmd;
rew_op |= OCELOT_SKB_CB(clone)->ts_id << 3;
} else if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) {
rew_op = ptp_cmd;
}
return rew_op;
}
#endif #endif
...@@ -89,15 +89,6 @@ ...@@ -89,15 +89,6 @@
/* Source PGIDs, one per physical port */ /* Source PGIDs, one per physical port */
#define PGID_SRC 80 #define PGID_SRC 80
#define IFH_TAG_TYPE_C 0
#define IFH_TAG_TYPE_S 1
#define IFH_REW_OP_NOOP 0x0
#define IFH_REW_OP_DSCP 0x1
#define IFH_REW_OP_ONE_STEP_PTP 0x2
#define IFH_REW_OP_TWO_STEP_PTP 0x3
#define IFH_REW_OP_ORIGIN_PTP 0x5
#define OCELOT_NUM_TC 8 #define OCELOT_NUM_TC 8
#define OCELOT_SPEED_2500 0 #define OCELOT_SPEED_2500 0
...@@ -695,16 +686,6 @@ struct ocelot_policer { ...@@ -695,16 +686,6 @@ struct ocelot_policer {
u32 burst; /* bytes */ u32 burst; /* bytes */
}; };
struct ocelot_skb_cb {
struct sk_buff *clone;
unsigned int ptp_class; /* valid only for clones */
u8 ptp_cmd;
u8 ts_id;
};
#define OCELOT_SKB_CB(skb) \
((struct ocelot_skb_cb *)((skb)->cb))
#define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri)) #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri))
#define ocelot_read_gix(ocelot, reg, gi) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi)) #define ocelot_read_gix(ocelot, reg, gi) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi))
#define ocelot_read_rix(ocelot, reg, ri) __ocelot_read_ix(ocelot, reg, reg##_RSZ * (ri)) #define ocelot_read_rix(ocelot, reg, ri) __ocelot_read_ix(ocelot, reg, reg##_RSZ * (ri))
...@@ -765,7 +746,6 @@ void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, ...@@ -765,7 +746,6 @@ void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp,
int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **skb); int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **skb);
void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp); void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp);
u32 ocelot_ptp_rew_op(struct sk_buff *skb);
#else #else
static inline bool ocelot_can_inject(struct ocelot *ocelot, int grp) static inline bool ocelot_can_inject(struct ocelot *ocelot, int grp)
...@@ -789,10 +769,6 @@ static inline void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp) ...@@ -789,10 +769,6 @@ static inline void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp)
{ {
} }
static inline u32 ocelot_ptp_rew_op(struct sk_buff *skb)
{
return 0;
}
#endif #endif
/* Hardware initialization */ /* Hardware initialization */
......
...@@ -101,8 +101,6 @@ config NET_DSA_TAG_RTL4_A ...@@ -101,8 +101,6 @@ config NET_DSA_TAG_RTL4_A
config NET_DSA_TAG_OCELOT config NET_DSA_TAG_OCELOT
tristate "Tag driver for Ocelot family of switches, using NPI port" tristate "Tag driver for Ocelot family of switches, using NPI port"
depends on MSCC_OCELOT_SWITCH_LIB || \
(MSCC_OCELOT_SWITCH_LIB=n && COMPILE_TEST)
select PACKING select PACKING
help help
Say Y or M if you want to enable NPI tagging for the Ocelot switches Say Y or M if you want to enable NPI tagging for the Ocelot switches
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
/* Copyright 2019 NXP /* Copyright 2019 NXP
*/ */
#include <linux/dsa/ocelot.h> #include <linux/dsa/ocelot.h>
#include <soc/mscc/ocelot.h>
#include "dsa_priv.h" #include "dsa_priv.h"
static void ocelot_xmit_common(struct sk_buff *skb, struct net_device *netdev, static void ocelot_xmit_common(struct sk_buff *skb, struct net_device *netdev,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* that on egress * that on egress
*/ */
#include <linux/dsa/8021q.h> #include <linux/dsa/8021q.h>
#include <linux/dsa/ocelot.h>
#include <soc/mscc/ocelot.h> #include <soc/mscc/ocelot.h>
#include <soc/mscc/ocelot_ptp.h> #include <soc/mscc/ocelot_ptp.h>
#include "dsa_priv.h" #include "dsa_priv.h"
......
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