]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
net: dsa: no longer clone skb in core driver
authorYangbo Lu <yangbo.lu@nxp.com>
Tue, 27 Apr 2021 04:21:59 +0000 (12:21 +0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 27 Apr 2021 21:10:15 +0000 (14:10 -0700)
It was a waste to clone skb directly in dsa_skb_tx_timestamp().
For one-step timestamping, a clone was not needed. For any failure of
port_txtstamp (this may usually happen), the skb clone had to be freed.

So this patch moves skb cloning for tx timestamp out of dsa core, and
let drivers clone skb in port_txtstamp if they really need.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Tested-by: Kurt Kanzenbach <kurt@linutronix.de>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c
drivers/net/dsa/hirschmann/hellcreek_hwtstamp.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
include/net/dsa.h
net/dsa/slave.c

index 5b2e023468fe9908a54647cdeb092c671a9ede06..40b41c794dfacbb45a5ebba88714009e3452ae67 100644 (file)
@@ -373,31 +373,38 @@ long hellcreek_hwtstamp_work(struct ptp_clock_info *ptp)
        return restart ? 1 : -1;
 }
 
-bool hellcreek_port_txtstamp(struct dsa_switch *ds, int port,
-                            struct sk_buff *clone)
+void hellcreek_port_txtstamp(struct dsa_switch *ds, int port,
+                            struct sk_buff *skb)
 {
        struct hellcreek *hellcreek = ds->priv;
        struct hellcreek_port_hwtstamp *ps;
        struct ptp_header *hdr;
+       struct sk_buff *clone;
        unsigned int type;
 
        ps = &hellcreek->ports[port].port_hwtstamp;
 
-       type = ptp_classify_raw(clone);
+       type = ptp_classify_raw(skb);
        if (type == PTP_CLASS_NONE)
-               return false;
+               return;
 
        /* Make sure the message is a PTP message that needs to be timestamped
         * and the interaction with the HW timestamping is enabled. If not, stop
         * here
         */
-       hdr = hellcreek_should_tstamp(hellcreek, port, clone, type);
+       hdr = hellcreek_should_tstamp(hellcreek, port, skb, type);
        if (!hdr)
-               return false;
+               return;
+
+       clone = skb_clone_sk(skb);
+       if (!clone)
+               return;
 
        if (test_and_set_bit_lock(HELLCREEK_HWTSTAMP_TX_IN_PROGRESS,
-                                 &ps->state))
-               return false;
+                                 &ps->state)) {
+               kfree_skb(clone);
+               return;
+       }
 
        ps->tx_skb = clone;
 
@@ -407,8 +414,6 @@ bool hellcreek_port_txtstamp(struct dsa_switch *ds, int port,
        ps->tx_tstamp_start = jiffies;
 
        ptp_schedule_worker(hellcreek->ptp_clock, 0);
-
-       return true;
 }
 
 bool hellcreek_port_rxtstamp(struct dsa_switch *ds, int port,
index 728cd5dc650f03c66e452127d890ebf6683d641f..71af77efb28b206443f7e654f30f9901c1714787 100644 (file)
@@ -44,8 +44,8 @@ int hellcreek_port_hwtstamp_get(struct dsa_switch *ds, int port,
 
 bool hellcreek_port_rxtstamp(struct dsa_switch *ds, int port,
                             struct sk_buff *clone, unsigned int type);
-bool hellcreek_port_txtstamp(struct dsa_switch *ds, int port,
-                            struct sk_buff *clone);
+void hellcreek_port_txtstamp(struct dsa_switch *ds, int port,
+                            struct sk_buff *skb);
 
 int hellcreek_get_ts_info(struct dsa_switch *ds, int port,
                          struct ethtool_ts_info *info);
index 79514a54d9030514a3cae05849f25b532113a514..8f74ffc7a2799d5f229823688a921fe2aad89b55 100644 (file)
@@ -468,32 +468,38 @@ long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp)
        return restart ? 1 : -1;
 }
 
-bool mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
-                            struct sk_buff *clone)
+void mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
+                            struct sk_buff *skb)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
        struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
        struct ptp_header *hdr;
+       struct sk_buff *clone;
        unsigned int type;
 
-       type = ptp_classify_raw(clone);
+       type = ptp_classify_raw(skb);
        if (type == PTP_CLASS_NONE)
-               return false;
+               return;
 
-       hdr = mv88e6xxx_should_tstamp(chip, port, clone, type);
+       hdr = mv88e6xxx_should_tstamp(chip, port, skb, type);
        if (!hdr)
-               return false;
+               return;
+
+       clone = skb_clone_sk(skb);
+       if (!clone)
+               return;
 
        if (test_and_set_bit_lock(MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS,
-                                 &ps->state))
-               return false;
+                                 &ps->state)) {
+               kfree_skb(clone);
+               return;
+       }
 
        ps->tx_skb = clone;
        ps->tx_tstamp_start = jiffies;
        ps->tx_seq_id = be16_to_cpu(hdr->sequence_id);
 
        ptp_schedule_worker(chip->ptp_clock, 0);
-       return true;
 }
 
 int mv88e6165_global_disable(struct mv88e6xxx_chip *chip)
index 91fbc7838fc87fc14cb811307bb6e48069b13500..cf7fb6d660b175b741d1743e1a204b11c465db88 100644 (file)
@@ -117,8 +117,8 @@ int mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds, int port,
 
 bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
                             struct sk_buff *clone, unsigned int type);
-bool mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
-                            struct sk_buff *clone);
+void mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
+                            struct sk_buff *skb);
 
 int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
                          struct ethtool_ts_info *info);
@@ -151,10 +151,9 @@ static inline bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
        return false;
 }
 
-static inline bool mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
-                                          struct sk_buff *clone)
+static inline void mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
+                                          struct sk_buff *skb)
 {
-       return false;
 }
 
 static inline int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
index d679f023dc0019bd1af646a14723590a87edaa8d..fe7e8bad90dfec962eab88f043ce317db3667b1a 100644 (file)
@@ -1395,18 +1395,21 @@ static bool felix_rxtstamp(struct dsa_switch *ds, int port,
        return false;
 }
 
-static bool felix_txtstamp(struct dsa_switch *ds, int port,
-                          struct sk_buff *clone)
+static void felix_txtstamp(struct dsa_switch *ds, int port,
+                          struct sk_buff *skb)
 {
        struct ocelot *ocelot = ds->priv;
        struct ocelot_port *ocelot_port = ocelot->ports[port];
+       struct sk_buff *clone;
 
        if (ocelot->ptp && ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
+               clone = skb_clone_sk(skb);
+               if (!clone)
+                       return;
+
                ocelot_port_add_txtstamp_skb(ocelot, port, clone);
-               return true;
+               DSA_SKB_CB(skb)->clone = clone;
        }
-
-       return false;
 }
 
 static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
index 72d052de82d8986e7bcb163e82ae7e5f46bda5d5..a5140084000df0d57c3d87b1fe50855bc07c113f 100644 (file)
@@ -431,19 +431,24 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
        return true;
 }
 
-/* Called from dsa_skb_tx_timestamp. This callback is just to make DSA clone
+/* Called from dsa_skb_tx_timestamp. This callback is just to clone
  * the skb and have it available in DSA_SKB_CB in the .port_deferred_xmit
  * callback, where we will timestamp it synchronously.
  */
-bool sja1105_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
+void sja1105_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
 {
        struct sja1105_private *priv = ds->priv;
        struct sja1105_port *sp = &priv->ports[port];
+       struct sk_buff *clone;
 
        if (!sp->hwts_tx_en)
-               return false;
+               return;
 
-       return true;
+       clone = skb_clone_sk(skb);
+       if (!clone)
+               return;
+
+       DSA_SKB_CB(skb)->clone = clone;
 }
 
 static int sja1105_ptp_reset(struct dsa_switch *ds)
index c70c4729a06d73b2076684c4e718919ac82442b8..34f97f58a35595eeb2c69294d2e3bd7d890aa41e 100644 (file)
@@ -104,7 +104,7 @@ void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
 bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
                           struct sk_buff *skb, unsigned int type);
 
-bool sja1105_port_txtstamp(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);
index 905066055b08d97e21772dd0b3ee4402c2fd2d6e..73ce6ce38aa1bd716884e8ffaa64720231454f6e 100644 (file)
@@ -740,8 +740,8 @@ struct dsa_switch_ops {
                                     struct ifreq *ifr);
        int     (*port_hwtstamp_set)(struct dsa_switch *ds, int port,
                                     struct ifreq *ifr);
-       bool    (*port_txtstamp)(struct dsa_switch *ds, int port,
-                                struct sk_buff *clone);
+       void    (*port_txtstamp)(struct dsa_switch *ds, int port,
+                                struct sk_buff *skb);
        bool    (*port_rxtstamp)(struct dsa_switch *ds, int port,
                                 struct sk_buff *skb, unsigned int type);
 
index acaa52e60d7f09d5287795dca5b966a5fbcb8f99..85e51f46a9d5d60e6207ec6ed9db5c5c3c97fb40 100644 (file)
@@ -555,7 +555,6 @@ static void dsa_skb_tx_timestamp(struct dsa_slave_priv *p,
                                 struct sk_buff *skb)
 {
        struct dsa_switch *ds = p->dp->ds;
-       struct sk_buff *clone;
 
        if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
                return;
@@ -563,16 +562,7 @@ static void dsa_skb_tx_timestamp(struct dsa_slave_priv *p,
        if (!ds->ops->port_txtstamp)
                return;
 
-       clone = skb_clone_sk(skb);
-       if (!clone)
-               return;
-
-       if (ds->ops->port_txtstamp(ds, p->dp->index, clone)) {
-               DSA_SKB_CB(skb)->clone = clone;
-               return;
-       }
-
-       kfree_skb(clone);
+       ds->ops->port_txtstamp(ds, p->dp->index, skb);
 }
 
 netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev)