Commit 5b2e12d5 authored by Edward Cree's avatar Edward Cree Committed by David S. Miller

sfc: bind indirect blocks for TC offload on EF100

Bind indirect blocks for recognised tunnel netdevices.
Currently these connect to a stub efx_tc_flower() that only returns
 -EOPNOTSUPP; subsequent patches will implement flower offloads to the
 Match-Action Engine.
Signed-off-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9dc0cad2
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include "tc.h" #include "tc.h"
#include "tc_bindings.h"
#include "mae.h" #include "mae.h"
#include "ef100_rep.h" #include "ef100_rep.h"
#include "efx.h" #include "efx.h"
...@@ -217,6 +218,9 @@ int efx_init_tc(struct efx_nic *efx) ...@@ -217,6 +218,9 @@ int efx_init_tc(struct efx_nic *efx)
if (rc) if (rc)
return rc; return rc;
efx->tc->up = true; efx->tc->up = true;
rc = flow_indr_dev_register(efx_tc_indr_setup_cb, efx);
if (rc)
return rc;
return 0; return 0;
} }
...@@ -225,6 +229,8 @@ void efx_fini_tc(struct efx_nic *efx) ...@@ -225,6 +229,8 @@ void efx_fini_tc(struct efx_nic *efx)
/* We can get called even if efx_init_struct_tc() failed */ /* We can get called even if efx_init_struct_tc() failed */
if (!efx->tc) if (!efx->tc)
return; return;
if (efx->tc->up)
flow_indr_dev_unregister(efx_tc_indr_setup_cb, efx, efx_tc_block_unbind);
efx_tc_deconfigure_rep_mport(efx); efx_tc_deconfigure_rep_mport(efx);
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf); efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf);
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire); efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire);
......
...@@ -46,7 +46,7 @@ static int efx_tc_block_cb(enum tc_setup_type type, void *type_data, ...@@ -46,7 +46,7 @@ static int efx_tc_block_cb(enum tc_setup_type type, void *type_data,
} }
} }
static void efx_tc_block_unbind(void *cb_priv) void efx_tc_block_unbind(void *cb_priv)
{ {
struct efx_tc_block_binding *binding = cb_priv; struct efx_tc_block_binding *binding = cb_priv;
...@@ -135,6 +135,77 @@ int efx_tc_setup_block(struct net_device *net_dev, struct efx_nic *efx, ...@@ -135,6 +135,77 @@ int efx_tc_setup_block(struct net_device *net_dev, struct efx_nic *efx,
} }
} }
int efx_tc_indr_setup_cb(struct net_device *net_dev, struct Qdisc *sch,
void *cb_priv, enum tc_setup_type type,
void *type_data, void *data,
void (*cleanup)(struct flow_block_cb *block_cb))
{
struct flow_block_offload *tcb = type_data;
struct efx_tc_block_binding *binding;
struct flow_block_cb *block_cb;
struct efx_nic *efx = cb_priv;
bool is_ovs_int_port;
int rc;
if (!net_dev)
return -EOPNOTSUPP;
if (tcb->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
tcb->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
return -EOPNOTSUPP;
is_ovs_int_port = netif_is_ovs_master(net_dev);
if (tcb->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
!is_ovs_int_port)
return -EOPNOTSUPP;
if (is_ovs_int_port)
return -EOPNOTSUPP;
switch (type) {
case TC_SETUP_BLOCK:
switch (tcb->command) {
case FLOW_BLOCK_BIND:
binding = efx_tc_create_binding(efx, NULL, net_dev, tcb->block);
if (IS_ERR(binding))
return PTR_ERR(binding);
block_cb = flow_indr_block_cb_alloc(efx_tc_block_cb, binding,
binding, efx_tc_block_unbind,
tcb, net_dev, sch, data, binding,
cleanup);
rc = PTR_ERR_OR_ZERO(block_cb);
netif_dbg(efx, drv, efx->net_dev,
"bind indr block for device %s, rc %d\n",
net_dev ? net_dev->name : NULL, rc);
if (rc) {
list_del(&binding->list);
kfree(binding);
} else {
flow_block_cb_add(block_cb, tcb);
}
return rc;
case FLOW_BLOCK_UNBIND:
binding = efx_tc_find_binding(efx, net_dev);
if (!binding)
return -ENOENT;
block_cb = flow_block_cb_lookup(tcb->block,
efx_tc_block_cb,
binding);
if (!block_cb)
return -ENOENT;
flow_indr_block_cb_remove(block_cb, tcb);
netif_dbg(efx, drv, efx->net_dev,
"unbind indr block for device %s\n",
net_dev ? net_dev->name : NULL);
return 0;
default:
return -EOPNOTSUPP;
}
default:
return -EOPNOTSUPP;
}
}
/* .ndo_setup_tc implementation /* .ndo_setup_tc implementation
* Entry point for flower block and filter management. * Entry point for flower block and filter management.
*/ */
......
...@@ -16,8 +16,14 @@ ...@@ -16,8 +16,14 @@
struct efx_rep; struct efx_rep;
void efx_tc_block_unbind(void *cb_priv);
int efx_tc_setup_block(struct net_device *net_dev, struct efx_nic *efx, int efx_tc_setup_block(struct net_device *net_dev, struct efx_nic *efx,
struct flow_block_offload *tcb, struct efx_rep *efv); struct flow_block_offload *tcb, struct efx_rep *efv);
int efx_tc_setup(struct net_device *net_dev, enum tc_setup_type type, int efx_tc_setup(struct net_device *net_dev, enum tc_setup_type type,
void *type_data); void *type_data);
int efx_tc_indr_setup_cb(struct net_device *net_dev, struct Qdisc *sch,
void *cb_priv, enum tc_setup_type type,
void *type_data, void *data,
void (*cleanup)(struct flow_block_cb *block_cb));
#endif /* EFX_TC_BINDINGS_H */ #endif /* EFX_TC_BINDINGS_H */
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