]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
net: mscc: ocelot: always pass skb clone to ocelot_port_add_txtstamp_skb
authorVladimir Oltean <vladimir.oltean@nxp.com>
Wed, 23 Sep 2020 11:24:20 +0000 (14:24 +0300)
committerDavid S. Miller <davem@davemloft.net>
Fri, 25 Sep 2020 02:47:56 +0000 (19:47 -0700)
Currently, ocelot switchdev passes the skb directly to the function that
enqueues it to the list of skb's awaiting a TX timestamp. Whereas the
felix DSA driver first clones the skb, then passes the clone to this
queue.

This matters because in the case of felix, the common IRQ handler, which
is ocelot_get_txtstamp(), currently clones the clone, and frees the
original clone. This is useless and can be simplified by using
skb_complete_tx_timestamp() instead of skb_tstamp_tx().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/ocelot/felix.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_net.c
include/soc/mscc/ocelot.h
net/dsa/tag_ocelot.c

index 5f395d4119ac783da641b2c194587b16f0175680..a56fc50f5be401fadb0149f9ee16d52f3f082c0d 100644 (file)
@@ -669,8 +669,11 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port,
        struct ocelot *ocelot = ds->priv;
        struct ocelot_port *ocelot_port = ocelot->ports[port];
 
-       if (!ocelot_port_add_txtstamp_skb(ocelot_port, clone))
+       if (ocelot->ptp && (skb_shinfo(clone)->tx_flags & SKBTX_HW_TSTAMP) &&
+           ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
+               ocelot_port_add_txtstamp_skb(ocelot, port, clone);
                return true;
+       }
 
        return false;
 }
index 8518e1d60da4f3b9cec248dbbb1239f28d8929fd..0445c5ee55515daf72c5acc34c17db46eb74ee78 100644 (file)
@@ -413,26 +413,20 @@ void ocelot_port_disable(struct ocelot *ocelot, int port)
 }
 EXPORT_SYMBOL(ocelot_port_disable);
 
-int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
-                                struct sk_buff *skb)
+void ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
+                                 struct sk_buff *clone)
 {
-       struct skb_shared_info *shinfo = skb_shinfo(skb);
-       struct ocelot *ocelot = ocelot_port->ocelot;
+       struct ocelot_port *ocelot_port = ocelot->ports[port];
 
-       if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
-           ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
-               spin_lock(&ocelot_port->ts_id_lock);
+       spin_lock(&ocelot_port->ts_id_lock);
 
-               shinfo->tx_flags |= SKBTX_IN_PROGRESS;
-               /* Store timestamp ID in cb[0] of sk_buff */
-               skb->cb[0] = ocelot_port->ts_id;
-               ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
-               skb_queue_tail(&ocelot_port->tx_skbs, skb);
+       skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
+       /* Store timestamp ID in cb[0] of sk_buff */
+       clone->cb[0] = ocelot_port->ts_id;
+       ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
+       skb_queue_tail(&ocelot_port->tx_skbs, clone);
 
-               spin_unlock(&ocelot_port->ts_id_lock);
-               return 0;
-       }
-       return -ENODATA;
+       spin_unlock(&ocelot_port->ts_id_lock);
 }
 EXPORT_SYMBOL(ocelot_port_add_txtstamp_skb);
 
@@ -511,9 +505,7 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
                /* Set the timestamp into the skb */
                memset(&shhwtstamps, 0, sizeof(shhwtstamps));
                shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
-               skb_tstamp_tx(skb_match, &shhwtstamps);
-
-               dev_kfree_skb_any(skb_match);
+               skb_complete_tx_timestamp(skb_match, &shhwtstamps);
 
                /* Next ts */
                ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
index 8490e42e9e2d5d4ce99e65cf4db1538a57808328..028a0150f97d5efcfacd984184194325f77dfc24 100644 (file)
@@ -330,7 +330,6 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
        u8 grp = 0; /* Send everything on CPU group 0 */
        unsigned int i, count, last;
        int port = priv->chip_port;
-       bool do_tstamp;
 
        val = ocelot_read(ocelot, QS_INJ_STATUS);
        if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))) ||
@@ -345,7 +344,23 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
        info.vid = skb_vlan_tag_get(skb);
 
        /* Check if timestamping is needed */
-       do_tstamp = (ocelot_port_add_txtstamp_skb(ocelot_port, skb) == 0);
+       if (ocelot->ptp && (shinfo->tx_flags & SKBTX_HW_TSTAMP)) {
+               info.rew_op = ocelot_port->ptp_cmd;
+
+               if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
+                       struct sk_buff *clone;
+
+                       clone = skb_clone_sk(skb);
+                       if (!clone) {
+                               kfree_skb(skb);
+                               return NETDEV_TX_OK;
+                       }
+
+                       ocelot_port_add_txtstamp_skb(ocelot, port, clone);
+
+                       info.rew_op |= clone->cb[0] << 3;
+               }
+       }
 
        if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
                info.rew_op = ocelot_port->ptp_cmd;
@@ -383,8 +398,7 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->stats.tx_packets++;
        dev->stats.tx_bytes += skb->len;
 
-       if (!do_tstamp)
-               dev_kfree_skb_any(skb);
+       kfree_skb(skb);
 
        return NETDEV_TX_OK;
 }
index 0ac4e7fba086f623535632a82216c3980e78d083..3105bbb6cdcff0b35c8528f3f6be3bc1570522d5 100644 (file)
@@ -710,8 +710,8 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
 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);
-int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
-                                struct sk_buff *skb);
+void ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
+                                 struct sk_buff *clone);
 void ocelot_get_txtstamp(struct ocelot *ocelot);
 void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu);
 int ocelot_get_max_mtu(struct ocelot *ocelot, int port);
index b4fc05cafaa61e99ca14a564801b42018dd6fb35..d1a7e224adff80764dab04e59114549dd7f3f2c2 100644 (file)
@@ -137,6 +137,7 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
                                   struct net_device *netdev)
 {
        struct dsa_port *dp = dsa_slave_to_port(netdev);
+       struct sk_buff *clone = DSA_SKB_CB(skb)->clone;
        struct dsa_switch *ds = dp->ds;
        struct ocelot *ocelot = ds->priv;
        struct ocelot_port *ocelot_port;
@@ -159,9 +160,8 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
        qos_class = skb->priority;
        packing(injection, &qos_class, 19,  17, OCELOT_TAG_LEN, PACK, 0);
 
-       if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
-               struct sk_buff *clone = DSA_SKB_CB(skb)->clone;
-
+       /* TX timestamping was requested */
+       if (clone) {
                rew_op = ocelot_port->ptp_cmd;
                /* Retrieve timestamp ID populated inside skb->cb[0] of the
                 * clone by ocelot_port_add_txtstamp_skb