ocelot.c (62a22bcbd30ed01a0f0331288aa0cca9d9aae23b) ocelot.c (90e0aa8d108d22cb0dd646083fb3dfcc7a43a018)
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Microsemi Ocelot Switch driver
4 *
5 * Copyright (c) 2017 Microsemi Corporation
6 */
7#include <linux/dsa/ocelot.h>
8#include <linux/if_bridge.h>

--- 205 unchanged lines hidden (view full) ---

214 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
215
216 ocelot_rmw_gix(ocelot, val,
217 ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
218 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA,
219 ANA_PORT_DROP_CFG, port);
220}
221
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Microsemi Ocelot Switch driver
4 *
5 * Copyright (c) 2017 Microsemi Corporation
6 */
7#include <linux/dsa/ocelot.h>
8#include <linux/if_bridge.h>

--- 205 unchanged lines hidden (view full) ---

214 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
215
216 ocelot_rmw_gix(ocelot, val,
217 ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
218 ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA,
219 ANA_PORT_DROP_CFG, port);
220}
221
222static int ocelot_vlan_member_set(struct ocelot *ocelot, u32 vlan_mask, u16 vid)
222static struct ocelot_bridge_vlan *ocelot_bridge_vlan_find(struct ocelot *ocelot,
223 u16 vid)
223{
224{
225 struct ocelot_bridge_vlan *vlan;
226
227 list_for_each_entry(vlan, &ocelot->vlans, list)
228 if (vlan->vid == vid)
229 return vlan;
230
231 return NULL;
232}
233
234static int ocelot_vlan_member_add(struct ocelot *ocelot, int port, u16 vid)
235{
236 struct ocelot_bridge_vlan *vlan = ocelot_bridge_vlan_find(ocelot, vid);
237 unsigned long portmask;
224 int err;
225
238 int err;
239
226 err = ocelot_vlant_set_mask(ocelot, vid, vlan_mask);
227 if (err)
240 if (vlan) {
241 portmask = vlan->portmask | BIT(port);
242
243 err = ocelot_vlant_set_mask(ocelot, vid, portmask);
244 if (err)
245 return err;
246
247 vlan->portmask = portmask;
248
249 return 0;
250 }
251
252 vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
253 if (!vlan)
254 return -ENOMEM;
255
256 portmask = BIT(port);
257
258 err = ocelot_vlant_set_mask(ocelot, vid, portmask);
259 if (err) {
260 kfree(vlan);
228 return err;
261 return err;
262 }
229
263
230 ocelot->vlan_mask[vid] = vlan_mask;
264 vlan->vid = vid;
265 vlan->portmask = portmask;
266 INIT_LIST_HEAD(&vlan->list);
267 list_add_tail(&vlan->list, &ocelot->vlans);
231
232 return 0;
233}
234
268
269 return 0;
270}
271
235static int ocelot_vlan_member_add(struct ocelot *ocelot, int port, u16 vid)
236{
237 return ocelot_vlan_member_set(ocelot,
238 ocelot->vlan_mask[vid] | BIT(port),
239 vid);
240}
241
242static int ocelot_vlan_member_del(struct ocelot *ocelot, int port, u16 vid)
243{
272static int ocelot_vlan_member_del(struct ocelot *ocelot, int port, u16 vid)
273{
244 return ocelot_vlan_member_set(ocelot,
245 ocelot->vlan_mask[vid] & ~BIT(port),
246 vid);
274 struct ocelot_bridge_vlan *vlan = ocelot_bridge_vlan_find(ocelot, vid);
275 unsigned long portmask;
276 int err;
277
278 if (!vlan)
279 return 0;
280
281 portmask = vlan->portmask & ~BIT(port);
282
283 err = ocelot_vlant_set_mask(ocelot, vid, portmask);
284 if (err)
285 return err;
286
287 vlan->portmask = portmask;
288 if (vlan->portmask)
289 return 0;
290
291 list_del(&vlan->list);
292 kfree(vlan);
293
294 return 0;
247}
248
249int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
250 bool vlan_aware, struct netlink_ext_ack *extack)
251{
252 struct ocelot_vcap_block *block = &ocelot->block[VCAP_IS1];
253 struct ocelot_port *ocelot_port = ocelot->ports[port];
254 struct ocelot_vcap_filter *filter;

--- 109 unchanged lines hidden (view full) ---

364
365 /* Clear VLAN table, by default all ports are members of all VLANs */
366 ocelot_write(ocelot, ANA_TABLES_VLANACCESS_CMD_INIT,
367 ANA_TABLES_VLANACCESS);
368 ocelot_vlant_wait_for_completion(ocelot);
369
370 /* Configure the port VLAN memberships */
371 for (vid = 1; vid < VLAN_N_VID; vid++)
295}
296
297int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
298 bool vlan_aware, struct netlink_ext_ack *extack)
299{
300 struct ocelot_vcap_block *block = &ocelot->block[VCAP_IS1];
301 struct ocelot_port *ocelot_port = ocelot->ports[port];
302 struct ocelot_vcap_filter *filter;

--- 109 unchanged lines hidden (view full) ---

412
413 /* Clear VLAN table, by default all ports are members of all VLANs */
414 ocelot_write(ocelot, ANA_TABLES_VLANACCESS_CMD_INIT,
415 ANA_TABLES_VLANACCESS);
416 ocelot_vlant_wait_for_completion(ocelot);
417
418 /* Configure the port VLAN memberships */
419 for (vid = 1; vid < VLAN_N_VID; vid++)
372 ocelot_vlan_member_set(ocelot, 0, vid);
420 ocelot_vlant_set_mask(ocelot, vid, 0);
373
374 /* Because VLAN filtering is enabled, we need VID 0 to get untagged
375 * traffic. It is added automatically if 8021q module is loaded, but
376 * we can't rely on it since module may be not loaded.
377 */
421
422 /* Because VLAN filtering is enabled, we need VID 0 to get untagged
423 * traffic. It is added automatically if 8021q module is loaded, but
424 * we can't rely on it since module may be not loaded.
425 */
378 ocelot_vlan_member_set(ocelot, all_ports, 0);
426 ocelot_vlant_set_mask(ocelot, 0, all_ports);
379
380 /* Set vlan ingress filter mask to all ports but the CPU port by
381 * default.
382 */
383 ocelot_write(ocelot, all_ports, ANA_VLANMASK);
384
385 for (port = 0; port < ocelot->num_phys_ports; port++) {
386 ocelot_write_gix(ocelot, 0, REW_PORT_VLAN_CFG, port);

--- 1735 unchanged lines hidden (view full) ---

2122 ocelot->owq = alloc_ordered_workqueue("ocelot-owq", 0);
2123 if (!ocelot->owq) {
2124 destroy_workqueue(ocelot->stats_queue);
2125 return -ENOMEM;
2126 }
2127
2128 INIT_LIST_HEAD(&ocelot->multicast);
2129 INIT_LIST_HEAD(&ocelot->pgids);
427
428 /* Set vlan ingress filter mask to all ports but the CPU port by
429 * default.
430 */
431 ocelot_write(ocelot, all_ports, ANA_VLANMASK);
432
433 for (port = 0; port < ocelot->num_phys_ports; port++) {
434 ocelot_write_gix(ocelot, 0, REW_PORT_VLAN_CFG, port);

--- 1735 unchanged lines hidden (view full) ---

2170 ocelot->owq = alloc_ordered_workqueue("ocelot-owq", 0);
2171 if (!ocelot->owq) {
2172 destroy_workqueue(ocelot->stats_queue);
2173 return -ENOMEM;
2174 }
2175
2176 INIT_LIST_HEAD(&ocelot->multicast);
2177 INIT_LIST_HEAD(&ocelot->pgids);
2178 INIT_LIST_HEAD(&ocelot->vlans);
2130 ocelot_detect_features(ocelot);
2131 ocelot_mact_init(ocelot);
2132 ocelot_vlan_init(ocelot);
2133 ocelot_vcap_init(ocelot);
2134 ocelot_cpu_port_init(ocelot);
2135
2136 for (port = 0; port < ocelot->num_phys_ports; port++) {
2137 /* Clear all counters (5 groups) */

--- 120 unchanged lines hidden ---
2179 ocelot_detect_features(ocelot);
2180 ocelot_mact_init(ocelot);
2181 ocelot_vlan_init(ocelot);
2182 ocelot_vcap_init(ocelot);
2183 ocelot_cpu_port_init(ocelot);
2184
2185 for (port = 0; port < ocelot->num_phys_ports; port++) {
2186 /* Clear all counters (5 groups) */

--- 120 unchanged lines hidden ---