X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/221c0d2b2d2a960986dbe0d8ce8b9a085178a22d..72607e76c7dd22869ae985371d1d261456f2f28c:/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c diff --git a/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c b/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c index 0d54126cc..6c807bc02 100644 --- a/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c +++ b/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c @@ -209,6 +209,7 @@ struct rtl8366_smi { struct mii_bus *mii_bus; struct switch_dev dev; int mii_irq[PHY_MAX_ADDR]; + char buf[4096]; #ifdef DEBUG struct dentry *debugfs_root; #endif @@ -218,7 +219,10 @@ struct rtl8366_smi { u16 g_dbg_reg; #endif -#define to_rtl8366(_dev) container_of(_dev, struct rtl8366_smi, dev) +static inline struct rtl8366_smi *sw_to_rtl8366(struct switch_dev *sw) +{ + return container_of(sw, struct rtl8366_smi, dev); +} static inline void rtl8366_smi_clk_delay(struct rtl8366_smi *smi) { @@ -932,19 +936,21 @@ static int rtl8366_vlan_set_4ktable(struct rtl8366_smi *smi, int enable) static int rtl8366s_reset_vlan(struct rtl8366_smi *smi) { - int i; struct rtl8366s_vlan4kentry vlan4k; struct rtl8366s_vlanconfig vlanmc; + int err; + int i; /* clear 16 VLAN member configuration */ + vlanmc.vid = 0; + vlanmc.priority = 0; + vlanmc.member = 0; + vlanmc.untag = 0; + vlanmc.fid = 0; for (i = 0; i < RTL8366_NUM_VLANS; i++) { - vlanmc.vid = 0; - vlanmc.priority = 0; - vlanmc.member = 0; - vlanmc.untag = 0; - vlanmc.fid = 0; - if (rtl8366s_set_vlan_member_config(smi, i, &vlanmc) != 0) - return -EIO; + err = rtl8366s_set_vlan_member_config(smi, i, &vlanmc); + if (err) + return err; } /* Set a default VLAN with vid 1 to 4K table for all ports */ @@ -952,13 +958,15 @@ static int rtl8366s_reset_vlan(struct rtl8366_smi *smi) vlan4k.member = RTL8366_PORT_ALL; vlan4k.untag = RTL8366_PORT_ALL; vlan4k.fid = 0; - if (rtl8366s_set_vlan_4k_entry(smi, &vlan4k) != 0) - return -EIO; + err = rtl8366s_set_vlan_4k_entry(smi, &vlan4k); + if (err) + return err; /* Set all ports PVID to default VLAN */ for (i = 0; i < RTL8366_NUM_PORTS; i++) { - if (rtl8366_set_vlan_port_pvid(smi, i, 0) != 0) - return -EIO; + err = rtl8366_set_vlan_port_pvid(smi, i, 0); + if (err) + return err; } return 0; @@ -975,44 +983,44 @@ static ssize_t rtl8366_read_debugfs_mibs(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - char buf[4096]; int i, j, len = 0; struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; + char *buf = smi->buf; - len += snprintf(buf + len, sizeof(buf) - len, "MIB Counters:\n"); - len += snprintf(buf + len, sizeof(buf) - len, "Counter" + len += snprintf(buf + len, sizeof(smi->buf) - len, "MIB Counters:\n"); + len += snprintf(buf + len, sizeof(smi->buf) - len, "Counter" " " "Port 0 \t\t Port 1 \t\t Port 2 \t\t Port 3 \t\t " "Port 4\n"); for (i = 0; i < 33; ++i) { - len += snprintf(buf + len, sizeof(buf) - len, "%d:%s ", + len += snprintf(buf + len, sizeof(smi->buf) - len, "%d:%s ", i, MIBCOUNTERS[i]); for (j = 0; j < RTL8366_NUM_PORTS; ++j) { unsigned long long counter = 0; if (!rtl8366_get_mib_counter(smi, i, j, &counter)) - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "[%llu]", counter); else - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "[error]"); if (j != RTL8366_NUM_PORTS - 1) { if (counter < 100000) len += snprintf(buf + len, - sizeof(buf) - len, + sizeof(smi->buf) - len, "\t"); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "\t"); } } - len += snprintf(buf + len, sizeof(buf) - len, "\n"); + len += snprintf(buf + len, sizeof(smi->buf) - len, "\n"); } - len += snprintf(buf + len, sizeof(buf) - len, "\n"); + len += snprintf(buf + len, sizeof(smi->buf) - len, "\n"); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1021,12 +1029,12 @@ static ssize_t rtl8366_read_debugfs_vlan(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - char buf[4096]; int i, j, len = 0; struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; + char *buf = smi->buf; - len += snprintf(buf + len, sizeof(buf) - len, "VLAN Member Config:\n"); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "VLAN Member Config:\n"); + len += snprintf(buf + len, sizeof(smi->buf) - len, "\t id \t vid \t prio \t member \t untag \t fid " "\tports\n"); @@ -1035,7 +1043,7 @@ static ssize_t rtl8366_read_debugfs_vlan(struct file *file, rtl8366s_get_vlan_member_config(smi, i, &vlanmc); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "\t[%d] \t %d \t %d \t 0x%04x \t 0x%04x \t %d " "\t", i, vlanmc.vid, vlanmc.priority, vlanmc.member, vlanmc.untag, vlanmc.fid); @@ -1045,11 +1053,11 @@ static ssize_t rtl8366_read_debugfs_vlan(struct file *file, if (!rtl8366_get_port_vlan_index(smi, j, &index)) { if (index == i) len += snprintf(buf + len, - sizeof(buf) - len, + sizeof(smi->buf) - len, "%d", j); } } - len += snprintf(buf + len, sizeof(buf) - len, "\n"); + len += snprintf(buf + len, sizeof(smi->buf) - len, "\n"); } return simple_read_from_buffer(user_buf, count, ppos, buf, len); @@ -1061,19 +1069,19 @@ static ssize_t rtl8366_read_debugfs_reg(struct file *file, { u32 t, reg = g_dbg_reg; int err, len = 0; - char buf[512]; struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; + char *buf = smi->buf; - memset(buf, '\0', sizeof(buf)); + memset(buf, '\0', sizeof(smi->buf)); err = rtl8366_smi_read_reg(smi, reg, &t); if (err) { - len += snprintf(buf, sizeof(buf), + len += snprintf(buf, sizeof(smi->buf), "Read failed (reg: 0x%04x)\n", reg); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } - len += snprintf(buf, sizeof(buf), "reg = 0x%04x, val = 0x%04x\n", + len += snprintf(buf, sizeof(smi->buf), "reg = 0x%04x, val = 0x%04x\n", reg, t); return simple_read_from_buffer(user_buf, count, ppos, buf, len); @@ -1086,11 +1094,11 @@ static ssize_t rtl8366_write_debugfs_reg(struct file *file, unsigned long data; u32 reg = g_dbg_reg; int err; - char buf[50]; size_t len; struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; + char *buf = smi->buf; - len = min(count, sizeof(buf) - 1); + len = min(count, sizeof(smi->buf) - 1); if (copy_from_user(buf, user_buf, len)) { dev_err(&smi->pdev->dev, "copy from user failed\n"); return -EFAULT; @@ -1196,7 +1204,7 @@ static int rtl8366_global_reset_mibs(struct switch_dev *dev, struct switch_val *val) { u32 data = 0; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); if (val->value.i == 1) { rtl8366_smi_read_reg(smi, RTL8366S_MIB_CTRL_REG, &data); @@ -1212,7 +1220,7 @@ static int rtl8366_get_vlan(struct switch_dev *dev, struct switch_val *val) { u32 data; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); if (attr->ofs == 1) { rtl8366_smi_read_reg(smi, RTL8366_CHIP_GLOBAL_CTRL_REG, &data); @@ -1238,7 +1246,7 @@ static int rtl8366_global_get_blinkrate(struct switch_dev *dev, struct switch_val *val) { u32 data; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); rtl8366_smi_read_reg(smi, RTL8366_LED_BLINKRATE_REG, &data); val->value.i = (data & (RTL8366_LED_BLINKRATE_MASK)); @@ -1251,7 +1259,7 @@ static int rtl8366_global_set_blinkrate(struct switch_dev *dev, struct switch_val *val) { u32 data; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); if (val->value.i >= 6) return -EINVAL; @@ -1270,7 +1278,7 @@ static int rtl8366_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) { - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); if (attr->ofs == 1) return rtl8366_vlan_set_vlan(smi, val->value.i); @@ -1278,27 +1286,19 @@ static int rtl8366_set_vlan(struct switch_dev *dev, return rtl8366_vlan_set_4ktable(smi, val->value.i); } -static int rtl8366_init_vlan(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = to_rtl8366(dev); - return rtl8366s_reset_vlan(smi); -} - static int rtl8366_attr_get_port_link(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) { - char buf[1024]; u32 len = 0, data = 0; int speed, duplex, link, txpause, rxpause, nway; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); + char *buf = smi->buf; if (val->port_vlan >= RTL8366_NUM_PORTS) return -EINVAL; - memset(buf, '\0', sizeof(buf)); + memset(buf, '\0', sizeof(smi->buf)); rtl8366_smi_read_reg(smi, RTL8366S_PORT_LINK_STATUS_BASE + (val->port_vlan >> 1), &data); @@ -1313,34 +1313,34 @@ static int rtl8366_attr_get_port_link(struct switch_dev *dev, rxpause = (data & RTL8366S_PORT_STATUS_RXPAUSE_MASK) >> 6; nway = (data & RTL8366S_PORT_STATUS_AN_MASK) >> 7; - len += snprintf(buf + len, sizeof(buf) - len, "Port %d: ", + len += snprintf(buf + len, sizeof(smi->buf) - len, "Port %d: ", val->port_vlan); if (link) - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "Link UP, Speed: "); else - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "Link DOWN, Speed: "); if (speed == 0) - len += snprintf(buf + len, sizeof(buf) - len, "10Base-TX "); + len += snprintf(buf + len, sizeof(smi->buf) - len, "10Base-TX "); else if (speed == 1) - len += snprintf(buf + len, sizeof(buf) - len, "100Base-TX "); + len += snprintf(buf + len, sizeof(smi->buf) - len, "100Base-TX "); else if (speed == 2) - len += snprintf(buf + len, sizeof(buf) - len, "1000Base-TX "); + len += snprintf(buf + len, sizeof(smi->buf) - len, "1000Base-TX "); if (duplex) - len += snprintf(buf + len, sizeof(buf) - len, "Full-Duplex, "); + len += snprintf(buf + len, sizeof(smi->buf) - len, "Full-Duplex, "); else - len += snprintf(buf + len, sizeof(buf) - len, "Half-Duplex, "); + len += snprintf(buf + len, sizeof(smi->buf) - len, "Half-Duplex, "); if (txpause) - len += snprintf(buf + len, sizeof(buf) - len, "TX-Pause "); + len += snprintf(buf + len, sizeof(smi->buf) - len, "TX-Pause "); if (rxpause) - len += snprintf(buf + len, sizeof(buf) - len, "RX-Pause "); + len += snprintf(buf + len, sizeof(smi->buf) - len, "RX-Pause "); if (nway) - len += snprintf(buf + len, sizeof(buf) - len, "nway "); + len += snprintf(buf + len, sizeof(smi->buf) - len, "nway "); val->value.s = buf; val->len = len; @@ -1353,40 +1353,40 @@ static int rtl8366_attr_get_vlan_info(struct switch_dev *dev, struct switch_val *val) { int i; - char buf[1024]; u32 len = 0; struct rtl8366s_vlanconfig vlanmc; struct rtl8366s_vlan4kentry vlan4k; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); + char *buf = smi->buf; if (val->port_vlan >= RTL8366_NUM_PORTS) return -EINVAL; - memset(buf, '\0', sizeof(buf)); + memset(buf, '\0', sizeof(smi->buf)); rtl8366s_get_vlan_member_config(smi, val->port_vlan, &vlanmc); rtl8366s_get_vlan_4k_entry(smi, vlanmc.vid, &vlan4k); - len += snprintf(buf + len, sizeof(buf) - len, "VLAN %d: Ports: ", + len += snprintf(buf + len, sizeof(smi->buf) - len, "VLAN %d: Ports: ", val->port_vlan); for (i = 0; i < RTL8366_NUM_PORTS; ++i) { int index = 0; if (!rtl8366_get_port_vlan_index(smi, i, &index) && index == val->port_vlan) - len += snprintf(buf + len, sizeof(buf) - len, "%d", i); + len += snprintf(buf + len, sizeof(smi->buf) - len, "%d", i); } - len += snprintf(buf + len, sizeof(buf) - len, "\n"); + len += snprintf(buf + len, sizeof(smi->buf) - len, "\n"); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "\t\t vid \t prio \t member \t untag \t fid\n"); - len += snprintf(buf + len, sizeof(buf) - len, "\tMC:\t"); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "\tMC:\t"); + len += snprintf(buf + len, sizeof(smi->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(buf) - len, "\t4K:\t"); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "\t4K:\t"); + len += snprintf(buf + len, sizeof(smi->buf) - len, "%d \t \t 0x%04x \t 0x%04x \t %d", vlan4k.vid, vlan4k.member, vlan4k.untag, vlan4k.fid); @@ -1401,7 +1401,7 @@ static int rtl8366_set_port_led(struct switch_dev *dev, struct switch_val *val) { u32 data = 0; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); if (val->port_vlan >= RTL8366_NUM_PORTS || (1 << val->port_vlan) == RTL8366_PORT_UNKNOWN) return -EINVAL; @@ -1425,7 +1425,7 @@ static int rtl8366_get_port_led(struct switch_dev *dev, struct switch_val *val) { u32 data = 0; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); if (val->port_vlan >= RTL8366_NUM_LEDGROUPS) return -EINVAL; @@ -1440,7 +1440,7 @@ static int rtl8366_reset_port_mibs(struct switch_dev *dev, struct switch_val *val) { u32 data = 0; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); if (val->port_vlan >= RTL8366_NUM_PORTS) return -EINVAL; @@ -1455,24 +1455,25 @@ static int rtl8366_get_port_mib(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) { - char buf[2048]; int i, len = 0; unsigned long long counter = 0; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); + char *buf = smi->buf; + if (val->port_vlan >= RTL8366_NUM_PORTS) return -EINVAL; - len += snprintf(buf + len, sizeof(buf) - len, "Port %d MIB counters\n", + len += snprintf(buf + len, sizeof(smi->buf) - len, "Port %d MIB counters\n", val->port_vlan); for (i = 0; i < RTL8366S_MIB_COUNT; ++i) { - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "%d:%s\t", i, MIBCOUNTERS[i]); if (!rtl8366_get_mib_counter(smi, i, val->port_vlan, &counter)) - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "[%llu]\n", counter); else - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, sizeof(smi->buf) - len, "[error]\n"); } @@ -1481,107 +1482,103 @@ static int rtl8366_get_port_mib(struct switch_dev *dev, return 0; } -static int rtl8366_set_member(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) +static int rtl8366_get_ports(struct switch_dev *dev, + struct switch_val *val) { struct rtl8366s_vlanconfig vlanmc; - struct rtl8366s_vlan4kentry vlan4k; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); + struct switch_port *port; + int i; if (val->port_vlan >= RTL8366_NUM_VLANS) return -EINVAL; rtl8366s_get_vlan_member_config(smi, val->port_vlan, &vlanmc); - rtl8366s_get_vlan_4k_entry(smi, vlanmc.vid, &vlan4k); - - vlan4k.member = vlanmc.member = val->value.i; - rtl8366s_set_vlan_member_config(smi, val->port_vlan, &vlanmc); - rtl8366s_set_vlan_4k_entry(smi, &vlan4k); - + port = &val->value.ports[0]; + val->len = 0; + for (i = 0; i < RTL8366_NUM_PORTS; i++) { + if (!(vlanmc.member & BIT(i))) + continue; + + port->id = i; + port->flags = (vlanmc.untag & BIT(i)) ? + 0 : BIT(SWITCH_PORT_FLAG_TAGGED); + val->len++; + port++; + } return 0; } -static int rtl8366_get_member(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) +static int rtl8366_set_ports(struct switch_dev *dev, + struct switch_val *val) { struct rtl8366s_vlanconfig vlanmc; struct rtl8366s_vlan4kentry vlan4k; - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); + struct switch_port *port; + int i; if (val->port_vlan >= RTL8366_NUM_VLANS) return -EINVAL; rtl8366s_get_vlan_member_config(smi, val->port_vlan, &vlanmc); - rtl8366s_get_vlan_4k_entry(smi, vlanmc.vid, &vlan4k); - val->value.i = vlanmc.member; + vlanmc.untag = 0; + vlanmc.member = 0; - return 0; -} + port = &val->value.ports[0]; + for (i = 0; i < val->len; i++, port++) { + vlanmc.member |= BIT(port->id); -static int rtl8366_set_untag(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366s_vlanconfig vlanmc; - struct rtl8366s_vlan4kentry vlan4k; - struct rtl8366_smi *smi = to_rtl8366(dev); - - if (val->port_vlan >= RTL8366_NUM_VLANS) - return -EINVAL; + if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) + vlanmc.untag |= BIT(port->id); + } - rtl8366s_get_vlan_member_config(smi, val->port_vlan, &vlanmc); - rtl8366s_get_vlan_4k_entry(smi, vlanmc.vid, &vlan4k); + vlan4k.member = vlanmc.member; + vlan4k.untag = vlanmc.untag; - vlan4k.untag = vlanmc.untag = val->value.i; rtl8366s_set_vlan_member_config(smi, val->port_vlan, &vlanmc); rtl8366s_set_vlan_4k_entry(smi, &vlan4k); - - return 0; -} - -static int rtl8366_get_untag(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366s_vlanconfig vlanmc; - struct rtl8366s_vlan4kentry vlan4k; - struct rtl8366_smi *smi = to_rtl8366(dev); - - if (val->port_vlan >= RTL8366_NUM_VLANS) - return -EINVAL; - - rtl8366s_get_vlan_member_config(smi, val->port_vlan, &vlanmc); - rtl8366s_get_vlan_4k_entry(smi, vlanmc.vid, &vlan4k); - - - val->value.i = vlanmc.untag; - return 0; } static int rtl8366_get_port_pvid(struct switch_dev *dev, int port, int *val) { - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); return rtl8366_get_vlan_port_pvid(smi, port, val); } static int rtl8366_set_port_pvid(struct switch_dev *dev, int port, int val) { - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); return rtl8366_set_vlan_port_pvid(smi, port, val); } static int rtl8366_reset_switch(struct switch_dev *dev) { - struct rtl8366_smi *smi = to_rtl8366(dev); + struct rtl8366_smi *smi = sw_to_rtl8366(dev); + int timeout = 10; + u32 data; + rtl8366_smi_write_reg(smi, RTL8366_RESET_CTRL_REG, RTL8366_CHIP_CTRL_RESET_HW); - return 0; + 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 rtl8366s_reset_vlan(smi); } static struct switch_attr rtl8366_globals[] = { @@ -1603,15 +1600,6 @@ static struct switch_attr rtl8366_globals[] = { .max = 1, .ofs = 2 }, - { - .type = SWITCH_TYPE_INT, - .name = "init_vlan", - .description = "Initialize VLAN tables to defaults", - .set = rtl8366_init_vlan, - .get = NULL, - .max = 1 - }, - { .type = SWITCH_TYPE_INT, .name = "reset_mibs", @@ -1667,22 +1655,6 @@ static struct switch_attr rtl8366_port[] = { }; static struct switch_attr rtl8366_vlan[] = { - { - .type = SWITCH_TYPE_INT, - .name = "untag", - .description = "Get/Set VLAN untag port set (bitmask)", - .set = rtl8366_set_untag, - .get = rtl8366_get_untag, - .max = 63, - }, - { - .type = SWITCH_TYPE_INT, - .name = "member", - .description = "Get/Set VLAN member port set (bitmask)", - .set = rtl8366_set_member, - .get = rtl8366_get_member, - .max = 63, - }, { .type = SWITCH_TYPE_STRING, .name = "info", @@ -1713,11 +1685,34 @@ static struct switch_dev rtldev = { .n_attr = ARRAY_SIZE(rtl8366_vlan), }, + .get_vlan_ports = rtl8366_get_ports, + .set_vlan_ports = rtl8366_set_ports, .get_port_pvid = rtl8366_get_port_pvid, .set_port_pvid = rtl8366_set_port_pvid, .reset_switch = rtl8366_reset_switch, }; +static int rtl8366_smi_switch_init(struct rtl8366_smi *smi) +{ + struct switch_dev *dev = &smi->dev; + int err; + + memcpy(dev, &rtldev, sizeof(struct switch_dev)); + dev->priv = smi; + dev->devname = dev_name(&smi->pdev->dev); + + err = register_switch(dev, NULL); + if (err) + dev_err(&smi->pdev->dev, "switch registration failed\n"); + + return err; +} + +static void rtl8366_smi_switch_cleanup(struct rtl8366_smi *smi) +{ + unregister_switch(&smi->dev); +} + static int rtl8366_smi_mii_read(struct mii_bus *bus, int addr, int reg) { struct rtl8366_smi *smi = bus->priv; @@ -1787,6 +1782,12 @@ static void rtl8366_smi_mii_cleanup(struct rtl8366_smi *smi) mdiobus_free(smi->mii_bus); } +static int rtl8366_smi_mii_bus_match(struct mii_bus *bus) +{ + return (bus->read == rtl8366_smi_mii_read && + bus->write == rtl8366_smi_mii_write); +} + static int rtl8366_smi_setup(struct rtl8366_smi *smi) { u32 chip_id = 0; @@ -1878,8 +1879,14 @@ static int __init rtl8366_smi_probe(struct platform_device *pdev) if (err) goto err_clear_drvdata; + err = rtl8366_smi_switch_init(smi); + if (err) + goto err_mii_cleanup; + return 0; + err_mii_cleanup: + rtl8366_smi_mii_cleanup(smi); err_clear_drvdata: platform_set_drvdata(pdev, NULL); gpio_free(pdata->gpio_sck); @@ -1893,26 +1900,8 @@ static int __init rtl8366_smi_probe(struct platform_device *pdev) int rtl8366_phy_config_init(struct phy_device *phydev) { - int err; - struct net_device *netdev = phydev->attached_dev; - struct rtl8366_smi *smi = phydev->bus->priv; - struct switch_dev *dev = &smi->dev; - - /* Only init the switch for the primary PHY */ - if (phydev->addr != 4) { - printk(KERN_INFO "Discarding address: %d\n", phydev->addr); - return 0; - } - - memcpy(&smi->dev, &rtldev, sizeof(struct switch_dev)); - dev->priv = smi; - dev->netdev = netdev; - - err = register_switch(dev, netdev); - if (err < 0) { - printk(KERN_INFO "Switch registration failed\n"); - return err; - } + if (!rtl8366_smi_mii_bus_match(phydev->bus)) + return -EINVAL; return 0; } @@ -1944,8 +1933,8 @@ static int __devexit rtl8366_smi_remove(struct platform_device *pdev) pdata = pdev->dev.platform_data; + rtl8366_smi_switch_cleanup(smi); rtl8366_debugfs_remove(smi); - phy_driver_unregister(&rtl8366_smi_phy_driver); rtl8366_smi_mii_cleanup(smi); platform_set_drvdata(pdev, NULL); gpio_free(pdata->gpio_sck);