Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_acl_flex_actions.c
blob6ca6894125f0c1f188c56994ecb253d1311b9dd0
1 /*
2 * drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c
3 * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2017 Jiri Pirko <jiri@mellanox.com>
5 * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the names of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
36 #include "spectrum_acl_flex_actions.h"
37 #include "core_acl_flex_actions.h"
39 #define MLXSW_SP_KVDL_ACT_EXT_SIZE 1
41 static int mlxsw_sp_act_kvdl_set_add(void *priv, u32 *p_kvdl_index,
42 char *enc_actions, bool is_first)
44 struct mlxsw_sp *mlxsw_sp = priv;
45 char pefa_pl[MLXSW_REG_PEFA_LEN];
46 u32 kvdl_index;
47 int err;
49 /* The first action set of a TCAM entry is stored directly in TCAM,
50 * not KVD linear area.
52 if (is_first)
53 return 0;
55 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ACT_EXT_SIZE,
56 &kvdl_index);
57 if (err)
58 return err;
59 mlxsw_reg_pefa_pack(pefa_pl, kvdl_index, enc_actions);
60 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pefa), pefa_pl);
61 if (err)
62 goto err_pefa_write;
63 *p_kvdl_index = kvdl_index;
64 return 0;
66 err_pefa_write:
67 mlxsw_sp_kvdl_free(mlxsw_sp, kvdl_index);
68 return err;
71 static void mlxsw_sp_act_kvdl_set_del(void *priv, u32 kvdl_index,
72 bool is_first)
74 struct mlxsw_sp *mlxsw_sp = priv;
76 if (is_first)
77 return;
78 mlxsw_sp_kvdl_free(mlxsw_sp, kvdl_index);
81 static int mlxsw_sp_act_kvdl_fwd_entry_add(void *priv, u32 *p_kvdl_index,
82 u8 local_port)
84 struct mlxsw_sp *mlxsw_sp = priv;
85 char ppbs_pl[MLXSW_REG_PPBS_LEN];
86 u32 kvdl_index;
87 int err;
89 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, 1, &kvdl_index);
90 if (err)
91 return err;
92 mlxsw_reg_ppbs_pack(ppbs_pl, kvdl_index, local_port);
93 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ppbs), ppbs_pl);
94 if (err)
95 goto err_ppbs_write;
96 *p_kvdl_index = kvdl_index;
97 return 0;
99 err_ppbs_write:
100 mlxsw_sp_kvdl_free(mlxsw_sp, kvdl_index);
101 return err;
104 static void mlxsw_sp_act_kvdl_fwd_entry_del(void *priv, u32 kvdl_index)
106 struct mlxsw_sp *mlxsw_sp = priv;
108 mlxsw_sp_kvdl_free(mlxsw_sp, kvdl_index);
111 static int
112 mlxsw_sp_act_counter_index_get(void *priv, unsigned int *p_counter_index)
114 struct mlxsw_sp *mlxsw_sp = priv;
116 return mlxsw_sp_flow_counter_alloc(mlxsw_sp, p_counter_index);
119 static void
120 mlxsw_sp_act_counter_index_put(void *priv, unsigned int counter_index)
122 struct mlxsw_sp *mlxsw_sp = priv;
124 mlxsw_sp_flow_counter_free(mlxsw_sp, counter_index);
127 static int
128 mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port, u8 local_out_port,
129 bool ingress, int *p_span_id)
131 struct mlxsw_sp_port *in_port, *out_port;
132 struct mlxsw_sp_span_entry *span_entry;
133 struct mlxsw_sp *mlxsw_sp = priv;
134 enum mlxsw_sp_span_type type;
135 int err;
137 type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
138 out_port = mlxsw_sp->ports[local_out_port];
139 in_port = mlxsw_sp->ports[local_in_port];
141 err = mlxsw_sp_span_mirror_add(in_port, out_port, type, false);
142 if (err)
143 return err;
145 span_entry = mlxsw_sp_span_entry_find(mlxsw_sp, local_out_port);
146 if (!span_entry) {
147 err = -ENOENT;
148 goto err_span_entry_find;
151 *p_span_id = span_entry->id;
152 return 0;
154 err_span_entry_find:
155 mlxsw_sp_span_mirror_del(in_port, local_out_port, type, false);
156 return err;
159 static void
160 mlxsw_sp_act_mirror_del(void *priv, u8 local_in_port, u8 local_out_port,
161 bool ingress)
163 struct mlxsw_sp *mlxsw_sp = priv;
164 struct mlxsw_sp_port *in_port;
165 enum mlxsw_sp_span_type type;
167 type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
168 in_port = mlxsw_sp->ports[local_in_port];
170 mlxsw_sp_span_mirror_del(in_port, local_out_port, type, false);
173 static const struct mlxsw_afa_ops mlxsw_sp_act_afa_ops = {
174 .kvdl_set_add = mlxsw_sp_act_kvdl_set_add,
175 .kvdl_set_del = mlxsw_sp_act_kvdl_set_del,
176 .kvdl_fwd_entry_add = mlxsw_sp_act_kvdl_fwd_entry_add,
177 .kvdl_fwd_entry_del = mlxsw_sp_act_kvdl_fwd_entry_del,
178 .counter_index_get = mlxsw_sp_act_counter_index_get,
179 .counter_index_put = mlxsw_sp_act_counter_index_put,
180 .mirror_add = mlxsw_sp_act_mirror_add,
181 .mirror_del = mlxsw_sp_act_mirror_del,
184 int mlxsw_sp_afa_init(struct mlxsw_sp *mlxsw_sp)
186 mlxsw_sp->afa = mlxsw_afa_create(MLXSW_CORE_RES_GET(mlxsw_sp->core,
187 ACL_ACTIONS_PER_SET),
188 &mlxsw_sp_act_afa_ops, mlxsw_sp);
189 return PTR_ERR_OR_ZERO(mlxsw_sp->afa);
192 void mlxsw_sp_afa_fini(struct mlxsw_sp *mlxsw_sp)
194 mlxsw_afa_destroy(mlxsw_sp->afa);