X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/f816719c99d7d833944acfd073d8001cd6405175..dd5918a57f41eb33dfa38cfb5ec03377d813af7c:/target/linux/generic-2.6/files/drivers/net/phy/rtl8366s.c?ds=sidebyside diff --git a/target/linux/generic-2.6/files/drivers/net/phy/rtl8366s.c b/target/linux/generic-2.6/files/drivers/net/phy/rtl8366s.c index 86c637f10..da8fe556c 100644 --- a/target/linux/generic-2.6/files/drivers/net/phy/rtl8366s.c +++ b/target/linux/generic-2.6/files/drivers/net/phy/rtl8366s.c @@ -34,6 +34,25 @@ #define RTL8366_CHIP_GLOBAL_CTRL_REG 0x0000 #define RTL8366_CHIP_CTRL_VLAN (1 << 13) +/* Switch Global Configuration register */ +#define RTL8366_SGCR 0x0000 +#define RTL8366_SGCR_EN_BC_STORM_CTRL BIT(0) +#define RTL8366_SGCR_MAX_LENGTH(_x) (_x << 4) +#define RTL8366_SGCR_MAX_LENGTH_MASK RTL8366_SGCR_MAX_LENGTH(0x3) +#define RTL8366_SGCR_MAX_LENGTH_1522 RTL8366_SGCR_MAX_LENGTH(0x0) +#define RTL8366_SGCR_MAX_LENGTH_1536 RTL8366_SGCR_MAX_LENGTH(0x1) +#define RTL8366_SGCR_MAX_LENGTH_1552 RTL8366_SGCR_MAX_LENGTH(0x2) +#define RTL8366_SGCR_MAX_LENGTH_16000 RTL8366_SGCR_MAX_LENGTH(0x3) + +/* Port Enable Control register */ +#define RTL8366_PECR 0x0001 + +/* Switch Security Control registers */ +#define RTL8366_SSCR0 0x0002 +#define RTL8366_SSCR1 0x0003 +#define RTL8366_SSCR2 0x0004 +#define RTL8366_SSCR2_DROP_UNKNOWN_DA BIT(0) + #define RTL8366_RESET_CTRL_REG 0x0100 #define RTL8366_CHIP_CTRL_RESET_HW 1 #define RTL8366_CHIP_CTRL_RESET_SW (1 << 1) @@ -230,6 +249,20 @@ static struct mib_counter rtl8366s_mib_counters[RTL8366S_MIB_COUNT] = { { 1, 6, 2, "IfOutBroadcastPkts" }, }; +#define REG_WR(_smi, _reg, _val) \ + do { \ + err = rtl8366_smi_write_reg(_smi, _reg, _val); \ + if (err) \ + return err; \ + } while (0) + +#define REG_RMW(_smi, _reg, _mask, _val) \ + do { \ + err = rtl8366_smi_rmwr(_smi, _reg, _mask, _val); \ + if (err) \ + return err; \ + } while (0) + static inline struct rtl8366s *smi_to_rtl8366s(struct rtl8366_smi *smi) { return container_of(smi, struct rtl8366s, smi); @@ -270,6 +303,29 @@ static int rtl8366s_reset_chip(struct rtl8366_smi *smi) return 0; } +static int rtl8366s_hw_init(struct rtl8366_smi *smi) +{ + int err; + + /* set maximum packet length to 1536 bytes */ + REG_RMW(smi, RTL8366_SGCR, RTL8366_SGCR_MAX_LENGTH_MASK, + RTL8366_SGCR_MAX_LENGTH_1536); + + /* enable all ports */ + REG_WR(smi, RTL8366_PECR, 0); + + /* disable learning for all ports */ + REG_WR(smi, RTL8366_SSCR0, RTL8366_PORT_ALL); + + /* disable auto ageing for all ports */ + REG_WR(smi, RTL8366_SSCR1, RTL8366_PORT_ALL); + + /* don't drop packets whose DA has not been learned */ + REG_RMW(smi, RTL8366_SSCR2, RTL8366_SSCR2_DROP_UNKNOWN_DA, 0); + + return 0; +} + static int rtl8366s_read_phy_reg(struct rtl8366_smi *smi, u32 phy_no, u32 page, u32 addr, u32 *data) { @@ -574,8 +630,7 @@ static int rtl8366s_set_vlan_mc(struct rtl8366_smi *smi, u32 index, return 0; } -static int rtl8366s_get_port_vlan_index(struct rtl8366_smi *smi, int port, - int *val) +static int rtl8366s_get_mc_index(struct rtl8366_smi *smi, int port, int *val) { u32 data; int err; @@ -592,17 +647,68 @@ static int rtl8366s_get_port_vlan_index(struct rtl8366_smi *smi, int port, RTL8366S_PORT_VLAN_CTRL_MASK; return 0; +} +static int rtl8366s_set_mc_index(struct rtl8366_smi *smi, int port, int index) +{ + if (port >= RTL8366_NUM_PORTS || index >= RTL8366_NUM_VLANS) + return -EINVAL; + + return rtl8366_smi_rmwr(smi, RTL8366S_PORT_VLAN_CTRL_REG(port), + RTL8366S_PORT_VLAN_CTRL_MASK << + RTL8366S_PORT_VLAN_CTRL_SHIFT(port), + (index & RTL8366S_PORT_VLAN_CTRL_MASK) << + RTL8366S_PORT_VLAN_CTRL_SHIFT(port)); } -static int rtl8366s_get_vlan_port_pvid(struct rtl8366_smi *smi, int port, - int *val) +static int rtl8366s_set_vlan(struct rtl8366_smi *smi, int vid, u32 member, + u32 untag, u32 fid) +{ + struct rtl8366_vlan_4k vlan4k; + int err; + int i; + + /* Update the 4K table */ + err = rtl8366s_get_vlan_4k(smi, vid, &vlan4k); + if (err) + return err; + + vlan4k.member = member; + vlan4k.untag = untag; + vlan4k.fid = fid; + err = rtl8366s_set_vlan_4k(smi, &vlan4k); + if (err) + return err; + + /* Try to find an existing MC entry for this VID */ + for (i = 0; i < RTL8366_NUM_VLANS; i++) { + struct rtl8366_vlan_mc vlanmc; + + err = rtl8366s_get_vlan_mc(smi, i, &vlanmc); + if (err) + return err; + + if (vid == vlanmc.vid) { + /* update the MC entry */ + vlanmc.member = member; + vlanmc.untag = untag; + vlanmc.fid = fid; + + err = rtl8366s_set_vlan_mc(smi, i, &vlanmc); + break; + } + } + + return err; +} + +static int rtl8366s_get_pvid(struct rtl8366_smi *smi, int port, int *val) { struct rtl8366_vlan_mc vlanmc; int err; int index; - err = rtl8366s_get_port_vlan_index(smi, port, &index); + err = rtl8366s_get_mc_index(smi, port, &index); if (err) return err; @@ -614,134 +720,131 @@ static int rtl8366s_get_vlan_port_pvid(struct rtl8366_smi *smi, int port, return 0; } -static int rtl8366s_set_port_vlan_index(struct rtl8366_smi *smi, int port, - int index) +static int rtl8366s_mc_is_used(struct rtl8366_smi *smi, int mc_index, + int *used) { - u32 data; int err; + int i; - if (port >= RTL8366_NUM_PORTS || index >= RTL8366_NUM_VLANS) - return -EINVAL; + *used = 0; + for (i = 0; i < RTL8366_NUM_PORTS; i++) { + int index = 0; - err = rtl8366_smi_read_reg(smi, RTL8366S_PORT_VLAN_CTRL_REG(port), - &data); - if (err) - return err; + err = rtl8366s_get_mc_index(smi, i, &index); + if (err) + return err; - data &= ~(RTL8366S_PORT_VLAN_CTRL_MASK << - RTL8366S_PORT_VLAN_CTRL_SHIFT(port)); - data |= (index & RTL8366S_PORT_VLAN_CTRL_MASK) << - RTL8366S_PORT_VLAN_CTRL_SHIFT(port); + if (mc_index == index) { + *used = 1; + break; + } + } - err = rtl8366_smi_write_reg(smi, RTL8366S_PORT_VLAN_CTRL_REG(port), - data); - return err; + return 0; } -static int rtl8366s_set_vlan_port_pvid(struct rtl8366_smi *smi, int port, int val) +static int rtl8366s_set_pvid(struct rtl8366_smi *smi, unsigned port, + unsigned vid) { - int i; struct rtl8366_vlan_mc vlanmc; struct rtl8366_vlan_4k vlan4k; + int err; + int i; - if (port >= RTL8366_NUM_PORTS || val >= RTL8366_NUM_VIDS) - return -EINVAL; - - /* Updating the 4K entry; lookup it and change the port member set */ - rtl8366s_get_vlan_4k(smi, val, &vlan4k); - vlan4k.member |= ((1 << port) | RTL8366_PORT_CPU); - vlan4k.untag = RTL8366_PORT_ALL_BUT_CPU; - rtl8366s_set_vlan_4k(smi, &vlan4k); - - /* - * For the 16 entries more work needs to be done. First see if such - * VID is already there and change it - */ - for (i = 0; i < RTL8366_NUM_VLANS; ++i) { - rtl8366s_get_vlan_mc(smi, i, &vlanmc); - - /* Try to find an existing vid and update port member set */ - if (val == vlanmc.vid) { - vlanmc.member |= ((1 << port) | RTL8366_PORT_CPU); - rtl8366s_set_vlan_mc(smi, i, &vlanmc); + /* Try to find an existing MC entry for this VID */ + for (i = 0; i < RTL8366_NUM_VLANS; i++) { + err = rtl8366s_get_vlan_mc(smi, i, &vlanmc); + if (err) + return err; - /* Now update PVID register settings */ - rtl8366s_set_port_vlan_index(smi, port, i); + if (vid == vlanmc.vid) { + err = rtl8366s_set_vlan_mc(smi, i, &vlanmc); + if (err) + return err; - return 0; + err = rtl8366s_set_mc_index(smi, port, i); + return err; } } - /* - * PVID could not be found from vlan table. Replace unused (one that - * has no member ports) with new one - */ - for (i = 0; i < RTL8366_NUM_VLANS; ++i) { - rtl8366s_get_vlan_mc(smi, i, &vlanmc); + /* We have no MC entry for this VID, try to find an empty one */ + for (i = 0; i < RTL8366_NUM_VLANS; i++) { + err = rtl8366s_get_vlan_mc(smi, i, &vlanmc); + if (err) + return err; - /* - * See if this vlan member configuration is unused. It is - * unused if member set contains no ports or CPU port only - */ - if (!vlanmc.member || vlanmc.member == RTL8366_PORT_CPU) { - vlanmc.vid = val; - vlanmc.priority = 0; - vlanmc.untag = RTL8366_PORT_ALL_BUT_CPU; - vlanmc.member = ((1 << port) | RTL8366_PORT_CPU); - vlanmc.fid = 0; + if (vlanmc.vid == 0 && vlanmc.member == 0) { + /* Update the entry from the 4K table */ + err = rtl8366s_get_vlan_4k(smi, vid, &vlan4k); + if (err) + return err; + + vlanmc.vid = vid; + vlanmc.member = vlan4k.member; + vlanmc.untag = vlan4k.untag; + vlanmc.fid = vlan4k.fid; + err = rtl8366s_set_vlan_mc(smi, i, &vlanmc); + if (err) + return err; + + err = rtl8366s_set_mc_index(smi, port, i); + return err; + } + } - rtl8366s_set_vlan_mc(smi, i, &vlanmc); + /* MC table is full, try to find an unused entry and replace it */ + for (i = 0; i < RTL8366_NUM_VLANS; i++) { + int used; - /* Now update PVID register settings */ - rtl8366s_set_port_vlan_index(smi, port, i); + err = rtl8366s_mc_is_used(smi, i, &used); + if (err) + return err; - return 0; + if (!used) { + /* Update the entry from the 4K table */ + err = rtl8366s_get_vlan_4k(smi, vid, &vlan4k); + if (err) + return err; + + vlanmc.vid = vid; + vlanmc.member = vlan4k.member; + vlanmc.untag = vlan4k.untag; + vlanmc.fid = vlan4k.fid; + err = rtl8366s_set_vlan_mc(smi, i, &vlanmc); + if (err) + return err; + + err = rtl8366s_set_mc_index(smi, port, i); + return err; } } dev_err(smi->parent, - "All 16 vlan member configurations are in use\n"); + "all VLAN member configurations are in use\n"); - return -EINVAL; + return -ENOSPC; } - static int rtl8366s_vlan_set_vlan(struct rtl8366_smi *smi, int enable) { - u32 data = 0; - - rtl8366_smi_read_reg(smi, RTL8366_CHIP_GLOBAL_CTRL_REG, &data); - - if (enable) - data |= RTL8366_CHIP_CTRL_VLAN; - else - data &= ~RTL8366_CHIP_CTRL_VLAN; - - return rtl8366_smi_write_reg(smi, RTL8366_CHIP_GLOBAL_CTRL_REG, data); + return rtl8366_smi_rmwr(smi, RTL8366_CHIP_GLOBAL_CTRL_REG, + RTL8366_CHIP_CTRL_VLAN, + (enable) ? RTL8366_CHIP_CTRL_VLAN : 0); } static int rtl8366s_vlan_set_4ktable(struct rtl8366_smi *smi, int enable) { - u32 data = 0; - - rtl8366_smi_read_reg(smi, RTL8366S_VLAN_TB_CTRL_REG, &data); - - if (enable) - data |= 1; - else - data &= ~1; - - return rtl8366_smi_write_reg(smi, RTL8366S_VLAN_TB_CTRL_REG, data); + return rtl8366_smi_rmwr(smi, RTL8366S_VLAN_TB_CTRL_REG, + 1, (enable) ? 1 : 0); } static int rtl8366s_reset_vlan(struct rtl8366_smi *smi) { - struct rtl8366_vlan_4k vlan4k; struct rtl8366_vlan_mc vlanmc; int err; int i; - /* clear 16 VLAN member configuration */ + /* clear VLAN member configurations */ vlanmc.vid = 0; vlanmc.priority = 0; vlanmc.member = 0; @@ -753,18 +856,18 @@ static int rtl8366s_reset_vlan(struct rtl8366_smi *smi) return err; } - /* Set a default VLAN with vid 1 to 4K table for all ports */ - vlan4k.vid = 1; - vlan4k.member = RTL8366_PORT_ALL; - vlan4k.untag = RTL8366_PORT_ALL; - vlan4k.fid = 0; - err = rtl8366s_set_vlan_4k(smi, &vlan4k); - if (err) - return err; - - /* Set all ports PVID to default VLAN */ for (i = 0; i < RTL8366_NUM_PORTS; i++) { - err = rtl8366s_set_vlan_port_pvid(smi, i, 0); + if (i == RTL8366_PORT_CPU) + continue; + + err = rtl8366s_set_vlan(smi, (i + 1), + (1 << i) | RTL8366_PORT_CPU, + (1 << i) | RTL8366_PORT_CPU, + 0); + if (err) + return err; + + err = rtl8366s_set_pvid(smi, i, (i + 1)); if (err) return err; } @@ -815,20 +918,18 @@ static ssize_t rtl8366s_read_debugfs_mibs(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, len); } -static ssize_t rtl8366s_read_debugfs_vlan(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) +static ssize_t rtl8366s_read_debugfs_vlan_mc(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { struct rtl8366s *rtl = (struct rtl8366s *)file->private_data; struct rtl8366_smi *smi = &rtl->smi; - int i, j, len = 0; + int i, len = 0; char *buf = rtl->buf; len += snprintf(buf + len, sizeof(rtl->buf) - len, - "VLAN Member Config:\n"); - len += snprintf(buf + len, sizeof(rtl->buf) - len, - "\t id \t vid \t prio \t member \t untag \t fid " - "\tports\n"); + "%2s %6s %4s %6s %6s %3s\n", + "id", "vid","prio", "member", "untag", "fid"); for (i = 0; i < RTL8366_NUM_VLANS; ++i) { struct rtl8366_vlan_mc vlanmc; @@ -836,20 +937,9 @@ static ssize_t rtl8366s_read_debugfs_vlan(struct file *file, rtl8366s_get_vlan_mc(smi, i, &vlanmc); len += snprintf(buf + len, sizeof(rtl->buf) - len, - "\t[%d] \t %d \t %d \t 0x%04x \t 0x%04x \t %d " - "\t", i, vlanmc.vid, vlanmc.priority, + "%2d %6d %4d 0x%04x 0x%04x %3d\n", + i, vlanmc.vid, vlanmc.priority, vlanmc.member, vlanmc.untag, vlanmc.fid); - - for (j = 0; j < RTL8366_NUM_PORTS; ++j) { - int index = 0; - if (!rtl8366s_get_port_vlan_index(smi, j, &index)) { - if (index == i) - len += snprintf(buf + len, - sizeof(rtl->buf) - len, - "%d", j); - } - } - len += snprintf(buf + len, sizeof(rtl->buf) - len, "\n"); } return simple_read_from_buffer(user_buf, count, ppos, buf, len); @@ -924,8 +1014,8 @@ static const struct file_operations fops_rtl8366s_regs = { .owner = THIS_MODULE }; -static const struct file_operations fops_rtl8366s_vlan = { - .read = rtl8366s_read_debugfs_vlan, +static const struct file_operations fops_rtl8366s_vlan_mc = { + .read = rtl8366s_read_debugfs_vlan_mc, .open = rtl8366s_debugfs_open, .owner = THIS_MODULE }; @@ -965,11 +1055,11 @@ static void rtl8366s_debugfs_init(struct rtl8366s *rtl) return; } - node = debugfs_create_file("vlan", S_IRUSR, root, rtl, - &fops_rtl8366s_vlan); + node = debugfs_create_file("vlan_mc", S_IRUSR, root, rtl, + &fops_rtl8366s_vlan_mc); if (!node) { dev_err(rtl->parent, "Creating debugfs file '%s' failed\n", - "vlan"); + "vlan_mc"); return; } @@ -1000,15 +1090,12 @@ static int rtl8366s_sw_reset_mibs(struct switch_dev *dev, struct switch_val *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; + int err = 0; - if (val->value.i == 1) { - rtl8366_smi_read_reg(smi, RTL8366S_MIB_CTRL_REG, &data); - data |= (1 << 2); - rtl8366_smi_write_reg(smi, RTL8366S_MIB_CTRL_REG, data); - } + if (val->value.i == 1) + err = rtl8366_smi_rmwr(smi, RTL8366S_MIB_CTRL_REG, 0, (1 << 2)); - return 0; + return err; } static int rtl8366s_sw_get_vlan_enable(struct switch_dev *dev, @@ -1056,19 +1143,13 @@ static int rtl8366s_sw_set_blinkrate(struct switch_dev *dev, struct switch_val *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; if (val->value.i >= 6) return -EINVAL; - rtl8366_smi_read_reg(smi, RTL8366_LED_BLINKRATE_REG, &data); - - data &= ~RTL8366_LED_BLINKRATE_MASK; - data |= val->value.i; - - rtl8366_smi_write_reg(smi, RTL8366_LED_BLINKRATE_REG, data); - - return 0; + return rtl8366_smi_rmwr(smi, RTL8366_LED_BLINKRATE_REG, + RTL8366_LED_BLINKRATE_MASK, + val->value.i); } static int rtl8366s_sw_set_vlan_enable(struct switch_dev *dev, @@ -1146,43 +1227,35 @@ static int rtl8366s_sw_get_vlan_info(struct switch_dev *dev, { int i; u32 len = 0; - struct rtl8366_vlan_mc vlanmc; struct rtl8366_vlan_4k vlan4k; struct rtl8366s *rtl = sw_to_rtl8366s(dev); struct rtl8366_smi *smi = &rtl->smi; char *buf = rtl->buf; + int err; if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS) return -EINVAL; memset(buf, '\0', sizeof(rtl->buf)); - rtl8366s_get_vlan_mc(smi, val->port_vlan, &vlanmc); - rtl8366s_get_vlan_4k(smi, vlanmc.vid, &vlan4k); + err = rtl8366s_get_vlan_4k(smi, val->port_vlan, &vlan4k); + if (err) + return err; - len += snprintf(buf + len, sizeof(rtl->buf) - len, "VLAN %d: Ports: ", - val->port_vlan); + len += snprintf(buf + len, sizeof(rtl->buf) - len, + "VLAN %d: Ports: '", vlan4k.vid); - for (i = 0; i < RTL8366_NUM_PORTS; ++i) { - int index = 0; - if (!rtl8366s_get_port_vlan_index(smi, i, &index) && - index == val->port_vlan) - len += snprintf(buf + len, sizeof(rtl->buf) - len, - "%d", i); + for (i = 0; i < RTL8366_NUM_PORTS; i++) { + if (!(vlan4k.member & (1 << i))) + continue; + + len += snprintf(buf + len, sizeof(rtl->buf) - len, "%d%s", i, + (vlan4k.untag & (1 << i)) ? "" : "t"); } - len += snprintf(buf + len, sizeof(rtl->buf) - len, "\n"); len += snprintf(buf + len, sizeof(rtl->buf) - len, - "\t\t vid \t prio \t member \t untag \t fid\n"); - len += snprintf(buf + len, sizeof(rtl->buf) - len, "\tMC:\t"); - len += snprintf(buf + len, sizeof(rtl->buf) - len, - "%d \t %d \t 0x%04x \t 0x%04x \t %d\n", - vlanmc.vid, vlanmc.priority, vlanmc.member, - vlanmc.untag, vlanmc.fid); - len += snprintf(buf + len, sizeof(rtl->buf) - len, "\t4K:\t"); - len += snprintf(buf + len, sizeof(rtl->buf) - len, - "%d \t \t 0x%04x \t 0x%04x \t %d", - vlan4k.vid, vlan4k.member, vlan4k.untag, vlan4k.fid); + "', members=%04x, untag=%04x, fid=%u", + vlan4k.member, vlan4k.untag, vlan4k.fid); val->value.s = buf; val->len = len; @@ -1195,24 +1268,25 @@ static int rtl8366s_sw_set_port_led(struct switch_dev *dev, struct switch_val *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; + u32 data; + u32 mask; + u32 reg; if (val->port_vlan >= RTL8366_NUM_PORTS || (1 << val->port_vlan) == RTL8366_PORT_UNKNOWN) return -EINVAL; if (val->port_vlan == RTL8366_PORT_NUM_CPU) { - rtl8366_smi_read_reg(smi, RTL8366_LED_BLINKRATE_REG, &data); - data = (data & (~(0xF << 4))) | (val->value.i << 4); - rtl8366_smi_write_reg(smi, RTL8366_LED_BLINKRATE_REG, data); + reg = RTL8366_LED_BLINKRATE_REG; + mask = 0xF << 4; + data = val->value.i << 4; } else { - rtl8366_smi_read_reg(smi, RTL8366_LED_CTRL_REG, &data); - data = (data & (~(0xF << (val->port_vlan * 4)))) | - (val->value.i << (val->port_vlan * 4)); - rtl8366_smi_write_reg(smi, RTL8366_LED_CTRL_REG, data); + reg = RTL8366_LED_CTRL_REG; + mask = 0xF << (val->port_vlan * 4), + data = val->value.i << (val->port_vlan * 4); } - return 0; + return rtl8366_smi_rmwr(smi, RTL8366_LED_BLINKRATE_REG, mask, data); } static int rtl8366s_sw_get_port_led(struct switch_dev *dev, @@ -1236,16 +1310,13 @@ static int rtl8366s_sw_reset_port_mibs(struct switch_dev *dev, struct switch_val *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; if (val->port_vlan >= RTL8366_NUM_PORTS) return -EINVAL; - rtl8366_smi_read_reg(smi, RTL8366S_MIB_CTRL_REG, &data); - data |= (1 << (val->port_vlan + 3)); - rtl8366_smi_write_reg(smi, RTL8366S_MIB_CTRL_REG, data); - return 0; + return rtl8366_smi_rmwr(smi, RTL8366S_MIB_CTRL_REG, + 0, (1 << (val->port_vlan + 3))); } static int rtl8366s_sw_get_port_mib(struct switch_dev *dev, @@ -1285,23 +1356,23 @@ static int rtl8366s_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - struct rtl8366_vlan_mc vlanmc; struct switch_port *port; + struct rtl8366_vlan_4k vlan4k; int i; if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS) return -EINVAL; - rtl8366s_get_vlan_mc(smi, val->port_vlan, &vlanmc); + rtl8366s_get_vlan_4k(smi, val->port_vlan, &vlan4k); port = &val->value.ports[0]; val->len = 0; for (i = 0; i < RTL8366_NUM_PORTS; i++) { - if (!(vlanmc.member & BIT(i))) + if (!(vlan4k.member & BIT(i))) continue; port->id = i; - port->flags = (vlanmc.untag & BIT(i)) ? + port->flags = (vlan4k.untag & BIT(i)) ? 0 : BIT(SWITCH_PORT_FLAG_TAGGED); val->len++; port++; @@ -1313,46 +1384,35 @@ static int rtl8366s_sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - struct rtl8366_vlan_mc vlanmc; - struct rtl8366_vlan_4k vlan4k; struct switch_port *port; + u32 member = 0; + u32 untag = 0; int i; if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS) return -EINVAL; - rtl8366s_get_vlan_mc(smi, val->port_vlan, &vlanmc); - rtl8366s_get_vlan_4k(smi, vlanmc.vid, &vlan4k); - - vlanmc.untag = 0; - vlanmc.member = 0; - port = &val->value.ports[0]; for (i = 0; i < val->len; i++, port++) { - vlanmc.member |= BIT(port->id); + member |= BIT(port->id); if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) - vlanmc.untag |= BIT(port->id); + untag |= BIT(port->id); } - vlan4k.member = vlanmc.member; - vlan4k.untag = vlanmc.untag; - - rtl8366s_set_vlan_mc(smi, val->port_vlan, &vlanmc); - rtl8366s_set_vlan_4k(smi, &vlan4k); - return 0; + return rtl8366s_set_vlan(smi, val->port_vlan, member, untag, 0); } static int rtl8366s_sw_get_port_pvid(struct switch_dev *dev, int port, int *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - return rtl8366s_get_vlan_port_pvid(smi, port, val); + return rtl8366s_get_pvid(smi, port, val); } static int rtl8366s_sw_set_port_pvid(struct switch_dev *dev, int port, int val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - return rtl8366s_set_vlan_port_pvid(smi, port, val); + return rtl8366s_set_pvid(smi, port, val); } static int rtl8366s_sw_reset_switch(struct switch_dev *dev) @@ -1364,6 +1424,10 @@ static int rtl8366s_sw_reset_switch(struct switch_dev *dev) if (err) return err; + err = rtl8366s_hw_init(smi); + if (err) + return err; + return rtl8366s_reset_vlan(smi); } @@ -1529,12 +1593,14 @@ static int rtl8366s_setup(struct rtl8366s *rtl) struct rtl8366_smi *smi = &rtl->smi; int ret; + rtl8366s_debugfs_init(rtl); + ret = rtl8366s_reset_chip(smi); if (ret) return ret; - rtl8366s_debugfs_init(rtl); - return 0; + ret = rtl8366s_hw_init(smi); + return ret; } static int rtl8366s_detect(struct rtl8366_smi *smi)