diff options
author | Jiri Pirko <jiri@resnulli.us> | 2013-06-10 11:42:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-12 06:06:16 -0400 |
commit | 735d381fa57c573935d35a24ea271ec99897ac63 (patch) | |
tree | e1118f79060396214ac150339eaa6a3a1c7c2168 /drivers/net/team | |
parent | d80b35beac78b52faad2359adf6a6b14e2725e51 (diff) |
team: remove synchronize_rcu() called during port disable
Check the unlikely case of team->en_port_count == 0 before modulo
operation.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/team')
-rw-r--r-- | drivers/net/team/team.c | 20 | ||||
-rw-r--r-- | drivers/net/team/team_mode_loadbalance.c | 3 | ||||
-rw-r--r-- | drivers/net/team/team_mode_roundrobin.c | 3 |
3 files changed, 8 insertions, 18 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 488ed4f535e5..e46fef38685b 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c | |||
@@ -525,31 +525,26 @@ static void team_set_no_mode(struct team *team) | |||
525 | team->mode = &__team_no_mode; | 525 | team->mode = &__team_no_mode; |
526 | } | 526 | } |
527 | 527 | ||
528 | static void __team_adjust_ops(struct team *team, int en_port_count) | 528 | static void team_adjust_ops(struct team *team) |
529 | { | 529 | { |
530 | /* | 530 | /* |
531 | * To avoid checks in rx/tx skb paths, ensure here that non-null and | 531 | * To avoid checks in rx/tx skb paths, ensure here that non-null and |
532 | * correct ops are always set. | 532 | * correct ops are always set. |
533 | */ | 533 | */ |
534 | 534 | ||
535 | if (!en_port_count || !team_is_mode_set(team) || | 535 | if (!team->en_port_count || !team_is_mode_set(team) || |
536 | !team->mode->ops->transmit) | 536 | !team->mode->ops->transmit) |
537 | team->ops.transmit = team_dummy_transmit; | 537 | team->ops.transmit = team_dummy_transmit; |
538 | else | 538 | else |
539 | team->ops.transmit = team->mode->ops->transmit; | 539 | team->ops.transmit = team->mode->ops->transmit; |
540 | 540 | ||
541 | if (!en_port_count || !team_is_mode_set(team) || | 541 | if (!team->en_port_count || !team_is_mode_set(team) || |
542 | !team->mode->ops->receive) | 542 | !team->mode->ops->receive) |
543 | team->ops.receive = team_dummy_receive; | 543 | team->ops.receive = team_dummy_receive; |
544 | else | 544 | else |
545 | team->ops.receive = team->mode->ops->receive; | 545 | team->ops.receive = team->mode->ops->receive; |
546 | } | 546 | } |
547 | 547 | ||
548 | static void team_adjust_ops(struct team *team) | ||
549 | { | ||
550 | __team_adjust_ops(team, team->en_port_count); | ||
551 | } | ||
552 | |||
553 | /* | 548 | /* |
554 | * We can benefit from the fact that it's ensured no port is present | 549 | * We can benefit from the fact that it's ensured no port is present |
555 | * at the time of mode change. Therefore no packets are in fly so there's no | 550 | * at the time of mode change. Therefore no packets are in fly so there's no |
@@ -877,14 +872,9 @@ static void team_port_disable(struct team *team, | |||
877 | hlist_del_rcu(&port->hlist); | 872 | hlist_del_rcu(&port->hlist); |
878 | __reconstruct_port_hlist(team, port->index); | 873 | __reconstruct_port_hlist(team, port->index); |
879 | port->index = -1; | 874 | port->index = -1; |
880 | team_queue_override_port_del(team, port); | ||
881 | __team_adjust_ops(team, team->en_port_count - 1); | ||
882 | /* | ||
883 | * Wait until readers see adjusted ops. This ensures that | ||
884 | * readers never see team->en_port_count == 0 | ||
885 | */ | ||
886 | synchronize_rcu(); | ||
887 | team->en_port_count--; | 875 | team->en_port_count--; |
876 | team_queue_override_port_del(team, port); | ||
877 | team_adjust_ops(team); | ||
888 | } | 878 | } |
889 | 879 | ||
890 | #define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ | 880 | #define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ |
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c index cdc31b5ea15e..829a9cd2b4da 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c | |||
@@ -112,9 +112,8 @@ static struct team_port *lb_hash_select_tx_port(struct team *team, | |||
112 | struct sk_buff *skb, | 112 | struct sk_buff *skb, |
113 | unsigned char hash) | 113 | unsigned char hash) |
114 | { | 114 | { |
115 | int port_index; | 115 | int port_index = team_num_to_port_index(team, hash); |
116 | 116 | ||
117 | port_index = hash % team->en_port_count; | ||
118 | return team_get_port_by_index_rcu(team, port_index); | 117 | return team_get_port_by_index_rcu(team, port_index); |
119 | } | 118 | } |
120 | 119 | ||
diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c index d268e4de781b..90311c7375fb 100644 --- a/drivers/net/team/team_mode_roundrobin.c +++ b/drivers/net/team/team_mode_roundrobin.c | |||
@@ -30,7 +30,8 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb) | |||
30 | struct team_port *port; | 30 | struct team_port *port; |
31 | int port_index; | 31 | int port_index; |
32 | 32 | ||
33 | port_index = rr_priv(team)->sent_packets++ % team->en_port_count; | 33 | port_index = team_num_to_port_index(team, |
34 | rr_priv(team)->sent_packets++); | ||
34 | port = team_get_port_by_index_rcu(team, port_index); | 35 | port = team_get_port_by_index_rcu(team, port_index); |
35 | port = team_get_first_port_txable_rcu(team, port); | 36 | port = team_get_first_port_txable_rcu(team, port); |
36 | if (unlikely(!port)) | 37 | if (unlikely(!port)) |