diff options
| -rw-r--r-- | net/dsa/tag_8021q.c | 60 |
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 | */ |
| 25 | u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port) | 63 | u16 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 | } |
| 29 | EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid); | 68 | EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid); |
| 30 | 69 | ||
| @@ -33,21 +72,22 @@ EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid); | |||
| 33 | */ | 72 | */ |
| 34 | u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port) | 73 | u16 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 | } |
| 38 | EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid); | 78 | EXPORT_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. */ |
| 41 | int dsa_8021q_rx_switch_id(u16 vid) | 81 | int 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 | } |
| 45 | EXPORT_SYMBOL_GPL(dsa_8021q_rx_switch_id); | 85 | EXPORT_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. */ |
| 48 | int dsa_8021q_rx_source_port(u16 vid) | 88 | int 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 | } |
| 52 | EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port); | 92 | EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port); |
| 53 | 93 | ||
