Commit 0d4fd02e authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by David S. Miller

net: flow_offload: add flow_block_cb_is_busy() and use it

This patch adds a function to check if flow block callback is already in
use.  Call this new function from flow_block_cb_setup_simple() and from
drivers.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 722d36e6
......@@ -722,6 +722,10 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
if (indr_priv)
return -EEXIST;
if (flow_block_cb_is_busy(mlx5e_rep_indr_setup_block_cb,
indr_priv, &mlx5e_block_cb_list))
return -EBUSY;
indr_priv = kmalloc(sizeof(*indr_priv), GFP_KERNEL);
if (!indr_priv)
return -ENOMEM;
......
......@@ -1698,6 +1698,10 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
switch (f->command) {
case FLOW_BLOCK_BIND:
if (flow_block_cb_is_busy(cb, mlxsw_sp_port,
&mlxsw_sp_block_cb_list))
return -EBUSY;
block_cb = flow_block_cb_alloc(f->net, cb, mlxsw_sp_port,
mlxsw_sp_port, NULL);
if (IS_ERR(block_cb))
......
......@@ -153,6 +153,9 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
switch (f->command) {
case FLOW_BLOCK_BIND:
if (flow_block_cb_is_busy(cb, port, &ocelot_block_cb_list))
return -EBUSY;
block_cb = flow_block_cb_alloc(f->net, cb, port, port, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
......
......@@ -1320,6 +1320,10 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
switch (f->command) {
case FLOW_BLOCK_BIND:
if (flow_block_cb_is_busy(nfp_flower_setup_tc_block_cb, repr,
&nfp_block_cb_list))
return -EBUSY;
block_cb = flow_block_cb_alloc(f->net,
nfp_flower_setup_tc_block_cb,
repr, repr, NULL);
......
......@@ -296,6 +296,9 @@ static inline void flow_block_cb_remove(struct flow_block_cb *block_cb,
list_move(&block_cb->list, &offload->cb_list);
}
bool flow_block_cb_is_busy(tc_setup_cb_t *cb, void *cb_ident,
struct list_head *driver_block_list);
int flow_block_cb_setup_simple(struct flow_block_offload *f,
struct list_head *driver_list, tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv, bool ingress_only);
......
......@@ -228,6 +228,21 @@ unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb)
}
EXPORT_SYMBOL(flow_block_cb_decref);
bool flow_block_cb_is_busy(tc_setup_cb_t *cb, void *cb_ident,
struct list_head *driver_block_list)
{
struct flow_block_cb *block_cb;
list_for_each_entry(block_cb, driver_block_list, driver_list) {
if (block_cb->cb == cb &&
block_cb->cb_ident == cb_ident)
return true;
}
return false;
}
EXPORT_SYMBOL(flow_block_cb_is_busy);
int flow_block_cb_setup_simple(struct flow_block_offload *f,
struct list_head *driver_block_list,
tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
......@@ -243,6 +258,9 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f,
switch (f->command) {
case FLOW_BLOCK_BIND:
if (flow_block_cb_is_busy(cb, cb_ident, driver_block_list))
return -EBUSY;
block_cb = flow_block_cb_alloc(f->net, cb, cb_ident,
cb_priv, NULL);
if (IS_ERR(block_cb))
......
......@@ -961,6 +961,9 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
switch (f->command) {
case FLOW_BLOCK_BIND:
if (flow_block_cb_is_busy(cb, dev, &dsa_slave_block_cb_list))
return -EBUSY;
block_cb = flow_block_cb_alloc(f->net, cb, dev, dev, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment