diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2016-01-06 18:32:21 +0000 |
---|---|---|
committer | Rafał Miłecki <zajec5@gmail.com> | 2016-01-06 18:32:21 +0000 |
commit | 5f69279dd608b54807714716cb9ff9e39f2e72c5 (patch) | |
tree | 69c4c2add0659077461d5118e2718b17edc07cba | |
parent | a09e713299e3490866b9ce38558de14849d80e3b (diff) | |
download | upstream-5f69279dd608b54807714716cb9ff9e39f2e72c5.tar.gz upstream-5f69279dd608b54807714716cb9ff9e39f2e72c5.tar.bz2 upstream-5f69279dd608b54807714716cb9ff9e39f2e72c5.zip |
swconfig: add API for setting port link speed
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 <zajec5@gmail.com>
SVN-Revision: 48142
-rw-r--r-- | target/linux/generic/files/drivers/net/phy/swconfig.c | 49 | ||||
-rw-r--r-- | target/linux/generic/files/include/linux/switch.h | 2 |
2 files changed, 50 insertions, 1 deletions
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 @@ -128,6 +128,16 @@ swconfig_get_pvid(struct switch_dev *dev, const struct switch_attr *attr, } 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) { @@ -595,6 +611,22 @@ swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head, } 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) { const struct switch_attr *attr; @@ -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); }; |