linux/net/dsa/tag_ocelot_8021q.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright 2020-2021 NXP Semiconductors
   3 *
   4 * An implementation of the software-defined tag_8021q.c tagger format, which
   5 * also preserves full functionality under a vlan_filtering bridge. It does
   6 * this by using the TCAM engines for:
   7 * - pushing the RX VLAN as a second, outer tag, on egress towards the CPU port
   8 * - redirecting towards the correct front port based on TX VLAN and popping
   9 *   that on egress
  10 */
  11#include <linux/dsa/8021q.h>
  12#include <soc/mscc/ocelot.h>
  13#include <soc/mscc/ocelot_ptp.h>
  14#include "dsa_priv.h"
  15
  16static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
  17                                   struct net_device *netdev)
  18{
  19        struct dsa_port *dp = dsa_slave_to_port(netdev);
  20        u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index);
  21        u16 queue_mapping = skb_get_queue_mapping(skb);
  22        u8 pcp = netdev_txq_to_tc(netdev, queue_mapping);
  23        struct ocelot *ocelot = dp->ds->priv;
  24        int port = dp->index;
  25        u32 rew_op = 0;
  26
  27        rew_op = ocelot_ptp_rew_op(skb);
  28        if (rew_op) {
  29                if (!ocelot_can_inject(ocelot, 0))
  30                        return NULL;
  31
  32                ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb);
  33                return NULL;
  34        }
  35
  36        return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q,
  37                              ((pcp << VLAN_PRIO_SHIFT) | tx_vid));
  38}
  39
  40static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
  41                                  struct net_device *netdev,
  42                                  struct packet_type *pt)
  43{
  44        int src_port, switch_id, subvlan;
  45
  46        dsa_8021q_rcv(skb, &src_port, &switch_id, &subvlan);
  47
  48        skb->dev = dsa_master_find_slave(netdev, switch_id, src_port);
  49        if (!skb->dev)
  50                return NULL;
  51
  52        skb->offload_fwd_mark = 1;
  53
  54        return skb;
  55}
  56
  57static const struct dsa_device_ops ocelot_8021q_netdev_ops = {
  58        .name                   = "ocelot-8021q",
  59        .proto                  = DSA_TAG_PROTO_OCELOT_8021Q,
  60        .xmit                   = ocelot_xmit,
  61        .rcv                    = ocelot_rcv,
  62        .needed_headroom        = VLAN_HLEN,
  63        .promisc_on_master      = true,
  64};
  65
  66MODULE_LICENSE("GPL v2");
  67MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_OCELOT_8021Q);
  68
  69module_dsa_tag_driver(ocelot_8021q_netdev_ops);
  70