aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2013-06-10 11:42:23 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-12 06:05:53 -0400
commit6c31ff366c1116823e77019bae3e92e9d77a49f4 (patch)
tree5b296c8556264707bb6359c779270e6694c6e2a9 /drivers
parentdffebd2c5cd528a136b276a2a75c56222312d7a4 (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')
-rw-r--r--drivers/net/team/team.c63
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)
725static void __team_queue_override_port_del(struct team *team, 725static 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
733static bool team_queue_override_port_has_gt_prio_than(struct team_port *port, 733static 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
783static void team_queue_override_port_refresh(struct team *team, 782static 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
792static 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
806static 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
813static 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
1292static const struct team_option team_options[] = { 1323static const struct team_option team_options[] = {
1293 { 1324 {
1294 .name = "mode", 1325 .name = "mode",