]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: mscc: ocelot: use common tag parsing code with DSA
authorVladimir Oltean <vladimir.oltean@nxp.com>
Sat, 13 Feb 2021 22:37:56 +0000 (00:37 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 15 Feb 2021 01:31:44 +0000 (17:31 -0800)
The Injection Frame Header and Extraction Frame Header that the switch
prepends to frames over the NPI port is also prepended to frames
delivered over the CPU port module's queues.

Let's unify the handling of the frame headers by making the ocelot
driver call some helpers exported by the DSA tagger. Among other things,
this allows us to get rid of the strange cpu_to_be32 when transmitting
the Injection Frame Header on ocelot, since the packing API uses
network byte order natively (when "quirks" is 0).

The comments above ocelot_gen_ifh talk about setting pop_cnt to 3, and
the cpu extraction queue mask to something, but the code doesn't do it,
so we don't do it either.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/ocelot/felix.c
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/dsa/ocelot/seville_vsc9953.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot.h
drivers/net/ethernet/mscc/ocelot_vsc7514.c
include/linux/dsa/ocelot.h [new file with mode: 0644]
include/soc/mscc/ocelot.h
net/dsa/tag_ocelot.c

index d3180b0f2307fdece78827c9a135ed76fa518404..60e0d354adea95d2c40181ce8fe5a36597af3a6f 100644 (file)
@@ -14,8 +14,8 @@
 #include <soc/mscc/ocelot_ptp.h>
 #include <soc/mscc/ocelot.h>
 #include <linux/dsa/8021q.h>
+#include <linux/dsa/ocelot.h>
 #include <linux/platform_device.h>
-#include <linux/packing.h>
 #include <linux/module.h>
 #include <linux/of_net.h>
 #include <linux/pci.h>
@@ -1161,9 +1161,9 @@ static int felix_hwtstamp_set(struct dsa_switch *ds, int port,
 static bool felix_rxtstamp(struct dsa_switch *ds, int port,
                           struct sk_buff *skb, unsigned int type)
 {
+       u8 *extraction = skb->data - ETH_HLEN - OCELOT_TAG_LEN;
        struct skb_shared_hwtstamps *shhwtstamps;
        struct ocelot *ocelot = ds->priv;
-       u8 *extraction = skb->data - ETH_HLEN - OCELOT_TAG_LEN;
        u32 tstamp_lo, tstamp_hi;
        struct timespec64 ts;
        u64 tstamp, val;
@@ -1171,7 +1171,7 @@ static bool felix_rxtstamp(struct dsa_switch *ds, int port,
        ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);
        tstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
 
-       packing(extraction, &val,  116, 85, OCELOT_TAG_LEN, UNPACK, 0);
+       ocelot_xfh_get_rew_val(extraction, &val);
        tstamp_lo = (u32)val;
 
        tstamp_hi = tstamp >> 32;
index e944868cc120bf7c4665ff28a6ff1d7fb8882c67..cacc6f9c01135cd9763fa2db3e69f6c83935db9a 100644 (file)
@@ -8,7 +8,7 @@
 #include <soc/mscc/ocelot_ptp.h>
 #include <soc/mscc/ocelot_sys.h>
 #include <soc/mscc/ocelot.h>
-#include <linux/packing.h>
+#include <linux/dsa/ocelot.h>
 #include <linux/pcs-lynx.h>
 #include <net/pkt_sched.h>
 #include <linux/iopoll.h>
index 512f677a6c1c5682f81fffd893d7a925f2bc0c05..d7348ea4831e7720c96214a9f2018f75695e93d2 100644 (file)
@@ -8,7 +8,7 @@
 #include <soc/mscc/ocelot.h>
 #include <linux/of_platform.h>
 #include <linux/pcs-lynx.h>
-#include <linux/packing.h>
+#include <linux/dsa/ocelot.h>
 #include <linux/iopoll.h>
 #include "felix.h"
 
index 7106d9ee534a0b72eb215af60140c08aaca2d8c1..699b0c1c178096ca21fbe5cf8ca8722c6a7d6c6d 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2017 Microsemi Corporation
  */
+#include <linux/dsa/ocelot.h>
 #include <linux/if_bridge.h>
 #include <soc/mscc/ocelot_vcap.h>
 #include "ocelot.h"
@@ -628,26 +629,6 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
 }
 EXPORT_SYMBOL(ocelot_get_txtstamp);
 
-/* Generate the IFH for frame injection
- *
- * The IFH is a 128bit-value
- * bit 127: bypass the analyzer processing
- * bit 56-67: destination mask
- * bit 28-29: pop_cnt: 3 disables all rewriting of the frame
- * bit 20-27: cpu extraction queue mask
- * bit 16: tag type 0: C-tag, 1: S-tag
- * bit 0-11: VID
- */
-static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
-{
-       ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21);
-       ifh[1] = (0xf00 & info->port) >> 8;
-       ifh[2] = (0xff & info->port) << 24;
-       ifh[3] = (info->tag_type << 16) | info->vid;
-
-       return 0;
-}
-
 bool ocelot_can_inject(struct ocelot *ocelot, int grp)
 {
        u32 val = ocelot_read(ocelot, QS_INJ_STATUS);
@@ -664,23 +645,20 @@ EXPORT_SYMBOL(ocelot_can_inject);
 void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp,
                              u32 rew_op, struct sk_buff *skb)
 {
-       struct frame_info info = {};
-       u32 ifh[OCELOT_TAG_LEN / 4];
+       u32 ifh[OCELOT_TAG_LEN / 4] = {0};
        unsigned int i, count, last;
 
        ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
                         QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp);
 
-       info.port = BIT(port);
-       info.tag_type = IFH_TAG_TYPE_C;
-       info.vid = skb_vlan_tag_get(skb);
-       info.rew_op = rew_op;
-
-       ocelot_gen_ifh(ifh, &info);
+       ocelot_ifh_set_bypass(ifh, 1);
+       ocelot_ifh_set_dest(ifh, BIT(port));
+       ocelot_ifh_set_tag_type(ifh, IFH_TAG_TYPE_C);
+       ocelot_ifh_set_vid(ifh, skb_vlan_tag_get(skb));
+       ocelot_ifh_set_rew_op(ifh, rew_op);
 
        for (i = 0; i < OCELOT_TAG_LEN / 4; i++)
-               ocelot_write_rix(ocelot, (__force u32)cpu_to_be32(ifh[i]),
-                                QS_INJ_WR, grp);
+               ocelot_write_rix(ocelot, ifh[i], QS_INJ_WR, grp);
 
        count = DIV_ROUND_UP(skb->len, 4);
        last = skb->len % 4;
index c485795c606bad9dbe5de7c41a8751d6ac8ef2f5..db6b1a4c392649c963be26ae85a443dd5a019e9b 100644 (file)
 
 #define OCELOT_PTP_QUEUE_SZ    128
 
-struct frame_info {
-       u32 len;
-       u16 port;
-       u16 vid;
-       u8 tag_type;
-       u16 rew_op;
-       u32 timestamp;  /* rew_val */
-};
-
 struct ocelot_port_tc {
        bool block_shared;
        unsigned long offload_cnt;
index b075dc13354a2fb1740a4b001ea2f763fbf8f666..fe0f8d6a32cee6ef5877e3e75ef7d4a008a7bd10 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2017 Microsemi Corporation
  */
+#include <linux/dsa/ocelot.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of_net.h>
@@ -18,8 +19,6 @@
 #include <soc/mscc/ocelot_hsio.h>
 #include "ocelot.h"
 
-#define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0))
-
 static const u32 ocelot_ana_regmap[] = {
        REG(ANA_ADVLEARN,                               0x009000),
        REG(ANA_VLANMASK,                               0x009004),
@@ -532,29 +531,6 @@ static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)
        return 0;
 }
 
-static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
-{
-       u8 llen, wlen;
-       u64 ifh[2];
-
-       ifh[0] = be64_to_cpu(((__force __be64 *)_ifh)[0]);
-       ifh[1] = be64_to_cpu(((__force __be64 *)_ifh)[1]);
-
-       wlen = IFH_EXTRACT_BITFIELD64(ifh[0], 7,  8);
-       llen = IFH_EXTRACT_BITFIELD64(ifh[0], 15,  6);
-
-       info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80;
-
-       info->timestamp = IFH_EXTRACT_BITFIELD64(ifh[0], 21, 32);
-
-       info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
-
-       info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16,  1);
-       info->vid = IFH_EXTRACT_BITFIELD64(ifh[1], 0,  12);
-
-       return 0;
-}
-
 static int ocelot_rx_frame_word(struct ocelot *ocelot, u8 grp, bool ifh,
                                u32 *rval)
 {
@@ -609,20 +585,20 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
                struct ocelot_port_private *priv;
                struct ocelot_port *ocelot_port;
                u64 tod_in_ns, full_ts_in_ns;
-               struct frame_info info = {};
+               u64 src_port, len, timestamp;
                struct net_device *dev;
-               u32 ifh[4], val, *buf;
+               u32 xfh[4], val, *buf;
                struct timespec64 ts;
-               int sz, len, buf_len;
                struct sk_buff *skb;
+               int sz, buf_len;
 
                for (i = 0; i < OCELOT_TAG_LEN / 4; i++) {
-                       err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]);
+                       err = ocelot_rx_frame_word(ocelot, grp, true, &xfh[i]);
                        if (err != 4)
                                goto out;
                }
 
-               /* At this point the IFH was read correctly, so it is safe to
+               /* At this point the XFH was read correctly, so it is safe to
                 * presume that there is no error. The err needs to be reset
                 * otherwise a frame could come in CPU queue between the while
                 * condition and the check for error later on. And in that case
@@ -630,21 +606,23 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
                 */
                err = 0;
 
-               ocelot_parse_ifh(ifh, &info);
+               ocelot_xfh_get_src_port(xfh, &src_port);
+               ocelot_xfh_get_len(xfh, &len);
+               ocelot_xfh_get_rew_val(xfh, &timestamp);
 
-               ocelot_port = ocelot->ports[info.port];
+               ocelot_port = ocelot->ports[src_port];
                priv = container_of(ocelot_port, struct ocelot_port_private,
                                    port);
                dev = priv->dev;
 
-               skb = netdev_alloc_skb(dev, info.len);
+               skb = netdev_alloc_skb(dev, len);
 
                if (unlikely(!skb)) {
                        netdev_err(dev, "Unable to allocate sk_buff\n");
                        err = -ENOMEM;
                        goto out;
                }
-               buf_len = info.len - ETH_FCS_LEN;
+               buf_len = len - ETH_FCS_LEN;
                buf = (u32 *)skb_put(skb, buf_len);
 
                len = 0;
@@ -677,12 +655,12 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
                        ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);
 
                        tod_in_ns = ktime_set(ts.tv_sec, ts.tv_nsec);
-                       if ((tod_in_ns & 0xffffffff) < info.timestamp)
+                       if ((tod_in_ns & 0xffffffff) < timestamp)
                                full_ts_in_ns = (((tod_in_ns >> 32) - 1) << 32) |
-                                               info.timestamp;
+                                               timestamp;
                        else
                                full_ts_in_ns = (tod_in_ns & GENMASK_ULL(63, 32)) |
-                                               info.timestamp;
+                                               timestamp;
 
                        shhwtstamps = skb_hwtstamps(skb);
                        memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
@@ -692,7 +670,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
                /* Everything we see on an interface that is in the HW bridge
                 * has already been forwarded.
                 */
-               if (ocelot->bridge_mask & BIT(info.port))
+               if (ocelot->bridge_mask & BIT(src_port))
                        skb->offload_fwd_mark = 1;
 
                skb->protocol = eth_type_trans(skb, dev);
diff --git a/include/linux/dsa/ocelot.h b/include/linux/dsa/ocelot.h
new file mode 100644 (file)
index 0000000..763dbbf
--- /dev/null
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright 2019-2021 NXP Semiconductors
+ */
+
+#ifndef _NET_DSA_TAG_OCELOT_H
+#define _NET_DSA_TAG_OCELOT_H
+
+#include <linux/packing.h>
+
+#define OCELOT_TAG_LEN                 16
+#define OCELOT_SHORT_PREFIX_LEN                4
+#define OCELOT_LONG_PREFIX_LEN         16
+#define OCELOT_TOTAL_TAG_LEN   (OCELOT_SHORT_PREFIX_LEN + OCELOT_TAG_LEN)
+
+/* The CPU injection header and the CPU extraction header can have 3 types of
+ * prefixes: long, short and no prefix. The format of the header itself is the
+ * same in all 3 cases.
+ *
+ * Extraction with long prefix:
+ *
+ * +-------------------+-------------------+------+------+------------+-------+
+ * | ff:ff:ff:ff:ff:ff | fe:ff:ff:ff:ff:ff | 8880 | 000a | extraction | frame |
+ * |                   |                   |      |      |   header   |       |
+ * +-------------------+-------------------+------+------+------------+-------+
+ *        48 bits             48 bits      16 bits 16 bits  128 bits
+ *
+ * Extraction with short prefix:
+ *
+ *                                         +------+------+------------+-------+
+ *                                         | 8880 | 000a | extraction | frame |
+ *                                         |      |      |   header   |       |
+ *                                         +------+------+------------+-------+
+ *                                         16 bits 16 bits  128 bits
+ *
+ * Extraction with no prefix:
+ *
+ *                                                       +------------+-------+
+ *                                                       | extraction | frame |
+ *                                                       |   header   |       |
+ *                                                       +------------+-------+
+ *                                                          128 bits
+ *
+ *
+ * Injection with long prefix:
+ *
+ * +-------------------+-------------------+------+------+------------+-------+
+ * |      any dmac     |      any smac     | 8880 | 000a | injection  | frame |
+ * |                   |                   |      |      |   header   |       |
+ * +-------------------+-------------------+------+------+------------+-------+
+ *        48 bits             48 bits      16 bits 16 bits  128 bits
+ *
+ * Injection with short prefix:
+ *
+ *                                         +------+------+------------+-------+
+ *                                         | 8880 | 000a | injection  | frame |
+ *                                         |      |      |   header   |       |
+ *                                         +------+------+------------+-------+
+ *                                         16 bits 16 bits  128 bits
+ *
+ * Injection with no prefix:
+ *
+ *                                                       +------------+-------+
+ *                                                       | injection  | frame |
+ *                                                       |   header   |       |
+ *                                                       +------------+-------+
+ *                                                          128 bits
+ *
+ * The injection header looks like this (network byte order, bit 127
+ * is part of lowest address byte in memory, bit 0 is part of highest
+ * address byte):
+ *
+ *         +------+------+------+------+------+------+------+------+
+ * 127:120 |BYPASS| MASQ |          MASQ_PORT        |REW_OP|REW_OP|
+ *         +------+------+------+------+------+------+------+------+
+ * 119:112 |                         REW_OP                        |
+ *         +------+------+------+------+------+------+------+------+
+ * 111:104 |                         REW_VAL                       |
+ *         +------+------+------+------+------+------+------+------+
+ * 103: 96 |                         REW_VAL                       |
+ *         +------+------+------+------+------+------+------+------+
+ *  95: 88 |                         REW_VAL                       |
+ *         +------+------+------+------+------+------+------+------+
+ *  87: 80 |                         REW_VAL                       |
+ *         +------+------+------+------+------+------+------+------+
+ *  79: 72 |                          RSV                          |
+ *         +------+------+------+------+------+------+------+------+
+ *  71: 64 |            RSV            |           DEST            |
+ *         +------+------+------+------+------+------+------+------+
+ *  63: 56 |                         DEST                          |
+ *         +------+------+------+------+------+------+------+------+
+ *  55: 48 |                          RSV                          |
+ *         +------+------+------+------+------+------+------+------+
+ *  47: 40 |  RSV |         SRC_PORT          |     RSV     |TFRM_TIMER|
+ *         +------+------+------+------+------+------+------+------+
+ *  39: 32 |     TFRM_TIMER     |               RSV                |
+ *         +------+------+------+------+------+------+------+------+
+ *  31: 24 |  RSV |  DP  |   POP_CNT   |           CPUQ            |
+ *         +------+------+------+------+------+------+------+------+
+ *  23: 16 |           CPUQ            |      QOS_CLASS     |TAG_TYPE|
+ *         +------+------+------+------+------+------+------+------+
+ *  15:  8 |         PCP        |  DEI |            VID            |
+ *         +------+------+------+------+------+------+------+------+
+ *   7:  0 |                          VID                          |
+ *         +------+------+------+------+------+------+------+------+
+ *
+ * And the extraction header looks like this:
+ *
+ *         +------+------+------+------+------+------+------+------+
+ * 127:120 |  RSV |                  REW_OP                        |
+ *         +------+------+------+------+------+------+------+------+
+ * 119:112 |       REW_OP       |              REW_VAL             |
+ *         +------+------+------+------+------+------+------+------+
+ * 111:104 |                         REW_VAL                       |
+ *         +------+------+------+------+------+------+------+------+
+ * 103: 96 |                         REW_VAL                       |
+ *         +------+------+------+------+------+------+------+------+
+ *  95: 88 |                         REW_VAL                       |
+ *         +------+------+------+------+------+------+------+------+
+ *  87: 80 |       REW_VAL      |               LLEN               |
+ *         +------+------+------+------+------+------+------+------+
+ *  79: 72 | LLEN |                      WLEN                      |
+ *         +------+------+------+------+------+------+------+------+
+ *  71: 64 | WLEN |                      RSV                       |
+ *         +------+------+------+------+------+------+------+------+
+ *  63: 56 |                          RSV                          |
+ *         +------+------+------+------+------+------+------+------+
+ *  55: 48 |                          RSV                          |
+ *         +------+------+------+------+------+------+------+------+
+ *  47: 40 | RSV  |          SRC_PORT         |       ACL_ID       |
+ *         +------+------+------+------+------+------+------+------+
+ *  39: 32 |       ACL_ID       |  RSV |         SFLOW_ID          |
+ *         +------+------+------+------+------+------+------+------+
+ *  31: 24 |ACL_HIT| DP  |  LRN_FLAGS  |           CPUQ            |
+ *         +------+------+------+------+------+------+------+------+
+ *  23: 16 |           CPUQ            |      QOS_CLASS     |TAG_TYPE|
+ *         +------+------+------+------+------+------+------+------+
+ *  15:  8 |         PCP        |  DEI |            VID            |
+ *         +------+------+------+------+------+------+------+------+
+ *   7:  0 |                          VID                          |
+ *         +------+------+------+------+------+------+------+------+
+ */
+
+static inline void ocelot_xfh_get_rew_val(void *extraction, u64 *rew_val)
+{
+       packing(extraction, rew_val, 116, 85, OCELOT_TAG_LEN, UNPACK, 0);
+}
+
+static inline void ocelot_xfh_get_len(void *extraction, u64 *len)
+{
+       u64 llen, wlen;
+
+       packing(extraction, &llen, 84, 79, OCELOT_TAG_LEN, UNPACK, 0);
+       packing(extraction, &wlen, 78, 71, OCELOT_TAG_LEN, UNPACK, 0);
+
+       *len = 60 * wlen + llen - 80;
+}
+
+static inline void ocelot_xfh_get_src_port(void *extraction, u64 *src_port)
+{
+       packing(extraction, src_port, 46, 43, OCELOT_TAG_LEN, UNPACK, 0);
+}
+
+static inline void ocelot_xfh_get_qos_class(void *extraction, u64 *qos_class)
+{
+       packing(extraction, qos_class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);
+}
+
+static inline void ocelot_xfh_get_tag_type(void *extraction, u64 *tag_type)
+{
+       packing(extraction, tag_type, 16, 16, OCELOT_TAG_LEN, UNPACK, 0);
+}
+
+static inline void ocelot_xfh_get_vlan_tci(void *extraction, u64 *vlan_tci)
+{
+       packing(extraction, vlan_tci, 15, 0, OCELOT_TAG_LEN, UNPACK, 0);
+}
+
+static inline void ocelot_ifh_set_bypass(void *injection, u64 bypass)
+{
+       packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
+}
+
+static inline void ocelot_ifh_set_rew_op(void *injection, u64 rew_op)
+{
+       packing(injection, &rew_op, 125, 117, OCELOT_TAG_LEN, PACK, 0);
+}
+
+static inline void ocelot_ifh_set_dest(void *injection, u64 dest)
+{
+       packing(injection, &dest, 67, 56, OCELOT_TAG_LEN, PACK, 0);
+}
+
+static inline void ocelot_ifh_set_qos_class(void *injection, u64 qos_class)
+{
+       packing(injection, &qos_class, 19, 17, OCELOT_TAG_LEN, PACK, 0);
+}
+
+static inline void ocelot_ifh_set_tag_type(void *injection, u64 tag_type)
+{
+       packing(injection, &tag_type, 16, 16, OCELOT_TAG_LEN, PACK, 0);
+}
+
+static inline void ocelot_ifh_set_vid(void *injection, u64 vid)
+{
+       packing(injection, &vid, 11, 0, OCELOT_TAG_LEN, PACK, 0);
+}
+
+#endif
index a22aa944e921b1edc2b0a5e23474f0990363bd18..11cae2e968b51d3c09d37259df56190427911323 100644 (file)
@@ -87,9 +87,6 @@
 /* Source PGIDs, one per physical port */
 #define PGID_SRC                       80
 
-#define IFH_INJ_BYPASS                 BIT(31)
-#define IFH_INJ_POP_CNT_DISABLE                (3 << 28)
-
 #define IFH_TAG_TYPE_C                 0
 #define IFH_TAG_TYPE_S                 1
 
 #define IFH_REW_OP_ORIGIN_PTP          0x5
 
 #define OCELOT_NUM_TC                  8
-#define OCELOT_TAG_LEN                 16
-#define OCELOT_SHORT_PREFIX_LEN                4
-#define OCELOT_LONG_PREFIX_LEN         16
-#define OCELOT_TOTAL_TAG_LEN   (OCELOT_SHORT_PREFIX_LEN + OCELOT_TAG_LEN)
 
 #define OCELOT_SPEED_2500              0
 #define OCELOT_SPEED_1000              1
index 225b145fd1310af7578431dd9d721ce2b0c8e8e5..8ce0b26f35203d051b06daebbedd1e3a67c13a36 100644 (file)
 // SPDX-License-Identifier: GPL-2.0
 /* Copyright 2019 NXP Semiconductors
  */
+#include <linux/dsa/ocelot.h>
 #include <soc/mscc/ocelot.h>
-#include <linux/packing.h>
 #include "dsa_priv.h"
 
-/* The CPU injection header and the CPU extraction header can have 3 types of
- * prefixes: long, short and no prefix. The format of the header itself is the
- * same in all 3 cases.
- *
- * Extraction with long prefix:
- *
- * +-------------------+-------------------+------+------+------------+-------+
- * | ff:ff:ff:ff:ff:ff | ff:ff:ff:ff:ff:ff | 8880 | 000a | extraction | frame |
- * |                   |                   |      |      |   header   |       |
- * +-------------------+-------------------+------+------+------------+-------+
- *        48 bits             48 bits      16 bits 16 bits  128 bits
- *
- * Extraction with short prefix:
- *
- *                                         +------+------+------------+-------+
- *                                         | 8880 | 000a | extraction | frame |
- *                                         |      |      |   header   |       |
- *                                         +------+------+------------+-------+
- *                                         16 bits 16 bits  128 bits
- *
- * Extraction with no prefix:
- *
- *                                                       +------------+-------+
- *                                                       | extraction | frame |
- *                                                       |   header   |       |
- *                                                       +------------+-------+
- *                                                          128 bits
- *
- *
- * Injection with long prefix:
- *
- * +-------------------+-------------------+------+------+------------+-------+
- * |      any dmac     |      any smac     | 8880 | 000a | injection  | frame |
- * |                   |                   |      |      |   header   |       |
- * +-------------------+-------------------+------+------+------------+-------+
- *        48 bits             48 bits      16 bits 16 bits  128 bits
- *
- * Injection with short prefix:
- *
- *                                         +------+------+------------+-------+
- *                                         | 8880 | 000a | injection  | frame |
- *                                         |      |      |   header   |       |
- *                                         +------+------+------------+-------+
- *                                         16 bits 16 bits  128 bits
- *
- * Injection with no prefix:
- *
- *                                                       +------------+-------+
- *                                                       | injection  | frame |
- *                                                       |   header   |       |
- *                                                       +------------+-------+
- *                                                          128 bits
- *
- * The injection header looks like this (network byte order, bit 127
- * is part of lowest address byte in memory, bit 0 is part of highest
- * address byte):
- *
- *         +------+------+------+------+------+------+------+------+
- * 127:120 |BYPASS| MASQ |          MASQ_PORT        |REW_OP|REW_OP|
- *         +------+------+------+------+------+------+------+------+
- * 119:112 |                         REW_OP                        |
- *         +------+------+------+------+------+------+------+------+
- * 111:104 |                         REW_VAL                       |
- *         +------+------+------+------+------+------+------+------+
- * 103: 96 |                         REW_VAL                       |
- *         +------+------+------+------+------+------+------+------+
- *  95: 88 |                         REW_VAL                       |
- *         +------+------+------+------+------+------+------+------+
- *  87: 80 |                         REW_VAL                       |
- *         +------+------+------+------+------+------+------+------+
- *  79: 72 |                          RSV                          |
- *         +------+------+------+------+------+------+------+------+
- *  71: 64 |            RSV            |           DEST            |
- *         +------+------+------+------+------+------+------+------+
- *  63: 56 |                         DEST                          |
- *         +------+------+------+------+------+------+------+------+
- *  55: 48 |                          RSV                          |
- *         +------+------+------+------+------+------+------+------+
- *  47: 40 |  RSV |         SRC_PORT          |     RSV     |TFRM_TIMER|
- *         +------+------+------+------+------+------+------+------+
- *  39: 32 |     TFRM_TIMER     |               RSV                |
- *         +------+------+------+------+------+------+------+------+
- *  31: 24 |  RSV |  DP  |   POP_CNT   |           CPUQ            |
- *         +------+------+------+------+------+------+------+------+
- *  23: 16 |           CPUQ            |      QOS_CLASS     |TAG_TYPE|
- *         +------+------+------+------+------+------+------+------+
- *  15:  8 |         PCP        |  DEI |            VID            |
- *         +------+------+------+------+------+------+------+------+
- *   7:  0 |                          VID                          |
- *         +------+------+------+------+------+------+------+------+
- *
- * And the extraction header looks like this:
- *
- *         +------+------+------+------+------+------+------+------+
- * 127:120 |  RSV |                  REW_OP                        |
- *         +------+------+------+------+------+------+------+------+
- * 119:112 |       REW_OP       |              REW_VAL             |
- *         +------+------+------+------+------+------+------+------+
- * 111:104 |                         REW_VAL                       |
- *         +------+------+------+------+------+------+------+------+
- * 103: 96 |                         REW_VAL                       |
- *         +------+------+------+------+------+------+------+------+
- *  95: 88 |                         REW_VAL                       |
- *         +------+------+------+------+------+------+------+------+
- *  87: 80 |       REW_VAL      |               LLEN               |
- *         +------+------+------+------+------+------+------+------+
- *  79: 72 | LLEN |                      WLEN                      |
- *         +------+------+------+------+------+------+------+------+
- *  71: 64 | WLEN |                      RSV                       |
- *         +------+------+------+------+------+------+------+------+
- *  63: 56 |                          RSV                          |
- *         +------+------+------+------+------+------+------+------+
- *  55: 48 |                          RSV                          |
- *         +------+------+------+------+------+------+------+------+
- *  47: 40 | RSV  |          SRC_PORT         |       ACL_ID       |
- *         +------+------+------+------+------+------+------+------+
- *  39: 32 |       ACL_ID       |  RSV |         SFLOW_ID          |
- *         +------+------+------+------+------+------+------+------+
- *  31: 24 |ACL_HIT| DP  |  LRN_FLAGS  |           CPUQ            |
- *         +------+------+------+------+------+------+------+------+
- *  23: 16 |           CPUQ            |      QOS_CLASS     |TAG_TYPE|
- *         +------+------+------+------+------+------+------+------+
- *  15:  8 |         PCP        |  DEI |            VID            |
- *         +------+------+------+------+------+------+------+------+
- *   7:  0 |                          VID                          |
- *         +------+------+------+------+------+------+------+------+
- */
-
 static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
                                   struct net_device *netdev)
 {
@@ -142,7 +14,6 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
        struct ocelot *ocelot = ds->priv;
        struct ocelot_port *ocelot_port;
        u8 *prefix, *injection;
-       u64 qos_class, rew_op;
 
        ocelot_port = ocelot->ports[dp->index];
 
@@ -155,19 +26,19 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
        /* Fix up the fields which are not statically determined
         * in the template
         */
-       qos_class = skb->priority;
-       packing(injection, &qos_class, 19,  17, OCELOT_TAG_LEN, PACK, 0);
+       ocelot_ifh_set_qos_class(injection, skb->priority);
 
        /* TX timestamping was requested */
        if (clone) {
-               rew_op = ocelot_port->ptp_cmd;
+               u64 rew_op = ocelot_port->ptp_cmd;
+
                /* Retrieve timestamp ID populated inside skb->cb[0] of the
                 * clone by ocelot_port_add_txtstamp_skb
                 */
                if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
                        rew_op |= clone->cb[0] << 3;
 
-               packing(injection, &rew_op, 125, 117, OCELOT_TAG_LEN, PACK, 0);
+               ocelot_ifh_set_rew_op(injection, rew_op);
        }
 
        return skb;
@@ -208,10 +79,10 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
        /* Remove from inet csum the extraction header */
        skb_postpull_rcsum(skb, start, OCELOT_TOTAL_TAG_LEN);
 
-       packing(extraction, &src_port,  46, 43, OCELOT_TAG_LEN, UNPACK, 0);
-       packing(extraction, &qos_class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);
-       packing(extraction, &tag_type,  16, 16, OCELOT_TAG_LEN, UNPACK, 0);
-       packing(extraction, &vlan_tci,  15,  0, OCELOT_TAG_LEN, UNPACK, 0);
+       ocelot_xfh_get_src_port(extraction, &src_port);
+       ocelot_xfh_get_qos_class(extraction, &qos_class);
+       ocelot_xfh_get_tag_type(extraction, &tag_type);
+       ocelot_xfh_get_vlan_tci(extraction, &vlan_tci);
 
        skb->dev = dsa_master_find_slave(netdev, 0, src_port);
        if (!skb->dev)