diff options
author | Edward Cree <ecree.xilinx@gmail.com> | 2022-09-26 21:57:32 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-09-28 11:43:22 +0300 |
commit | 5b2e12d51bd8efaf0be8309d5b2c716ad848cb37 (patch) | |
tree | 0193b6642f02ac4e46d839d9257c3ba51f278de0 /drivers | |
parent | 9dc0cad203ab57efac34e6bcb67635edf3b62ebf (diff) | |
download | linux-5b2e12d51bd8efaf0be8309d5b2c716ad848cb37.tar.xz |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/sfc/tc.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/tc_bindings.c | 73 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/tc_bindings.h | 6 |
3 files changed, 84 insertions, 1 deletions
diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 23c4325e739a..cb7f76c74e66 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -10,6 +10,7 @@ */ #include "tc.h" +#include "tc_bindings.h" #include "mae.h" #include "ef100_rep.h" #include "efx.h" @@ -217,6 +218,9 @@ int efx_init_tc(struct efx_nic *efx) if (rc) return rc; efx->tc->up = true; + rc = flow_indr_dev_register(efx_tc_indr_setup_cb, efx); + if (rc) + return rc; 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 */ if (!efx->tc) 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_default_rule(efx, &efx->tc->dflt.pf); efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire); diff --git a/drivers/net/ethernet/sfc/tc_bindings.c b/drivers/net/ethernet/sfc/tc_bindings.c index d9401ee7b8e1..c18d64519c2d 100644 --- a/drivers/net/ethernet/sfc/tc_bindings.c +++ b/drivers/net/ethernet/sfc/tc_bindings.c @@ -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; @@ -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 * Entry point for flower block and filter management. */ diff --git a/drivers/net/ethernet/sfc/tc_bindings.h b/drivers/net/ethernet/sfc/tc_bindings.h index bcd63c270585..c210bb09150e 100644 --- a/drivers/net/ethernet/sfc/tc_bindings.h +++ b/drivers/net/ethernet/sfc/tc_bindings.h @@ -16,8 +16,14 @@ 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, struct flow_block_offload *tcb, struct efx_rep *efv); int efx_tc_setup(struct net_device *net_dev, enum tc_setup_type type, 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 */ |