return ret;
}
+static int
+ar8216_atu_flush_port(struct ar8xxx_priv *priv, int port)
+{
+ u32 t;
+ int ret;
+
+ ret = ar8216_wait_bit(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_ACTIVE, 0);
+ if (!ret) {
+ t = (port << AR8216_ATU_PORT_NUM_S) | AR8216_ATU_OP_FLUSH_PORT;
+ t |= AR8216_ATU_ACTIVE;
+ ar8xxx_write(priv, AR8216_REG_ATU_FUNC0, t);
+ }
+
+ return ret;
+}
+
static u32
ar8216_read_port_status(struct ar8xxx_priv *priv, int port)
{
return 0;
}
+int
+ar8xxx_sw_set_flush_arl_table(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
+ int ret;
+
+ mutex_lock(&priv->reg_mutex);
+ ret = priv->chip->atu_flush(priv);
+ mutex_unlock(&priv->reg_mutex);
+
+ return ret;
+}
+
+int
+ar8xxx_sw_set_flush_port_arl_table(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
+ int port, ret;
+
+ port = val->port_vlan;
+ if (port >= dev->ports)
+ return -EINVAL;
+
+ mutex_lock(&priv->reg_mutex);
+ ret = priv->chip->atu_flush_port(priv, port);
+ mutex_unlock(&priv->reg_mutex);
+
+ return ret;
+}
+
static const struct switch_attr ar8xxx_sw_attr_globals[] = {
{
.type = SWITCH_TYPE_INT,
.set = NULL,
.get = ar8xxx_sw_get_arl_table,
},
+ {
+ .type = SWITCH_TYPE_NOVAL,
+ .name = "flush_arl_table",
+ .description = "Flush ARL table",
+ .set = ar8xxx_sw_set_flush_arl_table,
+ },
};
-const struct switch_attr ar8xxx_sw_attr_port[2] = {
+const struct switch_attr ar8xxx_sw_attr_port[] = {
{
.type = SWITCH_TYPE_NOVAL,
.name = "reset_mib",
.set = NULL,
.get = ar8xxx_sw_get_port_mib,
},
+ {
+ .type = SWITCH_TYPE_NOVAL,
+ .name = "flush_arl_table",
+ .description = "Flush port's ARL table entries",
+ .set = ar8xxx_sw_set_flush_port_arl_table,
+ },
};
const struct switch_attr ar8xxx_sw_attr_vlan[1] = {
.setup_port = ar8216_setup_port,
.read_port_status = ar8216_read_port_status,
.atu_flush = ar8216_atu_flush,
+ .atu_flush_port = ar8216_atu_flush_port,
.vtu_flush = ar8216_vtu_flush,
.vtu_load_vlan = ar8216_vtu_load_vlan,
.set_mirror_regs = ar8216_set_mirror_regs,
.setup_port = ar8236_setup_port,
.read_port_status = ar8216_read_port_status,
.atu_flush = ar8216_atu_flush,
+ .atu_flush_port = ar8216_atu_flush_port,
.vtu_flush = ar8216_vtu_flush,
.vtu_load_vlan = ar8216_vtu_load_vlan,
.set_mirror_regs = ar8216_set_mirror_regs,
.setup_port = ar8216_setup_port,
.read_port_status = ar8216_read_port_status,
.atu_flush = ar8216_atu_flush,
+ .atu_flush_port = ar8216_atu_flush_port,
.vtu_flush = ar8216_vtu_flush,
.vtu_load_vlan = ar8216_vtu_load_vlan,
.set_mirror_regs = ar8216_set_mirror_regs,
priv->link_up[i] = link_new;
changed = true;
+ /* flush ARL entries for this port if it went down*/
+ if (!link_new)
+ priv->chip->atu_flush_port(priv, i);
dev_info(&priv->phy->dev, "Port %d is %s\n",
i, link_new ? "up" : "down");
}
- if (changed)
- priv->chip->atu_flush(priv);
-
mutex_unlock(&priv->reg_mutex);
return changed;
struct ar8xxx_priv *priv = phydev->priv;
struct switch_port_link link;
- /* check for link changes and flush ATU
- * if a change was detected
- */
+ /* check for switch port link changes */
if (phydev->state == PHY_CHANGELINK)
ar8xxx_check_link_states(priv);