ar8216: add ARL table flushing per port
authorFelix Fietkau <nbd@openwrt.org>
Wed, 15 Jul 2015 08:17:28 +0000 (08:17 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Wed, 15 Jul 2015 08:17:28 +0000 (08:17 +0000)
Adds functions for flushing ARL table entries per port.

Successfully tested on AR8327. Implementation for AR8216/AR8236/AR8316
is based on the AR8236 datasheet and assumes that the three chips
share a common ATU register layout.
Compile-tested only for AR8216/AR8236/AR8316.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
SVN-Revision: 46380

target/linux/generic/files/drivers/net/phy/ar8216.c
target/linux/generic/files/drivers/net/phy/ar8216.h
target/linux/generic/files/drivers/net/phy/ar8327.c
target/linux/generic/files/drivers/net/phy/ar8327.h

index 595f144..f4c7b8d 100644 (file)
@@ -606,6 +606,22 @@ ar8216_atu_flush(struct ar8xxx_priv *priv)
        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)
 {
@@ -1542,6 +1558,7 @@ static const struct ar8xxx_chip ar8216_chip = {
        .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,
@@ -1570,6 +1587,7 @@ static const struct ar8xxx_chip ar8236_chip = {
        .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,
@@ -1598,6 +1616,7 @@ static const struct ar8xxx_chip ar8316_chip = {
        .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,
index 934a8b5..5abbd55 100644 (file)
 #define   AR8216_ATU_OP_FLUSH          0x1
 #define   AR8216_ATU_OP_LOAD           0x2
 #define   AR8216_ATU_OP_PURGE          0x3
-#define   AR8216_ATU_OP_FLUSH_LOCKED   0x4
-#define   AR8216_ATU_OP_FLUSH_UNICAST  0x5
+#define   AR8216_ATU_OP_FLUSH_UNLOCKED 0x4
+#define   AR8216_ATU_OP_FLUSH_PORT     0x5
 #define   AR8216_ATU_OP_GET_NEXT       0x6
 #define   AR8216_ATU_ACTIVE            BIT(3)
 #define   AR8216_ATU_PORT_NUM          BITS(8, 4)
+#define   AR8216_ATU_PORT_NUM_S                8
 #define   AR8216_ATU_FULL_VIO          BIT(12)
 #define   AR8216_ATU_ADDR5             BITS(16, 8)
 #define   AR8216_ATU_ADDR5_S           16
@@ -397,6 +398,7 @@ struct ar8xxx_chip {
        u32 (*read_port_status)(struct ar8xxx_priv *priv, int port);
        u32 (*read_port_eee_status)(struct ar8xxx_priv *priv, int port);
        int (*atu_flush)(struct ar8xxx_priv *priv);
+       int (*atu_flush_port)(struct ar8xxx_priv *priv, int port);
        void (*vtu_flush)(struct ar8xxx_priv *priv);
        void (*vtu_load_vlan)(struct ar8xxx_priv *priv, u32 vid, u32 port_mask);
        void (*phy_fixup)(struct ar8xxx_priv *priv, int phy);
index a6dd7d8..fd4a262 100644 (file)
@@ -765,6 +765,24 @@ ar8327_atu_flush(struct ar8xxx_priv *priv)
        return ret;
 }
 
+static int
+ar8327_atu_flush_port(struct ar8xxx_priv *priv, int port)
+{
+       u32 t;
+       int ret;
+
+       ret = ar8216_wait_bit(priv, AR8327_REG_ATU_FUNC,
+                             AR8327_ATU_FUNC_BUSY, 0);
+       if (!ret) {
+               t = (port << AR8327_ATU_PORT_NUM_S);
+               t |= AR8327_ATU_FUNC_OP_FLUSH_PORT;
+               t |= AR8327_ATU_FUNC_BUSY;
+               ar8xxx_write(priv, AR8327_REG_ATU_FUNC, t);
+       }
+
+       return ret;
+}
+
 static void
 ar8327_vtu_op(struct ar8xxx_priv *priv, u32 op, u32 val)
 {
@@ -1189,6 +1207,7 @@ const struct ar8xxx_chip ar8327_chip = {
        .read_port_status = ar8327_read_port_status,
        .read_port_eee_status = ar8327_read_port_eee_status,
        .atu_flush = ar8327_atu_flush,
+       .atu_flush_port = ar8327_atu_flush_port,
        .vtu_flush = ar8327_vtu_flush,
        .vtu_load_vlan = ar8327_vtu_load_vlan,
        .phy_fixup = ar8327_phy_fixup,
@@ -1222,6 +1241,7 @@ const struct ar8xxx_chip ar8337_chip = {
        .read_port_status = ar8327_read_port_status,
        .read_port_eee_status = ar8327_read_port_eee_status,
        .atu_flush = ar8327_atu_flush,
+       .atu_flush_port = ar8327_atu_flush_port,
        .vtu_flush = ar8327_vtu_flush,
        .vtu_load_vlan = ar8327_vtu_load_vlan,
        .phy_fixup = ar8327_phy_fixup,
index 29eeb62..8d1fb3b 100644 (file)
 #define   AR8327_ATU_FUNC_OP_FLUSH             0x1
 #define   AR8327_ATU_FUNC_OP_LOAD              0x2
 #define   AR8327_ATU_FUNC_OP_PURGE             0x3
-#define   AR8327_ATU_FUNC_OP_FLUSH_LOCKED      0x4
-#define   AR8327_ATU_FUNC_OP_FLUSH_UNICAST     0x5
+#define   AR8327_ATU_FUNC_OP_FLUSH_UNLOCKED    0x4
+#define   AR8327_ATU_FUNC_OP_FLUSH_PORT                0x5
 #define   AR8327_ATU_FUNC_OP_GET_NEXT          0x6
 #define   AR8327_ATU_FUNC_OP_SEARCH_MAC                0x7
 #define   AR8327_ATU_FUNC_OP_CHANGE_TRUNK      0x8
+#define   AR8327_ATU_PORT_NUM                  BITS(8, 4)
+#define   AR8327_ATU_PORT_NUM_S                        8
 #define   AR8327_ATU_FUNC_BUSY                 BIT(31)
 
 #define AR8327_REG_VTU_FUNC0                   0x0610