2010.08.26. 1:17 keltezéssel, Roman Yeryomin írta:
> 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 <[email protected]>
> --
>
> 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 <[email protected]>
> * Copyright (C) 2010 Antti Seppälä <[email protected]>
> + * Copyright (C) 2010 Roman Yeryomin <[email protected]>
> *
> * 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)
Please add spaces around the '+' in these macros.
> +#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;
You don't have to duplicate the VLAN access code, you can use the get_vlan_4k()
function of smi->ops instead. Additionally, if you would use that, then this
function would be generic, and should go into rtl8366_smi.c.
> +}
> +
> +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;
This function should be generic as well. Please move it to rtl8366_smi.c, get
the current VLAN configuration via 'smi->ops->get_vlan_4k', then update it with
'rtl8366_set_vlan'.
> +}
> +
> 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);
Please add spaces around the '<<' operators everywhere in the patch.
> +
> + return rtl8366_smi_write_reg(smi, RTL8366RB_PECR, data);
You should use 'rtl8366_smi_rmwr()' her.
> +}
> +
> +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));
You should use 'rtl8366_smi_rmwr()' here too. And please don't use lines longer
than 80 characters.
> +
> +}
> +
> +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) );
Same as above.
> +
> + 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
> );
Use 'rtl8366_smi_rmwr()' here as well.
> +
> +}
> +
> +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);
Ditto.
> +}
> +
> +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 <[email protected]>");
> MODULE_AUTHOR("Antti Seppälä <[email protected]>");
> +MODULE_AUTHOR("Roman Yeryomin <[email protected]>");
> MODULE_LICENSE("GPL v2");
> MODULE_ALIAS("platform:" RTL8366RB_DRIVER_NAME);
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel