From: Bastien Curutchet <bastien.curutchet@bootlin.com>
To: Jakub Kicinski <kuba@kernel.org>
Cc: woojung.huh@microchip.com, UNGLinuxDriver@microchip.com,
andrew@lunn.ch, olteanv@gmail.com, davem@davemloft.net,
edumazet@google.com, pabeni@redhat.com, richardcochran@gmail.com,
linux@armlinux.org.uk, horms@kernel.org,
maxime.chevallier@bootlin.com, pascal.eberhard@se.com,
miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next v3 08/10] net: dsa: microchip: add KSZ8463 tail tag handling
Date: Fri, 31 Jul 2026 11:59:35 +0200 [thread overview]
Message-ID: <f5184c4c-de97-4da3-8b98-aae00b8b9a3b@bootlin.com> (raw)
In-Reply-To: <20260731022344.800383-1-kuba@kernel.org>
Hi,
On 7/31/26 4:23 AM, Jakub Kicinski wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> --- Patch [8]: [PATCH net-next v3 08/10] net: dsa: microchip: add KSZ8463 tail tag handling ---
> commit 20a43ca1297a3640a458d9df2837f23e6b9191ea
> Author: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
>
> net: dsa: microchip: add KSZ8463 tail tag handling
>
> This adds a KSZ8463-specific DSA tag driver so that RX timestamps can be
> taken from the reserved2 field of the PTP header instead of from the tail
> tag, and switches ksz8463_get_tag_protocol() over to the new
> DSA_TAG_PROTO_KSZ8463. A few questions below about the new receive and
> transmit paths.
>
>> diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
>> index 5e5bfc5cae2d..ac9e8ef5774a 100644
>> --- a/drivers/net/dsa/microchip/ksz8.c
>> +++ b/drivers/net/dsa/microchip/ksz8.c
>> @@ -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;
>
> [Severity: Low]
> This changes the user-visible tagging protocol name for KSZ8463 boards,
> which is reachable both through the conduit's sysfs "tagging" attribute and
> through the "dsa-tag-protocol" device tree property.
>
> A board that currently pins the previous default:
>
> dsa-tag-protocol = "ksz9893";
>
> now hits the -EPROTONOSUPPORT return in ksz8463_connect_tag_protocol()
> instead of degrading to the old behaviour. Would it be worth mentioning
> this compatibility aspect in the commit message?
>
I don't have any strong opinion on this.
>>
>> tagger_data = ksz_tagger_data(ds);
>
> [ ... include/net/dsa.h hunks snipped ... ]
>
>> diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
>> index f8b40437c5fa..b4d70ba930dc 100644
>> --- a/net/dsa/tag_ksz.c
>> +++ b/net/dsa/tag_ksz.c
>
> [ ... ]
>
>> @@ -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);
>> +}
>
> [Severity: Medium]
> Is the loss of the tail tag override bit intentional here?
>
Yes it is, it doesn't exist on KSZ8463.
> Until this patch KSZ8463 used ksz9893_xmit(), which passes
> KSZ9893_TAIL_TAG_OVERRIDE (BIT(5)) as the override_mask argument, and
> ksz8795_xmit() likewise passes KSZ8795_TAIL_TAG_OVERRIDE. ksz8463_xmit()
> passes 0, which makes this branch of ksz_common_xmit() dead for the new
> tagger:
>
> if (is_link_local_ether_addr(hdr->h_dest))
> *tag |= override_mask;
>
> Does that mean CPU-injected link-local frames (STP BPDUs, peer delay
> multicast, LLDP) are now subject to normal port state filtering, so a port
> in BLOCKING or LISTENING state drops them?
>
> KSZ8463_TAIL_TAG_PRIO is GENMASK(4, 3), i.e. the same layout as the KSZ9893
> tail tag, which suggests the override bit does exist at BIT(5) on this part.
> The KSZ8463 tail tag layout is not documented anywhere in the driver, so if
> BIT(5) is in fact reserved on this chip, could the change (and the now
> constant override_mask argument) get an explicit note?
>
> [Severity: Medium]
> The do_tstamp = false argument means ksz_xmit_timestamp() never runs for
> KSZ8463, and that is the only consumer of
> KSZ_SKB_CB(skb)->update_correction:
>
> net/dsa/tag_ksz.c:ksz_xmit_timestamp() {
> ...
> /* Set correction field to 0 and update UDP checksum */
> ptp_header_update_correction(skb, ptp_type, ptp_hdr, 0);
> ...
> }
>
> ksz_port_txtstamp() in drivers/net/dsa/microchip/ksz_ptp.c still sets that
> field and returns without cloning, expecting the tagger to do the work:
>
> case PTP_MSGTYPE_PDELAY_RESP:
> if (prt->tstamp_config.tx_type == HWTSTAMP_TX_ONESTEP_P2P) {
> KSZ_SKB_CB(skb)->ptp_type = type;
> KSZ_SKB_CB(skb)->update_correction = true;
> return;
> }
>
> ksz_get_ts_info() also keeps advertising the mode for this chip:
>
> ts->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ONESTEP_P2P);
>
> if (is_lan937x(dev))
> ts->tx_types |= BIT(HWTSTAMP_TX_ON);
>
> So user space can select HWTSTAMP_TX_ONESTEP_P2P on a KSZ8463 port while the
> tag driver performs no correction field handling at all, and
> ksz_port_rxtstamp() still subtracts the ingress timestamp from the
> PDelay_Req correction in that mode. Is the correction field expected to be
> handled entirely in hardware here? If so, could the commit message say so,
> since the xmit side behaviour change is not mentioned?
>
This series only adds support for two step PTP, that's why
ksz_xmit_timestamp() isn't called by the KSZ8463 code path.
>> +
>> +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);
>
> [Severity: Low]
> This isn't a bug, but the DSA core runs the same classifier a few
> instructions later and hands the result to the driver:
>
> net/dsa/tag.c:dsa_skb_defer_rx_timestamp() {
> ...
> __skb_push(skb, ETH_HLEN);
> type = ptp_classify_raw(skb);
> __skb_pull(skb, ETH_HLEN);
> if (type == PTP_CLASS_NONE)
> return false;
> return ds->ops->port_rxtstamp(ds, p->dp->index, skb, type);
> }
>
> and ksz_port_rxtstamp() already calls ptp_parse_header() itself. So every
> received frame on a KSZ8463 conduit now runs the PTP BPF classifier in the
> tagger, even with hardware timestamping disabled, and PTP frames are
> classified twice.
>
> Unlike KSZ9477/KSZ9893, where the timestamp sits in the tail tag and has to
> be consumed before ksz_common_rcv() trims it, ptp_hdr->reserved2 survives
> into ksz_port_rxtstamp() untouched. Could the reserved2 extraction live in
> ksz_port_rxtstamp() instead, where the PTP class is already available?
>
That would mean adding ksz8463-specific handling in the common
ksz_port_rxtstamp() or create a ksz8463_port_rxtstamp() with once again
its load of code duplication.
>> + if (ptp_class == PTP_CLASS_NONE)
>> + goto common_rcv;
>> +
>> + ptp_hdr = ptp_parse_header(skb, ptp_class);
>
> [Severity: Medium]
> Only PTP_CLASS_NONE is filtered here, but the code below interprets the
> frame with the PTPv2 struct ptp_header layout. ptp_classify_raw() also
> returns PTP_CLASS_V1_IPV4/PTP_CLASS_V1_IPV6, as documented in
> include/linux/ptp_classify.h:
>
> * PTP_CLASS_V1_IPV{4,6}, PTP_CLASS_V2_IPV{4,6} or
> * PTP_CLASS_V2_{L2,VLAN}, depending on the packet content.
>
> and the classifier program simply masks the version nibble, so any value
> 1..15 comes back ORed with the encapsulation bits:
>
> net/core/ptp_classifier.c:
> { 0x48, 0, 0, 0x0016 }, /* ldh [22] */
> { 0x54, 0, 0, 0x000f }, /* and #0xf */
> { 0x44, 0, 0, 0x0010 }, /* or #0x10 */
>
> ptp_parse_header() does no version filtering either, it only skips
> VLAN/IP/UDP headers and bounds-checks sizeof(struct ptp_header). For a
> PTPv1 frame, offsets 8..11 are inside the 16-byte subdomain field rather
> than a reserved field, so real header content would be read as a timestamp
> and then zeroed. Should there be a "if (!(ptp_class & PTP_CLASS_V2))" gate
> before the reserved2 access?
>
ksz8463_set_hwtstamp_config() in PATCH 10 refuses PTP V1 so we
explicitly tell userspace that V1 isn't supported.
>> + if (ptp_hdr) {
>> + ts = ksz_decode_tstamp(get_unaligned_be32(&ptp_hdr->reserved2));
>> + KSZ_SKB_CB(skb)->tstamp = ts;
>> + ptp_hdr->reserved2 = 0;
>> + }
>
> [Severity: Medium]
> Is there anything that keeps this from running while the switch PTP unit is
> disabled? The tagger never looks at KSZ_HWTS_EN here, and does not even
> fetch ksz_tagger_private(), while the transmit side in the same file does
> gate on it:
>
> net/dsa/tag_ksz.c:ksz_xmit_timestamp() {
> ...
> if (!test_bit(KSZ_HWTS_EN, &priv->state))
> return;
> ...
> }
>
> That bit is set together with PTP_ENABLE in ksz_ptp_enable_mode():
>
> tagger_data->hwtstamp_set_state(dev->ds, tag_en);
>
> return ksz_rmw16(dev, regs[PTP_MSG_CONF1], PTP_ENABLE,
> tag_en ? PTP_ENABLE : 0);
>
> so "PTP disabled" is the default state, in which the hardware never wrote
> anything into reserved2. In that state, does this code destroy 4 bytes of a
> genuine remote frame (messageTypeSpecific in IEEE 1588-2019) and build
> KSZ_SKB_CB(skb)->tstamp out of remote bytes? ksz_port_rxtstamp() then
> publishes it with no prt->hwts_rx_en test:
>
> drivers/net/dsa/microchip/ksz_ptp.c:ksz_port_rxtstamp() {
> ...
> tstamp = KSZ_SKB_CB(skb)->tstamp;
> memset(hwtstamps, 0, sizeof(*hwtstamps));
> hwtstamps->hwtstamp = ksz_tstamp_reconstruct(dev, tstamp);
> ...
> }
>
> ksz9477_rcv() only trusts the timestamp when the hardware sets
> KSZ9477_PTP_TAG_INDICATION, and the commit message says KSZ8463 provides no
> such indication. For comparison, hellcreek gates on the enable bit before
> touching reserved2, in hellcreek_should_tstamp():
>
> if (!test_bit(HELLCREEK_HWTSTAMP_ENABLED, &ps->state))
> return NULL;
>
> Would the same gating be appropriate here?
>
This is only done when we receive PTP frames because otherwise ptp_hdr
is NULL. I think it's not a big deal to zero-out the reserved area of
PTP frames we received even if the PTP is disabled, this area is very
likely already set to 0 by the peer. Then ksz_port_rxtstamp indeed
reconstructs the timestamp but it also does it for the other switches,
not only for the KSZ8463.
> [Severity: Medium]
> Does the "ptp_hdr->reserved2 = 0" store need checksum bookkeeping? For PTP
> over UDP (advertised by ksz_get_ts_info() through
> HWTSTAMP_FILTER_PTP_V2_L4_EVENT) these 4 bytes are covered by the UDP
> checksum, but neither the checksum field nor skb->csum / skb->ip_summed are
> updated.
>
> On a conduit reporting CHECKSUM_COMPLETE, skb->csum then still describes the
> unmodified bytes and is carried forward by ksz_common_rcv():
>
> if (pskb_trim_rcsum(skb, skb->len - len)) {
>
> In HWTSTAMP_TX_ONESTEP_P2P mode, ksz_port_rxtstamp() additionally calls
> ptp_header_update_correction() on the same frame, which does:
>
> include/linux/ptp_classify.h:ptp_header_update_correction() {
> ...
> uhdr->check = csum_fold(ptp_check_diff8(correction_old, hdr->correction,
> ~csum_unfold(uhdr->check)));
> ...
> skb->ip_summed = CHECKSUM_NONE;
> }
>
> so the stack recomputes the UDP checksum over data whose reserved2 delta was
> never accounted for. If the switch updates the UDP checksum when it inserts
> the timestamp, would PDelay_Req frames then be dropped in udp_rcv()? The
> same file already uses ptp_header_update_correction() from
> ksz_xmit_timestamp() for in-place PTP header edits.
>
This series adds support for two-step PTP on the L2 layer so the IP
checksums won't be involved in the transactions.
Best regards,
Bastien
next prev parent reply other threads:[~2026-07-31 9:59 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 10:20 [PATCH net-next v3 00/10] net: dsa: microchip: add PTP support for KSZ8463 Bastien Curutchet (Schneider Electric)
2026-07-27 10:20 ` [PATCH net-next v3 01/10] net: dsa: microchip: implement ksz8463_setup() Bastien Curutchet (Schneider Electric)
2026-07-31 2:23 ` Jakub Kicinski
2026-07-31 6:57 ` Bastien Curutchet
2026-07-27 10:20 ` [PATCH net-next v3 02/10] net: dsa: microchip: split ksz8_config_cpu_port() Bastien Curutchet (Schneider Electric)
2026-07-27 10:20 ` [PATCH net-next v3 03/10] net: dsa: microchip: allow the use of other IRQ operations Bastien Curutchet (Schneider Electric)
2026-07-27 10:20 ` [PATCH net-next v3 04/10] net: dsa: microchip: add PTP interrupt handling for KSZ8463 Bastien Curutchet (Schneider Electric)
2026-07-31 2:23 ` Jakub Kicinski
2026-07-31 8:41 ` Bastien Curutchet
2026-07-27 10:20 ` [PATCH net-next v3 05/10] net: dsa: microchip: adapt port offset for KSZ8463's PTP register Bastien Curutchet (Schneider Electric)
2026-07-27 10:20 ` [PATCH net-next v3 06/10] net: dsa: tag_ksz: move the KSZ8795 tag handling below ksz_xmit_timestamp() Bastien Curutchet (Schneider Electric)
2026-07-27 10:20 ` [PATCH net-next v3 07/10] net: dsa: tag_ksz: share code for KSZ8795 and KSZ9893 xmit operations Bastien Curutchet (Schneider Electric)
2026-07-31 2:23 ` Jakub Kicinski
2026-07-31 9:14 ` Bastien Curutchet
2026-07-27 10:20 ` [PATCH net-next v3 08/10] net: dsa: microchip: add KSZ8463 tail tag handling Bastien Curutchet (Schneider Electric)
2026-07-31 2:23 ` Jakub Kicinski
2026-07-31 6:15 ` Bastien Curutchet
2026-07-31 2:23 ` Jakub Kicinski
2026-07-31 9:59 ` Bastien Curutchet [this message]
2026-07-27 10:20 ` [PATCH net-next v3 09/10] net: dsa: microchip: explicitly enable detection of L2 PTP frames Bastien Curutchet (Schneider Electric)
2026-07-27 10:20 ` [PATCH net-next v3 10/10] net: dsa: microchip: add two-steps PTP support for KSZ8463 Bastien Curutchet (Schneider Electric)
2026-07-31 2:23 ` Jakub Kicinski
2026-07-31 10:18 ` Bastien Curutchet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f5184c4c-de97-4da3-8b98-aae00b8b9a3b@bootlin.com \
--to=bastien.curutchet@bootlin.com \
--cc=UNGLinuxDriver@microchip.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=maxime.chevallier@bootlin.com \
--cc=miquel.raynal@bootlin.com \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
--cc=pascal.eberhard@se.com \
--cc=richardcochran@gmail.com \
--cc=thomas.petazzoni@bootlin.com \
--cc=woojung.huh@microchip.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox