linux/net/dsa/tag_ksz.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * net/dsa/tag_ksz.c - Microchip KSZ Switch tag format handling
   4 * Copyright (c) 2017 Microchip Technology
   5 */
   6
   7#include <linux/etherdevice.h>
   8#include <linux/list.h>
   9#include <linux/slab.h>
  10#include <net/dsa.h>
  11#include "dsa_priv.h"
  12
  13/* Typically only one byte is used for tail tag. */
  14#define KSZ_EGRESS_TAG_LEN              1
  15#define KSZ_INGRESS_TAG_LEN             1
  16
  17static struct sk_buff *ksz_common_xmit(struct sk_buff *skb,
  18                                       struct net_device *dev, int len)
  19{
  20        struct sk_buff *nskb;
  21        int padlen;
  22
  23        padlen = (skb->len >= ETH_ZLEN) ? 0 : ETH_ZLEN - skb->len;
  24
  25        if (skb_tailroom(skb) >= padlen + len) {
  26                /* Let dsa_slave_xmit() free skb */
  27                if (__skb_put_padto(skb, skb->len + padlen, false))
  28                        return NULL;
  29
  30                nskb = skb;
  31        } else {
  32                nskb = alloc_skb(NET_IP_ALIGN + skb->len +
  33                                 padlen + len, GFP_ATOMIC);
  34                if (!nskb)
  35                        return NULL;
  36                skb_reserve(nskb, NET_IP_ALIGN);
  37
  38                skb_reset_mac_header(nskb);
  39                skb_set_network_header(nskb,
  40                                       skb_network_header(skb) - skb->head);
  41                skb_set_transport_header(nskb,
  42                                         skb_transport_header(skb) - skb->head);
  43                skb_copy_and_csum_dev(skb, skb_put(nskb, skb->len));
  44
  45                /* Let skb_put_padto() free nskb, and let dsa_slave_xmit() free
  46                 * skb
  47                 */
  48                if (skb_put_padto(nskb, nskb->len + padlen))
  49                        return NULL;
  50
  51                consume_skb(skb);
  52        }
  53
  54        return nskb;
  55}
  56
  57static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
  58                                      struct net_device *dev,
  59                                      unsigned int port, unsigned int len)
  60{
  61        skb->dev = dsa_master_find_slave(dev, 0, port);
  62        if (!skb->dev)
  63                return NULL;
  64
  65        pskb_trim_rcsum(skb, skb->len - len);
  66
  67        skb->offload_fwd_mark = true;
  68
  69        return skb;
  70}
  71
  72/*
  73 * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
  74 * ---------------------------------------------------------------------------
  75 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes)
  76 * ---------------------------------------------------------------------------
  77 * tag0 : Prioritization (not used now)
  78 * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
  79 *
  80 * For Egress (KSZ9477 -> Host), 1 byte is added before FCS.
  81 * ---------------------------------------------------------------------------
  82 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
  83 * ---------------------------------------------------------------------------
  84 * tag0 : zero-based value represents port
  85 *        (eg, 0x00=port1, 0x02=port3, 0x06=port7)
  86 */
  87
  88#define KSZ9477_INGRESS_TAG_LEN         2
  89#define KSZ9477_PTP_TAG_LEN             4
  90#define KSZ9477_PTP_TAG_INDICATION      0x80
  91
  92#define KSZ9477_TAIL_TAG_OVERRIDE       BIT(9)
  93#define KSZ9477_TAIL_TAG_LOOKUP         BIT(10)
  94
  95static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
  96                                    struct net_device *dev)
  97{
  98        struct dsa_port *dp = dsa_slave_to_port(dev);
  99        struct sk_buff *nskb;
 100        u16 *tag;
 101        u8 *addr;
 102
 103        nskb = ksz_common_xmit(skb, dev, KSZ9477_INGRESS_TAG_LEN);
 104        if (!nskb)
 105                return NULL;
 106
 107        /* Tag encoding */
 108        tag = skb_put(nskb, KSZ9477_INGRESS_TAG_LEN);
 109        addr = skb_mac_header(nskb);
 110
 111        *tag = BIT(dp->index);
 112
 113        if (is_link_local_ether_addr(addr))
 114                *tag |= KSZ9477_TAIL_TAG_OVERRIDE;
 115
 116        *tag = cpu_to_be16(*tag);
 117
 118        return nskb;
 119}
 120
 121static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev,
 122                                   struct packet_type *pt)
 123{
 124        /* Tag decoding */
 125        u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
 126        unsigned int port = tag[0] & 7;
 127        unsigned int len = KSZ_EGRESS_TAG_LEN;
 128
 129        /* Extra 4-bytes PTP timestamp */
 130        if (tag[0] & KSZ9477_PTP_TAG_INDICATION)
 131                len += KSZ9477_PTP_TAG_LEN;
 132
 133        return ksz_common_rcv(skb, dev, port, len);
 134}
 135
 136static const struct dsa_device_ops ksz9477_netdev_ops = {
 137        .name   = "ksz9477",
 138        .proto  = DSA_TAG_PROTO_KSZ9477,
 139        .xmit   = ksz9477_xmit,
 140        .rcv    = ksz9477_rcv,
 141        .overhead = KSZ9477_INGRESS_TAG_LEN,
 142};
 143
 144DSA_TAG_DRIVER(ksz9477_netdev_ops);
 145MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9477);
 146
 147#define KSZ9893_TAIL_TAG_OVERRIDE       BIT(5)
 148#define KSZ9893_TAIL_TAG_LOOKUP         BIT(6)
 149
 150static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
 151                                    struct net_device *dev)
 152{
 153        struct dsa_port *dp = dsa_slave_to_port(dev);
 154        struct sk_buff *nskb;
 155        u8 *addr;
 156        u8 *tag;
 157
 158        nskb = ksz_common_xmit(skb, dev, KSZ_INGRESS_TAG_LEN);
 159        if (!nskb)
 160                return NULL;
 161
 162        /* Tag encoding */
 163        tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
 164        addr = skb_mac_header(nskb);
 165
 166        *tag = BIT(dp->index);
 167
 168        if (is_link_local_ether_addr(addr))
 169                *tag |= KSZ9893_TAIL_TAG_OVERRIDE;
 170
 171        return nskb;
 172}
 173
 174static const struct dsa_device_ops ksz9893_netdev_ops = {
 175        .name   = "ksz9893",
 176        .proto  = DSA_TAG_PROTO_KSZ9893,
 177        .xmit   = ksz9893_xmit,
 178        .rcv    = ksz9477_rcv,
 179        .overhead = KSZ_INGRESS_TAG_LEN,
 180};
 181
 182DSA_TAG_DRIVER(ksz9893_netdev_ops);
 183MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
 184
 185static struct dsa_tag_driver *dsa_tag_driver_array[] = {
 186        &DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
 187        &DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
 188};
 189
 190module_dsa_tag_drivers(dsa_tag_driver_array);
 191
 192MODULE_LICENSE("GPL");
 193