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