X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/ef0ac006fffc32659c071f7ab85e167ea3608b01..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 557d84902..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) { @@ -604,6 +608,7 @@ static int rtl8366s_get_vlan_4k_entry(struct rtl8366_smi *smi, u32 vid, u32 data; u16 *tableaddr; + memset(vlan4k, '\0', sizeof(struct rtl8366s_vlan4kentry)); vlan4k->vid = vid; if (vid >= RTL8366_NUM_VIDS) @@ -679,18 +684,19 @@ static int rtl8366s_set_vlan_4k_entry(struct rtl8366_smi *smi, } static int rtl8366s_get_vlan_member_config(struct rtl8366_smi *smi, u32 index, - struct rtl8366s_vlanconfig - *vlanmconf) + struct rtl8366s_vlanconfig *vlanmc) { int err; u32 addr; u32 data; u16 *tableaddr; + memset(vlanmc, '\0', sizeof(struct rtl8366s_vlanconfig)); + if (index >= RTL8366_NUM_VLANS) return -EINVAL; - tableaddr = (u16 *)vlanmconf; + tableaddr = (u16 *)vlanmc; addr = RTL8366S_VLAN_MEMCONF_BASE + (index << 1); @@ -714,7 +720,7 @@ static int rtl8366s_get_vlan_member_config(struct rtl8366_smi *smi, u32 index, static int rtl8366s_set_vlan_member_config(struct rtl8366_smi *smi, u32 index, const struct rtl8366s_vlanconfig - *vlanmconf) + *vlanmc) { int err; u32 addr; @@ -722,17 +728,17 @@ static int rtl8366s_set_vlan_member_config(struct rtl8366_smi *smi, u32 index, u16 *tableaddr; if (index >= RTL8366_NUM_VLANS || - vlanmconf->vid >= RTL8366_NUM_VIDS || - vlanmconf->priority > RTL8366S_PRIORITYMAX || - vlanmconf->member > RTL8366_PORT_ALL || - vlanmconf->untag > RTL8366_PORT_ALL || - vlanmconf->fid > RTL8366S_FIDMAX) + vlanmc->vid >= RTL8366_NUM_VIDS || + vlanmc->priority > RTL8366S_PRIORITYMAX || + vlanmc->member > RTL8366_PORT_ALL || + vlanmc->untag > RTL8366_PORT_ALL || + vlanmc->fid > RTL8366S_FIDMAX) return -EINVAL; addr = RTL8366S_VLAN_MEMCONF_BASE + (index << 1); - tableaddr = (u16 *)vlanmconf; + tableaddr = (u16 *)vlanmc; data = *tableaddr; err = rtl8366_smi_write_reg(smi, addr, data); @@ -786,19 +792,17 @@ static int rtl8366_get_vlan_port_pvid(struct rtl8366_smi *smi, int port, { int err; int index; - struct rtl8366s_vlanconfig vlanMC; - - memset(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); + struct rtl8366s_vlanconfig vlanmc; err = rtl8366_get_port_vlan_index(smi, port, &index); if (err) return err; - err = rtl8366s_get_vlan_member_config(smi, index, &vlanMC); + err = rtl8366s_get_vlan_member_config(smi, index, &vlanmc); if (err) return err; - *val = vlanMC.vid; + *val = vlanmc.vid; return 0; } @@ -846,8 +850,8 @@ static int rtl8366_set_vlan_port_pvid(struct rtl8366_smi *smi, int port, int val) { int i; - struct rtl8366s_vlanconfig vlanMC; - struct rtl8366s_vlan4kentry vlan4K; + struct rtl8366s_vlanconfig vlanmc; + struct rtl8366s_vlan4kentry vlan4k; if (port >= RTL8366_NUM_PORTS || val >= RTL8366_NUM_VIDS) return -EINVAL; @@ -855,22 +859,20 @@ static int rtl8366_set_vlan_port_pvid(struct rtl8366_smi *smi, int port, /* Updating the 4K entry; lookup it and change the port member set */ - memset(&vlan4K, '\0', sizeof(struct rtl8366s_vlan4kentry)); - rtl8366s_get_vlan_4k_entry(smi, val, &vlan4K); - vlan4K.member |= ((1 << port) | RTL8366_PORT_CPU); - vlan4K.untag = RTL8366_PORT_ALL_BUT_CPU; - rtl8366s_set_vlan_4k_entry(smi, &vlan4K); + rtl8366s_get_vlan_4k_entry(smi, val, &vlan4k); + vlan4k.member |= ((1 << port) | RTL8366_PORT_CPU); + vlan4k.untag = RTL8366_PORT_ALL_BUT_CPU; + rtl8366s_set_vlan_4k_entry(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) { - memset(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); - rtl8366s_get_vlan_member_config(smi, i, &vlanMC); + rtl8366s_get_vlan_member_config(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_member_config(smi, i, &vlanMC); + if (val == vlanmc.vid) { + vlanmc.member |= ((1 << port) | RTL8366_PORT_CPU); + rtl8366s_set_vlan_member_config(smi, i, &vlanmc); /* Now update PVID register settings */ rtl8366_set_port_vlan_index(smi, port, i); @@ -882,19 +884,18 @@ static int rtl8366_set_vlan_port_pvid(struct rtl8366_smi *smi, int port, /* 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) { - memset(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); - rtl8366s_get_vlan_member_config(smi, i, &vlanMC); + rtl8366s_get_vlan_member_config(smi, i, &vlanmc); /* 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.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; - rtl8366s_set_vlan_member_config(smi, i, &vlanMC); + rtl8366s_set_vlan_member_config(smi, i, &vlanmc); /* Now update PVID register settings */ rtl8366_set_port_vlan_index(smi, port, i); @@ -935,33 +936,37 @@ static int rtl8366_vlan_set_4ktable(struct rtl8366_smi *smi, int enable) static int rtl8366s_reset_vlan(struct rtl8366_smi *smi) { + struct rtl8366s_vlan4kentry vlan4k; + struct rtl8366s_vlanconfig vlanmc; + int err; int i; - struct rtl8366s_vlan4kentry vlan4K; - struct rtl8366s_vlanconfig vlanMC; /* 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 */ - vlan4K.vid = 1; - vlan4K.member = RTL8366_PORT_ALL; - vlan4K.untag = RTL8366_PORT_ALL; - vlan4K.fid = 0; - if (rtl8366s_set_vlan_4k_entry(smi, &vlan4K) != 0) - return -EIO; + vlan4k.vid = 1; + vlan4k.member = RTL8366_PORT_ALL; + vlan4k.untag = RTL8366_PORT_ALL; + vlan4k.fid = 0; + 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; @@ -978,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); } @@ -1024,35 +1029,35 @@ 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"); for (i = 0; i < RTL8366_NUM_VLANS; ++i) { - struct rtl8366s_vlanconfig vlanMC; - memset(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); - rtl8366s_get_vlan_member_config(smi, i, &vlanMC); + struct rtl8366s_vlanconfig vlanmc; + + 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); + "\t", i, vlanmc.vid, vlanmc.priority, + vlanmc.member, vlanmc.untag, vlanmc.fid); for (j = 0; j < RTL8366_NUM_PORTS; ++j) { int index = 0; 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); @@ -1064,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); @@ -1089,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; @@ -1199,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); @@ -1215,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); @@ -1241,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)); @@ -1254,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; @@ -1273,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); @@ -1281,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); @@ -1316,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; @@ -1356,44 +1353,42 @@ 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 rtl8366s_vlanconfig vlanmc; + struct rtl8366s_vlan4kentry vlan4k; + 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(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); - memset(&vlan4K, '\0', sizeof(struct rtl8366s_vlan4kentry)); + 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); + 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, + vlanmc.vid, vlanmc.priority, vlanmc.member, + vlanmc.untag, vlanmc.fid); + 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); + vlan4k.vid, vlan4k.member, vlan4k.untag, vlan4k.fid); val->value.s = buf; val->len = len; @@ -1406,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; @@ -1430,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; @@ -1445,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; @@ -1460,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"); } @@ -1486,115 +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) -{ - struct rtl8366s_vlanconfig vlanMC; - struct rtl8366s_vlan4kentry vlan4K; - struct rtl8366_smi *smi = to_rtl8366(dev); - memset(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); - memset(&vlan4K, '\0', sizeof(struct rtl8366s_vlan4kentry)); - - 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); - - return 0; -} - -static int rtl8366_get_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); - memset(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); - memset(&vlan4K, '\0', sizeof(struct rtl8366s_vlan4kentry)); + struct rtl8366s_vlanconfig vlanmc; + 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; + rtl8366s_get_vlan_member_config(smi, val->port_vlan, &vlanmc); + 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_set_untag(struct switch_dev *dev, - const struct switch_attr *attr, +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); - memset(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); - memset(&vlan4K, '\0', sizeof(struct rtl8366s_vlan4kentry)); + struct rtl8366s_vlanconfig vlanmc; + struct rtl8366s_vlan4kentry vlan4k; + 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); + rtl8366s_get_vlan_member_config(smi, val->port_vlan, &vlanmc); + rtl8366s_get_vlan_4k_entry(smi, vlanmc.vid, &vlan4k); - vlan4K.untag = vlanMC.untag = val->value.i; - rtl8366s_set_vlan_member_config(smi, val->port_vlan, &vlanMC); - rtl8366s_set_vlan_4k_entry(smi, &vlan4K); + vlanmc.untag = 0; + vlanmc.member = 0; - 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); - memset(&vlanMC, '\0', sizeof(struct rtl8366s_vlanconfig)); - memset(&vlan4K, '\0', sizeof(struct rtl8366s_vlan4kentry)); - - 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); + port = &val->value.ports[0]; + for (i = 0; i < val->len; i++, port++) { + vlanmc.member |= BIT(port->id); + if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) + vlanmc.untag |= BIT(port->id); + } - val->value.i = vlanMC.untag; + vlan4k.member = vlanmc.member; + vlan4k.untag = vlanmc.untag; + rtl8366s_set_vlan_member_config(smi, val->port_vlan, &vlanmc); + rtl8366s_set_vlan_4k_entry(smi, &vlan4k); 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[] = { @@ -1616,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", @@ -1680,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", @@ -1726,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; @@ -1800,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; @@ -1891,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); @@ -1906,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; } @@ -1957,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);