From 5f69279dd608b54807714716cb9ff9e39f2e72c5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 6 Jan 2016 18:32:21 +0000 Subject: [PATCH] swconfig: add API for setting port link speed MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Some switches can force link speed for a port. Let's add API that will allow drivers to export this feature. Signed-off-by: Rafał Miłecki SVN-Revision: 48142 --- .../generic/files/drivers/net/phy/swconfig.c | 49 ++++++++++++++++++- .../generic/files/include/linux/switch.h | 2 + 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/target/linux/generic/files/drivers/net/phy/swconfig.c b/target/linux/generic/files/drivers/net/phy/swconfig.c index 07efda05eb..9a5f1e9123 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig.c @@ -127,6 +127,16 @@ swconfig_get_pvid(struct switch_dev *dev, const struct switch_attr *attr, return dev->ops->get_port_pvid(dev, val->port_vlan, &val->value.i); } +static int +swconfig_set_link(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + if (!dev->ops->set_port_link) + return -EOPNOTSUPP; + + return dev->ops->set_port_link(dev, val->port_vlan, val->value.link); +} + static int swconfig_get_link(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) @@ -206,7 +216,7 @@ static struct switch_attr default_port[] = { .type = SWITCH_TYPE_LINK, .name = "link", .description = "Get port link information", - .set = NULL, + .set = swconfig_set_link, .get = swconfig_get_link, } }; @@ -282,6 +292,12 @@ static const struct nla_policy port_policy[SWITCH_PORT_ATTR_MAX+1] = { [SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG }, }; +static struct nla_policy link_policy[SWITCH_LINK_ATTR_MAX] = { + [SWITCH_LINK_FLAG_DUPLEX] = { .type = NLA_FLAG }, + [SWITCH_LINK_FLAG_ANEG] = { .type = NLA_FLAG }, + [SWITCH_LINK_SPEED] = { .type = NLA_U32 }, +}; + static inline void swconfig_lock(void) { @@ -594,6 +610,22 @@ swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head, return 0; } +static int +swconfig_parse_link(struct sk_buff *msg, struct nlattr *nla, + struct switch_port_link *link) +{ + struct nlattr *tb[SWITCH_LINK_ATTR_MAX + 1]; + + if (nla_parse_nested(tb, SWITCH_LINK_ATTR_MAX, nla, link_policy)) + return -EINVAL; + + link->duplex = !!tb[SWITCH_LINK_FLAG_DUPLEX]; + link->aneg = !!tb[SWITCH_LINK_FLAG_ANEG]; + link->speed = nla_get_u32(tb[SWITCH_LINK_SPEED]); + + return 0; +} + static int swconfig_set_attr(struct sk_buff *skb, struct genl_info *info) { @@ -644,6 +676,21 @@ swconfig_set_attr(struct sk_buff *skb, struct genl_info *info) err = 0; } break; + case SWITCH_TYPE_LINK: + val.value.link = &dev->linkbuf; + memset(&dev->linkbuf, 0, sizeof(struct switch_port_link)); + + if (info->attrs[SWITCH_ATTR_OP_VALUE_LINK]) { + err = swconfig_parse_link(skb, + info->attrs[SWITCH_ATTR_OP_VALUE_LINK], + val.value.link); + if (err < 0) + goto error; + } else { + val.len = 0; + err = 0; + } + break; default: goto error; } diff --git a/target/linux/generic/files/include/linux/switch.h b/target/linux/generic/files/include/linux/switch.h index eac35f9135..4ada0e5d33 100644 --- a/target/linux/generic/files/include/linux/switch.h +++ b/target/linux/generic/files/include/linux/switch.h @@ -95,6 +95,8 @@ struct switch_dev_ops { int (*get_port_link)(struct switch_dev *dev, int port, struct switch_port_link *link); + int (*set_port_link)(struct switch_dev *dev, int port, + struct switch_port_link *link); int (*get_port_stats)(struct switch_dev *dev, int port, struct switch_port_stats *stats); }; -- 2.30.2