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
];
49 /* The first action set of a TCAM entry is stored directly in TCAM,
50 * not KVD linear area.
55 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, MLXSW_SP_KVDL_ACT_EXT_SIZE
,
59 mlxsw_reg_pefa_pack(pefa_pl
, kvdl_index
, enc_actions
);
60 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(pefa
), pefa_pl
);
63 *p_kvdl_index
= kvdl_index
;
67 mlxsw_sp_kvdl_free(mlxsw_sp
, kvdl_index
);
71 static void mlxsw_sp_act_kvdl_set_del(void *priv
, u32 kvdl_index
,
74 struct mlxsw_sp
*mlxsw_sp
= priv
;
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
,
84 struct mlxsw_sp
*mlxsw_sp
= priv
;
85 char ppbs_pl
[MLXSW_REG_PPBS_LEN
];
89 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, 1, &kvdl_index
);
92 mlxsw_reg_ppbs_pack(ppbs_pl
, kvdl_index
, local_port
);
93 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ppbs
), ppbs_pl
);
96 *p_kvdl_index
= kvdl_index
;
100 mlxsw_sp_kvdl_free(mlxsw_sp
, kvdl_index
);
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
);
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
);
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
);
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
;
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);
145 span_entry
= mlxsw_sp_span_entry_find(mlxsw_sp
, local_out_port
);
148 goto err_span_entry_find
;
151 *p_span_id
= span_entry
->id
;
155 mlxsw_sp_span_mirror_del(in_port
, local_out_port
, type
, false);
160 mlxsw_sp_act_mirror_del(void *priv
, u8 local_in_port
, u8 local_out_port
,
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
);