mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-20 11:13:58 +08:00
nfp: forbid disabling hw-tc-offload on representors while offload active
All netdevs which can accept TC offloads must implement
.ndo_set_features(). nfp_reprs currently do not do that, which
means hw-tc-offload can be turned on and off even when offloads
are active.
Whether the offloads are active is really a question to nfp_ports,
so remove the per-app tc_busy callback indirection thing, and
simply count the number of offloaded items in nfp_port structure.
Fixes: 8a2768732a
("nfp: provide infrastructure for offloading flower based TC filters")
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Tested-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0b9de4ca85
commit
d692403e5c
@ -182,6 +182,7 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
bv->tc_prog = cls_bpf->prog;
|
bv->tc_prog = cls_bpf->prog;
|
||||||
|
nn->port->tc_offload_cnt = !!bv->tc_prog;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,13 +220,6 @@ static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nfp_bpf_tc_busy(struct nfp_app *app, struct nfp_net *nn)
|
|
||||||
{
|
|
||||||
struct nfp_bpf_vnic *bv = nn->app_priv;
|
|
||||||
|
|
||||||
return !!bv->tc_prog;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nfp_bpf_change_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu)
|
nfp_bpf_change_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu)
|
||||||
{
|
{
|
||||||
@ -429,7 +423,6 @@ const struct nfp_app_type app_bpf = {
|
|||||||
.ctrl_msg_rx = nfp_bpf_ctrl_msg_rx,
|
.ctrl_msg_rx = nfp_bpf_ctrl_msg_rx,
|
||||||
|
|
||||||
.setup_tc = nfp_bpf_setup_tc,
|
.setup_tc = nfp_bpf_setup_tc,
|
||||||
.tc_busy = nfp_bpf_tc_busy,
|
|
||||||
.bpf = nfp_ndo_bpf,
|
.bpf = nfp_ndo_bpf,
|
||||||
.xdp_offload = nfp_bpf_xdp_offload,
|
.xdp_offload = nfp_bpf_xdp_offload,
|
||||||
};
|
};
|
||||||
|
@ -349,6 +349,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
|
|||||||
struct tc_cls_flower_offload *flow, bool egress)
|
struct tc_cls_flower_offload *flow, bool egress)
|
||||||
{
|
{
|
||||||
enum nfp_flower_tun_type tun_type = NFP_FL_TUNNEL_NONE;
|
enum nfp_flower_tun_type tun_type = NFP_FL_TUNNEL_NONE;
|
||||||
|
struct nfp_port *port = nfp_port_from_netdev(netdev);
|
||||||
struct nfp_flower_priv *priv = app->priv;
|
struct nfp_flower_priv *priv = app->priv;
|
||||||
struct nfp_fl_payload *flow_pay;
|
struct nfp_fl_payload *flow_pay;
|
||||||
struct nfp_fl_key_ls *key_layer;
|
struct nfp_fl_key_ls *key_layer;
|
||||||
@ -390,6 +391,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
|
|||||||
INIT_HLIST_NODE(&flow_pay->link);
|
INIT_HLIST_NODE(&flow_pay->link);
|
||||||
flow_pay->tc_flower_cookie = flow->cookie;
|
flow_pay->tc_flower_cookie = flow->cookie;
|
||||||
hash_add_rcu(priv->flow_table, &flow_pay->link, flow->cookie);
|
hash_add_rcu(priv->flow_table, &flow_pay->link, flow->cookie);
|
||||||
|
port->tc_offload_cnt++;
|
||||||
|
|
||||||
/* Deallocate flow payload when flower rule has been destroyed. */
|
/* Deallocate flow payload when flower rule has been destroyed. */
|
||||||
kfree(key_layer);
|
kfree(key_layer);
|
||||||
@ -421,6 +423,7 @@ static int
|
|||||||
nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
|
nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
|
||||||
struct tc_cls_flower_offload *flow)
|
struct tc_cls_flower_offload *flow)
|
||||||
{
|
{
|
||||||
|
struct nfp_port *port = nfp_port_from_netdev(netdev);
|
||||||
struct nfp_fl_payload *nfp_flow;
|
struct nfp_fl_payload *nfp_flow;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -442,6 +445,7 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
|
|||||||
|
|
||||||
err_free_flow:
|
err_free_flow:
|
||||||
hash_del_rcu(&nfp_flow->link);
|
hash_del_rcu(&nfp_flow->link);
|
||||||
|
port->tc_offload_cnt--;
|
||||||
kfree(nfp_flow->action_data);
|
kfree(nfp_flow->action_data);
|
||||||
kfree(nfp_flow->mask_data);
|
kfree(nfp_flow->mask_data);
|
||||||
kfree(nfp_flow->unmasked_data);
|
kfree(nfp_flow->unmasked_data);
|
||||||
|
@ -92,7 +92,6 @@ extern const struct nfp_app_type app_flower;
|
|||||||
* @stop: stop application logic
|
* @stop: stop application logic
|
||||||
* @ctrl_msg_rx: control message handler
|
* @ctrl_msg_rx: control message handler
|
||||||
* @setup_tc: setup TC ndo
|
* @setup_tc: setup TC ndo
|
||||||
* @tc_busy: TC HW offload busy (rules loaded)
|
|
||||||
* @bpf: BPF ndo offload-related calls
|
* @bpf: BPF ndo offload-related calls
|
||||||
* @xdp_offload: offload an XDP program
|
* @xdp_offload: offload an XDP program
|
||||||
* @eswitch_mode_get: get SR-IOV eswitch mode
|
* @eswitch_mode_get: get SR-IOV eswitch mode
|
||||||
@ -135,7 +134,6 @@ struct nfp_app_type {
|
|||||||
|
|
||||||
int (*setup_tc)(struct nfp_app *app, struct net_device *netdev,
|
int (*setup_tc)(struct nfp_app *app, struct net_device *netdev,
|
||||||
enum tc_setup_type type, void *type_data);
|
enum tc_setup_type type, void *type_data);
|
||||||
bool (*tc_busy)(struct nfp_app *app, struct nfp_net *nn);
|
|
||||||
int (*bpf)(struct nfp_app *app, struct nfp_net *nn,
|
int (*bpf)(struct nfp_app *app, struct nfp_net *nn,
|
||||||
struct netdev_bpf *xdp);
|
struct netdev_bpf *xdp);
|
||||||
int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn,
|
int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn,
|
||||||
@ -301,13 +299,6 @@ static inline bool nfp_app_has_tc(struct nfp_app *app)
|
|||||||
return app && app->type->setup_tc;
|
return app && app->type->setup_tc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool nfp_app_tc_busy(struct nfp_app *app, struct nfp_net *nn)
|
|
||||||
{
|
|
||||||
if (!app || !app->type->tc_busy)
|
|
||||||
return false;
|
|
||||||
return app->type->tc_busy(app, nn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int nfp_app_setup_tc(struct nfp_app *app,
|
static inline int nfp_app_setup_tc(struct nfp_app *app,
|
||||||
struct net_device *netdev,
|
struct net_device *netdev,
|
||||||
enum tc_setup_type type, void *type_data)
|
enum tc_setup_type type, void *type_data)
|
||||||
|
@ -3210,10 +3210,9 @@ static int nfp_net_set_features(struct net_device *netdev,
|
|||||||
new_ctrl &= ~NFP_NET_CFG_CTRL_GATHER;
|
new_ctrl &= ~NFP_NET_CFG_CTRL_GATHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed & NETIF_F_HW_TC && nfp_app_tc_busy(nn->app, nn)) {
|
err = nfp_port_set_features(netdev, features);
|
||||||
nn_err(nn, "Cannot disable HW TC offload while in use\n");
|
if (err)
|
||||||
return -EBUSY;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
nn_dbg(nn, "Feature change 0x%llx -> 0x%llx (changed=0x%llx)\n",
|
nn_dbg(nn, "Feature change 0x%llx -> 0x%llx (changed=0x%llx)\n",
|
||||||
netdev->features, features, changed);
|
netdev->features, features, changed);
|
||||||
|
@ -265,6 +265,7 @@ const struct net_device_ops nfp_repr_netdev_ops = {
|
|||||||
.ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk,
|
.ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk,
|
||||||
.ndo_get_vf_config = nfp_app_get_vf_config,
|
.ndo_get_vf_config = nfp_app_get_vf_config,
|
||||||
.ndo_set_vf_link_state = nfp_app_set_vf_link_state,
|
.ndo_set_vf_link_state = nfp_app_set_vf_link_state,
|
||||||
|
.ndo_set_features = nfp_port_set_features,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void nfp_repr_clean(struct nfp_repr *repr)
|
static void nfp_repr_clean(struct nfp_repr *repr)
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/lockdep.h>
|
#include <linux/lockdep.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
#include <net/switchdev.h>
|
#include <net/switchdev.h>
|
||||||
|
|
||||||
#include "nfpcore/nfp_cpp.h"
|
#include "nfpcore/nfp_cpp.h"
|
||||||
@ -100,6 +101,23 @@ int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
|
|||||||
return nfp_app_setup_tc(port->app, netdev, type, type_data);
|
return nfp_app_setup_tc(port->app, netdev, type, type_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)
|
||||||
|
{
|
||||||
|
struct nfp_port *port;
|
||||||
|
|
||||||
|
port = nfp_port_from_netdev(netdev);
|
||||||
|
if (!port)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
|
||||||
|
port->tc_offload_cnt) {
|
||||||
|
netdev_err(netdev, "Cannot disable HW TC offload while offloads active\n");
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct nfp_port *
|
struct nfp_port *
|
||||||
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id)
|
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id)
|
||||||
{
|
{
|
||||||
|
@ -72,6 +72,8 @@ enum nfp_port_flags {
|
|||||||
* @netdev: backpointer to associated netdev
|
* @netdev: backpointer to associated netdev
|
||||||
* @type: what port type does the entity represent
|
* @type: what port type does the entity represent
|
||||||
* @flags: port flags
|
* @flags: port flags
|
||||||
|
* @tc_offload_cnt: number of active TC offloads, how offloads are counted
|
||||||
|
* is not defined, use as a boolean
|
||||||
* @app: backpointer to the app structure
|
* @app: backpointer to the app structure
|
||||||
* @dl_port: devlink port structure
|
* @dl_port: devlink port structure
|
||||||
* @eth_id: for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme
|
* @eth_id: for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme
|
||||||
@ -87,6 +89,7 @@ struct nfp_port {
|
|||||||
enum nfp_port_type type;
|
enum nfp_port_type type;
|
||||||
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
unsigned long tc_offload_cnt;
|
||||||
|
|
||||||
struct nfp_app *app;
|
struct nfp_app *app;
|
||||||
|
|
||||||
@ -121,6 +124,9 @@ static inline bool nfp_port_is_vnic(const struct nfp_port *port)
|
|||||||
return port->type == NFP_PORT_PF_PORT || port->type == NFP_PORT_VF_PORT;
|
return port->type == NFP_PORT_PF_PORT || port->type == NFP_PORT_VF_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nfp_port_set_features(struct net_device *netdev, netdev_features_t features);
|
||||||
|
|
||||||
struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
|
struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
|
||||||
struct nfp_port *
|
struct nfp_port *
|
||||||
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id);
|
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id);
|
||||||
|
Loading…
Reference in New Issue
Block a user