1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Atlantic Network Driver
3  * Copyright (C) 2020 Marvell International Ltd.
4  */
5 
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"
11 
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;                                                 \
19 									       \
20 		ret = func(__VA_ARGS__);                                       \
21 									       \
22 		aq_mss_mdio_sem_put(hw);                                       \
23 	} while (0);                                                           \
24 	ret;                                                                   \
25 })
26 
27 /*******************************************************************************
28  *                               MDIO wrappers
29  ******************************************************************************/
30 static int aq_mss_mdio_sem_get(struct aq_hw_s *hw)
31 {
32 	u32 val;
33 
34 	return readx_poll_timeout_atomic(hw_atl_sem_mdio_get, hw, val,
35 					 val == 1U, 10U, 100000U);
36 }
37 
38 static void aq_mss_mdio_sem_put(struct aq_hw_s *hw)
39 {
40 	hw_atl_reg_glb_cpu_sem_set(hw, 1U, HW_ATL_FW_SM_MDIO);
41 }
42 
43 static int aq_mss_mdio_read(struct aq_hw_s *hw, u16 mmd, u16 addr, u16 *data)
44 {
45 	*data = aq_mdio_read_word(hw, mmd, addr);
46 	return (*data != 0xffff) ? 0 : -ETIME;
47 }
48 
49 static int aq_mss_mdio_write(struct aq_hw_s *hw, u16 mmd, u16 addr, u16 data)
50 {
51 	aq_mdio_write_word(hw, mmd, addr, data);
52 	return 0;
53 }
54 
55 /*******************************************************************************
56  *                          MACSEC config and status
57  ******************************************************************************/
58 
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)
62 {
63 	struct mss_ingress_lut_addr_ctl_register lut_sel_reg;
64 	struct mss_ingress_lut_ctl_register lut_op_reg;
65 
66 	unsigned int i;
67 
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
72 	 *
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.
76 	 *
77 	 * For EUR devices: Not need to use the PIF mailbox; it is safe to
78 	 * write to the registers directly.
79 	 */
80 
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 +
88 					  1,
89 				  packed_record[i + 1]);
90 	}
91 
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);
99 	}
100 
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;
104 
105 	lut_op_reg.bits_0.lut_read = 0;
106 	lut_op_reg.bits_0.lut_write = 1;
107 
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);
113 
114 	return 0;
115 }
116 
117 /*! Read the specified Ingress LUT table row.
118  *  packed_record - [OUT] The table row data (raw).
119  */
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)
123 {
124 	struct mss_ingress_lut_addr_ctl_register lut_sel_reg;
125 	struct mss_ingress_lut_ctl_register lut_op_reg;
126 	int ret;
127 
128 	unsigned int i;
129 
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;
133 
134 	lut_op_reg.bits_0.lut_read = 1;
135 	lut_op_reg.bits_0.lut_write = 0;
136 
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;
147 
148 	memset(packed_record, 0, sizeof(u16) * num_words);
149 
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 +
153 					       i,
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;
163 	}
164 
165 	return 0;
166 }
167 
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)
172 {
173 	struct mss_egress_lut_addr_ctl_register lut_sel_reg;
174 	struct mss_egress_lut_ctl_register lut_op_reg;
175 
176 	unsigned int i;
177 
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]);
186 	}
187 
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,
194 				  0);
195 	}
196 
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;
200 
201 	lut_op_reg.bits_0.lut_read = 0;
202 	lut_op_reg.bits_0.lut_write = 1;
203 
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);
209 
210 	return 0;
211 }
212 
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)
216 {
217 	struct mss_egress_lut_addr_ctl_register lut_sel_reg;
218 	struct mss_egress_lut_ctl_register lut_op_reg;
219 	int ret;
220 
221 	unsigned int i;
222 
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;
226 
227 	lut_op_reg.bits_0.lut_read = 1;
228 	lut_op_reg.bits_0.lut_write = 0;
229 
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;
240 
241 	memset(packed_record, 0, sizeof(u16) * num_words);
242 
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 +
246 					       i,
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;
256 	}
257 
258 	return 0;
259 }
260 
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)
265 {
266 	u16 packed_record[6];
267 
268 	if (table_index >= NUMROWS_INGRESSPRECTLFRECORD)
269 		return -EINVAL;
270 
271 	memset(packed_record, 0, sizeof(u16) * 6);
272 
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;
280 
281 	return set_raw_ingress_record(hw, packed_record, 6, 0,
282 				      ROWOFFSET_INGRESSPRECTLFRECORD +
283 					      table_index);
284 }
285 
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)
289 {
290 	return AQ_API_CALL_SAFE(set_ingress_prectlf_record, hw, rec,
291 				table_index);
292 }
293 
294 static int get_ingress_prectlf_record(struct aq_hw_s *hw,
295 				      struct aq_mss_ingress_prectlf_record *rec,
296 				      u16 table_index)
297 {
298 	u16 packed_record[6];
299 	int ret;
300 
301 	if (table_index >= NUMROWS_INGRESSPRECTLFRECORD)
302 		return -EINVAL;
303 
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.
309 	 */
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;
316 	}
317 
318 	ret = get_raw_ingress_record(hw, packed_record, 6, 0,
319 				     ROWOFFSET_INGRESSPRECTLFRECORD +
320 					     table_index);
321 	if (unlikely(ret))
322 		return ret;
323 
324 	rec->sa_da[0] = packed_record[0];
325 	rec->sa_da[0] |= packed_record[1] << 16;
326 
327 	rec->sa_da[1] = packed_record[2];
328 
329 	rec->eth_type = packed_record[3];
330 
331 	rec->match_mask = packed_record[4];
332 
333 	rec->match_type = packed_record[5] & 0xF;
334 
335 	rec->action = (packed_record[5] >> 4) & 0x1;
336 
337 	return 0;
338 }
339 
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)
343 {
344 	memset(rec, 0, sizeof(*rec));
345 
346 	return AQ_API_CALL_SAFE(get_ingress_prectlf_record, hw, rec,
347 				table_index);
348 }
349 
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)
354 {
355 	u16 packed_record[20];
356 
357 	if (table_index >= NUMROWS_INGRESSPRECLASSRECORD)
358 		return -EINVAL;
359 
360 	memset(packed_record, 0, sizeof(u16) * 20);
361 
362 	packed_record[0] = rec->sci[0] & 0xFFFF;
363 	packed_record[1] = (rec->sci[0] >> 16) & 0xFFFF;
364 
365 	packed_record[2] = rec->sci[1] & 0xFFFF;
366 	packed_record[3] = (rec->sci[1] >> 16) & 0xFFFF;
367 
368 	packed_record[4] = rec->tci & 0xFF;
369 
370 	packed_record[4] |= (rec->encr_offset & 0xFF) << 8;
371 
372 	packed_record[5] = rec->eth_type & 0xFFFF;
373 
374 	packed_record[6] = rec->snap[0] & 0xFFFF;
375 	packed_record[7] = (rec->snap[0] >> 16) & 0xFFFF;
376 
377 	packed_record[8] = rec->snap[1] & 0xFF;
378 
379 	packed_record[8] |= (rec->llc & 0xFF) << 8;
380 	packed_record[9] = (rec->llc >> 8) & 0xFFFF;
381 
382 	packed_record[10] = rec->mac_sa[0] & 0xFFFF;
383 	packed_record[11] = (rec->mac_sa[0] >> 16) & 0xFFFF;
384 
385 	packed_record[12] = rec->mac_sa[1] & 0xFFFF;
386 
387 	packed_record[13] = rec->mac_da[0] & 0xFFFF;
388 	packed_record[14] = (rec->mac_da[0] >> 16) & 0xFFFF;
389 
390 	packed_record[15] = rec->mac_da[1] & 0xFFFF;
391 
392 	packed_record[16] = rec->lpbk_packet & 0x1;
393 
394 	packed_record[16] |= (rec->an_mask & 0x3) << 1;
395 
396 	packed_record[16] |= (rec->tci_mask & 0x3F) << 3;
397 
398 	packed_record[16] |= (rec->sci_mask & 0x7F) << 9;
399 	packed_record[17] = (rec->sci_mask >> 7) & 0x1;
400 
401 	packed_record[17] |= (rec->eth_type_mask & 0x3) << 1;
402 
403 	packed_record[17] |= (rec->snap_mask & 0x1F) << 3;
404 
405 	packed_record[17] |= (rec->llc_mask & 0x7) << 8;
406 
407 	packed_record[17] |= (rec->_802_2_encapsulate & 0x1) << 11;
408 
409 	packed_record[17] |= (rec->sa_mask & 0xF) << 12;
410 	packed_record[18] = (rec->sa_mask >> 4) & 0x3;
411 
412 	packed_record[18] |= (rec->da_mask & 0x3F) << 2;
413 
414 	packed_record[18] |= (rec->lpbk_mask & 0x1) << 8;
415 
416 	packed_record[18] |= (rec->sc_idx & 0x1F) << 9;
417 
418 	packed_record[18] |= (rec->proc_dest & 0x1) << 14;
419 
420 	packed_record[18] |= (rec->action & 0x1) << 15;
421 	packed_record[19] = (rec->action >> 1) & 0x1;
422 
423 	packed_record[19] |= (rec->ctrl_unctrl & 0x1) << 1;
424 
425 	packed_record[19] |= (rec->sci_from_table & 0x1) << 2;
426 
427 	packed_record[19] |= (rec->reserved & 0xF) << 3;
428 
429 	packed_record[19] |= (rec->valid & 0x1) << 7;
430 
431 	return set_raw_ingress_record(hw, packed_record, 20, 1,
432 				      ROWOFFSET_INGRESSPRECLASSRECORD +
433 					      table_index);
434 }
435 
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)
439 {
440 	int err = AQ_API_CALL_SAFE(set_ingress_preclass_record, hw, rec,
441 				   table_index);
442 
443 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
444 
445 	return err;
446 }
447 
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)
452 {
453 	u16 packed_record[20];
454 	int ret;
455 
456 	if (table_index >= NUMROWS_INGRESSPRECLASSRECORD)
457 		return -EINVAL;
458 
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.
461 	 */
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;
468 	}
469 
470 	ret = get_raw_ingress_record(hw, packed_record, 20, 1,
471 				     ROWOFFSET_INGRESSPRECLASSRECORD +
472 					     table_index);
473 	if (unlikely(ret))
474 		return ret;
475 
476 	rec->sci[0] = packed_record[0];
477 	rec->sci[0] |= packed_record[1] << 16;
478 
479 	rec->sci[1] = packed_record[2];
480 	rec->sci[1] |= packed_record[3] << 16;
481 
482 	rec->tci = packed_record[4] & 0xFF;
483 
484 	rec->encr_offset = (packed_record[4] >> 8) & 0xFF;
485 
486 	rec->eth_type = packed_record[5];
487 
488 	rec->snap[0] = packed_record[6];
489 	rec->snap[0] |= packed_record[7] << 16;
490 
491 	rec->snap[1] = packed_record[8] & 0xFF;
492 
493 	rec->llc = (packed_record[8] >> 8) & 0xFF;
494 	rec->llc |= packed_record[9] << 8;
495 
496 	rec->mac_sa[0] = packed_record[10];
497 	rec->mac_sa[0] |= packed_record[11] << 16;
498 
499 	rec->mac_sa[1] = packed_record[12];
500 
501 	rec->mac_da[0] = packed_record[13];
502 	rec->mac_da[0] |= packed_record[14] << 16;
503 
504 	rec->mac_da[1] = packed_record[15];
505 
506 	rec->lpbk_packet = packed_record[16] & 0x1;
507 
508 	rec->an_mask = (packed_record[16] >> 1) & 0x3;
509 
510 	rec->tci_mask = (packed_record[16] >> 3) & 0x3F;
511 
512 	rec->sci_mask = (packed_record[16] >> 9) & 0x7F;
513 	rec->sci_mask |= (packed_record[17] & 0x1) << 7;
514 
515 	rec->eth_type_mask = (packed_record[17] >> 1) & 0x3;
516 
517 	rec->snap_mask = (packed_record[17] >> 3) & 0x1F;
518 
519 	rec->llc_mask = (packed_record[17] >> 8) & 0x7;
520 
521 	rec->_802_2_encapsulate = (packed_record[17] >> 11) & 0x1;
522 
523 	rec->sa_mask = (packed_record[17] >> 12) & 0xF;
524 	rec->sa_mask |= (packed_record[18] & 0x3) << 4;
525 
526 	rec->da_mask = (packed_record[18] >> 2) & 0x3F;
527 
528 	rec->lpbk_mask = (packed_record[18] >> 8) & 0x1;
529 
530 	rec->sc_idx = (packed_record[18] >> 9) & 0x1F;
531 
532 	rec->proc_dest = (packed_record[18] >> 14) & 0x1;
533 
534 	rec->action = (packed_record[18] >> 15) & 0x1;
535 	rec->action |= (packed_record[19] & 0x1) << 1;
536 
537 	rec->ctrl_unctrl = (packed_record[19] >> 1) & 0x1;
538 
539 	rec->sci_from_table = (packed_record[19] >> 2) & 0x1;
540 
541 	rec->reserved = (packed_record[19] >> 3) & 0xF;
542 
543 	rec->valid = (packed_record[19] >> 7) & 0x1;
544 
545 	return 0;
546 }
547 
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)
551 {
552 	memset(rec, 0, sizeof(*rec));
553 
554 	return AQ_API_CALL_SAFE(get_ingress_preclass_record, hw, rec,
555 				table_index);
556 }
557 
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)
561 {
562 	u16 packed_record[8];
563 
564 	if (table_index >= NUMROWS_INGRESSSCRECORD)
565 		return -EINVAL;
566 
567 	memset(packed_record, 0, sizeof(u16) * 8);
568 
569 	packed_record[0] = rec->stop_time & 0xFFFF;
570 	packed_record[1] = (rec->stop_time >> 16) & 0xFFFF;
571 
572 	packed_record[2] = rec->start_time & 0xFFFF;
573 	packed_record[3] = (rec->start_time >> 16) & 0xFFFF;
574 
575 	packed_record[4] = rec->validate_frames & 0x3;
576 
577 	packed_record[4] |= (rec->replay_protect & 0x1) << 2;
578 
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;
582 
583 	packed_record[6] |= (rec->receiving & 0x1) << 3;
584 
585 	packed_record[6] |= (rec->fresh & 0x1) << 4;
586 
587 	packed_record[6] |= (rec->an_rol & 0x1) << 5;
588 
589 	packed_record[6] |= (rec->reserved & 0x3FF) << 6;
590 	packed_record[7] = (rec->reserved >> 10) & 0x7FFF;
591 
592 	packed_record[7] |= (rec->valid & 0x1) << 15;
593 
594 	return set_raw_ingress_record(hw, packed_record, 8, 3,
595 				      ROWOFFSET_INGRESSSCRECORD + table_index);
596 }
597 
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)
601 {
602 	int err = AQ_API_CALL_SAFE(set_ingress_sc_record, hw, rec, table_index);
603 
604 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
605 
606 	return err;
607 }
608 
609 static int get_ingress_sc_record(struct aq_hw_s *hw,
610 				 struct aq_mss_ingress_sc_record *rec,
611 				 u16 table_index)
612 {
613 	u16 packed_record[8];
614 	int ret;
615 
616 	if (table_index >= NUMROWS_INGRESSSCRECORD)
617 		return -EINVAL;
618 
619 	ret = get_raw_ingress_record(hw, packed_record, 8, 3,
620 				     ROWOFFSET_INGRESSSCRECORD + table_index);
621 	if (unlikely(ret))
622 		return ret;
623 
624 	rec->stop_time = packed_record[0];
625 	rec->stop_time |= packed_record[1] << 16;
626 
627 	rec->start_time = packed_record[2];
628 	rec->start_time |= packed_record[3] << 16;
629 
630 	rec->validate_frames = packed_record[4] & 0x3;
631 
632 	rec->replay_protect = (packed_record[4] >> 2) & 0x1;
633 
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;
637 
638 	rec->receiving = (packed_record[6] >> 3) & 0x1;
639 
640 	rec->fresh = (packed_record[6] >> 4) & 0x1;
641 
642 	rec->an_rol = (packed_record[6] >> 5) & 0x1;
643 
644 	rec->reserved = (packed_record[6] >> 6) & 0x3FF;
645 	rec->reserved |= (packed_record[7] & 0x7FFF) << 10;
646 
647 	rec->valid = (packed_record[7] >> 15) & 0x1;
648 
649 	return 0;
650 }
651 
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)
655 {
656 	memset(rec, 0, sizeof(*rec));
657 
658 	return AQ_API_CALL_SAFE(get_ingress_sc_record, hw, rec, table_index);
659 }
660 
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)
664 {
665 	u16 packed_record[8];
666 
667 	if (table_index >= NUMROWS_INGRESSSARECORD)
668 		return -EINVAL;
669 
670 	memset(packed_record, 0, sizeof(u16) * 8);
671 
672 	packed_record[0] = rec->stop_time & 0xFFFF;
673 	packed_record[1] = (rec->stop_time >> 16) & 0xFFFF;
674 
675 	packed_record[2] = rec->start_time & 0xFFFF;
676 	packed_record[3] = (rec->start_time >> 16) & 0xFFFF;
677 
678 	packed_record[4] = rec->next_pn & 0xFFFF;
679 	packed_record[5] = (rec->next_pn >> 16) & 0xFFFF;
680 
681 	packed_record[6] = rec->sat_nextpn & 0x1;
682 
683 	packed_record[6] |= (rec->in_use & 0x1) << 1;
684 
685 	packed_record[6] |= (rec->fresh & 0x1) << 2;
686 
687 	packed_record[6] |= (rec->reserved & 0x1FFF) << 3;
688 	packed_record[7] = (rec->reserved >> 13) & 0x7FFF;
689 
690 	packed_record[7] |= (rec->valid & 0x1) << 15;
691 
692 	return set_raw_ingress_record(hw, packed_record, 8, 3,
693 				      ROWOFFSET_INGRESSSARECORD + table_index);
694 }
695 
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)
699 {
700 	int err = AQ_API_CALL_SAFE(set_ingress_sa_record, hw, rec, table_index);
701 
702 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
703 
704 	return err;
705 }
706 
707 static int get_ingress_sa_record(struct aq_hw_s *hw,
708 				 struct aq_mss_ingress_sa_record *rec,
709 				 u16 table_index)
710 {
711 	u16 packed_record[8];
712 	int ret;
713 
714 	if (table_index >= NUMROWS_INGRESSSARECORD)
715 		return -EINVAL;
716 
717 	ret = get_raw_ingress_record(hw, packed_record, 8, 3,
718 				     ROWOFFSET_INGRESSSARECORD + table_index);
719 	if (unlikely(ret))
720 		return ret;
721 
722 	rec->stop_time = packed_record[0];
723 	rec->stop_time |= packed_record[1] << 16;
724 
725 	rec->start_time = packed_record[2];
726 	rec->start_time |= packed_record[3] << 16;
727 
728 	rec->next_pn = packed_record[4];
729 	rec->next_pn |= packed_record[5] << 16;
730 
731 	rec->sat_nextpn = packed_record[6] & 0x1;
732 
733 	rec->in_use = (packed_record[6] >> 1) & 0x1;
734 
735 	rec->fresh = (packed_record[6] >> 2) & 0x1;
736 
737 	rec->reserved = (packed_record[6] >> 3) & 0x1FFF;
738 	rec->reserved |= (packed_record[7] & 0x7FFF) << 13;
739 
740 	rec->valid = (packed_record[7] >> 15) & 0x1;
741 
742 	return 0;
743 }
744 
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)
748 {
749 	memset(rec, 0, sizeof(*rec));
750 
751 	return AQ_API_CALL_SAFE(get_ingress_sa_record, hw, rec, table_index);
752 }
753 
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)
758 {
759 	u16 packed_record[18];
760 
761 	if (table_index >= NUMROWS_INGRESSSAKEYRECORD)
762 		return -EINVAL;
763 
764 	memset(packed_record, 0, sizeof(u16) * 18);
765 
766 	packed_record[0] = rec->key[0] & 0xFFFF;
767 	packed_record[1] = (rec->key[0] >> 16) & 0xFFFF;
768 
769 	packed_record[2] = rec->key[1] & 0xFFFF;
770 	packed_record[3] = (rec->key[1] >> 16) & 0xFFFF;
771 
772 	packed_record[4] = rec->key[2] & 0xFFFF;
773 	packed_record[5] = (rec->key[2] >> 16) & 0xFFFF;
774 
775 	packed_record[6] = rec->key[3] & 0xFFFF;
776 	packed_record[7] = (rec->key[3] >> 16) & 0xFFFF;
777 
778 	packed_record[8] = rec->key[4] & 0xFFFF;
779 	packed_record[9] = (rec->key[4] >> 16) & 0xFFFF;
780 
781 	packed_record[10] = rec->key[5] & 0xFFFF;
782 	packed_record[11] = (rec->key[5] >> 16) & 0xFFFF;
783 
784 	packed_record[12] = rec->key[6] & 0xFFFF;
785 	packed_record[13] = (rec->key[6] >> 16) & 0xFFFF;
786 
787 	packed_record[14] = rec->key[7] & 0xFFFF;
788 	packed_record[15] = (rec->key[7] >> 16) & 0xFFFF;
789 
790 	packed_record[16] = rec->key_len & 0x3;
791 
792 	return set_raw_ingress_record(hw, packed_record, 18, 2,
793 				      ROWOFFSET_INGRESSSAKEYRECORD +
794 					      table_index);
795 }
796 
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)
800 {
801 	int err = AQ_API_CALL_SAFE(set_ingress_sakey_record, hw, rec,
802 				   table_index);
803 
804 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
805 
806 	return err;
807 }
808 
809 static int get_ingress_sakey_record(struct aq_hw_s *hw,
810 				    struct aq_mss_ingress_sakey_record *rec,
811 				    u16 table_index)
812 {
813 	u16 packed_record[18];
814 	int ret;
815 
816 	if (table_index >= NUMROWS_INGRESSSAKEYRECORD)
817 		return -EINVAL;
818 
819 	ret = get_raw_ingress_record(hw, packed_record, 18, 2,
820 				     ROWOFFSET_INGRESSSAKEYRECORD +
821 					     table_index);
822 	if (unlikely(ret))
823 		return ret;
824 
825 	rec->key[0] = packed_record[0];
826 	rec->key[0] |= packed_record[1] << 16;
827 
828 	rec->key[1] = packed_record[2];
829 	rec->key[1] |= packed_record[3] << 16;
830 
831 	rec->key[2] = packed_record[4];
832 	rec->key[2] |= packed_record[5] << 16;
833 
834 	rec->key[3] = packed_record[6];
835 	rec->key[3] |= packed_record[7] << 16;
836 
837 	rec->key[4] = packed_record[8];
838 	rec->key[4] |= packed_record[9] << 16;
839 
840 	rec->key[5] = packed_record[10];
841 	rec->key[5] |= packed_record[11] << 16;
842 
843 	rec->key[6] = packed_record[12];
844 	rec->key[6] |= packed_record[13] << 16;
845 
846 	rec->key[7] = packed_record[14];
847 	rec->key[7] |= packed_record[15] << 16;
848 
849 	rec->key_len = packed_record[16] & 0x3;
850 
851 	return 0;
852 }
853 
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)
857 {
858 	memset(rec, 0, sizeof(*rec));
859 
860 	return AQ_API_CALL_SAFE(get_ingress_sakey_record, hw, rec, table_index);
861 }
862 
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)
867 {
868 	u16 packed_record[8];
869 
870 	if (table_index >= NUMROWS_INGRESSPOSTCLASSRECORD)
871 		return -EINVAL;
872 
873 	memset(packed_record, 0, sizeof(u16) * 8);
874 
875 	packed_record[0] = rec->byte0 & 0xFF;
876 
877 	packed_record[0] |= (rec->byte1 & 0xFF) << 8;
878 
879 	packed_record[1] = rec->byte2 & 0xFF;
880 
881 	packed_record[1] |= (rec->byte3 & 0xFF) << 8;
882 
883 	packed_record[2] = rec->eth_type & 0xFFFF;
884 
885 	packed_record[3] = rec->eth_type_valid & 0x1;
886 
887 	packed_record[3] |= (rec->vlan_id & 0xFFF) << 1;
888 
889 	packed_record[3] |= (rec->vlan_up & 0x7) << 13;
890 
891 	packed_record[4] = rec->vlan_valid & 0x1;
892 
893 	packed_record[4] |= (rec->sai & 0x1F) << 1;
894 
895 	packed_record[4] |= (rec->sai_hit & 0x1) << 6;
896 
897 	packed_record[4] |= (rec->eth_type_mask & 0xF) << 7;
898 
899 	packed_record[4] |= (rec->byte3_location & 0x1F) << 11;
900 	packed_record[5] = (rec->byte3_location >> 5) & 0x1;
901 
902 	packed_record[5] |= (rec->byte3_mask & 0x3) << 1;
903 
904 	packed_record[5] |= (rec->byte2_location & 0x3F) << 3;
905 
906 	packed_record[5] |= (rec->byte2_mask & 0x3) << 9;
907 
908 	packed_record[5] |= (rec->byte1_location & 0x1F) << 11;
909 	packed_record[6] = (rec->byte1_location >> 5) & 0x1;
910 
911 	packed_record[6] |= (rec->byte1_mask & 0x3) << 1;
912 
913 	packed_record[6] |= (rec->byte0_location & 0x3F) << 3;
914 
915 	packed_record[6] |= (rec->byte0_mask & 0x3) << 9;
916 
917 	packed_record[6] |= (rec->eth_type_valid_mask & 0x3) << 11;
918 
919 	packed_record[6] |= (rec->vlan_id_mask & 0x7) << 13;
920 	packed_record[7] = (rec->vlan_id_mask >> 3) & 0x1;
921 
922 	packed_record[7] |= (rec->vlan_up_mask & 0x3) << 1;
923 
924 	packed_record[7] |= (rec->vlan_valid_mask & 0x3) << 3;
925 
926 	packed_record[7] |= (rec->sai_mask & 0x3) << 5;
927 
928 	packed_record[7] |= (rec->sai_hit_mask & 0x3) << 7;
929 
930 	packed_record[7] |= (rec->firstlevel_actions & 0x1) << 9;
931 
932 	packed_record[7] |= (rec->secondlevel_actions & 0x1) << 10;
933 
934 	packed_record[7] |= (rec->reserved & 0xF) << 11;
935 
936 	packed_record[7] |= (rec->valid & 0x1) << 15;
937 
938 	return set_raw_ingress_record(hw, packed_record, 8, 4,
939 				      ROWOFFSET_INGRESSPOSTCLASSRECORD +
940 					      table_index);
941 }
942 
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)
946 {
947 	return AQ_API_CALL_SAFE(set_ingress_postclass_record, hw, rec,
948 				table_index);
949 }
950 
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)
955 {
956 	u16 packed_record[8];
957 	int ret;
958 
959 	if (table_index >= NUMROWS_INGRESSPOSTCLASSRECORD)
960 		return -EINVAL;
961 
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.
964 	 */
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;
971 	}
972 
973 	ret = get_raw_ingress_record(hw, packed_record, 8, 4,
974 				     ROWOFFSET_INGRESSPOSTCLASSRECORD +
975 					     table_index);
976 	if (unlikely(ret))
977 		return ret;
978 
979 	rec->byte0 = packed_record[0] & 0xFF;
980 
981 	rec->byte1 = (packed_record[0] >> 8) & 0xFF;
982 
983 	rec->byte2 = packed_record[1] & 0xFF;
984 
985 	rec->byte3 = (packed_record[1] >> 8) & 0xFF;
986 
987 	rec->eth_type = packed_record[2];
988 
989 	rec->eth_type_valid = packed_record[3] & 0x1;
990 
991 	rec->vlan_id = (packed_record[3] >> 1) & 0xFFF;
992 
993 	rec->vlan_up = (packed_record[3] >> 13) & 0x7;
994 
995 	rec->vlan_valid = packed_record[4] & 0x1;
996 
997 	rec->sai = (packed_record[4] >> 1) & 0x1F;
998 
999 	rec->sai_hit = (packed_record[4] >> 6) & 0x1;
1000 
1001 	rec->eth_type_mask = (packed_record[4] >> 7) & 0xF;
1002 
1003 	rec->byte3_location = (packed_record[4] >> 11) & 0x1F;
1004 	rec->byte3_location |= (packed_record[5] & 0x1) << 5;
1005 
1006 	rec->byte3_mask = (packed_record[5] >> 1) & 0x3;
1007 
1008 	rec->byte2_location = (packed_record[5] >> 3) & 0x3F;
1009 
1010 	rec->byte2_mask = (packed_record[5] >> 9) & 0x3;
1011 
1012 	rec->byte1_location = (packed_record[5] >> 11) & 0x1F;
1013 	rec->byte1_location |= (packed_record[6] & 0x1) << 5;
1014 
1015 	rec->byte1_mask = (packed_record[6] >> 1) & 0x3;
1016 
1017 	rec->byte0_location = (packed_record[6] >> 3) & 0x3F;
1018 
1019 	rec->byte0_mask = (packed_record[6] >> 9) & 0x3;
1020 
1021 	rec->eth_type_valid_mask = (packed_record[6] >> 11) & 0x3;
1022 
1023 	rec->vlan_id_mask = (packed_record[6] >> 13) & 0x7;
1024 	rec->vlan_id_mask |= (packed_record[7] & 0x1) << 3;
1025 
1026 	rec->vlan_up_mask = (packed_record[7] >> 1) & 0x3;
1027 
1028 	rec->vlan_valid_mask = (packed_record[7] >> 3) & 0x3;
1029 
1030 	rec->sai_mask = (packed_record[7] >> 5) & 0x3;
1031 
1032 	rec->sai_hit_mask = (packed_record[7] >> 7) & 0x3;
1033 
1034 	rec->firstlevel_actions = (packed_record[7] >> 9) & 0x1;
1035 
1036 	rec->secondlevel_actions = (packed_record[7] >> 10) & 0x1;
1037 
1038 	rec->reserved = (packed_record[7] >> 11) & 0xF;
1039 
1040 	rec->valid = (packed_record[7] >> 15) & 0x1;
1041 
1042 	return 0;
1043 }
1044 
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)
1048 {
1049 	memset(rec, 0, sizeof(*rec));
1050 
1051 	return AQ_API_CALL_SAFE(get_ingress_postclass_record, hw, rec,
1052 				table_index);
1053 }
1054 
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)
1059 {
1060 	u16 packed_record[6];
1061 
1062 	if (table_index >= NUMROWS_INGRESSPOSTCTLFRECORD)
1063 		return -EINVAL;
1064 
1065 	memset(packed_record, 0, sizeof(u16) * 6);
1066 
1067 	packed_record[0] = rec->sa_da[0] & 0xFFFF;
1068 	packed_record[1] = (rec->sa_da[0] >> 16) & 0xFFFF;
1069 
1070 	packed_record[2] = rec->sa_da[1] & 0xFFFF;
1071 
1072 	packed_record[3] = rec->eth_type & 0xFFFF;
1073 
1074 	packed_record[4] = rec->match_mask & 0xFFFF;
1075 
1076 	packed_record[5] = rec->match_type & 0xF;
1077 
1078 	packed_record[5] |= (rec->action & 0x1) << 4;
1079 
1080 	return set_raw_ingress_record(hw, packed_record, 6, 5,
1081 				      ROWOFFSET_INGRESSPOSTCTLFRECORD +
1082 					      table_index);
1083 }
1084 
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)
1088 {
1089 	return AQ_API_CALL_SAFE(set_ingress_postctlf_record, hw, rec,
1090 				table_index);
1091 }
1092 
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)
1097 {
1098 	u16 packed_record[6];
1099 	int ret;
1100 
1101 	if (table_index >= NUMROWS_INGRESSPOSTCTLFRECORD)
1102 		return -EINVAL;
1103 
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.
1106 	 */
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;
1113 	}
1114 
1115 	ret = get_raw_ingress_record(hw, packed_record, 6, 5,
1116 				     ROWOFFSET_INGRESSPOSTCTLFRECORD +
1117 					     table_index);
1118 	if (unlikely(ret))
1119 		return ret;
1120 
1121 	rec->sa_da[0] = packed_record[0];
1122 	rec->sa_da[0] |= packed_record[1] << 16;
1123 
1124 	rec->sa_da[1] = packed_record[2];
1125 
1126 	rec->eth_type = packed_record[3];
1127 
1128 	rec->match_mask = packed_record[4];
1129 
1130 	rec->match_type = packed_record[5] & 0xF;
1131 
1132 	rec->action = (packed_record[5] >> 4) & 0x1;
1133 
1134 	return 0;
1135 }
1136 
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)
1140 {
1141 	memset(rec, 0, sizeof(*rec));
1142 
1143 	return AQ_API_CALL_SAFE(get_ingress_postctlf_record, hw, rec,
1144 				table_index);
1145 }
1146 
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)
1150 {
1151 	u16 packed_record[6];
1152 
1153 	if (table_index >= NUMROWS_EGRESSCTLFRECORD)
1154 		return -EINVAL;
1155 
1156 	memset(packed_record, 0, sizeof(u16) * 6);
1157 
1158 	packed_record[0] = rec->sa_da[0] & 0xFFFF;
1159 	packed_record[1] = (rec->sa_da[0] >> 16) & 0xFFFF;
1160 
1161 	packed_record[2] = rec->sa_da[1] & 0xFFFF;
1162 
1163 	packed_record[3] = rec->eth_type & 0xFFFF;
1164 
1165 	packed_record[4] = rec->match_mask & 0xFFFF;
1166 
1167 	packed_record[5] = rec->match_type & 0xF;
1168 
1169 	packed_record[5] |= (rec->action & 0x1) << 4;
1170 
1171 	return set_raw_egress_record(hw, packed_record, 6, 0,
1172 				     ROWOFFSET_EGRESSCTLFRECORD + table_index);
1173 }
1174 
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)
1178 {
1179 	return AQ_API_CALL_SAFE(set_egress_ctlf_record, hw, rec, table_index);
1180 }
1181 
1182 static int get_egress_ctlf_record(struct aq_hw_s *hw,
1183 				  struct aq_mss_egress_ctlf_record *rec,
1184 				  u16 table_index)
1185 {
1186 	u16 packed_record[6];
1187 	int ret;
1188 
1189 	if (table_index >= NUMROWS_EGRESSCTLFRECORD)
1190 		return -EINVAL;
1191 
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.
1194 	 */
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;
1201 	}
1202 
1203 	ret = get_raw_egress_record(hw, packed_record, 6, 0,
1204 				    ROWOFFSET_EGRESSCTLFRECORD + table_index);
1205 	if (unlikely(ret))
1206 		return ret;
1207 
1208 	rec->sa_da[0] = packed_record[0];
1209 	rec->sa_da[0] |= packed_record[1] << 16;
1210 
1211 	rec->sa_da[1] = packed_record[2];
1212 
1213 	rec->eth_type = packed_record[3];
1214 
1215 	rec->match_mask = packed_record[4];
1216 
1217 	rec->match_type = packed_record[5] & 0xF;
1218 
1219 	rec->action = (packed_record[5] >> 4) & 0x1;
1220 
1221 	return 0;
1222 }
1223 
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)
1227 {
1228 	memset(rec, 0, sizeof(*rec));
1229 
1230 	return AQ_API_CALL_SAFE(get_egress_ctlf_record, hw, rec, table_index);
1231 }
1232 
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)
1236 {
1237 	u16 packed_record[28];
1238 
1239 	if (table_index >= NUMROWS_EGRESSCLASSRECORD)
1240 		return -EINVAL;
1241 
1242 	memset(packed_record, 0, sizeof(u16) * 28);
1243 
1244 	packed_record[0] = rec->vlan_id & 0xFFF;
1245 
1246 	packed_record[0] |= (rec->vlan_up & 0x7) << 12;
1247 
1248 	packed_record[0] |= (rec->vlan_valid & 0x1) << 15;
1249 
1250 	packed_record[1] = rec->byte3 & 0xFF;
1251 
1252 	packed_record[1] |= (rec->byte2 & 0xFF) << 8;
1253 
1254 	packed_record[2] = rec->byte1 & 0xFF;
1255 
1256 	packed_record[2] |= (rec->byte0 & 0xFF) << 8;
1257 
1258 	packed_record[3] = rec->tci & 0xFF;
1259 
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;
1263 
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;
1267 
1268 	packed_record[7] |= (rec->eth_type & 0xFF) << 8;
1269 	packed_record[8] = (rec->eth_type >> 8) & 0xFF;
1270 
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;
1274 
1275 	packed_record[10] |= (rec->snap[1] & 0xFF) << 8;
1276 
1277 	packed_record[11] = rec->llc & 0xFFFF;
1278 	packed_record[12] = (rec->llc >> 16) & 0xFF;
1279 
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;
1283 
1284 	packed_record[14] |= (rec->mac_sa[1] & 0xFF) << 8;
1285 	packed_record[15] = (rec->mac_sa[1] >> 8) & 0xFF;
1286 
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;
1290 
1291 	packed_record[17] |= (rec->mac_da[1] & 0xFF) << 8;
1292 	packed_record[18] = (rec->mac_da[1] >> 8) & 0xFF;
1293 
1294 	packed_record[18] |= (rec->pn & 0xFF) << 8;
1295 	packed_record[19] = (rec->pn >> 8) & 0xFFFF;
1296 	packed_record[20] = (rec->pn >> 24) & 0xFF;
1297 
1298 	packed_record[20] |= (rec->byte3_location & 0x3F) << 8;
1299 
1300 	packed_record[20] |= (rec->byte3_mask & 0x1) << 14;
1301 
1302 	packed_record[20] |= (rec->byte2_location & 0x1) << 15;
1303 	packed_record[21] = (rec->byte2_location >> 1) & 0x1F;
1304 
1305 	packed_record[21] |= (rec->byte2_mask & 0x1) << 5;
1306 
1307 	packed_record[21] |= (rec->byte1_location & 0x3F) << 6;
1308 
1309 	packed_record[21] |= (rec->byte1_mask & 0x1) << 12;
1310 
1311 	packed_record[21] |= (rec->byte0_location & 0x7) << 13;
1312 	packed_record[22] = (rec->byte0_location >> 3) & 0x7;
1313 
1314 	packed_record[22] |= (rec->byte0_mask & 0x1) << 3;
1315 
1316 	packed_record[22] |= (rec->vlan_id_mask & 0x3) << 4;
1317 
1318 	packed_record[22] |= (rec->vlan_up_mask & 0x1) << 6;
1319 
1320 	packed_record[22] |= (rec->vlan_valid_mask & 0x1) << 7;
1321 
1322 	packed_record[22] |= (rec->tci_mask & 0xFF) << 8;
1323 
1324 	packed_record[23] = rec->sci_mask & 0xFF;
1325 
1326 	packed_record[23] |= (rec->eth_type_mask & 0x3) << 8;
1327 
1328 	packed_record[23] |= (rec->snap_mask & 0x1F) << 10;
1329 
1330 	packed_record[23] |= (rec->llc_mask & 0x1) << 15;
1331 	packed_record[24] = (rec->llc_mask >> 1) & 0x3;
1332 
1333 	packed_record[24] |= (rec->sa_mask & 0x3F) << 2;
1334 
1335 	packed_record[24] |= (rec->da_mask & 0x3F) << 8;
1336 
1337 	packed_record[24] |= (rec->pn_mask & 0x3) << 14;
1338 	packed_record[25] = (rec->pn_mask >> 2) & 0x3;
1339 
1340 	packed_record[25] |= (rec->eight02dot2 & 0x1) << 2;
1341 
1342 	packed_record[25] |= (rec->tci_sc & 0x1) << 3;
1343 
1344 	packed_record[25] |= (rec->tci_87543 & 0x1) << 4;
1345 
1346 	packed_record[25] |= (rec->exp_sectag_en & 0x1) << 5;
1347 
1348 	packed_record[25] |= (rec->sc_idx & 0x1F) << 6;
1349 
1350 	packed_record[25] |= (rec->sc_sa & 0x3) << 11;
1351 
1352 	packed_record[25] |= (rec->debug & 0x1) << 13;
1353 
1354 	packed_record[25] |= (rec->action & 0x3) << 14;
1355 
1356 	packed_record[26] = (rec->valid & 0x1) << 3;
1357 
1358 	return set_raw_egress_record(hw, packed_record, 28, 1,
1359 				     ROWOFFSET_EGRESSCLASSRECORD + table_index);
1360 }
1361 
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)
1365 {
1366 	return AQ_API_CALL_SAFE(set_egress_class_record, hw, rec, table_index);
1367 }
1368 
1369 static int get_egress_class_record(struct aq_hw_s *hw,
1370 				   struct aq_mss_egress_class_record *rec,
1371 				   u16 table_index)
1372 {
1373 	u16 packed_record[28];
1374 	int ret;
1375 
1376 	if (table_index >= NUMROWS_EGRESSCLASSRECORD)
1377 		return -EINVAL;
1378 
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.
1381 	 */
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;
1388 	}
1389 
1390 	ret = get_raw_egress_record(hw, packed_record, 28, 1,
1391 				    ROWOFFSET_EGRESSCLASSRECORD + table_index);
1392 	if (unlikely(ret))
1393 		return ret;
1394 
1395 	rec->vlan_id = packed_record[0] & 0xFFF;
1396 
1397 	rec->vlan_up = (packed_record[0] >> 12) & 0x7;
1398 
1399 	rec->vlan_valid = (packed_record[0] >> 15) & 0x1;
1400 
1401 	rec->byte3 = packed_record[1] & 0xFF;
1402 
1403 	rec->byte2 = (packed_record[1] >> 8) & 0xFF;
1404 
1405 	rec->byte1 = packed_record[2] & 0xFF;
1406 
1407 	rec->byte0 = (packed_record[2] >> 8) & 0xFF;
1408 
1409 	rec->tci = packed_record[3] & 0xFF;
1410 
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;
1414 
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;
1418 
1419 	rec->eth_type = (packed_record[7] >> 8) & 0xFF;
1420 	rec->eth_type |= (packed_record[8] & 0xFF) << 8;
1421 
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;
1425 
1426 	rec->snap[1] = (packed_record[10] >> 8) & 0xFF;
1427 
1428 	rec->llc = packed_record[11];
1429 	rec->llc |= (packed_record[12] & 0xFF) << 16;
1430 
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;
1434 
1435 	rec->mac_sa[1] = (packed_record[14] >> 8) & 0xFF;
1436 	rec->mac_sa[1] |= (packed_record[15] & 0xFF) << 8;
1437 
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;
1441 
1442 	rec->mac_da[1] = (packed_record[17] >> 8) & 0xFF;
1443 	rec->mac_da[1] |= (packed_record[18] & 0xFF) << 8;
1444 
1445 	rec->pn = (packed_record[18] >> 8) & 0xFF;
1446 	rec->pn |= packed_record[19] << 8;
1447 	rec->pn |= (packed_record[20] & 0xFF) << 24;
1448 
1449 	rec->byte3_location = (packed_record[20] >> 8) & 0x3F;
1450 
1451 	rec->byte3_mask = (packed_record[20] >> 14) & 0x1;
1452 
1453 	rec->byte2_location = (packed_record[20] >> 15) & 0x1;
1454 	rec->byte2_location |= (packed_record[21] & 0x1F) << 1;
1455 
1456 	rec->byte2_mask = (packed_record[21] >> 5) & 0x1;
1457 
1458 	rec->byte1_location = (packed_record[21] >> 6) & 0x3F;
1459 
1460 	rec->byte1_mask = (packed_record[21] >> 12) & 0x1;
1461 
1462 	rec->byte0_location = (packed_record[21] >> 13) & 0x7;
1463 	rec->byte0_location |= (packed_record[22] & 0x7) << 3;
1464 
1465 	rec->byte0_mask = (packed_record[22] >> 3) & 0x1;
1466 
1467 	rec->vlan_id_mask = (packed_record[22] >> 4) & 0x3;
1468 
1469 	rec->vlan_up_mask = (packed_record[22] >> 6) & 0x1;
1470 
1471 	rec->vlan_valid_mask = (packed_record[22] >> 7) & 0x1;
1472 
1473 	rec->tci_mask = (packed_record[22] >> 8) & 0xFF;
1474 
1475 	rec->sci_mask = packed_record[23] & 0xFF;
1476 
1477 	rec->eth_type_mask = (packed_record[23] >> 8) & 0x3;
1478 
1479 	rec->snap_mask = (packed_record[23] >> 10) & 0x1F;
1480 
1481 	rec->llc_mask = (packed_record[23] >> 15) & 0x1;
1482 	rec->llc_mask |= (packed_record[24] & 0x3) << 1;
1483 
1484 	rec->sa_mask = (packed_record[24] >> 2) & 0x3F;
1485 
1486 	rec->da_mask = (packed_record[24] >> 8) & 0x3F;
1487 
1488 	rec->pn_mask = (packed_record[24] >> 14) & 0x3;
1489 	rec->pn_mask |= (packed_record[25] & 0x3) << 2;
1490 
1491 	rec->eight02dot2 = (packed_record[25] >> 2) & 0x1;
1492 
1493 	rec->tci_sc = (packed_record[25] >> 3) & 0x1;
1494 
1495 	rec->tci_87543 = (packed_record[25] >> 4) & 0x1;
1496 
1497 	rec->exp_sectag_en = (packed_record[25] >> 5) & 0x1;
1498 
1499 	rec->sc_idx = (packed_record[25] >> 6) & 0x1F;
1500 
1501 	rec->sc_sa = (packed_record[25] >> 11) & 0x3;
1502 
1503 	rec->debug = (packed_record[25] >> 13) & 0x1;
1504 
1505 	rec->action = (packed_record[25] >> 14) & 0x3;
1506 
1507 	rec->valid = (packed_record[26] >> 3) & 0x1;
1508 
1509 	return 0;
1510 }
1511 
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)
1515 {
1516 	memset(rec, 0, sizeof(*rec));
1517 
1518 	return AQ_API_CALL_SAFE(get_egress_class_record, hw, rec, table_index);
1519 }
1520 
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)
1524 {
1525 	u16 packed_record[8];
1526 
1527 	if (table_index >= NUMROWS_EGRESSSCRECORD)
1528 		return -EINVAL;
1529 
1530 	memset(packed_record, 0, sizeof(u16) * 8);
1531 
1532 	packed_record[0] = rec->start_time & 0xFFFF;
1533 	packed_record[1] = (rec->start_time >> 16) & 0xFFFF;
1534 
1535 	packed_record[2] = rec->stop_time & 0xFFFF;
1536 	packed_record[3] = (rec->stop_time >> 16) & 0xFFFF;
1537 
1538 	packed_record[4] = rec->curr_an & 0x3;
1539 
1540 	packed_record[4] |= (rec->an_roll & 0x1) << 2;
1541 
1542 	packed_record[4] |= (rec->tci & 0x3F) << 3;
1543 
1544 	packed_record[4] |= (rec->enc_off & 0x7F) << 9;
1545 	packed_record[5] = (rec->enc_off >> 7) & 0x1;
1546 
1547 	packed_record[5] |= (rec->protect & 0x1) << 1;
1548 
1549 	packed_record[5] |= (rec->recv & 0x1) << 2;
1550 
1551 	packed_record[5] |= (rec->fresh & 0x1) << 3;
1552 
1553 	packed_record[5] |= (rec->sak_len & 0x3) << 4;
1554 
1555 	packed_record[7] = (rec->valid & 0x1) << 15;
1556 
1557 	return set_raw_egress_record(hw, packed_record, 8, 2,
1558 				     ROWOFFSET_EGRESSSCRECORD + table_index);
1559 }
1560 
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)
1564 {
1565 	return AQ_API_CALL_SAFE(set_egress_sc_record, hw, rec, table_index);
1566 }
1567 
1568 static int get_egress_sc_record(struct aq_hw_s *hw,
1569 				struct aq_mss_egress_sc_record *rec,
1570 				u16 table_index)
1571 {
1572 	u16 packed_record[8];
1573 	int ret;
1574 
1575 	if (table_index >= NUMROWS_EGRESSSCRECORD)
1576 		return -EINVAL;
1577 
1578 	ret = get_raw_egress_record(hw, packed_record, 8, 2,
1579 				    ROWOFFSET_EGRESSSCRECORD + table_index);
1580 	if (unlikely(ret))
1581 		return ret;
1582 
1583 	rec->start_time = packed_record[0];
1584 	rec->start_time |= packed_record[1] << 16;
1585 
1586 	rec->stop_time = packed_record[2];
1587 	rec->stop_time |= packed_record[3] << 16;
1588 
1589 	rec->curr_an = packed_record[4] & 0x3;
1590 
1591 	rec->an_roll = (packed_record[4] >> 2) & 0x1;
1592 
1593 	rec->tci = (packed_record[4] >> 3) & 0x3F;
1594 
1595 	rec->enc_off = (packed_record[4] >> 9) & 0x7F;
1596 	rec->enc_off |= (packed_record[5] & 0x1) << 7;
1597 
1598 	rec->protect = (packed_record[5] >> 1) & 0x1;
1599 
1600 	rec->recv = (packed_record[5] >> 2) & 0x1;
1601 
1602 	rec->fresh = (packed_record[5] >> 3) & 0x1;
1603 
1604 	rec->sak_len = (packed_record[5] >> 4) & 0x3;
1605 
1606 	rec->valid = (packed_record[7] >> 15) & 0x1;
1607 
1608 	return 0;
1609 }
1610 
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)
1614 {
1615 	memset(rec, 0, sizeof(*rec));
1616 
1617 	return AQ_API_CALL_SAFE(get_egress_sc_record, hw, rec, table_index);
1618 }
1619 
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)
1623 {
1624 	u16 packed_record[8];
1625 
1626 	if (table_index >= NUMROWS_EGRESSSARECORD)
1627 		return -EINVAL;
1628 
1629 	memset(packed_record, 0, sizeof(u16) * 8);
1630 
1631 	packed_record[0] = rec->start_time & 0xFFFF;
1632 	packed_record[1] = (rec->start_time >> 16) & 0xFFFF;
1633 
1634 	packed_record[2] = rec->stop_time & 0xFFFF;
1635 	packed_record[3] = (rec->stop_time >> 16) & 0xFFFF;
1636 
1637 	packed_record[4] = rec->next_pn & 0xFFFF;
1638 	packed_record[5] = (rec->next_pn >> 16) & 0xFFFF;
1639 
1640 	packed_record[6] = rec->sat_pn & 0x1;
1641 
1642 	packed_record[6] |= (rec->fresh & 0x1) << 1;
1643 
1644 	packed_record[7] = (rec->valid & 0x1) << 15;
1645 
1646 	return set_raw_egress_record(hw, packed_record, 8, 2,
1647 				     ROWOFFSET_EGRESSSARECORD + table_index);
1648 }
1649 
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)
1653 {
1654 	int err = AQ_API_CALL_SAFE(set_egress_sa_record, hw, rec, table_index);
1655 
1656 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
1657 
1658 	return err;
1659 }
1660 
1661 static int get_egress_sa_record(struct aq_hw_s *hw,
1662 				struct aq_mss_egress_sa_record *rec,
1663 				u16 table_index)
1664 {
1665 	u16 packed_record[8];
1666 	int ret;
1667 
1668 	if (table_index >= NUMROWS_EGRESSSARECORD)
1669 		return -EINVAL;
1670 
1671 	ret = get_raw_egress_record(hw, packed_record, 8, 2,
1672 				    ROWOFFSET_EGRESSSARECORD + table_index);
1673 	if (unlikely(ret))
1674 		return ret;
1675 
1676 	rec->start_time = packed_record[0];
1677 	rec->start_time |= packed_record[1] << 16;
1678 
1679 	rec->stop_time = packed_record[2];
1680 	rec->stop_time |= packed_record[3] << 16;
1681 
1682 	rec->next_pn = packed_record[4];
1683 	rec->next_pn |= packed_record[5] << 16;
1684 
1685 	rec->sat_pn = packed_record[6] & 0x1;
1686 
1687 	rec->fresh = (packed_record[6] >> 1) & 0x1;
1688 
1689 	rec->valid = (packed_record[7] >> 15) & 0x1;
1690 
1691 	return 0;
1692 }
1693 
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)
1697 {
1698 	memset(rec, 0, sizeof(*rec));
1699 
1700 	return AQ_API_CALL_SAFE(get_egress_sa_record, hw, rec, table_index);
1701 }
1702 
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)
1706 {
1707 	u16 packed_record[16];
1708 	int ret;
1709 
1710 	if (table_index >= NUMROWS_EGRESSSAKEYRECORD)
1711 		return -EINVAL;
1712 
1713 	memset(packed_record, 0, sizeof(u16) * 16);
1714 
1715 	packed_record[0] = rec->key[0] & 0xFFFF;
1716 	packed_record[1] = (rec->key[0] >> 16) & 0xFFFF;
1717 
1718 	packed_record[2] = rec->key[1] & 0xFFFF;
1719 	packed_record[3] = (rec->key[1] >> 16) & 0xFFFF;
1720 
1721 	packed_record[4] = rec->key[2] & 0xFFFF;
1722 	packed_record[5] = (rec->key[2] >> 16) & 0xFFFF;
1723 
1724 	packed_record[6] = rec->key[3] & 0xFFFF;
1725 	packed_record[7] = (rec->key[3] >> 16) & 0xFFFF;
1726 
1727 	packed_record[8] = rec->key[4] & 0xFFFF;
1728 	packed_record[9] = (rec->key[4] >> 16) & 0xFFFF;
1729 
1730 	packed_record[10] = rec->key[5] & 0xFFFF;
1731 	packed_record[11] = (rec->key[5] >> 16) & 0xFFFF;
1732 
1733 	packed_record[12] = rec->key[6] & 0xFFFF;
1734 	packed_record[13] = (rec->key[6] >> 16) & 0xFFFF;
1735 
1736 	packed_record[14] = rec->key[7] & 0xFFFF;
1737 	packed_record[15] = (rec->key[7] >> 16) & 0xFFFF;
1738 
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;
1748 
1749 	return 0;
1750 }
1751 
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)
1755 {
1756 	int err = AQ_API_CALL_SAFE(set_egress_sakey_record, hw, rec,
1757 				   table_index);
1758 
1759 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
1760 
1761 	return err;
1762 }
1763 
1764 static int get_egress_sakey_record(struct aq_hw_s *hw,
1765 				   struct aq_mss_egress_sakey_record *rec,
1766 				   u16 table_index)
1767 {
1768 	u16 packed_record[16];
1769 	int ret;
1770 
1771 	if (table_index >= NUMROWS_EGRESSSAKEYRECORD)
1772 		return -EINVAL;
1773 
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;
1783 
1784 	rec->key[0] = packed_record[0];
1785 	rec->key[0] |= packed_record[1] << 16;
1786 
1787 	rec->key[1] = packed_record[2];
1788 	rec->key[1] |= packed_record[3] << 16;
1789 
1790 	rec->key[2] = packed_record[4];
1791 	rec->key[2] |= packed_record[5] << 16;
1792 
1793 	rec->key[3] = packed_record[6];
1794 	rec->key[3] |= packed_record[7] << 16;
1795 
1796 	rec->key[4] = packed_record[8];
1797 	rec->key[4] |= packed_record[9] << 16;
1798 
1799 	rec->key[5] = packed_record[10];
1800 	rec->key[5] |= packed_record[11] << 16;
1801 
1802 	rec->key[6] = packed_record[12];
1803 	rec->key[6] |= packed_record[13] << 16;
1804 
1805 	rec->key[7] = packed_record[14];
1806 	rec->key[7] |= packed_record[15] << 16;
1807 
1808 	return 0;
1809 }
1810 
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)
1814 {
1815 	memset(rec, 0, sizeof(*rec));
1816 
1817 	return AQ_API_CALL_SAFE(get_egress_sakey_record, hw, rec, table_index);
1818 }
1819 
1820 static int get_egress_sc_counters(struct aq_hw_s *hw,
1821 				  struct aq_mss_egress_sc_counters *counters,
1822 				  u16 sc_index)
1823 {
1824 	u16 packed_record[4];
1825 	int ret;
1826 
1827 	if (sc_index >= NUMROWS_EGRESSSCRECORD)
1828 		return -EINVAL;
1829 
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);
1837 
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);
1845 
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);
1853 
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);
1861 
1862 	return 0;
1863 }
1864 
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)
1868 {
1869 	memset(counters, 0, sizeof(*counters));
1870 
1871 	return AQ_API_CALL_SAFE(get_egress_sc_counters, hw, counters, sc_index);
1872 }
1873 
1874 static int get_egress_sa_counters(struct aq_hw_s *hw,
1875 				  struct aq_mss_egress_sa_counters *counters,
1876 				  u16 sa_index)
1877 {
1878 	u16 packed_record[4];
1879 	int ret;
1880 
1881 	if (sa_index >= NUMROWS_EGRESSSARECORD)
1882 		return -EINVAL;
1883 
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);
1891 
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);
1899 
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);
1907 
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);
1915 
1916 	return 0;
1917 }
1918 
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)
1922 {
1923 	memset(counters, 0, sizeof(*counters));
1924 
1925 	return AQ_API_CALL_SAFE(get_egress_sa_counters, hw, counters, sa_index);
1926 }
1927 
1928 static int
1929 get_egress_common_counters(struct aq_hw_s *hw,
1930 			   struct aq_mss_egress_common_counters *counters)
1931 {
1932 	u16 packed_record[4];
1933 	int ret;
1934 
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);
1940 
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);
1948 
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);
1956 
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);
1962 
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);
1970 
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);
1978 
1979 	return 0;
1980 }
1981 
1982 int aq_mss_get_egress_common_counters(struct aq_hw_s *hw,
1983 	struct aq_mss_egress_common_counters *counters)
1984 {
1985 	memset(counters, 0, sizeof(*counters));
1986 
1987 	return AQ_API_CALL_SAFE(get_egress_common_counters, hw, counters);
1988 }
1989 
1990 static int clear_egress_counters(struct aq_hw_s *hw)
1991 {
1992 	struct mss_egress_ctl_register ctl_reg;
1993 	int ret;
1994 
1995 	memset(&ctl_reg, 0, sizeof(ctl_reg));
1996 
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;
2006 
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;
2018 
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;
2029 
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;
2040 
2041 	return 0;
2042 }
2043 
2044 int aq_mss_clear_egress_counters(struct aq_hw_s *hw)
2045 {
2046 	return AQ_API_CALL_SAFE(clear_egress_counters, hw);
2047 }
2048 
2049 static int get_ingress_sa_counters(struct aq_hw_s *hw,
2050 				   struct aq_mss_ingress_sa_counters *counters,
2051 				   u16 sa_index)
2052 {
2053 	u16 packed_record[4];
2054 	int ret;
2055 
2056 	if (sa_index >= NUMROWS_INGRESSSARECORD)
2057 		return -EINVAL;
2058 
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);
2067 
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);
2076 
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);
2083 
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);
2090 
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);
2099 
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);
2106 
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);
2113 
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);
2120 
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);
2127 
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);
2136 
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);
2145 
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);
2154 
2155 	return 0;
2156 }
2157 
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)
2161 {
2162 	memset(counters, 0, sizeof(*counters));
2163 
2164 	return AQ_API_CALL_SAFE(get_ingress_sa_counters, hw, counters,
2165 				sa_index);
2166 }
2167 
2168 static int
2169 get_ingress_common_counters(struct aq_hw_s *hw,
2170 			    struct aq_mss_ingress_common_counters *counters)
2171 {
2172 	u16 packed_record[4];
2173 	int ret;
2174 
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);
2180 
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);
2188 
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);
2196 
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);
2202 
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);
2210 
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);
2216 
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);
2222 
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);
2230 
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);
2238 
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);
2246 
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);
2254 
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);
2262 
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);
2270 
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);
2278 
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);
2286 
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);
2294 
2295 	return 0;
2296 }
2297 
2298 int aq_mss_get_ingress_common_counters(struct aq_hw_s *hw,
2299 	struct aq_mss_ingress_common_counters *counters)
2300 {
2301 	memset(counters, 0, sizeof(*counters));
2302 
2303 	return AQ_API_CALL_SAFE(get_ingress_common_counters, hw, counters);
2304 }
2305 
2306 static int clear_ingress_counters(struct aq_hw_s *hw)
2307 {
2308 	struct mss_ingress_ctl_register ctl_reg;
2309 	int ret;
2310 
2311 	memset(&ctl_reg, 0, sizeof(ctl_reg));
2312 
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;
2322 
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;
2334 
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;
2345 
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;
2356 
2357 	return 0;
2358 }
2359 
2360 int aq_mss_clear_ingress_counters(struct aq_hw_s *hw)
2361 {
2362 	return AQ_API_CALL_SAFE(clear_ingress_counters, hw);
2363 }
2364 
2365 static int get_egress_sa_expired(struct aq_hw_s *hw, u32 *expired)
2366 {
2367 	u16 val;
2368 	int ret;
2369 
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;
2375 
2376 	*expired = val;
2377 
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;
2383 
2384 	*expired |= val << 16;
2385 
2386 	return 0;
2387 }
2388 
2389 int aq_mss_get_egress_sa_expired(struct aq_hw_s *hw, u32 *expired)
2390 {
2391 	*expired = 0;
2392 
2393 	return AQ_API_CALL_SAFE(get_egress_sa_expired, hw, expired);
2394 }
2395 
2396 static int get_egress_sa_threshold_expired(struct aq_hw_s *hw,
2397 					   u32 *expired)
2398 {
2399 	u16 val;
2400 	int ret;
2401 
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;
2406 
2407 	*expired = val;
2408 
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;
2413 
2414 	*expired |= val << 16;
2415 
2416 	return 0;
2417 }
2418 
2419 int aq_mss_get_egress_sa_threshold_expired(struct aq_hw_s *hw,
2420 					   u32 *expired)
2421 {
2422 	*expired = 0;
2423 
2424 	return AQ_API_CALL_SAFE(get_egress_sa_threshold_expired, hw, expired);
2425 }
2426 
2427 static int set_egress_sa_expired(struct aq_hw_s *hw, u32 expired)
2428 {
2429 	int ret;
2430 
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;
2436 
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;
2442 
2443 	return 0;
2444 }
2445 
2446 int aq_mss_set_egress_sa_expired(struct aq_hw_s *hw, u32 expired)
2447 {
2448 	return AQ_API_CALL_SAFE(set_egress_sa_expired, hw, expired);
2449 }
2450 
2451 static int set_egress_sa_threshold_expired(struct aq_hw_s *hw, u32 expired)
2452 {
2453 	int ret;
2454 
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;
2460 
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;
2466 
2467 	return 0;
2468 }
2469 
2470 int aq_mss_set_egress_sa_threshold_expired(struct aq_hw_s *hw, u32 expired)
2471 {
2472 	return AQ_API_CALL_SAFE(set_egress_sa_threshold_expired, hw, expired);
2473 }
2474