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: Edward Cree <ecree.xilinx@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9dc0cad203
commit
5b2e12d51b
|
@ -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)
|
||||||
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)
|
||||||
/* 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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 @@
|
||||||
|
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in New Issue