Commit 5a6ff4b1 authored by Vlad Buslov's avatar Vlad Buslov Committed by David S. Miller

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: default avatarVlad Buslov <vladbu@mellanox.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9838b20a
...@@ -505,6 +505,8 @@ tcf_match_indev(struct sk_buff *skb, int ifindex) ...@@ -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, ...@@ -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, ...@@ -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 @@ int tc_setup_flow_action(struct flow_action *flow_action, ...@@ -3410,6 +3439,9 @@ int tc_setup_flow_action(struct flow_action *flow_action,
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, ...@@ -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, ...@@ -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) {
......
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