1 From 7028f54b620f8df344b18e46e4a78e266091ab45 Mon Sep 17 00:00:00 2001
2 From: Linus Walleij <linus.walleij@linaro.org>
3 Date: Sun, 26 Sep 2021 00:59:26 +0200
4 Subject: [PATCH 03/11] net: dsa: rtl8366rb: Rewrite weird VLAN filering
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
10 While we were defining one VLAN per port for isolating the ports
11 the port_vlan_filtering() callback was implemented to enable a
12 VLAN on the port + 1. This function makes no sense, not only is
13 it incomplete as it only enables the VLAN, it doesn't do what
14 the callback is supposed to do, which is to selectively enable
15 and disable filtering on a certain port.
17 Implement the correct callback: we have two registers dealing
18 with filtering on the RTL9366RB, so we implement an ASIC-specific
19 callback and implement filering using the register bit that makes
20 the switch drop frames if the port is not in the VLAN member set.
22 The DSA documentation Documentation/networking/switchdev.rst states:
24 When the bridge has VLAN filtering enabled and a PVID is not
25 configured on the ingress port, untagged and 802.1p tagged
26 packets must be dropped. When the bridge has VLAN filtering
27 enabled and a PVID exists on the ingress port, untagged and
28 priority-tagged packets must be accepted and forwarded according
29 to the bridge's port membership of the PVID VLAN. When the
30 bridge has VLAN filtering disabled, the presence/lack of a
31 PVID should not influence the packet forwarding decision.
33 To comply with this, we add two arrays of bool in the RTL8366RB
34 state that keeps track of if filtering and PVID is enabled or
35 not for each port. We then add code such that whenever filtering
36 or PVID changes, we update the filter according to the
39 Cc: Vladimir Oltean <olteanv@gmail.com>
40 Cc: Mauri Sandberg <sandberg@mailfence.com>
41 Cc: Alvin Šipraga <alsi@bang-olufsen.dk>
42 Cc: Florian Fainelli <f.fainelli@gmail.com>
43 Cc: DENG Qingfang <dqfext@gmail.com>
44 Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
45 Signed-off-by: David S. Miller <davem@davemloft.net>
47 drivers/net/dsa/realtek-smi-core.h | 2 -
48 drivers/net/dsa/rtl8366.c | 35 ----------
49 drivers/net/dsa/rtl8366rb.c | 102 +++++++++++++++++++++++++++--
50 3 files changed, 95 insertions(+), 44 deletions(-)
52 --- a/drivers/net/dsa/realtek-smi-core.h
53 +++ b/drivers/net/dsa/realtek-smi-core.h
54 @@ -129,8 +129,6 @@ int rtl8366_set_pvid(struct realtek_smi
55 int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable);
56 int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable);
57 int rtl8366_reset_vlan(struct realtek_smi *smi);
58 -int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
59 - struct netlink_ext_ack *extack);
60 int rtl8366_vlan_add(struct dsa_switch *ds, int port,
61 const struct switchdev_obj_port_vlan *vlan,
62 struct netlink_ext_ack *extack);
63 --- a/drivers/net/dsa/rtl8366.c
64 +++ b/drivers/net/dsa/rtl8366.c
65 @@ -292,41 +292,6 @@ int rtl8366_reset_vlan(struct realtek_sm
67 EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
69 -int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
70 - struct netlink_ext_ack *extack)
72 - struct realtek_smi *smi = ds->priv;
73 - struct rtl8366_vlan_4k vlan4k;
76 - /* Use VLAN nr port + 1 since VLAN0 is not valid */
77 - if (!smi->ops->is_vlan_valid(smi, port + 1))
80 - dev_info(smi->dev, "%s filtering on port %d\n",
81 - vlan_filtering ? "enable" : "disable",
85 - * The hardware support filter ID (FID) 0..7, I have no clue how to
86 - * support this in the driver when the callback only says on/off.
88 - ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
92 - /* Just set the filter to FID 1 for now then */
93 - ret = rtl8366_set_vlan(smi, port + 1,
102 -EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
104 int rtl8366_vlan_add(struct dsa_switch *ds, int port,
105 const struct switchdev_obj_port_vlan *vlan,
106 struct netlink_ext_ack *extack)
107 --- a/drivers/net/dsa/rtl8366rb.c
108 +++ b/drivers/net/dsa/rtl8366rb.c
110 #define RTL8366RB_PHY_NO_OFFSET 9
111 #define RTL8366RB_PHY_NO_MASK (0x1f << 9)
113 +/* VLAN Ingress Control Register 1, one bit per port.
114 + * bit 0 .. 5 will make the switch drop ingress frames without
115 + * VID such as untagged or priority-tagged frames for respective
117 + * bit 6 .. 11 will make the switch drop ingress frames carrying
118 + * a C-tag with VID != 0 for respective port.
120 +#define RTL8366RB_VLAN_INGRESS_CTRL1_REG 0x037E
121 +#define RTL8366RB_VLAN_INGRESS_CTRL1_DROP(port) (BIT((port)) | BIT((port) + 6))
123 +/* VLAN Ingress Control Register 2, one bit per port.
124 + * bit0 .. bit5 will make the switch drop all ingress frames with
125 + * a VLAN classification that does not include the port is in its
128 #define RTL8366RB_VLAN_INGRESS_CTRL2_REG 0x037f
130 /* LED control registers */
133 * struct rtl8366rb - RTL8366RB-specific data
134 * @max_mtu: per-port max MTU setting
135 + * @pvid_enabled: if PVID is set for respective port
136 + * @vlan_filtering: if VLAN filtering is enabled for respective port
139 unsigned int max_mtu[RTL8366RB_NUM_PORTS];
140 + bool pvid_enabled[RTL8366RB_NUM_PORTS];
141 + bool vlan_filtering[RTL8366RB_NUM_PORTS];
144 static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = {
145 @@ -933,11 +952,13 @@ static int rtl8366rb_setup(struct dsa_sw
149 - /* Discard VLAN tagged packets if the port is not a member of
150 - * the VLAN with which the packets is associated.
152 + /* Accept all packets by default, we enable filtering on-demand */
153 + ret = regmap_write(smi->map, RTL8366RB_VLAN_INGRESS_CTRL1_REG,
157 ret = regmap_write(smi->map, RTL8366RB_VLAN_INGRESS_CTRL2_REG,
158 - RTL8366RB_PORT_ALL);
163 @@ -1209,6 +1230,53 @@ rtl8366rb_port_bridge_leave(struct dsa_s
164 RTL8366RB_PORT_ISO_PORTS(port_bitmap), 0);
168 + * rtl8366rb_drop_untagged() - make the switch drop untagged and C-tagged frames
169 + * @smi: SMI state container
170 + * @port: the port to drop untagged and C-tagged frames on
171 + * @drop: whether to drop or pass untagged and C-tagged frames
173 +static int rtl8366rb_drop_untagged(struct realtek_smi *smi, int port, bool drop)
175 + return regmap_update_bits(smi->map, RTL8366RB_VLAN_INGRESS_CTRL1_REG,
176 + RTL8366RB_VLAN_INGRESS_CTRL1_DROP(port),
177 + drop ? RTL8366RB_VLAN_INGRESS_CTRL1_DROP(port) : 0);
180 +static int rtl8366rb_vlan_filtering(struct dsa_switch *ds, int port,
181 + bool vlan_filtering,
182 + struct netlink_ext_ack *extack)
184 + struct realtek_smi *smi = ds->priv;
185 + struct rtl8366rb *rb;
188 + rb = smi->chip_data;
190 + dev_dbg(smi->dev, "port %d: %s VLAN filtering\n", port,
191 + vlan_filtering ? "enable" : "disable");
193 + /* If the port is not in the member set, the frame will be dropped */
194 + ret = regmap_update_bits(smi->map, RTL8366RB_VLAN_INGRESS_CTRL2_REG,
195 + BIT(port), vlan_filtering ? BIT(port) : 0);
199 + /* Keep track if filtering is enabled on each port */
200 + rb->vlan_filtering[port] = vlan_filtering;
202 + /* If VLAN filtering is enabled and PVID is also enabled, we must
203 + * not drop any untagged or C-tagged frames. If we turn off VLAN
204 + * filtering on a port, we need ti accept any frames.
206 + if (vlan_filtering)
207 + ret = rtl8366rb_drop_untagged(smi, port, !rb->pvid_enabled[port]);
209 + ret = rtl8366rb_drop_untagged(smi, port, false);
214 static int rtl8366rb_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
216 struct realtek_smi *smi = ds->priv;
217 @@ -1420,14 +1488,34 @@ static int rtl8366rb_get_mc_index(struct
219 static int rtl8366rb_set_mc_index(struct realtek_smi *smi, int port, int index)
221 + struct rtl8366rb *rb;
225 + rb = smi->chip_data;
226 + pvid_enabled = !!index;
228 if (port >= smi->num_ports || index >= RTL8366RB_NUM_VLANS)
231 - return regmap_update_bits(smi->map, RTL8366RB_PORT_VLAN_CTRL_REG(port),
232 + ret = regmap_update_bits(smi->map, RTL8366RB_PORT_VLAN_CTRL_REG(port),
233 RTL8366RB_PORT_VLAN_CTRL_MASK <<
234 RTL8366RB_PORT_VLAN_CTRL_SHIFT(port),
235 (index & RTL8366RB_PORT_VLAN_CTRL_MASK) <<
236 RTL8366RB_PORT_VLAN_CTRL_SHIFT(port));
240 + rb->pvid_enabled[port] = pvid_enabled;
242 + /* If VLAN filtering is enabled and PVID is also enabled, we must
243 + * not drop any untagged or C-tagged frames. Make sure to update the
244 + * filtering setting.
246 + if (rb->vlan_filtering[port])
247 + ret = rtl8366rb_drop_untagged(smi, port, !pvid_enabled);
252 static bool rtl8366rb_is_vlan_valid(struct realtek_smi *smi, unsigned int vlan)
253 @@ -1437,7 +1525,7 @@ static bool rtl8366rb_is_vlan_valid(stru
254 if (smi->vlan4k_enabled)
255 max = RTL8366RB_NUM_VIDS - 1;
257 - if (vlan == 0 || vlan > max)
262 @@ -1594,7 +1682,7 @@ static const struct dsa_switch_ops rtl83
263 .get_sset_count = rtl8366_get_sset_count,
264 .port_bridge_join = rtl8366rb_port_bridge_join,
265 .port_bridge_leave = rtl8366rb_port_bridge_leave,
266 - .port_vlan_filtering = rtl8366_vlan_filtering,
267 + .port_vlan_filtering = rtl8366rb_vlan_filtering,
268 .port_vlan_add = rtl8366_vlan_add,
269 .port_vlan_del = rtl8366_vlan_del,
270 .port_enable = rtl8366rb_port_enable,