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/team.c | |
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/team.c')
-rw-r--r-- | drivers/net/team/team.c | 20 |
1 files changed, 5 insertions, 15 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 | \ |