net: sched: take reference to action dev before calling offloads
In order to remove dependency on rtnl lock when calling hardware offload API, take reference to action mirred dev when initializing flow_action structure in tc_setup_flow_action(). Implement function tc_cleanup_flow_action(), use it to release the device after hardware offload API is done using it. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9838b20a7f
commit
5a6ff4b13d
@ -505,6 +505,8 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)
|
|||||||
|
|
||||||
int tc_setup_flow_action(struct flow_action *flow_action,
|
int tc_setup_flow_action(struct flow_action *flow_action,
|
||||||
const struct tcf_exts *exts, bool rtnl_held);
|
const struct tcf_exts *exts, bool rtnl_held);
|
||||||
|
void tc_cleanup_flow_action(struct flow_action *flow_action);
|
||||||
|
|
||||||
int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
|
int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
|
||||||
void *type_data, bool err_stop, bool rtnl_held);
|
void *type_data, bool err_stop, bool rtnl_held);
|
||||||
int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp,
|
int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp,
|
||||||
|
@ -3265,6 +3265,27 @@ int tc_setup_cb_reoffload(struct tcf_block *block, struct tcf_proto *tp,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tc_setup_cb_reoffload);
|
EXPORT_SYMBOL(tc_setup_cb_reoffload);
|
||||||
|
|
||||||
|
void tc_cleanup_flow_action(struct flow_action *flow_action)
|
||||||
|
{
|
||||||
|
struct flow_action_entry *entry;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
flow_action_for_each(i, entry, flow_action) {
|
||||||
|
switch (entry->id) {
|
||||||
|
case FLOW_ACTION_REDIRECT:
|
||||||
|
case FLOW_ACTION_MIRRED:
|
||||||
|
case FLOW_ACTION_REDIRECT_INGRESS:
|
||||||
|
case FLOW_ACTION_MIRRED_INGRESS:
|
||||||
|
if (entry->dev)
|
||||||
|
dev_put(entry->dev);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tc_cleanup_flow_action);
|
||||||
|
|
||||||
int tc_setup_flow_action(struct flow_action *flow_action,
|
int tc_setup_flow_action(struct flow_action *flow_action,
|
||||||
const struct tcf_exts *exts, bool rtnl_held)
|
const struct tcf_exts *exts, bool rtnl_held)
|
||||||
{
|
{
|
||||||
@ -3294,15 +3315,23 @@ int tc_setup_flow_action(struct flow_action *flow_action,
|
|||||||
} else if (is_tcf_mirred_egress_redirect(act)) {
|
} else if (is_tcf_mirred_egress_redirect(act)) {
|
||||||
entry->id = FLOW_ACTION_REDIRECT;
|
entry->id = FLOW_ACTION_REDIRECT;
|
||||||
entry->dev = tcf_mirred_dev(act);
|
entry->dev = tcf_mirred_dev(act);
|
||||||
|
if (entry->dev)
|
||||||
|
dev_hold(entry->dev);
|
||||||
} else if (is_tcf_mirred_egress_mirror(act)) {
|
} else if (is_tcf_mirred_egress_mirror(act)) {
|
||||||
entry->id = FLOW_ACTION_MIRRED;
|
entry->id = FLOW_ACTION_MIRRED;
|
||||||
entry->dev = tcf_mirred_dev(act);
|
entry->dev = tcf_mirred_dev(act);
|
||||||
|
if (entry->dev)
|
||||||
|
dev_hold(entry->dev);
|
||||||
} else if (is_tcf_mirred_ingress_redirect(act)) {
|
} else if (is_tcf_mirred_ingress_redirect(act)) {
|
||||||
entry->id = FLOW_ACTION_REDIRECT_INGRESS;
|
entry->id = FLOW_ACTION_REDIRECT_INGRESS;
|
||||||
entry->dev = tcf_mirred_dev(act);
|
entry->dev = tcf_mirred_dev(act);
|
||||||
|
if (entry->dev)
|
||||||
|
dev_hold(entry->dev);
|
||||||
} else if (is_tcf_mirred_ingress_mirror(act)) {
|
} else if (is_tcf_mirred_ingress_mirror(act)) {
|
||||||
entry->id = FLOW_ACTION_MIRRED_INGRESS;
|
entry->id = FLOW_ACTION_MIRRED_INGRESS;
|
||||||
entry->dev = tcf_mirred_dev(act);
|
entry->dev = tcf_mirred_dev(act);
|
||||||
|
if (entry->dev)
|
||||||
|
dev_hold(entry->dev);
|
||||||
} else if (is_tcf_vlan(act)) {
|
} else if (is_tcf_vlan(act)) {
|
||||||
switch (tcf_vlan_action(act)) {
|
switch (tcf_vlan_action(act)) {
|
||||||
case TCA_VLAN_ACT_PUSH:
|
case TCA_VLAN_ACT_PUSH:
|
||||||
@ -3410,6 +3439,9 @@ err_out:
|
|||||||
if (!rtnl_held)
|
if (!rtnl_held)
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
tc_cleanup_flow_action(flow_action);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tc_setup_flow_action);
|
EXPORT_SYMBOL(tc_setup_flow_action);
|
||||||
|
@ -465,6 +465,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
|
|||||||
|
|
||||||
err = tc_setup_cb_add(block, tp, TC_SETUP_CLSFLOWER, &cls_flower,
|
err = tc_setup_cb_add(block, tp, TC_SETUP_CLSFLOWER, &cls_flower,
|
||||||
skip_sw, &f->flags, &f->in_hw_count, true);
|
skip_sw, &f->flags, &f->in_hw_count, true);
|
||||||
|
tc_cleanup_flow_action(&cls_flower.rule->action);
|
||||||
kfree(cls_flower.rule);
|
kfree(cls_flower.rule);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -1838,6 +1839,7 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
|
|||||||
TC_SETUP_CLSFLOWER, &cls_flower,
|
TC_SETUP_CLSFLOWER, &cls_flower,
|
||||||
cb_priv, &f->flags,
|
cb_priv, &f->flags,
|
||||||
&f->in_hw_count);
|
&f->in_hw_count);
|
||||||
|
tc_cleanup_flow_action(&cls_flower.rule->action);
|
||||||
kfree(cls_flower.rule);
|
kfree(cls_flower.rule);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
Loading…
Reference in New Issue
Block a user