diff options
-rw-r--r-- | drivers/net/team/team.c | 72 | ||||
-rw-r--r-- | include/linux/if_team.h | 26 |
2 files changed, 81 insertions, 17 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 2645fae26d6f..e639abecd14f 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c | |||
@@ -76,6 +76,11 @@ int team_port_set_team_mac(struct team_port *port) | |||
76 | } | 76 | } |
77 | EXPORT_SYMBOL(team_port_set_team_mac); | 77 | EXPORT_SYMBOL(team_port_set_team_mac); |
78 | 78 | ||
79 | static void team_refresh_port_linkup(struct team_port *port) | ||
80 | { | ||
81 | port->linkup = port->user.linkup_enabled ? port->user.linkup : | ||
82 | port->state.linkup; | ||
83 | } | ||
79 | 84 | ||
80 | /******************* | 85 | /******************* |
81 | * Options handling | 86 | * Options handling |
@@ -880,6 +885,40 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) | |||
880 | return team_change_mode(team, ctx->data.str_val); | 885 | return team_change_mode(team, ctx->data.str_val); |
881 | } | 886 | } |
882 | 887 | ||
888 | static int team_user_linkup_option_get(struct team *team, | ||
889 | struct team_gsetter_ctx *ctx) | ||
890 | { | ||
891 | ctx->data.bool_val = ctx->port->user.linkup; | ||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | static int team_user_linkup_option_set(struct team *team, | ||
896 | struct team_gsetter_ctx *ctx) | ||
897 | { | ||
898 | ctx->port->user.linkup = ctx->data.bool_val; | ||
899 | team_refresh_port_linkup(ctx->port); | ||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static int team_user_linkup_en_option_get(struct team *team, | ||
904 | struct team_gsetter_ctx *ctx) | ||
905 | { | ||
906 | struct team_port *port = ctx->port; | ||
907 | |||
908 | ctx->data.bool_val = port->user.linkup_enabled; | ||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | static int team_user_linkup_en_option_set(struct team *team, | ||
913 | struct team_gsetter_ctx *ctx) | ||
914 | { | ||
915 | struct team_port *port = ctx->port; | ||
916 | |||
917 | port->user.linkup_enabled = ctx->data.bool_val; | ||
918 | team_refresh_port_linkup(ctx->port); | ||
919 | return 0; | ||
920 | } | ||
921 | |||
883 | static const struct team_option team_options[] = { | 922 | static const struct team_option team_options[] = { |
884 | { | 923 | { |
885 | .name = "mode", | 924 | .name = "mode", |
@@ -887,6 +926,20 @@ static const struct team_option team_options[] = { | |||
887 | .getter = team_mode_option_get, | 926 | .getter = team_mode_option_get, |
888 | .setter = team_mode_option_set, | 927 | .setter = team_mode_option_set, |
889 | }, | 928 | }, |
929 | { | ||
930 | .name = "user_linkup", | ||
931 | .type = TEAM_OPTION_TYPE_BOOL, | ||
932 | .per_port = true, | ||
933 | .getter = team_user_linkup_option_get, | ||
934 | .setter = team_user_linkup_option_set, | ||
935 | }, | ||
936 | { | ||
937 | .name = "user_linkup_enabled", | ||
938 | .type = TEAM_OPTION_TYPE_BOOL, | ||
939 | .per_port = true, | ||
940 | .getter = team_user_linkup_en_option_get, | ||
941 | .setter = team_user_linkup_en_option_set, | ||
942 | }, | ||
890 | }; | 943 | }; |
891 | 944 | ||
892 | static int team_init(struct net_device *dev) | 945 | static int team_init(struct net_device *dev) |
@@ -1670,10 +1723,10 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, | |||
1670 | } | 1723 | } |
1671 | if ((port->removed && | 1724 | if ((port->removed && |
1672 | nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || | 1725 | nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || |
1673 | (port->linkup && | 1726 | (port->state.linkup && |
1674 | nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || | 1727 | nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || |
1675 | nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->speed) || | 1728 | nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->state.speed) || |
1676 | nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex)) | 1729 | nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->state.duplex)) |
1677 | goto nla_put_failure; | 1730 | goto nla_put_failure; |
1678 | nla_nest_end(skb, port_item); | 1731 | nla_nest_end(skb, port_item); |
1679 | } | 1732 | } |
@@ -1833,23 +1886,24 @@ static void __team_port_change_check(struct team_port *port, bool linkup) | |||
1833 | { | 1886 | { |
1834 | int err; | 1887 | int err; |
1835 | 1888 | ||
1836 | if (!port->removed && port->linkup == linkup) | 1889 | if (!port->removed && port->state.linkup == linkup) |
1837 | return; | 1890 | return; |
1838 | 1891 | ||
1839 | port->changed = true; | 1892 | port->changed = true; |
1840 | port->linkup = linkup; | 1893 | port->state.linkup = linkup; |
1894 | team_refresh_port_linkup(port); | ||
1841 | if (linkup) { | 1895 | if (linkup) { |
1842 | struct ethtool_cmd ecmd; | 1896 | struct ethtool_cmd ecmd; |
1843 | 1897 | ||
1844 | err = __ethtool_get_settings(port->dev, &ecmd); | 1898 | err = __ethtool_get_settings(port->dev, &ecmd); |
1845 | if (!err) { | 1899 | if (!err) { |
1846 | port->speed = ethtool_cmd_speed(&ecmd); | 1900 | port->state.speed = ethtool_cmd_speed(&ecmd); |
1847 | port->duplex = ecmd.duplex; | 1901 | port->state.duplex = ecmd.duplex; |
1848 | goto send_event; | 1902 | goto send_event; |
1849 | } | 1903 | } |
1850 | } | 1904 | } |
1851 | port->speed = 0; | 1905 | port->state.speed = 0; |
1852 | port->duplex = 0; | 1906 | port->state.duplex = 0; |
1853 | 1907 | ||
1854 | send_event: | 1908 | send_event: |
1855 | err = team_nl_send_event_port_list_get(port->team); | 1909 | err = team_nl_send_event_port_list_get(port->team); |
diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 78c84fd9a170..5fd5ab171165 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h | |||
@@ -33,6 +33,24 @@ struct team_port { | |||
33 | struct team *team; | 33 | struct team *team; |
34 | int index; | 34 | int index; |
35 | 35 | ||
36 | bool linkup; /* either state.linkup or user.linkup */ | ||
37 | |||
38 | struct { | ||
39 | bool linkup; | ||
40 | u32 speed; | ||
41 | u8 duplex; | ||
42 | } state; | ||
43 | |||
44 | /* Values set by userspace */ | ||
45 | struct { | ||
46 | bool linkup; | ||
47 | bool linkup_enabled; | ||
48 | } user; | ||
49 | |||
50 | /* Custom gennetlink interface related flags */ | ||
51 | bool changed; | ||
52 | bool removed; | ||
53 | |||
36 | /* | 54 | /* |
37 | * A place for storing original values of the device before it | 55 | * A place for storing original values of the device before it |
38 | * become a port. | 56 | * become a port. |
@@ -42,14 +60,6 @@ struct team_port { | |||
42 | unsigned int mtu; | 60 | unsigned int mtu; |
43 | } orig; | 61 | } orig; |
44 | 62 | ||
45 | bool linkup; | ||
46 | u32 speed; | ||
47 | u8 duplex; | ||
48 | |||
49 | /* Custom gennetlink interface related flags */ | ||
50 | bool changed; | ||
51 | bool removed; | ||
52 | |||
53 | struct rcu_head rcu; | 63 | struct rcu_head rcu; |
54 | }; | 64 | }; |
55 | 65 | ||