Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2023 Marvell.
3 : : */
4 : :
5 : : #include "roc_api.h"
6 : : #include "roc_priv.h"
7 : :
8 : : struct mcs_event_cb {
9 : : TAILQ_ENTRY(mcs_event_cb) next;
10 : : enum roc_mcs_event_type event;
11 : : roc_mcs_dev_cb_fn cb_fn;
12 : : void *cb_arg;
13 : : void *userdata;
14 : : void *ret_param;
15 : : uint32_t active;
16 : : };
17 : : TAILQ_HEAD(mcs_event_cb_list, mcs_event_cb);
18 : :
19 : : PLT_STATIC_ASSERT(ROC_MCS_MEM_SZ >= (sizeof(struct mcs_priv) + sizeof(struct mcs_event_cb_list)));
20 : :
21 : : bool
22 : 0 : roc_mcs_is_supported(void)
23 : : {
24 : : struct get_hw_cap_rsp *hw_cap_rsp;
25 : : struct npa_lf *npa;
26 : :
27 : : /* Use mbox handler of first probed pci_func for initial mcs mbox communication. */
28 : 0 : npa = idev_npa_obj_get();
29 [ # # ]: 0 : if (!npa)
30 : : return false;
31 : :
32 : 0 : mbox_alloc_msg_get_hw_cap(npa->mbox);
33 [ # # ]: 0 : if (mbox_process_msg(npa->mbox, (void *)&hw_cap_rsp))
34 : : return false;
35 : :
36 [ # # ]: 0 : if (hw_cap_rsp->hw_caps & HW_CAP_MACSEC)
37 : 0 : return true;
38 : :
39 : : return false;
40 : : }
41 : :
42 : : int
43 [ # # ]: 0 : roc_mcs_hw_info_get(struct roc_mcs_hw_info *hw_info)
44 : : {
45 : : struct mcs_hw_info *hw;
46 : : struct npa_lf *npa;
47 : : int rc;
48 : :
49 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
50 : :
51 [ # # ]: 0 : if (hw_info == NULL)
52 : : return -EINVAL;
53 : :
54 : : /* Use mbox handler of first probed pci_func for
55 : : * initial mcs mbox communication.
56 : : */
57 : 0 : npa = idev_npa_obj_get();
58 [ # # ]: 0 : if (!npa)
59 : : return MCS_ERR_DEVICE_NOT_FOUND;
60 : :
61 : 0 : mbox_alloc_msg_mcs_get_hw_info(npa->mbox);
62 : 0 : rc = mbox_process_msg(npa->mbox, (void *)&hw);
63 [ # # ]: 0 : if (rc)
64 : : return rc;
65 : :
66 : 0 : hw_info->num_mcs_blks = hw->num_mcs_blks;
67 : 0 : hw_info->tcam_entries = hw->tcam_entries;
68 : 0 : hw_info->secy_entries = hw->secy_entries;
69 : 0 : hw_info->sc_entries = hw->sc_entries;
70 : 0 : hw_info->sa_entries = hw->sa_entries;
71 : :
72 : 0 : return rc;
73 : : }
74 : :
75 : : int
76 [ # # ]: 0 : roc_mcs_active_lmac_set(struct roc_mcs *mcs, struct roc_mcs_set_active_lmac *lmac)
77 : : {
78 : : struct mcs_set_active_lmac *req;
79 : : struct msg_rsp *rsp;
80 : :
81 : : /* Only needed for 105N */
82 [ # # ]: 0 : if (!roc_model_is_cnf10kb())
83 : : return 0;
84 : :
85 [ # # ]: 0 : if (lmac == NULL)
86 : : return -EINVAL;
87 : :
88 : : MCS_SUPPORT_CHECK;
89 : :
90 : 0 : req = mbox_alloc_msg_mcs_set_active_lmac(mcs->mbox);
91 [ # # ]: 0 : if (req == NULL)
92 : : return -ENOMEM;
93 : :
94 : 0 : req->lmac_bmap = lmac->lmac_bmap;
95 : 0 : req->channel_base = lmac->channel_base;
96 : 0 : req->mcs_id = mcs->idx;
97 : :
98 : 0 : return mbox_process_msg(mcs->mbox, (void *)&rsp);
99 : : }
100 : :
101 : : static int
102 [ # # ]: 0 : mcs_port_reset_set(struct roc_mcs *mcs, struct roc_mcs_port_reset_req *port, uint8_t reset)
103 : : {
104 : : struct mcs_port_reset_req *req;
105 : : struct msg_rsp *rsp;
106 : :
107 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
108 : :
109 : 0 : req = mbox_alloc_msg_mcs_port_reset(mcs->mbox);
110 [ # # ]: 0 : if (req == NULL)
111 : : return -ENOMEM;
112 : :
113 : 0 : req->reset = reset;
114 : 0 : req->lmac_id = port->port_id;
115 : 0 : req->mcs_id = mcs->idx;
116 : :
117 : 0 : return mbox_process_msg(mcs->mbox, (void *)&rsp);
118 : : }
119 : :
120 : : int
121 : 0 : roc_mcs_lmac_mode_set(struct roc_mcs *mcs, struct roc_mcs_set_lmac_mode *port)
122 : : {
123 : : struct mcs_set_lmac_mode *req;
124 : : struct msg_rsp *rsp;
125 : :
126 [ # # ]: 0 : if (port == NULL)
127 : : return -EINVAL;
128 : :
129 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
130 : :
131 : 0 : req = mbox_alloc_msg_mcs_set_lmac_mode(mcs->mbox);
132 [ # # ]: 0 : if (req == NULL)
133 : : return -ENOMEM;
134 : :
135 : 0 : req->lmac_id = port->lmac_id;
136 : 0 : req->mcs_id = mcs->idx;
137 : 0 : req->mode = port->mode;
138 : :
139 : 0 : return mbox_process_msg(mcs->mbox, (void *)&rsp);
140 : : }
141 : :
142 : : int
143 : 0 : roc_mcs_pn_threshold_set(struct roc_mcs *mcs, struct roc_mcs_set_pn_threshold *pn)
144 : : {
145 : : struct mcs_set_pn_threshold *req;
146 : : struct msg_rsp *rsp;
147 : :
148 [ # # ]: 0 : if (pn == NULL)
149 : : return -EINVAL;
150 : :
151 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
152 : :
153 : 0 : req = mbox_alloc_msg_mcs_set_pn_threshold(mcs->mbox);
154 [ # # ]: 0 : if (req == NULL)
155 : : return -ENOMEM;
156 : :
157 : 0 : req->threshold = pn->threshold;
158 : 0 : req->mcs_id = mcs->idx;
159 : 0 : req->dir = pn->dir;
160 : 0 : req->xpn = pn->xpn;
161 : :
162 : 0 : return mbox_process_msg(mcs->mbox, (void *)&rsp);
163 : : }
164 : :
165 : : int
166 [ # # ]: 0 : roc_mcs_ctrl_pkt_rule_alloc(struct roc_mcs *mcs, struct roc_mcs_alloc_ctrl_pkt_rule_req *req,
167 : : struct roc_mcs_alloc_ctrl_pkt_rule_rsp *rsp)
168 : : {
169 : : struct mcs_alloc_ctrl_pkt_rule_req *rule_req;
170 : : struct mcs_alloc_ctrl_pkt_rule_rsp *rule_rsp;
171 : : int rc;
172 : :
173 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
174 : :
175 [ # # ]: 0 : if (req == NULL || rsp == NULL)
176 : : return -EINVAL;
177 : :
178 : 0 : rule_req = mbox_alloc_msg_mcs_alloc_ctrl_pkt_rule(mcs->mbox);
179 [ # # ]: 0 : if (rule_req == NULL)
180 : : return -ENOMEM;
181 : :
182 : 0 : rule_req->rule_type = req->rule_type;
183 : 0 : rule_req->mcs_id = mcs->idx;
184 : 0 : rule_req->dir = req->dir;
185 : :
186 : 0 : rc = mbox_process_msg(mcs->mbox, (void *)&rule_rsp);
187 [ # # ]: 0 : if (rc)
188 : : return rc;
189 : :
190 : 0 : rsp->rule_type = rule_rsp->rule_type;
191 : 0 : rsp->rule_idx = rule_rsp->rule_idx;
192 : 0 : rsp->dir = rule_rsp->dir;
193 : :
194 : 0 : return 0;
195 : : }
196 : :
197 : : int
198 [ # # ]: 0 : roc_mcs_ctrl_pkt_rule_free(struct roc_mcs *mcs, struct roc_mcs_free_ctrl_pkt_rule_req *req)
199 : : {
200 : : struct mcs_free_ctrl_pkt_rule_req *rule_req;
201 : : struct msg_rsp *rsp;
202 : :
203 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
204 : :
205 [ # # ]: 0 : if (req == NULL)
206 : : return -EINVAL;
207 : :
208 : 0 : rule_req = mbox_alloc_msg_mcs_free_ctrl_pkt_rule(mcs->mbox);
209 [ # # ]: 0 : if (rule_req == NULL)
210 : : return -ENOMEM;
211 : :
212 : 0 : rule_req->rule_type = req->rule_type;
213 : 0 : rule_req->rule_idx = req->rule_idx;
214 : 0 : rule_req->mcs_id = mcs->idx;
215 : 0 : rule_req->dir = req->dir;
216 : 0 : rule_req->all = req->all;
217 : :
218 : 0 : return mbox_process_msg(mcs->mbox, (void *)&rsp);
219 : : }
220 : :
221 : : int
222 [ # # ]: 0 : roc_mcs_ctrl_pkt_rule_write(struct roc_mcs *mcs, struct roc_mcs_ctrl_pkt_rule_write_req *req)
223 : : {
224 : : struct mcs_ctrl_pkt_rule_write_req *rule_req;
225 : : struct msg_rsp *rsp;
226 : :
227 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
228 : :
229 [ # # ]: 0 : if (req == NULL)
230 : : return -EINVAL;
231 : :
232 : 0 : rule_req = mbox_alloc_msg_mcs_ctrl_pkt_rule_write(mcs->mbox);
233 [ # # ]: 0 : if (rule_req == NULL)
234 : : return -ENOMEM;
235 : :
236 : 0 : rule_req->rule_type = req->rule_type;
237 : 0 : rule_req->rule_idx = req->rule_idx;
238 : 0 : rule_req->mcs_id = mcs->idx;
239 : 0 : rule_req->dir = req->dir;
240 : 0 : rule_req->data0 = req->data0;
241 : 0 : rule_req->data1 = req->data1;
242 : 0 : rule_req->data2 = req->data2;
243 : :
244 : 0 : return mbox_process_msg(mcs->mbox, (void *)&rsp);
245 : : }
246 : :
247 : : int
248 [ # # ]: 0 : roc_mcs_port_cfg_set(struct roc_mcs *mcs, struct roc_mcs_port_cfg_set_req *req)
249 : : {
250 : : struct mcs_port_cfg_set_req *set_req;
251 : : struct msg_rsp *rsp;
252 : :
253 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
254 : :
255 [ # # ]: 0 : if (req == NULL)
256 : : return -EINVAL;
257 : :
258 : 0 : set_req = mbox_alloc_msg_mcs_port_cfg_set(mcs->mbox);
259 [ # # ]: 0 : if (set_req == NULL)
260 : : return -ENOMEM;
261 : :
262 : 0 : set_req->cstm_tag_rel_mode_sel = req->cstm_tag_rel_mode_sel;
263 : 0 : set_req->custom_hdr_enb = req->custom_hdr_enb;
264 : 0 : set_req->fifo_skid = req->fifo_skid;
265 : 0 : set_req->lmac_mode = req->port_mode;
266 : 0 : set_req->lmac_id = req->port_id;
267 : 0 : set_req->mcs_id = mcs->idx;
268 : :
269 : 0 : return mbox_process_msg(mcs->mbox, (void *)&rsp);
270 : : }
271 : :
272 : : int
273 [ # # ]: 0 : roc_mcs_port_cfg_get(struct roc_mcs *mcs, struct roc_mcs_port_cfg_get_req *req,
274 : : struct roc_mcs_port_cfg_get_rsp *rsp)
275 : : {
276 : : struct mcs_port_cfg_get_req *get_req;
277 : : struct mcs_port_cfg_get_rsp *get_rsp;
278 : : int rc;
279 : :
280 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
281 : :
282 [ # # ]: 0 : if (req == NULL)
283 : : return -EINVAL;
284 : :
285 : 0 : get_req = mbox_alloc_msg_mcs_port_cfg_get(mcs->mbox);
286 [ # # ]: 0 : if (get_req == NULL)
287 : : return -ENOMEM;
288 : :
289 : 0 : get_req->lmac_id = req->port_id;
290 : 0 : get_req->mcs_id = mcs->idx;
291 : :
292 : 0 : rc = mbox_process_msg(mcs->mbox, (void *)&get_rsp);
293 [ # # ]: 0 : if (rc)
294 : : return rc;
295 : :
296 : 0 : rsp->cstm_tag_rel_mode_sel = get_rsp->cstm_tag_rel_mode_sel;
297 : 0 : rsp->custom_hdr_enb = get_rsp->custom_hdr_enb;
298 : 0 : rsp->fifo_skid = get_rsp->fifo_skid;
299 : 0 : rsp->port_mode = get_rsp->lmac_mode;
300 : 0 : rsp->port_id = get_rsp->lmac_id;
301 : :
302 : 0 : return 0;
303 : : }
304 : :
305 : : int
306 [ # # ]: 0 : roc_mcs_custom_tag_cfg_get(struct roc_mcs *mcs, struct roc_mcs_custom_tag_cfg_get_req *req,
307 : : struct roc_mcs_custom_tag_cfg_get_rsp *rsp)
308 : : {
309 : : struct mcs_custom_tag_cfg_get_req *get_req;
310 : : struct mcs_custom_tag_cfg_get_rsp *get_rsp;
311 : : int i, rc;
312 : :
313 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
314 : :
315 [ # # ]: 0 : if (req == NULL)
316 : : return -EINVAL;
317 : :
318 : 0 : get_req = mbox_alloc_msg_mcs_custom_tag_cfg_get(mcs->mbox);
319 [ # # ]: 0 : if (get_req == NULL)
320 : : return -ENOMEM;
321 : :
322 : 0 : get_req->dir = req->dir;
323 : 0 : get_req->mcs_id = mcs->idx;
324 : :
325 : 0 : rc = mbox_process_msg(mcs->mbox, (void *)&get_rsp);
326 [ # # ]: 0 : if (rc)
327 : : return rc;
328 : :
329 [ # # ]: 0 : for (i = 0; i < 8; i++) {
330 : 0 : rsp->cstm_etype[i] = get_rsp->cstm_etype[i];
331 : 0 : rsp->cstm_indx[i] = get_rsp->cstm_indx[i];
332 : : }
333 : :
334 : 0 : rsp->cstm_etype_en = get_rsp->cstm_etype_en;
335 : 0 : rsp->dir = get_rsp->dir;
336 : :
337 : 0 : return 0;
338 : : }
339 : :
340 : : int
341 : 0 : roc_mcs_intr_configure(struct roc_mcs *mcs, struct roc_mcs_intr_cfg *config)
342 : : {
343 : : struct mcs_intr_cfg *req;
344 : : struct msg_rsp *rsp;
345 : : int rc;
346 : :
347 [ # # ]: 0 : if (config == NULL)
348 : : return -EINVAL;
349 : :
350 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
351 : :
352 [ # # ]: 0 : if (mcs->intr_cfg_once)
353 : : return 0;
354 : :
355 : 0 : req = mbox_alloc_msg_mcs_intr_cfg(mcs->mbox);
356 [ # # ]: 0 : if (req == NULL)
357 : : return -ENOMEM;
358 : :
359 : 0 : req->intr_mask = config->intr_mask;
360 : 0 : req->mcs_id = mcs->idx;
361 : :
362 : 0 : rc = mbox_process_msg(mcs->mbox, (void *)&rsp);
363 [ # # ]: 0 : if (rc == 0)
364 : 0 : mcs->intr_cfg_once = true;
365 : :
366 : : return rc;
367 : : }
368 : :
369 : : int
370 : 0 : roc_mcs_port_recovery(struct roc_mcs *mcs, union roc_mcs_event_data *mdata, uint8_t port_id)
371 : : {
372 : : struct mcs_priv *priv = roc_mcs_to_mcs_priv(mcs);
373 : 0 : struct roc_mcs_pn_table_write_req pn_table = {0};
374 : 0 : struct roc_mcs_rx_sc_sa_map rx_map = {0};
375 : 0 : struct roc_mcs_tx_sc_sa_map tx_map = {0};
376 : 0 : struct roc_mcs_port_reset_req port = {0};
377 : 0 : struct roc_mcs_clear_stats stats = {0};
378 : : int tx_cnt = 0, rx_cnt = 0, rc = 0;
379 : : uint64_t set;
380 : : int i;
381 : :
382 : 0 : port.port_id = port_id;
383 : 0 : rc = mcs_port_reset_set(mcs, &port, 1);
384 : :
385 : : /* Reset TX/RX PN tables */
386 [ # # ]: 0 : for (i = 0; i < (priv->sa_entries << 1); i++) {
387 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].sa_bmap, i);
388 [ # # ]: 0 : if (set) {
389 : 0 : pn_table.pn_id = i;
390 : 0 : pn_table.next_pn = 1;
391 : 0 : pn_table.dir = MCS_RX;
392 [ # # ]: 0 : if (i >= priv->sa_entries) {
393 : 0 : pn_table.dir = MCS_TX;
394 : 0 : pn_table.pn_id -= priv->sa_entries;
395 : : }
396 : 0 : rc = roc_mcs_pn_table_write(mcs, &pn_table);
397 [ # # ]: 0 : if (rc)
398 : 0 : return rc;
399 : :
400 [ # # ]: 0 : if (i >= priv->sa_entries)
401 : 0 : tx_cnt++;
402 : : else
403 : 0 : rx_cnt++;
404 : : }
405 : : }
406 : :
407 [ # # ]: 0 : if (tx_cnt || rx_cnt) {
408 : 0 : mdata->tx_sa_array = plt_zmalloc(tx_cnt * sizeof(uint16_t), 0);
409 [ # # # # ]: 0 : if (tx_cnt && (mdata->tx_sa_array == NULL)) {
410 : : rc = -ENOMEM;
411 : 0 : goto exit;
412 : : }
413 : 0 : mdata->rx_sa_array = plt_zmalloc(rx_cnt * sizeof(uint16_t), 0);
414 [ # # # # ]: 0 : if (rx_cnt && (mdata->rx_sa_array == NULL)) {
415 : : rc = -ENOMEM;
416 : 0 : goto exit;
417 : : }
418 : :
419 : 0 : mdata->num_tx_sa = tx_cnt;
420 : 0 : mdata->num_rx_sa = rx_cnt;
421 [ # # ]: 0 : for (i = 0; i < (priv->sa_entries << 1); i++) {
422 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].sa_bmap, i);
423 [ # # ]: 0 : if (set) {
424 [ # # ]: 0 : if (i >= priv->sa_entries)
425 : 0 : mdata->tx_sa_array[--tx_cnt] = i - priv->sa_entries;
426 : : else
427 : 0 : mdata->rx_sa_array[--rx_cnt] = i;
428 : : }
429 : : }
430 : : }
431 : : tx_cnt = 0;
432 : : rx_cnt = 0;
433 : :
434 : : /* Reset Tx active SA to index:0 */
435 [ # # ]: 0 : for (i = priv->sc_entries; i < (priv->sc_entries << 1); i++) {
436 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
437 [ # # ]: 0 : if (set) {
438 : 0 : uint16_t sc_id = i - priv->sc_entries;
439 : :
440 : 0 : tx_map.sa_index0 = priv->port_rsrc[port_id].sc_conf[sc_id].tx.sa_idx0;
441 : 0 : tx_map.sa_index1 = priv->port_rsrc[port_id].sc_conf[sc_id].tx.sa_idx1;
442 : 0 : tx_map.rekey_ena = priv->port_rsrc[port_id].sc_conf[sc_id].tx.rekey_enb;
443 : 0 : tx_map.sectag_sci = priv->port_rsrc[port_id].sc_conf[sc_id].tx.sci;
444 : 0 : tx_map.sa_index0_vld = 1;
445 : 0 : tx_map.sa_index1_vld = 0;
446 : 0 : tx_map.tx_sa_active = 0;
447 : 0 : tx_map.sc_id = sc_id;
448 : 0 : rc = roc_mcs_tx_sc_sa_map_write(mcs, &tx_map);
449 [ # # ]: 0 : if (rc)
450 : 0 : return rc;
451 : :
452 : 0 : tx_cnt++;
453 : : }
454 : : }
455 : :
456 [ # # ]: 0 : if (tx_cnt) {
457 : 0 : mdata->tx_sc_array = plt_zmalloc(tx_cnt * sizeof(uint16_t), 0);
458 [ # # ]: 0 : if (tx_cnt && (mdata->tx_sc_array == NULL)) {
459 : : rc = -ENOMEM;
460 : 0 : goto exit;
461 : : }
462 : :
463 : 0 : mdata->num_tx_sc = tx_cnt;
464 [ # # ]: 0 : for (i = priv->sc_entries; i < (priv->sc_entries << 1); i++) {
465 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
466 [ # # ]: 0 : if (set)
467 : 0 : mdata->tx_sc_array[--tx_cnt] = i - priv->sc_entries;
468 : : }
469 : : }
470 : :
471 : : /* Clear SA_IN_USE for active ANs in RX CPM */
472 [ # # ]: 0 : for (i = 0; i < priv->sc_entries; i++) {
473 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
474 [ # # ]: 0 : if (set) {
475 : 0 : rx_map.sa_index = priv->port_rsrc[port_id].sc_conf[i].rx.sa_idx;
476 : 0 : rx_map.an = priv->port_rsrc[port_id].sc_conf[i].rx.an;
477 : 0 : rx_map.sa_in_use = 0;
478 : 0 : rx_map.sc_id = i;
479 : 0 : rc = roc_mcs_rx_sc_sa_map_write(mcs, &rx_map);
480 [ # # ]: 0 : if (rc)
481 : 0 : return rc;
482 : :
483 : 0 : rx_cnt++;
484 : : }
485 : : }
486 : :
487 : : /* Reset flow(flow/secy/sc/sa) stats mapped to this PORT */
488 [ # # ]: 0 : for (i = 0; i < (priv->tcam_entries << 1); i++) {
489 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].tcam_bmap, i);
490 [ # # ]: 0 : if (set) {
491 : 0 : stats.type = MCS_FLOWID_STATS;
492 : 0 : stats.id = i;
493 : 0 : stats.dir = MCS_RX;
494 [ # # ]: 0 : if (i >= priv->sa_entries) {
495 : 0 : stats.dir = MCS_TX;
496 : 0 : stats.id -= priv->tcam_entries;
497 : : }
498 : 0 : rc = roc_mcs_stats_clear(mcs, &stats);
499 [ # # ]: 0 : if (rc)
500 : 0 : return rc;
501 : : }
502 : : }
503 [ # # ]: 0 : for (i = 0; i < (priv->secy_entries << 1); i++) {
504 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].secy_bmap, i);
505 [ # # ]: 0 : if (set) {
506 : 0 : stats.type = MCS_SECY_STATS;
507 : 0 : stats.id = i;
508 : 0 : stats.dir = MCS_RX;
509 [ # # ]: 0 : if (i >= priv->sa_entries) {
510 : 0 : stats.dir = MCS_TX;
511 : 0 : stats.id -= priv->secy_entries;
512 : : }
513 : 0 : rc = roc_mcs_stats_clear(mcs, &stats);
514 [ # # ]: 0 : if (rc)
515 : 0 : return rc;
516 : : }
517 : : }
518 [ # # ]: 0 : for (i = 0; i < (priv->sc_entries << 1); i++) {
519 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
520 [ # # ]: 0 : if (set) {
521 : 0 : stats.type = MCS_SC_STATS;
522 : 0 : stats.id = i;
523 : 0 : stats.dir = MCS_RX;
524 [ # # ]: 0 : if (i >= priv->sa_entries) {
525 : 0 : stats.dir = MCS_TX;
526 : 0 : stats.id -= priv->sc_entries;
527 : : }
528 : 0 : rc = roc_mcs_stats_clear(mcs, &stats);
529 [ # # ]: 0 : if (rc)
530 : 0 : return rc;
531 : : }
532 : : }
533 [ # # ]: 0 : if (roc_model_is_cn10kb_a0()) {
534 [ # # ]: 0 : for (i = 0; i < (priv->sa_entries << 1); i++) {
535 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].sa_bmap, i);
536 [ # # ]: 0 : if (set) {
537 : 0 : stats.type = MCS_SA_STATS;
538 : 0 : stats.id = i;
539 : 0 : stats.dir = MCS_RX;
540 [ # # ]: 0 : if (i >= priv->sa_entries) {
541 : 0 : stats.dir = MCS_TX;
542 : 0 : stats.id -= priv->sa_entries;
543 : : }
544 : 0 : rc = roc_mcs_stats_clear(mcs, &stats);
545 [ # # ]: 0 : if (rc)
546 : 0 : return rc;
547 : : }
548 : : }
549 : : }
550 : : {
551 : 0 : stats.type = MCS_PORT_STATS;
552 : 0 : stats.id = port_id;
553 : 0 : rc = roc_mcs_stats_clear(mcs, &stats);
554 [ # # ]: 0 : if (rc)
555 : : return rc;
556 : : }
557 : :
558 [ # # ]: 0 : if (rx_cnt) {
559 : 0 : mdata->rx_sc_array = plt_zmalloc(rx_cnt * sizeof(uint16_t), 0);
560 [ # # ]: 0 : if (mdata->rx_sc_array == NULL) {
561 : : rc = -ENOMEM;
562 : 0 : goto exit;
563 : : }
564 : 0 : mdata->sc_an_array = plt_zmalloc(rx_cnt * sizeof(uint8_t), 0);
565 [ # # ]: 0 : if (mdata->sc_an_array == NULL) {
566 : : rc = -ENOMEM;
567 : 0 : goto exit;
568 : : }
569 : :
570 : 0 : mdata->num_rx_sc = rx_cnt;
571 : : }
572 : :
573 : : /* Reactivate in-use ANs for active SCs in RX CPM */
574 [ # # ]: 0 : for (i = 0; i < priv->sc_entries; i++) {
575 [ # # ]: 0 : set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
576 [ # # ]: 0 : if (set) {
577 : 0 : rx_map.sa_index = priv->port_rsrc[port_id].sc_conf[i].rx.sa_idx;
578 : 0 : rx_map.an = priv->port_rsrc[port_id].sc_conf[i].rx.an;
579 : 0 : rx_map.sa_in_use = 1;
580 : 0 : rx_map.sc_id = i;
581 : 0 : rc = roc_mcs_rx_sc_sa_map_write(mcs, &rx_map);
582 [ # # ]: 0 : if (rc)
583 : 0 : return rc;
584 : :
585 : 0 : mdata->rx_sc_array[--rx_cnt] = i;
586 : 0 : mdata->sc_an_array[rx_cnt] = priv->port_rsrc[port_id].sc_conf[i].rx.an;
587 : : }
588 : : }
589 : :
590 : 0 : port.port_id = port_id;
591 : 0 : rc = mcs_port_reset_set(mcs, &port, 0);
592 : :
593 : 0 : return rc;
594 : 0 : exit:
595 [ # # ]: 0 : if (mdata->num_tx_sa)
596 : 0 : plt_free(mdata->tx_sa_array);
597 [ # # ]: 0 : if (mdata->num_rx_sa)
598 : 0 : plt_free(mdata->rx_sa_array);
599 [ # # ]: 0 : if (mdata->num_tx_sc)
600 : 0 : plt_free(mdata->tx_sc_array);
601 [ # # ]: 0 : if (mdata->num_rx_sc) {
602 : 0 : plt_free(mdata->rx_sc_array);
603 : 0 : plt_free(mdata->sc_an_array);
604 : : }
605 : : return rc;
606 : : }
607 : :
608 : : int
609 : 0 : roc_mcs_port_reset(struct roc_mcs *mcs, struct roc_mcs_port_reset_req *port)
610 : : {
611 : 0 : struct roc_mcs_event_desc desc = {0};
612 : : int rc;
613 : :
614 : : /* Initiate port reset and software recovery */
615 : 0 : rc = roc_mcs_port_recovery(mcs, &desc.metadata, port->port_id);
616 [ # # ]: 0 : if (rc)
617 : 0 : goto exit;
618 : :
619 : 0 : desc.type = ROC_MCS_EVENT_PORT_RESET_RECOVERY;
620 : : /* Notify the entity details to the application which are recovered */
621 : 0 : mcs_event_cb_process(mcs, &desc);
622 : :
623 : 0 : exit:
624 [ # # ]: 0 : if (desc.metadata.num_tx_sa)
625 : 0 : plt_free(desc.metadata.tx_sa_array);
626 [ # # ]: 0 : if (desc.metadata.num_rx_sa)
627 : 0 : plt_free(desc.metadata.rx_sa_array);
628 [ # # ]: 0 : if (desc.metadata.num_tx_sc)
629 : 0 : plt_free(desc.metadata.tx_sc_array);
630 [ # # ]: 0 : if (desc.metadata.num_rx_sc) {
631 : 0 : plt_free(desc.metadata.rx_sc_array);
632 : 0 : plt_free(desc.metadata.sc_an_array);
633 : : }
634 : :
635 : 0 : return rc;
636 : : }
637 : :
638 : : int
639 [ # # ]: 0 : roc_mcs_event_cb_register(struct roc_mcs *mcs, enum roc_mcs_event_type event,
640 : : roc_mcs_dev_cb_fn cb_fn, void *cb_arg, void *userdata)
641 : : {
642 : : struct mcs_event_cb_list *cb_list = (struct mcs_event_cb_list *)roc_mcs_to_mcs_cb_list(mcs);
643 : : struct mcs_event_cb *cb;
644 : :
645 [ # # # # ]: 0 : if (cb_fn == NULL || cb_arg == NULL || userdata == NULL)
646 : : return -EINVAL;
647 : :
648 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
649 : :
650 [ # # ]: 0 : TAILQ_FOREACH(cb, cb_list, next) {
651 [ # # # # : 0 : if (cb->cb_fn == cb_fn && cb->cb_arg == cb_arg && cb->event == event)
# # ]
652 : : break;
653 : : }
654 : :
655 [ # # ]: 0 : if (cb == NULL) {
656 : 0 : cb = plt_zmalloc(sizeof(struct mcs_event_cb), 0);
657 [ # # ]: 0 : if (!cb)
658 : : return -ENOMEM;
659 : :
660 : 0 : cb->cb_fn = cb_fn;
661 : 0 : cb->cb_arg = cb_arg;
662 : 0 : cb->event = event;
663 : 0 : cb->userdata = userdata;
664 : 0 : TAILQ_INSERT_TAIL(cb_list, cb, next);
665 : : }
666 : :
667 : : return 0;
668 : : }
669 : :
670 : : int
671 [ # # ]: 0 : roc_mcs_event_cb_unregister(struct roc_mcs *mcs, enum roc_mcs_event_type event)
672 : : {
673 : : struct mcs_event_cb_list *cb_list = (struct mcs_event_cb_list *)roc_mcs_to_mcs_cb_list(mcs);
674 : : struct mcs_event_cb *cb, *next;
675 : :
676 [ # # # # ]: 0 : MCS_SUPPORT_CHECK;
677 : :
678 [ # # ]: 0 : for (cb = TAILQ_FIRST(cb_list); cb != NULL; cb = next) {
679 : 0 : next = TAILQ_NEXT(cb, next);
680 : :
681 [ # # ]: 0 : if (cb->event != event)
682 : 0 : continue;
683 : :
684 [ # # ]: 0 : if (cb->active == 0) {
685 [ # # ]: 0 : TAILQ_REMOVE(cb_list, cb, next);
686 : 0 : plt_free(cb);
687 : : } else {
688 : : return -EAGAIN;
689 : : }
690 : : }
691 : :
692 : : return 0;
693 : : }
694 : :
695 : : int
696 : 0 : mcs_event_cb_process(struct roc_mcs *mcs, struct roc_mcs_event_desc *desc)
697 : : {
698 : : struct mcs_event_cb_list *cb_list = (struct mcs_event_cb_list *)roc_mcs_to_mcs_cb_list(mcs);
699 : : struct mcs_event_cb mcs_cb;
700 : : struct mcs_event_cb *cb;
701 : : int rc = 0;
702 : :
703 [ # # ]: 0 : TAILQ_FOREACH(cb, cb_list, next) {
704 [ # # # # ]: 0 : if (cb->cb_fn == NULL || cb->event != desc->type)
705 : 0 : continue;
706 : :
707 : 0 : mcs_cb = *cb;
708 : 0 : cb->active = 1;
709 : : mcs_cb.ret_param = desc;
710 : :
711 : 0 : rc = mcs_cb.cb_fn(mcs_cb.userdata, mcs_cb.ret_param, mcs_cb.cb_arg,
712 : 0 : mcs->sa_port_map[desc->metadata.sa_idx]);
713 : 0 : cb->active = 0;
714 : : }
715 : :
716 : 0 : return rc;
717 : : }
718 : :
719 : : static int
720 : 0 : mcs_alloc_bmap(uint16_t entries, void **mem, struct plt_bitmap **bmap)
721 : : {
722 : : size_t bmap_sz;
723 : : int rc = 0;
724 : :
725 : 0 : bmap_sz = plt_bitmap_get_memory_footprint(entries);
726 : 0 : *mem = plt_zmalloc(bmap_sz, PLT_CACHE_LINE_SIZE);
727 [ # # ]: 0 : if (*mem == NULL)
728 : : rc = -ENOMEM;
729 : :
730 : 0 : *bmap = plt_bitmap_init(entries, *mem, bmap_sz);
731 [ # # ]: 0 : if (!*bmap) {
732 : 0 : plt_free(*mem);
733 : 0 : *mem = NULL;
734 : : rc = -ENOMEM;
735 : : }
736 : :
737 : 0 : return rc;
738 : : }
739 : :
740 : : static void
741 : 0 : rsrc_bmap_free(struct mcs_rsrc *rsrc)
742 : : {
743 : : plt_bitmap_free(rsrc->tcam_bmap);
744 : 0 : plt_free(rsrc->tcam_bmap_mem);
745 : : plt_bitmap_free(rsrc->secy_bmap);
746 : 0 : plt_free(rsrc->secy_bmap_mem);
747 : : plt_bitmap_free(rsrc->sc_bmap);
748 : 0 : plt_free(rsrc->sc_bmap_mem);
749 : : plt_bitmap_free(rsrc->sa_bmap);
750 : 0 : plt_free(rsrc->sa_bmap_mem);
751 : 0 : }
752 : :
753 : : static int
754 : 0 : rsrc_bmap_alloc(struct mcs_priv *priv, struct mcs_rsrc *rsrc)
755 : : {
756 : : int rc;
757 : :
758 : 0 : rc = mcs_alloc_bmap(priv->tcam_entries << 1, &rsrc->tcam_bmap_mem, &rsrc->tcam_bmap);
759 [ # # ]: 0 : if (rc)
760 : 0 : goto exit;
761 : :
762 : 0 : rc = mcs_alloc_bmap(priv->secy_entries << 1, &rsrc->secy_bmap_mem, &rsrc->secy_bmap);
763 [ # # ]: 0 : if (rc)
764 : 0 : goto exit;
765 : :
766 : 0 : rc = mcs_alloc_bmap(priv->sc_entries << 1, &rsrc->sc_bmap_mem, &rsrc->sc_bmap);
767 [ # # ]: 0 : if (rc)
768 : 0 : goto exit;
769 : :
770 : 0 : rc = mcs_alloc_bmap(priv->sa_entries << 1, &rsrc->sa_bmap_mem, &rsrc->sa_bmap);
771 [ # # ]: 0 : if (rc)
772 : 0 : goto exit;
773 : :
774 : : return rc;
775 : 0 : exit:
776 : 0 : rsrc_bmap_free(rsrc);
777 : :
778 : 0 : return rc;
779 : : }
780 : :
781 : : static int
782 : 0 : mcs_alloc_rsrc_bmap(struct roc_mcs *mcs)
783 : : {
784 : : struct mcs_priv *priv = roc_mcs_to_mcs_priv(mcs);
785 : : struct mcs_hw_info *hw;
786 : : int i, rc;
787 : :
788 : 0 : mbox_alloc_msg_mcs_get_hw_info(mcs->mbox);
789 : 0 : rc = mbox_process_msg(mcs->mbox, (void *)&hw);
790 [ # # ]: 0 : if (rc)
791 : : return rc;
792 : :
793 : 0 : priv->num_mcs_blks = hw->num_mcs_blks;
794 : 0 : priv->tcam_entries = hw->tcam_entries;
795 : 0 : priv->secy_entries = hw->secy_entries;
796 : 0 : priv->sc_entries = hw->sc_entries;
797 : 0 : priv->sa_entries = hw->sa_entries;
798 : :
799 : 0 : rc = rsrc_bmap_alloc(priv, &priv->dev_rsrc);
800 [ # # ]: 0 : if (rc)
801 : : return rc;
802 : :
803 : 0 : priv->port_rsrc = plt_zmalloc(sizeof(struct mcs_rsrc) * 4, 0);
804 [ # # ]: 0 : if (priv->port_rsrc == NULL) {
805 : 0 : rsrc_bmap_free(&priv->dev_rsrc);
806 : 0 : return -ENOMEM;
807 : : }
808 : :
809 [ # # ]: 0 : for (i = 0; i < MAX_PORTS_PER_MCS; i++) {
810 : 0 : rc = rsrc_bmap_alloc(priv, &priv->port_rsrc[i]);
811 [ # # ]: 0 : if (rc)
812 : 0 : goto exit;
813 : :
814 : 0 : priv->port_rsrc[i].sc_conf =
815 : 0 : plt_zmalloc(priv->sc_entries * sizeof(struct mcs_sc_conf), 0);
816 [ # # ]: 0 : if (priv->port_rsrc[i].sc_conf == NULL) {
817 : 0 : rsrc_bmap_free(&priv->port_rsrc[i]);
818 : 0 : goto exit;
819 : : }
820 : : }
821 : :
822 : 0 : mcs->sa_port_map = plt_zmalloc(sizeof(uint8_t) * hw->sa_entries, 0);
823 [ # # ]: 0 : if (mcs->sa_port_map == NULL)
824 : 0 : goto exit;
825 : :
826 : : return rc;
827 : :
828 : : exit:
829 [ # # ]: 0 : while (i--) {
830 : 0 : rsrc_bmap_free(&priv->port_rsrc[i]);
831 : 0 : plt_free(priv->port_rsrc[i].sc_conf);
832 : : }
833 : 0 : plt_free(priv->port_rsrc);
834 : :
835 : 0 : return -ENOMEM;
836 : : }
837 : :
838 : : struct roc_mcs *
839 [ # # ]: 0 : roc_mcs_dev_init(uint8_t mcs_idx)
840 : : {
841 : : struct mcs_event_cb_list *cb_list;
842 : : struct roc_mcs *mcs;
843 : : struct npa_lf *npa;
844 : :
845 [ # # # # ]: 0 : if (!(roc_feature_bphy_has_macsec() || roc_feature_nix_has_macsec()))
846 : : return NULL;
847 : :
848 : 0 : mcs = roc_idev_mcs_get(mcs_idx);
849 [ # # ]: 0 : if (mcs) {
850 : 0 : plt_info("Skipping device, mcs device already probed");
851 : 0 : mcs->refcount++;
852 : 0 : return mcs;
853 : : }
854 : :
855 : 0 : mcs = plt_zmalloc(sizeof(struct roc_mcs), PLT_CACHE_LINE_SIZE);
856 [ # # ]: 0 : if (!mcs)
857 : : return NULL;
858 : :
859 : 0 : npa = idev_npa_obj_get();
860 [ # # ]: 0 : if (!npa)
861 : 0 : goto exit;
862 : :
863 : 0 : mcs->mbox = npa->mbox;
864 : 0 : mcs->idx = mcs_idx;
865 : :
866 : : /* Add any per mcsv initialization */
867 [ # # ]: 0 : if (mcs_alloc_rsrc_bmap(mcs))
868 : 0 : goto exit;
869 : :
870 : : cb_list = (struct mcs_event_cb_list *)roc_mcs_to_mcs_cb_list(mcs);
871 : 0 : TAILQ_INIT(cb_list);
872 : :
873 : 0 : roc_idev_mcs_set(mcs);
874 : 0 : mcs->refcount++;
875 : :
876 : 0 : return mcs;
877 : 0 : exit:
878 : 0 : plt_free(mcs);
879 : 0 : return NULL;
880 : : }
881 : :
882 : : void
883 : 0 : roc_mcs_dev_fini(struct roc_mcs *mcs)
884 : : {
885 : : struct mcs_priv *priv;
886 : : int i;
887 : :
888 : 0 : mcs->refcount--;
889 [ # # ]: 0 : if (mcs->refcount > 0)
890 : : return;
891 : :
892 : : priv = roc_mcs_to_mcs_priv(mcs);
893 : :
894 : 0 : rsrc_bmap_free(&priv->dev_rsrc);
895 : :
896 [ # # ]: 0 : for (i = 0; i < MAX_PORTS_PER_MCS; i++) {
897 : 0 : rsrc_bmap_free(&priv->port_rsrc[i]);
898 : 0 : plt_free(priv->port_rsrc[i].sc_conf);
899 : : }
900 : :
901 : 0 : plt_free(priv->port_rsrc);
902 : :
903 : 0 : plt_free(mcs->sa_port_map);
904 : :
905 : 0 : roc_idev_mcs_free(mcs);
906 : :
907 : 0 : plt_free(mcs);
908 : : }
|