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

Reply via email to