]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: dsa: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set()
authorVladimir Oltean <vladimir.oltean@nxp.com>
Thu, 8 May 2025 09:52:36 +0000 (12:52 +0300)
committerJakub Kicinski <kuba@kernel.org>
Fri, 9 May 2025 23:34:09 +0000 (16:34 -0700)
New timestamping API was introduced in commit 66f7223039c0 ("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>
18 files changed:
drivers/net/dsa/hirschmann/hellcreek.h
drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c
drivers/net/dsa/hirschmann/hellcreek_hwtstamp.h
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/microchip/ksz_ptp.c
drivers/net/dsa/microchip/ksz_ptp.h
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/mv88e6xxx/hwtstamp.c
drivers/net/dsa/mv88e6xxx/hwtstamp.h
drivers/net/dsa/ocelot/felix.c
drivers/net/dsa/sja1105/sja1105_ptp.c
drivers/net/dsa/sja1105/sja1105_ptp.h
drivers/net/ethernet/mscc/ocelot_net.c
drivers/net/ethernet/mscc/ocelot_ptp.c
include/net/dsa.h
include/soc/mscc/ocelot.h
net/dsa/port.c
net/dsa/user.c

index 9c2ed2ba79daccf54b7b6fea73e756e0870d6452..bebf0d3ff3302d01ee3aaac1437d23a1b2f42daf 100644 (file)
@@ -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 {
index ca2500aba96fa2f0d930fce9c67229d97b44e712..99941ff1ebf9b1ad79c414d62274a3a39df2f473 100644 (file)
@@ -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
index 7d88da2134f2ddc355332f498d2a0684c38123b1..388821c4aa101a3eb5b8401c40bef427c2209a97 100644 (file)
 #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);
index dd5429ff16eee2614b038aff73f2029087533d25..a034017568cd9c12870fa4d5f8b0536f3a469958 100644 (file)
@@ -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;
index 22fb9ef4645c184a667298b1a3f0b7c44b9ccba4..bc54a96ba6461cb7d89c5e0247e8897e4bf688d1 100644 (file)
@@ -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;
 }
index 2f1783c0d723177ee90c4155bc83c84b1b84518d..3086e519b1b641e9e4126cb6ff43409f6d7f29a5 100644 (file)
@@ -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,
index 86bf113c9bfa1e9ca15d0d651ea96a56a4c14605..7d00482f53a3b69424d4171dd272b704e282adb7 100644 (file)
@@ -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 {
index 49e6e1355142dc95ab620e46db603fe17012f174..f663799b0b3b42b3cd71ae7a5b2915d1badb2ca8 100644 (file)
@@ -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,
index 85acc758e3eb1c3f1d1abfab23200dd664727c9b..22e4acc957f0ba713def36d40ff087676e206648 100644 (file)
 #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;
 }
index 0a4e682a55ef5760d024c720167f913e553d218b..2dd4e56e1cf11014cc4997eae7317883018fe888 100644 (file)
@@ -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;
 
index 3abc64aec411acd95ef1ef608f931756d0e6cc98..fefe46e2a5e612e1169006d0bd4c43252f51260e 100644 (file)
@@ -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,
index 8add2bd5f72842d1e08fca466ad0c72d1de8c17b..325e3777ea07fe6dd144a3a674dfcc4474c6c44a 100644 (file)
@@ -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);
index 7663d196eaf89bab65928d5bf4f0be1cee71e852..469784d3a1a67b061be22d961b0e953d44dfb39d 100644 (file)
@@ -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)
index d2a0a32f75ea90529641d2288fa56d3ab6d0f2e6..88b5422cc2a0cc7e0b6b0d59283cc3ab2608a16d 100644 (file)
@@ -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);
 
index a0a9481c52c290f92e6f28433d5697175c0ca07b..55e2d97f247eb0305baaf5719782269433918f18 100644 (file)
@@ -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,
index 6db7fc9dbaa49252dab52398d7df7f07bff11b40..48d6deb3efd7151493e014c4fbbfa3358c78c29e 100644 (file)
@@ -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);
index 5c9d1798e830a0dd2ff863ed6506b819c994c146..082573ae6864aabe4d18c2d966432e150432015d 100644 (file)
@@ -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;
 }
 
index 804dc7dac4f2fee08043d09eaca44fa83e0f4d79..e9334520c54a35c48c74031feb602c06d9763a0d 100644 (file)
@@ -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 = {