WIP FPC-III support
[linux/fpc-iii.git] / drivers / net / ethernet / aquantia / atlantic / macsec / macsec_api.c
blob36c7cf05630a1ea4711cde2d1a88d7a0050ed0d0
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Atlantic Network Driver
3 * Copyright (C) 2020 Marvell International Ltd.
4 */
6 #include "macsec_api.h"
7 #include <linux/mdio.h>
8 #include "MSS_Ingress_registers.h"
9 #include "MSS_Egress_registers.h"
10 #include "aq_phy.h"
12 #define AQ_API_CALL_SAFE(func, ...) \
13 ({ \
14 int ret; \
15 do { \
16 ret = aq_mss_mdio_sem_get(hw); \
17 if (unlikely(ret)) \
18 break; \
20 ret = func(__VA_ARGS__); \
22 aq_mss_mdio_sem_put(hw); \
23 } while (0); \
24 ret; \
27 /*******************************************************************************
28 * MDIO wrappers
29 ******************************************************************************/
30 static int aq_mss_mdio_sem_get(struct aq_hw_s *hw)
32 u32 val;
34 return readx_poll_timeout_atomic(hw_atl_sem_mdio_get, hw, val,
35 val == 1U, 10U, 100000U);
38 static void aq_mss_mdio_sem_put(struct aq_hw_s *hw)
40 hw_atl_reg_glb_cpu_sem_set(hw, 1U, HW_ATL_FW_SM_MDIO);
43 static int aq_mss_mdio_read(struct aq_hw_s *hw, u16 mmd, u16 addr, u16 *data)
45 *data = aq_mdio_read_word(hw, mmd, addr);
46 return (*data != 0xffff) ? 0 : -ETIME;
49 static int aq_mss_mdio_write(struct aq_hw_s *hw, u16 mmd, u16 addr, u16 data)
51 aq_mdio_write_word(hw, mmd, addr, data);
52 return 0;
55 /*******************************************************************************
56 * MACSEC config and status
57 ******************************************************************************/
59 static int set_raw_ingress_record(struct aq_hw_s *hw, u16 *packed_record,
60 u8 num_words, u8 table_id,
61 u16 table_index)
63 struct mss_ingress_lut_addr_ctl_register lut_sel_reg;
64 struct mss_ingress_lut_ctl_register lut_op_reg;
66 unsigned int i;
68 /* NOTE: MSS registers must always be read/written as adjacent pairs.
69 * For instance, to write either or both 1E.80A0 and 80A1, we have to:
70 * 1. Write 1E.80A0 first
71 * 2. Then write 1E.80A1
73 * For HHD devices: These writes need to be performed consecutively, and
74 * to ensure this we use the PIF mailbox to delegate the reads/writes to
75 * the FW.
77 * For EUR devices: Not need to use the PIF mailbox; it is safe to
78 * write to the registers directly.
81 /* Write the packed record words to the data buffer registers. */
82 for (i = 0; i < num_words; i += 2) {
83 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
84 MSS_INGRESS_LUT_DATA_CTL_REGISTER_ADDR + i,
85 packed_record[i]);
86 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
87 MSS_INGRESS_LUT_DATA_CTL_REGISTER_ADDR + i +
89 packed_record[i + 1]);
92 /* Clear out the unused data buffer registers. */
93 for (i = num_words; i < 24; i += 2) {
94 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
95 MSS_INGRESS_LUT_DATA_CTL_REGISTER_ADDR + i,
96 0);
97 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
98 MSS_INGRESS_LUT_DATA_CTL_REGISTER_ADDR + i + 1, 0);
101 /* Select the table and row index to write to */
102 lut_sel_reg.bits_0.lut_select = table_id;
103 lut_sel_reg.bits_0.lut_addr = table_index;
105 lut_op_reg.bits_0.lut_read = 0;
106 lut_op_reg.bits_0.lut_write = 1;
108 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
109 MSS_INGRESS_LUT_ADDR_CTL_REGISTER_ADDR,
110 lut_sel_reg.word_0);
111 aq_mss_mdio_write(hw, MDIO_MMD_VEND1, MSS_INGRESS_LUT_CTL_REGISTER_ADDR,
112 lut_op_reg.word_0);
114 return 0;
117 /*! Read the specified Ingress LUT table row.
118 * packed_record - [OUT] The table row data (raw).
120 static int get_raw_ingress_record(struct aq_hw_s *hw, u16 *packed_record,
121 u8 num_words, u8 table_id,
122 u16 table_index)
124 struct mss_ingress_lut_addr_ctl_register lut_sel_reg;
125 struct mss_ingress_lut_ctl_register lut_op_reg;
126 int ret;
128 unsigned int i;
130 /* Select the table and row index to read */
131 lut_sel_reg.bits_0.lut_select = table_id;
132 lut_sel_reg.bits_0.lut_addr = table_index;
134 lut_op_reg.bits_0.lut_read = 1;
135 lut_op_reg.bits_0.lut_write = 0;
137 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
138 MSS_INGRESS_LUT_ADDR_CTL_REGISTER_ADDR,
139 lut_sel_reg.word_0);
140 if (unlikely(ret))
141 return ret;
142 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
143 MSS_INGRESS_LUT_CTL_REGISTER_ADDR,
144 lut_op_reg.word_0);
145 if (unlikely(ret))
146 return ret;
148 memset(packed_record, 0, sizeof(u16) * num_words);
150 for (i = 0; i < num_words; i += 2) {
151 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
152 MSS_INGRESS_LUT_DATA_CTL_REGISTER_ADDR +
154 &packed_record[i]);
155 if (unlikely(ret))
156 return ret;
157 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
158 MSS_INGRESS_LUT_DATA_CTL_REGISTER_ADDR +
159 i + 1,
160 &packed_record[i + 1]);
161 if (unlikely(ret))
162 return ret;
165 return 0;
168 /*! Write packed_record to the specified Egress LUT table row. */
169 static int set_raw_egress_record(struct aq_hw_s *hw, u16 *packed_record,
170 u8 num_words, u8 table_id,
171 u16 table_index)
173 struct mss_egress_lut_addr_ctl_register lut_sel_reg;
174 struct mss_egress_lut_ctl_register lut_op_reg;
176 unsigned int i;
178 /* Write the packed record words to the data buffer registers. */
179 for (i = 0; i < num_words; i += 2) {
180 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
181 MSS_EGRESS_LUT_DATA_CTL_REGISTER_ADDR + i,
182 packed_record[i]);
183 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
184 MSS_EGRESS_LUT_DATA_CTL_REGISTER_ADDR + i + 1,
185 packed_record[i + 1]);
188 /* Clear out the unused data buffer registers. */
189 for (i = num_words; i < 28; i += 2) {
190 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
191 MSS_EGRESS_LUT_DATA_CTL_REGISTER_ADDR + i, 0);
192 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
193 MSS_EGRESS_LUT_DATA_CTL_REGISTER_ADDR + i + 1,
197 /* Select the table and row index to write to */
198 lut_sel_reg.bits_0.lut_select = table_id;
199 lut_sel_reg.bits_0.lut_addr = table_index;
201 lut_op_reg.bits_0.lut_read = 0;
202 lut_op_reg.bits_0.lut_write = 1;
204 aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
205 MSS_EGRESS_LUT_ADDR_CTL_REGISTER_ADDR,
206 lut_sel_reg.word_0);
207 aq_mss_mdio_write(hw, MDIO_MMD_VEND1, MSS_EGRESS_LUT_CTL_REGISTER_ADDR,
208 lut_op_reg.word_0);
210 return 0;
213 static int get_raw_egress_record(struct aq_hw_s *hw, u16 *packed_record,
214 u8 num_words, u8 table_id,
215 u16 table_index)
217 struct mss_egress_lut_addr_ctl_register lut_sel_reg;
218 struct mss_egress_lut_ctl_register lut_op_reg;
219 int ret;
221 unsigned int i;
223 /* Select the table and row index to read */
224 lut_sel_reg.bits_0.lut_select = table_id;
225 lut_sel_reg.bits_0.lut_addr = table_index;
227 lut_op_reg.bits_0.lut_read = 1;
228 lut_op_reg.bits_0.lut_write = 0;
230 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
231 MSS_EGRESS_LUT_ADDR_CTL_REGISTER_ADDR,
232 lut_sel_reg.word_0);
233 if (unlikely(ret))
234 return ret;
235 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
236 MSS_EGRESS_LUT_CTL_REGISTER_ADDR,
237 lut_op_reg.word_0);
238 if (unlikely(ret))
239 return ret;
241 memset(packed_record, 0, sizeof(u16) * num_words);
243 for (i = 0; i < num_words; i += 2) {
244 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
245 MSS_EGRESS_LUT_DATA_CTL_REGISTER_ADDR +
247 &packed_record[i]);
248 if (unlikely(ret))
249 return ret;
250 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
251 MSS_EGRESS_LUT_DATA_CTL_REGISTER_ADDR +
252 i + 1,
253 &packed_record[i + 1]);
254 if (unlikely(ret))
255 return ret;
258 return 0;
261 static int
262 set_ingress_prectlf_record(struct aq_hw_s *hw,
263 const struct aq_mss_ingress_prectlf_record *rec,
264 u16 table_index)
266 u16 packed_record[6];
268 if (table_index >= NUMROWS_INGRESSPRECTLFRECORD)
269 return -EINVAL;
271 memset(packed_record, 0, sizeof(u16) * 6);
273 packed_record[0] = rec->sa_da[0] & 0xFFFF;
274 packed_record[1] = (rec->sa_da[0] >> 16) & 0xFFFF;
275 packed_record[2] = rec->sa_da[1] & 0xFFFF;
276 packed_record[3] = rec->eth_type & 0xFFFF;
277 packed_record[4] = rec->match_mask & 0xFFFF;
278 packed_record[5] = rec->match_type & 0xF;
279 packed_record[5] |= (rec->action & 0x1) << 4;
281 return set_raw_ingress_record(hw, packed_record, 6, 0,
282 ROWOFFSET_INGRESSPRECTLFRECORD +
283 table_index);
286 int aq_mss_set_ingress_prectlf_record(struct aq_hw_s *hw,
287 const struct aq_mss_ingress_prectlf_record *rec,
288 u16 table_index)
290 return AQ_API_CALL_SAFE(set_ingress_prectlf_record, hw, rec,
291 table_index);
294 static int get_ingress_prectlf_record(struct aq_hw_s *hw,
295 struct aq_mss_ingress_prectlf_record *rec,
296 u16 table_index)
298 u16 packed_record[6];
299 int ret;
301 if (table_index >= NUMROWS_INGRESSPRECTLFRECORD)
302 return -EINVAL;
304 /* If the row that we want to read is odd, first read the previous even
305 * row, throw that value away, and finally read the desired row.
306 * This is a workaround for EUR devices that allows us to read
307 * odd-numbered rows. For HHD devices: this workaround will not work,
308 * so don't bother; odd-numbered rows are not readable.
310 if ((table_index % 2) > 0) {
311 ret = get_raw_ingress_record(hw, packed_record, 6, 0,
312 ROWOFFSET_INGRESSPRECTLFRECORD +
313 table_index - 1);
314 if (unlikely(ret))
315 return ret;
318 ret = get_raw_ingress_record(hw, packed_record, 6, 0,
319 ROWOFFSET_INGRESSPRECTLFRECORD +
320 table_index);
321 if (unlikely(ret))
322 return ret;
324 rec->sa_da[0] = packed_record[0];
325 rec->sa_da[0] |= packed_record[1] << 16;
327 rec->sa_da[1] = packed_record[2];
329 rec->eth_type = packed_record[3];
331 rec->match_mask = packed_record[4];
333 rec->match_type = packed_record[5] & 0xF;
335 rec->action = (packed_record[5] >> 4) & 0x1;
337 return 0;
340 int aq_mss_get_ingress_prectlf_record(struct aq_hw_s *hw,
341 struct aq_mss_ingress_prectlf_record *rec,
342 u16 table_index)
344 memset(rec, 0, sizeof(*rec));
346 return AQ_API_CALL_SAFE(get_ingress_prectlf_record, hw, rec,
347 table_index);
350 static int
351 set_ingress_preclass_record(struct aq_hw_s *hw,
352 const struct aq_mss_ingress_preclass_record *rec,
353 u16 table_index)
355 u16 packed_record[20];
357 if (table_index >= NUMROWS_INGRESSPRECLASSRECORD)
358 return -EINVAL;
360 memset(packed_record, 0, sizeof(u16) * 20);
362 packed_record[0] = rec->sci[0] & 0xFFFF;
363 packed_record[1] = (rec->sci[0] >> 16) & 0xFFFF;
365 packed_record[2] = rec->sci[1] & 0xFFFF;
366 packed_record[3] = (rec->sci[1] >> 16) & 0xFFFF;
368 packed_record[4] = rec->tci & 0xFF;
370 packed_record[4] |= (rec->encr_offset & 0xFF) << 8;
372 packed_record[5] = rec->eth_type & 0xFFFF;
374 packed_record[6] = rec->snap[0] & 0xFFFF;
375 packed_record[7] = (rec->snap[0] >> 16) & 0xFFFF;
377 packed_record[8] = rec->snap[1] & 0xFF;
379 packed_record[8] |= (rec->llc & 0xFF) << 8;
380 packed_record[9] = (rec->llc >> 8) & 0xFFFF;
382 packed_record[10] = rec->mac_sa[0] & 0xFFFF;
383 packed_record[11] = (rec->mac_sa[0] >> 16) & 0xFFFF;
385 packed_record[12] = rec->mac_sa[1] & 0xFFFF;
387 packed_record[13] = rec->mac_da[0] & 0xFFFF;
388 packed_record[14] = (rec->mac_da[0] >> 16) & 0xFFFF;
390 packed_record[15] = rec->mac_da[1] & 0xFFFF;
392 packed_record[16] = rec->lpbk_packet & 0x1;
394 packed_record[16] |= (rec->an_mask & 0x3) << 1;
396 packed_record[16] |= (rec->tci_mask & 0x3F) << 3;
398 packed_record[16] |= (rec->sci_mask & 0x7F) << 9;
399 packed_record[17] = (rec->sci_mask >> 7) & 0x1;
401 packed_record[17] |= (rec->eth_type_mask & 0x3) << 1;
403 packed_record[17] |= (rec->snap_mask & 0x1F) << 3;
405 packed_record[17] |= (rec->llc_mask & 0x7) << 8;
407 packed_record[17] |= (rec->_802_2_encapsulate & 0x1) << 11;
409 packed_record[17] |= (rec->sa_mask & 0xF) << 12;
410 packed_record[18] = (rec->sa_mask >> 4) & 0x3;
412 packed_record[18] |= (rec->da_mask & 0x3F) << 2;
414 packed_record[18] |= (rec->lpbk_mask & 0x1) << 8;
416 packed_record[18] |= (rec->sc_idx & 0x1F) << 9;
418 packed_record[18] |= (rec->proc_dest & 0x1) << 14;
420 packed_record[18] |= (rec->action & 0x1) << 15;
421 packed_record[19] = (rec->action >> 1) & 0x1;
423 packed_record[19] |= (rec->ctrl_unctrl & 0x1) << 1;
425 packed_record[19] |= (rec->sci_from_table & 0x1) << 2;
427 packed_record[19] |= (rec->reserved & 0xF) << 3;
429 packed_record[19] |= (rec->valid & 0x1) << 7;
431 return set_raw_ingress_record(hw, packed_record, 20, 1,
432 ROWOFFSET_INGRESSPRECLASSRECORD +
433 table_index);
436 int aq_mss_set_ingress_preclass_record(struct aq_hw_s *hw,
437 const struct aq_mss_ingress_preclass_record *rec,
438 u16 table_index)
440 int err = AQ_API_CALL_SAFE(set_ingress_preclass_record, hw, rec,
441 table_index);
443 WARN_ONCE(err, "%s failed with %d\n", __func__, err);
445 return err;
448 static int
449 get_ingress_preclass_record(struct aq_hw_s *hw,
450 struct aq_mss_ingress_preclass_record *rec,
451 u16 table_index)
453 u16 packed_record[20];
454 int ret;
456 if (table_index >= NUMROWS_INGRESSPRECLASSRECORD)
457 return -EINVAL;
459 /* If the row that we want to read is odd, first read the previous even
460 * row, throw that value away, and finally read the desired row.
462 if ((table_index % 2) > 0) {
463 ret = get_raw_ingress_record(hw, packed_record, 20, 1,
464 ROWOFFSET_INGRESSPRECLASSRECORD +
465 table_index - 1);
466 if (unlikely(ret))
467 return ret;
470 ret = get_raw_ingress_record(hw, packed_record, 20, 1,
471 ROWOFFSET_INGRESSPRECLASSRECORD +
472 table_index);
473 if (unlikely(ret))
474 return ret;
476 rec->sci[0] = packed_record[0];
477 rec->sci[0] |= packed_record[1] << 16;
479 rec->sci[1] = packed_record[2];
480 rec->sci[1] |= packed_record[3] << 16;
482 rec->tci = packed_record[4] & 0xFF;
484 rec->encr_offset = (packed_record[4] >> 8) & 0xFF;
486 rec->eth_type = packed_record[5];
488 rec->snap[0] = packed_record[6];
489 rec->snap[0] |= packed_record[7] << 16;
491 rec->snap[1] = packed_record[8] & 0xFF;
493 rec->llc = (packed_record[8] >> 8) & 0xFF;
494 rec->llc |= packed_record[9] << 8;
496 rec->mac_sa[0] = packed_record[10];
497 rec->mac_sa[0] |= packed_record[11] << 16;
499 rec->mac_sa[1] = packed_record[12];
501 rec->mac_da[0] = packed_record[13];
502 rec->mac_da[0] |= packed_record[14] << 16;
504 rec->mac_da[1] = packed_record[15];
506 rec->lpbk_packet = packed_record[16] & 0x1;
508 rec->an_mask = (packed_record[16] >> 1) & 0x3;
510 rec->tci_mask = (packed_record[16] >> 3) & 0x3F;
512 rec->sci_mask = (packed_record[16] >> 9) & 0x7F;
513 rec->sci_mask |= (packed_record[17] & 0x1) << 7;
515 rec->eth_type_mask = (packed_record[17] >> 1) & 0x3;
517 rec->snap_mask = (packed_record[17] >> 3) & 0x1F;
519 rec->llc_mask = (packed_record[17] >> 8) & 0x7;
521 rec->_802_2_encapsulate = (packed_record[17] >> 11) & 0x1;
523 rec->sa_mask = (packed_record[17] >> 12) & 0xF;
524 rec->sa_mask |= (packed_record[18] & 0x3) << 4;
526 rec->da_mask = (packed_record[18] >> 2) & 0x3F;
528 rec->lpbk_mask = (packed_record[18] >> 8) & 0x1;
530 rec->sc_idx = (packed_record[18] >> 9) & 0x1F;
532 rec->proc_dest = (packed_record[18] >> 14) & 0x1;
534 rec->action = (packed_record[18] >> 15) & 0x1;
535 rec->action |= (packed_record[19] & 0x1) << 1;
537 rec->ctrl_unctrl = (packed_record[19] >> 1) & 0x1;
539 rec->sci_from_table = (packed_record[19] >> 2) & 0x1;
541 rec->reserved = (packed_record[19] >> 3) & 0xF;
543 rec->valid = (packed_record[19] >> 7) & 0x1;
545 return 0;
548 int aq_mss_get_ingress_preclass_record(struct aq_hw_s *hw,
549 struct aq_mss_ingress_preclass_record *rec,
550 u16 table_index)
552 memset(rec, 0, sizeof(*rec));
554 return AQ_API_CALL_SAFE(get_ingress_preclass_record, hw, rec,
555 table_index);
558 static int set_ingress_sc_record(struct aq_hw_s *hw,
559 const struct aq_mss_ingress_sc_record *rec,
560 u16 table_index)
562 u16 packed_record[8];
564 if (table_index >= NUMROWS_INGRESSSCRECORD)
565 return -EINVAL;
567 memset(packed_record, 0, sizeof(u16) * 8);
569 packed_record[0] = rec->stop_time & 0xFFFF;
570 packed_record[1] = (rec->stop_time >> 16) & 0xFFFF;
572 packed_record[2] = rec->start_time & 0xFFFF;
573 packed_record[3] = (rec->start_time >> 16) & 0xFFFF;
575 packed_record[4] = rec->validate_frames & 0x3;
577 packed_record[4] |= (rec->replay_protect & 0x1) << 2;
579 packed_record[4] |= (rec->anti_replay_window & 0x1FFF) << 3;
580 packed_record[5] = (rec->anti_replay_window >> 13) & 0xFFFF;
581 packed_record[6] = (rec->anti_replay_window >> 29) & 0x7;
583 packed_record[6] |= (rec->receiving & 0x1) << 3;
585 packed_record[6] |= (rec->fresh & 0x1) << 4;
587 packed_record[6] |= (rec->an_rol & 0x1) << 5;
589 packed_record[6] |= (rec->reserved & 0x3FF) << 6;
590 packed_record[7] = (rec->reserved >> 10) & 0x7FFF;
592 packed_record[7] |= (rec->valid & 0x1) << 15;
594 return set_raw_ingress_record(hw, packed_record, 8, 3,
595 ROWOFFSET_INGRESSSCRECORD + table_index);
598 int aq_mss_set_ingress_sc_record(struct aq_hw_s *hw,
599 const struct aq_mss_ingress_sc_record *rec,
600 u16 table_index)
602 int err = AQ_API_CALL_SAFE(set_ingress_sc_record, hw, rec, table_index);
604 WARN_ONCE(err, "%s failed with %d\n", __func__, err);
606 return err;
609 static int get_ingress_sc_record(struct aq_hw_s *hw,
610 struct aq_mss_ingress_sc_record *rec,
611 u16 table_index)
613 u16 packed_record[8];
614 int ret;
616 if (table_index >= NUMROWS_INGRESSSCRECORD)
617 return -EINVAL;
619 ret = get_raw_ingress_record(hw, packed_record, 8, 3,
620 ROWOFFSET_INGRESSSCRECORD + table_index);
621 if (unlikely(ret))
622 return ret;
624 rec->stop_time = packed_record[0];
625 rec->stop_time |= packed_record[1] << 16;
627 rec->start_time = packed_record[2];
628 rec->start_time |= packed_record[3] << 16;
630 rec->validate_frames = packed_record[4] & 0x3;
632 rec->replay_protect = (packed_record[4] >> 2) & 0x1;
634 rec->anti_replay_window = (packed_record[4] >> 3) & 0x1FFF;
635 rec->anti_replay_window |= packed_record[5] << 13;
636 rec->anti_replay_window |= (packed_record[6] & 0x7) << 29;
638 rec->receiving = (packed_record[6] >> 3) & 0x1;
640 rec->fresh = (packed_record[6] >> 4) & 0x1;
642 rec->an_rol = (packed_record[6] >> 5) & 0x1;
644 rec->reserved = (packed_record[6] >> 6) & 0x3FF;
645 rec->reserved |= (packed_record[7] & 0x7FFF) << 10;
647 rec->valid = (packed_record[7] >> 15) & 0x1;
649 return 0;
652 int aq_mss_get_ingress_sc_record(struct aq_hw_s *hw,
653 struct aq_mss_ingress_sc_record *rec,
654 u16 table_index)
656 memset(rec, 0, sizeof(*rec));
658 return AQ_API_CALL_SAFE(get_ingress_sc_record, hw, rec, table_index);
661 static int set_ingress_sa_record(struct aq_hw_s *hw,
662 const struct aq_mss_ingress_sa_record *rec,
663 u16 table_index)
665 u16 packed_record[8];
667 if (table_index >= NUMROWS_INGRESSSARECORD)
668 return -EINVAL;
670 memset(packed_record, 0, sizeof(u16) * 8);
672 packed_record[0] = rec->stop_time & 0xFFFF;
673 packed_record[1] = (rec->stop_time >> 16) & 0xFFFF;
675 packed_record[2] = rec->start_time & 0xFFFF;
676 packed_record[3] = (rec->start_time >> 16) & 0xFFFF;
678 packed_record[4] = rec->next_pn & 0xFFFF;
679 packed_record[5] = (rec->next_pn >> 16) & 0xFFFF;
681 packed_record[6] = rec->sat_nextpn & 0x1;
683 packed_record[6] |= (rec->in_use & 0x1) << 1;
685 packed_record[6] |= (rec->fresh & 0x1) << 2;
687 packed_record[6] |= (rec->reserved & 0x1FFF) << 3;
688 packed_record[7] = (rec->reserved >> 13) & 0x7FFF;
690 packed_record[7] |= (rec->valid & 0x1) << 15;
692 return set_raw_ingress_record(hw, packed_record, 8, 3,
693 ROWOFFSET_INGRESSSARECORD + table_index);
696 int aq_mss_set_ingress_sa_record(struct aq_hw_s *hw,
697 const struct aq_mss_ingress_sa_record *rec,
698 u16 table_index)
700 int err = AQ_API_CALL_SAFE(set_ingress_sa_record, hw, rec, table_index);
702 WARN_ONCE(err, "%s failed with %d\n", __func__, err);
704 return err;
707 static int get_ingress_sa_record(struct aq_hw_s *hw,
708 struct aq_mss_ingress_sa_record *rec,
709 u16 table_index)
711 u16 packed_record[8];
712 int ret;
714 if (table_index >= NUMROWS_INGRESSSARECORD)
715 return -EINVAL;
717 ret = get_raw_ingress_record(hw, packed_record, 8, 3,
718 ROWOFFSET_INGRESSSARECORD + table_index);
719 if (unlikely(ret))
720 return ret;
722 rec->stop_time = packed_record[0];
723 rec->stop_time |= packed_record[1] << 16;
725 rec->start_time = packed_record[2];
726 rec->start_time |= packed_record[3] << 16;
728 rec->next_pn = packed_record[4];
729 rec->next_pn |= packed_record[5] << 16;
731 rec->sat_nextpn = packed_record[6] & 0x1;
733 rec->in_use = (packed_record[6] >> 1) & 0x1;
735 rec->fresh = (packed_record[6] >> 2) & 0x1;
737 rec->reserved = (packed_record[6] >> 3) & 0x1FFF;
738 rec->reserved |= (packed_record[7] & 0x7FFF) << 13;
740 rec->valid = (packed_record[7] >> 15) & 0x1;
742 return 0;
745 int aq_mss_get_ingress_sa_record(struct aq_hw_s *hw,
746 struct aq_mss_ingress_sa_record *rec,
747 u16 table_index)
749 memset(rec, 0, sizeof(*rec));
751 return AQ_API_CALL_SAFE(get_ingress_sa_record, hw, rec, table_index);
754 static int
755 set_ingress_sakey_record(struct aq_hw_s *hw,
756 const struct aq_mss_ingress_sakey_record *rec,
757 u16 table_index)
759 u16 packed_record[18];
761 if (table_index >= NUMROWS_INGRESSSAKEYRECORD)
762 return -EINVAL;
764 memset(packed_record, 0, sizeof(u16) * 18);
766 packed_record[0] = rec->key[0] & 0xFFFF;
767 packed_record[1] = (rec->key[0] >> 16) & 0xFFFF;
769 packed_record[2] = rec->key[1] & 0xFFFF;
770 packed_record[3] = (rec->key[1] >> 16) & 0xFFFF;
772 packed_record[4] = rec->key[2] & 0xFFFF;
773 packed_record[5] = (rec->key[2] >> 16) & 0xFFFF;
775 packed_record[6] = rec->key[3] & 0xFFFF;
776 packed_record[7] = (rec->key[3] >> 16) & 0xFFFF;
778 packed_record[8] = rec->key[4] & 0xFFFF;
779 packed_record[9] = (rec->key[4] >> 16) & 0xFFFF;
781 packed_record[10] = rec->key[5] & 0xFFFF;
782 packed_record[11] = (rec->key[5] >> 16) & 0xFFFF;
784 packed_record[12] = rec->key[6] & 0xFFFF;
785 packed_record[13] = (rec->key[6] >> 16) & 0xFFFF;
787 packed_record[14] = rec->key[7] & 0xFFFF;
788 packed_record[15] = (rec->key[7] >> 16) & 0xFFFF;
790 packed_record[16] = rec->key_len & 0x3;
792 return set_raw_ingress_record(hw, packed_record, 18, 2,
793 ROWOFFSET_INGRESSSAKEYRECORD +
794 table_index);
797 int aq_mss_set_ingress_sakey_record(struct aq_hw_s *hw,
798 const struct aq_mss_ingress_sakey_record *rec,
799 u16 table_index)
801 int err = AQ_API_CALL_SAFE(set_ingress_sakey_record, hw, rec,
802 table_index);
804 WARN_ONCE(err, "%s failed with %d\n", __func__, err);
806 return err;
809 static int get_ingress_sakey_record(struct aq_hw_s *hw,
810 struct aq_mss_ingress_sakey_record *rec,
811 u16 table_index)
813 u16 packed_record[18];
814 int ret;
816 if (table_index >= NUMROWS_INGRESSSAKEYRECORD)
817 return -EINVAL;
819 ret = get_raw_ingress_record(hw, packed_record, 18, 2,
820 ROWOFFSET_INGRESSSAKEYRECORD +
821 table_index);
822 if (unlikely(ret))
823 return ret;
825 rec->key[0] = packed_record[0];
826 rec->key[0] |= packed_record[1] << 16;
828 rec->key[1] = packed_record[2];
829 rec->key[1] |= packed_record[3] << 16;
831 rec->key[2] = packed_record[4];
832 rec->key[2] |= packed_record[5] << 16;
834 rec->key[3] = packed_record[6];
835 rec->key[3] |= packed_record[7] << 16;
837 rec->key[4] = packed_record[8];
838 rec->key[4] |= packed_record[9] << 16;
840 rec->key[5] = packed_record[10];
841 rec->key[5] |= packed_record[11] << 16;
843 rec->key[6] = packed_record[12];
844 rec->key[6] |= packed_record[13] << 16;
846 rec->key[7] = packed_record[14];
847 rec->key[7] |= packed_record[15] << 16;
849 rec->key_len = packed_record[16] & 0x3;
851 return 0;
854 int aq_mss_get_ingress_sakey_record(struct aq_hw_s *hw,
855 struct aq_mss_ingress_sakey_record *rec,
856 u16 table_index)
858 memset(rec, 0, sizeof(*rec));
860 return AQ_API_CALL_SAFE(get_ingress_sakey_record, hw, rec, table_index);
863 static int
864 set_ingress_postclass_record(struct aq_hw_s *hw,
865 const struct aq_mss_ingress_postclass_record *rec,
866 u16 table_index)
868 u16 packed_record[8];
870 if (table_index >= NUMROWS_INGRESSPOSTCLASSRECORD)
871 return -EINVAL;
873 memset(packed_record, 0, sizeof(u16) * 8);
875 packed_record[0] = rec->byte0 & 0xFF;
877 packed_record[0] |= (rec->byte1 & 0xFF) << 8;
879 packed_record[1] = rec->byte2 & 0xFF;
881 packed_record[1] |= (rec->byte3 & 0xFF) << 8;
883 packed_record[2] = rec->eth_type & 0xFFFF;
885 packed_record[3] = rec->eth_type_valid & 0x1;
887 packed_record[3] |= (rec->vlan_id & 0xFFF) << 1;
889 packed_record[3] |= (rec->vlan_up & 0x7) << 13;
891 packed_record[4] = rec->vlan_valid & 0x1;
893 packed_record[4] |= (rec->sai & 0x1F) << 1;
895 packed_record[4] |= (rec->sai_hit & 0x1) << 6;
897 packed_record[4] |= (rec->eth_type_mask & 0xF) << 7;
899 packed_record[4] |= (rec->byte3_location & 0x1F) << 11;
900 packed_record[5] = (rec->byte3_location >> 5) & 0x1;
902 packed_record[5] |= (rec->byte3_mask & 0x3) << 1;
904 packed_record[5] |= (rec->byte2_location & 0x3F) << 3;
906 packed_record[5] |= (rec->byte2_mask & 0x3) << 9;
908 packed_record[5] |= (rec->byte1_location & 0x1F) << 11;
909 packed_record[6] = (rec->byte1_location >> 5) & 0x1;
911 packed_record[6] |= (rec->byte1_mask & 0x3) << 1;
913 packed_record[6] |= (rec->byte0_location & 0x3F) << 3;
915 packed_record[6] |= (rec->byte0_mask & 0x3) << 9;
917 packed_record[6] |= (rec->eth_type_valid_mask & 0x3) << 11;
919 packed_record[6] |= (rec->vlan_id_mask & 0x7) << 13;
920 packed_record[7] = (rec->vlan_id_mask >> 3) & 0x1;
922 packed_record[7] |= (rec->vlan_up_mask & 0x3) << 1;
924 packed_record[7] |= (rec->vlan_valid_mask & 0x3) << 3;
926 packed_record[7] |= (rec->sai_mask & 0x3) << 5;
928 packed_record[7] |= (rec->sai_hit_mask & 0x3) << 7;
930 packed_record[7] |= (rec->firstlevel_actions & 0x1) << 9;
932 packed_record[7] |= (rec->secondlevel_actions & 0x1) << 10;
934 packed_record[7] |= (rec->reserved & 0xF) << 11;
936 packed_record[7] |= (rec->valid & 0x1) << 15;
938 return set_raw_ingress_record(hw, packed_record, 8, 4,
939 ROWOFFSET_INGRESSPOSTCLASSRECORD +
940 table_index);
943 int aq_mss_set_ingress_postclass_record(struct aq_hw_s *hw,
944 const struct aq_mss_ingress_postclass_record *rec,
945 u16 table_index)
947 return AQ_API_CALL_SAFE(set_ingress_postclass_record, hw, rec,
948 table_index);
951 static int
952 get_ingress_postclass_record(struct aq_hw_s *hw,
953 struct aq_mss_ingress_postclass_record *rec,
954 u16 table_index)
956 u16 packed_record[8];
957 int ret;
959 if (table_index >= NUMROWS_INGRESSPOSTCLASSRECORD)
960 return -EINVAL;
962 /* If the row that we want to read is odd, first read the previous even
963 * row, throw that value away, and finally read the desired row.
965 if ((table_index % 2) > 0) {
966 ret = get_raw_ingress_record(hw, packed_record, 8, 4,
967 ROWOFFSET_INGRESSPOSTCLASSRECORD +
968 table_index - 1);
969 if (unlikely(ret))
970 return ret;
973 ret = get_raw_ingress_record(hw, packed_record, 8, 4,
974 ROWOFFSET_INGRESSPOSTCLASSRECORD +
975 table_index);
976 if (unlikely(ret))
977 return ret;
979 rec->byte0 = packed_record[0] & 0xFF;
981 rec->byte1 = (packed_record[0] >> 8) & 0xFF;
983 rec->byte2 = packed_record[1] & 0xFF;
985 rec->byte3 = (packed_record[1] >> 8) & 0xFF;
987 rec->eth_type = packed_record[2];
989 rec->eth_type_valid = packed_record[3] & 0x1;
991 rec->vlan_id = (packed_record[3] >> 1) & 0xFFF;
993 rec->vlan_up = (packed_record[3] >> 13) & 0x7;
995 rec->vlan_valid = packed_record[4] & 0x1;
997 rec->sai = (packed_record[4] >> 1) & 0x1F;
999 rec->sai_hit = (packed_record[4] >> 6) & 0x1;
1001 rec->eth_type_mask = (packed_record[4] >> 7) & 0xF;
1003 rec->byte3_location = (packed_record[4] >> 11) & 0x1F;
1004 rec->byte3_location |= (packed_record[5] & 0x1) << 5;
1006 rec->byte3_mask = (packed_record[5] >> 1) & 0x3;
1008 rec->byte2_location = (packed_record[5] >> 3) & 0x3F;
1010 rec->byte2_mask = (packed_record[5] >> 9) & 0x3;
1012 rec->byte1_location = (packed_record[5] >> 11) & 0x1F;
1013 rec->byte1_location |= (packed_record[6] & 0x1) << 5;
1015 rec->byte1_mask = (packed_record[6] >> 1) & 0x3;
1017 rec->byte0_location = (packed_record[6] >> 3) & 0x3F;
1019 rec->byte0_mask = (packed_record[6] >> 9) & 0x3;
1021 rec->eth_type_valid_mask = (packed_record[6] >> 11) & 0x3;
1023 rec->vlan_id_mask = (packed_record[6] >> 13) & 0x7;
1024 rec->vlan_id_mask |= (packed_record[7] & 0x1) << 3;
1026 rec->vlan_up_mask = (packed_record[7] >> 1) & 0x3;
1028 rec->vlan_valid_mask = (packed_record[7] >> 3) & 0x3;
1030 rec->sai_mask = (packed_record[7] >> 5) & 0x3;
1032 rec->sai_hit_mask = (packed_record[7] >> 7) & 0x3;
1034 rec->firstlevel_actions = (packed_record[7] >> 9) & 0x1;
1036 rec->secondlevel_actions = (packed_record[7] >> 10) & 0x1;
1038 rec->reserved = (packed_record[7] >> 11) & 0xF;
1040 rec->valid = (packed_record[7] >> 15) & 0x1;
1042 return 0;
1045 int aq_mss_get_ingress_postclass_record(struct aq_hw_s *hw,
1046 struct aq_mss_ingress_postclass_record *rec,
1047 u16 table_index)
1049 memset(rec, 0, sizeof(*rec));
1051 return AQ_API_CALL_SAFE(get_ingress_postclass_record, hw, rec,
1052 table_index);
1055 static int
1056 set_ingress_postctlf_record(struct aq_hw_s *hw,
1057 const struct aq_mss_ingress_postctlf_record *rec,
1058 u16 table_index)
1060 u16 packed_record[6];
1062 if (table_index >= NUMROWS_INGRESSPOSTCTLFRECORD)
1063 return -EINVAL;
1065 memset(packed_record, 0, sizeof(u16) * 6);
1067 packed_record[0] = rec->sa_da[0] & 0xFFFF;
1068 packed_record[1] = (rec->sa_da[0] >> 16) & 0xFFFF;
1070 packed_record[2] = rec->sa_da[1] & 0xFFFF;
1072 packed_record[3] = rec->eth_type & 0xFFFF;
1074 packed_record[4] = rec->match_mask & 0xFFFF;
1076 packed_record[5] = rec->match_type & 0xF;
1078 packed_record[5] |= (rec->action & 0x1) << 4;
1080 return set_raw_ingress_record(hw, packed_record, 6, 5,
1081 ROWOFFSET_INGRESSPOSTCTLFRECORD +
1082 table_index);
1085 int aq_mss_set_ingress_postctlf_record(struct aq_hw_s *hw,
1086 const struct aq_mss_ingress_postctlf_record *rec,
1087 u16 table_index)
1089 return AQ_API_CALL_SAFE(set_ingress_postctlf_record, hw, rec,
1090 table_index);
1093 static int
1094 get_ingress_postctlf_record(struct aq_hw_s *hw,
1095 struct aq_mss_ingress_postctlf_record *rec,
1096 u16 table_index)
1098 u16 packed_record[6];
1099 int ret;
1101 if (table_index >= NUMROWS_INGRESSPOSTCTLFRECORD)
1102 return -EINVAL;
1104 /* If the row that we want to read is odd, first read the previous even
1105 * row, throw that value away, and finally read the desired row.
1107 if ((table_index % 2) > 0) {
1108 ret = get_raw_ingress_record(hw, packed_record, 6, 5,
1109 ROWOFFSET_INGRESSPOSTCTLFRECORD +
1110 table_index - 1);
1111 if (unlikely(ret))
1112 return ret;
1115 ret = get_raw_ingress_record(hw, packed_record, 6, 5,
1116 ROWOFFSET_INGRESSPOSTCTLFRECORD +
1117 table_index);
1118 if (unlikely(ret))
1119 return ret;
1121 rec->sa_da[0] = packed_record[0];
1122 rec->sa_da[0] |= packed_record[1] << 16;
1124 rec->sa_da[1] = packed_record[2];
1126 rec->eth_type = packed_record[3];
1128 rec->match_mask = packed_record[4];
1130 rec->match_type = packed_record[5] & 0xF;
1132 rec->action = (packed_record[5] >> 4) & 0x1;
1134 return 0;
1137 int aq_mss_get_ingress_postctlf_record(struct aq_hw_s *hw,
1138 struct aq_mss_ingress_postctlf_record *rec,
1139 u16 table_index)
1141 memset(rec, 0, sizeof(*rec));
1143 return AQ_API_CALL_SAFE(get_ingress_postctlf_record, hw, rec,
1144 table_index);
1147 static int set_egress_ctlf_record(struct aq_hw_s *hw,
1148 const struct aq_mss_egress_ctlf_record *rec,
1149 u16 table_index)
1151 u16 packed_record[6];
1153 if (table_index >= NUMROWS_EGRESSCTLFRECORD)
1154 return -EINVAL;
1156 memset(packed_record, 0, sizeof(u16) * 6);
1158 packed_record[0] = rec->sa_da[0] & 0xFFFF;
1159 packed_record[1] = (rec->sa_da[0] >> 16) & 0xFFFF;
1161 packed_record[2] = rec->sa_da[1] & 0xFFFF;
1163 packed_record[3] = rec->eth_type & 0xFFFF;
1165 packed_record[4] = rec->match_mask & 0xFFFF;
1167 packed_record[5] = rec->match_type & 0xF;
1169 packed_record[5] |= (rec->action & 0x1) << 4;
1171 return set_raw_egress_record(hw, packed_record, 6, 0,
1172 ROWOFFSET_EGRESSCTLFRECORD + table_index);
1175 int aq_mss_set_egress_ctlf_record(struct aq_hw_s *hw,
1176 const struct aq_mss_egress_ctlf_record *rec,
1177 u16 table_index)
1179 return AQ_API_CALL_SAFE(set_egress_ctlf_record, hw, rec, table_index);
1182 static int get_egress_ctlf_record(struct aq_hw_s *hw,
1183 struct aq_mss_egress_ctlf_record *rec,
1184 u16 table_index)
1186 u16 packed_record[6];
1187 int ret;
1189 if (table_index >= NUMROWS_EGRESSCTLFRECORD)
1190 return -EINVAL;
1192 /* If the row that we want to read is odd, first read the previous even
1193 * row, throw that value away, and finally read the desired row.
1195 if ((table_index % 2) > 0) {
1196 ret = get_raw_egress_record(hw, packed_record, 6, 0,
1197 ROWOFFSET_EGRESSCTLFRECORD +
1198 table_index - 1);
1199 if (unlikely(ret))
1200 return ret;
1203 ret = get_raw_egress_record(hw, packed_record, 6, 0,
1204 ROWOFFSET_EGRESSCTLFRECORD + table_index);
1205 if (unlikely(ret))
1206 return ret;
1208 rec->sa_da[0] = packed_record[0];
1209 rec->sa_da[0] |= packed_record[1] << 16;
1211 rec->sa_da[1] = packed_record[2];
1213 rec->eth_type = packed_record[3];
1215 rec->match_mask = packed_record[4];
1217 rec->match_type = packed_record[5] & 0xF;
1219 rec->action = (packed_record[5] >> 4) & 0x1;
1221 return 0;
1224 int aq_mss_get_egress_ctlf_record(struct aq_hw_s *hw,
1225 struct aq_mss_egress_ctlf_record *rec,
1226 u16 table_index)
1228 memset(rec, 0, sizeof(*rec));
1230 return AQ_API_CALL_SAFE(get_egress_ctlf_record, hw, rec, table_index);
1233 static int set_egress_class_record(struct aq_hw_s *hw,
1234 const struct aq_mss_egress_class_record *rec,
1235 u16 table_index)
1237 u16 packed_record[28];
1239 if (table_index >= NUMROWS_EGRESSCLASSRECORD)
1240 return -EINVAL;
1242 memset(packed_record, 0, sizeof(u16) * 28);
1244 packed_record[0] = rec->vlan_id & 0xFFF;
1246 packed_record[0] |= (rec->vlan_up & 0x7) << 12;
1248 packed_record[0] |= (rec->vlan_valid & 0x1) << 15;
1250 packed_record[1] = rec->byte3 & 0xFF;
1252 packed_record[1] |= (rec->byte2 & 0xFF) << 8;
1254 packed_record[2] = rec->byte1 & 0xFF;
1256 packed_record[2] |= (rec->byte0 & 0xFF) << 8;
1258 packed_record[3] = rec->tci & 0xFF;
1260 packed_record[3] |= (rec->sci[0] & 0xFF) << 8;
1261 packed_record[4] = (rec->sci[0] >> 8) & 0xFFFF;
1262 packed_record[5] = (rec->sci[0] >> 24) & 0xFF;
1264 packed_record[5] |= (rec->sci[1] & 0xFF) << 8;
1265 packed_record[6] = (rec->sci[1] >> 8) & 0xFFFF;
1266 packed_record[7] = (rec->sci[1] >> 24) & 0xFF;
1268 packed_record[7] |= (rec->eth_type & 0xFF) << 8;
1269 packed_record[8] = (rec->eth_type >> 8) & 0xFF;
1271 packed_record[8] |= (rec->snap[0] & 0xFF) << 8;
1272 packed_record[9] = (rec->snap[0] >> 8) & 0xFFFF;
1273 packed_record[10] = (rec->snap[0] >> 24) & 0xFF;
1275 packed_record[10] |= (rec->snap[1] & 0xFF) << 8;
1277 packed_record[11] = rec->llc & 0xFFFF;
1278 packed_record[12] = (rec->llc >> 16) & 0xFF;
1280 packed_record[12] |= (rec->mac_sa[0] & 0xFF) << 8;
1281 packed_record[13] = (rec->mac_sa[0] >> 8) & 0xFFFF;
1282 packed_record[14] = (rec->mac_sa[0] >> 24) & 0xFF;
1284 packed_record[14] |= (rec->mac_sa[1] & 0xFF) << 8;
1285 packed_record[15] = (rec->mac_sa[1] >> 8) & 0xFF;
1287 packed_record[15] |= (rec->mac_da[0] & 0xFF) << 8;
1288 packed_record[16] = (rec->mac_da[0] >> 8) & 0xFFFF;
1289 packed_record[17] = (rec->mac_da[0] >> 24) & 0xFF;
1291 packed_record[17] |= (rec->mac_da[1] & 0xFF) << 8;
1292 packed_record[18] = (rec->mac_da[1] >> 8) & 0xFF;
1294 packed_record[18] |= (rec->pn & 0xFF) << 8;
1295 packed_record[19] = (rec->pn >> 8) & 0xFFFF;
1296 packed_record[20] = (rec->pn >> 24) & 0xFF;
1298 packed_record[20] |= (rec->byte3_location & 0x3F) << 8;
1300 packed_record[20] |= (rec->byte3_mask & 0x1) << 14;
1302 packed_record[20] |= (rec->byte2_location & 0x1) << 15;
1303 packed_record[21] = (rec->byte2_location >> 1) & 0x1F;
1305 packed_record[21] |= (rec->byte2_mask & 0x1) << 5;
1307 packed_record[21] |= (rec->byte1_location & 0x3F) << 6;
1309 packed_record[21] |= (rec->byte1_mask & 0x1) << 12;
1311 packed_record[21] |= (rec->byte0_location & 0x7) << 13;
1312 packed_record[22] = (rec->byte0_location >> 3) & 0x7;
1314 packed_record[22] |= (rec->byte0_mask & 0x1) << 3;
1316 packed_record[22] |= (rec->vlan_id_mask & 0x3) << 4;
1318 packed_record[22] |= (rec->vlan_up_mask & 0x1) << 6;
1320 packed_record[22] |= (rec->vlan_valid_mask & 0x1) << 7;
1322 packed_record[22] |= (rec->tci_mask & 0xFF) << 8;
1324 packed_record[23] = rec->sci_mask & 0xFF;
1326 packed_record[23] |= (rec->eth_type_mask & 0x3) << 8;
1328 packed_record[23] |= (rec->snap_mask & 0x1F) << 10;
1330 packed_record[23] |= (rec->llc_mask & 0x1) << 15;
1331 packed_record[24] = (rec->llc_mask >> 1) & 0x3;
1333 packed_record[24] |= (rec->sa_mask & 0x3F) << 2;
1335 packed_record[24] |= (rec->da_mask & 0x3F) << 8;
1337 packed_record[24] |= (rec->pn_mask & 0x3) << 14;
1338 packed_record[25] = (rec->pn_mask >> 2) & 0x3;
1340 packed_record[25] |= (rec->eight02dot2 & 0x1) << 2;
1342 packed_record[25] |= (rec->tci_sc & 0x1) << 3;
1344 packed_record[25] |= (rec->tci_87543 & 0x1) << 4;
1346 packed_record[25] |= (rec->exp_sectag_en & 0x1) << 5;
1348 packed_record[25] |= (rec->sc_idx & 0x1F) << 6;
1350 packed_record[25] |= (rec->sc_sa & 0x3) << 11;
1352 packed_record[25] |= (rec->debug & 0x1) << 13;
1354 packed_record[25] |= (rec->action & 0x3) << 14;
1356 packed_record[26] = (rec->valid & 0x1) << 3;
1358 return set_raw_egress_record(hw, packed_record, 28, 1,
1359 ROWOFFSET_EGRESSCLASSRECORD + table_index);
1362 int aq_mss_set_egress_class_record(struct aq_hw_s *hw,
1363 const struct aq_mss_egress_class_record *rec,
1364 u16 table_index)
1366 return AQ_API_CALL_SAFE(set_egress_class_record, hw, rec, table_index);
1369 static int get_egress_class_record(struct aq_hw_s *hw,
1370 struct aq_mss_egress_class_record *rec,
1371 u16 table_index)
1373 u16 packed_record[28];
1374 int ret;
1376 if (table_index >= NUMROWS_EGRESSCLASSRECORD)
1377 return -EINVAL;
1379 /* If the row that we want to read is odd, first read the previous even
1380 * row, throw that value away, and finally read the desired row.
1382 if ((table_index % 2) > 0) {
1383 ret = get_raw_egress_record(hw, packed_record, 28, 1,
1384 ROWOFFSET_EGRESSCLASSRECORD +
1385 table_index - 1);
1386 if (unlikely(ret))
1387 return ret;
1390 ret = get_raw_egress_record(hw, packed_record, 28, 1,
1391 ROWOFFSET_EGRESSCLASSRECORD + table_index);
1392 if (unlikely(ret))
1393 return ret;
1395 rec->vlan_id = packed_record[0] & 0xFFF;
1397 rec->vlan_up = (packed_record[0] >> 12) & 0x7;
1399 rec->vlan_valid = (packed_record[0] >> 15) & 0x1;
1401 rec->byte3 = packed_record[1] & 0xFF;
1403 rec->byte2 = (packed_record[1] >> 8) & 0xFF;
1405 rec->byte1 = packed_record[2] & 0xFF;
1407 rec->byte0 = (packed_record[2] >> 8) & 0xFF;
1409 rec->tci = packed_record[3] & 0xFF;
1411 rec->sci[0] = (packed_record[3] >> 8) & 0xFF;
1412 rec->sci[0] |= packed_record[4] << 8;
1413 rec->sci[0] |= (packed_record[5] & 0xFF) << 24;
1415 rec->sci[1] = (packed_record[5] >> 8) & 0xFF;
1416 rec->sci[1] |= packed_record[6] << 8;
1417 rec->sci[1] |= (packed_record[7] & 0xFF) << 24;
1419 rec->eth_type = (packed_record[7] >> 8) & 0xFF;
1420 rec->eth_type |= (packed_record[8] & 0xFF) << 8;
1422 rec->snap[0] = (packed_record[8] >> 8) & 0xFF;
1423 rec->snap[0] |= packed_record[9] << 8;
1424 rec->snap[0] |= (packed_record[10] & 0xFF) << 24;
1426 rec->snap[1] = (packed_record[10] >> 8) & 0xFF;
1428 rec->llc = packed_record[11];
1429 rec->llc |= (packed_record[12] & 0xFF) << 16;
1431 rec->mac_sa[0] = (packed_record[12] >> 8) & 0xFF;
1432 rec->mac_sa[0] |= packed_record[13] << 8;
1433 rec->mac_sa[0] |= (packed_record[14] & 0xFF) << 24;
1435 rec->mac_sa[1] = (packed_record[14] >> 8) & 0xFF;
1436 rec->mac_sa[1] |= (packed_record[15] & 0xFF) << 8;
1438 rec->mac_da[0] = (packed_record[15] >> 8) & 0xFF;
1439 rec->mac_da[0] |= packed_record[16] << 8;
1440 rec->mac_da[0] |= (packed_record[17] & 0xFF) << 24;
1442 rec->mac_da[1] = (packed_record[17] >> 8) & 0xFF;
1443 rec->mac_da[1] |= (packed_record[18] & 0xFF) << 8;
1445 rec->pn = (packed_record[18] >> 8) & 0xFF;
1446 rec->pn |= packed_record[19] << 8;
1447 rec->pn |= (packed_record[20] & 0xFF) << 24;
1449 rec->byte3_location = (packed_record[20] >> 8) & 0x3F;
1451 rec->byte3_mask = (packed_record[20] >> 14) & 0x1;
1453 rec->byte2_location = (packed_record[20] >> 15) & 0x1;
1454 rec->byte2_location |= (packed_record[21] & 0x1F) << 1;
1456 rec->byte2_mask = (packed_record[21] >> 5) & 0x1;
1458 rec->byte1_location = (packed_record[21] >> 6) & 0x3F;
1460 rec->byte1_mask = (packed_record[21] >> 12) & 0x1;
1462 rec->byte0_location = (packed_record[21] >> 13) & 0x7;
1463 rec->byte0_location |= (packed_record[22] & 0x7) << 3;
1465 rec->byte0_mask = (packed_record[22] >> 3) & 0x1;
1467 rec->vlan_id_mask = (packed_record[22] >> 4) & 0x3;
1469 rec->vlan_up_mask = (packed_record[22] >> 6) & 0x1;
1471 rec->vlan_valid_mask = (packed_record[22] >> 7) & 0x1;
1473 rec->tci_mask = (packed_record[22] >> 8) & 0xFF;
1475 rec->sci_mask = packed_record[23] & 0xFF;
1477 rec->eth_type_mask = (packed_record[23] >> 8) & 0x3;
1479 rec->snap_mask = (packed_record[23] >> 10) & 0x1F;
1481 rec->llc_mask = (packed_record[23] >> 15) & 0x1;
1482 rec->llc_mask |= (packed_record[24] & 0x3) << 1;
1484 rec->sa_mask = (packed_record[24] >> 2) & 0x3F;
1486 rec->da_mask = (packed_record[24] >> 8) & 0x3F;
1488 rec->pn_mask = (packed_record[24] >> 14) & 0x3;
1489 rec->pn_mask |= (packed_record[25] & 0x3) << 2;
1491 rec->eight02dot2 = (packed_record[25] >> 2) & 0x1;
1493 rec->tci_sc = (packed_record[25] >> 3) & 0x1;
1495 rec->tci_87543 = (packed_record[25] >> 4) & 0x1;
1497 rec->exp_sectag_en = (packed_record[25] >> 5) & 0x1;
1499 rec->sc_idx = (packed_record[25] >> 6) & 0x1F;
1501 rec->sc_sa = (packed_record[25] >> 11) & 0x3;
1503 rec->debug = (packed_record[25] >> 13) & 0x1;
1505 rec->action = (packed_record[25] >> 14) & 0x3;
1507 rec->valid = (packed_record[26] >> 3) & 0x1;
1509 return 0;
1512 int aq_mss_get_egress_class_record(struct aq_hw_s *hw,
1513 struct aq_mss_egress_class_record *rec,
1514 u16 table_index)
1516 memset(rec, 0, sizeof(*rec));
1518 return AQ_API_CALL_SAFE(get_egress_class_record, hw, rec, table_index);
1521 static int set_egress_sc_record(struct aq_hw_s *hw,
1522 const struct aq_mss_egress_sc_record *rec,
1523 u16 table_index)
1525 u16 packed_record[8];
1527 if (table_index >= NUMROWS_EGRESSSCRECORD)
1528 return -EINVAL;
1530 memset(packed_record, 0, sizeof(u16) * 8);
1532 packed_record[0] = rec->start_time & 0xFFFF;
1533 packed_record[1] = (rec->start_time >> 16) & 0xFFFF;
1535 packed_record[2] = rec->stop_time & 0xFFFF;
1536 packed_record[3] = (rec->stop_time >> 16) & 0xFFFF;
1538 packed_record[4] = rec->curr_an & 0x3;
1540 packed_record[4] |= (rec->an_roll & 0x1) << 2;
1542 packed_record[4] |= (rec->tci & 0x3F) << 3;
1544 packed_record[4] |= (rec->enc_off & 0x7F) << 9;
1545 packed_record[5] = (rec->enc_off >> 7) & 0x1;
1547 packed_record[5] |= (rec->protect & 0x1) << 1;
1549 packed_record[5] |= (rec->recv & 0x1) << 2;
1551 packed_record[5] |= (rec->fresh & 0x1) << 3;
1553 packed_record[5] |= (rec->sak_len & 0x3) << 4;
1555 packed_record[7] = (rec->valid & 0x1) << 15;
1557 return set_raw_egress_record(hw, packed_record, 8, 2,
1558 ROWOFFSET_EGRESSSCRECORD + table_index);
1561 int aq_mss_set_egress_sc_record(struct aq_hw_s *hw,
1562 const struct aq_mss_egress_sc_record *rec,
1563 u16 table_index)
1565 return AQ_API_CALL_SAFE(set_egress_sc_record, hw, rec, table_index);
1568 static int get_egress_sc_record(struct aq_hw_s *hw,
1569 struct aq_mss_egress_sc_record *rec,
1570 u16 table_index)
1572 u16 packed_record[8];
1573 int ret;
1575 if (table_index >= NUMROWS_EGRESSSCRECORD)
1576 return -EINVAL;
1578 ret = get_raw_egress_record(hw, packed_record, 8, 2,
1579 ROWOFFSET_EGRESSSCRECORD + table_index);
1580 if (unlikely(ret))
1581 return ret;
1583 rec->start_time = packed_record[0];
1584 rec->start_time |= packed_record[1] << 16;
1586 rec->stop_time = packed_record[2];
1587 rec->stop_time |= packed_record[3] << 16;
1589 rec->curr_an = packed_record[4] & 0x3;
1591 rec->an_roll = (packed_record[4] >> 2) & 0x1;
1593 rec->tci = (packed_record[4] >> 3) & 0x3F;
1595 rec->enc_off = (packed_record[4] >> 9) & 0x7F;
1596 rec->enc_off |= (packed_record[5] & 0x1) << 7;
1598 rec->protect = (packed_record[5] >> 1) & 0x1;
1600 rec->recv = (packed_record[5] >> 2) & 0x1;
1602 rec->fresh = (packed_record[5] >> 3) & 0x1;
1604 rec->sak_len = (packed_record[5] >> 4) & 0x3;
1606 rec->valid = (packed_record[7] >> 15) & 0x1;
1608 return 0;
1611 int aq_mss_get_egress_sc_record(struct aq_hw_s *hw,
1612 struct aq_mss_egress_sc_record *rec,
1613 u16 table_index)
1615 memset(rec, 0, sizeof(*rec));
1617 return AQ_API_CALL_SAFE(get_egress_sc_record, hw, rec, table_index);
1620 static int set_egress_sa_record(struct aq_hw_s *hw,
1621 const struct aq_mss_egress_sa_record *rec,
1622 u16 table_index)
1624 u16 packed_record[8];
1626 if (table_index >= NUMROWS_EGRESSSARECORD)
1627 return -EINVAL;
1629 memset(packed_record, 0, sizeof(u16) * 8);
1631 packed_record[0] = rec->start_time & 0xFFFF;
1632 packed_record[1] = (rec->start_time >> 16) & 0xFFFF;
1634 packed_record[2] = rec->stop_time & 0xFFFF;
1635 packed_record[3] = (rec->stop_time >> 16) & 0xFFFF;
1637 packed_record[4] = rec->next_pn & 0xFFFF;
1638 packed_record[5] = (rec->next_pn >> 16) & 0xFFFF;
1640 packed_record[6] = rec->sat_pn & 0x1;
1642 packed_record[6] |= (rec->fresh & 0x1) << 1;
1644 packed_record[7] = (rec->valid & 0x1) << 15;
1646 return set_raw_egress_record(hw, packed_record, 8, 2,
1647 ROWOFFSET_EGRESSSARECORD + table_index);
1650 int aq_mss_set_egress_sa_record(struct aq_hw_s *hw,
1651 const struct aq_mss_egress_sa_record *rec,
1652 u16 table_index)
1654 int err = AQ_API_CALL_SAFE(set_egress_sa_record, hw, rec, table_index);
1656 WARN_ONCE(err, "%s failed with %d\n", __func__, err);
1658 return err;
1661 static int get_egress_sa_record(struct aq_hw_s *hw,
1662 struct aq_mss_egress_sa_record *rec,
1663 u16 table_index)
1665 u16 packed_record[8];
1666 int ret;
1668 if (table_index >= NUMROWS_EGRESSSARECORD)
1669 return -EINVAL;
1671 ret = get_raw_egress_record(hw, packed_record, 8, 2,
1672 ROWOFFSET_EGRESSSARECORD + table_index);
1673 if (unlikely(ret))
1674 return ret;
1676 rec->start_time = packed_record[0];
1677 rec->start_time |= packed_record[1] << 16;
1679 rec->stop_time = packed_record[2];
1680 rec->stop_time |= packed_record[3] << 16;
1682 rec->next_pn = packed_record[4];
1683 rec->next_pn |= packed_record[5] << 16;
1685 rec->sat_pn = packed_record[6] & 0x1;
1687 rec->fresh = (packed_record[6] >> 1) & 0x1;
1689 rec->valid = (packed_record[7] >> 15) & 0x1;
1691 return 0;
1694 int aq_mss_get_egress_sa_record(struct aq_hw_s *hw,
1695 struct aq_mss_egress_sa_record *rec,
1696 u16 table_index)
1698 memset(rec, 0, sizeof(*rec));
1700 return AQ_API_CALL_SAFE(get_egress_sa_record, hw, rec, table_index);
1703 static int set_egress_sakey_record(struct aq_hw_s *hw,
1704 const struct aq_mss_egress_sakey_record *rec,
1705 u16 table_index)
1707 u16 packed_record[16];
1708 int ret;
1710 if (table_index >= NUMROWS_EGRESSSAKEYRECORD)
1711 return -EINVAL;
1713 memset(packed_record, 0, sizeof(u16) * 16);
1715 packed_record[0] = rec->key[0] & 0xFFFF;
1716 packed_record[1] = (rec->key[0] >> 16) & 0xFFFF;
1718 packed_record[2] = rec->key[1] & 0xFFFF;
1719 packed_record[3] = (rec->key[1] >> 16) & 0xFFFF;
1721 packed_record[4] = rec->key[2] & 0xFFFF;
1722 packed_record[5] = (rec->key[2] >> 16) & 0xFFFF;
1724 packed_record[6] = rec->key[3] & 0xFFFF;
1725 packed_record[7] = (rec->key[3] >> 16) & 0xFFFF;
1727 packed_record[8] = rec->key[4] & 0xFFFF;
1728 packed_record[9] = (rec->key[4] >> 16) & 0xFFFF;
1730 packed_record[10] = rec->key[5] & 0xFFFF;
1731 packed_record[11] = (rec->key[5] >> 16) & 0xFFFF;
1733 packed_record[12] = rec->key[6] & 0xFFFF;
1734 packed_record[13] = (rec->key[6] >> 16) & 0xFFFF;
1736 packed_record[14] = rec->key[7] & 0xFFFF;
1737 packed_record[15] = (rec->key[7] >> 16) & 0xFFFF;
1739 ret = set_raw_egress_record(hw, packed_record, 8, 2,
1740 ROWOFFSET_EGRESSSAKEYRECORD + table_index);
1741 if (unlikely(ret))
1742 return ret;
1743 ret = set_raw_egress_record(hw, packed_record + 8, 8, 2,
1744 ROWOFFSET_EGRESSSAKEYRECORD + table_index -
1745 32);
1746 if (unlikely(ret))
1747 return ret;
1749 return 0;
1752 int aq_mss_set_egress_sakey_record(struct aq_hw_s *hw,
1753 const struct aq_mss_egress_sakey_record *rec,
1754 u16 table_index)
1756 int err = AQ_API_CALL_SAFE(set_egress_sakey_record, hw, rec,
1757 table_index);
1759 WARN_ONCE(err, "%s failed with %d\n", __func__, err);
1761 return err;
1764 static int get_egress_sakey_record(struct aq_hw_s *hw,
1765 struct aq_mss_egress_sakey_record *rec,
1766 u16 table_index)
1768 u16 packed_record[16];
1769 int ret;
1771 if (table_index >= NUMROWS_EGRESSSAKEYRECORD)
1772 return -EINVAL;
1774 ret = get_raw_egress_record(hw, packed_record, 8, 2,
1775 ROWOFFSET_EGRESSSAKEYRECORD + table_index);
1776 if (unlikely(ret))
1777 return ret;
1778 ret = get_raw_egress_record(hw, packed_record + 8, 8, 2,
1779 ROWOFFSET_EGRESSSAKEYRECORD + table_index -
1780 32);
1781 if (unlikely(ret))
1782 return ret;
1784 rec->key[0] = packed_record[0];
1785 rec->key[0] |= packed_record[1] << 16;
1787 rec->key[1] = packed_record[2];
1788 rec->key[1] |= packed_record[3] << 16;
1790 rec->key[2] = packed_record[4];
1791 rec->key[2] |= packed_record[5] << 16;
1793 rec->key[3] = packed_record[6];
1794 rec->key[3] |= packed_record[7] << 16;
1796 rec->key[4] = packed_record[8];
1797 rec->key[4] |= packed_record[9] << 16;
1799 rec->key[5] = packed_record[10];
1800 rec->key[5] |= packed_record[11] << 16;
1802 rec->key[6] = packed_record[12];
1803 rec->key[6] |= packed_record[13] << 16;
1805 rec->key[7] = packed_record[14];
1806 rec->key[7] |= packed_record[15] << 16;
1808 return 0;
1811 int aq_mss_get_egress_sakey_record(struct aq_hw_s *hw,
1812 struct aq_mss_egress_sakey_record *rec,
1813 u16 table_index)
1815 memset(rec, 0, sizeof(*rec));
1817 return AQ_API_CALL_SAFE(get_egress_sakey_record, hw, rec, table_index);
1820 static int get_egress_sc_counters(struct aq_hw_s *hw,
1821 struct aq_mss_egress_sc_counters *counters,
1822 u16 sc_index)
1824 u16 packed_record[4];
1825 int ret;
1827 if (sc_index >= NUMROWS_EGRESSSCRECORD)
1828 return -EINVAL;
1830 ret = get_raw_egress_record(hw, packed_record, 4, 3, sc_index * 8 + 4);
1831 if (unlikely(ret))
1832 return ret;
1833 counters->sc_protected_pkts[0] =
1834 packed_record[0] | (packed_record[1] << 16);
1835 counters->sc_protected_pkts[1] =
1836 packed_record[2] | (packed_record[3] << 16);
1838 ret = get_raw_egress_record(hw, packed_record, 4, 3, sc_index * 8 + 5);
1839 if (unlikely(ret))
1840 return ret;
1841 counters->sc_encrypted_pkts[0] =
1842 packed_record[0] | (packed_record[1] << 16);
1843 counters->sc_encrypted_pkts[1] =
1844 packed_record[2] | (packed_record[3] << 16);
1846 ret = get_raw_egress_record(hw, packed_record, 4, 3, sc_index * 8 + 6);
1847 if (unlikely(ret))
1848 return ret;
1849 counters->sc_protected_octets[0] =
1850 packed_record[0] | (packed_record[1] << 16);
1851 counters->sc_protected_octets[1] =
1852 packed_record[2] | (packed_record[3] << 16);
1854 ret = get_raw_egress_record(hw, packed_record, 4, 3, sc_index * 8 + 7);
1855 if (unlikely(ret))
1856 return ret;
1857 counters->sc_encrypted_octets[0] =
1858 packed_record[0] | (packed_record[1] << 16);
1859 counters->sc_encrypted_octets[1] =
1860 packed_record[2] | (packed_record[3] << 16);
1862 return 0;
1865 int aq_mss_get_egress_sc_counters(struct aq_hw_s *hw,
1866 struct aq_mss_egress_sc_counters *counters,
1867 u16 sc_index)
1869 memset(counters, 0, sizeof(*counters));
1871 return AQ_API_CALL_SAFE(get_egress_sc_counters, hw, counters, sc_index);
1874 static int get_egress_sa_counters(struct aq_hw_s *hw,
1875 struct aq_mss_egress_sa_counters *counters,
1876 u16 sa_index)
1878 u16 packed_record[4];
1879 int ret;
1881 if (sa_index >= NUMROWS_EGRESSSARECORD)
1882 return -EINVAL;
1884 ret = get_raw_egress_record(hw, packed_record, 4, 3, sa_index * 8 + 0);
1885 if (unlikely(ret))
1886 return ret;
1887 counters->sa_hit_drop_redirect[0] =
1888 packed_record[0] | (packed_record[1] << 16);
1889 counters->sa_hit_drop_redirect[1] =
1890 packed_record[2] | (packed_record[3] << 16);
1892 ret = get_raw_egress_record(hw, packed_record, 4, 3, sa_index * 8 + 1);
1893 if (unlikely(ret))
1894 return ret;
1895 counters->sa_protected2_pkts[0] =
1896 packed_record[0] | (packed_record[1] << 16);
1897 counters->sa_protected2_pkts[1] =
1898 packed_record[2] | (packed_record[3] << 16);
1900 ret = get_raw_egress_record(hw, packed_record, 4, 3, sa_index * 8 + 2);
1901 if (unlikely(ret))
1902 return ret;
1903 counters->sa_protected_pkts[0] =
1904 packed_record[0] | (packed_record[1] << 16);
1905 counters->sa_protected_pkts[1] =
1906 packed_record[2] | (packed_record[3] << 16);
1908 ret = get_raw_egress_record(hw, packed_record, 4, 3, sa_index * 8 + 3);
1909 if (unlikely(ret))
1910 return ret;
1911 counters->sa_encrypted_pkts[0] =
1912 packed_record[0] | (packed_record[1] << 16);
1913 counters->sa_encrypted_pkts[1] =
1914 packed_record[2] | (packed_record[3] << 16);
1916 return 0;
1919 int aq_mss_get_egress_sa_counters(struct aq_hw_s *hw,
1920 struct aq_mss_egress_sa_counters *counters,
1921 u16 sa_index)
1923 memset(counters, 0, sizeof(*counters));
1925 return AQ_API_CALL_SAFE(get_egress_sa_counters, hw, counters, sa_index);
1928 static int
1929 get_egress_common_counters(struct aq_hw_s *hw,
1930 struct aq_mss_egress_common_counters *counters)
1932 u16 packed_record[4];
1933 int ret;
1935 ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 0);
1936 if (unlikely(ret))
1937 return ret;
1938 counters->ctl_pkt[0] = packed_record[0] | (packed_record[1] << 16);
1939 counters->ctl_pkt[1] = packed_record[2] | (packed_record[3] << 16);
1941 ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 1);
1942 if (unlikely(ret))
1943 return ret;
1944 counters->unknown_sa_pkts[0] =
1945 packed_record[0] | (packed_record[1] << 16);
1946 counters->unknown_sa_pkts[1] =
1947 packed_record[2] | (packed_record[3] << 16);
1949 ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 2);
1950 if (unlikely(ret))
1951 return ret;
1952 counters->untagged_pkts[0] =
1953 packed_record[0] | (packed_record[1] << 16);
1954 counters->untagged_pkts[1] =
1955 packed_record[2] | (packed_record[3] << 16);
1957 ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 3);
1958 if (unlikely(ret))
1959 return ret;
1960 counters->too_long[0] = packed_record[0] | (packed_record[1] << 16);
1961 counters->too_long[1] = packed_record[2] | (packed_record[3] << 16);
1963 ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 4);
1964 if (unlikely(ret))
1965 return ret;
1966 counters->ecc_error_pkts[0] =
1967 packed_record[0] | (packed_record[1] << 16);
1968 counters->ecc_error_pkts[1] =
1969 packed_record[2] | (packed_record[3] << 16);
1971 ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 5);
1972 if (unlikely(ret))
1973 return ret;
1974 counters->unctrl_hit_drop_redir[0] =
1975 packed_record[0] | (packed_record[1] << 16);
1976 counters->unctrl_hit_drop_redir[1] =
1977 packed_record[2] | (packed_record[3] << 16);
1979 return 0;
1982 int aq_mss_get_egress_common_counters(struct aq_hw_s *hw,
1983 struct aq_mss_egress_common_counters *counters)
1985 memset(counters, 0, sizeof(*counters));
1987 return AQ_API_CALL_SAFE(get_egress_common_counters, hw, counters);
1990 static int clear_egress_counters(struct aq_hw_s *hw)
1992 struct mss_egress_ctl_register ctl_reg;
1993 int ret;
1995 memset(&ctl_reg, 0, sizeof(ctl_reg));
1997 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1, MSS_EGRESS_CTL_REGISTER_ADDR,
1998 &ctl_reg.word_0);
1999 if (unlikely(ret))
2000 return ret;
2001 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2002 MSS_EGRESS_CTL_REGISTER_ADDR + 4,
2003 &ctl_reg.word_1);
2004 if (unlikely(ret))
2005 return ret;
2007 /* Toggle the Egress MIB clear bit 0->1->0 */
2008 ctl_reg.bits_0.clear_counter = 0;
2009 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2010 MSS_EGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2011 if (unlikely(ret))
2012 return ret;
2013 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2014 MSS_EGRESS_CTL_REGISTER_ADDR + 4,
2015 ctl_reg.word_1);
2016 if (unlikely(ret))
2017 return ret;
2019 ctl_reg.bits_0.clear_counter = 1;
2020 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2021 MSS_EGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2022 if (unlikely(ret))
2023 return ret;
2024 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2025 MSS_EGRESS_CTL_REGISTER_ADDR + 4,
2026 ctl_reg.word_1);
2027 if (unlikely(ret))
2028 return ret;
2030 ctl_reg.bits_0.clear_counter = 0;
2031 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2032 MSS_EGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2033 if (unlikely(ret))
2034 return ret;
2035 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2036 MSS_EGRESS_CTL_REGISTER_ADDR + 4,
2037 ctl_reg.word_1);
2038 if (unlikely(ret))
2039 return ret;
2041 return 0;
2044 int aq_mss_clear_egress_counters(struct aq_hw_s *hw)
2046 return AQ_API_CALL_SAFE(clear_egress_counters, hw);
2049 static int get_ingress_sa_counters(struct aq_hw_s *hw,
2050 struct aq_mss_ingress_sa_counters *counters,
2051 u16 sa_index)
2053 u16 packed_record[4];
2054 int ret;
2056 if (sa_index >= NUMROWS_INGRESSSARECORD)
2057 return -EINVAL;
2059 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2060 sa_index * 12 + 0);
2061 if (unlikely(ret))
2062 return ret;
2063 counters->untagged_hit_pkts[0] =
2064 packed_record[0] | (packed_record[1] << 16);
2065 counters->untagged_hit_pkts[1] =
2066 packed_record[2] | (packed_record[3] << 16);
2068 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2069 sa_index * 12 + 1);
2070 if (unlikely(ret))
2071 return ret;
2072 counters->ctrl_hit_drop_redir_pkts[0] =
2073 packed_record[0] | (packed_record[1] << 16);
2074 counters->ctrl_hit_drop_redir_pkts[1] =
2075 packed_record[2] | (packed_record[3] << 16);
2077 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2078 sa_index * 12 + 2);
2079 if (unlikely(ret))
2080 return ret;
2081 counters->not_using_sa[0] = packed_record[0] | (packed_record[1] << 16);
2082 counters->not_using_sa[1] = packed_record[2] | (packed_record[3] << 16);
2084 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2085 sa_index * 12 + 3);
2086 if (unlikely(ret))
2087 return ret;
2088 counters->unused_sa[0] = packed_record[0] | (packed_record[1] << 16);
2089 counters->unused_sa[1] = packed_record[2] | (packed_record[3] << 16);
2091 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2092 sa_index * 12 + 4);
2093 if (unlikely(ret))
2094 return ret;
2095 counters->not_valid_pkts[0] =
2096 packed_record[0] | (packed_record[1] << 16);
2097 counters->not_valid_pkts[1] =
2098 packed_record[2] | (packed_record[3] << 16);
2100 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2101 sa_index * 12 + 5);
2102 if (unlikely(ret))
2103 return ret;
2104 counters->invalid_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2105 counters->invalid_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2107 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2108 sa_index * 12 + 6);
2109 if (unlikely(ret))
2110 return ret;
2111 counters->ok_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2112 counters->ok_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2114 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2115 sa_index * 12 + 7);
2116 if (unlikely(ret))
2117 return ret;
2118 counters->late_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2119 counters->late_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2121 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2122 sa_index * 12 + 8);
2123 if (unlikely(ret))
2124 return ret;
2125 counters->delayed_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2126 counters->delayed_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2128 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2129 sa_index * 12 + 9);
2130 if (unlikely(ret))
2131 return ret;
2132 counters->unchecked_pkts[0] =
2133 packed_record[0] | (packed_record[1] << 16);
2134 counters->unchecked_pkts[1] =
2135 packed_record[2] | (packed_record[3] << 16);
2137 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2138 sa_index * 12 + 10);
2139 if (unlikely(ret))
2140 return ret;
2141 counters->validated_octets[0] =
2142 packed_record[0] | (packed_record[1] << 16);
2143 counters->validated_octets[1] =
2144 packed_record[2] | (packed_record[3] << 16);
2146 ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2147 sa_index * 12 + 11);
2148 if (unlikely(ret))
2149 return ret;
2150 counters->decrypted_octets[0] =
2151 packed_record[0] | (packed_record[1] << 16);
2152 counters->decrypted_octets[1] =
2153 packed_record[2] | (packed_record[3] << 16);
2155 return 0;
2158 int aq_mss_get_ingress_sa_counters(struct aq_hw_s *hw,
2159 struct aq_mss_ingress_sa_counters *counters,
2160 u16 sa_index)
2162 memset(counters, 0, sizeof(*counters));
2164 return AQ_API_CALL_SAFE(get_ingress_sa_counters, hw, counters,
2165 sa_index);
2168 static int
2169 get_ingress_common_counters(struct aq_hw_s *hw,
2170 struct aq_mss_ingress_common_counters *counters)
2172 u16 packed_record[4];
2173 int ret;
2175 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 0);
2176 if (unlikely(ret))
2177 return ret;
2178 counters->ctl_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2179 counters->ctl_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2181 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 1);
2182 if (unlikely(ret))
2183 return ret;
2184 counters->tagged_miss_pkts[0] =
2185 packed_record[0] | (packed_record[1] << 16);
2186 counters->tagged_miss_pkts[1] =
2187 packed_record[2] | (packed_record[3] << 16);
2189 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 2);
2190 if (unlikely(ret))
2191 return ret;
2192 counters->untagged_miss_pkts[0] =
2193 packed_record[0] | (packed_record[1] << 16);
2194 counters->untagged_miss_pkts[1] =
2195 packed_record[2] | (packed_record[3] << 16);
2197 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 3);
2198 if (unlikely(ret))
2199 return ret;
2200 counters->notag_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2201 counters->notag_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2203 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 4);
2204 if (unlikely(ret))
2205 return ret;
2206 counters->untagged_pkts[0] =
2207 packed_record[0] | (packed_record[1] << 16);
2208 counters->untagged_pkts[1] =
2209 packed_record[2] | (packed_record[3] << 16);
2211 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 5);
2212 if (unlikely(ret))
2213 return ret;
2214 counters->bad_tag_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2215 counters->bad_tag_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2217 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 6);
2218 if (unlikely(ret))
2219 return ret;
2220 counters->no_sci_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2221 counters->no_sci_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2223 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 7);
2224 if (unlikely(ret))
2225 return ret;
2226 counters->unknown_sci_pkts[0] =
2227 packed_record[0] | (packed_record[1] << 16);
2228 counters->unknown_sci_pkts[1] =
2229 packed_record[2] | (packed_record[3] << 16);
2231 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 8);
2232 if (unlikely(ret))
2233 return ret;
2234 counters->ctrl_prt_pass_pkts[0] =
2235 packed_record[0] | (packed_record[1] << 16);
2236 counters->ctrl_prt_pass_pkts[1] =
2237 packed_record[2] | (packed_record[3] << 16);
2239 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 9);
2240 if (unlikely(ret))
2241 return ret;
2242 counters->unctrl_prt_pass_pkts[0] =
2243 packed_record[0] | (packed_record[1] << 16);
2244 counters->unctrl_prt_pass_pkts[1] =
2245 packed_record[2] | (packed_record[3] << 16);
2247 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 10);
2248 if (unlikely(ret))
2249 return ret;
2250 counters->ctrl_prt_fail_pkts[0] =
2251 packed_record[0] | (packed_record[1] << 16);
2252 counters->ctrl_prt_fail_pkts[1] =
2253 packed_record[2] | (packed_record[3] << 16);
2255 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 11);
2256 if (unlikely(ret))
2257 return ret;
2258 counters->unctrl_prt_fail_pkts[0] =
2259 packed_record[0] | (packed_record[1] << 16);
2260 counters->unctrl_prt_fail_pkts[1] =
2261 packed_record[2] | (packed_record[3] << 16);
2263 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 12);
2264 if (unlikely(ret))
2265 return ret;
2266 counters->too_long_pkts[0] =
2267 packed_record[0] | (packed_record[1] << 16);
2268 counters->too_long_pkts[1] =
2269 packed_record[2] | (packed_record[3] << 16);
2271 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 13);
2272 if (unlikely(ret))
2273 return ret;
2274 counters->igpoc_ctl_pkts[0] =
2275 packed_record[0] | (packed_record[1] << 16);
2276 counters->igpoc_ctl_pkts[1] =
2277 packed_record[2] | (packed_record[3] << 16);
2279 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 14);
2280 if (unlikely(ret))
2281 return ret;
2282 counters->ecc_error_pkts[0] =
2283 packed_record[0] | (packed_record[1] << 16);
2284 counters->ecc_error_pkts[1] =
2285 packed_record[2] | (packed_record[3] << 16);
2287 ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 15);
2288 if (unlikely(ret))
2289 return ret;
2290 counters->unctrl_hit_drop_redir[0] =
2291 packed_record[0] | (packed_record[1] << 16);
2292 counters->unctrl_hit_drop_redir[1] =
2293 packed_record[2] | (packed_record[3] << 16);
2295 return 0;
2298 int aq_mss_get_ingress_common_counters(struct aq_hw_s *hw,
2299 struct aq_mss_ingress_common_counters *counters)
2301 memset(counters, 0, sizeof(*counters));
2303 return AQ_API_CALL_SAFE(get_ingress_common_counters, hw, counters);
2306 static int clear_ingress_counters(struct aq_hw_s *hw)
2308 struct mss_ingress_ctl_register ctl_reg;
2309 int ret;
2311 memset(&ctl_reg, 0, sizeof(ctl_reg));
2313 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2314 MSS_INGRESS_CTL_REGISTER_ADDR, &ctl_reg.word_0);
2315 if (unlikely(ret))
2316 return ret;
2317 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2318 MSS_INGRESS_CTL_REGISTER_ADDR + 4,
2319 &ctl_reg.word_1);
2320 if (unlikely(ret))
2321 return ret;
2323 /* Toggle the Ingress MIB clear bit 0->1->0 */
2324 ctl_reg.bits_0.clear_count = 0;
2325 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2326 MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2327 if (unlikely(ret))
2328 return ret;
2329 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2330 MSS_INGRESS_CTL_REGISTER_ADDR + 4,
2331 ctl_reg.word_1);
2332 if (unlikely(ret))
2333 return ret;
2335 ctl_reg.bits_0.clear_count = 1;
2336 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2337 MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2338 if (unlikely(ret))
2339 return ret;
2340 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2341 MSS_INGRESS_CTL_REGISTER_ADDR + 4,
2342 ctl_reg.word_1);
2343 if (unlikely(ret))
2344 return ret;
2346 ctl_reg.bits_0.clear_count = 0;
2347 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2348 MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2349 if (unlikely(ret))
2350 return ret;
2351 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2352 MSS_INGRESS_CTL_REGISTER_ADDR + 4,
2353 ctl_reg.word_1);
2354 if (unlikely(ret))
2355 return ret;
2357 return 0;
2360 int aq_mss_clear_ingress_counters(struct aq_hw_s *hw)
2362 return AQ_API_CALL_SAFE(clear_ingress_counters, hw);
2365 static int get_egress_sa_expired(struct aq_hw_s *hw, u32 *expired)
2367 u16 val;
2368 int ret;
2370 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2371 MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR,
2372 &val);
2373 if (unlikely(ret))
2374 return ret;
2376 *expired = val;
2378 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2379 MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR + 1,
2380 &val);
2381 if (unlikely(ret))
2382 return ret;
2384 *expired |= val << 16;
2386 return 0;
2389 int aq_mss_get_egress_sa_expired(struct aq_hw_s *hw, u32 *expired)
2391 *expired = 0;
2393 return AQ_API_CALL_SAFE(get_egress_sa_expired, hw, expired);
2396 static int get_egress_sa_threshold_expired(struct aq_hw_s *hw,
2397 u32 *expired)
2399 u16 val;
2400 int ret;
2402 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2403 MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR, &val);
2404 if (unlikely(ret))
2405 return ret;
2407 *expired = val;
2409 ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2410 MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR + 1, &val);
2411 if (unlikely(ret))
2412 return ret;
2414 *expired |= val << 16;
2416 return 0;
2419 int aq_mss_get_egress_sa_threshold_expired(struct aq_hw_s *hw,
2420 u32 *expired)
2422 *expired = 0;
2424 return AQ_API_CALL_SAFE(get_egress_sa_threshold_expired, hw, expired);
2427 static int set_egress_sa_expired(struct aq_hw_s *hw, u32 expired)
2429 int ret;
2431 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2432 MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR,
2433 expired & 0xFFFF);
2434 if (unlikely(ret))
2435 return ret;
2437 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2438 MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR + 1,
2439 expired >> 16);
2440 if (unlikely(ret))
2441 return ret;
2443 return 0;
2446 int aq_mss_set_egress_sa_expired(struct aq_hw_s *hw, u32 expired)
2448 return AQ_API_CALL_SAFE(set_egress_sa_expired, hw, expired);
2451 static int set_egress_sa_threshold_expired(struct aq_hw_s *hw, u32 expired)
2453 int ret;
2455 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2456 MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR,
2457 expired & 0xFFFF);
2458 if (unlikely(ret))
2459 return ret;
2461 ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2462 MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR + 1,
2463 expired >> 16);
2464 if (unlikely(ret))
2465 return ret;
2467 return 0;
2470 int aq_mss_set_egress_sa_threshold_expired(struct aq_hw_s *hw, u32 expired)
2472 return AQ_API_CALL_SAFE(set_egress_sa_threshold_expired, hw, expired);