This add support for IGMP Snooping on atheros switches (disabled by default), which avoids flooding the network with multicast data.
Tested on TL-WDR4300: disabling IGMP Snooping results in multicast flooding on each specific port, enabling it back again prevents each port from receiving all multicast packets. Partially based on: http://patchwork.ozlabs.org/patch/418122/ Signed-off-by: Álvaro Fernández Rojas <nolt...@gmail.com> --- v2: introduce changes suggested by Linus Lüssing - switch to disabled by default - add MLD snooping support - allow enabling/disabling IGMP v3, join and leave - add functions for controlling settings on all ports At least igmp_snooping, igmp_fast_join and igmp_fast_leave must be enabled in order to get IGMP working. MLD Snooping and IGMP v3 are optional. .../linux/generic/files/drivers/net/phy/ar8216.h | 7 + .../linux/generic/files/drivers/net/phy/ar8327.c | 557 +++++++++++++++++++++ .../linux/generic/files/drivers/net/phy/ar8327.h | 76 +++ 3 files changed, 640 insertions(+) diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.h b/target/linux/generic/files/drivers/net/phy/ar8216.h index 14fe928..6ebfcc7 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.h +++ b/target/linux/generic/files/drivers/net/phy/ar8216.h @@ -407,6 +407,13 @@ struct ar8xxx_chip { u32 *status, enum arl_op op); int (*sw_hw_apply)(struct switch_dev *dev); + int (*get_igmp_v3)(struct ar8xxx_priv *priv); + void (*set_igmp_v3)(struct ar8xxx_priv *priv, int enable); + int (*get_port_igmp)(struct ar8xxx_priv *priv, int port); + void (*set_port_igmp)(struct ar8xxx_priv *priv, int port, int enable); + int (*get_port_cfg)(struct ar8xxx_priv *priv, int port, u32 cfg); + void (*set_port_cfg)(struct ar8xxx_priv *priv, int port, u32 cfg, int enable); + const struct ar8xxx_mib_desc *mib_decs; unsigned num_mibs; unsigned mib_func; diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.c b/target/linux/generic/files/drivers/net/phy/ar8327.c index 90ee411..c885761 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8327.c +++ b/target/linux/generic/files/drivers/net/phy/ar8327.c @@ -33,6 +33,86 @@ extern const struct ar8xxx_mib_desc ar8236_mibs[39]; extern const struct switch_attr ar8xxx_sw_attr_vlan[1]; +const struct ar8327_port_data ar8327_ports_cfg[AR8327_NUM_PORTS] = { + { + /* Port 0 */ + .reg = AR8327_REG_FRAM_ACK_CTRL0, + .igmp_mld = AR8327_IGMP_MLD_EN0, + .igmp_join = AR8327_IGMP_JOIN_EN0, + .igmp_leave = AR8327_IGMP_LEAVE_EN0, + .eapol = AR8327_EAPOL_EN0, + .dhcp = AR8327_DHCP_EN0, + .arp_ack = AR8327_ARP_ACK_EN0, + .arp_req = AR8327_ARP_REQ_EN0 + }, + { + /* Port 1 */ + .reg = AR8327_REG_FRAM_ACK_CTRL0, + .igmp_mld = AR8327_IGMP_MLD_EN1, + .igmp_join = AR8327_IGMP_JOIN_EN1, + .igmp_leave = AR8327_IGMP_LEAVE_EN1, + .eapol = AR8327_EAPOL_EN1, + .dhcp = AR8327_DHCP_EN1, + .arp_ack = AR8327_ARP_ACK_EN1, + .arp_req = AR8327_ARP_REQ_EN1 + }, + { + /* Port 2 */ + .reg = AR8327_REG_FRAM_ACK_CTRL0, + .igmp_mld = AR8327_IGMP_MLD_EN2, + .igmp_join = AR8327_IGMP_JOIN_EN2, + .igmp_leave = AR8327_IGMP_LEAVE_EN2, + .eapol = AR8327_EAPOL_EN2, + .dhcp = AR8327_DHCP_EN2, + .arp_ack = AR8327_ARP_ACK_EN2, + .arp_req = AR8327_ARP_REQ_EN2 + }, + { + /* Port 3 */ + .reg = AR8327_REG_FRAM_ACK_CTRL0, + .igmp_mld = AR8327_IGMP_MLD_EN3, + .igmp_join = AR8327_IGMP_JOIN_EN3, + .igmp_leave = AR8327_IGMP_LEAVE_EN3, + .eapol = AR8327_EAPOL_EN3, + .dhcp = AR8327_DHCP_EN3, + .arp_ack = AR8327_ARP_ACK_EN3, + .arp_req = AR8327_ARP_REQ_EN3 + }, + { + /* Port 4 */ + .reg = AR8327_REG_FRAM_ACK_CTRL1, + .igmp_mld = AR8327_IGMP_MLD_EN4, + .igmp_join = AR8327_IGMP_JOIN_EN4, + .igmp_leave = AR8327_IGMP_LEAVE_EN4, + .eapol = AR8327_EAPOL_EN4, + .dhcp = AR8327_DHCP_EN4, + .arp_ack = AR8327_ARP_ACK_EN4, + .arp_req = AR8327_ARP_REQ_EN4 + }, + { + /* Port 5 */ + .reg = AR8327_REG_FRAM_ACK_CTRL1, + .igmp_mld = AR8327_IGMP_MLD_EN5, + .igmp_join = AR8327_IGMP_JOIN_EN5, + .igmp_leave = AR8327_IGMP_LEAVE_EN5, + .eapol = AR8327_EAPOL_EN5, + .dhcp = AR8327_DHCP_EN5, + .arp_ack = AR8327_ARP_ACK_EN5, + .arp_req = AR8327_ARP_REQ_EN5 + }, + { + /* Port 6 */ + .reg = AR8327_REG_FRAM_ACK_CTRL1, + .igmp_mld = AR8327_IGMP_MLD_EN6, + .igmp_join = AR8327_IGMP_JOIN_EN6, + .igmp_leave = AR8327_IGMP_LEAVE_EN6, + .eapol = AR8327_EAPOL_EN6, + .dhcp = AR8327_DHCP_EN6, + .arp_ack = AR8327_ARP_ACK_EN6, + .arp_req = AR8327_ARP_REQ_EN6 + }, +}; + static u32 ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg) { @@ -648,6 +728,174 @@ ar8327_cleanup(struct ar8xxx_priv *priv) ar8327_leds_cleanup(priv); } +int +ar8327_sw_get_igmp_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port; + + mutex_lock(&priv->reg_mutex); + for (port = 0; port < dev->ports; port++) { + val->value.i = priv->chip->get_port_igmp(priv, port); + if (!val->value.i) + break; + } + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_igmp_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port; + + mutex_lock(&priv->reg_mutex); + for (port = 0; port < dev->ports; port++) + priv->chip->set_port_igmp(priv, port, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_get_mld_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port; + + mutex_lock(&priv->reg_mutex); + for (port = 0; port < dev->ports; port++) { + val->value.i = priv->chip->get_port_cfg(priv, port, AR8327_PORT_IGMP_MLD); + if (!val->value.i) + break; + } + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_mld_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port; + + mutex_lock(&priv->reg_mutex); + for (port = 0; port < dev->ports; port++) + priv->chip->set_port_cfg(priv, port, AR8327_PORT_IGMP_MLD, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_get_igmp_fastjoin(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port; + + mutex_lock(&priv->reg_mutex); + for (port = 0; port < dev->ports; port++) { + val->value.i = priv->chip->get_port_cfg(priv, port, AR8327_PORT_IGMP_JOIN); + if (!val->value.i) + break; + } + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_igmp_fastjoin(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port; + + mutex_lock(&priv->reg_mutex); + for (port = 0; port < dev->ports; port++) + priv->chip->set_port_cfg(priv, port, AR8327_PORT_IGMP_JOIN, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_get_igmp_fastleave(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port; + + mutex_lock(&priv->reg_mutex); + for (port = 0; port < dev->ports; port++) { + val->value.i = priv->chip->get_port_cfg(priv, port, AR8327_PORT_IGMP_LEAVE); + if (!val->value.i) + break; + } + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_igmp_fastleave(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port; + + mutex_lock(&priv->reg_mutex); + for (port = 0; port < dev->ports; port++) + priv->chip->set_port_cfg(priv, port, AR8327_PORT_IGMP_LEAVE, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_get_igmp_v3(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->chip->get_igmp_v3(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_igmp_v3(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + + mutex_lock(&priv->reg_mutex); + priv->chip->set_igmp_v3(priv, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + static void ar8327_init_globals(struct ar8xxx_priv *priv) { @@ -783,6 +1031,85 @@ ar8327_atu_flush_port(struct ar8xxx_priv *priv, int port) return ret; } +int +ar8327_get_igmp_v3(struct ar8xxx_priv *priv) +{ + u32 val = ar8xxx_read(priv, AR8327_REG_FRAM_ACK_CTRL1); + + return (val & AR8327_IGMP_V3_EN) != 0; +} + +void +ar8327_set_igmp_v3(struct ar8xxx_priv *priv, int enable) +{ + if (enable) + ar8xxx_reg_set(priv, AR8327_REG_FRAM_ACK_CTRL1, AR8327_IGMP_V3_EN); + else + ar8xxx_reg_clear(priv, AR8327_REG_FRAM_ACK_CTRL1, AR8327_IGMP_V3_EN); +} + +static int +ar8327_get_port_igmp(struct ar8xxx_priv *priv, int port) +{ + u32 val = ar8xxx_read(priv, AR8327_REG_FWD_CTRL1) >> + AR8327_FWD_CTRL1_IGMP_S; + + return (val & BIT(port)) != 0; +} + +static void +ar8327_set_port_igmp(struct ar8xxx_priv *priv, int port, int enable) +{ + if (enable) + ar8xxx_rmw(priv, AR8327_REG_FWD_CTRL1, + BIT(port) << AR8327_FWD_CTRL1_MC_FLOOD_S, + BIT(port) << AR8327_FWD_CTRL1_IGMP_S); + else + ar8xxx_rmw(priv, AR8327_REG_FWD_CTRL1, + BIT(port) << AR8327_FWD_CTRL1_IGMP_S, + BIT(port) << AR8327_FWD_CTRL1_MC_FLOOD_S); +} + +static u32 +ar8327_port_cfg_values(int port, u32 cfg_values) +{ + u32 val = 0; + + if (cfg_values & AR8327_PORT_IGMP_MLD) + val |= ar8327_ports_cfg[port].igmp_mld; + if (cfg_values & AR8327_PORT_IGMP_JOIN) + val |= ar8327_ports_cfg[port].igmp_join; + if (cfg_values & AR8327_PORT_IGMP_LEAVE) + val |= ar8327_ports_cfg[port].igmp_leave; + if (cfg_values & AR8327_PORT_EAPOL) + val |= ar8327_ports_cfg[port].eapol; + if (cfg_values & AR8327_PORT_DHCP) + val |= ar8327_ports_cfg[port].dhcp; + if (cfg_values & AR8327_PORT_ARP_ACK) + val |= ar8327_ports_cfg[port].arp_ack; + if (cfg_values & AR8327_PORT_ARP_REQ) + val |= ar8327_ports_cfg[port].arp_req; + + return val; +} + +static int +ar8327_get_port_cfg(struct ar8xxx_priv *priv, int port, u32 cfg) +{ + u32 val = ar8xxx_read(priv, ar8327_ports_cfg[port].reg); + + return (val & ar8327_port_cfg_values(port, cfg)) != 0; +} + +static void +ar8327_set_port_cfg(struct ar8xxx_priv *priv, int port, u32 cfg, int enable) +{ + if (enable) + ar8xxx_reg_set(priv, ar8327_ports_cfg[port].reg, ar8327_port_cfg_values(port, cfg)); + else + ar8xxx_reg_clear(priv, ar8327_ports_cfg[port].reg, ar8327_port_cfg_values(port, cfg)); +} + static void ar8327_vtu_op(struct ar8xxx_priv *priv, u32 op, u32 val) { @@ -1084,6 +1411,150 @@ ar8327_sw_hw_apply(struct switch_dev *dev) return 0; } +int +ar8327_sw_get_port_igmp_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port = val->port_vlan; + + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->chip->get_port_igmp(priv, port); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_port_igmp_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port = val->port_vlan; + + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->reg_mutex); + priv->chip->set_port_igmp(priv, port, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_get_port_mld_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port = val->port_vlan; + + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->chip->get_port_cfg(priv, port, AR8327_PORT_IGMP_MLD); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_port_mld_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port = val->port_vlan; + + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->reg_mutex); + priv->chip->set_port_cfg(priv, port, AR8327_PORT_IGMP_MLD, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_get_port_igmp_fastjoin(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port = val->port_vlan; + + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->chip->get_port_cfg(priv, port, AR8327_PORT_IGMP_JOIN); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_port_igmp_fastjoin(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port = val->port_vlan; + + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->reg_mutex); + priv->chip->set_port_cfg(priv, port, AR8327_PORT_IGMP_JOIN, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_get_port_igmp_fastleave(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port = val->port_vlan; + + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->chip->get_port_cfg(priv, port, AR8327_PORT_IGMP_LEAVE); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +int +ar8327_sw_set_port_igmp_fastleave(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int port = val->port_vlan; + + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->reg_mutex); + priv->chip->set_port_cfg(priv, port, AR8327_PORT_IGMP_LEAVE, val->value.i); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + static const struct switch_attr ar8327_sw_attr_globals[] = { { .type = SWITCH_TYPE_INT, @@ -1144,6 +1615,46 @@ static const struct switch_attr ar8327_sw_attr_globals[] = { .description = "Flush ARL table", .set = ar8xxx_sw_set_flush_arl_table, }, + { + .type = SWITCH_TYPE_INT, + .name = "igmp_snooping", + .description = "Enable IGMP Snooping", + .set = ar8327_sw_set_igmp_snooping, + .get = ar8327_sw_get_igmp_snooping, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "igmp_v3", + .description = "Enable IGMP V3", + .set = ar8327_sw_set_igmp_v3, + .get = ar8327_sw_get_igmp_v3, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "mld_snooping", + .description = "Enable MLD Snooping", + .set = ar8327_sw_set_mld_snooping, + .get = ar8327_sw_get_mld_snooping, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "igmp_fast_join", + .description = "Enable IGMP Fast Join", + .set = ar8327_sw_set_igmp_fastjoin, + .get = ar8327_sw_get_igmp_fastjoin, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "igmp_fast_leave", + .description = "Enable IGMP Fast Leave", + .set = ar8327_sw_set_igmp_fastleave, + .get = ar8327_sw_get_igmp_fastleave, + .max = 1 + }, }; static const struct switch_attr ar8327_sw_attr_port[] = { @@ -1174,6 +1685,38 @@ static const struct switch_attr ar8327_sw_attr_port[] = { .description = "Flush port's ARL table entries", .set = ar8xxx_sw_set_flush_port_arl_table, }, + { + .type = SWITCH_TYPE_INT, + .name = "igmp_snooping", + .description = "Enable port's IGMP Snooping", + .set = ar8327_sw_set_port_igmp_snooping, + .get = ar8327_sw_get_port_igmp_snooping, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "mld_snooping", + .description = "Enable port's MLD Snooping", + .set = ar8327_sw_set_port_mld_snooping, + .get = ar8327_sw_get_port_mld_snooping, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "igmp_fast_join", + .description = "Enable port's IGMP Fast Join", + .set = ar8327_sw_set_port_igmp_fastjoin, + .get = ar8327_sw_get_port_igmp_fastjoin, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "igmp_fast_leave", + .description = "Enable port's IGMP Fast Leave", + .set = ar8327_sw_set_port_igmp_fastjoin, + .get = ar8327_sw_get_port_igmp_fastleave, + .max = 1 + }, }; static const struct switch_dev_ops ar8327_sw_ops = { @@ -1227,6 +1770,13 @@ const struct ar8xxx_chip ar8327_chip = { .get_arl_entry = ar8327_get_arl_entry, .sw_hw_apply = ar8327_sw_hw_apply, + .get_igmp_v3 = ar8327_get_igmp_v3, + .set_igmp_v3 = ar8327_set_igmp_v3, + .get_port_igmp = ar8327_get_port_igmp, + .set_port_igmp = ar8327_set_port_igmp, + .get_port_cfg = ar8327_get_port_cfg, + .set_port_cfg = ar8327_set_port_cfg, + .num_mibs = ARRAY_SIZE(ar8236_mibs), .mib_decs = ar8236_mibs, .mib_func = AR8327_REG_MIB_FUNC @@ -1261,6 +1811,13 @@ const struct ar8xxx_chip ar8337_chip = { .get_arl_entry = ar8327_get_arl_entry, .sw_hw_apply = ar8327_sw_hw_apply, + .get_igmp_v3 = ar8327_get_igmp_v3, + .set_igmp_v3 = ar8327_set_igmp_v3, + .get_port_igmp = ar8327_get_port_igmp, + .set_port_igmp = ar8327_set_port_igmp, + .get_port_cfg = ar8327_get_port_cfg, + .set_port_cfg = ar8327_set_port_cfg, + .num_mibs = ARRAY_SIZE(ar8236_mibs), .mib_decs = ar8236_mibs, .mib_func = AR8327_REG_MIB_FUNC diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.h b/target/linux/generic/files/drivers/net/phy/ar8327.h index 8d1fb3b..340ec82 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8327.h +++ b/target/linux/generic/files/drivers/net/phy/ar8327.h @@ -98,6 +98,61 @@ #define AR8327_REG_EEE_CTRL 0x100 #define AR8327_EEE_CTRL_DISABLE_PHY(_i) BIT(4 + (_i) * 2) +#define AR8327_REG_FRAM_ACK_CTRL0 0x210 +#define AR8327_IGMP_MLD_EN0 BIT(0) +#define AR8327_IGMP_JOIN_EN0 BIT(1) +#define AR8327_IGMP_LEAVE_EN0 BIT(2) +#define AR8327_EAPOL_EN0 BIT(3) +#define AR8327_DHCP_EN0 BIT(4) +#define AR8327_ARP_ACK_EN0 BIT(5) +#define AR8327_ARP_REQ_EN0 BIT(6) +#define AR8327_IGMP_MLD_EN1 BIT(8) +#define AR8327_IGMP_JOIN_EN1 BIT(9) +#define AR8327_IGMP_LEAVE_EN1 BIT(10) +#define AR8327_EAPOL_EN1 BIT(11) +#define AR8327_DHCP_EN1 BIT(12) +#define AR8327_ARP_ACK_EN1 BIT(13) +#define AR8327_ARP_REQ_EN1 BIT(14) +#define AR8327_IGMP_MLD_EN2 BIT(16) +#define AR8327_IGMP_JOIN_EN2 BIT(17) +#define AR8327_IGMP_LEAVE_EN2 BIT(18) +#define AR8327_EAPOL_EN2 BIT(19) +#define AR8327_DHCP_EN2 BIT(20) +#define AR8327_ARP_ACK_EN2 BIT(21) +#define AR8327_ARP_REQ_EN2 BIT(22) +#define AR8327_IGMP_MLD_EN3 BIT(24) +#define AR8327_IGMP_JOIN_EN3 BIT(25) +#define AR8327_IGMP_LEAVE_EN3 BIT(26) +#define AR8327_EAPOL_EN3 BIT(27) +#define AR8327_DHCP_EN3 BIT(28) +#define AR8327_ARP_ACK_EN3 BIT(29) +#define AR8327_ARP_REQ_EN3 BIT(30) + +#define AR8327_REG_FRAM_ACK_CTRL1 0x214 +#define AR8327_IGMP_MLD_EN4 BIT(0) +#define AR8327_IGMP_JOIN_EN4 BIT(1) +#define AR8327_IGMP_LEAVE_EN4 BIT(2) +#define AR8327_EAPOL_EN4 BIT(3) +#define AR8327_DHCP_EN4 BIT(4) +#define AR8327_ARP_ACK_EN4 BIT(5) +#define AR8327_ARP_REQ_EN4 BIT(6) +#define AR8327_IGMP_MLD_EN5 BIT(8) +#define AR8327_IGMP_JOIN_EN5 BIT(9) +#define AR8327_IGMP_LEAVE_EN5 BIT(10) +#define AR8327_EAPOL_EN5 BIT(11) +#define AR8327_DHCP_EN5 BIT(12) +#define AR8327_ARP_ACK_EN5 BIT(13) +#define AR8327_ARP_REQ_EN5 BIT(14) +#define AR8327_IGMP_MLD_EN6 BIT(16) +#define AR8327_IGMP_JOIN_EN6 BIT(17) +#define AR8327_IGMP_LEAVE_EN6 BIT(18) +#define AR8327_EAPOL_EN6 BIT(19) +#define AR8327_DHCP_EN6 BIT(20) +#define AR8327_ARP_ACK_EN6 BIT(21) +#define AR8327_ARP_REQ_EN6 BIT(22) +#define AR8327_IGMP_V3_EN BIT(24) +#define AR8327_PPPOE_EN BIT(25) + #define AR8327_REG_PORT_VLAN0(_i) (0x420 + (_i) * 0x8) #define AR8327_PORT_VLAN0_DEF_SVID BITS(0, 12) #define AR8327_PORT_VLAN0_DEF_SVID_S 0 @@ -217,6 +272,16 @@ enum ar8327_led_pattern { AR8327_LED_PATTERN_RULE, }; +enum ar8327_port_vals { + AR8327_PORT_IGMP_MLD = BIT(0), + AR8327_PORT_IGMP_JOIN = BIT(1), + AR8327_PORT_IGMP_LEAVE = BIT(2), + AR8327_PORT_EAPOL = BIT(3), + AR8327_PORT_DHCP = BIT(4), + AR8327_PORT_ARP_ACK = BIT(5), + AR8327_PORT_ARP_REQ = BIT(6) +}; + struct ar8327_led_entry { unsigned reg; unsigned shift; @@ -249,4 +314,15 @@ struct ar8327_data { bool eee[AR8XXX_NUM_PHYS]; }; +struct ar8327_port_data { + int reg; + u32 igmp_mld; + u32 igmp_join; + u32 igmp_leave; + u32 eapol; + u32 dhcp; + u32 arp_ack; + u32 arp_req; +}; + #endif -- 1.9.1 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel