The GPL sources for Belkin F5D8235 contain a driver for the rtl8366rb
switch that exposes many interesting features, like maximum packet length
setting, port bandwidth control, port priority, QoS, storm control and more.
It would be nice if these controls were available in swcontrol.
The sources can be downloaded at:
https://www.belkin.com/support/opensource/files/F5D8235v2-2.01.07-GPL.tar.gz
The driver is at:
Belkin_F5D8235-4_v2000_v2.01.07/Uboot_SDK_3200/drivers/rtl8366RB/
in the archive

This patch implements jumbo frame control, port bandwidth limitation and
port priority.

Signed-off-by: Luca Niccoli <[email protected]>

Index: target/linux/generic/files/drivers/net/phy/rtl8366rb.c
===================================================================
--- target/linux/generic/files/drivers/net/phy/rtl8366rb.c      (revisione 
23125)
+++ target/linux/generic/files/drivers/net/phy/rtl8366rb.c      (copia locale)
@@ -1,8 +1,9 @@
 /*
- * Platform driver for the Realtek RTL8366S ethernet switch
+ * Platform driver for the Realtek RTL8366RB ethernet switch
  *
  * Copyright (C) 2009-2010 Gabor Juhos <[email protected]>
  * Copyright (C) 2010 Antti Seppälä <[email protected]>
+ * Copyright (C) 2010 Luca Niccoli <[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
@@ -117,7 +118,27 @@
 #define RTL8366RB_PORT_STATUS_RXPAUSE_MASK     0x0040
 #define RTL8366RB_PORT_STATUS_AN_MASK          0x0080
 
+/* Port bandwidth control registers and Inter Frame Gap registers */
+#define RTL8366RB_IN_BANDWIDTH_BASE            0x0200
+#define RTL8366RB_IN_BANDWIDTH_REG(_p)         (RTL8366RB_IN_BANDWIDTH_BASE+_p)
+#define RTL8366RB_IN_BANDWIDTH_MASK            0x3fff
+#define RTL8366RB_IN_PREIFG_BASE               0x0200
+#define RTL8366RB_IN_PREIFG_OFFSET             14
+#define RTL8366RB_IN_PREIFG_MASK               (0x1 << 
RTL8366RB_IN_PREIFG_OFFSET)
+#define RTL8366RB_EG_BANDWIDTH_BASE            0x02D1
+#define RTL8366RB_EG_BANDWIDTH_REG(_p)         (RTL8366RB_EG_BANDWIDTH_BASE+_p)
+#define RTL8366RB_EG_BANDWIDTH_MASK            0x3fff
+#define RTL8366RB_EG_PREIFG_BASE               0x02F8
+#define RTL8366RB_EG_PREIFG_OFFSET             9
+#define RTL8366RB_EG_PREIFG_MASK               (0x1 << 
RTL8366RB_EG_PREIFG_OFFSET)
 
+
+/* Port-based priority register */
+#define RTL8366RB_PORT_PRIORITY_BASE           0x020C
+#define RTL8366RB_PORT_PRIORITY_BITS           3
+#define RTL8366RB_PORT_PRIORITY_MASK           0x7
+
+
 #define RTL8366RB_PORT_NUM_CPU         5
 #define RTL8366RB_NUM_PORTS            6
 #define RTL8366RB_NUM_VLANS            16
@@ -650,7 +671,49 @@
        return 0;
 }
 
+static int rtl8366rb_sw_get_max_length(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);
+
+       val->value.i = ((data & (RTL8366RB_SGCR_MAX_LENGTH_MASK)) >> 4);
+
+       return 0;
+}
+
+static int rtl8366rb_sw_set_max_length(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+       char length_code;
+ 
+       switch (val->value.i) {
+               case 0:
+                       length_code = RTL8366RB_SGCR_MAX_LENGTH_1522;
+                       break;
+               case 1:
+                       length_code = RTL8366RB_SGCR_MAX_LENGTH_1536;
+                       break;
+               case 2:
+                       length_code = RTL8366RB_SGCR_MAX_LENGTH_1552;
+                       break;
+               case 3:
+                       length_code = RTL8366RB_SGCR_MAX_LENGTH_9216;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+       return rtl8366_smi_rmwr(smi, RTL8366RB_SGCR,
+                               RTL8366RB_SGCR_MAX_LENGTH_MASK,
+                               length_code);
+}
+
+
 static const char *rtl8366rb_speed_str(unsigned speed)
 {
        switch (speed) {
@@ -748,6 +811,139 @@
        return 0;
 }
 
+static int rtl8366rb_sw_set_port_ib(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 || val->value.i > attr->max)
+               return -EINVAL;
+
+       if (val->value.i == 0)
+               data = 0x3FFF;
+       else
+               data = ( val->value.i - 1);
+
+       return rtl8366_smi_rmwr(smi, RTL8366RB_IN_BANDWIDTH_REG(val->port_vlan),
+                               RTL8366RB_IN_BANDWIDTH_MASK, data);
+}
+
+static int rtl8366rb_sw_get_port_ib(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+       u32 data = 0;
+       
+       if (val->port_vlan >= RTL8366RB_NUM_PORTS)
+               return -EINVAL;
+
+       rtl8366_smi_read_reg(smi, RTL8366RB_IN_BANDWIDTH_REG(val->port_vlan), 
&data);
+       data = data & RTL8366RB_IN_BANDWIDTH_MASK;
+       if (data == 0x3FFF)
+               val->value.i = 0;
+       else
+               val->value.i = data + 1;
+
+       return 0;
+}
+
+static int rtl8366rb_sw_set_port_eb(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 || val->value.i > attr->max)
+               return -EINVAL;
+
+       if (val->value.i == 0)
+               data = 0x3FFF;
+       else
+               data = ( val->value.i - 1);
+
+       return rtl8366_smi_rmwr(smi, RTL8366RB_EG_BANDWIDTH_REG(val->port_vlan),
+                               RTL8366RB_EG_BANDWIDTH_MASK, data);
+}
+
+static int rtl8366rb_sw_get_port_eb(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+       u32 data = 0;
+       
+       if (val->port_vlan >= RTL8366RB_NUM_PORTS)
+               return -EINVAL;
+
+       rtl8366_smi_read_reg(smi, RTL8366RB_EG_BANDWIDTH_REG(val->port_vlan), 
&data);
+       data = data & RTL8366RB_EG_BANDWIDTH_MASK;
+       if (data == 0x3FFF)
+               val->value.i = 0;
+       else
+               val->value.i = data + 1;
+
+       return 0;
+}
+
+static int rtl8366rb_sw_set_port_pri(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+       u32 mask;
+       u32 reg;
+       u32 data;
+
+       if (val->port_vlan >= RTL8366RB_NUM_PORTS || val->value.i > attr->max)
+               return -EINVAL;
+
+       if (val->port_vlan < 5) {
+               mask = RTL8366RB_PORT_PRIORITY_MASK <<
+                               (RTL8366RB_PORT_PRIORITY_BITS * val->port_vlan);
+               reg = RTL8366RB_PORT_PRIORITY_BASE;
+               data = val->value.i <<
+                               (RTL8366RB_PORT_PRIORITY_BITS * val->port_vlan);
+       } else {
+               mask = RTL8366RB_PORT_PRIORITY_MASK;
+               reg = RTL8366RB_PORT_PRIORITY_BASE + 1;
+               data = val->value.i;
+       }
+
+       return rtl8366_smi_rmwr(smi, reg, mask, data);
+}
+
+static int rtl8366rb_sw_get_port_pri(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+       u32 reg;
+       u32 shift;
+       u32 data = 0;
+
+       if (val->port_vlan >= RTL8366RB_NUM_PORTS)
+               return -EINVAL;
+
+       if (val->port_vlan < 5) {
+               reg = RTL8366RB_PORT_PRIORITY_BASE;
+               shift = RTL8366RB_PORT_PRIORITY_BITS * val->port_vlan;
+
+       } else {
+               reg = RTL8366RB_PORT_PRIORITY_BASE + 1;
+               shift = 0;
+       }
+
+       rtl8366_smi_read_reg(smi, reg, &data);
+
+       val->value.i = ((data >> shift) & RTL8366RB_PORT_PRIORITY_MASK);
+
+       return 0;
+}
+
 static int rtl8366rb_sw_reset_port_mibs(struct switch_dev *dev,
                                       const struct switch_attr *attr,
                                       struct switch_val *val)
@@ -814,6 +1010,14 @@
                .set = rtl8366rb_sw_set_blinkrate,
                .get = rtl8366rb_sw_get_blinkrate,
                .max = 5
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "max_length",
+               .description = "Get/Set the maximum length of valid packets"
+               " (0 = 1522, 1 = 1536, 2 = 1552, 3 = 9216)",
+               .set = rtl8366rb_sw_set_max_length,
+               .get = rtl8366rb_sw_get_max_length,
+               .max = 3,
        },
 };
 
@@ -844,6 +1048,29 @@
                .max = 15,
                .set = rtl8366rb_sw_set_port_led,
                .get = rtl8366rb_sw_get_port_led,
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "bandwidth_in",
+               .description = "Get/Set port ingress bandwidth "
+               "(bandwidth = n*64Kbps, 0 = disable bandwitdh control)",
+               .set = rtl8366rb_sw_set_port_ib,
+               .get = rtl8366rb_sw_get_port_ib,
+               .max = 16383
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "bandwidth_eg",
+               .description = "Get/Set port egress bandwidth "
+               "(bandwidth = n*64Kbps, 0 = disable bandwitdh control)",
+               .set = rtl8366rb_sw_set_port_eb,
+               .get = rtl8366rb_sw_get_port_eb,
+               .max = 16383
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "priority",
+               .description = "Get/Set port priority (0-7)",
+               .set = rtl8366rb_sw_set_port_pri,
+               .get = rtl8366rb_sw_get_port_pri,
+               .max = 7
        },
 };
 
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to