diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/flow_offload.c | 18 | ||||
-rw-r--r-- | net/dsa/slave.c | 3 |
2 files changed, 21 insertions, 0 deletions
diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c index a1b36b47dd89..76f8db3841d7 100644 --- a/net/core/flow_offload.c +++ b/net/core/flow_offload.c @@ -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)) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 90c32fd680db..9bcb598fc840 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -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); |