generic: rtl8366: prevent modifications of VLAN 0
[openwrt.git] / target / linux / generic-2.6 / files / drivers / net / phy / rtl8366s.c
index 833e455..c8e7dd6 100644 (file)
@@ -26,7 +26,7 @@
 #endif
 
 #define RTL8366S_DRIVER_DESC   "Realtek RTL8366S ethernet switch driver"
-#define RTL8366S_DRIVER_VER    "0.2.0"
+#define RTL8366S_DRIVER_VER    "0.2.1"
 
 #define RTL8366S_PHY_NO_MAX                 4
 #define RTL8366S_PHY_PAGE_MAX               7
@@ -230,6 +230,31 @@ static inline struct rtl8366s *sw_to_rtl8366s(struct switch_dev *sw)
        return container_of(sw, struct rtl8366s, dev);
 }
 
+static int rtl8366s_reset_chip(struct rtl8366s *rtl)
+{
+       struct rtl8366_smi *smi = &rtl->smi;
+       int timeout = 10;
+       u32 data;
+
+       rtl8366_smi_write_reg(smi, RTL8366_RESET_CTRL_REG,
+                             RTL8366_CHIP_CTRL_RESET_HW);
+       do {
+               msleep(1);
+               if (rtl8366_smi_read_reg(smi, RTL8366_RESET_CTRL_REG, &data))
+                       return -EIO;
+
+               if (!(data & RTL8366_CHIP_CTRL_RESET_HW))
+                       break;
+       } while (--timeout);
+
+       if (!timeout) {
+               printk("Timeout waiting for the switch to reset\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static int rtl8366s_read_phy_reg(struct rtl8366s *rtl,
                                 u32 phy_no, u32 page, u32 addr, u32 *data)
 {
@@ -1093,7 +1118,7 @@ static int rtl8366s_sw_get_vlan_info(struct switch_dev *dev,
        struct rtl8366s *rtl = sw_to_rtl8366s(dev);
        char *buf = rtl->buf;
 
-       if (val->port_vlan >= RTL8366_NUM_VLANS)
+       if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS)
                return -EINVAL;
 
        memset(buf, '\0', sizeof(rtl->buf));
@@ -1232,7 +1257,7 @@ static int rtl8366s_sw_get_vlan_ports(struct switch_dev *dev,
        struct switch_port *port;
        int i;
 
-       if (val->port_vlan >= RTL8366_NUM_VLANS)
+       if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS)
                return -EINVAL;
 
        rtl8366s_get_vlan_member_config(rtl, val->port_vlan, &vlanmc);
@@ -1261,7 +1286,7 @@ static int rtl8366s_sw_set_vlan_ports(struct switch_dev *dev,
        struct switch_port *port;
        int i;
 
-       if (val->port_vlan >= RTL8366_NUM_VLANS)
+       if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS)
                return -EINVAL;
 
        rtl8366s_get_vlan_member_config(rtl, val->port_vlan, &vlanmc);
@@ -1301,25 +1326,11 @@ static int rtl8366s_sw_set_port_pvid(struct switch_dev *dev, int port, int val)
 static int rtl8366s_sw_reset_switch(struct switch_dev *dev)
 {
        struct rtl8366s *rtl = sw_to_rtl8366s(dev);
-       struct rtl8366_smi *smi = &rtl->smi;
-       int timeout = 10;
-       u32 data;
-
-       rtl8366_smi_write_reg(smi, RTL8366_RESET_CTRL_REG,
-                             RTL8366_CHIP_CTRL_RESET_HW);
-       do {
-               msleep(1);
-               if (rtl8366_smi_read_reg(smi, RTL8366_RESET_CTRL_REG, &data))
-                       return -EIO;
-
-               if (!(data & RTL8366_CHIP_CTRL_RESET_HW))
-                       break;
-       } while (--timeout);
+       int err;
 
-       if (!timeout) {
-               printk("Timeout waiting for the switch to reset\n");
-               return -EIO;
-       }
+       err = rtl8366s_reset_chip(rtl);
+       if (err)
+               return err;
 
        return rtl8366s_reset_vlan(rtl);
 }
@@ -1553,8 +1564,11 @@ static int rtl8366s_setup(struct rtl8366s *rtl)
        dev_info(rtl->parent, "RTL%04x ver. %u chip found\n",
                 chip_id, chip_ver & RTL8366S_CHIP_VERSION_MASK);
 
-       rtl8366s_debugfs_init(rtl);
+       ret = rtl8366s_reset_chip(rtl);
+       if (ret)
+               return ret;
 
+       rtl8366s_debugfs_init(rtl);
        return 0;
 }
 
This page took 0.026083 seconds and 4 git commands to generate.