mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 11:03:07 -04:00
net: dsa: microchip: add KSZ8463 tail tag handling
KSZ8463 uses the KSZ9893 DSA TAG driver. However, the KSZ8463 doesn't use the tail tag to convey timestamps to the host as KSZ9893 does. It uses the reserved fields in the PTP header instead. Add a KSZ8463-specific DSA_TAG driver to handle KSZ8463 timestamps. There is no information in the tail tag to distinguish PTP packets from others so use the ptp_classify_raw() helper to find the PTP packets and extract the timestamp from their PTP headers. Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com> Link: https://patch.msgid.link/20260727-ksz-new-ptp-v3-8-caba39e680e3@bootlin.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
a97c78093e
commit
46e8ceb399
@@ -2966,7 +2966,7 @@ static enum dsa_tag_protocol ksz8463_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port,
|
||||
enum dsa_tag_protocol mp)
|
||||
{
|
||||
return DSA_TAG_PROTO_KSZ9893;
|
||||
return DSA_TAG_PROTO_KSZ8463;
|
||||
}
|
||||
|
||||
static int ksz8463_connect_tag_protocol(struct dsa_switch *ds,
|
||||
@@ -2974,7 +2974,7 @@ static int ksz8463_connect_tag_protocol(struct dsa_switch *ds,
|
||||
{
|
||||
struct ksz_tagger_data *tagger_data;
|
||||
|
||||
if (proto != DSA_TAG_PROTO_KSZ9893)
|
||||
if (proto != DSA_TAG_PROTO_KSZ8463)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
tagger_data = ksz_tagger_data(ds);
|
||||
|
||||
@@ -59,6 +59,7 @@ struct tc_action;
|
||||
#define DSA_TAG_PROTO_MXL_GSW1XX_VALUE 31
|
||||
#define DSA_TAG_PROTO_MXL862_VALUE 32
|
||||
#define DSA_TAG_PROTO_NETC_VALUE 33
|
||||
#define DSA_TAG_PROTO_KSZ8463_VALUE 34
|
||||
|
||||
enum dsa_tag_protocol {
|
||||
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
|
||||
@@ -95,6 +96,7 @@ enum dsa_tag_protocol {
|
||||
DSA_TAG_PROTO_MXL_GSW1XX = DSA_TAG_PROTO_MXL_GSW1XX_VALUE,
|
||||
DSA_TAG_PROTO_MXL862 = DSA_TAG_PROTO_MXL862_VALUE,
|
||||
DSA_TAG_PROTO_NETC = DSA_TAG_PROTO_NETC_VALUE,
|
||||
DSA_TAG_PROTO_KSZ8463 = DSA_TAG_PROTO_KSZ8463_VALUE,
|
||||
};
|
||||
|
||||
struct dsa_switch;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "tag.h"
|
||||
|
||||
#define KSZ8463_NAME "ksz8463"
|
||||
#define KSZ8795_NAME "ksz8795"
|
||||
#define KSZ9477_NAME "ksz9477"
|
||||
#define KSZ9893_NAME "ksz9893"
|
||||
@@ -396,6 +397,70 @@ static const struct dsa_device_ops ksz9893_netdev_ops = {
|
||||
DSA_TAG_DRIVER(ksz9893_netdev_ops);
|
||||
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893, KSZ9893_NAME);
|
||||
|
||||
#define KSZ8463_TAIL_TAG_PRIO GENMASK(4, 3)
|
||||
#define KSZ8463_TAIL_TAG_EG_PORT_M GENMASK(2, 0)
|
||||
|
||||
static struct sk_buff *ksz8463_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
u16 queue_mapping = skb_get_queue_mapping(skb);
|
||||
u8 prio = netdev_txq_to_tc(dev, queue_mapping);
|
||||
|
||||
return ksz_common_xmit(skb, dev, false,
|
||||
FIELD_PREP(KSZ8463_TAIL_TAG_PRIO, prio),
|
||||
0);
|
||||
}
|
||||
|
||||
static struct sk_buff *ksz8463_rcv(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
unsigned int len = KSZ_EGRESS_TAG_LEN;
|
||||
struct ptp_header *ptp_hdr;
|
||||
unsigned int ptp_class;
|
||||
unsigned int port;
|
||||
ktime_t ts;
|
||||
u8 *tag;
|
||||
|
||||
if (skb_linearize(skb)) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
KSZ_SKB_CB(skb)->tstamp = 0;
|
||||
|
||||
/* Tag decoding */
|
||||
tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
|
||||
port = tag[0] & KSZ8463_TAIL_TAG_EG_PORT_M;
|
||||
|
||||
__skb_push(skb, ETH_HLEN);
|
||||
ptp_class = ptp_classify_raw(skb);
|
||||
__skb_pull(skb, ETH_HLEN);
|
||||
if (ptp_class == PTP_CLASS_NONE)
|
||||
goto common_rcv;
|
||||
|
||||
ptp_hdr = ptp_parse_header(skb, ptp_class);
|
||||
if (ptp_hdr) {
|
||||
ts = ksz_decode_tstamp(get_unaligned_be32(&ptp_hdr->reserved2));
|
||||
KSZ_SKB_CB(skb)->tstamp = ts;
|
||||
ptp_hdr->reserved2 = 0;
|
||||
}
|
||||
|
||||
common_rcv:
|
||||
return ksz_common_rcv(skb, dev, port, len);
|
||||
}
|
||||
|
||||
static const struct dsa_device_ops ksz8463_netdev_ops = {
|
||||
.name = KSZ8463_NAME,
|
||||
.proto = DSA_TAG_PROTO_KSZ8463,
|
||||
.xmit = ksz8463_xmit,
|
||||
.rcv = ksz8463_rcv,
|
||||
.connect = ksz_connect,
|
||||
.disconnect = ksz_disconnect,
|
||||
.needed_tailroom = KSZ_INGRESS_TAG_LEN,
|
||||
};
|
||||
|
||||
DSA_TAG_DRIVER(ksz8463_netdev_ops);
|
||||
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8463, KSZ8463_NAME);
|
||||
|
||||
/* For xmit, 2/6 bytes are added before FCS.
|
||||
* ---------------------------------------------------------------------------
|
||||
* DA(6bytes)|SA(6bytes)|....|Data(nbytes)|ts(4bytes)|tag0(1byte)|tag1(1byte)|
|
||||
@@ -468,6 +533,7 @@ DSA_TAG_DRIVER(lan937x_netdev_ops);
|
||||
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_LAN937X, LAN937X_NAME);
|
||||
|
||||
static struct dsa_tag_driver *dsa_tag_driver_array[] = {
|
||||
&DSA_TAG_DRIVER_NAME(ksz8463_netdev_ops),
|
||||
&DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
|
||||
&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
|
||||
&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
|
||||
|
||||
Reference in New Issue
Block a user