aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/dsa/tag_8021q.c60
1 files changed, 50 insertions, 10 deletions
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index 4adec6bbfe59..65a35e976d7b 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -11,20 +11,59 @@
11 11
12#include "dsa_priv.h" 12#include "dsa_priv.h"
13 13
14/* Allocating two VLAN tags per port - one for the RX VID and 14/* Binary structure of the fake 12-bit VID field (when the TPID is
15 * the other for the TX VID - see below 15 * ETH_P_DSA_8021Q):
16 *
17 * | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
18 * +-----------+-----+-----------------+-----------+-----------------------+
19 * | DIR | RSV | SWITCH_ID | RSV | PORT |
20 * +-----------+-----+-----------------+-----------+-----------------------+
21 *
22 * DIR - VID[11:10]:
23 * Direction flags.
24 * * 1 (0b01) for RX VLAN,
25 * * 2 (0b10) for TX VLAN.
26 * These values make the special VIDs of 0, 1 and 4095 to be left
27 * unused by this coding scheme.
28 *
29 * RSV - VID[9]:
30 * To be used for further expansion of SWITCH_ID or for other purposes.
31 *
32 * SWITCH_ID - VID[8:6]:
33 * Index of switch within DSA tree. Must be between 0 and
34 * DSA_MAX_SWITCHES - 1.
35 *
36 * RSV - VID[5:4]:
37 * To be used for further expansion of PORT or for other purposes.
38 *
39 * PORT - VID[3:0]:
40 * Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1.
16 */ 41 */
17#define DSA_8021Q_VID_RANGE (DSA_MAX_SWITCHES * DSA_MAX_PORTS) 42
18#define DSA_8021Q_VID_BASE (VLAN_N_VID - 2 * DSA_8021Q_VID_RANGE - 1) 43#define DSA_8021Q_DIR_SHIFT 10
19#define DSA_8021Q_RX_VID_BASE (DSA_8021Q_VID_BASE) 44#define DSA_8021Q_DIR_MASK GENMASK(11, 10)
20#define DSA_8021Q_TX_VID_BASE (DSA_8021Q_VID_BASE + DSA_8021Q_VID_RANGE) 45#define DSA_8021Q_DIR(x) (((x) << DSA_8021Q_DIR_SHIFT) & \
46 DSA_8021Q_DIR_MASK)
47#define DSA_8021Q_DIR_RX DSA_8021Q_DIR(1)
48#define DSA_8021Q_DIR_TX DSA_8021Q_DIR(2)
49
50#define DSA_8021Q_SWITCH_ID_SHIFT 6
51#define DSA_8021Q_SWITCH_ID_MASK GENMASK(8, 6)
52#define DSA_8021Q_SWITCH_ID(x) (((x) << DSA_8021Q_SWITCH_ID_SHIFT) & \
53 DSA_8021Q_SWITCH_ID_MASK)
54
55#define DSA_8021Q_PORT_SHIFT 0
56#define DSA_8021Q_PORT_MASK GENMASK(3, 0)
57#define DSA_8021Q_PORT(x) (((x) << DSA_8021Q_PORT_SHIFT) & \
58 DSA_8021Q_PORT_MASK)
21 59
22/* Returns the VID to be inserted into the frame from xmit for switch steering 60/* Returns the VID to be inserted into the frame from xmit for switch steering
23 * instructions on egress. Encodes switch ID and port ID. 61 * instructions on egress. Encodes switch ID and port ID.
24 */ 62 */
25u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port) 63u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port)
26{ 64{
27 return DSA_8021Q_TX_VID_BASE + (DSA_MAX_PORTS * ds->index) + port; 65 return DSA_8021Q_DIR_TX | DSA_8021Q_SWITCH_ID(ds->index) |
66 DSA_8021Q_PORT(port);
28} 67}
29EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid); 68EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid);
30 69
@@ -33,21 +72,22 @@ EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid);
33 */ 72 */
34u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port) 73u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port)
35{ 74{
36 return DSA_8021Q_RX_VID_BASE + (DSA_MAX_PORTS * ds->index) + port; 75 return DSA_8021Q_DIR_RX | DSA_8021Q_SWITCH_ID(ds->index) |
76 DSA_8021Q_PORT(port);
37} 77}
38EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid); 78EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid);
39 79
40/* Returns the decoded switch ID from the RX VID. */ 80/* Returns the decoded switch ID from the RX VID. */
41int dsa_8021q_rx_switch_id(u16 vid) 81int dsa_8021q_rx_switch_id(u16 vid)
42{ 82{
43 return ((vid - DSA_8021Q_RX_VID_BASE) / DSA_MAX_PORTS); 83 return (vid & DSA_8021Q_SWITCH_ID_MASK) >> DSA_8021Q_SWITCH_ID_SHIFT;
44} 84}
45EXPORT_SYMBOL_GPL(dsa_8021q_rx_switch_id); 85EXPORT_SYMBOL_GPL(dsa_8021q_rx_switch_id);
46 86
47/* Returns the decoded port ID from the RX VID. */ 87/* Returns the decoded port ID from the RX VID. */
48int dsa_8021q_rx_source_port(u16 vid) 88int dsa_8021q_rx_source_port(u16 vid)
49{ 89{
50 return ((vid - DSA_8021Q_RX_VID_BASE) % DSA_MAX_PORTS); 90 return (vid & DSA_8021Q_PORT_MASK) >> DSA_8021Q_PORT_SHIFT;
51} 91}
52EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port); 92EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port);
53 93