diff options
author | Jiri Pirko <jiri@resnulli.us> | 2013-06-10 11:42:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-12 06:05:53 -0400 |
commit | 6c31ff366c1116823e77019bae3e92e9d77a49f4 (patch) | |
tree | 5b296c8556264707bb6359c779270e6694c6e2a9 /drivers/net/team/team.c | |
parent | dffebd2c5cd528a136b276a2a75c56222312d7a4 (diff) |
team: remove synchronize_rcu() called during queue override change
This patch removes synchronize_rcu() from function
__team_queue_override_port_del(). That can be done because it is ok to
do list_del_rcu() and list_add_tail_rcu() on the same list_head member
without calling synchronize_rcu() in between. A bit of refactoring
needed to be done because INIT_LIST_HEAD needed to be removed (to not
kill the forward pointer) as well.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Flavio Leitner <fbl@redhat.com>
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 | 63 |
1 files changed, 47 insertions, 16 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 04e9adb748c5..9cbe09df7765 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c | |||
@@ -725,9 +725,9 @@ static bool team_queue_override_transmit(struct team *team, struct sk_buff *skb) | |||
725 | static void __team_queue_override_port_del(struct team *team, | 725 | static void __team_queue_override_port_del(struct team *team, |
726 | struct team_port *port) | 726 | struct team_port *port) |
727 | { | 727 | { |
728 | if (!port->queue_id) | ||
729 | return; | ||
728 | list_del_rcu(&port->qom_list); | 730 | list_del_rcu(&port->qom_list); |
729 | synchronize_rcu(); | ||
730 | INIT_LIST_HEAD(&port->qom_list); | ||
731 | } | 731 | } |
732 | 732 | ||
733 | static bool team_queue_override_port_has_gt_prio_than(struct team_port *port, | 733 | static bool team_queue_override_port_has_gt_prio_than(struct team_port *port, |
@@ -749,9 +749,8 @@ static void __team_queue_override_port_add(struct team *team, | |||
749 | struct list_head *qom_list; | 749 | struct list_head *qom_list; |
750 | struct list_head *node; | 750 | struct list_head *node; |
751 | 751 | ||
752 | if (!port->queue_id || !team_port_enabled(port)) | 752 | if (!port->queue_id) |
753 | return; | 753 | return; |
754 | |||
755 | qom_list = __team_get_qom_list(team, port->queue_id); | 754 | qom_list = __team_get_qom_list(team, port->queue_id); |
756 | node = qom_list; | 755 | node = qom_list; |
757 | list_for_each_entry(cur, qom_list, qom_list) { | 756 | list_for_each_entry(cur, qom_list, qom_list) { |
@@ -768,7 +767,7 @@ static void __team_queue_override_enabled_check(struct team *team) | |||
768 | bool enabled = false; | 767 | bool enabled = false; |
769 | 768 | ||
770 | list_for_each_entry(port, &team->port_list, list) { | 769 | list_for_each_entry(port, &team->port_list, list) { |
771 | if (!list_empty(&port->qom_list)) { | 770 | if (port->queue_id) { |
772 | enabled = true; | 771 | enabled = true; |
773 | break; | 772 | break; |
774 | } | 773 | } |
@@ -780,14 +779,44 @@ static void __team_queue_override_enabled_check(struct team *team) | |||
780 | team->queue_override_enabled = enabled; | 779 | team->queue_override_enabled = enabled; |
781 | } | 780 | } |
782 | 781 | ||
783 | static void team_queue_override_port_refresh(struct team *team, | 782 | static void team_queue_override_port_prio_changed(struct team *team, |
784 | struct team_port *port) | 783 | struct team_port *port) |
785 | { | 784 | { |
785 | if (!port->queue_id || team_port_enabled(port)) | ||
786 | return; | ||
786 | __team_queue_override_port_del(team, port); | 787 | __team_queue_override_port_del(team, port); |
787 | __team_queue_override_port_add(team, port); | 788 | __team_queue_override_port_add(team, port); |
788 | __team_queue_override_enabled_check(team); | 789 | __team_queue_override_enabled_check(team); |
789 | } | 790 | } |
790 | 791 | ||
792 | static void team_queue_override_port_change_queue_id(struct team *team, | ||
793 | struct team_port *port, | ||
794 | u16 new_queue_id) | ||
795 | { | ||
796 | if (team_port_enabled(port)) { | ||
797 | __team_queue_override_port_del(team, port); | ||
798 | port->queue_id = new_queue_id; | ||
799 | __team_queue_override_port_add(team, port); | ||
800 | __team_queue_override_enabled_check(team); | ||
801 | } else { | ||
802 | port->queue_id = new_queue_id; | ||
803 | } | ||
804 | } | ||
805 | |||
806 | static void team_queue_override_port_add(struct team *team, | ||
807 | struct team_port *port) | ||
808 | { | ||
809 | __team_queue_override_port_add(team, port); | ||
810 | __team_queue_override_enabled_check(team); | ||
811 | } | ||
812 | |||
813 | static void team_queue_override_port_del(struct team *team, | ||
814 | struct team_port *port) | ||
815 | { | ||
816 | __team_queue_override_port_del(team, port); | ||
817 | __team_queue_override_enabled_check(team); | ||
818 | } | ||
819 | |||
791 | 820 | ||
792 | /**************** | 821 | /**************** |
793 | * Port handling | 822 | * Port handling |
@@ -819,7 +848,7 @@ static void team_port_enable(struct team *team, | |||
819 | hlist_add_head_rcu(&port->hlist, | 848 | hlist_add_head_rcu(&port->hlist, |
820 | team_port_index_hash(team, port->index)); | 849 | team_port_index_hash(team, port->index)); |
821 | team_adjust_ops(team); | 850 | team_adjust_ops(team); |
822 | team_queue_override_port_refresh(team, port); | 851 | team_queue_override_port_add(team, port); |
823 | if (team->ops.port_enabled) | 852 | if (team->ops.port_enabled) |
824 | team->ops.port_enabled(team, port); | 853 | team->ops.port_enabled(team, port); |
825 | } | 854 | } |
@@ -848,7 +877,7 @@ static void team_port_disable(struct team *team, | |||
848 | hlist_del_rcu(&port->hlist); | 877 | hlist_del_rcu(&port->hlist); |
849 | __reconstruct_port_hlist(team, port->index); | 878 | __reconstruct_port_hlist(team, port->index); |
850 | port->index = -1; | 879 | port->index = -1; |
851 | team_queue_override_port_refresh(team, port); | 880 | team_queue_override_port_del(team, port); |
852 | __team_adjust_ops(team, team->en_port_count - 1); | 881 | __team_adjust_ops(team, team->en_port_count - 1); |
853 | /* | 882 | /* |
854 | * Wait until readers see adjusted ops. This ensures that | 883 | * Wait until readers see adjusted ops. This ensures that |
@@ -1259,9 +1288,12 @@ static int team_priority_option_set(struct team *team, | |||
1259 | struct team_gsetter_ctx *ctx) | 1288 | struct team_gsetter_ctx *ctx) |
1260 | { | 1289 | { |
1261 | struct team_port *port = ctx->info->port; | 1290 | struct team_port *port = ctx->info->port; |
1291 | s32 priority = ctx->data.s32_val; | ||
1262 | 1292 | ||
1263 | port->priority = ctx->data.s32_val; | 1293 | if (port->priority == priority) |
1264 | team_queue_override_port_refresh(team, port); | 1294 | return 0; |
1295 | port->priority = priority; | ||
1296 | team_queue_override_port_prio_changed(team, port); | ||
1265 | return 0; | 1297 | return 0; |
1266 | } | 1298 | } |
1267 | 1299 | ||
@@ -1278,17 +1310,16 @@ static int team_queue_id_option_set(struct team *team, | |||
1278 | struct team_gsetter_ctx *ctx) | 1310 | struct team_gsetter_ctx *ctx) |
1279 | { | 1311 | { |
1280 | struct team_port *port = ctx->info->port; | 1312 | struct team_port *port = ctx->info->port; |
1313 | u16 new_queue_id = ctx->data.u32_val; | ||
1281 | 1314 | ||
1282 | if (port->queue_id == ctx->data.u32_val) | 1315 | if (port->queue_id == new_queue_id) |
1283 | return 0; | 1316 | return 0; |
1284 | if (ctx->data.u32_val >= team->dev->real_num_tx_queues) | 1317 | if (new_queue_id >= team->dev->real_num_tx_queues) |
1285 | return -EINVAL; | 1318 | return -EINVAL; |
1286 | port->queue_id = ctx->data.u32_val; | 1319 | team_queue_override_port_change_queue_id(team, port, new_queue_id); |
1287 | team_queue_override_port_refresh(team, port); | ||
1288 | return 0; | 1320 | return 0; |
1289 | } | 1321 | } |
1290 | 1322 | ||
1291 | |||
1292 | static const struct team_option team_options[] = { | 1323 | static const struct team_option team_options[] = { |
1293 | { | 1324 | { |
1294 | .name = "mode", | 1325 | .name = "mode", |