return 0;
}
-static int
-mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_flow_block *flow_block,
- struct tc_cls_matchall_offload *f)
-{
- switch (f->command) {
- case TC_CLSMATCHALL_REPLACE:
- return mlxsw_sp_mall_replace(flow_block, f);
- case TC_CLSMATCHALL_DESTROY:
- mlxsw_sp_mall_destroy(flow_block, f);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static int
-mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_flow_block *flow_block,
- struct flow_cls_offload *f)
-{
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_flow_block_mlxsw_sp(flow_block);
-
- switch (f->command) {
- case FLOW_CLS_REPLACE:
- return mlxsw_sp_flower_replace(mlxsw_sp, flow_block, f);
- case FLOW_CLS_DESTROY:
- mlxsw_sp_flower_destroy(mlxsw_sp, flow_block, f);
- return 0;
- case FLOW_CLS_STATS:
- return mlxsw_sp_flower_stats(mlxsw_sp, flow_block, f);
- case FLOW_CLS_TMPLT_CREATE:
- return mlxsw_sp_flower_tmplt_create(mlxsw_sp, flow_block, f);
- case FLOW_CLS_TMPLT_DESTROY:
- mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, flow_block, f);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static int mlxsw_sp_setup_tc_block_cb(enum tc_setup_type type,
- void *type_data, void *cb_priv)
-{
- struct mlxsw_sp_flow_block *flow_block = cb_priv;
-
- if (mlxsw_sp_flow_block_disabled(flow_block))
- return -EOPNOTSUPP;
-
- switch (type) {
- case TC_SETUP_CLSMATCHALL:
- return mlxsw_sp_setup_tc_cls_matchall(flow_block, type_data);
- case TC_SETUP_CLSFLOWER:
- return mlxsw_sp_setup_tc_cls_flower(flow_block, type_data);
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static void mlxsw_sp_tc_block_release(void *cb_priv)
-{
- struct mlxsw_sp_flow_block *flow_block = cb_priv;
-
- mlxsw_sp_flow_block_destroy(flow_block);
-}
-
-static LIST_HEAD(mlxsw_sp_block_cb_list);
-
-static int mlxsw_sp_setup_tc_block_bind(struct mlxsw_sp_port *mlxsw_sp_port,
- struct flow_block_offload *f,
- bool ingress)
-{
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- struct mlxsw_sp_flow_block *flow_block;
- struct flow_block_cb *block_cb;
- bool register_block = false;
- int err;
-
- block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_setup_tc_block_cb,
- mlxsw_sp);
- if (!block_cb) {
- flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, f->net);
- if (!flow_block)
- return -ENOMEM;
- block_cb = flow_block_cb_alloc(mlxsw_sp_setup_tc_block_cb,
- mlxsw_sp, flow_block,
- mlxsw_sp_tc_block_release);
- if (IS_ERR(block_cb)) {
- mlxsw_sp_flow_block_destroy(flow_block);
- err = PTR_ERR(block_cb);
- goto err_cb_register;
- }
- register_block = true;
- } else {
- flow_block = flow_block_cb_priv(block_cb);
- }
- flow_block_cb_incref(block_cb);
- err = mlxsw_sp_flow_block_bind(mlxsw_sp, flow_block,
- mlxsw_sp_port, ingress, f->extack);
- if (err)
- goto err_block_bind;
-
- if (ingress)
- mlxsw_sp_port->ing_flow_block = flow_block;
- else
- mlxsw_sp_port->eg_flow_block = flow_block;
-
- if (register_block) {
- flow_block_cb_add(block_cb, f);
- list_add_tail(&block_cb->driver_list, &mlxsw_sp_block_cb_list);
- }
-
- return 0;
-
-err_block_bind:
- if (!flow_block_cb_decref(block_cb))
- flow_block_cb_free(block_cb);
-err_cb_register:
- return err;
-}
-
-static void mlxsw_sp_setup_tc_block_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
- struct flow_block_offload *f,
- bool ingress)
-{
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- struct mlxsw_sp_flow_block *flow_block;
- struct flow_block_cb *block_cb;
- int err;
-
- block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_setup_tc_block_cb,
- mlxsw_sp);
- if (!block_cb)
- return;
-
- if (ingress)
- mlxsw_sp_port->ing_flow_block = NULL;
- else
- mlxsw_sp_port->eg_flow_block = NULL;
-
- flow_block = flow_block_cb_priv(block_cb);
- err = mlxsw_sp_flow_block_unbind(mlxsw_sp, flow_block,
- mlxsw_sp_port, ingress);
- if (!err && !flow_block_cb_decref(block_cb)) {
- flow_block_cb_remove(block_cb, f);
- list_del(&block_cb->driver_list);
- }
-}
-
-static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
- struct flow_block_offload *f)
-{
- bool ingress;
-
- if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- ingress = true;
- else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
- ingress = false;
- else
- return -EOPNOTSUPP;
-
- f->driver_block_list = &mlxsw_sp_block_cb_list;
-
- switch (f->command) {
- case FLOW_BLOCK_BIND:
- return mlxsw_sp_setup_tc_block_bind(mlxsw_sp_port, f, ingress);
- case FLOW_BLOCK_UNBIND:
- mlxsw_sp_setup_tc_block_unbind(mlxsw_sp_port, f, ingress);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
}
}
-
static int mlxsw_sp_feature_hw_tc(struct net_device *dev, bool enable)
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
return block->ruleset_zero;
}
-int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_flow_block *block,
- struct mlxsw_sp_port *mlxsw_sp_port,
- bool ingress,
- struct netlink_ext_ack *extack)
+static int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_flow_block *block,
+ struct mlxsw_sp_port *mlxsw_sp_port,
+ bool ingress,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp_flow_block_binding *binding;
int err;
return err;
}
-int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_flow_block *block,
- struct mlxsw_sp_port *mlxsw_sp_port,
- bool ingress)
+static int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_flow_block *block,
+ struct mlxsw_sp_port *mlxsw_sp_port,
+ bool ingress)
{
struct mlxsw_sp_flow_block_binding *binding;
return 0;
}
+
+static int mlxsw_sp_flow_block_mall_cb(struct mlxsw_sp_flow_block *flow_block,
+ struct tc_cls_matchall_offload *f)
+{
+ switch (f->command) {
+ case TC_CLSMATCHALL_REPLACE:
+ return mlxsw_sp_mall_replace(flow_block, f);
+ case TC_CLSMATCHALL_DESTROY:
+ mlxsw_sp_mall_destroy(flow_block, f);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int mlxsw_sp_flow_block_flower_cb(struct mlxsw_sp_flow_block *flow_block,
+ struct flow_cls_offload *f)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_flow_block_mlxsw_sp(flow_block);
+
+ switch (f->command) {
+ case FLOW_CLS_REPLACE:
+ return mlxsw_sp_flower_replace(mlxsw_sp, flow_block, f);
+ case FLOW_CLS_DESTROY:
+ mlxsw_sp_flower_destroy(mlxsw_sp, flow_block, f);
+ return 0;
+ case FLOW_CLS_STATS:
+ return mlxsw_sp_flower_stats(mlxsw_sp, flow_block, f);
+ case FLOW_CLS_TMPLT_CREATE:
+ return mlxsw_sp_flower_tmplt_create(mlxsw_sp, flow_block, f);
+ case FLOW_CLS_TMPLT_DESTROY:
+ mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, flow_block, f);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int mlxsw_sp_flow_block_cb(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ struct mlxsw_sp_flow_block *flow_block = cb_priv;
+
+ if (mlxsw_sp_flow_block_disabled(flow_block))
+ return -EOPNOTSUPP;
+
+ switch (type) {
+ case TC_SETUP_CLSMATCHALL:
+ return mlxsw_sp_flow_block_mall_cb(flow_block, type_data);
+ case TC_SETUP_CLSFLOWER:
+ return mlxsw_sp_flow_block_flower_cb(flow_block, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void mlxsw_sp_tc_block_release(void *cb_priv)
+{
+ struct mlxsw_sp_flow_block *flow_block = cb_priv;
+
+ mlxsw_sp_flow_block_destroy(flow_block);
+}
+
+static LIST_HEAD(mlxsw_sp_block_cb_list);
+
+static int mlxsw_sp_setup_tc_block_bind(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct flow_block_offload *f,
+ bool ingress)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ struct mlxsw_sp_flow_block *flow_block;
+ struct flow_block_cb *block_cb;
+ bool register_block = false;
+ int err;
+
+ block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_flow_block_cb,
+ mlxsw_sp);
+ if (!block_cb) {
+ flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, f->net);
+ if (!flow_block)
+ return -ENOMEM;
+ block_cb = flow_block_cb_alloc(mlxsw_sp_flow_block_cb,
+ mlxsw_sp, flow_block,
+ mlxsw_sp_tc_block_release);
+ if (IS_ERR(block_cb)) {
+ mlxsw_sp_flow_block_destroy(flow_block);
+ err = PTR_ERR(block_cb);
+ goto err_cb_register;
+ }
+ register_block = true;
+ } else {
+ flow_block = flow_block_cb_priv(block_cb);
+ }
+ flow_block_cb_incref(block_cb);
+ err = mlxsw_sp_flow_block_bind(mlxsw_sp, flow_block,
+ mlxsw_sp_port, ingress, f->extack);
+ if (err)
+ goto err_block_bind;
+
+ if (ingress)
+ mlxsw_sp_port->ing_flow_block = flow_block;
+ else
+ mlxsw_sp_port->eg_flow_block = flow_block;
+
+ if (register_block) {
+ flow_block_cb_add(block_cb, f);
+ list_add_tail(&block_cb->driver_list, &mlxsw_sp_block_cb_list);
+ }
+
+ return 0;
+
+err_block_bind:
+ if (!flow_block_cb_decref(block_cb))
+ flow_block_cb_free(block_cb);
+err_cb_register:
+ return err;
+}
+
+static void mlxsw_sp_setup_tc_block_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct flow_block_offload *f,
+ bool ingress)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ struct mlxsw_sp_flow_block *flow_block;
+ struct flow_block_cb *block_cb;
+ int err;
+
+ block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_flow_block_cb,
+ mlxsw_sp);
+ if (!block_cb)
+ return;
+
+ if (ingress)
+ mlxsw_sp_port->ing_flow_block = NULL;
+ else
+ mlxsw_sp_port->eg_flow_block = NULL;
+
+ flow_block = flow_block_cb_priv(block_cb);
+ err = mlxsw_sp_flow_block_unbind(mlxsw_sp, flow_block,
+ mlxsw_sp_port, ingress);
+ if (!err && !flow_block_cb_decref(block_cb)) {
+ flow_block_cb_remove(block_cb, f);
+ list_del(&block_cb->driver_list);
+ }
+}
+
+int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct flow_block_offload *f)
+{
+ bool ingress;
+
+ if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ ingress = true;
+ else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
+ ingress = false;
+ else
+ return -EOPNOTSUPP;
+
+ f->driver_block_list = &mlxsw_sp_block_cb_list;
+
+ switch (f->command) {
+ case FLOW_BLOCK_BIND:
+ return mlxsw_sp_setup_tc_block_bind(mlxsw_sp_port, f, ingress);
+ case FLOW_BLOCK_UNBIND:
+ mlxsw_sp_setup_tc_block_unbind(mlxsw_sp_port, f, ingress);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}