Commit 7d4f4d14 authored by David S. Miller's avatar David S. Miller

Merge branch 'mscc-ocelot-all-ports-vlan-untagged-egress'

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents dfcb63ce d4004422
...@@ -162,48 +162,117 @@ static int ocelot_vlant_set_mask(struct ocelot *ocelot, u16 vid, u32 mask) ...@@ -162,48 +162,117 @@ static int ocelot_vlant_set_mask(struct ocelot *ocelot, u16 vid, u32 mask)
return ocelot_vlant_wait_for_completion(ocelot); return ocelot_vlant_wait_for_completion(ocelot);
} }
static void ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, static int ocelot_port_num_untagged_vlans(struct ocelot *ocelot, int port)
struct ocelot_vlan native_vlan)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_bridge_vlan *vlan;
u32 val = 0; int num_untagged = 0;
ocelot_port->native_vlan = native_vlan; list_for_each_entry(vlan, &ocelot->vlans, list) {
if (!(vlan->portmask & BIT(port)))
continue;
ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(native_vlan.vid), if (vlan->untagged & BIT(port))
REW_PORT_VLAN_CFG_PORT_VID_M, num_untagged++;
REW_PORT_VLAN_CFG, port); }
return num_untagged;
}
static int ocelot_port_num_tagged_vlans(struct ocelot *ocelot, int port)
{
struct ocelot_bridge_vlan *vlan;
int num_tagged = 0;
list_for_each_entry(vlan, &ocelot->vlans, list) {
if (!(vlan->portmask & BIT(port)))
continue;
if (!(vlan->untagged & BIT(port)))
num_tagged++;
}
return num_tagged;
}
/* We use native VLAN when we have to mix egress-tagged VLANs with exactly
* _one_ egress-untagged VLAN (_the_ native VLAN)
*/
static bool ocelot_port_uses_native_vlan(struct ocelot *ocelot, int port)
{
return ocelot_port_num_tagged_vlans(ocelot, port) &&
ocelot_port_num_untagged_vlans(ocelot, port) == 1;
}
static struct ocelot_bridge_vlan *
ocelot_port_find_native_vlan(struct ocelot *ocelot, int port)
{
struct ocelot_bridge_vlan *vlan;
list_for_each_entry(vlan, &ocelot->vlans, list)
if (vlan->portmask & BIT(port) && vlan->untagged & BIT(port))
return vlan;
return NULL;
}
/* Keep in sync REW_TAG_CFG_TAG_CFG and, if applicable,
* REW_PORT_VLAN_CFG_PORT_VID, with the bridge VLAN table and VLAN awareness
* state of the port.
*/
static void ocelot_port_manage_port_tag(struct ocelot *ocelot, int port)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
enum ocelot_port_tag_config tag_cfg;
bool uses_native_vlan = false;
if (ocelot_port->vlan_aware) { if (ocelot_port->vlan_aware) {
if (native_vlan.valid) uses_native_vlan = ocelot_port_uses_native_vlan(ocelot, port);
/* Tag all frames except when VID == DEFAULT_VLAN */
val = REW_TAG_CFG_TAG_CFG(1); if (uses_native_vlan)
tag_cfg = OCELOT_PORT_TAG_NATIVE;
else if (ocelot_port_num_untagged_vlans(ocelot, port))
tag_cfg = OCELOT_PORT_TAG_DISABLED;
else else
/* Tag all frames */ tag_cfg = OCELOT_PORT_TAG_TRUNK;
val = REW_TAG_CFG_TAG_CFG(3);
} else { } else {
/* Port tagging disabled. */ tag_cfg = OCELOT_PORT_TAG_DISABLED;
val = REW_TAG_CFG_TAG_CFG(0);
} }
ocelot_rmw_gix(ocelot, val,
ocelot_rmw_gix(ocelot, REW_TAG_CFG_TAG_CFG(tag_cfg),
REW_TAG_CFG_TAG_CFG_M, REW_TAG_CFG_TAG_CFG_M,
REW_TAG_CFG, port); REW_TAG_CFG, port);
if (uses_native_vlan) {
struct ocelot_bridge_vlan *native_vlan;
/* Not having a native VLAN is impossible, because
* ocelot_port_num_untagged_vlans has returned 1.
* So there is no use in checking for NULL here.
*/
native_vlan = ocelot_port_find_native_vlan(ocelot, port);
ocelot_rmw_gix(ocelot,
REW_PORT_VLAN_CFG_PORT_VID(native_vlan->vid),
REW_PORT_VLAN_CFG_PORT_VID_M,
REW_PORT_VLAN_CFG, port);
}
} }
/* Default vlan to clasify for untagged frames (may be zero) */ /* Default vlan to clasify for untagged frames (may be zero) */
static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, static void ocelot_port_set_pvid(struct ocelot *ocelot, int port,
struct ocelot_vlan pvid_vlan) const struct ocelot_bridge_vlan *pvid_vlan)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
u16 pvid = OCELOT_VLAN_UNAWARE_PVID;
u32 val = 0; u32 val = 0;
ocelot_port->pvid_vlan = pvid_vlan; ocelot_port->pvid_vlan = pvid_vlan;
if (!ocelot_port->vlan_aware) if (ocelot_port->vlan_aware && pvid_vlan)
pvid_vlan.vid = 0; pvid = pvid_vlan->vid;
ocelot_rmw_gix(ocelot, ocelot_rmw_gix(ocelot,
ANA_PORT_VLAN_CFG_VLAN_VID(pvid_vlan.vid), ANA_PORT_VLAN_CFG_VLAN_VID(pvid),
ANA_PORT_VLAN_CFG_VLAN_VID_M, ANA_PORT_VLAN_CFG_VLAN_VID_M,
ANA_PORT_VLAN_CFG, port); ANA_PORT_VLAN_CFG, port);
...@@ -212,7 +281,7 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, ...@@ -212,7 +281,7 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port,
* classified to VLAN 0, but that is always in our RX filter, so it * classified to VLAN 0, but that is always in our RX filter, so it
* would get accepted were it not for this setting. * would get accepted were it not for this setting.
*/ */
if (!pvid_vlan.valid && ocelot_port->vlan_aware) if (!pvid_vlan && ocelot_port->vlan_aware)
val = ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA | val = ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA; ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
...@@ -222,31 +291,90 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, ...@@ -222,31 +291,90 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port,
ANA_PORT_DROP_CFG, port); ANA_PORT_DROP_CFG, port);
} }
static int ocelot_vlan_member_set(struct ocelot *ocelot, u32 vlan_mask, u16 vid) static struct ocelot_bridge_vlan *ocelot_bridge_vlan_find(struct ocelot *ocelot,
u16 vid)
{ {
struct ocelot_bridge_vlan *vlan;
list_for_each_entry(vlan, &ocelot->vlans, list)
if (vlan->vid == vid)
return vlan;
return NULL;
}
static int ocelot_vlan_member_add(struct ocelot *ocelot, int port, u16 vid,
bool untagged)
{
struct ocelot_bridge_vlan *vlan = ocelot_bridge_vlan_find(ocelot, vid);
unsigned long portmask;
int err; int err;
err = ocelot_vlant_set_mask(ocelot, vid, vlan_mask); if (vlan) {
portmask = vlan->portmask | BIT(port);
err = ocelot_vlant_set_mask(ocelot, vid, portmask);
if (err) if (err)
return err; return err;
ocelot->vlan_mask[vid] = vlan_mask; vlan->portmask = portmask;
/* Bridge VLANs can be overwritten with a different
* egress-tagging setting, so make sure to override an untagged
* with a tagged VID if that's going on.
*/
if (untagged)
vlan->untagged |= BIT(port);
else
vlan->untagged &= ~BIT(port);
return 0; return 0;
} }
static int ocelot_vlan_member_add(struct ocelot *ocelot, int port, u16 vid) vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
{ if (!vlan)
return ocelot_vlan_member_set(ocelot, return -ENOMEM;
ocelot->vlan_mask[vid] | BIT(port),
vid); portmask = BIT(port);
err = ocelot_vlant_set_mask(ocelot, vid, portmask);
if (err) {
kfree(vlan);
return err;
}
vlan->vid = vid;
vlan->portmask = portmask;
if (untagged)
vlan->untagged = BIT(port);
INIT_LIST_HEAD(&vlan->list);
list_add_tail(&vlan->list, &ocelot->vlans);
return 0;
} }
static int ocelot_vlan_member_del(struct ocelot *ocelot, int port, u16 vid) static int ocelot_vlan_member_del(struct ocelot *ocelot, int port, u16 vid)
{ {
return ocelot_vlan_member_set(ocelot, struct ocelot_bridge_vlan *vlan = ocelot_bridge_vlan_find(ocelot, vid);
ocelot->vlan_mask[vid] & ~BIT(port), unsigned long portmask;
vid); int err;
if (!vlan)
return 0;
portmask = vlan->portmask & ~BIT(port);
err = ocelot_vlant_set_mask(ocelot, vid, portmask);
if (err)
return err;
vlan->portmask = portmask;
if (vlan->portmask)
return 0;
list_del(&vlan->list);
kfree(vlan);
return 0;
} }
int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
...@@ -279,7 +407,7 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, ...@@ -279,7 +407,7 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
ANA_PORT_VLAN_CFG, port); ANA_PORT_VLAN_CFG, port);
ocelot_port_set_pvid(ocelot, port, ocelot_port->pvid_vlan); ocelot_port_set_pvid(ocelot, port, ocelot_port->pvid_vlan);
ocelot_port_set_native_vlan(ocelot, port, ocelot_port->native_vlan); ocelot_port_manage_port_tag(ocelot, port);
return 0; return 0;
} }
...@@ -288,15 +416,21 @@ EXPORT_SYMBOL(ocelot_port_vlan_filtering); ...@@ -288,15 +416,21 @@ EXPORT_SYMBOL(ocelot_port_vlan_filtering);
int ocelot_vlan_prepare(struct ocelot *ocelot, int port, u16 vid, bool pvid, int ocelot_vlan_prepare(struct ocelot *ocelot, int port, u16 vid, bool pvid,
bool untagged, struct netlink_ext_ack *extack) bool untagged, struct netlink_ext_ack *extack)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; if (untagged) {
/* We are adding an egress-tagged VLAN */
/* Deny changing the native VLAN, but always permit deleting it */ if (ocelot_port_uses_native_vlan(ocelot, port)) {
if (untagged && ocelot_port->native_vlan.vid != vid && NL_SET_ERR_MSG_MOD(extack,
ocelot_port->native_vlan.valid) { "Port with egress-tagged VLANs cannot have more than one egress-untagged (native) VLAN");
return -EBUSY;
}
} else {
/* We are adding an egress-tagged VLAN */
if (ocelot_port_num_untagged_vlans(ocelot, port) > 1) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"Port already has a native VLAN"); "Port with more than one egress-untagged VLAN cannot have egress-tagged VLANs");
return -EBUSY; return -EBUSY;
} }
}
return 0; return 0;
} }
...@@ -307,27 +441,17 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid, ...@@ -307,27 +441,17 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
{ {
int err; int err;
err = ocelot_vlan_member_add(ocelot, port, vid); err = ocelot_vlan_member_add(ocelot, port, vid, untagged);
if (err) if (err)
return err; return err;
/* Default ingress vlan classification */ /* Default ingress vlan classification */
if (pvid) { if (pvid)
struct ocelot_vlan pvid_vlan; ocelot_port_set_pvid(ocelot, port,
ocelot_bridge_vlan_find(ocelot, vid));
pvid_vlan.vid = vid;
pvid_vlan.valid = true;
ocelot_port_set_pvid(ocelot, port, pvid_vlan);
}
/* Untagged egress vlan clasification */ /* Untagged egress vlan clasification */
if (untagged) { ocelot_port_manage_port_tag(ocelot, port);
struct ocelot_vlan native_vlan;
native_vlan.vid = vid;
native_vlan.valid = true;
ocelot_port_set_native_vlan(ocelot, port, native_vlan);
}
return 0; return 0;
} }
...@@ -343,18 +467,11 @@ int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid) ...@@ -343,18 +467,11 @@ int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid)
return err; return err;
/* Ingress */ /* Ingress */
if (ocelot_port->pvid_vlan.vid == vid) { if (ocelot_port->pvid_vlan && ocelot_port->pvid_vlan->vid == vid)
struct ocelot_vlan pvid_vlan = {0}; ocelot_port_set_pvid(ocelot, port, NULL);
ocelot_port_set_pvid(ocelot, port, pvid_vlan);
}
/* Egress */ /* Egress */
if (ocelot_port->native_vlan.vid == vid) { ocelot_port_manage_port_tag(ocelot, port);
struct ocelot_vlan native_vlan = {0};
ocelot_port_set_native_vlan(ocelot, port, native_vlan);
}
return 0; return 0;
} }
...@@ -372,13 +489,13 @@ static void ocelot_vlan_init(struct ocelot *ocelot) ...@@ -372,13 +489,13 @@ static void ocelot_vlan_init(struct ocelot *ocelot)
/* Configure the port VLAN memberships */ /* Configure the port VLAN memberships */
for (vid = 1; vid < VLAN_N_VID; vid++) for (vid = 1; vid < VLAN_N_VID; vid++)
ocelot_vlan_member_set(ocelot, 0, vid); ocelot_vlant_set_mask(ocelot, vid, 0);
/* Because VLAN filtering is enabled, we need VID 0 to get untagged /* Because VLAN filtering is enabled, we need VID 0 to get untagged
* traffic. It is added automatically if 8021q module is loaded, but * traffic. It is added automatically if 8021q module is loaded, but
* we can't rely on it since module may be not loaded. * we can't rely on it since module may be not loaded.
*/ */
ocelot_vlan_member_set(ocelot, all_ports, 0); ocelot_vlant_set_mask(ocelot, OCELOT_VLAN_UNAWARE_PVID, all_ports);
/* Set vlan ingress filter mask to all ports but the CPU port by /* Set vlan ingress filter mask to all ports but the CPU port by
* default. * default.
...@@ -1680,12 +1797,11 @@ void ocelot_port_bridge_leave(struct ocelot *ocelot, int port, ...@@ -1680,12 +1797,11 @@ void ocelot_port_bridge_leave(struct ocelot *ocelot, int port,
struct net_device *bridge) struct net_device *bridge)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
struct ocelot_vlan pvid = {0}, native_vlan = {0};
ocelot_port->bridge = NULL; ocelot_port->bridge = NULL;
ocelot_port_set_pvid(ocelot, port, pvid); ocelot_port_set_pvid(ocelot, port, NULL);
ocelot_port_set_native_vlan(ocelot, port, native_vlan); ocelot_port_manage_port_tag(ocelot, port);
ocelot_apply_bridge_fwd_mask(ocelot); ocelot_apply_bridge_fwd_mask(ocelot);
} }
EXPORT_SYMBOL(ocelot_port_bridge_leave); EXPORT_SYMBOL(ocelot_port_bridge_leave);
...@@ -2071,7 +2187,8 @@ static void ocelot_cpu_port_init(struct ocelot *ocelot) ...@@ -2071,7 +2187,8 @@ static void ocelot_cpu_port_init(struct ocelot *ocelot)
OCELOT_TAG_PREFIX_NONE); OCELOT_TAG_PREFIX_NONE);
/* Configure the CPU port to be VLAN aware */ /* Configure the CPU port to be VLAN aware */
ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) | ocelot_write_gix(ocelot,
ANA_PORT_VLAN_CFG_VLAN_VID(OCELOT_VLAN_UNAWARE_PVID) |
ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1), ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
ANA_PORT_VLAN_CFG, cpu); ANA_PORT_VLAN_CFG, cpu);
...@@ -2130,6 +2247,7 @@ int ocelot_init(struct ocelot *ocelot) ...@@ -2130,6 +2247,7 @@ int ocelot_init(struct ocelot *ocelot)
INIT_LIST_HEAD(&ocelot->multicast); INIT_LIST_HEAD(&ocelot->multicast);
INIT_LIST_HEAD(&ocelot->pgids); INIT_LIST_HEAD(&ocelot->pgids);
INIT_LIST_HEAD(&ocelot->vlans);
ocelot_detect_features(ocelot); ocelot_detect_features(ocelot);
ocelot_mact_init(ocelot); ocelot_mact_init(ocelot);
ocelot_vlan_init(ocelot); ocelot_vlan_init(ocelot);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "ocelot_rew.h" #include "ocelot_rew.h"
#include "ocelot_qs.h" #include "ocelot_qs.h"
#define OCELOT_VLAN_UNAWARE_PVID 0
#define OCELOT_BUFFER_CELL_SZ 60 #define OCELOT_BUFFER_CELL_SZ 60
#define OCELOT_STATS_CHECK_DELAY (2 * HZ) #define OCELOT_STATS_CHECK_DELAY (2 * HZ)
......
...@@ -116,16 +116,16 @@ static void ocelot_mrp_save_mac(struct ocelot *ocelot, ...@@ -116,16 +116,16 @@ static void ocelot_mrp_save_mac(struct ocelot *ocelot,
struct ocelot_port *port) struct ocelot_port *port)
{ {
ocelot_mact_learn(ocelot, PGID_BLACKHOLE, mrp_test_dmac, ocelot_mact_learn(ocelot, PGID_BLACKHOLE, mrp_test_dmac,
port->pvid_vlan.vid, ENTRYTYPE_LOCKED); OCELOT_VLAN_UNAWARE_PVID, ENTRYTYPE_LOCKED);
ocelot_mact_learn(ocelot, PGID_BLACKHOLE, mrp_control_dmac, ocelot_mact_learn(ocelot, PGID_BLACKHOLE, mrp_control_dmac,
port->pvid_vlan.vid, ENTRYTYPE_LOCKED); OCELOT_VLAN_UNAWARE_PVID, ENTRYTYPE_LOCKED);
} }
static void ocelot_mrp_del_mac(struct ocelot *ocelot, static void ocelot_mrp_del_mac(struct ocelot *ocelot,
struct ocelot_port *port) struct ocelot_port *port)
{ {
ocelot_mact_forget(ocelot, mrp_test_dmac, port->pvid_vlan.vid); ocelot_mact_forget(ocelot, mrp_test_dmac, OCELOT_VLAN_UNAWARE_PVID);
ocelot_mact_forget(ocelot, mrp_control_dmac, port->pvid_vlan.vid); ocelot_mact_forget(ocelot, mrp_control_dmac, OCELOT_VLAN_UNAWARE_PVID);
} }
int ocelot_mrp_add(struct ocelot *ocelot, int port, int ocelot_mrp_add(struct ocelot *ocelot, int port,
......
...@@ -418,7 +418,7 @@ static int ocelot_vlan_vid_del(struct net_device *dev, u16 vid) ...@@ -418,7 +418,7 @@ static int ocelot_vlan_vid_del(struct net_device *dev, u16 vid)
* with VLAN filtering feature. We need to keep it to receive * with VLAN filtering feature. We need to keep it to receive
* untagged traffic. * untagged traffic.
*/ */
if (vid == 0) if (vid == OCELOT_VLAN_UNAWARE_PVID)
return 0; return 0;
ret = ocelot_vlan_del(ocelot, port, vid); ret = ocelot_vlan_del(ocelot, port, vid);
...@@ -553,7 +553,7 @@ static int ocelot_mc_unsync(struct net_device *dev, const unsigned char *addr) ...@@ -553,7 +553,7 @@ static int ocelot_mc_unsync(struct net_device *dev, const unsigned char *addr)
struct ocelot_mact_work_ctx w; struct ocelot_mact_work_ctx w;
ether_addr_copy(w.forget.addr, addr); ether_addr_copy(w.forget.addr, addr);
w.forget.vid = ocelot_port->pvid_vlan.vid; w.forget.vid = OCELOT_VLAN_UNAWARE_PVID;
w.type = OCELOT_MACT_FORGET; w.type = OCELOT_MACT_FORGET;
return ocelot_enqueue_mact_action(ocelot, &w); return ocelot_enqueue_mact_action(ocelot, &w);
...@@ -567,7 +567,7 @@ static int ocelot_mc_sync(struct net_device *dev, const unsigned char *addr) ...@@ -567,7 +567,7 @@ static int ocelot_mc_sync(struct net_device *dev, const unsigned char *addr)
struct ocelot_mact_work_ctx w; struct ocelot_mact_work_ctx w;
ether_addr_copy(w.learn.addr, addr); ether_addr_copy(w.learn.addr, addr);
w.learn.vid = ocelot_port->pvid_vlan.vid; w.learn.vid = OCELOT_VLAN_UNAWARE_PVID;
w.learn.pgid = PGID_CPU; w.learn.pgid = PGID_CPU;
w.learn.entry_type = ENTRYTYPE_LOCKED; w.learn.entry_type = ENTRYTYPE_LOCKED;
w.type = OCELOT_MACT_LEARN; w.type = OCELOT_MACT_LEARN;
...@@ -602,9 +602,9 @@ static int ocelot_port_set_mac_address(struct net_device *dev, void *p) ...@@ -602,9 +602,9 @@ static int ocelot_port_set_mac_address(struct net_device *dev, void *p)
/* Learn the new net device MAC address in the mac table. */ /* Learn the new net device MAC address in the mac table. */
ocelot_mact_learn(ocelot, PGID_CPU, addr->sa_data, ocelot_mact_learn(ocelot, PGID_CPU, addr->sa_data,
ocelot_port->pvid_vlan.vid, ENTRYTYPE_LOCKED); OCELOT_VLAN_UNAWARE_PVID, ENTRYTYPE_LOCKED);
/* Then forget the previous one. */ /* Then forget the previous one. */
ocelot_mact_forget(ocelot, dev->dev_addr, ocelot_port->pvid_vlan.vid); ocelot_mact_forget(ocelot, dev->dev_addr, OCELOT_VLAN_UNAWARE_PVID);
eth_hw_addr_set(dev, addr->sa_data); eth_hw_addr_set(dev, addr->sa_data);
return 0; return 0;
...@@ -1707,7 +1707,7 @@ int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target, ...@@ -1707,7 +1707,7 @@ int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,
eth_hw_addr_gen(dev, ocelot->base_mac, port); eth_hw_addr_gen(dev, ocelot->base_mac, port);
ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr,
ocelot_port->pvid_vlan.vid, ENTRYTYPE_LOCKED); OCELOT_VLAN_UNAWARE_PVID, ENTRYTYPE_LOCKED);
ocelot_init_port(ocelot, port); ocelot_init_port(ocelot, port);
......
...@@ -563,9 +563,22 @@ struct ocelot_vcap_block { ...@@ -563,9 +563,22 @@ struct ocelot_vcap_block {
int pol_lpr; int pol_lpr;
}; };
struct ocelot_vlan { struct ocelot_bridge_vlan {
bool valid;
u16 vid; u16 vid;
unsigned long portmask;
unsigned long untagged;
struct list_head list;
};
enum ocelot_port_tag_config {
/* all VLANs are egress-untagged */
OCELOT_PORT_TAG_DISABLED = 0,
/* all VLANs except the native VLAN and VID 0 are egress-tagged */
OCELOT_PORT_TAG_NATIVE = 1,
/* all VLANs except VID 0 are egress-tagged */
OCELOT_PORT_TAG_TRUNK_NO_VID0 = 2,
/* all VLANs are egress-tagged */
OCELOT_PORT_TAG_TRUNK = 3,
}; };
enum ocelot_sb { enum ocelot_sb {
...@@ -590,9 +603,7 @@ struct ocelot_port { ...@@ -590,9 +603,7 @@ struct ocelot_port {
bool vlan_aware; bool vlan_aware;
/* VLAN that untagged frames are classified to, on ingress */ /* VLAN that untagged frames are classified to, on ingress */
struct ocelot_vlan pvid_vlan; const struct ocelot_bridge_vlan *pvid_vlan;
/* The VLAN ID that will be transmitted as untagged, on egress */
struct ocelot_vlan native_vlan;
unsigned int ptp_skbs_in_flight; unsigned int ptp_skbs_in_flight;
u8 ptp_cmd; u8 ptp_cmd;
...@@ -635,8 +646,7 @@ struct ocelot { ...@@ -635,8 +646,7 @@ struct ocelot {
u8 base_mac[ETH_ALEN]; u8 base_mac[ETH_ALEN];
/* Keep track of the vlan port masks */ struct list_head vlans;
u32 vlan_mask[VLAN_N_VID];
/* Switches like VSC9959 have flooding per traffic class */ /* Switches like VSC9959 have flooding per traffic class */
int num_flooding_pgids; int num_flooding_pgids;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment