Commit 6c14058e authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski
Browse files

net: dsa: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()



New timestamping API was introduced in commit 66f72230 ("net: add
NDOs for configuring hardware timestamping") from kernel v6.6. It is
time to convert DSA to the new API, so that the ndo_eth_ioctl() path can
be removed completely.

Move the ds->ops->port_hwtstamp_get() and ds->ops->port_hwtstamp_set()
calls from dsa_user_ioctl() to dsa_user_hwtstamp_get() and
dsa_user_hwtstamp_set().

Due to the fact that the underlying ifreq type changes to
kernel_hwtstamp_config, the drivers and the Ocelot switchdev front-end,
all hooked up directly or indirectly, must also be converted all at once.

The conversion also updates the comment from dsa_port_supports_hwtstamp(),
which is no longer true because kernel_hwtstamp_config is kernel memory
and does not need copy_to_user(). I've deliberated whether it is
necessary to also update "err != -EOPNOTSUPP" to a more general "!err",
but all drivers now either return 0 or -EOPNOTSUPP.

The existing logic from the ocelot_ioctl() function, to avoid
configuring timestamping if the PHY supports the operation, is obsoleted
by more advanced core logic in dev_set_hwtstamp_phylib().

This is only a partial preparation for proper PHY timestamping support.
None of these switch driver currently sets up PTP traps for PHY
timestamping, so setting dev->see_all_hwtstamp_requests is not yet
necessary and the conversion is relatively trivial.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> # felix, sja1105, mv88e6xxx
Reviewed-by: default avatarVadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20250508095236.887789-1-vladimir.oltean@nxp.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 0df69324
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -244,7 +244,7 @@ struct hellcreek_port_hwtstamp {
	struct sk_buff *tx_skb;

	/* Current timestamp configuration */
	struct hwtstamp_config tstamp_config;
	struct kernel_hwtstamp_config tstamp_config;
};

struct hellcreek_port {
+9 −15
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ int hellcreek_get_ts_info(struct dsa_switch *ds, int port,
 * the user requested what is actually available or not
 */
static int hellcreek_set_hwtstamp_config(struct hellcreek *hellcreek, int port,
					 struct hwtstamp_config *config)
					 struct kernel_hwtstamp_config *config)
{
	struct hellcreek_port_hwtstamp *ps =
		&hellcreek->ports[port].port_hwtstamp;
@@ -110,41 +110,35 @@ static int hellcreek_set_hwtstamp_config(struct hellcreek *hellcreek, int port,
}

int hellcreek_port_hwtstamp_set(struct dsa_switch *ds, int port,
				struct ifreq *ifr)
				struct kernel_hwtstamp_config *config,
				struct netlink_ext_ack *extack)
{
	struct hellcreek *hellcreek = ds->priv;
	struct hellcreek_port_hwtstamp *ps;
	struct hwtstamp_config config;
	int err;

	ps = &hellcreek->ports[port].port_hwtstamp;

	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
		return -EFAULT;

	err = hellcreek_set_hwtstamp_config(hellcreek, port, &config);
	err = hellcreek_set_hwtstamp_config(hellcreek, port, config);
	if (err)
		return err;

	/* Save the chosen configuration to be returned later */
	memcpy(&ps->tstamp_config, &config, sizeof(config));
	ps->tstamp_config = *config;

	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
		-EFAULT : 0;
	return 0;
}

int hellcreek_port_hwtstamp_get(struct dsa_switch *ds, int port,
				struct ifreq *ifr)
				struct kernel_hwtstamp_config *config)
{
	struct hellcreek *hellcreek = ds->priv;
	struct hellcreek_port_hwtstamp *ps;
	struct hwtstamp_config *config;

	ps = &hellcreek->ports[port].port_hwtstamp;
	config = &ps->tstamp_config;
	*config = ps->tstamp_config;

	return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
		-EFAULT : 0;
	return 0;
}

/* Returns a pointer to the PTP header if the caller should time stamp, or NULL
+3 −2
Original line number Diff line number Diff line
@@ -38,9 +38,10 @@
#define TX_TSTAMP_TIMEOUT	msecs_to_jiffies(40)

int hellcreek_port_hwtstamp_set(struct dsa_switch *ds, int port,
				struct ifreq *ifr);
				struct kernel_hwtstamp_config *config,
				struct netlink_ext_ack *extack);
int hellcreek_port_hwtstamp_get(struct dsa_switch *ds, int port,
				struct ifreq *ifr);
				struct kernel_hwtstamp_config *config);

bool hellcreek_port_rxtstamp(struct dsa_switch *ds, int port,
			     struct sk_buff *clone, unsigned int type);
+1 −1
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ struct ksz_port {
	struct ksz_irq pirq;
	u8 num;
#if IS_ENABLED(CONFIG_NET_DSA_MICROCHIP_KSZ_PTP)
	struct hwtstamp_config tstamp_config;
	struct kernel_hwtstamp_config tstamp_config;
	bool hwts_tx_en;
	bool hwts_rx_en;
	struct ksz_irq ptpirq;
+10 −16
Original line number Diff line number Diff line
@@ -319,22 +319,21 @@ int ksz_get_ts_info(struct dsa_switch *ds, int port, struct kernel_ethtool_ts_in
	return 0;
}

int ksz_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
int ksz_hwtstamp_get(struct dsa_switch *ds, int port,
		     struct kernel_hwtstamp_config *config)
{
	struct ksz_device *dev = ds->priv;
	struct hwtstamp_config *config;
	struct ksz_port *prt;

	prt = &dev->ports[port];
	config = &prt->tstamp_config;
	*config = prt->tstamp_config;

	return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
		-EFAULT : 0;
	return 0;
}

static int ksz_set_hwtstamp_config(struct ksz_device *dev,
				   struct ksz_port *prt,
				   struct hwtstamp_config *config)
				   struct kernel_hwtstamp_config *config)
{
	int ret;

@@ -404,26 +403,21 @@ static int ksz_set_hwtstamp_config(struct ksz_device *dev,
	return ksz_ptp_enable_mode(dev);
}

int ksz_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
int ksz_hwtstamp_set(struct dsa_switch *ds, int port,
		     struct kernel_hwtstamp_config *config,
		     struct netlink_ext_ack *extack)
{
	struct ksz_device *dev = ds->priv;
	struct hwtstamp_config config;
	struct ksz_port *prt;
	int ret;

	prt = &dev->ports[port];

	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
		return -EFAULT;

	ret = ksz_set_hwtstamp_config(dev, prt, &config);
	ret = ksz_set_hwtstamp_config(dev, prt, config);
	if (ret)
		return ret;

	memcpy(&prt->tstamp_config, &config, sizeof(config));

	if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
		return -EFAULT;
	prt->tstamp_config = *config;

	return 0;
}
Loading