aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/team/team.c68
-rw-r--r--include/linux/if_team.h9
2 files changed, 50 insertions, 27 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 7ec53f81c1c..cff8e253df7 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -89,8 +89,7 @@ static void team_refresh_port_linkup(struct team_port *port)
89struct team_option_inst { /* One for each option instance */ 89struct team_option_inst { /* One for each option instance */
90 struct list_head list; 90 struct list_head list;
91 struct team_option *option; 91 struct team_option *option;
92 struct team_port *port; /* != NULL if per-port */ 92 struct team_option_inst_info info;
93 u32 array_index;
94 bool changed; 93 bool changed;
95 bool removed; 94 bool removed;
96}; 95};
@@ -130,6 +129,7 @@ static int __team_option_inst_add(struct team *team, struct team_option *option,
130 struct team_option_inst *opt_inst; 129 struct team_option_inst *opt_inst;
131 unsigned int array_size; 130 unsigned int array_size;
132 unsigned int i; 131 unsigned int i;
132 int err;
133 133
134 array_size = option->array_size; 134 array_size = option->array_size;
135 if (!array_size) 135 if (!array_size)
@@ -140,11 +140,17 @@ static int __team_option_inst_add(struct team *team, struct team_option *option,
140 if (!opt_inst) 140 if (!opt_inst)
141 return -ENOMEM; 141 return -ENOMEM;
142 opt_inst->option = option; 142 opt_inst->option = option;
143 opt_inst->port = port; 143 opt_inst->info.port = port;
144 opt_inst->array_index = i; 144 opt_inst->info.array_index = i;
145 opt_inst->changed = true; 145 opt_inst->changed = true;
146 opt_inst->removed = false; 146 opt_inst->removed = false;
147 list_add_tail(&opt_inst->list, &team->option_inst_list); 147 list_add_tail(&opt_inst->list, &team->option_inst_list);
148 if (option->init) {
149 err = option->init(team, &opt_inst->info);
150 if (err)
151 return err;
152 }
153
148 } 154 }
149 return 0; 155 return 0;
150} 156}
@@ -193,7 +199,7 @@ static void __team_option_inst_del_port(struct team *team,
193 199
194 list_for_each_entry_safe(opt_inst, tmp, &team->option_inst_list, list) { 200 list_for_each_entry_safe(opt_inst, tmp, &team->option_inst_list, list) {
195 if (opt_inst->option->per_port && 201 if (opt_inst->option->per_port &&
196 opt_inst->port == port) 202 opt_inst->info.port == port)
197 __team_option_inst_del(opt_inst); 203 __team_option_inst_del(opt_inst);
198 } 204 }
199} 205}
@@ -224,7 +230,7 @@ static void __team_option_inst_mark_removed_port(struct team *team,
224 struct team_option_inst *opt_inst; 230 struct team_option_inst *opt_inst;
225 231
226 list_for_each_entry(opt_inst, &team->option_inst_list, list) { 232 list_for_each_entry(opt_inst, &team->option_inst_list, list) {
227 if (opt_inst->port == port) { 233 if (opt_inst->info.port == port) {
228 opt_inst->changed = true; 234 opt_inst->changed = true;
229 opt_inst->removed = true; 235 opt_inst->removed = true;
230 } 236 }
@@ -958,39 +964,47 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx)
958static int team_port_en_option_get(struct team *team, 964static int team_port_en_option_get(struct team *team,
959 struct team_gsetter_ctx *ctx) 965 struct team_gsetter_ctx *ctx)
960{ 966{
961 ctx->data.bool_val = team_port_enabled(ctx->port); 967 struct team_port *port = ctx->info->port;
968
969 ctx->data.bool_val = team_port_enabled(port);
962 return 0; 970 return 0;
963} 971}
964 972
965static int team_port_en_option_set(struct team *team, 973static int team_port_en_option_set(struct team *team,
966 struct team_gsetter_ctx *ctx) 974 struct team_gsetter_ctx *ctx)
967{ 975{
976 struct team_port *port = ctx->info->port;
977
968 if (ctx->data.bool_val) 978 if (ctx->data.bool_val)
969 team_port_enable(team, ctx->port); 979 team_port_enable(team, port);
970 else 980 else
971 team_port_disable(team, ctx->port); 981 team_port_disable(team, port);
972 return 0; 982 return 0;
973} 983}
974 984
975static int team_user_linkup_option_get(struct team *team, 985static int team_user_linkup_option_get(struct team *team,
976 struct team_gsetter_ctx *ctx) 986 struct team_gsetter_ctx *ctx)
977{ 987{
978 ctx->data.bool_val = ctx->port->user.linkup; 988 struct team_port *port = ctx->info->port;
989
990 ctx->data.bool_val = port->user.linkup;
979 return 0; 991 return 0;
980} 992}
981 993
982static int team_user_linkup_option_set(struct team *team, 994static int team_user_linkup_option_set(struct team *team,
983 struct team_gsetter_ctx *ctx) 995 struct team_gsetter_ctx *ctx)
984{ 996{
985 ctx->port->user.linkup = ctx->data.bool_val; 997 struct team_port *port = ctx->info->port;
986 team_refresh_port_linkup(ctx->port); 998
999 port->user.linkup = ctx->data.bool_val;
1000 team_refresh_port_linkup(port);
987 return 0; 1001 return 0;
988} 1002}
989 1003
990static int team_user_linkup_en_option_get(struct team *team, 1004static int team_user_linkup_en_option_get(struct team *team,
991 struct team_gsetter_ctx *ctx) 1005 struct team_gsetter_ctx *ctx)
992{ 1006{
993 struct team_port *port = ctx->port; 1007 struct team_port *port = ctx->info->port;
994 1008
995 ctx->data.bool_val = port->user.linkup_enabled; 1009 ctx->data.bool_val = port->user.linkup_enabled;
996 return 0; 1010 return 0;
@@ -999,10 +1013,10 @@ static int team_user_linkup_en_option_get(struct team *team,
999static int team_user_linkup_en_option_set(struct team *team, 1013static int team_user_linkup_en_option_set(struct team *team,
1000 struct team_gsetter_ctx *ctx) 1014 struct team_gsetter_ctx *ctx)
1001{ 1015{
1002 struct team_port *port = ctx->port; 1016 struct team_port *port = ctx->info->port;
1003 1017
1004 port->user.linkup_enabled = ctx->data.bool_val; 1018 port->user.linkup_enabled = ctx->data.bool_val;
1005 team_refresh_port_linkup(ctx->port); 1019 team_refresh_port_linkup(port);
1006 return 0; 1020 return 0;
1007} 1021}
1008 1022
@@ -1557,6 +1571,7 @@ static int team_nl_fill_options_get(struct sk_buff *skb,
1557 list_for_each_entry(opt_inst, &team->option_inst_list, list) { 1571 list_for_each_entry(opt_inst, &team->option_inst_list, list) {
1558 struct nlattr *option_item; 1572 struct nlattr *option_item;
1559 struct team_option *option = opt_inst->option; 1573 struct team_option *option = opt_inst->option;
1574 struct team_option_inst_info *opt_inst_info;
1560 struct team_gsetter_ctx ctx; 1575 struct team_gsetter_ctx ctx;
1561 1576
1562 /* Include only changed options if fill all mode is not on */ 1577 /* Include only changed options if fill all mode is not on */
@@ -1575,16 +1590,18 @@ static int team_nl_fill_options_get(struct sk_buff *skb,
1575 if (opt_inst->removed && 1590 if (opt_inst->removed &&
1576 nla_put_flag(skb, TEAM_ATTR_OPTION_REMOVED)) 1591 nla_put_flag(skb, TEAM_ATTR_OPTION_REMOVED))
1577 goto nla_put_failure; 1592 goto nla_put_failure;
1578 if (opt_inst->port && 1593
1594 opt_inst_info = &opt_inst->info;
1595 if (opt_inst_info->port &&
1579 nla_put_u32(skb, TEAM_ATTR_OPTION_PORT_IFINDEX, 1596 nla_put_u32(skb, TEAM_ATTR_OPTION_PORT_IFINDEX,
1580 opt_inst->port->dev->ifindex)) 1597 opt_inst_info->port->dev->ifindex))
1581 goto nla_put_failure; 1598 goto nla_put_failure;
1582 ctx.port = opt_inst->port;
1583 if (opt_inst->option->array_size && 1599 if (opt_inst->option->array_size &&
1584 nla_put_u32(skb, TEAM_ATTR_OPTION_ARRAY_INDEX, 1600 nla_put_u32(skb, TEAM_ATTR_OPTION_ARRAY_INDEX,
1585 opt_inst->array_index)) 1601 opt_inst_info->array_index))
1586 goto nla_put_failure; 1602 goto nla_put_failure;
1587 ctx.array_index = opt_inst->array_index; 1603 ctx.info = opt_inst_info;
1604
1588 switch (option->type) { 1605 switch (option->type) {
1589 case TEAM_OPTION_TYPE_U32: 1606 case TEAM_OPTION_TYPE_U32:
1590 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32)) 1607 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32))
@@ -1746,19 +1763,20 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
1746 list_for_each_entry(opt_inst, &team->option_inst_list, list) { 1763 list_for_each_entry(opt_inst, &team->option_inst_list, list) {
1747 struct team_option *option = opt_inst->option; 1764 struct team_option *option = opt_inst->option;
1748 struct team_gsetter_ctx ctx; 1765 struct team_gsetter_ctx ctx;
1766 struct team_option_inst_info *opt_inst_info;
1749 int tmp_ifindex; 1767 int tmp_ifindex;
1750 1768
1751 tmp_ifindex = opt_inst->port ? 1769 opt_inst_info = &opt_inst->info;
1752 opt_inst->port->dev->ifindex : 0; 1770 tmp_ifindex = opt_inst_info->port ?
1771 opt_inst_info->port->dev->ifindex : 0;
1753 if (option->type != opt_type || 1772 if (option->type != opt_type ||
1754 strcmp(option->name, opt_name) || 1773 strcmp(option->name, opt_name) ||
1755 tmp_ifindex != opt_port_ifindex || 1774 tmp_ifindex != opt_port_ifindex ||
1756 (option->array_size && !opt_is_array) || 1775 (option->array_size && !opt_is_array) ||
1757 opt_inst->array_index != opt_array_index) 1776 opt_inst_info->array_index != opt_array_index)
1758 continue; 1777 continue;
1759 opt_found = true; 1778 opt_found = true;
1760 ctx.port = opt_inst->port; 1779 ctx.info = opt_inst_info;
1761 ctx.array_index = opt_inst->array_index;
1762 switch (opt_type) { 1780 switch (opt_type) {
1763 case TEAM_OPTION_TYPE_U32: 1781 case TEAM_OPTION_TYPE_U32:
1764 ctx.data.u32_val = nla_get_u32(attr_data); 1782 ctx.data.u32_val = nla_get_u32(attr_data);
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index b1719e239a0..30854cb0c85 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -83,6 +83,11 @@ enum team_option_type {
83 TEAM_OPTION_TYPE_BOOL, 83 TEAM_OPTION_TYPE_BOOL,
84}; 84};
85 85
86struct team_option_inst_info {
87 u32 array_index;
88 struct team_port *port; /* != NULL if per-port */
89};
90
86struct team_gsetter_ctx { 91struct team_gsetter_ctx {
87 union { 92 union {
88 u32 u32_val; 93 u32 u32_val;
@@ -93,8 +98,7 @@ struct team_gsetter_ctx {
93 } bin_val; 98 } bin_val;
94 bool bool_val; 99 bool bool_val;
95 } data; 100 } data;
96 u32 array_index; 101 struct team_option_inst_info *info;
97 struct team_port *port;
98}; 102};
99 103
100struct team_option { 104struct team_option {
@@ -103,6 +107,7 @@ struct team_option {
103 bool per_port; 107 bool per_port;
104 unsigned int array_size; /* != 0 means the option is array */ 108 unsigned int array_size; /* != 0 means the option is array */
105 enum team_option_type type; 109 enum team_option_type type;
110 int (*init)(struct team *team, struct team_option_inst_info *info);
106 int (*getter)(struct team *team, struct team_gsetter_ctx *ctx); 111 int (*getter)(struct team *team, struct team_gsetter_ctx *ctx);
107 int (*setter)(struct team *team, struct team_gsetter_ctx *ctx); 112 int (*setter)(struct team *team, struct team_gsetter_ctx *ctx);
108}; 113};