ar71xx: ar8216: move policies, pvid to setup_port

This moves ingress, egress policy and pvid decisions to setup_port methods.
They arenow device type dependent.

This allows policy changes on only one device type which is needed to allow
tagged + untagged operation on ar8327.

Tested on TP-LINK WDR-3600 (ar8327N).

Signed-off-by: Valentin Spreckels <Valentin.Spreckels@Informatik.Uni-Oldenburg.DE>

SVN-Revision: 42652
This commit is contained in:
Felix Fietkau 2014-09-23 10:18:38 +00:00
parent 9c43ea9a8b
commit 1c675ee9be

View file

@ -73,8 +73,7 @@ struct ar8xxx_chip {
void (*init_globals)(struct ar8xxx_priv *priv); void (*init_globals)(struct ar8xxx_priv *priv);
void (*init_port)(struct ar8xxx_priv *priv, int port); void (*init_port)(struct ar8xxx_priv *priv, int port);
void (*setup_port)(struct ar8xxx_priv *priv, int port, u32 egress, void (*setup_port)(struct ar8xxx_priv *priv, int port, u32 members);
u32 ingress, u32 members, u32 pvid);
u32 (*read_port_status)(struct ar8xxx_priv *priv, int port); u32 (*read_port_status)(struct ar8xxx_priv *priv, int port);
int (*atu_flush)(struct ar8xxx_priv *priv); int (*atu_flush)(struct ar8xxx_priv *priv);
void (*vtu_flush)(struct ar8xxx_priv *priv); void (*vtu_flush)(struct ar8xxx_priv *priv);
@ -722,10 +721,24 @@ ar8216_read_port_status(struct ar8xxx_priv *priv, int port)
} }
static void static void
ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 egress, u32 ingress, ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
u32 members, u32 pvid)
{ {
u32 header; u32 header;
u32 egress, ingress;
u32 pvid;
if (priv->vlan) {
pvid = priv->vlan_id[priv->pvid[port]];
if (priv->vlan_tagged & (1 << port))
egress = AR8216_OUT_ADD_VLAN;
else
egress = AR8216_OUT_STRIP_VLAN;
ingress = AR8216_IN_SECURE;
} else {
pvid = port;
egress = AR8216_OUT_KEEP;
ingress = AR8216_IN_PORT_ONLY;
}
if (chip_is_ar8216(priv) && priv->vlan && port == AR8216_PORT_CPU) if (chip_is_ar8216(priv) && priv->vlan && port == AR8216_PORT_CPU)
header = AR8216_PORT_CTRL_HEADER; header = AR8216_PORT_CTRL_HEADER;
@ -807,9 +820,24 @@ static const struct ar8xxx_chip ar8216_chip = {
}; };
static void static void
ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 egress, u32 ingress, ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
u32 members, u32 pvid)
{ {
u32 egress, ingress;
u32 pvid;
if (priv->vlan) {
pvid = priv->vlan_id[priv->pvid[port]];
if (priv->vlan_tagged & (1 << port))
egress = AR8216_OUT_ADD_VLAN;
else
egress = AR8216_OUT_STRIP_VLAN;
ingress = AR8216_IN_SECURE;
} else {
pvid = port;
egress = AR8216_OUT_KEEP;
ingress = AR8216_IN_PORT_ONLY;
}
ar8xxx_rmw(priv, AR8216_REG_PORT_CTRL(port), ar8xxx_rmw(priv, AR8216_REG_PORT_CTRL(port),
AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE | AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE |
AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE | AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE |
@ -1731,31 +1759,31 @@ ar8327_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask)
} }
static void static void
ar8327_setup_port(struct ar8xxx_priv *priv, int port, u32 egress, u32 ingress, ar8327_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
u32 members, u32 pvid)
{ {
u32 t; u32 t;
u32 mode; u32 egress, ingress;
u32 pvid;
if (priv->vlan) {
pvid = priv->vlan_id[priv->pvid[port]];
if (priv->vlan_tagged & (1 << port))
egress = AR8327_PORT_VLAN1_OUT_MODE_TAG;
else
egress = AR8327_PORT_VLAN1_OUT_MODE_UNTAG;
ingress = AR8216_IN_SECURE;
} else {
pvid = port;
egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
ingress = AR8216_IN_PORT_ONLY;
}
t = pvid << AR8327_PORT_VLAN0_DEF_SVID_S; t = pvid << AR8327_PORT_VLAN0_DEF_SVID_S;
t |= pvid << AR8327_PORT_VLAN0_DEF_CVID_S; t |= pvid << AR8327_PORT_VLAN0_DEF_CVID_S;
priv->write(priv, AR8327_REG_PORT_VLAN0(port), t); priv->write(priv, AR8327_REG_PORT_VLAN0(port), t);
mode = AR8327_PORT_VLAN1_OUT_MODE_UNMOD;
switch (egress) {
case AR8216_OUT_KEEP:
mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
break;
case AR8216_OUT_STRIP_VLAN:
mode = AR8327_PORT_VLAN1_OUT_MODE_UNTAG;
break;
case AR8216_OUT_ADD_VLAN:
mode = AR8327_PORT_VLAN1_OUT_MODE_TAG;
break;
}
t = AR8327_PORT_VLAN1_PORT_VLAN_PROP; t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
t |= mode << AR8327_PORT_VLAN1_OUT_MODE_S; t |= egress << AR8327_PORT_VLAN1_OUT_MODE_S;
priv->write(priv, AR8327_REG_PORT_VLAN1(port), t); priv->write(priv, AR8327_REG_PORT_VLAN1(port), t);
t = members; t = members;
@ -2041,24 +2069,7 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev)
/* update the port destination mask registers and tag settings */ /* update the port destination mask registers and tag settings */
for (i = 0; i < dev->ports; i++) { for (i = 0; i < dev->ports; i++) {
int egress, ingress; priv->chip->setup_port(priv, i, portmask[i]);
int pvid;
if (priv->vlan) {
pvid = priv->vlan_id[priv->pvid[i]];
if (priv->vlan_tagged & (1 << i))
egress = AR8216_OUT_ADD_VLAN;
else
egress = AR8216_OUT_STRIP_VLAN;
ingress = AR8216_IN_SECURE;
} else {
pvid = i;
egress = AR8216_OUT_KEEP;
ingress = AR8216_IN_PORT_ONLY;
}
priv->chip->setup_port(priv, i, egress, ingress, portmask[i],
pvid);
} }
ar8xxx_set_mirror_regs(priv); ar8xxx_set_mirror_regs(priv);