]>
Commit | Line | Data |
---|---|---|
9948a064 JP |
1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */ | |
64eccd00 JP |
3 | |
4 | #include <linux/kernel.h> | |
5 | #include <linux/errno.h> | |
6 | #include <linux/parman.h> | |
7 | ||
8 | #include "reg.h" | |
9 | #include "core.h" | |
10 | #include "spectrum.h" | |
11 | #include "spectrum_acl_tcam.h" | |
12 | ||
13 | static int | |
14 | mlxsw_sp_acl_ctcam_region_resize(struct mlxsw_sp *mlxsw_sp, | |
15 | struct mlxsw_sp_acl_tcam_region *region, | |
16 | u16 new_size) | |
17 | { | |
18 | char ptar_pl[MLXSW_REG_PTAR_LEN]; | |
19 | ||
20 | mlxsw_reg_ptar_pack(ptar_pl, MLXSW_REG_PTAR_OP_RESIZE, | |
21 | region->key_type, new_size, region->id, | |
22 | region->tcam_region_info); | |
23 | return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptar), ptar_pl); | |
24 | } | |
25 | ||
26 | static void | |
27 | mlxsw_sp_acl_ctcam_region_move(struct mlxsw_sp *mlxsw_sp, | |
28 | struct mlxsw_sp_acl_tcam_region *region, | |
29 | u16 src_offset, u16 dst_offset, u16 size) | |
30 | { | |
31 | char prcr_pl[MLXSW_REG_PRCR_LEN]; | |
32 | ||
33 | mlxsw_reg_prcr_pack(prcr_pl, MLXSW_REG_PRCR_OP_MOVE, | |
34 | region->tcam_region_info, src_offset, | |
35 | region->tcam_region_info, dst_offset, size); | |
36 | mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(prcr), prcr_pl); | |
37 | } | |
38 | ||
39 | static int | |
40 | mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, | |
a20ff8eb IS |
41 | struct mlxsw_sp_acl_ctcam_region *cregion, |
42 | struct mlxsw_sp_acl_ctcam_entry *centry, | |
ea8b2e28 JP |
43 | struct mlxsw_sp_acl_rule_info *rulei, |
44 | bool fillup_priority) | |
64eccd00 | 45 | { |
a20ff8eb | 46 | struct mlxsw_sp_acl_tcam_region *region = cregion->region; |
a5995cc8 | 47 | struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); |
64eccd00 JP |
48 | char ptce2_pl[MLXSW_REG_PTCE2_LEN]; |
49 | char *act_set; | |
ea8b2e28 | 50 | u32 priority; |
64eccd00 JP |
51 | char *mask; |
52 | char *key; | |
ea8b2e28 JP |
53 | int err; |
54 | ||
55 | err = mlxsw_sp_acl_tcam_priority_get(mlxsw_sp, rulei, &priority, | |
56 | fillup_priority); | |
57 | if (err) | |
58 | return err; | |
64eccd00 JP |
59 | |
60 | mlxsw_reg_ptce2_pack(ptce2_pl, true, MLXSW_REG_PTCE2_OP_WRITE_WRITE, | |
a20ff8eb IS |
61 | region->tcam_region_info, |
62 | centry->parman_item.index, priority); | |
64eccd00 JP |
63 | key = mlxsw_reg_ptce2_flex_key_blocks_data(ptce2_pl); |
64 | mask = mlxsw_reg_ptce2_mask_data(ptce2_pl); | |
59600844 | 65 | mlxsw_afk_encode(afk, region->key_info, &rulei->values, key, mask); |
64eccd00 | 66 | |
a0a777b9 IS |
67 | err = cregion->ops->entry_insert(cregion, centry, mask); |
68 | if (err) | |
69 | return err; | |
70 | ||
64eccd00 JP |
71 | /* Only the first action set belongs here, the rest is in KVD */ |
72 | act_set = mlxsw_afa_block_first_set(rulei->act_block); | |
73 | mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set); | |
74 | ||
ff0db43c ND |
75 | err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl); |
76 | if (err) | |
77 | goto err_ptce2_write; | |
78 | ||
79 | return 0; | |
80 | ||
81 | err_ptce2_write: | |
82 | cregion->ops->entry_remove(cregion, centry); | |
83 | return err; | |
64eccd00 JP |
84 | } |
85 | ||
86 | static void | |
87 | mlxsw_sp_acl_ctcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp, | |
a20ff8eb IS |
88 | struct mlxsw_sp_acl_ctcam_region *cregion, |
89 | struct mlxsw_sp_acl_ctcam_entry *centry) | |
64eccd00 JP |
90 | { |
91 | char ptce2_pl[MLXSW_REG_PTCE2_LEN]; | |
92 | ||
93 | mlxsw_reg_ptce2_pack(ptce2_pl, false, MLXSW_REG_PTCE2_OP_WRITE_WRITE, | |
a20ff8eb IS |
94 | cregion->region->tcam_region_info, |
95 | centry->parman_item.index, 0); | |
64eccd00 | 96 | mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl); |
a0a777b9 | 97 | cregion->ops->entry_remove(cregion, centry); |
64eccd00 JP |
98 | } |
99 | ||
2507a64c ND |
100 | static int |
101 | mlxsw_sp_acl_ctcam_region_entry_action_replace(struct mlxsw_sp *mlxsw_sp, | |
102 | struct mlxsw_sp_acl_ctcam_region *cregion, | |
103 | struct mlxsw_sp_acl_ctcam_entry *centry, | |
104 | struct mlxsw_afa_block *afa_block, | |
105 | unsigned int priority) | |
106 | { | |
107 | char ptce2_pl[MLXSW_REG_PTCE2_LEN]; | |
108 | char *act_set; | |
109 | ||
110 | mlxsw_reg_ptce2_pack(ptce2_pl, true, MLXSW_REG_PTCE2_OP_WRITE_UPDATE, | |
111 | cregion->region->tcam_region_info, | |
112 | centry->parman_item.index, priority); | |
113 | ||
114 | act_set = mlxsw_afa_block_first_set(afa_block); | |
115 | mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set); | |
116 | ||
117 | return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl); | |
118 | } | |
119 | ||
120 | ||
64eccd00 JP |
121 | static int mlxsw_sp_acl_ctcam_region_parman_resize(void *priv, |
122 | unsigned long new_count) | |
123 | { | |
124 | struct mlxsw_sp_acl_ctcam_region *cregion = priv; | |
125 | struct mlxsw_sp_acl_tcam_region *region = cregion->region; | |
126 | struct mlxsw_sp *mlxsw_sp = region->mlxsw_sp; | |
127 | u64 max_tcam_rules; | |
128 | ||
129 | max_tcam_rules = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_TCAM_RULES); | |
130 | if (new_count > max_tcam_rules) | |
131 | return -EINVAL; | |
132 | return mlxsw_sp_acl_ctcam_region_resize(mlxsw_sp, region, new_count); | |
133 | } | |
134 | ||
135 | static void mlxsw_sp_acl_ctcam_region_parman_move(void *priv, | |
136 | unsigned long from_index, | |
137 | unsigned long to_index, | |
138 | unsigned long count) | |
139 | { | |
140 | struct mlxsw_sp_acl_ctcam_region *cregion = priv; | |
141 | struct mlxsw_sp_acl_tcam_region *region = cregion->region; | |
142 | struct mlxsw_sp *mlxsw_sp = region->mlxsw_sp; | |
143 | ||
144 | mlxsw_sp_acl_ctcam_region_move(mlxsw_sp, region, | |
145 | from_index, to_index, count); | |
146 | } | |
147 | ||
148 | static const struct parman_ops mlxsw_sp_acl_ctcam_region_parman_ops = { | |
149 | .base_count = MLXSW_SP_ACL_TCAM_REGION_BASE_COUNT, | |
150 | .resize_step = MLXSW_SP_ACL_TCAM_REGION_RESIZE_STEP, | |
151 | .resize = mlxsw_sp_acl_ctcam_region_parman_resize, | |
152 | .move = mlxsw_sp_acl_ctcam_region_parman_move, | |
153 | .algo = PARMAN_ALGO_TYPE_LSORT, | |
154 | }; | |
155 | ||
a0a777b9 IS |
156 | int |
157 | mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp, | |
158 | struct mlxsw_sp_acl_ctcam_region *cregion, | |
159 | struct mlxsw_sp_acl_tcam_region *region, | |
160 | const struct mlxsw_sp_acl_ctcam_region_ops *ops) | |
64eccd00 JP |
161 | { |
162 | cregion->region = region; | |
a0a777b9 | 163 | cregion->ops = ops; |
64eccd00 JP |
164 | cregion->parman = parman_create(&mlxsw_sp_acl_ctcam_region_parman_ops, |
165 | cregion); | |
166 | if (!cregion->parman) | |
167 | return -ENOMEM; | |
168 | return 0; | |
169 | } | |
170 | ||
171 | void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion) | |
172 | { | |
173 | parman_destroy(cregion->parman); | |
174 | } | |
175 | ||
176 | void mlxsw_sp_acl_ctcam_chunk_init(struct mlxsw_sp_acl_ctcam_region *cregion, | |
177 | struct mlxsw_sp_acl_ctcam_chunk *cchunk, | |
178 | unsigned int priority) | |
179 | { | |
180 | parman_prio_init(cregion->parman, &cchunk->parman_prio, priority); | |
181 | } | |
182 | ||
183 | void mlxsw_sp_acl_ctcam_chunk_fini(struct mlxsw_sp_acl_ctcam_chunk *cchunk) | |
184 | { | |
185 | parman_prio_fini(&cchunk->parman_prio); | |
186 | } | |
187 | ||
188 | int mlxsw_sp_acl_ctcam_entry_add(struct mlxsw_sp *mlxsw_sp, | |
189 | struct mlxsw_sp_acl_ctcam_region *cregion, | |
190 | struct mlxsw_sp_acl_ctcam_chunk *cchunk, | |
191 | struct mlxsw_sp_acl_ctcam_entry *centry, | |
ea8b2e28 JP |
192 | struct mlxsw_sp_acl_rule_info *rulei, |
193 | bool fillup_priority) | |
64eccd00 JP |
194 | { |
195 | int err; | |
196 | ||
197 | err = parman_item_add(cregion->parman, &cchunk->parman_prio, | |
198 | ¢ry->parman_item); | |
199 | if (err) | |
200 | return err; | |
201 | ||
a20ff8eb | 202 | err = mlxsw_sp_acl_ctcam_region_entry_insert(mlxsw_sp, cregion, centry, |
ea8b2e28 | 203 | rulei, fillup_priority); |
64eccd00 JP |
204 | if (err) |
205 | goto err_rule_insert; | |
206 | return 0; | |
207 | ||
208 | err_rule_insert: | |
209 | parman_item_remove(cregion->parman, &cchunk->parman_prio, | |
210 | ¢ry->parman_item); | |
211 | return err; | |
212 | } | |
213 | ||
214 | void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp, | |
215 | struct mlxsw_sp_acl_ctcam_region *cregion, | |
216 | struct mlxsw_sp_acl_ctcam_chunk *cchunk, | |
217 | struct mlxsw_sp_acl_ctcam_entry *centry) | |
218 | { | |
a20ff8eb | 219 | mlxsw_sp_acl_ctcam_region_entry_remove(mlxsw_sp, cregion, centry); |
64eccd00 JP |
220 | parman_item_remove(cregion->parman, &cchunk->parman_prio, |
221 | ¢ry->parman_item); | |
222 | } | |
2507a64c ND |
223 | |
224 | int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, | |
225 | struct mlxsw_sp_acl_ctcam_region *cregion, | |
226 | struct mlxsw_sp_acl_ctcam_chunk *cchunk, | |
227 | struct mlxsw_sp_acl_ctcam_entry *centry, | |
228 | struct mlxsw_sp_acl_rule_info *rulei) | |
229 | { | |
230 | return mlxsw_sp_acl_ctcam_region_entry_action_replace(mlxsw_sp, cregion, | |
231 | centry, | |
232 | rulei->act_block, | |
233 | rulei->priority); | |
234 | } |