tag_lan9303.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2017 Pengutronix, Juergen Borleis <jbe@pengutronix.de>
  4. */
  5. #include <linux/dsa/lan9303.h>
  6. #include <linux/etherdevice.h>
  7. #include <linux/list.h>
  8. #include <linux/slab.h>
  9. #include "dsa_priv.h"
  10. /* To define the outgoing port and to discover the incoming port a regular
  11. * VLAN tag is used by the LAN9303. But its VID meaning is 'special':
  12. *
  13. * Dest MAC Src MAC TAG Type
  14. * ...| 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 | 1 2 |...
  15. * |<------->|
  16. * TAG:
  17. * |<------------->|
  18. * | 1 2 | 3 4 |
  19. * TPID VID
  20. * 0x8100
  21. *
  22. * VID bit 3 indicates a request for an ALR lookup.
  23. *
  24. * If VID bit 3 is zero, then bits 0 and 1 specify the destination port
  25. * (0, 1, 2) or broadcast (3) or the source port (1, 2).
  26. *
  27. * VID bit 4 is used to specify if the STP port state should be overridden.
  28. * Required when no forwarding between the external ports should happen.
  29. */
  30. #define LAN9303_TAG_LEN 4
  31. # define LAN9303_TAG_TX_USE_ALR BIT(3)
  32. # define LAN9303_TAG_TX_STP_OVERRIDE BIT(4)
  33. # define LAN9303_TAG_RX_IGMP BIT(3)
  34. # define LAN9303_TAG_RX_STP BIT(4)
  35. # define LAN9303_TAG_RX_TRAPPED_TO_CPU (LAN9303_TAG_RX_IGMP | \
  36. LAN9303_TAG_RX_STP)
  37. /* Decide whether to transmit using ALR lookup, or transmit directly to
  38. * port using tag. ALR learning is performed only when using ALR lookup.
  39. * If the two external ports are bridged and the frame is unicast,
  40. * then use ALR lookup to allow ALR learning on CPU port.
  41. * Otherwise transmit directly to port with STP state override.
  42. * See also: lan9303_separate_ports() and lan9303.pdf 6.4.10.1
  43. */
  44. static int lan9303_xmit_use_arl(struct dsa_port *dp, u8 *dest_addr)
  45. {
  46. struct lan9303 *chip = dp->ds->priv;
  47. return chip->is_bridged && !is_multicast_ether_addr(dest_addr);
  48. }
  49. static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
  50. {
  51. struct dsa_port *dp = dsa_slave_to_port(dev);
  52. __be16 *lan9303_tag;
  53. u16 tag;
  54. /* provide 'LAN9303_TAG_LEN' bytes additional space */
  55. skb_push(skb, LAN9303_TAG_LEN);
  56. /* make room between MACs and Ether-Type */
  57. memmove(skb->data, skb->data + LAN9303_TAG_LEN, 2 * ETH_ALEN);
  58. lan9303_tag = (__be16 *)(skb->data + 2 * ETH_ALEN);
  59. tag = lan9303_xmit_use_arl(dp, skb->data) ?
  60. LAN9303_TAG_TX_USE_ALR :
  61. dp->index | LAN9303_TAG_TX_STP_OVERRIDE;
  62. lan9303_tag[0] = htons(ETH_P_8021Q);
  63. lan9303_tag[1] = htons(tag);
  64. return skb;
  65. }
  66. static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
  67. struct packet_type *pt)
  68. {
  69. __be16 *lan9303_tag;
  70. u16 lan9303_tag1;
  71. unsigned int source_port;
  72. if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {
  73. dev_warn_ratelimited(&dev->dev,
  74. "Dropping packet, cannot pull\n");
  75. return NULL;
  76. }
  77. /* '->data' points into the middle of our special VLAN tag information:
  78. *
  79. * ~ MAC src | 0x81 | 0x00 | 0xyy | 0xzz | ether type
  80. * ^
  81. * ->data
  82. */
  83. lan9303_tag = (__be16 *)(skb->data - 2);
  84. if (lan9303_tag[0] != htons(ETH_P_8021Q)) {
  85. dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid VLAN marker\n");
  86. return NULL;
  87. }
  88. lan9303_tag1 = ntohs(lan9303_tag[1]);
  89. source_port = lan9303_tag1 & 0x3;
  90. skb->dev = dsa_master_find_slave(dev, 0, source_port);
  91. if (!skb->dev) {
  92. dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
  93. return NULL;
  94. }
  95. /* remove the special VLAN tag between the MAC addresses
  96. * and the current ethertype field.
  97. */
  98. skb_pull_rcsum(skb, 2 + 2);
  99. memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN),
  100. 2 * ETH_ALEN);
  101. skb->offload_fwd_mark = !(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU);
  102. return skb;
  103. }
  104. static const struct dsa_device_ops lan9303_netdev_ops = {
  105. .name = "lan9303",
  106. .proto = DSA_TAG_PROTO_LAN9303,
  107. .xmit = lan9303_xmit,
  108. .rcv = lan9303_rcv,
  109. .overhead = LAN9303_TAG_LEN,
  110. };
  111. MODULE_LICENSE("GPL");
  112. MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_LAN9303);
  113. module_dsa_tag_driver(lan9303_netdev_ops);