diff options
Diffstat (limited to 'drivers/net/team/team_mode_loadbalance.c')
| -rw-r--r-- | drivers/net/team/team_mode_loadbalance.c | 92 |
1 files changed, 46 insertions, 46 deletions
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c index 1468ddf424cc..b14538bde2f8 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -1,11 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * drivers/net/team/team_mode_loadbalance.c - Load-balancing mode for team * Copyright (c) 2012 Jiri Pirko <jpirko@redhat.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/kernel.h> @@ -34,8 +30,6 @@ static rx_handler_result_t lb_receive(struct team *team, struct team_port *port, struct lb_priv; typedef struct team_port *lb_select_tx_port_func_t(struct team *, - struct lb_priv *, - struct sk_buff *, unsigned char); #define LB_TX_HASHTABLE_SIZE 256 /* hash is a char */ @@ -122,8 +116,6 @@ static void lb_tx_hash_to_port_mapping_null_port(struct team *team, /* Basic tx selection based solely by hash */ static struct team_port *lb_hash_select_tx_port(struct team *team, - struct lb_priv *lb_priv, - struct sk_buff *skb, unsigned char hash) { int port_index = team_num_to_port_index(team, hash); @@ -133,11 +125,16 @@ static struct team_port *lb_hash_select_tx_port(struct team *team, /* Hash to port mapping select tx port */ static struct team_port *lb_htpm_select_tx_port(struct team *team, - struct lb_priv *lb_priv, - struct sk_buff *skb, unsigned char hash) { - return rcu_dereference_bh(LB_HTPM_PORT_BY_HASH(lb_priv, hash)); + struct lb_priv *lb_priv = get_lb_priv(team); + struct team_port *port; + + port = rcu_dereference_bh(LB_HTPM_PORT_BY_HASH(lb_priv, hash)); + if (likely(port)) + return port; + /* If no valid port in the table, fall back to simple hash */ + return lb_hash_select_tx_port(team, hash); } struct lb_select_tx_port { @@ -195,7 +192,7 @@ static unsigned int lb_get_skb_hash(struct lb_priv *lb_priv, fp = rcu_dereference_bh(lb_priv->fp); if (unlikely(!fp)) return 0; - lhash = BPF_PROG_RUN(fp, skb); + lhash = bpf_prog_run(fp, skb); c = (char *) &lhash; return c[0] ^ c[1] ^ c[2] ^ c[3]; } @@ -227,7 +224,7 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb) hash = lb_get_skb_hash(lb_priv, skb); select_tx_port_func = rcu_dereference_bh(lb_priv->select_tx_port_func); - port = select_tx_port_func(team, lb_priv, skb, hash); + port = select_tx_port_func(team, hash); if (unlikely(!port)) goto drop; if (team_dev_queue_xmit(team, port, skb)) @@ -240,19 +237,18 @@ drop: return false; } -static int lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx) +static void lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); if (!lb_priv->ex->orig_fprog) { ctx->data.bin_val.len = 0; ctx->data.bin_val.ptr = NULL; - return 0; + return; } ctx->data.bin_val.len = lb_priv->ex->orig_fprog->len * sizeof(struct sock_filter); ctx->data.bin_val.ptr = lb_priv->ex->orig_fprog->filter; - return 0; } static int __fprog_create(struct sock_fprog_kern **pfprog, u32 data_len, @@ -305,8 +301,7 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx) if (lb_priv->ex->orig_fprog) { /* Clear old filter data */ __fprog_destroy(lb_priv->ex->orig_fprog); - orig_fp = rcu_dereference_protected(lb_priv->fp, - lockdep_is_held(&team->lock)); + orig_fp = rtnl_dereference(lb_priv->fp); } rcu_assign_pointer(lb_priv->fp, fp); @@ -319,18 +314,29 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx) return 0; } -static int lb_tx_method_get(struct team *team, struct team_gsetter_ctx *ctx) +static void lb_bpf_func_free(struct team *team) +{ + struct lb_priv *lb_priv = get_lb_priv(team); + struct bpf_prog *fp; + + if (!lb_priv->ex->orig_fprog) + return; + + __fprog_destroy(lb_priv->ex->orig_fprog); + fp = rtnl_dereference(lb_priv->fp); + bpf_prog_destroy(fp); +} + +static void lb_tx_method_get(struct team *team, struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); lb_select_tx_port_func_t *func; char *name; - func = rcu_dereference_protected(lb_priv->select_tx_port_func, - lockdep_is_held(&team->lock)); + func = rtnl_dereference(lb_priv->select_tx_port_func); name = lb_select_tx_port_get_name(func); BUG_ON(!name); ctx->data.str_val = name; - return 0; } static int lb_tx_method_set(struct team *team, struct team_gsetter_ctx *ctx) @@ -345,18 +351,17 @@ static int lb_tx_method_set(struct team *team, struct team_gsetter_ctx *ctx) return 0; } -static int lb_tx_hash_to_port_mapping_init(struct team *team, - struct team_option_inst_info *info) +static void lb_tx_hash_to_port_mapping_init(struct team *team, + struct team_option_inst_info *info) { struct lb_priv *lb_priv = get_lb_priv(team); unsigned char hash = info->array_index; LB_HTPM_OPT_INST_INFO_BY_HASH(lb_priv, hash) = info; - return 0; } -static int lb_tx_hash_to_port_mapping_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void lb_tx_hash_to_port_mapping_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); struct team_port *port; @@ -364,7 +369,6 @@ static int lb_tx_hash_to_port_mapping_get(struct team *team, port = LB_HTPM_PORT_BY_HASH(lb_priv, hash); ctx->data.u32_val = port ? port->dev->ifindex : 0; - return 0; } static int lb_tx_hash_to_port_mapping_set(struct team *team, @@ -385,44 +389,40 @@ static int lb_tx_hash_to_port_mapping_set(struct team *team, return -ENODEV; } -static int lb_hash_stats_init(struct team *team, - struct team_option_inst_info *info) +static void lb_hash_stats_init(struct team *team, + struct team_option_inst_info *info) { struct lb_priv *lb_priv = get_lb_priv(team); unsigned char hash = info->array_index; lb_priv->ex->stats.info[hash].opt_inst_info = info; - return 0; } -static int lb_hash_stats_get(struct team *team, struct team_gsetter_ctx *ctx) +static void lb_hash_stats_get(struct team *team, struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); unsigned char hash = ctx->info->array_index; ctx->data.bin_val.ptr = &lb_priv->ex->stats.info[hash].stats; ctx->data.bin_val.len = sizeof(struct lb_stats); - return 0; } -static int lb_port_stats_init(struct team *team, - struct team_option_inst_info *info) +static void lb_port_stats_init(struct team *team, + struct team_option_inst_info *info) { struct team_port *port = info->port; struct lb_port_priv *lb_port_priv = get_lb_port_priv(port); lb_port_priv->stats_info.opt_inst_info = info; - return 0; } -static int lb_port_stats_get(struct team *team, struct team_gsetter_ctx *ctx) +static void lb_port_stats_get(struct team *team, struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; struct lb_port_priv *lb_port_priv = get_lb_port_priv(port); ctx->data.bin_val.ptr = &lb_port_priv->stats_info.stats; ctx->data.bin_val.len = sizeof(struct lb_stats); - return 0; } static void __lb_stats_info_refresh_prepare(struct lb_stats_info *s_info) @@ -450,9 +450,9 @@ static void __lb_one_cpu_stats_add(struct lb_stats *acc_stats, struct lb_stats tmp; do { - start = u64_stats_fetch_begin_irq(syncp); + start = u64_stats_fetch_begin(syncp); tmp.tx_bytes = cpu_stats->tx_bytes; - } while (u64_stats_fetch_retry_irq(syncp, start)); + } while (u64_stats_fetch_retry(syncp, start)); acc_stats->tx_bytes += tmp.tx_bytes; } @@ -475,7 +475,7 @@ static void lb_stats_refresh(struct work_struct *work) team = lb_priv_ex->team; lb_priv = get_lb_priv(team); - if (!mutex_trylock(&team->lock)) { + if (!rtnl_trylock()) { schedule_delayed_work(&lb_priv_ex->stats.refresh_dw, 0); return; } @@ -512,16 +512,15 @@ static void lb_stats_refresh(struct work_struct *work) schedule_delayed_work(&lb_priv_ex->stats.refresh_dw, (lb_priv_ex->stats.refresh_interval * HZ) / 10); - mutex_unlock(&team->lock); + rtnl_unlock(); } -static int lb_stats_refresh_interval_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void lb_stats_refresh_interval_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); ctx->data.u32_val = lb_priv->ex->stats.refresh_interval; - return 0; } static int lb_stats_refresh_interval_set(struct team *team, @@ -633,6 +632,7 @@ static void lb_exit(struct team *team) team_options_unregister(team, lb_options, ARRAY_SIZE(lb_options)); + lb_bpf_func_free(team); cancel_delayed_work_sync(&lb_priv->ex->stats.refresh_dw); free_percpu(lb_priv->pcpu_stats); kfree(lb_priv->ex); |
