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 -> KSZ8795), 1 byte is added before FCS.
  74 * ---------------------------------------------------------------------------
  75 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag(1byte)|FCS(4bytes)
  76 * ---------------------------------------------------------------------------
  77 * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
  78 *
  79 * For Egress (KSZ8795 -> Host), 1 byte is added before FCS.
  80 * ---------------------------------------------------------------------------
  81 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
  82 * ---------------------------------------------------------------------------
  83 * tag0 : zero-based value represents port
  84 *        (eg, 0x00=port1, 0x02=port3, 0x06=port7)
  85 */
  86
  87#define KSZ8795_TAIL_TAG_OVERRIDE       BIT(6)
  88#define KSZ8795_TAIL_TAG_LOOKUP         BIT(7)
  89
  90static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
  91{
  92        struct dsa_port *dp = dsa_slave_to_port(dev);
  93        struct sk_buff *nskb;
  94        u8 *tag;
  95        u8 *addr;
  96
  97        nskb = ksz_common_xmit(skb, dev, KSZ_INGRESS_TAG_LEN);
  98        if (!nskb)
  99                return NULL;
 100
 101        /* Tag encoding */
 102        tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
 103        addr = skb_mac_header(nskb);
 104
 105        *tag = 1 << dp->index;
 106        if (is_link_local_ether_addr(addr))
 107                *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
 108
 109        return nskb;
 110}
 111
 112static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev,
 113                                  struct packet_type *pt)
 114{
 115        u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
 116
 117        return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN);
 118}
 119
 120static const struct dsa_device_ops ksz8795_netdev_ops = {
 121        .name   = "ksz8795",
 122        .proto  = DSA_TAG_PROTO_KSZ8795,
 123        .xmit   = ksz8795_xmit,
 124        .rcv    = ksz8795_rcv,
 125        .overhead = KSZ_INGRESS_TAG_LEN,
 126        .tail_tag = true,
 127};
 128
 129DSA_TAG_DRIVER(ksz8795_netdev_ops);
 130MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795);
 131
 132/*
 133 * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
 134 * ---------------------------------------------------------------------------
 135 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes)
 136 * ---------------------------------------------------------------------------
 137 * tag0 : Prioritization (not used now)
 138 * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
 139 *
 140 * For Egress (KSZ9477 -> Host), 1 byte is added before FCS.
 141 * ---------------------------------------------------------------------------
 142 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
 143 * ---------------------------------------------------------------------------
 144 * tag0 : zero-based value represents port
 145 *        (eg, 0x00=port1, 0x02=port3, 0x06=port7)
 146 */
 147
 148#define KSZ9477_INGRESS_TAG_LEN         2
 149#define KSZ9477_PTP_TAG_LEN             4
 150#define KSZ9477_PTP_TAG_INDICATION      0x80
 151
 152#define KSZ9477_TAIL_TAG_OVERRIDE       BIT(9)
 153#define KSZ9477_TAIL_TAG_LOOKUP         BIT(10)
 154
 155static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
 156                                    struct net_device *dev)
 157{
 158        struct dsa_port *dp = dsa_slave_to_port(dev);
 159        struct sk_buff *nskb;
 160        __be16 *tag;
 161        u8 *addr;
 162        u16 val;
 163
 164        nskb = ksz_common_xmit(skb, dev, KSZ9477_INGRESS_TAG_LEN);
 165        if (!nskb)
 166                return NULL;
 167
 168        /* Tag encoding */
 169        tag = skb_put(nskb, KSZ9477_INGRESS_TAG_LEN);
 170        addr = skb_mac_header(nskb);
 171
 172        val = BIT(dp->index);
 173
 174        if (is_link_local_ether_addr(addr))
 175                val |= KSZ9477_TAIL_TAG_OVERRIDE;
 176
 177        *tag = cpu_to_be16(val);
 178
 179        return nskb;
 180}
 181
 182static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev,
 183                                   struct packet_type *pt)
 184{
 185        /* Tag decoding */
 186        u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
 187        unsigned int port = tag[0] & 7;
 188        unsigned int len = KSZ_EGRESS_TAG_LEN;
 189
 190        /* Extra 4-bytes PTP timestamp */
 191        if (tag[0] & KSZ9477_PTP_TAG_INDICATION)
 192                len += KSZ9477_PTP_TAG_LEN;
 193
 194        return ksz_common_rcv(skb, dev, port, len);
 195}
 196
 197static const struct dsa_device_ops ksz9477_netdev_ops = {
 198        .name   = "ksz9477",
 199        .proto  = DSA_TAG_PROTO_KSZ9477,
 200        .xmit   = ksz9477_xmit,
 201        .rcv    = ksz9477_rcv,
 202        .overhead = KSZ9477_INGRESS_TAG_LEN,
 203        .tail_tag = true,
 204};
 205
 206DSA_TAG_DRIVER(ksz9477_netdev_ops);
 207MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9477);
 208
 209#define KSZ9893_TAIL_TAG_OVERRIDE       BIT(5)
 210#define KSZ9893_TAIL_TAG_LOOKUP         BIT(6)
 211
 212static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
 213                                    struct net_device *dev)
 214{
 215        struct dsa_port *dp = dsa_slave_to_port(dev);
 216        struct sk_buff *nskb;
 217        u8 *addr;
 218        u8 *tag;
 219
 220        nskb = ksz_common_xmit(skb, dev, KSZ_INGRESS_TAG_LEN);
 221        if (!nskb)
 222                return NULL;
 223
 224        /* Tag encoding */
 225        tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
 226        addr = skb_mac_header(nskb);
 227
 228        *tag = BIT(dp->index);
 229
 230        if (is_link_local_ether_addr(addr))
 231                *tag |= KSZ9893_TAIL_TAG_OVERRIDE;
 232
 233        return nskb;
 234}
 235
 236static const struct dsa_device_ops ksz9893_netdev_ops = {
 237        .name   = "ksz9893",
 238        .proto  = DSA_TAG_PROTO_KSZ9893,
 239        .xmit   = ksz9893_xmit,
 240        .rcv    = ksz9477_rcv,
 241        .overhead = KSZ_INGRESS_TAG_LEN,
 242        .tail_tag = true,
 243};
 244
 245DSA_TAG_DRIVER(ksz9893_netdev_ops);
 246MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
 247
 248static struct dsa_tag_driver *dsa_tag_driver_array[] = {
 249        &DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
 250        &DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
 251        &DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
 252};
 253
 254module_dsa_tag_drivers(dsa_tag_driver_array);
 255
 256MODULE_LICENSE("GPL");
 257