mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
net: dsa: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
New timestamping API was introduced in commit 66f7223039
("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: Vladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> # felix, sja1105, mv88e6xxx
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20250508095236.887789-1-vladimir.oltean@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
0df6932485
commit
6c14058edf
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -39,8 +39,11 @@ void ksz_ptp_clock_unregister(struct dsa_switch *ds);
|
|||
|
||||
int ksz_get_ts_info(struct dsa_switch *ds, int port,
|
||||
struct kernel_ethtool_ts_info *ts);
|
||||
int ksz_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr);
|
||||
int ksz_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr);
|
||||
int ksz_hwtstamp_get(struct dsa_switch *ds, int port,
|
||||
struct kernel_hwtstamp_config *config);
|
||||
int ksz_hwtstamp_set(struct dsa_switch *ds, int port,
|
||||
struct kernel_hwtstamp_config *config,
|
||||
struct netlink_ext_ack *extack);
|
||||
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,
|
||||
|
|
|
@ -241,7 +241,7 @@ struct mv88e6xxx_port_hwtstamp {
|
|||
u16 tx_seq_id;
|
||||
|
||||
/* Current timestamp configuration */
|
||||
struct hwtstamp_config tstamp_config;
|
||||
struct kernel_hwtstamp_config tstamp_config;
|
||||
};
|
||||
|
||||
enum mv88e6xxx_policy_mapping {
|
||||
|
|
|
@ -89,7 +89,7 @@ int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
|
|||
}
|
||||
|
||||
static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
|
||||
struct hwtstamp_config *config)
|
||||
struct kernel_hwtstamp_config *config)
|
||||
{
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
|
||||
struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
|
||||
|
@ -169,42 +169,38 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
|
|||
}
|
||||
|
||||
int mv88e6xxx_port_hwtstamp_set(struct dsa_switch *ds, int port,
|
||||
struct ifreq *ifr)
|
||||
struct kernel_hwtstamp_config *config,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
|
||||
struct hwtstamp_config config;
|
||||
int err;
|
||||
|
||||
if (!chip->info->ptp_support)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
|
||||
return -EFAULT;
|
||||
|
||||
err = mv88e6xxx_set_hwtstamp_config(chip, port, &config);
|
||||
err = mv88e6xxx_set_hwtstamp_config(chip, 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 mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds, int port,
|
||||
struct ifreq *ifr)
|
||||
struct kernel_hwtstamp_config *config)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
|
||||
struct hwtstamp_config *config = &ps->tstamp_config;
|
||||
|
||||
if (!chip->info->ptp_support)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
|
||||
-EFAULT : 0;
|
||||
*config = ps->tstamp_config;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the PTP header if the caller should time stamp,
|
||||
|
|
|
@ -111,9 +111,10 @@
|
|||
#ifdef CONFIG_NET_DSA_MV88E6XXX_PTP
|
||||
|
||||
int mv88e6xxx_port_hwtstamp_set(struct dsa_switch *ds, int port,
|
||||
struct ifreq *ifr);
|
||||
struct kernel_hwtstamp_config *cfg,
|
||||
struct netlink_ext_ack *extack);
|
||||
int mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds, int port,
|
||||
struct ifreq *ifr);
|
||||
struct kernel_hwtstamp_config *cfg);
|
||||
|
||||
bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
|
||||
struct sk_buff *clone, unsigned int type);
|
||||
|
@ -132,14 +133,17 @@ int mv88e6165_global_disable(struct mv88e6xxx_chip *chip);
|
|||
|
||||
#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
|
||||
|
||||
static inline int mv88e6xxx_port_hwtstamp_set(struct dsa_switch *ds,
|
||||
int port, struct ifreq *ifr)
|
||||
static inline int
|
||||
mv88e6xxx_port_hwtstamp_set(struct dsa_switch *ds, int port,
|
||||
struct kernel_hwtstamp_config *config,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds,
|
||||
int port, struct ifreq *ifr)
|
||||
static inline int
|
||||
mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds, int port,
|
||||
struct kernel_hwtstamp_config *config)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
|
|
@ -1774,22 +1774,25 @@ static void felix_teardown(struct dsa_switch *ds)
|
|||
}
|
||||
|
||||
static int felix_hwtstamp_get(struct dsa_switch *ds, int port,
|
||||
struct ifreq *ifr)
|
||||
struct kernel_hwtstamp_config *config)
|
||||
{
|
||||
struct ocelot *ocelot = ds->priv;
|
||||
|
||||
return ocelot_hwstamp_get(ocelot, port, ifr);
|
||||
ocelot_hwstamp_get(ocelot, port, config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int felix_hwtstamp_set(struct dsa_switch *ds, int port,
|
||||
struct ifreq *ifr)
|
||||
struct kernel_hwtstamp_config *config,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ocelot *ocelot = ds->priv;
|
||||
struct felix *felix = ocelot_to_felix(ocelot);
|
||||
bool using_tag_8021q;
|
||||
int err;
|
||||
|
||||
err = ocelot_hwstamp_set(ocelot, port, ifr);
|
||||
err = ocelot_hwstamp_set(ocelot, port, config, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -58,19 +58,17 @@ enum sja1105_ptp_clk_mode {
|
|||
#define ptp_data_to_sja1105(d) \
|
||||
container_of((d), struct sja1105_private, ptp_data)
|
||||
|
||||
int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
|
||||
int sja1105_hwtstamp_set(struct dsa_switch *ds, int port,
|
||||
struct kernel_hwtstamp_config *config,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
unsigned long hwts_tx_en, hwts_rx_en;
|
||||
struct hwtstamp_config config;
|
||||
|
||||
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
|
||||
return -EFAULT;
|
||||
|
||||
hwts_tx_en = priv->hwts_tx_en;
|
||||
hwts_rx_en = priv->hwts_rx_en;
|
||||
|
||||
switch (config.tx_type) {
|
||||
switch (config->tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
hwts_tx_en &= ~BIT(port);
|
||||
break;
|
||||
|
@ -81,7 +79,7 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
|
|||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (config.rx_filter) {
|
||||
switch (config->rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
hwts_rx_en &= ~BIT(port);
|
||||
break;
|
||||
|
@ -92,32 +90,28 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
|
|||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
|
||||
return -EFAULT;
|
||||
|
||||
priv->hwts_tx_en = hwts_tx_en;
|
||||
priv->hwts_rx_en = hwts_rx_en;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
|
||||
int sja1105_hwtstamp_get(struct dsa_switch *ds, int port,
|
||||
struct kernel_hwtstamp_config *config)
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct hwtstamp_config config;
|
||||
|
||||
config.flags = 0;
|
||||
config->flags = 0;
|
||||
if (priv->hwts_tx_en & BIT(port))
|
||||
config.tx_type = HWTSTAMP_TX_ON;
|
||||
config->tx_type = HWTSTAMP_TX_ON;
|
||||
else
|
||||
config.tx_type = HWTSTAMP_TX_OFF;
|
||||
config->tx_type = HWTSTAMP_TX_OFF;
|
||||
if (priv->hwts_rx_en & BIT(port))
|
||||
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
|
||||
else
|
||||
config.rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
config->rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
|
||||
-EFAULT : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sja1105_get_ts_info(struct dsa_switch *ds, int port,
|
||||
|
|
|
@ -112,9 +112,12 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
|
|||
void sja1105_port_txtstamp(struct dsa_switch *ds, int port,
|
||||
struct sk_buff *skb);
|
||||
|
||||
int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr);
|
||||
int sja1105_hwtstamp_get(struct dsa_switch *ds, int port,
|
||||
struct kernel_hwtstamp_config *config);
|
||||
|
||||
int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr);
|
||||
int sja1105_hwtstamp_set(struct dsa_switch *ds, int port,
|
||||
struct kernel_hwtstamp_config *config,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
int __sja1105_ptp_gettimex(struct dsa_switch *ds, u64 *ns,
|
||||
struct ptp_system_timestamp *sts);
|
||||
|
|
|
@ -869,24 +869,31 @@ static int ocelot_set_features(struct net_device *dev,
|
|||
}
|
||||
|
||||
static int ocelot_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
return phy_mii_ioctl(dev->phydev, ifr, cmd);
|
||||
}
|
||||
|
||||
static int ocelot_port_hwtstamp_get(struct net_device *dev,
|
||||
struct kernel_hwtstamp_config *cfg)
|
||||
{
|
||||
struct ocelot_port_private *priv = netdev_priv(dev);
|
||||
struct ocelot *ocelot = priv->port.ocelot;
|
||||
int port = priv->port.index;
|
||||
|
||||
/* If the attached PHY device isn't capable of timestamping operations,
|
||||
* use our own (when possible).
|
||||
*/
|
||||
if (!phy_has_hwtstamp(dev->phydev) && ocelot->ptp) {
|
||||
switch (cmd) {
|
||||
case SIOCSHWTSTAMP:
|
||||
return ocelot_hwstamp_set(ocelot, port, ifr);
|
||||
case SIOCGHWTSTAMP:
|
||||
return ocelot_hwstamp_get(ocelot, port, ifr);
|
||||
}
|
||||
}
|
||||
ocelot_hwstamp_get(ocelot, port, cfg);
|
||||
|
||||
return phy_mii_ioctl(dev->phydev, ifr, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ocelot_port_hwtstamp_set(struct net_device *dev,
|
||||
struct kernel_hwtstamp_config *cfg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ocelot_port_private *priv = netdev_priv(dev);
|
||||
struct ocelot *ocelot = priv->port.ocelot;
|
||||
int port = priv->port.index;
|
||||
|
||||
return ocelot_hwstamp_set(ocelot, port, cfg, extack);
|
||||
}
|
||||
|
||||
static int ocelot_change_mtu(struct net_device *dev, int new_mtu)
|
||||
|
@ -917,6 +924,8 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
|
|||
.ndo_set_features = ocelot_set_features,
|
||||
.ndo_setup_tc = ocelot_setup_tc,
|
||||
.ndo_eth_ioctl = ocelot_ioctl,
|
||||
.ndo_hwtstamp_get = ocelot_port_hwtstamp_get,
|
||||
.ndo_hwtstamp_set = ocelot_port_hwtstamp_set,
|
||||
};
|
||||
|
||||
struct net_device *ocelot_port_to_netdev(struct ocelot *ocelot, int port)
|
||||
|
|
|
@ -514,47 +514,42 @@ static int ocelot_ptp_tx_type_to_cmd(int tx_type, int *ptp_cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
|
||||
void ocelot_hwstamp_get(struct ocelot *ocelot, int port,
|
||||
struct kernel_hwtstamp_config *cfg)
|
||||
{
|
||||
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||
struct hwtstamp_config cfg = {};
|
||||
|
||||
switch (ocelot_port->ptp_cmd) {
|
||||
case IFH_REW_OP_TWO_STEP_PTP:
|
||||
cfg.tx_type = HWTSTAMP_TX_ON;
|
||||
cfg->tx_type = HWTSTAMP_TX_ON;
|
||||
break;
|
||||
case IFH_REW_OP_ORIGIN_PTP:
|
||||
cfg.tx_type = HWTSTAMP_TX_ONESTEP_SYNC;
|
||||
cfg->tx_type = HWTSTAMP_TX_ONESTEP_SYNC;
|
||||
break;
|
||||
default:
|
||||
cfg.tx_type = HWTSTAMP_TX_OFF;
|
||||
cfg->tx_type = HWTSTAMP_TX_OFF;
|
||||
break;
|
||||
}
|
||||
|
||||
cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
||||
cfg->rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
|
||||
}
|
||||
EXPORT_SYMBOL(ocelot_hwstamp_get);
|
||||
|
||||
int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
|
||||
int ocelot_hwstamp_set(struct ocelot *ocelot, int port,
|
||||
struct kernel_hwtstamp_config *cfg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||
int ptp_cmd, old_ptp_cmd = ocelot_port->ptp_cmd;
|
||||
bool l2 = false, l4 = false;
|
||||
struct hwtstamp_config cfg;
|
||||
bool old_l2, old_l4;
|
||||
int ptp_cmd;
|
||||
int err;
|
||||
|
||||
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
|
||||
return -EFAULT;
|
||||
|
||||
/* Tx type sanity check */
|
||||
err = ocelot_ptp_tx_type_to_cmd(cfg.tx_type, &ptp_cmd);
|
||||
err = ocelot_ptp_tx_type_to_cmd(cfg->tx_type, &ptp_cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (cfg.rx_filter) {
|
||||
switch (cfg->rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
|
@ -577,27 +572,15 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
|
|||
return -ERANGE;
|
||||
}
|
||||
|
||||
old_l2 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L2;
|
||||
old_l4 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L4;
|
||||
|
||||
err = ocelot_setup_ptp_traps(ocelot, port, l2, l4);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ocelot_port->ptp_cmd = ptp_cmd;
|
||||
|
||||
cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
|
||||
|
||||
if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) {
|
||||
err = -EFAULT;
|
||||
goto out_restore_ptp_traps;
|
||||
}
|
||||
cfg->rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
|
||||
|
||||
return 0;
|
||||
out_restore_ptp_traps:
|
||||
ocelot_setup_ptp_traps(ocelot, port, old_l2, old_l4);
|
||||
ocelot_port->ptp_cmd = old_ptp_cmd;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(ocelot_hwstamp_set);
|
||||
|
||||
|
|
|
@ -1131,9 +1131,10 @@ struct dsa_switch_ops {
|
|||
* PTP functionality
|
||||
*/
|
||||
int (*port_hwtstamp_get)(struct dsa_switch *ds, int port,
|
||||
struct ifreq *ifr);
|
||||
struct kernel_hwtstamp_config *config);
|
||||
int (*port_hwtstamp_set)(struct dsa_switch *ds, int port,
|
||||
struct ifreq *ifr);
|
||||
struct kernel_hwtstamp_config *config,
|
||||
struct netlink_ext_ack *extack);
|
||||
void (*port_txtstamp)(struct dsa_switch *ds, int port,
|
||||
struct sk_buff *skb);
|
||||
bool (*port_rxtstamp)(struct dsa_switch *ds, int port,
|
||||
|
|
|
@ -1073,8 +1073,11 @@ int ocelot_vlan_prepare(struct ocelot *ocelot, int port, u16 vid, bool pvid,
|
|||
int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
|
||||
bool untagged);
|
||||
int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid);
|
||||
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr);
|
||||
int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr);
|
||||
void ocelot_hwstamp_get(struct ocelot *ocelot, int port,
|
||||
struct kernel_hwtstamp_config *cfg);
|
||||
int ocelot_hwstamp_set(struct ocelot *ocelot, int port,
|
||||
struct kernel_hwtstamp_config *cfg,
|
||||
struct netlink_ext_ack *extack);
|
||||
int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
|
||||
struct sk_buff *skb,
|
||||
struct sk_buff **clone);
|
||||
|
|
|
@ -116,19 +116,15 @@ static bool dsa_port_can_configure_learning(struct dsa_port *dp)
|
|||
|
||||
bool dsa_port_supports_hwtstamp(struct dsa_port *dp)
|
||||
{
|
||||
struct kernel_hwtstamp_config config = {};
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
struct ifreq ifr = {};
|
||||
int err;
|
||||
|
||||
if (!ds->ops->port_hwtstamp_get || !ds->ops->port_hwtstamp_set)
|
||||
return false;
|
||||
|
||||
/* "See through" shim implementations of the "get" method.
|
||||
* Since we can't cook up a complete ioctl request structure, this will
|
||||
* fail in copy_to_user() with -EFAULT, which hopefully is enough to
|
||||
* detect a valid implementation.
|
||||
*/
|
||||
err = ds->ops->port_hwtstamp_get(ds, dp->index, &ifr);
|
||||
/* "See through" shim implementations of the "get" method. */
|
||||
err = ds->ops->port_hwtstamp_get(ds, dp->index, &config);
|
||||
return err != -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
|
|
@ -578,20 +578,6 @@ dsa_user_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|||
static int dsa_user_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct dsa_user_priv *p = netdev_priv(dev);
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
int port = p->dp->index;
|
||||
|
||||
/* Pass through to switch driver if it supports timestamping */
|
||||
switch (cmd) {
|
||||
case SIOCGHWTSTAMP:
|
||||
if (ds->ops->port_hwtstamp_get)
|
||||
return ds->ops->port_hwtstamp_get(ds, port, ifr);
|
||||
break;
|
||||
case SIOCSHWTSTAMP:
|
||||
if (ds->ops->port_hwtstamp_set)
|
||||
return ds->ops->port_hwtstamp_set(ds, port, ifr);
|
||||
break;
|
||||
}
|
||||
|
||||
return phylink_mii_ioctl(p->dp->pl, ifr, cmd);
|
||||
}
|
||||
|
@ -2574,6 +2560,31 @@ static int dsa_user_fill_forward_path(struct net_device_path_ctx *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dsa_user_hwtstamp_get(struct net_device *dev,
|
||||
struct kernel_hwtstamp_config *cfg)
|
||||
{
|
||||
struct dsa_port *dp = dsa_user_to_port(dev);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (!ds->ops->port_hwtstamp_get)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ds->ops->port_hwtstamp_get(ds, dp->index, cfg);
|
||||
}
|
||||
|
||||
static int dsa_user_hwtstamp_set(struct net_device *dev,
|
||||
struct kernel_hwtstamp_config *cfg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct dsa_port *dp = dsa_user_to_port(dev);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (!ds->ops->port_hwtstamp_set)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ds->ops->port_hwtstamp_set(ds, dp->index, cfg, extack);
|
||||
}
|
||||
|
||||
static const struct net_device_ops dsa_user_netdev_ops = {
|
||||
.ndo_open = dsa_user_open,
|
||||
.ndo_stop = dsa_user_close,
|
||||
|
@ -2595,6 +2606,8 @@ static const struct net_device_ops dsa_user_netdev_ops = {
|
|||
.ndo_vlan_rx_kill_vid = dsa_user_vlan_rx_kill_vid,
|
||||
.ndo_change_mtu = dsa_user_change_mtu,
|
||||
.ndo_fill_forward_path = dsa_user_fill_forward_path,
|
||||
.ndo_hwtstamp_get = dsa_user_hwtstamp_get,
|
||||
.ndo_hwtstamp_set = dsa_user_hwtstamp_set,
|
||||
};
|
||||
|
||||
static const struct device_type dsa_type = {
|
||||
|
|
Loading…
Reference in New Issue
Block a user