X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/f79dd5c8406414c2913af9a4fdb913539f88c011..77450dabca4497bbfb5e353de5d566813a551ee5:/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 e2172f1b9..a79de4e6b 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) { @@ -975,44 +979,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 +1025,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 +1039,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 +1049,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 +1065,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 +1090,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 +1200,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 +1216,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 +1242,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 +1255,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 +1274,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 +1282,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 +1309,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 +1349,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 +1397,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 +1421,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 +1436,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 +1451,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 +1478,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 (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) + vlanmc.untag |= BIT(port->id); + } - if (val->port_vlan >= RTL8366_NUM_VLANS) - return -EINVAL; + vlan4k.member = vlanmc.member; + vlan4k.untag = vlanmc.untag; - 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); - - 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 +1596,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 +1651,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,6 +1681,8 @@ 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,