* [PATCH net-next v4 1/8] net: dsa: microchip: Add support for KSZ8463 global irq
2026-01-27 9:06 [PATCH net-next v4 0/8] net: dsa: microchip: Add PTP support for the KSZ8463 Bastien Curutchet (Schneider Electric)
@ 2026-01-27 9:06 ` Bastien Curutchet (Schneider Electric)
2026-01-27 19:42 ` Maxime Chevallier
2026-01-28 3:03 ` Jakub Kicinski
2026-01-27 9:06 ` [PATCH net-next v4 2/8] net: dsa: microchip: Decorrelate IRQ domain from port Bastien Curutchet (Schneider Electric)
` (6 subsequent siblings)
7 siblings, 2 replies; 25+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-01-27 9:06 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Richard Cochran, Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel, Bastien Curutchet (Schneider Electric)
KSZ8463's interrupt scheme differs from the others KSZ swicthes. Its
global interrupt handling is done through an 'enable irq' register
instead of a 'mask irq' one, so the bit logic to enable/disable
interrupt is reversed. Also its interrupts registers are 16-bits
registers and don't have the same address.
Add ksz8463-specific global interrupt setup function that still relies
on the ksz_irq_common_setup().
Add a check on the device type in the irq_chip operations to adjust the
bit logic for KSZ8463
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz_common.c | 40 +++++++++++++++++++++++++++++-----
drivers/net/dsa/microchip/ksz_common.h | 3 +++
2 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index e5fa1f5fc09b37c1a9d907175f8cd2cd60aee180..82ec7142a02c432f162e472c831faa010c035123 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2817,14 +2817,20 @@ static void ksz_irq_mask(struct irq_data *d)
{
struct ksz_irq *kirq = irq_data_get_irq_chip_data(d);
- kirq->masked |= BIT(d->hwirq);
+ if (ksz_is_ksz8463(kirq->dev))
+ kirq->masked &= ~BIT(d->hwirq);
+ else
+ kirq->masked |= BIT(d->hwirq);
}
static void ksz_irq_unmask(struct irq_data *d)
{
struct ksz_irq *kirq = irq_data_get_irq_chip_data(d);
- kirq->masked &= ~BIT(d->hwirq);
+ if (ksz_is_ksz8463(kirq->dev))
+ kirq->masked |= BIT(d->hwirq);
+ else
+ kirq->masked &= ~BIT(d->hwirq);
}
static void ksz_irq_bus_lock(struct irq_data *d)
@@ -2840,7 +2846,10 @@ static void ksz_irq_bus_sync_unlock(struct irq_data *d)
struct ksz_device *dev = kirq->dev;
int ret;
- ret = ksz_write8(dev, kirq->reg_mask, kirq->masked);
+ if (ksz_is_ksz8463(dev))
+ ret = ksz_write16(dev, kirq->reg_mask, kirq->masked);
+ else
+ ret = ksz_write8(dev, kirq->reg_mask, kirq->masked);
if (ret)
dev_err(dev->dev, "failed to change IRQ mask\n");
@@ -2890,14 +2899,14 @@ static irqreturn_t ksz_irq_thread_fn(int irq, void *dev_id)
unsigned int nhandled = 0;
struct ksz_device *dev;
unsigned int sub_irq;
- u8 data;
+ u16 data;
int ret;
u8 n;
dev = kirq->dev;
/* Read interrupt status register */
- ret = ksz_read8(dev, kirq->reg_status, &data);
+ ret = ksz_read16(dev, kirq->reg_status, &data);
if (ret)
goto out;
@@ -2939,6 +2948,22 @@ static int ksz_irq_common_setup(struct ksz_device *dev, struct ksz_irq *kirq)
return ret;
}
+static int ksz8463_girq_setup(struct dsa_switch *ds)
+{
+ struct ksz_device *dev = ds->priv;
+ struct ksz_irq *girq = &dev->girq;
+
+ girq->nirqs = 15;
+ girq->reg_mask = KSZ8463_REG_IER;
+ girq->reg_status = KSZ8463_REG_ISR;
+ girq->masked = 0;
+ snprintf(girq->name, sizeof(girq->name), "global_irq");
+
+ girq->irq_num = dev->irq;
+
+ return ksz_irq_common_setup(dev, girq);
+}
+
static int ksz_girq_setup(struct ksz_device *dev)
{
struct ksz_irq *girq = &dev->girq;
@@ -3044,7 +3069,10 @@ static int ksz_setup(struct dsa_switch *ds)
p->learning = true;
if (dev->irq > 0) {
- ret = ksz_girq_setup(dev);
+ if (ksz_is_ksz8463(dev))
+ ret = ksz8463_girq_setup(ds);
+ else
+ ret = ksz_girq_setup(dev);
if (ret)
return ret;
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 929aff4c55de5254defdc1afb52b224b3898233b..67a488a3b5787f93f9e2a9266ce04f6611b56bf8 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -839,6 +839,9 @@ static inline bool ksz_is_sgmii_port(struct ksz_device *dev, int port)
#define KSZ87XX_INT_PME_MASK BIT(4)
/* Interrupt */
+#define KSZ8463_REG_ISR 0x190
+#define KSZ8463_REG_IER 0x192
+
#define REG_SW_PORT_INT_STATUS__1 0x001B
#define REG_SW_PORT_INT_MASK__1 0x001F
--
2.52.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH net-next v4 1/8] net: dsa: microchip: Add support for KSZ8463 global irq
2026-01-27 9:06 ` [PATCH net-next v4 1/8] net: dsa: microchip: Add support for KSZ8463 global irq Bastien Curutchet (Schneider Electric)
@ 2026-01-27 19:42 ` Maxime Chevallier
2026-01-28 3:03 ` Jakub Kicinski
1 sibling, 0 replies; 25+ messages in thread
From: Maxime Chevallier @ 2026-01-27 19:42 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric), Woojung Huh,
UNGLinuxDriver, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel
Hi,
On 27/01/2026 10:06, Bastien Curutchet (Schneider Electric) wrote:
> KSZ8463's interrupt scheme differs from the others KSZ swicthes. Its
> global interrupt handling is done through an 'enable irq' register
> instead of a 'mask irq' one, so the bit logic to enable/disable
> interrupt is reversed. Also its interrupts registers are 16-bits
> registers and don't have the same address.
>
> Add ksz8463-specific global interrupt setup function that still relies
> on the ksz_irq_common_setup().
> Add a check on the device type in the irq_chip operations to adjust the
> bit logic for KSZ8463
>
> Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Maxime
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next v4 1/8] net: dsa: microchip: Add support for KSZ8463 global irq
2026-01-27 9:06 ` [PATCH net-next v4 1/8] net: dsa: microchip: Add support for KSZ8463 global irq Bastien Curutchet (Schneider Electric)
2026-01-27 19:42 ` Maxime Chevallier
@ 2026-01-28 3:03 ` Jakub Kicinski
2026-01-28 9:22 ` Bastien Curutchet
1 sibling, 1 reply; 25+ messages in thread
From: Jakub Kicinski @ 2026-01-28 3:03 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric)
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
On Tue, 27 Jan 2026 10:06:43 +0100 Bastien Curutchet (Schneider
Electric) wrote:
> /* Read interrupt status register */
> - ret = ksz_read8(dev, kirq->reg_status, &data);
> + ret = ksz_read16(dev, kirq->reg_status, &data);
AI code review points out that we're potentially over-reading here for
!ksz_is_ksz8463(kirq->dev), I'm assuming the wider read is okay for all
chips? Is this something that'll be obvious to all readers of this code
or should we perhaps leave a relevant comment here? (assuming you need
to respin, not sure its worth a respin by itself)
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next v4 1/8] net: dsa: microchip: Add support for KSZ8463 global irq
2026-01-28 3:03 ` Jakub Kicinski
@ 2026-01-28 9:22 ` Bastien Curutchet
0 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet @ 2026-01-28 9:22 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
Hi Jakub,
On 1/28/26 4:03 AM, Jakub Kicinski wrote:
> On Tue, 27 Jan 2026 10:06:43 +0100 Bastien Curutchet (Schneider
> Electric) wrote:
>> /* Read interrupt status register */
>> - ret = ksz_read8(dev, kirq->reg_status, &data);
>> + ret = ksz_read16(dev, kirq->reg_status, &data);
>
> AI code review points out that we're potentially over-reading here for
> !ksz_is_ksz8463(kirq->dev), I'm assuming the wider read is okay for all
> chips? Is this something that'll be obvious to all readers of this code
> or should we perhaps leave a relevant comment here? (assuming you need
> to respin, not sure its worth a respin by itself)
The loop below this read only iterates over the first kirq->nirqs bits,
so I assume a wider read is fine. I wanted to avoid adding if
(ksz_is_ksz8463()) branches as much as possible.
Indeed, a comment wouldn't hurt here; I'll add one if I need to respin.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH net-next v4 2/8] net: dsa: microchip: Decorrelate IRQ domain from port
2026-01-27 9:06 [PATCH net-next v4 0/8] net: dsa: microchip: Add PTP support for the KSZ8463 Bastien Curutchet (Schneider Electric)
2026-01-27 9:06 ` [PATCH net-next v4 1/8] net: dsa: microchip: Add support for KSZ8463 global irq Bastien Curutchet (Schneider Electric)
@ 2026-01-27 9:06 ` Bastien Curutchet (Schneider Electric)
2026-01-27 9:06 ` [PATCH net-next v4 3/8] net: dsa: microchip: Decorrelate msg_irq index from IRQ bit offset Bastien Curutchet (Schneider Electric)
` (5 subsequent siblings)
7 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-01-27 9:06 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Richard Cochran, Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel, Bastien Curutchet (Schneider Electric)
KSZ8463 has one register holding interrupt bits from both port 1 and 2.
So it has to use one IRQ domain for both of its ports. This conflicts
with the current initialization procedure that ties one IRQ domain to
each port.
Decorrelate IRQ domain from port so a port can use an IRQ domain not
directly related to itself.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz_ptp.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c
index 4a2cc57a628f97bd51fcb11057bc4effda9205dd..3b0dddf918595e9318c9e9779035d5152dcd9dde 100644
--- a/drivers/net/dsa/microchip/ksz_ptp.c
+++ b/drivers/net/dsa/microchip/ksz_ptp.c
@@ -1099,18 +1099,17 @@ static void ksz_ptp_msg_irq_free(struct ksz_port *port, u8 n)
irq_dispose_mapping(ptpmsg_irq->num);
}
-static int ksz_ptp_msg_irq_setup(struct ksz_port *port, u8 n)
+static int ksz_ptp_msg_irq_setup(struct irq_domain *domain, struct ksz_port *port, u8 n)
{
u16 ts_reg[] = {REG_PTP_PORT_PDRESP_TS, REG_PTP_PORT_XDELAY_TS,
REG_PTP_PORT_SYNC_TS};
static const char * const name[] = {"pdresp-msg", "xdreq-msg",
"sync-msg"};
const struct ksz_dev_ops *ops = port->ksz_dev->dev_ops;
- struct ksz_irq *ptpirq = &port->ptpirq;
struct ksz_ptp_irq *ptpmsg_irq;
ptpmsg_irq = &port->ptpmsg_irq[n];
- ptpmsg_irq->num = irq_create_mapping(ptpirq->domain, n);
+ ptpmsg_irq->num = irq_create_mapping(domain, n);
if (!ptpmsg_irq->num)
return -EINVAL;
@@ -1162,7 +1161,7 @@ int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p)
goto out;
for (irq = 0; irq < ptpirq->nirqs; irq++) {
- ret = ksz_ptp_msg_irq_setup(port, irq);
+ ret = ksz_ptp_msg_irq_setup(ptpirq->domain, port, irq);
if (ret)
goto out_ptp_msg;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH net-next v4 3/8] net: dsa: microchip: Decorrelate msg_irq index from IRQ bit offset
2026-01-27 9:06 [PATCH net-next v4 0/8] net: dsa: microchip: Add PTP support for the KSZ8463 Bastien Curutchet (Schneider Electric)
2026-01-27 9:06 ` [PATCH net-next v4 1/8] net: dsa: microchip: Add support for KSZ8463 global irq Bastien Curutchet (Schneider Electric)
2026-01-27 9:06 ` [PATCH net-next v4 2/8] net: dsa: microchip: Decorrelate IRQ domain from port Bastien Curutchet (Schneider Electric)
@ 2026-01-27 9:06 ` Bastien Curutchet (Schneider Electric)
2026-01-27 9:06 ` [PATCH net-next v4 4/8] net: dsa: microchip: Add support for KSZ8463's PTP interrupts Bastien Curutchet (Schneider Electric)
` (4 subsequent siblings)
7 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-01-27 9:06 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Richard Cochran, Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel, Bastien Curutchet (Schneider Electric)
KSZ8463 has one register containing all the PTP-related interrupts from
all ports. So it will use one IRQ domain for all of them, leading to 4
interrupt bits to be dispatched in two ports. Current implementation
doesn't allow to do so because the IRQ bit offset is also used as index
to store the struct ptpmsg_irq in the table held by the port.
Add a new input to the setup() function to independently provide the
interrupt bit offset and the ptpmsg_irq index.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz_ptp.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c
index 3b0dddf918595e9318c9e9779035d5152dcd9dde..ae46ba41c588c076de2c3b70c7c6702ad85263d5 100644
--- a/drivers/net/dsa/microchip/ksz_ptp.c
+++ b/drivers/net/dsa/microchip/ksz_ptp.c
@@ -1099,7 +1099,8 @@ static void ksz_ptp_msg_irq_free(struct ksz_port *port, u8 n)
irq_dispose_mapping(ptpmsg_irq->num);
}
-static int ksz_ptp_msg_irq_setup(struct irq_domain *domain, struct ksz_port *port, u8 n)
+static int ksz_ptp_msg_irq_setup(struct irq_domain *domain, struct ksz_port *port,
+ u8 index, int irq)
{
u16 ts_reg[] = {REG_PTP_PORT_PDRESP_TS, REG_PTP_PORT_XDELAY_TS,
REG_PTP_PORT_SYNC_TS};
@@ -1108,15 +1109,15 @@ static int ksz_ptp_msg_irq_setup(struct irq_domain *domain, struct ksz_port *por
const struct ksz_dev_ops *ops = port->ksz_dev->dev_ops;
struct ksz_ptp_irq *ptpmsg_irq;
- ptpmsg_irq = &port->ptpmsg_irq[n];
- ptpmsg_irq->num = irq_create_mapping(domain, n);
+ ptpmsg_irq = &port->ptpmsg_irq[index];
+ ptpmsg_irq->num = irq_create_mapping(domain, irq);
if (!ptpmsg_irq->num)
return -EINVAL;
ptpmsg_irq->port = port;
- ptpmsg_irq->ts_reg = ops->get_port_addr(port->num, ts_reg[n]);
+ ptpmsg_irq->ts_reg = ops->get_port_addr(port->num, ts_reg[index]);
- strscpy(ptpmsg_irq->name, name[n]);
+ strscpy(ptpmsg_irq->name, name[index]);
return request_threaded_irq(ptpmsg_irq->num, NULL,
ksz_ptp_msg_thread_fn, IRQF_ONESHOT,
@@ -1161,7 +1162,7 @@ int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p)
goto out;
for (irq = 0; irq < ptpirq->nirqs; irq++) {
- ret = ksz_ptp_msg_irq_setup(ptpirq->domain, port, irq);
+ ret = ksz_ptp_msg_irq_setup(ptpirq->domain, port, irq, irq);
if (ret)
goto out_ptp_msg;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH net-next v4 4/8] net: dsa: microchip: Add support for KSZ8463's PTP interrupts
2026-01-27 9:06 [PATCH net-next v4 0/8] net: dsa: microchip: Add PTP support for the KSZ8463 Bastien Curutchet (Schneider Electric)
` (2 preceding siblings ...)
2026-01-27 9:06 ` [PATCH net-next v4 3/8] net: dsa: microchip: Decorrelate msg_irq index from IRQ bit offset Bastien Curutchet (Schneider Electric)
@ 2026-01-27 9:06 ` Bastien Curutchet (Schneider Electric)
2026-01-27 9:06 ` [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling Bastien Curutchet (Schneider Electric)
` (3 subsequent siblings)
7 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-01-27 9:06 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Richard Cochran, Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel, Bastien Curutchet (Schneider Electric)
KSZ8463 PTP interrupts aren't handled by the driver.
The interrupt layout in KSZ8463 has nothing to do with the other
switches:
- all the interrupts of all ports are grouped into one status register
while others have one interrupt register per port
- xdelay_req and pdresp timestamps share one single interrupt bit on the
KSZ8463 while each of them has its own interrupt bit on other switches
Add KSZ8463-specific IRQ setup()/free() functions to support KSZ8463.
Both ports share one IRQ domain held by port n°1.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz_common.c | 49 +++++++++-----
drivers/net/dsa/microchip/ksz_common.h | 2 +
drivers/net/dsa/microchip/ksz_ptp.c | 112 +++++++++++++++++++++++++++++++-
drivers/net/dsa/microchip/ksz_ptp.h | 9 +++
drivers/net/dsa/microchip/ksz_ptp_reg.h | 7 ++
5 files changed, 160 insertions(+), 19 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 82ec7142a02c432f162e472c831faa010c035123..224be307b3417bf30d62da5c94efc6714d914dc6 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3076,15 +3076,21 @@ static int ksz_setup(struct dsa_switch *ds)
if (ret)
return ret;
- dsa_switch_for_each_user_port(dp, dev->ds) {
- ret = ksz_pirq_setup(dev, dp->index);
+ if (ksz_is_ksz8463(dev)) {
+ ret = ksz8463_ptp_irq_setup(ds);
if (ret)
- goto port_release;
-
- if (dev->info->ptp_capable) {
- ret = ksz_ptp_irq_setup(ds, dp->index);
+ goto girq_release;
+ } else {
+ dsa_switch_for_each_user_port(dp, dev->ds) {
+ ret = ksz_pirq_setup(dev, dp->index);
if (ret)
- goto pirq_release;
+ goto port_release;
+
+ if (dev->info->ptp_capable) {
+ ret = ksz_ptp_irq_setup(ds, dp->index);
+ if (ret)
+ goto pirq_release;
+ }
}
}
}
@@ -3119,14 +3125,20 @@ static int ksz_setup(struct dsa_switch *ds)
ksz_ptp_clock_unregister(ds);
port_release:
if (dev->irq > 0) {
- dsa_switch_for_each_user_port_continue_reverse(dp, dev->ds) {
- if (dev->info->ptp_capable)
- ksz_ptp_irq_free(ds, dp->index);
+ if (ksz_is_ksz8463(dev)) {
+ ksz8463_ptp_irq_free(ds);
+ } else {
+ dsa_switch_for_each_user_port_continue_reverse(dp, dev->ds) {
+ if (dev->info->ptp_capable)
+ ksz_ptp_irq_free(ds, dp->index);
pirq_release:
- ksz_irq_free(&dev->ports[dp->index].pirq);
+ ksz_irq_free(&dev->ports[dp->index].pirq);
+ }
}
- ksz_irq_free(&dev->girq);
}
+girq_release:
+ if (dev->irq > 0)
+ ksz_irq_free(&dev->girq);
return ret;
}
@@ -3140,11 +3152,14 @@ static void ksz_teardown(struct dsa_switch *ds)
ksz_ptp_clock_unregister(ds);
if (dev->irq > 0) {
- dsa_switch_for_each_user_port(dp, dev->ds) {
- if (dev->info->ptp_capable)
- ksz_ptp_irq_free(ds, dp->index);
-
- ksz_irq_free(&dev->ports[dp->index].pirq);
+ if (ksz_is_ksz8463(dev)) {
+ ksz8463_ptp_irq_free(ds);
+ } else {
+ dsa_switch_for_each_user_port(dp, dev->ds) {
+ if (dev->info->ptp_capable)
+ ksz_ptp_irq_free(ds, dp->index);
+ ksz_irq_free(&dev->ports[dp->index].pirq);
+ }
}
ksz_irq_free(&dev->girq);
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 67a488a3b5787f93f9e2a9266ce04f6611b56bf8..dfbc3d13daca8d7a8b9d3ffe6a7c1ec9927863f2 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -851,6 +851,8 @@ static inline bool ksz_is_sgmii_port(struct ksz_device *dev, int port)
#define PORT_SRC_PHY_INT 1
#define PORT_SRC_PTP_INT 2
+#define KSZ8463_SRC_PTP_INT 12
+
#define KSZ8795_HUGE_PACKET_SIZE 2000
#define KSZ8863_HUGE_PACKET_SIZE 1916
#define KSZ8863_NORMAL_PACKET_SIZE 1536
diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c
index ae46ba41c588c076de2c3b70c7c6702ad85263d5..5daadf62689e6d60ab32e7a5a6c1f3fac3024b87 100644
--- a/drivers/net/dsa/microchip/ksz_ptp.c
+++ b/drivers/net/dsa/microchip/ksz_ptp.c
@@ -31,6 +31,9 @@
#define KSZ_PTP_SUBNS_BITS 32
#define KSZ_PTP_INT_START 13
+#define KSZ8463_PTP_PORT1_INT_START 12
+#define KSZ8463_PTP_PORT2_INT_START 14
+#define KSZ8463_PTP_INT_START KSZ8463_PTP_PORT1_INT_START
static int ksz_ptp_tou_gpio(struct ksz_device *dev)
{
@@ -1102,6 +1105,7 @@ static void ksz_ptp_msg_irq_free(struct ksz_port *port, u8 n)
static int ksz_ptp_msg_irq_setup(struct irq_domain *domain, struct ksz_port *port,
u8 index, int irq)
{
+ static const char * const ksz8463_name[] = {"sync-msg", "delay-msg"};
u16 ts_reg[] = {REG_PTP_PORT_PDRESP_TS, REG_PTP_PORT_XDELAY_TS,
REG_PTP_PORT_SYNC_TS};
static const char * const name[] = {"pdresp-msg", "xdreq-msg",
@@ -1115,15 +1119,106 @@ static int ksz_ptp_msg_irq_setup(struct irq_domain *domain, struct ksz_port *por
return -EINVAL;
ptpmsg_irq->port = port;
- ptpmsg_irq->ts_reg = ops->get_port_addr(port->num, ts_reg[index]);
- strscpy(ptpmsg_irq->name, name[index]);
+ if (ksz_is_ksz8463(port->ksz_dev)) {
+ ts_reg[0] = KSZ8463_REG_PORT_SYNC_TS;
+ ts_reg[1] = KSZ8463_REG_PORT_DREQ_TS;
+ strscpy(ptpmsg_irq->name, ksz8463_name[index]);
+ } else {
+ strscpy(ptpmsg_irq->name, name[index]);
+ }
+
+ ptpmsg_irq->ts_reg = ops->get_port_addr(port->num, ts_reg[index]);
return request_threaded_irq(ptpmsg_irq->num, NULL,
ksz_ptp_msg_thread_fn, IRQF_ONESHOT,
ptpmsg_irq->name, ptpmsg_irq);
}
+static int ksz8463_ptp_port_irq_setup(struct ksz_irq *ptpirq, struct ksz_port *port, int hw_irq)
+{
+ int ret;
+ int i;
+
+ init_completion(&port->tstamp_msg_comp);
+
+ for (i = 0; i < 2; i++) {
+ ret = ksz_ptp_msg_irq_setup(ptpirq->domain, port, i, hw_irq++);
+ if (ret)
+ goto release_msg_irq;
+ }
+
+ return 0;
+
+release_msg_irq:
+ while (i--)
+ ksz_ptp_msg_irq_free(port, i);
+
+ return ret;
+}
+
+static void ksz8463_ptp_port_irq_teardown(struct ksz_port *port)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ ksz_ptp_msg_irq_free(port, i);
+}
+
+int ksz8463_ptp_irq_setup(struct dsa_switch *ds)
+{
+ struct ksz_device *dev = ds->priv;
+ struct ksz_port *port1, *port2;
+ struct ksz_irq *ptpirq;
+ int ret;
+
+ port1 = &dev->ports[0];
+ port2 = &dev->ports[1];
+ ptpirq = &port1->ptpirq;
+
+ ptpirq->irq_num = irq_find_mapping(dev->girq.domain, KSZ8463_SRC_PTP_INT);
+ if (!ptpirq->irq_num)
+ return -EINVAL;
+
+ ptpirq->dev = dev;
+ ptpirq->nirqs = 4;
+ ptpirq->reg_mask = KSZ8463_PTP_TS_IER;
+ ptpirq->reg_status = KSZ8463_PTP_TS_ISR;
+ ptpirq->irq0_offset = KSZ8463_PTP_INT_START;
+ snprintf(ptpirq->name, sizeof(ptpirq->name), "ptp-irq");
+
+ ptpirq->domain = irq_domain_create_linear(dev_fwnode(dev->dev), ptpirq->nirqs,
+ &ksz_ptp_irq_domain_ops, ptpirq);
+ if (!ptpirq->domain)
+ return -ENOMEM;
+
+ ret = request_threaded_irq(ptpirq->irq_num, NULL, ksz_ptp_irq_thread_fn,
+ IRQF_ONESHOT, ptpirq->name, ptpirq);
+ if (ret)
+ goto release_domain;
+
+ ret = ksz8463_ptp_port_irq_setup(ptpirq, port1,
+ KSZ8463_PTP_PORT1_INT_START - KSZ8463_PTP_INT_START);
+ if (ret)
+ goto release_irq;
+
+ ret = ksz8463_ptp_port_irq_setup(ptpirq, port2,
+ KSZ8463_PTP_PORT2_INT_START - KSZ8463_PTP_INT_START);
+ if (ret)
+ goto free_port1;
+
+ return 0;
+
+free_port1:
+ ksz8463_ptp_port_irq_teardown(port1);
+release_irq:
+ free_irq(ptpirq->irq_num, ptpirq);
+release_domain:
+ irq_domain_remove(ptpirq->domain);
+
+ return ret;
+}
+
int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p)
{
struct ksz_device *dev = ds->priv;
@@ -1181,6 +1276,19 @@ int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p)
return ret;
}
+void ksz8463_ptp_irq_free(struct dsa_switch *ds)
+{
+ struct ksz_device *dev = ds->priv;
+ struct ksz_port *port1 = &dev->ports[0];
+ struct ksz_port *port2 = &dev->ports[1];
+ struct ksz_irq *ptpirq = &port1->ptpirq;
+
+ ksz8463_ptp_port_irq_teardown(port1);
+ ksz8463_ptp_port_irq_teardown(port2);
+ free_irq(ptpirq->irq_num, ptpirq);
+ irq_domain_remove(ptpirq->domain);
+}
+
void ksz_ptp_irq_free(struct dsa_switch *ds, u8 p)
{
struct ksz_device *dev = ds->priv;
diff --git a/drivers/net/dsa/microchip/ksz_ptp.h b/drivers/net/dsa/microchip/ksz_ptp.h
index 3086e519b1b641e9e4126cb6ff43409f6d7f29a5..46494caacc4287b845b8e5c3a68bcfc7a03bcf9d 100644
--- a/drivers/net/dsa/microchip/ksz_ptp.h
+++ b/drivers/net/dsa/microchip/ksz_ptp.h
@@ -48,6 +48,8 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb);
void ksz_port_deferred_xmit(struct kthread_work *work);
bool ksz_port_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb,
unsigned int type);
+int ksz8463_ptp_irq_setup(struct dsa_switch *ds);
+void ksz8463_ptp_irq_free(struct dsa_switch *ds);
int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p);
void ksz_ptp_irq_free(struct dsa_switch *ds, u8 p);
@@ -65,6 +67,13 @@ static inline int ksz_ptp_clock_register(struct dsa_switch *ds)
static inline void ksz_ptp_clock_unregister(struct dsa_switch *ds) { }
+static inline int ksz8463_ptp_irq_setup(struct dsa_switch *ds)
+{
+ return 0;
+}
+
+static inline void ksz8463_ptp_irq_free(struct dsa_switch *ds) {}
+
static inline int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p)
{
return 0;
diff --git a/drivers/net/dsa/microchip/ksz_ptp_reg.h b/drivers/net/dsa/microchip/ksz_ptp_reg.h
index eab9aecb7fa8a50323de4140695b2004d1beab8c..e80fb4bd1a0e970ba3570374d3dc82c8e2cc15b4 100644
--- a/drivers/net/dsa/microchip/ksz_ptp_reg.h
+++ b/drivers/net/dsa/microchip/ksz_ptp_reg.h
@@ -121,6 +121,10 @@
#define REG_PTP_PORT_SYNC_TS 0x0C0C
#define REG_PTP_PORT_PDRESP_TS 0x0C10
+#define KSZ8463_REG_PORT_DREQ_TS 0x0648
+#define KSZ8463_REG_PORT_SYNC_TS 0x064C
+#define KSZ8463_REG_PORT_DRESP_TS 0x0650
+
#define REG_PTP_PORT_TX_INT_STATUS__2 0x0C14
#define REG_PTP_PORT_TX_INT_ENABLE__2 0x0C16
@@ -131,4 +135,7 @@
#define KSZ_XDREQ_MSG 1
#define KSZ_PDRES_MSG 0
+#define KSZ8463_PTP_TS_ISR 0x68C
+#define KSZ8463_PTP_TS_IER 0x68E
+
#endif
--
2.52.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling
2026-01-27 9:06 [PATCH net-next v4 0/8] net: dsa: microchip: Add PTP support for the KSZ8463 Bastien Curutchet (Schneider Electric)
` (3 preceding siblings ...)
2026-01-27 9:06 ` [PATCH net-next v4 4/8] net: dsa: microchip: Add support for KSZ8463's PTP interrupts Bastien Curutchet (Schneider Electric)
@ 2026-01-27 9:06 ` Bastien Curutchet (Schneider Electric)
2026-01-30 4:15 ` Jakub Kicinski
2026-02-02 13:29 ` Vladimir Oltean
2026-01-27 9:06 ` [PATCH net-next v4 6/8] net: dsa: microchip: Enable Ethernet PTP detection Bastien Curutchet (Schneider Electric)
` (2 subsequent siblings)
7 siblings, 2 replies; 25+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-01-27 9:06 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Richard Cochran, Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel, Bastien Curutchet (Schneider Electric)
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-specifig 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>
---
drivers/net/dsa/microchip/ksz_common.c | 5 ++-
include/net/dsa.h | 2 +
net/dsa/tag_ksz.c | 70 ++++++++++++++++++++++++++++++++++
3 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 224be307b3417bf30d62da5c94efc6714d914dc6..5141343d2f40bbd380c0b52f6919b842fb71a8fd 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3580,8 +3580,10 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev))
proto = DSA_TAG_PROTO_KSZ8795;
+ if (dev->chip_id == KSZ8463_CHIP_ID)
+ proto = DSA_TAG_PROTO_KSZ8463;
+
if (dev->chip_id == KSZ88X3_CHIP_ID ||
- dev->chip_id == KSZ8463_CHIP_ID ||
dev->chip_id == KSZ8563_CHIP_ID ||
dev->chip_id == KSZ9893_CHIP_ID ||
dev->chip_id == KSZ9563_CHIP_ID)
@@ -3611,6 +3613,7 @@ static int ksz_connect_tag_protocol(struct dsa_switch *ds,
return 0;
case DSA_TAG_PROTO_KSZ9893:
case DSA_TAG_PROTO_KSZ9477:
+ case DSA_TAG_PROTO_KSZ8463:
case DSA_TAG_PROTO_LAN937X:
tagger_data = ksz_tagger_data(ds);
tagger_data->xmit_work_fn = ksz_port_deferred_xmit;
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 6b2b5ed64ea4cee6ab59c9e6eaab30f07f82816a..5b5fed6e6f9171f5875d61c1395758065ac5808a 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -57,6 +57,7 @@ struct tc_action;
#define DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE 29
#define DSA_TAG_PROTO_YT921X_VALUE 30
#define DSA_TAG_PROTO_MXL_GSW1XX_VALUE 31
+#define DSA_TAG_PROTO_KSZ8463_VALUE 32
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
@@ -91,6 +92,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_VSC73XX_8021Q = DSA_TAG_PROTO_VSC73XX_8021Q_VALUE,
DSA_TAG_PROTO_YT921X = DSA_TAG_PROTO_YT921X_VALUE,
DSA_TAG_PROTO_MXL_GSW1XX = DSA_TAG_PROTO_MXL_GSW1XX_VALUE,
+ DSA_TAG_PROTO_KSZ8463 = DSA_TAG_PROTO_KSZ8463_VALUE,
};
struct dsa_switch;
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index 9170a0148cc43b4213ec4bd8e81d338589671f23..f6590549908e016ca224501e6bc296c9c5feafb3 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -16,6 +16,7 @@
#define KSZ9477_NAME "ksz9477"
#define KSZ9893_NAME "ksz9893"
#define LAN937X_NAME "lan937x"
+#define KSZ8463_NAME "ksz8463"
/* Typically only one byte is used for tail tag. */
#define KSZ_PTP_TAG_LEN 4
@@ -383,6 +384,74 @@ 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);
+ struct dsa_port *dp = dsa_user_to_port(dev);
+ u8 *tag;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+ return NULL;
+
+ tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
+
+ *tag = BIT(dp->index);
+ *tag |= FIELD_PREP(KSZ8463_TAIL_TAG_PRIO, prio);
+
+ return ksz_defer_xmit(dp, skb);
+}
+
+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 tstamp;
+ u8 *tag;
+
+ if (skb_linearize(skb))
+ return NULL;
+
+ /* 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) {
+ tstamp = ksz_decode_tstamp(get_unaligned_be32(&ptp_hdr->reserved2));
+ KSZ_SKB_CB(skb)->tstamp = tstamp;
+ 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)|
@@ -457,6 +526,7 @@ static struct dsa_tag_driver *dsa_tag_driver_array[] = {
&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
&DSA_TAG_DRIVER_NAME(lan937x_netdev_ops),
+ &DSA_TAG_DRIVER_NAME(ksz8463_netdev_ops),
};
module_dsa_tag_drivers(dsa_tag_driver_array);
--
2.52.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling
2026-01-27 9:06 ` [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling Bastien Curutchet (Schneider Electric)
@ 2026-01-30 4:15 ` Jakub Kicinski
2026-02-18 9:35 ` Bastien Curutchet
2026-02-02 13:29 ` Vladimir Oltean
1 sibling, 1 reply; 25+ messages in thread
From: Jakub Kicinski @ 2026-01-30 4:15 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric)
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
Sorry for the nit but:
On Tue, 27 Jan 2026 10:06:47 +0100 Bastien Curutchet (Schneider
Electric) wrote:
> case DSA_TAG_PROTO_KSZ9893:
> case DSA_TAG_PROTO_KSZ9477:
> + case DSA_TAG_PROTO_KSZ8463:
> case DSA_TAG_PROTO_LAN937X:
This..
> #define KSZ9477_NAME "ksz9477"
> #define KSZ9893_NAME "ksz9893"
> #define LAN937X_NAME "lan937x"
> +#define KSZ8463_NAME "ksz8463"
this
> @@ -457,6 +526,7 @@ static struct dsa_tag_driver *dsa_tag_driver_array[] = {
> &DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
> &DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
> &DSA_TAG_DRIVER_NAME(lan937x_netdev_ops),
> + &DSA_TAG_DRIVER_NAME(ksz8463_netdev_ops),
and this - appear to have been alphabetically sorted previously, now
we're just adding at the end.
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling
2026-01-30 4:15 ` Jakub Kicinski
@ 2026-02-18 9:35 ` Bastien Curutchet
0 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet @ 2026-02-18 9:35 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
Hi Jakub,
On 1/30/26 5:15 AM, Jakub Kicinski wrote:
> Sorry for the nit but:
>
> On Tue, 27 Jan 2026 10:06:47 +0100 Bastien Curutchet (Schneider
> Electric) wrote:
>> case DSA_TAG_PROTO_KSZ9893:
>> case DSA_TAG_PROTO_KSZ9477:
>> + case DSA_TAG_PROTO_KSZ8463:
>> case DSA_TAG_PROTO_LAN937X:
>
> This..
>
>> #define KSZ9477_NAME "ksz9477"
>> #define KSZ9893_NAME "ksz9893"
>> #define LAN937X_NAME "lan937x"
>> +#define KSZ8463_NAME "ksz8463"
>
> this
>
>> @@ -457,6 +526,7 @@ static struct dsa_tag_driver *dsa_tag_driver_array[] = {
>> &DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
>> &DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
>> &DSA_TAG_DRIVER_NAME(lan937x_netdev_ops),
>> + &DSA_TAG_DRIVER_NAME(ksz8463_netdev_ops),
>
> and this - appear to have been alphabetically sorted previously, now
> we're just adding at the end.
Good catch, I'll fix this in next iteration (once net-next re-opens).
Best regards,
Bastien
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling
2026-01-27 9:06 ` [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling Bastien Curutchet (Schneider Electric)
2026-01-30 4:15 ` Jakub Kicinski
@ 2026-02-02 13:29 ` Vladimir Oltean
2026-02-18 9:36 ` Bastien Curutchet
1 sibling, 1 reply; 25+ messages in thread
From: Vladimir Oltean @ 2026-02-02 13:29 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric)
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
On Tue, Jan 27, 2026 at 10:06:47AM +0100, Bastien Curutchet (Schneider Electric) wrote:
> @@ -383,6 +384,74 @@ 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);
> + struct dsa_port *dp = dsa_user_to_port(dev);
> + u8 *tag;
> +
> + if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
> + return NULL;
> +
> + tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
> +
> + *tag = BIT(dp->index);
You're out of sync with mainline which has transitioned all
BIT(dp->index) users to dsa_xmit_port_mask(skb, dev).
To avoid this in the future please do not duplicate the ksz9893 xmit
implementation, but call a common function and use a "bool do_tstamp"
variable which is true when called from ksz9893 and false from ksz8463.
> + *tag |= FIELD_PREP(KSZ8463_TAIL_TAG_PRIO, prio);
> +
> + return ksz_defer_xmit(dp, skb);
> +}
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling
2026-02-02 13:29 ` Vladimir Oltean
@ 2026-02-18 9:36 ` Bastien Curutchet
0 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet @ 2026-02-18 9:36 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
Hi Vladimir,
On 2/2/26 2:29 PM, Vladimir Oltean wrote:
> On Tue, Jan 27, 2026 at 10:06:47AM +0100, Bastien Curutchet (Schneider Electric) wrote:
>> @@ -383,6 +384,74 @@ 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);
>> + struct dsa_port *dp = dsa_user_to_port(dev);
>> + u8 *tag;
>> +
>> + if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
>> + return NULL;
>> +
>> + tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
>> +
>> + *tag = BIT(dp->index);
>
> You're out of sync with mainline which has transitioned all
> BIT(dp->index) users to dsa_xmit_port_mask(skb, dev).
>
> To avoid this in the future please do not duplicate the ksz9893 xmit
> implementation, but call a common function and use a "bool do_tstamp"
> variable which is true when called from ksz9893 and false from ksz8463.
>
Ok, I'll do it, thank you.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH net-next v4 6/8] net: dsa: microchip: Enable Ethernet PTP detection
2026-01-27 9:06 [PATCH net-next v4 0/8] net: dsa: microchip: Add PTP support for the KSZ8463 Bastien Curutchet (Schneider Electric)
` (4 preceding siblings ...)
2026-01-27 9:06 ` [PATCH net-next v4 5/8] net: dsa: microchip: Add KSZ8463 tail tag handling Bastien Curutchet (Schneider Electric)
@ 2026-01-27 9:06 ` Bastien Curutchet (Schneider Electric)
2026-01-30 4:17 ` Jakub Kicinski
2026-01-27 9:06 ` [PATCH net-next v4 7/8] net: dsa: microchip: Adapt port offset for KSZ8463's PTP register Bastien Curutchet (Schneider Electric)
2026-01-27 9:06 ` [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463 Bastien Curutchet (Schneider Electric)
7 siblings, 1 reply; 25+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-01-27 9:06 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Richard Cochran, Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel, Bastien Curutchet (Schneider Electric)
KSZ8463 needs to enable the Ethernet PTP detection to fire the
interrupts when a timestamp is captured.
Enable Ethernet PTP detection.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz_ptp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c
index 5daadf62689e6d60ab32e7a5a6c1f3fac3024b87..7eb033157f226b1169bc184d71569328e9a20a5b 100644
--- a/drivers/net/dsa/microchip/ksz_ptp.c
+++ b/drivers/net/dsa/microchip/ksz_ptp.c
@@ -947,8 +947,8 @@ int ksz_ptp_clock_register(struct dsa_switch *ds)
/* Currently only P2P mode is supported. When 802_1AS bit is set, it
* forwards all PTP packets to host port and none to other ports.
*/
- ret = ksz_rmw16(dev, regs[PTP_MSG_CONF1], PTP_TC_P2P | PTP_802_1AS,
- PTP_TC_P2P | PTP_802_1AS);
+ ret = ksz_rmw16(dev, regs[PTP_MSG_CONF1], PTP_TC_P2P | PTP_802_1AS | PTP_ETH_ENABLE,
+ PTP_TC_P2P | PTP_802_1AS | PTP_ETH_ENABLE);
if (ret)
return ret;
--
2.52.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH net-next v4 6/8] net: dsa: microchip: Enable Ethernet PTP detection
2026-01-27 9:06 ` [PATCH net-next v4 6/8] net: dsa: microchip: Enable Ethernet PTP detection Bastien Curutchet (Schneider Electric)
@ 2026-01-30 4:17 ` Jakub Kicinski
2026-01-30 5:16 ` Tristram.Ha
0 siblings, 1 reply; 25+ messages in thread
From: Jakub Kicinski @ 2026-01-30 4:17 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric)
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
On Tue, 27 Jan 2026 10:06:48 +0100 Bastien Curutchet (Schneider
Electric) wrote:
> KSZ8463 needs to enable the Ethernet PTP detection to fire the
> interrupts when a timestamp is captured.
Is it worth stating our expectation WRT other switches given this
is a shared function (not advocating to add a condition to be clear,
just document).
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH net-next v4 6/8] net: dsa: microchip: Enable Ethernet PTP detection
2026-01-30 4:17 ` Jakub Kicinski
@ 2026-01-30 5:16 ` Tristram.Ha
2026-02-18 10:22 ` Bastien Curutchet
0 siblings, 1 reply; 25+ messages in thread
From: Tristram.Ha @ 2026-01-30 5:16 UTC (permalink / raw)
To: kuba, bastien.curutchet
Cc: Woojung.Huh, UNGLinuxDriver, andrew, olteanv, davem, edumazet,
pabeni, richardcochran, horms, pascal.eberhard, miquel.raynal,
thomas.petazzoni, netdev, linux-kernel
> On Tue, 27 Jan 2026 10:06:48 +0100 Bastien Curutchet (Schneider
> Electric) wrote:
> > KSZ8463 needs to enable the Ethernet PTP detection to fire the
> > interrupts when a timestamp is captured.
>
> Is it worth stating our expectation WRT other switches given this
> is a shared function (not advocating to add a condition to be clear,
> just document).
KSZ8464 uses the first generation of PTP engine while KSZ9477/KSZ9567 and
LAN937X use the second generation. Most of their basic operations like
transmitting are the same. KSZ8463 enables 1-step E2E TC operation by
default while the newer switches need to enable the function manually.
Because of that the PTP function in KSZ8463 is disabled after driver
starts until the Linux PTP stack wants to enable the feature.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next v4 6/8] net: dsa: microchip: Enable Ethernet PTP detection
2026-01-30 5:16 ` Tristram.Ha
@ 2026-02-18 10:22 ` Bastien Curutchet
0 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet @ 2026-02-18 10:22 UTC (permalink / raw)
To: Tristram.Ha, kuba
Cc: Woojung.Huh, UNGLinuxDriver, andrew, olteanv, davem, edumazet,
pabeni, richardcochran, horms, pascal.eberhard, miquel.raynal,
thomas.petazzoni, netdev, linux-kernel
Hi,
On 1/30/26 6:16 AM, Tristram.Ha@microchip.com wrote:
>> On Tue, 27 Jan 2026 10:06:48 +0100 Bastien Curutchet (Schneider
>> Electric) wrote:
>>> KSZ8463 needs to enable the Ethernet PTP detection to fire the
>>> interrupts when a timestamp is captured.
>>
>> Is it worth stating our expectation WRT other switches given this
>> is a shared function (not advocating to add a condition to be clear,
>> just document).
The PTP_ETH_ENABLE bit added here is already set by default on the
'second generation' switches Tristram mentioned but not on the KSZ8463.
I'll add details to the commit log.
>
> KSZ8464 uses the first generation of PTP engine while KSZ9477/KSZ9567 and
> LAN937X use the second generation. Most of their basic operations like
> transmitting are the same. KSZ8463 enables 1-step E2E TC operation by
> default while the newer switches need to enable the function manually.
> Because of that the PTP function in KSZ8463 is disabled after driver
> starts until the Linux PTP stack wants to enable the feature.
>
I think that here you refer to the PTP_ENABLE bit. It's indeed unset at
init in ksz8_config_cpu_port() but it's then set back by
ksz_ptp_enable_mode() when needed.
PTP_ETH_ENABLE (bit 5) enables detection of L2 PTP frames
PTP_ENABLE (bit 6) enables the full PTP feature.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH net-next v4 7/8] net: dsa: microchip: Adapt port offset for KSZ8463's PTP register
2026-01-27 9:06 [PATCH net-next v4 0/8] net: dsa: microchip: Add PTP support for the KSZ8463 Bastien Curutchet (Schneider Electric)
` (5 preceding siblings ...)
2026-01-27 9:06 ` [PATCH net-next v4 6/8] net: dsa: microchip: Enable Ethernet PTP detection Bastien Curutchet (Schneider Electric)
@ 2026-01-27 9:06 ` Bastien Curutchet (Schneider Electric)
2026-01-27 9:06 ` [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463 Bastien Curutchet (Schneider Electric)
7 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-01-27 9:06 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Richard Cochran, Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel, Bastien Curutchet (Schneider Electric)
In KSZ8463 register's layout, the offset between port 1 and port 2
registers isn't the same in the generic control register area than in
the PTP register area. The get_port_addr() always uses the same offset
so it doesn't work when it's used to access PTP registers.
Adapt the port offset in get_port_addr() when the accessed register is
in the PTP area.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index c354abdafc1b542a32c276ef939a90db30c67f55..a05527899b8bab6d53509ba38c58101b79e98ee5 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -2020,6 +2020,9 @@ u32 ksz8_get_port_addr(int port, int offset)
u32 ksz8463_get_port_addr(int port, int offset)
{
+ if (offset >= KSZ8463_PTP_CLK_CTRL)
+ return offset + 0x20 * port;
+
return offset + 0x18 * port;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463
2026-01-27 9:06 [PATCH net-next v4 0/8] net: dsa: microchip: Add PTP support for the KSZ8463 Bastien Curutchet (Schneider Electric)
` (6 preceding siblings ...)
2026-01-27 9:06 ` [PATCH net-next v4 7/8] net: dsa: microchip: Adapt port offset for KSZ8463's PTP register Bastien Curutchet (Schneider Electric)
@ 2026-01-27 9:06 ` Bastien Curutchet (Schneider Electric)
2026-02-02 13:43 ` Vladimir Oltean
7 siblings, 1 reply; 25+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-01-27 9:06 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Richard Cochran, Simon Horman
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni, netdev,
linux-kernel, Bastien Curutchet (Schneider Electric)
The KSZ8463 switch supports PTP but it's not supported by driver.
Add L2 two-step PTP support for the KSZ8463. IPv4 and IPv6 layers aren't
supported. Neither is one-step PTP.
The pdelay_req and pdelay_resp timestamps share one interrupt bit status.
So introduce last_tx_is_pdelayresp to keep track of the last sent event
type. Use it to retrieve the relevant timestamp when the interrupt is
caught.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 9 ++----
drivers/net/dsa/microchip/ksz8_reg.h | 1 +
drivers/net/dsa/microchip/ksz_common.c | 1 +
drivers/net/dsa/microchip/ksz_common.h | 1 +
drivers/net/dsa/microchip/ksz_ptp.c | 52 ++++++++++++++++++++++++++-------
drivers/net/dsa/microchip/ksz_ptp_reg.h | 4 +++
6 files changed, 51 insertions(+), 17 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index a05527899b8bab6d53509ba38c58101b79e98ee5..f4dfdbd52b9daeab8a0134fb09cf4c960d9d9409 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -143,9 +143,9 @@ int ksz8_reset_switch(struct ksz_device *dev)
KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, false);
} else if (ksz_is_ksz8463(dev)) {
ksz_cfg(dev, KSZ8463_REG_SW_RESET,
- KSZ8463_GLOBAL_SOFTWARE_RESET, true);
+ KSZ8463_GLOBAL_SOFTWARE_RESET | KSZ8463_PTP_SOFTWARE_RESET, true);
ksz_cfg(dev, KSZ8463_REG_SW_RESET,
- KSZ8463_GLOBAL_SOFTWARE_RESET, false);
+ KSZ8463_GLOBAL_SOFTWARE_RESET | KSZ8463_PTP_SOFTWARE_RESET, false);
} else {
/* reset switch */
ksz_write8(dev, REG_POWER_MANAGEMENT_1,
@@ -1763,10 +1763,7 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)
COPPER_RECEIVE_ADJUSTMENT, 0);
}
- /* Turn off PTP function as the switch's proprietary way of
- * handling timestamp is not supported in current Linux PTP
- * stack implementation.
- */
+ /* Turn off PTP function as the switch enables it by default */
regmap_update_bits(ksz_regmap_16(dev),
KSZ8463_PTP_MSG_CONF1,
PTP_ENABLE, 0);
diff --git a/drivers/net/dsa/microchip/ksz8_reg.h b/drivers/net/dsa/microchip/ksz8_reg.h
index 332408567b473c141c3695328a524f257f2cfc70..0558740ae57738fa7e4a8f3f429254033c54af12 100644
--- a/drivers/net/dsa/microchip/ksz8_reg.h
+++ b/drivers/net/dsa/microchip/ksz8_reg.h
@@ -765,6 +765,7 @@
#define KSZ8463_REG_SW_RESET 0x126
#define KSZ8463_GLOBAL_SOFTWARE_RESET BIT(0)
+#define KSZ8463_PTP_SOFTWARE_RESET BIT(2)
#define KSZ8463_PTP_CLK_CTRL 0x600
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 5141343d2f40bbd380c0b52f6919b842fb71a8fd..55e3fa4791078cb099e236e6e5a29515727ed8ab 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -1512,6 +1512,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.supports_mii = {false, false, true},
.supports_rmii = {false, false, true},
.internal_phy = {true, true, false},
+ .ptp_capable = true,
},
[KSZ8563] = {
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index dfbc3d13daca8d7a8b9d3ffe6a7c1ec9927863f2..1fface82086eed87749d4702b046fcab313663e9 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -150,6 +150,7 @@ struct ksz_port {
struct kernel_hwtstamp_config tstamp_config;
bool hwts_tx_en;
bool hwts_rx_en;
+ bool last_tx_is_pdelayresp;
struct ksz_irq ptpirq;
struct ksz_ptp_irq ptpmsg_irq[3];
ktime_t tstamp_msg;
diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c
index 7eb033157f226b1169bc184d71569328e9a20a5b..a86d087b4c0d05120ba532a221e66bc704d1dfb5 100644
--- a/drivers/net/dsa/microchip/ksz_ptp.c
+++ b/drivers/net/dsa/microchip/ksz_ptp.c
@@ -308,15 +308,20 @@ int ksz_get_ts_info(struct dsa_switch *ds, int port, struct kernel_ethtool_ts_in
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
- ts->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ONESTEP_P2P);
+ ts->tx_types = BIT(HWTSTAMP_TX_OFF);
- if (is_lan937x(dev))
+ if (!ksz_is_ksz8463(dev))
+ ts->tx_types |= BIT(HWTSTAMP_TX_ONESTEP_P2P);
+
+ if (is_lan937x(dev) || ksz_is_ksz8463(dev))
ts->tx_types |= BIT(HWTSTAMP_TX_ON);
ts->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
- BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
- BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
- BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT);
+ if (!ksz_is_ksz8463(dev)) {
+ ts->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
+ }
ts->phc_index = ptp_clock_index(ptp_data->clock);
@@ -353,6 +358,9 @@ static int ksz_set_hwtstamp_config(struct ksz_device *dev,
prt->hwts_tx_en = false;
break;
case HWTSTAMP_TX_ONESTEP_P2P:
+ if (ksz_is_ksz8463(dev))
+ return -ERANGE;
+
prt->ptpmsg_irq[KSZ_SYNC_MSG].ts_en = false;
prt->ptpmsg_irq[KSZ_XDREQ_MSG].ts_en = true;
prt->ptpmsg_irq[KSZ_PDRES_MSG].ts_en = false;
@@ -364,14 +372,19 @@ static int ksz_set_hwtstamp_config(struct ksz_device *dev,
break;
case HWTSTAMP_TX_ON:
- if (!is_lan937x(dev))
+ if (!is_lan937x(dev) && !ksz_is_ksz8463(dev))
return -ERANGE;
- prt->ptpmsg_irq[KSZ_SYNC_MSG].ts_en = true;
- prt->ptpmsg_irq[KSZ_XDREQ_MSG].ts_en = true;
- prt->ptpmsg_irq[KSZ_PDRES_MSG].ts_en = true;
- prt->hwts_tx_en = true;
+ if (ksz_is_ksz8463(dev)) {
+ prt->ptpmsg_irq[KSZ8463_SYNC_MSG].ts_en = true;
+ prt->ptpmsg_irq[KSZ8463_XDREQ_PDRES_MSG].ts_en = true;
+ } else {
+ prt->ptpmsg_irq[KSZ_SYNC_MSG].ts_en = true;
+ prt->ptpmsg_irq[KSZ_XDREQ_MSG].ts_en = true;
+ prt->ptpmsg_irq[KSZ_PDRES_MSG].ts_en = true;
+ }
+ prt->hwts_tx_en = true;
ret = ksz_rmw16(dev, regs[PTP_MSG_CONF1], PTP_1STEP, 0);
if (ret)
return ret;
@@ -387,6 +400,8 @@ static int ksz_set_hwtstamp_config(struct ksz_device *dev,
break;
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ if (ksz_is_ksz8463(dev))
+ return -ERANGE;
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
prt->hwts_rx_en = true;
break;
@@ -397,6 +412,8 @@ static int ksz_set_hwtstamp_config(struct ksz_device *dev,
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ if (ksz_is_ksz8463(dev))
+ return -ERANGE;
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
prt->hwts_rx_en = true;
break;
@@ -518,6 +535,8 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
if (!hdr)
return;
+ prt->last_tx_is_pdelayresp = false;
+
ptp_msg_type = ptp_get_msgtype(hdr, type);
switch (ptp_msg_type) {
@@ -528,6 +547,7 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
case PTP_MSGTYPE_PDELAY_REQ:
break;
case PTP_MSGTYPE_PDELAY_RESP:
+ prt->last_tx_is_pdelayresp = true;
if (prt->tstamp_config.tx_type == HWTSTAMP_TX_ONESTEP_P2P) {
KSZ_SKB_CB(skb)->ptp_type = type;
KSZ_SKB_CB(skb)->update_correction = true;
@@ -972,7 +992,17 @@ void ksz_ptp_clock_unregister(struct dsa_switch *ds)
static int ksz_read_ts(struct ksz_port *port, u16 reg, u32 *ts)
{
- return ksz_read32(port->ksz_dev, reg, ts);
+ u16 ts_reg = reg;
+
+ /**
+ * On KSZ8463 DREQ and DRESP timestamps share one interrupt line
+ * so we have to check the nature of the latest event sent to know
+ * where the timestamp is located
+ */
+ if (ksz_is_ksz8463(port->ksz_dev) && port->last_tx_is_pdelayresp)
+ ts_reg += KSZ8463_DRESP_TS_OFFSET;
+
+ return ksz_read32(port->ksz_dev, ts_reg, ts);
}
static irqreturn_t ksz_ptp_msg_thread_fn(int irq, void *dev_id)
diff --git a/drivers/net/dsa/microchip/ksz_ptp_reg.h b/drivers/net/dsa/microchip/ksz_ptp_reg.h
index e80fb4bd1a0e970ba3570374d3dc82c8e2cc15b4..ac9d0f2b348b0469abbeed0e645fe8ef441d35fb 100644
--- a/drivers/net/dsa/microchip/ksz_ptp_reg.h
+++ b/drivers/net/dsa/microchip/ksz_ptp_reg.h
@@ -125,6 +125,10 @@
#define KSZ8463_REG_PORT_SYNC_TS 0x064C
#define KSZ8463_REG_PORT_DRESP_TS 0x0650
+#define KSZ8463_DRESP_TS_OFFSET (KSZ8463_REG_PORT_DRESP_TS - KSZ8463_REG_PORT_DREQ_TS)
+#define KSZ8463_SYNC_MSG 0
+#define KSZ8463_XDREQ_PDRES_MSG 1
+
#define REG_PTP_PORT_TX_INT_STATUS__2 0x0C14
#define REG_PTP_PORT_TX_INT_ENABLE__2 0x0C16
--
2.52.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463
2026-01-27 9:06 ` [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463 Bastien Curutchet (Schneider Electric)
@ 2026-02-02 13:43 ` Vladimir Oltean
2026-02-18 15:21 ` Bastien Curutchet
0 siblings, 1 reply; 25+ messages in thread
From: Vladimir Oltean @ 2026-02-02 13:43 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric)
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
On Tue, Jan 27, 2026 at 10:06:50AM +0100, Bastien Curutchet (Schneider Electric) wrote:
> The KSZ8463 switch supports PTP but it's not supported by driver.
>
> Add L2 two-step PTP support for the KSZ8463. IPv4 and IPv6 layers aren't
> supported. Neither is one-step PTP.
>
> The pdelay_req and pdelay_resp timestamps share one interrupt bit status.
> So introduce last_tx_is_pdelayresp to keep track of the last sent event
> type. Use it to retrieve the relevant timestamp when the interrupt is
> caught.
>
> Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
> ---
> @@ -518,6 +535,8 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
> if (!hdr)
> return;
>
> + prt->last_tx_is_pdelayresp = false;
> +
> ptp_msg_type = ptp_get_msgtype(hdr, type);
>
> switch (ptp_msg_type) {
> @@ -528,6 +547,7 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
> case PTP_MSGTYPE_PDELAY_REQ:
> break;
> case PTP_MSGTYPE_PDELAY_RESP:
> + prt->last_tx_is_pdelayresp = true;
> if (prt->tstamp_config.tx_type == HWTSTAMP_TX_ONESTEP_P2P) {
> KSZ_SKB_CB(skb)->ptp_type = type;
> KSZ_SKB_CB(skb)->update_correction = true;
> @@ -972,7 +992,17 @@ void ksz_ptp_clock_unregister(struct dsa_switch *ds)
>
> static int ksz_read_ts(struct ksz_port *port, u16 reg, u32 *ts)
> {
> - return ksz_read32(port->ksz_dev, reg, ts);
> + u16 ts_reg = reg;
> +
> + /**
> + * On KSZ8463 DREQ and DRESP timestamps share one interrupt line
> + * so we have to check the nature of the latest event sent to know
> + * where the timestamp is located
> + */
> + if (ksz_is_ksz8463(port->ksz_dev) && port->last_tx_is_pdelayresp)
> + ts_reg += KSZ8463_DRESP_TS_OFFSET;
> +
> + return ksz_read32(port->ksz_dev, ts_reg, ts);
> }
There is a race condition here.
ksz_port_txtstamp() is called "at line rate" - it doesn't wait for the
timestamping of the currently in progress skb to finish.
See the order in
static netdev_tx_t dsa_user_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dsa_user_priv *p = netdev_priv(dev);
struct sk_buff *nskb;
dev_sw_netstats_tx_add(dev, 1, skb->len);
memset(skb->cb, 0, sizeof(skb->cb));
dsa_skb_tx_timestamp(p, skb); // calls ksz_port_txtstamp()
...
nskb = p->xmit(skb, dev); // calls ksz9893_xmit() -> ksz_defer_xmit()
if (!nskb) {
kfree_skb(skb); // deferred xmit enters this code path
return NETDEV_TX_OK;
}
return dsa_enqueue_skb(nskb, dev);
}
The deferred worker gets scheduled much later, time during which a
second PTP packet may be transmitted from the stack.
If you let the second skb change the port->last_tx_is_pdelayresp which
ksz_ptp_msg_thread_fn() -> ksz_read_ts() thinks is associated with the
first skb, you're in big trouble.
You need to set port->last_tx_is_pdelayresp in the atomic section where
you know for sure that there's a single TX timestampable skb in flight.
There's no explicit lock which creates that atomic section, but the fact
that the worker kthread of the tagger processes work items one by one is
what gives you that guarantee.
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463
2026-02-02 13:43 ` Vladimir Oltean
@ 2026-02-18 15:21 ` Bastien Curutchet
2026-02-18 15:25 ` Vladimir Oltean
0 siblings, 1 reply; 25+ messages in thread
From: Bastien Curutchet @ 2026-02-18 15:21 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
Hi Vladimir,
On 2/2/26 2:43 PM, Vladimir Oltean wrote:
> On Tue, Jan 27, 2026 at 10:06:50AM +0100, Bastien Curutchet (Schneider Electric) wrote:
>> The KSZ8463 switch supports PTP but it's not supported by driver.
>>
>> Add L2 two-step PTP support for the KSZ8463. IPv4 and IPv6 layers aren't
>> supported. Neither is one-step PTP.
>>
>> The pdelay_req and pdelay_resp timestamps share one interrupt bit status.
>> So introduce last_tx_is_pdelayresp to keep track of the last sent event
>> type. Use it to retrieve the relevant timestamp when the interrupt is
>> caught.
>>
>> Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
>> ---
>> @@ -518,6 +535,8 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
>> if (!hdr)
>> return;
>>
>> + prt->last_tx_is_pdelayresp = false;
>> +
>> ptp_msg_type = ptp_get_msgtype(hdr, type);
>>
>> switch (ptp_msg_type) {
>> @@ -528,6 +547,7 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
>> case PTP_MSGTYPE_PDELAY_REQ:
>> break;
>> case PTP_MSGTYPE_PDELAY_RESP:
>> + prt->last_tx_is_pdelayresp = true;
>> if (prt->tstamp_config.tx_type == HWTSTAMP_TX_ONESTEP_P2P) {
>> KSZ_SKB_CB(skb)->ptp_type = type;
>> KSZ_SKB_CB(skb)->update_correction = true;
>> @@ -972,7 +992,17 @@ void ksz_ptp_clock_unregister(struct dsa_switch *ds)
>>
>> static int ksz_read_ts(struct ksz_port *port, u16 reg, u32 *ts)
>> {
>> - return ksz_read32(port->ksz_dev, reg, ts);
>> + u16 ts_reg = reg;
>> +
>> + /**
>> + * On KSZ8463 DREQ and DRESP timestamps share one interrupt line
>> + * so we have to check the nature of the latest event sent to know
>> + * where the timestamp is located
>> + */
>> + if (ksz_is_ksz8463(port->ksz_dev) && port->last_tx_is_pdelayresp)
>> + ts_reg += KSZ8463_DRESP_TS_OFFSET;
>> +
>> + return ksz_read32(port->ksz_dev, ts_reg, ts);
>> }
>
> There is a race condition here.
>
> ksz_port_txtstamp() is called "at line rate" - it doesn't wait for the
> timestamping of the currently in progress skb to finish.
>
> See the order in
> static netdev_tx_t dsa_user_xmit(struct sk_buff *skb, struct net_device *dev)
> {
> struct dsa_user_priv *p = netdev_priv(dev);
> struct sk_buff *nskb;
>
> dev_sw_netstats_tx_add(dev, 1, skb->len);
>
> memset(skb->cb, 0, sizeof(skb->cb));
>
> dsa_skb_tx_timestamp(p, skb); // calls ksz_port_txtstamp()
>
> ...
>
> nskb = p->xmit(skb, dev); // calls ksz9893_xmit() -> ksz_defer_xmit()
> if (!nskb) {
> kfree_skb(skb); // deferred xmit enters this code path
> return NETDEV_TX_OK;
> }
>
> return dsa_enqueue_skb(nskb, dev);
> }
>
> The deferred worker gets scheduled much later, time during which a
> second PTP packet may be transmitted from the stack.
>
> If you let the second skb change the port->last_tx_is_pdelayresp which
> ksz_ptp_msg_thread_fn() -> ksz_read_ts() thinks is associated with the
> first skb, you're in big trouble.
>
> You need to set port->last_tx_is_pdelayresp in the atomic section where
> you know for sure that there's a single TX timestampable skb in flight.
> There's no explicit lock which creates that atomic section, but the fact
> that the worker kthread of the tagger processes work items one by one is
> what gives you that guarantee.
Thank you for the explanations. I suspected a race condition here but I
didn't know how to mitigate it. I tested a new version on my side with
port->last_tx_is_pdelayresp set in the ksz_port_deferred_xmit() worker
and it works fine.
I'll wait for net-next to open back to send this new version.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463
2026-02-18 15:21 ` Bastien Curutchet
@ 2026-02-18 15:25 ` Vladimir Oltean
2026-02-18 16:42 ` Bastien Curutchet
0 siblings, 1 reply; 25+ messages in thread
From: Vladimir Oltean @ 2026-02-18 15:25 UTC (permalink / raw)
To: Bastien Curutchet
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
On Wed, Feb 18, 2026 at 04:21:26PM +0100, Bastien Curutchet wrote:
> > You need to set port->last_tx_is_pdelayresp in the atomic section where
> > you know for sure that there's a single TX timestampable skb in flight.
> > There's no explicit lock which creates that atomic section, but the fact
> > that the worker kthread of the tagger processes work items one by one is
> > what gives you that guarantee.
>
> Thank you for the explanations. I suspected a race condition here but I
> didn't know how to mitigate it. I tested a new version on my side with
> port->last_tx_is_pdelayresp set in the ksz_port_deferred_xmit() worker and
> it works fine.
Good.
Next question: if the logic is all in ksz_port_deferred_xmit(), which is
sleepable and sends packets one by one, do you actually need to save the
packet type in port->last_tx_is_pdelayresp? Can't you just keep a local
variable with it?
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463
2026-02-18 15:25 ` Vladimir Oltean
@ 2026-02-18 16:42 ` Bastien Curutchet
2026-02-18 16:47 ` Vladimir Oltean
0 siblings, 1 reply; 25+ messages in thread
From: Bastien Curutchet @ 2026-02-18 16:42 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
On 2/18/26 4:25 PM, Vladimir Oltean wrote:
> On Wed, Feb 18, 2026 at 04:21:26PM +0100, Bastien Curutchet wrote:
>>> You need to set port->last_tx_is_pdelayresp in the atomic section where
>>> you know for sure that there's a single TX timestampable skb in flight.
>>> There's no explicit lock which creates that atomic section, but the fact
>>> that the worker kthread of the tagger processes work items one by one is
>>> what gives you that guarantee.
>>
>> Thank you for the explanations. I suspected a race condition here but I
>> didn't know how to mitigate it. I tested a new version on my side with
>> port->last_tx_is_pdelayresp set in the ksz_port_deferred_xmit() worker and
>> it works fine.
>
> Good.
>
> Next question: if the logic is all in ksz_port_deferred_xmit(), which is
> sleepable and sends packets one by one, do you actually need to save the
> packet type in port->last_tx_is_pdelayresp? Can't you just keep a local
> variable with it?
Well, I think I could but it feels like a significant rework of the
existing implementation. So far the register location is tied to the
struct ksz_ptp_irq, since on all the other switches one interrupt bit is
associated with one timestamp only. In fact, even on the KSZ8463 the
same logic applies because there are two interrupt bits per port: one
for the sync messages and one for the pdelay_req / pdelay_resp messages.
If I'm not mistaken, using a local variable here would mean moving the
timestamp reading from ksz_ptp_msg_thread_fn() to
ksz_port_deferred_xmit(). We would then need to check the type of each
packet before sending it, in order to know where to read the timestamp
after wait_for_completion() returns.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463
2026-02-18 16:42 ` Bastien Curutchet
@ 2026-02-18 16:47 ` Vladimir Oltean
2026-02-18 16:49 ` Bastien Curutchet
0 siblings, 1 reply; 25+ messages in thread
From: Vladimir Oltean @ 2026-02-18 16:47 UTC (permalink / raw)
To: Bastien Curutchet
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
On Wed, Feb 18, 2026 at 05:42:32PM +0100, Bastien Curutchet wrote:
> On 2/18/26 4:25 PM, Vladimir Oltean wrote:
> > On Wed, Feb 18, 2026 at 04:21:26PM +0100, Bastien Curutchet wrote:
> > > > You need to set port->last_tx_is_pdelayresp in the atomic section where
> > > > you know for sure that there's a single TX timestampable skb in flight.
> > > > There's no explicit lock which creates that atomic section, but the fact
> > > > that the worker kthread of the tagger processes work items one by one is
> > > > what gives you that guarantee.
> > >
> > > Thank you for the explanations. I suspected a race condition here but I
> > > didn't know how to mitigate it. I tested a new version on my side with
> > > port->last_tx_is_pdelayresp set in the ksz_port_deferred_xmit() worker and
> > > it works fine.
> >
> > Good.
> >
> > Next question: if the logic is all in ksz_port_deferred_xmit(), which is
> > sleepable and sends packets one by one, do you actually need to save the
> > packet type in port->last_tx_is_pdelayresp? Can't you just keep a local
> > variable with it?
>
> Well, I think I could but it feels like a significant rework of the existing
> implementation. So far the register location is tied to the struct
> ksz_ptp_irq, since on all the other switches one interrupt bit is associated
> with one timestamp only. In fact, even on the KSZ8463 the same logic applies
> because there are two interrupt bits per port: one for the sync messages and
> one for the pdelay_req / pdelay_resp messages.
>
> If I'm not mistaken, using a local variable here would mean moving the
> timestamp reading from ksz_ptp_msg_thread_fn() to ksz_port_deferred_xmit().
> We would then need to check the type of each packet before sending it, in
> order to know where to read the timestamp after wait_for_completion()
> returns.
OK. I no longer had a git tree checked out with these patches, so I
forgot you need the PTP type in the IRQ handler. It's fine the way you
plan to send the next version. Thanks for checking.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463
2026-02-18 16:47 ` Vladimir Oltean
@ 2026-02-18 16:49 ` Bastien Curutchet
0 siblings, 0 replies; 25+ messages in thread
From: Bastien Curutchet @ 2026-02-18 16:49 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Woojung Huh, UNGLinuxDriver, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
Simon Horman, Pascal Eberhard, Miquèl Raynal,
Thomas Petazzoni, netdev, linux-kernel
On 2/18/26 5:47 PM, Vladimir Oltean wrote:
> On Wed, Feb 18, 2026 at 05:42:32PM +0100, Bastien Curutchet wrote:
>> On 2/18/26 4:25 PM, Vladimir Oltean wrote:
>>> On Wed, Feb 18, 2026 at 04:21:26PM +0100, Bastien Curutchet wrote:
>>>>> You need to set port->last_tx_is_pdelayresp in the atomic section where
>>>>> you know for sure that there's a single TX timestampable skb in flight.
>>>>> There's no explicit lock which creates that atomic section, but the fact
>>>>> that the worker kthread of the tagger processes work items one by one is
>>>>> what gives you that guarantee.
>>>>
>>>> Thank you for the explanations. I suspected a race condition here but I
>>>> didn't know how to mitigate it. I tested a new version on my side with
>>>> port->last_tx_is_pdelayresp set in the ksz_port_deferred_xmit() worker and
>>>> it works fine.
>>>
>>> Good.
>>>
>>> Next question: if the logic is all in ksz_port_deferred_xmit(), which is
>>> sleepable and sends packets one by one, do you actually need to save the
>>> packet type in port->last_tx_is_pdelayresp? Can't you just keep a local
>>> variable with it?
>>
>> Well, I think I could but it feels like a significant rework of the existing
>> implementation. So far the register location is tied to the struct
>> ksz_ptp_irq, since on all the other switches one interrupt bit is associated
>> with one timestamp only. In fact, even on the KSZ8463 the same logic applies
>> because there are two interrupt bits per port: one for the sync messages and
>> one for the pdelay_req / pdelay_resp messages.
>>
>> If I'm not mistaken, using a local variable here would mean moving the
>> timestamp reading from ksz_ptp_msg_thread_fn() to ksz_port_deferred_xmit().
>> We would then need to check the type of each packet before sending it, in
>> order to know where to read the timestamp after wait_for_completion()
>> returns.
>
> OK. I no longer had a git tree checked out with these patches, so I
> forgot you need the PTP type in the IRQ handler. It's fine the way you
> plan to send the next version. Thanks for checking.
Ok great, thank you.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 25+ messages in thread