Using this patch it's possible to define port egress/ingress bandwidth limit with 64 kbps step (this also requires enable_qos set to 1 which seems to be 1 already by default after switch reset), enable or disable any port and set vlan to different fid (0-7). Implementation of fid support maybe a bit ugly and could be done together with set_vlan_ports (which sets fid to 0 by default so after every `set ports ...` one need to `set fid ...` also) but this way it works fine too.
Signed-off-by: Roman Yeryomin <ro...@advem.lv> --
Index: target/linux/generic/files/drivers/net/phy/rtl8366rb.c =================================================================== --- a/target/linux/generic/files/drivers/net/phy/rtl8366rb.c (revision 22745) +++ b/target/linux/generic/files/drivers/net/phy/rtl8366rb.c (working copy) @@ -3,6 +3,7 @@ * * Copyright (C) 2009-2010 Gabor Juhos <juh...@openwrt.org> * Copyright (C) 2010 Antti Seppälä <a.sepp...@gmail.com> + * Copyright (C) 2010 Roman Yeryomin <ro...@advem.lv> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -163,6 +164,27 @@ #define RTL8366RB_VLAN_MEMBER_MASK 0xff #define RTL8366RB_VLAN_FID_MASK 0x7 + +/* Port ingress bandwidth control */ +#define RTL8366RB_IB_BASE 0x0200 +#define RTL8366RB_IB_REG(pnum) (RTL8366RB_IB_BASE+pnum) +#define RTL8366RB_IB_BDTH_MASK 0x3fff +#define RTL8366RB_IB_PREIFG_OFFSET 14 +#define RTL8366RB_IB_PREIFG_MASK (1 << RTL8366RB_IB_PREIFG_OFFSET) + +/* Port egress bandwidth control */ +#define RTL8366RB_EB_BASE 0x02d1 +#define RTL8366RB_EB_REG(pnum) (RTL8366RB_EB_BASE+pnum) +#define RTL8366RB_EB_BDTH_MASK 0x3fff +#define RTL8366RB_EB_PREIFG_REG 0x02f8 +#define RTL8366RB_EB_PREIFG_OFFSET 9 +#define RTL8366RB_EB_PREIFG_MASK (1 << RTL8366RB_EB_PREIFG_OFFSET) + +/* QOS */ +/* Include/Exclude Preamble and IFG(20Bytes). 0:Exclude, 1:Include. */ +#define RTL8366RB_QOS_DEFAULT_PREIFG 1 + + static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = { { 0, 0, 4, "IfInOctets" }, { 0, 4, 4, "EtherStatsOctets" }, @@ -455,6 +477,86 @@ return err; } +static int rtl8366rb_sw_get_vlan_fid(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + int err; + + if (val->port_vlan >= RTL8366RB_NUM_VIDS) + return -EINVAL; + + /* write VID */ + err = rtl8366_smi_write_reg(smi, RTL8366RB_VLAN_TABLE_WRITE_BASE, + val->port_vlan & RTL8366RB_VLAN_VID_MASK); + if (err) + return err; + + /* write table access control word */ + err = rtl8366_smi_write_reg(smi, RTL8366RB_TABLE_ACCESS_CTRL_REG, + RTL8366RB_TABLE_VLAN_READ_CTRL); + if (err) + return err; + + err = rtl8366_smi_read_reg(smi, RTL8366RB_VLAN_TABLE_READ_BASE + 2, &data); + if (err) + return err; + + val->value.i = data & RTL8366RB_VLAN_FID_MASK; + + return 0; +} + +static int rtl8366rb_sw_set_vlan_fid(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + int err; + + if (val->port_vlan >= RTL8366RB_NUM_VIDS || + val->value.i > RTL8366RB_FIDMAX) + return -EINVAL; + + /* write VID */ + err = rtl8366_smi_write_reg(smi, RTL8366RB_VLAN_TABLE_WRITE_BASE, + val->port_vlan & RTL8366RB_VLAN_VID_MASK); + if (err) + return err; + + /* write table access control word */ + err = rtl8366_smi_write_reg(smi, RTL8366RB_TABLE_ACCESS_CTRL_REG, + RTL8366RB_TABLE_VLAN_READ_CTRL); + if (err) + return err; + + err = rtl8366_smi_read_reg(smi, RTL8366RB_VLAN_TABLE_READ_BASE + 1, &data); + if (err) + return err; + + err = rtl8366_smi_write_reg(smi, RTL8366RB_VLAN_TABLE_WRITE_BASE + 1, data); + if (err) + return err; + + data = val->port_vlan & RTL8366RB_VLAN_VID_MASK; + err = rtl8366_smi_write_reg(smi, RTL8366RB_VLAN_TABLE_WRITE_BASE, data); + if (err) + return err; + data = val->value.i & RTL8366RB_VLAN_FID_MASK; + err = rtl8366_smi_write_reg(smi, RTL8366RB_VLAN_TABLE_WRITE_BASE + 2, data); + if (err) + return err; + + /* write table access control word */ + err = rtl8366_smi_write_reg(smi, RTL8366RB_TABLE_ACCESS_CTRL_REG, + RTL8366RB_TABLE_VLAN_WRITE_CTRL); + + return err; +} + static int rtl8366rb_get_vlan_mc(struct rtl8366_smi *smi, u32 index, struct rtl8366_vlan_mc *vlanmc) { @@ -748,6 +850,163 @@ return 0; } +static int rtl8366rb_sw_set_port_disable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + if (val->port_vlan >= RTL8366RB_NUM_PORTS) + return -EINVAL; + + rtl8366_smi_read_reg(smi, RTL8366RB_PECR, &data); + if (val->value.i) + data = data | (1<<val->port_vlan); + else + data = data & ~(1<<val->port_vlan); + + return rtl8366_smi_write_reg(smi, RTL8366RB_PECR, data); +} + +static int rtl8366rb_sw_get_port_disable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + if (val->port_vlan >= RTL8366RB_NUM_PORTS) + return -EINVAL; + + rtl8366_smi_read_reg(smi, RTL8366RB_PECR, &data); + if (data & (1<<val->port_vlan)) + val->value.i = 1; + else + val->value.i = 0; + + return 0; +} + +static int rtl8366rb_sw_set_port_rate_in(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + if (val->port_vlan >= RTL8366RB_NUM_PORTS) + return -EINVAL; + + if (val->value.i > 0 && val->value.i < 1048512) + val->value.i = (val->value.i - 1) / 64 ; + else + val->value.i = 16383; + + rtl8366_smi_read_reg(smi, RTL8366RB_IB_REG(val->port_vlan), &data); + + return rtl8366_smi_write_reg(smi, RTL8366RB_IB_REG(val->port_vlan), + (data & ~(RTL8366RB_IB_BDTH_MASK | RTL8366RB_IB_PREIFG_MASK)) | val->value.i | (RTL8366RB_QOS_DEFAULT_PREIFG << RTL8366RB_IB_PREIFG_OFFSET)); + +} + +static int rtl8366rb_sw_get_port_rate_in(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + if (val->port_vlan >= RTL8366RB_NUM_PORTS) + return -EINVAL; + + rtl8366_smi_read_reg(smi, RTL8366RB_IB_REG(val->port_vlan), &data); + data &= RTL8366RB_IB_BDTH_MASK; + if (data < RTL8366RB_IB_BDTH_MASK) + data += 1; + + val->value.i = (int)data * 64; + + return 0; +} + +static int rtl8366rb_sw_set_port_rate_out(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + if (val->port_vlan >= RTL8366RB_NUM_PORTS) + return -EINVAL; + + rtl8366_smi_read_reg(smi, RTL8366RB_EB_PREIFG_REG, &data); + rtl8366_smi_write_reg(smi, RTL8366RB_EB_PREIFG_REG, + (data & ~(RTL8366RB_EB_PREIFG_MASK)) | (RTL8366RB_QOS_DEFAULT_PREIFG << RTL8366RB_EB_PREIFG_OFFSET) ); + + if (val->value.i > 0 && val->value.i < 1048512) + val->value.i = (val->value.i - 1) / 64 ; + else + val->value.i = 16383; + + rtl8366_smi_read_reg(smi, RTL8366RB_EB_REG(val->port_vlan), &data); + return rtl8366_smi_write_reg(smi, RTL8366RB_EB_REG(val->port_vlan), + (data & ~(RTL8366RB_EB_BDTH_MASK)) | val->value.i ); + +} + +static int rtl8366rb_sw_get_port_rate_out(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + if (val->port_vlan >= RTL8366RB_NUM_PORTS) + return -EINVAL; + + rtl8366_smi_read_reg(smi, RTL8366RB_EB_REG(val->port_vlan), &data); + data &= RTL8366RB_EB_BDTH_MASK; + if (data < RTL8366RB_EB_BDTH_MASK) + data += 1; + + val->value.i = (int)data * 64; + + return 0; +} + +static int rtl8366rb_sw_set_qos_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + rtl8366_smi_read_reg(smi, RTL8366RB_SGCR, &data); + if (val->value.i) + data = data | (1<<15); + else + data = data & ~(1<<15); + + return rtl8366_smi_write_reg(smi, RTL8366RB_SGCR, data); +} + +static int rtl8366rb_sw_get_qos_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + rtl8366_smi_read_reg(smi, RTL8366RB_SGCR, &data); + if (data & (1<<15)) + val->value.i = 1; + else + val->value.i = 0; + + return 0; +} + static int rtl8366rb_sw_reset_port_mibs(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) @@ -814,6 +1073,13 @@ .set = rtl8366rb_sw_set_blinkrate, .get = rtl8366rb_sw_get_blinkrate, .max = 5 + }, { + .type = SWITCH_TYPE_INT, + .name = "enable_qos", + .description = "Enable QOS", + .set = rtl8366rb_sw_set_qos_enable, + .get = rtl8366rb_sw_get_qos_enable, + .max = 1 }, }; @@ -844,6 +1110,27 @@ .max = 15, .set = rtl8366rb_sw_set_port_led, .get = rtl8366rb_sw_get_port_led, + }, { + .type = SWITCH_TYPE_INT, + .name = "disable", + .description = "Get/Set port state (enabled or disabled)", + .max = 1, + .set = rtl8366rb_sw_set_port_disable, + .get = rtl8366rb_sw_get_port_disable, + }, { + .type = SWITCH_TYPE_INT, + .name = "rate_in", + .description = "Get/Set port ingress (incoming) bandwidth limit in kbps", + .max = 1048512, + .set = rtl8366rb_sw_set_port_rate_in, + .get = rtl8366rb_sw_get_port_rate_in, + }, { + .type = SWITCH_TYPE_INT, + .name = "rate_out", + .description = "Get/Set port egress (outgoing) bandwidth limit in kbps", + .max = 1048512, + .set = rtl8366rb_sw_set_port_rate_out, + .get = rtl8366rb_sw_get_port_rate_out, }, }; @@ -855,6 +1142,13 @@ .max = 1, .set = NULL, .get = rtl8366_sw_get_vlan_info, + }, { + .type = SWITCH_TYPE_INT, + .name = "fid", + .description = "Get/Set vlan fid", + .max = RTL8366RB_FIDMAX, + .set = rtl8366rb_sw_set_vlan_fid, + .get = rtl8366rb_sw_get_vlan_fid, }, }; @@ -1132,5 +1426,6 @@ MODULE_VERSION(RTL8366RB_DRIVER_VER); MODULE_AUTHOR("Gabor Juhos <juh...@openwrt.org>"); MODULE_AUTHOR("Antti Seppälä <a.sepp...@gmail.com>"); +MODULE_AUTHOR("Roman Yeryomin <ro...@advem.lv>"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" RTL8366RB_DRIVER_NAME);
_______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel