xref: /linux/drivers/net/ethernet/aquantia/atlantic/macsec/macsec_api.c (revision 8e07e0e3964ca4e23ce7b68e2096fe660a888942)
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 	int ret;
761 
762 	if (table_index >= NUMROWS_INGRESSSAKEYRECORD)
763 		return -EINVAL;
764 
765 	memset(packed_record, 0, sizeof(u16) * 18);
766 
767 	packed_record[0] = rec->key[0] & 0xFFFF;
768 	packed_record[1] = (rec->key[0] >> 16) & 0xFFFF;
769 
770 	packed_record[2] = rec->key[1] & 0xFFFF;
771 	packed_record[3] = (rec->key[1] >> 16) & 0xFFFF;
772 
773 	packed_record[4] = rec->key[2] & 0xFFFF;
774 	packed_record[5] = (rec->key[2] >> 16) & 0xFFFF;
775 
776 	packed_record[6] = rec->key[3] & 0xFFFF;
777 	packed_record[7] = (rec->key[3] >> 16) & 0xFFFF;
778 
779 	packed_record[8] = rec->key[4] & 0xFFFF;
780 	packed_record[9] = (rec->key[4] >> 16) & 0xFFFF;
781 
782 	packed_record[10] = rec->key[5] & 0xFFFF;
783 	packed_record[11] = (rec->key[5] >> 16) & 0xFFFF;
784 
785 	packed_record[12] = rec->key[6] & 0xFFFF;
786 	packed_record[13] = (rec->key[6] >> 16) & 0xFFFF;
787 
788 	packed_record[14] = rec->key[7] & 0xFFFF;
789 	packed_record[15] = (rec->key[7] >> 16) & 0xFFFF;
790 
791 	packed_record[16] = rec->key_len & 0x3;
792 
793 	ret = set_raw_ingress_record(hw, packed_record, 18, 2,
794 				     ROWOFFSET_INGRESSSAKEYRECORD +
795 				     table_index);
796 
797 	memzero_explicit(packed_record, sizeof(packed_record));
798 	return ret;
799 }
800 
801 int aq_mss_set_ingress_sakey_record(struct aq_hw_s *hw,
802 	const struct aq_mss_ingress_sakey_record *rec,
803 	u16 table_index)
804 {
805 	int err = AQ_API_CALL_SAFE(set_ingress_sakey_record, hw, rec,
806 				   table_index);
807 
808 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
809 
810 	return err;
811 }
812 
813 static int get_ingress_sakey_record(struct aq_hw_s *hw,
814 				    struct aq_mss_ingress_sakey_record *rec,
815 				    u16 table_index)
816 {
817 	u16 packed_record[18];
818 	int ret;
819 
820 	if (table_index >= NUMROWS_INGRESSSAKEYRECORD)
821 		return -EINVAL;
822 
823 	ret = get_raw_ingress_record(hw, packed_record, 18, 2,
824 				     ROWOFFSET_INGRESSSAKEYRECORD +
825 					     table_index);
826 	if (unlikely(ret))
827 		return ret;
828 
829 	rec->key[0] = packed_record[0];
830 	rec->key[0] |= packed_record[1] << 16;
831 
832 	rec->key[1] = packed_record[2];
833 	rec->key[1] |= packed_record[3] << 16;
834 
835 	rec->key[2] = packed_record[4];
836 	rec->key[2] |= packed_record[5] << 16;
837 
838 	rec->key[3] = packed_record[6];
839 	rec->key[3] |= packed_record[7] << 16;
840 
841 	rec->key[4] = packed_record[8];
842 	rec->key[4] |= packed_record[9] << 16;
843 
844 	rec->key[5] = packed_record[10];
845 	rec->key[5] |= packed_record[11] << 16;
846 
847 	rec->key[6] = packed_record[12];
848 	rec->key[6] |= packed_record[13] << 16;
849 
850 	rec->key[7] = packed_record[14];
851 	rec->key[7] |= packed_record[15] << 16;
852 
853 	rec->key_len = packed_record[16] & 0x3;
854 
855 	return 0;
856 }
857 
858 int aq_mss_get_ingress_sakey_record(struct aq_hw_s *hw,
859 				    struct aq_mss_ingress_sakey_record *rec,
860 				    u16 table_index)
861 {
862 	memset(rec, 0, sizeof(*rec));
863 
864 	return AQ_API_CALL_SAFE(get_ingress_sakey_record, hw, rec, table_index);
865 }
866 
867 static int
868 set_ingress_postclass_record(struct aq_hw_s *hw,
869 			     const struct aq_mss_ingress_postclass_record *rec,
870 			     u16 table_index)
871 {
872 	u16 packed_record[8];
873 
874 	if (table_index >= NUMROWS_INGRESSPOSTCLASSRECORD)
875 		return -EINVAL;
876 
877 	memset(packed_record, 0, sizeof(u16) * 8);
878 
879 	packed_record[0] = rec->byte0 & 0xFF;
880 
881 	packed_record[0] |= (rec->byte1 & 0xFF) << 8;
882 
883 	packed_record[1] = rec->byte2 & 0xFF;
884 
885 	packed_record[1] |= (rec->byte3 & 0xFF) << 8;
886 
887 	packed_record[2] = rec->eth_type & 0xFFFF;
888 
889 	packed_record[3] = rec->eth_type_valid & 0x1;
890 
891 	packed_record[3] |= (rec->vlan_id & 0xFFF) << 1;
892 
893 	packed_record[3] |= (rec->vlan_up & 0x7) << 13;
894 
895 	packed_record[4] = rec->vlan_valid & 0x1;
896 
897 	packed_record[4] |= (rec->sai & 0x1F) << 1;
898 
899 	packed_record[4] |= (rec->sai_hit & 0x1) << 6;
900 
901 	packed_record[4] |= (rec->eth_type_mask & 0xF) << 7;
902 
903 	packed_record[4] |= (rec->byte3_location & 0x1F) << 11;
904 	packed_record[5] = (rec->byte3_location >> 5) & 0x1;
905 
906 	packed_record[5] |= (rec->byte3_mask & 0x3) << 1;
907 
908 	packed_record[5] |= (rec->byte2_location & 0x3F) << 3;
909 
910 	packed_record[5] |= (rec->byte2_mask & 0x3) << 9;
911 
912 	packed_record[5] |= (rec->byte1_location & 0x1F) << 11;
913 	packed_record[6] = (rec->byte1_location >> 5) & 0x1;
914 
915 	packed_record[6] |= (rec->byte1_mask & 0x3) << 1;
916 
917 	packed_record[6] |= (rec->byte0_location & 0x3F) << 3;
918 
919 	packed_record[6] |= (rec->byte0_mask & 0x3) << 9;
920 
921 	packed_record[6] |= (rec->eth_type_valid_mask & 0x3) << 11;
922 
923 	packed_record[6] |= (rec->vlan_id_mask & 0x7) << 13;
924 	packed_record[7] = (rec->vlan_id_mask >> 3) & 0x1;
925 
926 	packed_record[7] |= (rec->vlan_up_mask & 0x3) << 1;
927 
928 	packed_record[7] |= (rec->vlan_valid_mask & 0x3) << 3;
929 
930 	packed_record[7] |= (rec->sai_mask & 0x3) << 5;
931 
932 	packed_record[7] |= (rec->sai_hit_mask & 0x3) << 7;
933 
934 	packed_record[7] |= (rec->firstlevel_actions & 0x1) << 9;
935 
936 	packed_record[7] |= (rec->secondlevel_actions & 0x1) << 10;
937 
938 	packed_record[7] |= (rec->reserved & 0xF) << 11;
939 
940 	packed_record[7] |= (rec->valid & 0x1) << 15;
941 
942 	return set_raw_ingress_record(hw, packed_record, 8, 4,
943 				      ROWOFFSET_INGRESSPOSTCLASSRECORD +
944 					      table_index);
945 }
946 
947 int aq_mss_set_ingress_postclass_record(struct aq_hw_s *hw,
948 	const struct aq_mss_ingress_postclass_record *rec,
949 	u16 table_index)
950 {
951 	return AQ_API_CALL_SAFE(set_ingress_postclass_record, hw, rec,
952 				table_index);
953 }
954 
955 static int
956 get_ingress_postclass_record(struct aq_hw_s *hw,
957 			     struct aq_mss_ingress_postclass_record *rec,
958 			     u16 table_index)
959 {
960 	u16 packed_record[8];
961 	int ret;
962 
963 	if (table_index >= NUMROWS_INGRESSPOSTCLASSRECORD)
964 		return -EINVAL;
965 
966 	/* If the row that we want to read is odd, first read the previous even
967 	 * row, throw that value away, and finally read the desired row.
968 	 */
969 	if ((table_index % 2) > 0) {
970 		ret = get_raw_ingress_record(hw, packed_record, 8, 4,
971 					     ROWOFFSET_INGRESSPOSTCLASSRECORD +
972 						     table_index - 1);
973 		if (unlikely(ret))
974 			return ret;
975 	}
976 
977 	ret = get_raw_ingress_record(hw, packed_record, 8, 4,
978 				     ROWOFFSET_INGRESSPOSTCLASSRECORD +
979 					     table_index);
980 	if (unlikely(ret))
981 		return ret;
982 
983 	rec->byte0 = packed_record[0] & 0xFF;
984 
985 	rec->byte1 = (packed_record[0] >> 8) & 0xFF;
986 
987 	rec->byte2 = packed_record[1] & 0xFF;
988 
989 	rec->byte3 = (packed_record[1] >> 8) & 0xFF;
990 
991 	rec->eth_type = packed_record[2];
992 
993 	rec->eth_type_valid = packed_record[3] & 0x1;
994 
995 	rec->vlan_id = (packed_record[3] >> 1) & 0xFFF;
996 
997 	rec->vlan_up = (packed_record[3] >> 13) & 0x7;
998 
999 	rec->vlan_valid = packed_record[4] & 0x1;
1000 
1001 	rec->sai = (packed_record[4] >> 1) & 0x1F;
1002 
1003 	rec->sai_hit = (packed_record[4] >> 6) & 0x1;
1004 
1005 	rec->eth_type_mask = (packed_record[4] >> 7) & 0xF;
1006 
1007 	rec->byte3_location = (packed_record[4] >> 11) & 0x1F;
1008 	rec->byte3_location |= (packed_record[5] & 0x1) << 5;
1009 
1010 	rec->byte3_mask = (packed_record[5] >> 1) & 0x3;
1011 
1012 	rec->byte2_location = (packed_record[5] >> 3) & 0x3F;
1013 
1014 	rec->byte2_mask = (packed_record[5] >> 9) & 0x3;
1015 
1016 	rec->byte1_location = (packed_record[5] >> 11) & 0x1F;
1017 	rec->byte1_location |= (packed_record[6] & 0x1) << 5;
1018 
1019 	rec->byte1_mask = (packed_record[6] >> 1) & 0x3;
1020 
1021 	rec->byte0_location = (packed_record[6] >> 3) & 0x3F;
1022 
1023 	rec->byte0_mask = (packed_record[6] >> 9) & 0x3;
1024 
1025 	rec->eth_type_valid_mask = (packed_record[6] >> 11) & 0x3;
1026 
1027 	rec->vlan_id_mask = (packed_record[6] >> 13) & 0x7;
1028 	rec->vlan_id_mask |= (packed_record[7] & 0x1) << 3;
1029 
1030 	rec->vlan_up_mask = (packed_record[7] >> 1) & 0x3;
1031 
1032 	rec->vlan_valid_mask = (packed_record[7] >> 3) & 0x3;
1033 
1034 	rec->sai_mask = (packed_record[7] >> 5) & 0x3;
1035 
1036 	rec->sai_hit_mask = (packed_record[7] >> 7) & 0x3;
1037 
1038 	rec->firstlevel_actions = (packed_record[7] >> 9) & 0x1;
1039 
1040 	rec->secondlevel_actions = (packed_record[7] >> 10) & 0x1;
1041 
1042 	rec->reserved = (packed_record[7] >> 11) & 0xF;
1043 
1044 	rec->valid = (packed_record[7] >> 15) & 0x1;
1045 
1046 	return 0;
1047 }
1048 
1049 int aq_mss_get_ingress_postclass_record(struct aq_hw_s *hw,
1050 	struct aq_mss_ingress_postclass_record *rec,
1051 	u16 table_index)
1052 {
1053 	memset(rec, 0, sizeof(*rec));
1054 
1055 	return AQ_API_CALL_SAFE(get_ingress_postclass_record, hw, rec,
1056 				table_index);
1057 }
1058 
1059 static int
1060 set_ingress_postctlf_record(struct aq_hw_s *hw,
1061 			    const struct aq_mss_ingress_postctlf_record *rec,
1062 			    u16 table_index)
1063 {
1064 	u16 packed_record[6];
1065 
1066 	if (table_index >= NUMROWS_INGRESSPOSTCTLFRECORD)
1067 		return -EINVAL;
1068 
1069 	memset(packed_record, 0, sizeof(u16) * 6);
1070 
1071 	packed_record[0] = rec->sa_da[0] & 0xFFFF;
1072 	packed_record[1] = (rec->sa_da[0] >> 16) & 0xFFFF;
1073 
1074 	packed_record[2] = rec->sa_da[1] & 0xFFFF;
1075 
1076 	packed_record[3] = rec->eth_type & 0xFFFF;
1077 
1078 	packed_record[4] = rec->match_mask & 0xFFFF;
1079 
1080 	packed_record[5] = rec->match_type & 0xF;
1081 
1082 	packed_record[5] |= (rec->action & 0x1) << 4;
1083 
1084 	return set_raw_ingress_record(hw, packed_record, 6, 5,
1085 				      ROWOFFSET_INGRESSPOSTCTLFRECORD +
1086 					      table_index);
1087 }
1088 
1089 int aq_mss_set_ingress_postctlf_record(struct aq_hw_s *hw,
1090 	const struct aq_mss_ingress_postctlf_record *rec,
1091 	u16 table_index)
1092 {
1093 	return AQ_API_CALL_SAFE(set_ingress_postctlf_record, hw, rec,
1094 				table_index);
1095 }
1096 
1097 static int
1098 get_ingress_postctlf_record(struct aq_hw_s *hw,
1099 			    struct aq_mss_ingress_postctlf_record *rec,
1100 			    u16 table_index)
1101 {
1102 	u16 packed_record[6];
1103 	int ret;
1104 
1105 	if (table_index >= NUMROWS_INGRESSPOSTCTLFRECORD)
1106 		return -EINVAL;
1107 
1108 	/* If the row that we want to read is odd, first read the previous even
1109 	 * row, throw that value away, and finally read the desired row.
1110 	 */
1111 	if ((table_index % 2) > 0) {
1112 		ret = get_raw_ingress_record(hw, packed_record, 6, 5,
1113 					     ROWOFFSET_INGRESSPOSTCTLFRECORD +
1114 						     table_index - 1);
1115 		if (unlikely(ret))
1116 			return ret;
1117 	}
1118 
1119 	ret = get_raw_ingress_record(hw, packed_record, 6, 5,
1120 				     ROWOFFSET_INGRESSPOSTCTLFRECORD +
1121 					     table_index);
1122 	if (unlikely(ret))
1123 		return ret;
1124 
1125 	rec->sa_da[0] = packed_record[0];
1126 	rec->sa_da[0] |= packed_record[1] << 16;
1127 
1128 	rec->sa_da[1] = packed_record[2];
1129 
1130 	rec->eth_type = packed_record[3];
1131 
1132 	rec->match_mask = packed_record[4];
1133 
1134 	rec->match_type = packed_record[5] & 0xF;
1135 
1136 	rec->action = (packed_record[5] >> 4) & 0x1;
1137 
1138 	return 0;
1139 }
1140 
1141 int aq_mss_get_ingress_postctlf_record(struct aq_hw_s *hw,
1142 	struct aq_mss_ingress_postctlf_record *rec,
1143 	u16 table_index)
1144 {
1145 	memset(rec, 0, sizeof(*rec));
1146 
1147 	return AQ_API_CALL_SAFE(get_ingress_postctlf_record, hw, rec,
1148 				table_index);
1149 }
1150 
1151 static int set_egress_ctlf_record(struct aq_hw_s *hw,
1152 				  const struct aq_mss_egress_ctlf_record *rec,
1153 				  u16 table_index)
1154 {
1155 	u16 packed_record[6];
1156 
1157 	if (table_index >= NUMROWS_EGRESSCTLFRECORD)
1158 		return -EINVAL;
1159 
1160 	memset(packed_record, 0, sizeof(u16) * 6);
1161 
1162 	packed_record[0] = rec->sa_da[0] & 0xFFFF;
1163 	packed_record[1] = (rec->sa_da[0] >> 16) & 0xFFFF;
1164 
1165 	packed_record[2] = rec->sa_da[1] & 0xFFFF;
1166 
1167 	packed_record[3] = rec->eth_type & 0xFFFF;
1168 
1169 	packed_record[4] = rec->match_mask & 0xFFFF;
1170 
1171 	packed_record[5] = rec->match_type & 0xF;
1172 
1173 	packed_record[5] |= (rec->action & 0x1) << 4;
1174 
1175 	return set_raw_egress_record(hw, packed_record, 6, 0,
1176 				     ROWOFFSET_EGRESSCTLFRECORD + table_index);
1177 }
1178 
1179 int aq_mss_set_egress_ctlf_record(struct aq_hw_s *hw,
1180 				  const struct aq_mss_egress_ctlf_record *rec,
1181 				  u16 table_index)
1182 {
1183 	return AQ_API_CALL_SAFE(set_egress_ctlf_record, hw, rec, table_index);
1184 }
1185 
1186 static int get_egress_ctlf_record(struct aq_hw_s *hw,
1187 				  struct aq_mss_egress_ctlf_record *rec,
1188 				  u16 table_index)
1189 {
1190 	u16 packed_record[6];
1191 	int ret;
1192 
1193 	if (table_index >= NUMROWS_EGRESSCTLFRECORD)
1194 		return -EINVAL;
1195 
1196 	/* If the row that we want to read is odd, first read the previous even
1197 	 * row, throw that value away, and finally read the desired row.
1198 	 */
1199 	if ((table_index % 2) > 0) {
1200 		ret = get_raw_egress_record(hw, packed_record, 6, 0,
1201 					    ROWOFFSET_EGRESSCTLFRECORD +
1202 						    table_index - 1);
1203 		if (unlikely(ret))
1204 			return ret;
1205 	}
1206 
1207 	ret = get_raw_egress_record(hw, packed_record, 6, 0,
1208 				    ROWOFFSET_EGRESSCTLFRECORD + table_index);
1209 	if (unlikely(ret))
1210 		return ret;
1211 
1212 	rec->sa_da[0] = packed_record[0];
1213 	rec->sa_da[0] |= packed_record[1] << 16;
1214 
1215 	rec->sa_da[1] = packed_record[2];
1216 
1217 	rec->eth_type = packed_record[3];
1218 
1219 	rec->match_mask = packed_record[4];
1220 
1221 	rec->match_type = packed_record[5] & 0xF;
1222 
1223 	rec->action = (packed_record[5] >> 4) & 0x1;
1224 
1225 	return 0;
1226 }
1227 
1228 int aq_mss_get_egress_ctlf_record(struct aq_hw_s *hw,
1229 				  struct aq_mss_egress_ctlf_record *rec,
1230 				  u16 table_index)
1231 {
1232 	memset(rec, 0, sizeof(*rec));
1233 
1234 	return AQ_API_CALL_SAFE(get_egress_ctlf_record, hw, rec, table_index);
1235 }
1236 
1237 static int set_egress_class_record(struct aq_hw_s *hw,
1238 				   const struct aq_mss_egress_class_record *rec,
1239 				   u16 table_index)
1240 {
1241 	u16 packed_record[28];
1242 
1243 	if (table_index >= NUMROWS_EGRESSCLASSRECORD)
1244 		return -EINVAL;
1245 
1246 	memset(packed_record, 0, sizeof(u16) * 28);
1247 
1248 	packed_record[0] = rec->vlan_id & 0xFFF;
1249 
1250 	packed_record[0] |= (rec->vlan_up & 0x7) << 12;
1251 
1252 	packed_record[0] |= (rec->vlan_valid & 0x1) << 15;
1253 
1254 	packed_record[1] = rec->byte3 & 0xFF;
1255 
1256 	packed_record[1] |= (rec->byte2 & 0xFF) << 8;
1257 
1258 	packed_record[2] = rec->byte1 & 0xFF;
1259 
1260 	packed_record[2] |= (rec->byte0 & 0xFF) << 8;
1261 
1262 	packed_record[3] = rec->tci & 0xFF;
1263 
1264 	packed_record[3] |= (rec->sci[0] & 0xFF) << 8;
1265 	packed_record[4] = (rec->sci[0] >> 8) & 0xFFFF;
1266 	packed_record[5] = (rec->sci[0] >> 24) & 0xFF;
1267 
1268 	packed_record[5] |= (rec->sci[1] & 0xFF) << 8;
1269 	packed_record[6] = (rec->sci[1] >> 8) & 0xFFFF;
1270 	packed_record[7] = (rec->sci[1] >> 24) & 0xFF;
1271 
1272 	packed_record[7] |= (rec->eth_type & 0xFF) << 8;
1273 	packed_record[8] = (rec->eth_type >> 8) & 0xFF;
1274 
1275 	packed_record[8] |= (rec->snap[0] & 0xFF) << 8;
1276 	packed_record[9] = (rec->snap[0] >> 8) & 0xFFFF;
1277 	packed_record[10] = (rec->snap[0] >> 24) & 0xFF;
1278 
1279 	packed_record[10] |= (rec->snap[1] & 0xFF) << 8;
1280 
1281 	packed_record[11] = rec->llc & 0xFFFF;
1282 	packed_record[12] = (rec->llc >> 16) & 0xFF;
1283 
1284 	packed_record[12] |= (rec->mac_sa[0] & 0xFF) << 8;
1285 	packed_record[13] = (rec->mac_sa[0] >> 8) & 0xFFFF;
1286 	packed_record[14] = (rec->mac_sa[0] >> 24) & 0xFF;
1287 
1288 	packed_record[14] |= (rec->mac_sa[1] & 0xFF) << 8;
1289 	packed_record[15] = (rec->mac_sa[1] >> 8) & 0xFF;
1290 
1291 	packed_record[15] |= (rec->mac_da[0] & 0xFF) << 8;
1292 	packed_record[16] = (rec->mac_da[0] >> 8) & 0xFFFF;
1293 	packed_record[17] = (rec->mac_da[0] >> 24) & 0xFF;
1294 
1295 	packed_record[17] |= (rec->mac_da[1] & 0xFF) << 8;
1296 	packed_record[18] = (rec->mac_da[1] >> 8) & 0xFF;
1297 
1298 	packed_record[18] |= (rec->pn & 0xFF) << 8;
1299 	packed_record[19] = (rec->pn >> 8) & 0xFFFF;
1300 	packed_record[20] = (rec->pn >> 24) & 0xFF;
1301 
1302 	packed_record[20] |= (rec->byte3_location & 0x3F) << 8;
1303 
1304 	packed_record[20] |= (rec->byte3_mask & 0x1) << 14;
1305 
1306 	packed_record[20] |= (rec->byte2_location & 0x1) << 15;
1307 	packed_record[21] = (rec->byte2_location >> 1) & 0x1F;
1308 
1309 	packed_record[21] |= (rec->byte2_mask & 0x1) << 5;
1310 
1311 	packed_record[21] |= (rec->byte1_location & 0x3F) << 6;
1312 
1313 	packed_record[21] |= (rec->byte1_mask & 0x1) << 12;
1314 
1315 	packed_record[21] |= (rec->byte0_location & 0x7) << 13;
1316 	packed_record[22] = (rec->byte0_location >> 3) & 0x7;
1317 
1318 	packed_record[22] |= (rec->byte0_mask & 0x1) << 3;
1319 
1320 	packed_record[22] |= (rec->vlan_id_mask & 0x3) << 4;
1321 
1322 	packed_record[22] |= (rec->vlan_up_mask & 0x1) << 6;
1323 
1324 	packed_record[22] |= (rec->vlan_valid_mask & 0x1) << 7;
1325 
1326 	packed_record[22] |= (rec->tci_mask & 0xFF) << 8;
1327 
1328 	packed_record[23] = rec->sci_mask & 0xFF;
1329 
1330 	packed_record[23] |= (rec->eth_type_mask & 0x3) << 8;
1331 
1332 	packed_record[23] |= (rec->snap_mask & 0x1F) << 10;
1333 
1334 	packed_record[23] |= (rec->llc_mask & 0x1) << 15;
1335 	packed_record[24] = (rec->llc_mask >> 1) & 0x3;
1336 
1337 	packed_record[24] |= (rec->sa_mask & 0x3F) << 2;
1338 
1339 	packed_record[24] |= (rec->da_mask & 0x3F) << 8;
1340 
1341 	packed_record[24] |= (rec->pn_mask & 0x3) << 14;
1342 	packed_record[25] = (rec->pn_mask >> 2) & 0x3;
1343 
1344 	packed_record[25] |= (rec->eight02dot2 & 0x1) << 2;
1345 
1346 	packed_record[25] |= (rec->tci_sc & 0x1) << 3;
1347 
1348 	packed_record[25] |= (rec->tci_87543 & 0x1) << 4;
1349 
1350 	packed_record[25] |= (rec->exp_sectag_en & 0x1) << 5;
1351 
1352 	packed_record[25] |= (rec->sc_idx & 0x1F) << 6;
1353 
1354 	packed_record[25] |= (rec->sc_sa & 0x3) << 11;
1355 
1356 	packed_record[25] |= (rec->debug & 0x1) << 13;
1357 
1358 	packed_record[25] |= (rec->action & 0x3) << 14;
1359 
1360 	packed_record[26] = (rec->valid & 0x1) << 3;
1361 
1362 	return set_raw_egress_record(hw, packed_record, 28, 1,
1363 				     ROWOFFSET_EGRESSCLASSRECORD + table_index);
1364 }
1365 
1366 int aq_mss_set_egress_class_record(struct aq_hw_s *hw,
1367 				   const struct aq_mss_egress_class_record *rec,
1368 				   u16 table_index)
1369 {
1370 	return AQ_API_CALL_SAFE(set_egress_class_record, hw, rec, table_index);
1371 }
1372 
1373 static int get_egress_class_record(struct aq_hw_s *hw,
1374 				   struct aq_mss_egress_class_record *rec,
1375 				   u16 table_index)
1376 {
1377 	u16 packed_record[28];
1378 	int ret;
1379 
1380 	if (table_index >= NUMROWS_EGRESSCLASSRECORD)
1381 		return -EINVAL;
1382 
1383 	/* If the row that we want to read is odd, first read the previous even
1384 	 * row, throw that value away, and finally read the desired row.
1385 	 */
1386 	if ((table_index % 2) > 0) {
1387 		ret = get_raw_egress_record(hw, packed_record, 28, 1,
1388 					    ROWOFFSET_EGRESSCLASSRECORD +
1389 						    table_index - 1);
1390 		if (unlikely(ret))
1391 			return ret;
1392 	}
1393 
1394 	ret = get_raw_egress_record(hw, packed_record, 28, 1,
1395 				    ROWOFFSET_EGRESSCLASSRECORD + table_index);
1396 	if (unlikely(ret))
1397 		return ret;
1398 
1399 	rec->vlan_id = packed_record[0] & 0xFFF;
1400 
1401 	rec->vlan_up = (packed_record[0] >> 12) & 0x7;
1402 
1403 	rec->vlan_valid = (packed_record[0] >> 15) & 0x1;
1404 
1405 	rec->byte3 = packed_record[1] & 0xFF;
1406 
1407 	rec->byte2 = (packed_record[1] >> 8) & 0xFF;
1408 
1409 	rec->byte1 = packed_record[2] & 0xFF;
1410 
1411 	rec->byte0 = (packed_record[2] >> 8) & 0xFF;
1412 
1413 	rec->tci = packed_record[3] & 0xFF;
1414 
1415 	rec->sci[0] = (packed_record[3] >> 8) & 0xFF;
1416 	rec->sci[0] |= packed_record[4] << 8;
1417 	rec->sci[0] |= (packed_record[5] & 0xFF) << 24;
1418 
1419 	rec->sci[1] = (packed_record[5] >> 8) & 0xFF;
1420 	rec->sci[1] |= packed_record[6] << 8;
1421 	rec->sci[1] |= (packed_record[7] & 0xFF) << 24;
1422 
1423 	rec->eth_type = (packed_record[7] >> 8) & 0xFF;
1424 	rec->eth_type |= (packed_record[8] & 0xFF) << 8;
1425 
1426 	rec->snap[0] = (packed_record[8] >> 8) & 0xFF;
1427 	rec->snap[0] |= packed_record[9] << 8;
1428 	rec->snap[0] |= (packed_record[10] & 0xFF) << 24;
1429 
1430 	rec->snap[1] = (packed_record[10] >> 8) & 0xFF;
1431 
1432 	rec->llc = packed_record[11];
1433 	rec->llc |= (packed_record[12] & 0xFF) << 16;
1434 
1435 	rec->mac_sa[0] = (packed_record[12] >> 8) & 0xFF;
1436 	rec->mac_sa[0] |= packed_record[13] << 8;
1437 	rec->mac_sa[0] |= (packed_record[14] & 0xFF) << 24;
1438 
1439 	rec->mac_sa[1] = (packed_record[14] >> 8) & 0xFF;
1440 	rec->mac_sa[1] |= (packed_record[15] & 0xFF) << 8;
1441 
1442 	rec->mac_da[0] = (packed_record[15] >> 8) & 0xFF;
1443 	rec->mac_da[0] |= packed_record[16] << 8;
1444 	rec->mac_da[0] |= (packed_record[17] & 0xFF) << 24;
1445 
1446 	rec->mac_da[1] = (packed_record[17] >> 8) & 0xFF;
1447 	rec->mac_da[1] |= (packed_record[18] & 0xFF) << 8;
1448 
1449 	rec->pn = (packed_record[18] >> 8) & 0xFF;
1450 	rec->pn |= packed_record[19] << 8;
1451 	rec->pn |= (packed_record[20] & 0xFF) << 24;
1452 
1453 	rec->byte3_location = (packed_record[20] >> 8) & 0x3F;
1454 
1455 	rec->byte3_mask = (packed_record[20] >> 14) & 0x1;
1456 
1457 	rec->byte2_location = (packed_record[20] >> 15) & 0x1;
1458 	rec->byte2_location |= (packed_record[21] & 0x1F) << 1;
1459 
1460 	rec->byte2_mask = (packed_record[21] >> 5) & 0x1;
1461 
1462 	rec->byte1_location = (packed_record[21] >> 6) & 0x3F;
1463 
1464 	rec->byte1_mask = (packed_record[21] >> 12) & 0x1;
1465 
1466 	rec->byte0_location = (packed_record[21] >> 13) & 0x7;
1467 	rec->byte0_location |= (packed_record[22] & 0x7) << 3;
1468 
1469 	rec->byte0_mask = (packed_record[22] >> 3) & 0x1;
1470 
1471 	rec->vlan_id_mask = (packed_record[22] >> 4) & 0x3;
1472 
1473 	rec->vlan_up_mask = (packed_record[22] >> 6) & 0x1;
1474 
1475 	rec->vlan_valid_mask = (packed_record[22] >> 7) & 0x1;
1476 
1477 	rec->tci_mask = (packed_record[22] >> 8) & 0xFF;
1478 
1479 	rec->sci_mask = packed_record[23] & 0xFF;
1480 
1481 	rec->eth_type_mask = (packed_record[23] >> 8) & 0x3;
1482 
1483 	rec->snap_mask = (packed_record[23] >> 10) & 0x1F;
1484 
1485 	rec->llc_mask = (packed_record[23] >> 15) & 0x1;
1486 	rec->llc_mask |= (packed_record[24] & 0x3) << 1;
1487 
1488 	rec->sa_mask = (packed_record[24] >> 2) & 0x3F;
1489 
1490 	rec->da_mask = (packed_record[24] >> 8) & 0x3F;
1491 
1492 	rec->pn_mask = (packed_record[24] >> 14) & 0x3;
1493 	rec->pn_mask |= (packed_record[25] & 0x3) << 2;
1494 
1495 	rec->eight02dot2 = (packed_record[25] >> 2) & 0x1;
1496 
1497 	rec->tci_sc = (packed_record[25] >> 3) & 0x1;
1498 
1499 	rec->tci_87543 = (packed_record[25] >> 4) & 0x1;
1500 
1501 	rec->exp_sectag_en = (packed_record[25] >> 5) & 0x1;
1502 
1503 	rec->sc_idx = (packed_record[25] >> 6) & 0x1F;
1504 
1505 	rec->sc_sa = (packed_record[25] >> 11) & 0x3;
1506 
1507 	rec->debug = (packed_record[25] >> 13) & 0x1;
1508 
1509 	rec->action = (packed_record[25] >> 14) & 0x3;
1510 
1511 	rec->valid = (packed_record[26] >> 3) & 0x1;
1512 
1513 	return 0;
1514 }
1515 
1516 int aq_mss_get_egress_class_record(struct aq_hw_s *hw,
1517 				   struct aq_mss_egress_class_record *rec,
1518 				   u16 table_index)
1519 {
1520 	memset(rec, 0, sizeof(*rec));
1521 
1522 	return AQ_API_CALL_SAFE(get_egress_class_record, hw, rec, table_index);
1523 }
1524 
1525 static int set_egress_sc_record(struct aq_hw_s *hw,
1526 				const struct aq_mss_egress_sc_record *rec,
1527 				u16 table_index)
1528 {
1529 	u16 packed_record[8];
1530 
1531 	if (table_index >= NUMROWS_EGRESSSCRECORD)
1532 		return -EINVAL;
1533 
1534 	memset(packed_record, 0, sizeof(u16) * 8);
1535 
1536 	packed_record[0] = rec->start_time & 0xFFFF;
1537 	packed_record[1] = (rec->start_time >> 16) & 0xFFFF;
1538 
1539 	packed_record[2] = rec->stop_time & 0xFFFF;
1540 	packed_record[3] = (rec->stop_time >> 16) & 0xFFFF;
1541 
1542 	packed_record[4] = rec->curr_an & 0x3;
1543 
1544 	packed_record[4] |= (rec->an_roll & 0x1) << 2;
1545 
1546 	packed_record[4] |= (rec->tci & 0x3F) << 3;
1547 
1548 	packed_record[4] |= (rec->enc_off & 0x7F) << 9;
1549 	packed_record[5] = (rec->enc_off >> 7) & 0x1;
1550 
1551 	packed_record[5] |= (rec->protect & 0x1) << 1;
1552 
1553 	packed_record[5] |= (rec->recv & 0x1) << 2;
1554 
1555 	packed_record[5] |= (rec->fresh & 0x1) << 3;
1556 
1557 	packed_record[5] |= (rec->sak_len & 0x3) << 4;
1558 
1559 	packed_record[7] = (rec->valid & 0x1) << 15;
1560 
1561 	return set_raw_egress_record(hw, packed_record, 8, 2,
1562 				     ROWOFFSET_EGRESSSCRECORD + table_index);
1563 }
1564 
1565 int aq_mss_set_egress_sc_record(struct aq_hw_s *hw,
1566 				const struct aq_mss_egress_sc_record *rec,
1567 				u16 table_index)
1568 {
1569 	return AQ_API_CALL_SAFE(set_egress_sc_record, hw, rec, table_index);
1570 }
1571 
1572 static int get_egress_sc_record(struct aq_hw_s *hw,
1573 				struct aq_mss_egress_sc_record *rec,
1574 				u16 table_index)
1575 {
1576 	u16 packed_record[8];
1577 	int ret;
1578 
1579 	if (table_index >= NUMROWS_EGRESSSCRECORD)
1580 		return -EINVAL;
1581 
1582 	ret = get_raw_egress_record(hw, packed_record, 8, 2,
1583 				    ROWOFFSET_EGRESSSCRECORD + table_index);
1584 	if (unlikely(ret))
1585 		return ret;
1586 
1587 	rec->start_time = packed_record[0];
1588 	rec->start_time |= packed_record[1] << 16;
1589 
1590 	rec->stop_time = packed_record[2];
1591 	rec->stop_time |= packed_record[3] << 16;
1592 
1593 	rec->curr_an = packed_record[4] & 0x3;
1594 
1595 	rec->an_roll = (packed_record[4] >> 2) & 0x1;
1596 
1597 	rec->tci = (packed_record[4] >> 3) & 0x3F;
1598 
1599 	rec->enc_off = (packed_record[4] >> 9) & 0x7F;
1600 	rec->enc_off |= (packed_record[5] & 0x1) << 7;
1601 
1602 	rec->protect = (packed_record[5] >> 1) & 0x1;
1603 
1604 	rec->recv = (packed_record[5] >> 2) & 0x1;
1605 
1606 	rec->fresh = (packed_record[5] >> 3) & 0x1;
1607 
1608 	rec->sak_len = (packed_record[5] >> 4) & 0x3;
1609 
1610 	rec->valid = (packed_record[7] >> 15) & 0x1;
1611 
1612 	return 0;
1613 }
1614 
1615 int aq_mss_get_egress_sc_record(struct aq_hw_s *hw,
1616 				struct aq_mss_egress_sc_record *rec,
1617 				u16 table_index)
1618 {
1619 	memset(rec, 0, sizeof(*rec));
1620 
1621 	return AQ_API_CALL_SAFE(get_egress_sc_record, hw, rec, table_index);
1622 }
1623 
1624 static int set_egress_sa_record(struct aq_hw_s *hw,
1625 				const struct aq_mss_egress_sa_record *rec,
1626 				u16 table_index)
1627 {
1628 	u16 packed_record[8];
1629 
1630 	if (table_index >= NUMROWS_EGRESSSARECORD)
1631 		return -EINVAL;
1632 
1633 	memset(packed_record, 0, sizeof(u16) * 8);
1634 
1635 	packed_record[0] = rec->start_time & 0xFFFF;
1636 	packed_record[1] = (rec->start_time >> 16) & 0xFFFF;
1637 
1638 	packed_record[2] = rec->stop_time & 0xFFFF;
1639 	packed_record[3] = (rec->stop_time >> 16) & 0xFFFF;
1640 
1641 	packed_record[4] = rec->next_pn & 0xFFFF;
1642 	packed_record[5] = (rec->next_pn >> 16) & 0xFFFF;
1643 
1644 	packed_record[6] = rec->sat_pn & 0x1;
1645 
1646 	packed_record[6] |= (rec->fresh & 0x1) << 1;
1647 
1648 	packed_record[7] = (rec->valid & 0x1) << 15;
1649 
1650 	return set_raw_egress_record(hw, packed_record, 8, 2,
1651 				     ROWOFFSET_EGRESSSARECORD + table_index);
1652 }
1653 
1654 int aq_mss_set_egress_sa_record(struct aq_hw_s *hw,
1655 				const struct aq_mss_egress_sa_record *rec,
1656 				u16 table_index)
1657 {
1658 	int err = AQ_API_CALL_SAFE(set_egress_sa_record, hw, rec, table_index);
1659 
1660 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
1661 
1662 	return err;
1663 }
1664 
1665 static int get_egress_sa_record(struct aq_hw_s *hw,
1666 				struct aq_mss_egress_sa_record *rec,
1667 				u16 table_index)
1668 {
1669 	u16 packed_record[8];
1670 	int ret;
1671 
1672 	if (table_index >= NUMROWS_EGRESSSARECORD)
1673 		return -EINVAL;
1674 
1675 	ret = get_raw_egress_record(hw, packed_record, 8, 2,
1676 				    ROWOFFSET_EGRESSSARECORD + table_index);
1677 	if (unlikely(ret))
1678 		return ret;
1679 
1680 	rec->start_time = packed_record[0];
1681 	rec->start_time |= packed_record[1] << 16;
1682 
1683 	rec->stop_time = packed_record[2];
1684 	rec->stop_time |= packed_record[3] << 16;
1685 
1686 	rec->next_pn = packed_record[4];
1687 	rec->next_pn |= packed_record[5] << 16;
1688 
1689 	rec->sat_pn = packed_record[6] & 0x1;
1690 
1691 	rec->fresh = (packed_record[6] >> 1) & 0x1;
1692 
1693 	rec->valid = (packed_record[7] >> 15) & 0x1;
1694 
1695 	return 0;
1696 }
1697 
1698 int aq_mss_get_egress_sa_record(struct aq_hw_s *hw,
1699 				struct aq_mss_egress_sa_record *rec,
1700 				u16 table_index)
1701 {
1702 	memset(rec, 0, sizeof(*rec));
1703 
1704 	return AQ_API_CALL_SAFE(get_egress_sa_record, hw, rec, table_index);
1705 }
1706 
1707 static int set_egress_sakey_record(struct aq_hw_s *hw,
1708 				   const struct aq_mss_egress_sakey_record *rec,
1709 				   u16 table_index)
1710 {
1711 	u16 packed_record[16];
1712 	int ret;
1713 
1714 	if (table_index >= NUMROWS_EGRESSSAKEYRECORD)
1715 		return -EINVAL;
1716 
1717 	memset(packed_record, 0, sizeof(u16) * 16);
1718 
1719 	packed_record[0] = rec->key[0] & 0xFFFF;
1720 	packed_record[1] = (rec->key[0] >> 16) & 0xFFFF;
1721 
1722 	packed_record[2] = rec->key[1] & 0xFFFF;
1723 	packed_record[3] = (rec->key[1] >> 16) & 0xFFFF;
1724 
1725 	packed_record[4] = rec->key[2] & 0xFFFF;
1726 	packed_record[5] = (rec->key[2] >> 16) & 0xFFFF;
1727 
1728 	packed_record[6] = rec->key[3] & 0xFFFF;
1729 	packed_record[7] = (rec->key[3] >> 16) & 0xFFFF;
1730 
1731 	packed_record[8] = rec->key[4] & 0xFFFF;
1732 	packed_record[9] = (rec->key[4] >> 16) & 0xFFFF;
1733 
1734 	packed_record[10] = rec->key[5] & 0xFFFF;
1735 	packed_record[11] = (rec->key[5] >> 16) & 0xFFFF;
1736 
1737 	packed_record[12] = rec->key[6] & 0xFFFF;
1738 	packed_record[13] = (rec->key[6] >> 16) & 0xFFFF;
1739 
1740 	packed_record[14] = rec->key[7] & 0xFFFF;
1741 	packed_record[15] = (rec->key[7] >> 16) & 0xFFFF;
1742 
1743 	ret = set_raw_egress_record(hw, packed_record, 8, 2,
1744 				    ROWOFFSET_EGRESSSAKEYRECORD + table_index);
1745 	if (unlikely(ret))
1746 		goto clear_key;
1747 	ret = set_raw_egress_record(hw, packed_record + 8, 8, 2,
1748 				    ROWOFFSET_EGRESSSAKEYRECORD + table_index -
1749 					    32);
1750 
1751 clear_key:
1752 	memzero_explicit(packed_record, sizeof(packed_record));
1753 	return ret;
1754 }
1755 
1756 int aq_mss_set_egress_sakey_record(struct aq_hw_s *hw,
1757 				   const struct aq_mss_egress_sakey_record *rec,
1758 				   u16 table_index)
1759 {
1760 	int err = AQ_API_CALL_SAFE(set_egress_sakey_record, hw, rec,
1761 				   table_index);
1762 
1763 	WARN_ONCE(err, "%s failed with %d\n", __func__, err);
1764 
1765 	return err;
1766 }
1767 
1768 static int get_egress_sakey_record(struct aq_hw_s *hw,
1769 				   struct aq_mss_egress_sakey_record *rec,
1770 				   u16 table_index)
1771 {
1772 	u16 packed_record[16];
1773 	int ret;
1774 
1775 	if (table_index >= NUMROWS_EGRESSSAKEYRECORD)
1776 		return -EINVAL;
1777 
1778 	ret = get_raw_egress_record(hw, packed_record, 8, 2,
1779 				    ROWOFFSET_EGRESSSAKEYRECORD + table_index);
1780 	if (unlikely(ret))
1781 		return ret;
1782 	ret = get_raw_egress_record(hw, packed_record + 8, 8, 2,
1783 				    ROWOFFSET_EGRESSSAKEYRECORD + table_index -
1784 					    32);
1785 	if (unlikely(ret))
1786 		return ret;
1787 
1788 	rec->key[0] = packed_record[0];
1789 	rec->key[0] |= packed_record[1] << 16;
1790 
1791 	rec->key[1] = packed_record[2];
1792 	rec->key[1] |= packed_record[3] << 16;
1793 
1794 	rec->key[2] = packed_record[4];
1795 	rec->key[2] |= packed_record[5] << 16;
1796 
1797 	rec->key[3] = packed_record[6];
1798 	rec->key[3] |= packed_record[7] << 16;
1799 
1800 	rec->key[4] = packed_record[8];
1801 	rec->key[4] |= packed_record[9] << 16;
1802 
1803 	rec->key[5] = packed_record[10];
1804 	rec->key[5] |= packed_record[11] << 16;
1805 
1806 	rec->key[6] = packed_record[12];
1807 	rec->key[6] |= packed_record[13] << 16;
1808 
1809 	rec->key[7] = packed_record[14];
1810 	rec->key[7] |= packed_record[15] << 16;
1811 
1812 	return 0;
1813 }
1814 
1815 int aq_mss_get_egress_sakey_record(struct aq_hw_s *hw,
1816 				   struct aq_mss_egress_sakey_record *rec,
1817 				   u16 table_index)
1818 {
1819 	memset(rec, 0, sizeof(*rec));
1820 
1821 	return AQ_API_CALL_SAFE(get_egress_sakey_record, hw, rec, table_index);
1822 }
1823 
1824 static int get_egress_sc_counters(struct aq_hw_s *hw,
1825 				  struct aq_mss_egress_sc_counters *counters,
1826 				  u16 sc_index)
1827 {
1828 	u16 packed_record[4];
1829 	int ret;
1830 
1831 	if (sc_index >= NUMROWS_EGRESSSCRECORD)
1832 		return -EINVAL;
1833 
1834 	ret = get_raw_egress_record(hw, packed_record, 4, 3, sc_index * 8 + 4);
1835 	if (unlikely(ret))
1836 		return ret;
1837 	counters->sc_protected_pkts[0] =
1838 		packed_record[0] | (packed_record[1] << 16);
1839 	counters->sc_protected_pkts[1] =
1840 		packed_record[2] | (packed_record[3] << 16);
1841 
1842 	ret = get_raw_egress_record(hw, packed_record, 4, 3, sc_index * 8 + 5);
1843 	if (unlikely(ret))
1844 		return ret;
1845 	counters->sc_encrypted_pkts[0] =
1846 		packed_record[0] | (packed_record[1] << 16);
1847 	counters->sc_encrypted_pkts[1] =
1848 		packed_record[2] | (packed_record[3] << 16);
1849 
1850 	ret = get_raw_egress_record(hw, packed_record, 4, 3, sc_index * 8 + 6);
1851 	if (unlikely(ret))
1852 		return ret;
1853 	counters->sc_protected_octets[0] =
1854 		packed_record[0] | (packed_record[1] << 16);
1855 	counters->sc_protected_octets[1] =
1856 		packed_record[2] | (packed_record[3] << 16);
1857 
1858 	ret = get_raw_egress_record(hw, packed_record, 4, 3, sc_index * 8 + 7);
1859 	if (unlikely(ret))
1860 		return ret;
1861 	counters->sc_encrypted_octets[0] =
1862 		packed_record[0] | (packed_record[1] << 16);
1863 	counters->sc_encrypted_octets[1] =
1864 		packed_record[2] | (packed_record[3] << 16);
1865 
1866 	return 0;
1867 }
1868 
1869 int aq_mss_get_egress_sc_counters(struct aq_hw_s *hw,
1870 				  struct aq_mss_egress_sc_counters *counters,
1871 				  u16 sc_index)
1872 {
1873 	memset(counters, 0, sizeof(*counters));
1874 
1875 	return AQ_API_CALL_SAFE(get_egress_sc_counters, hw, counters, sc_index);
1876 }
1877 
1878 static int get_egress_sa_counters(struct aq_hw_s *hw,
1879 				  struct aq_mss_egress_sa_counters *counters,
1880 				  u16 sa_index)
1881 {
1882 	u16 packed_record[4];
1883 	int ret;
1884 
1885 	if (sa_index >= NUMROWS_EGRESSSARECORD)
1886 		return -EINVAL;
1887 
1888 	ret = get_raw_egress_record(hw, packed_record, 4, 3, sa_index * 8 + 0);
1889 	if (unlikely(ret))
1890 		return ret;
1891 	counters->sa_hit_drop_redirect[0] =
1892 		packed_record[0] | (packed_record[1] << 16);
1893 	counters->sa_hit_drop_redirect[1] =
1894 		packed_record[2] | (packed_record[3] << 16);
1895 
1896 	ret = get_raw_egress_record(hw, packed_record, 4, 3, sa_index * 8 + 1);
1897 	if (unlikely(ret))
1898 		return ret;
1899 	counters->sa_protected2_pkts[0] =
1900 		packed_record[0] | (packed_record[1] << 16);
1901 	counters->sa_protected2_pkts[1] =
1902 		packed_record[2] | (packed_record[3] << 16);
1903 
1904 	ret = get_raw_egress_record(hw, packed_record, 4, 3, sa_index * 8 + 2);
1905 	if (unlikely(ret))
1906 		return ret;
1907 	counters->sa_protected_pkts[0] =
1908 		packed_record[0] | (packed_record[1] << 16);
1909 	counters->sa_protected_pkts[1] =
1910 		packed_record[2] | (packed_record[3] << 16);
1911 
1912 	ret = get_raw_egress_record(hw, packed_record, 4, 3, sa_index * 8 + 3);
1913 	if (unlikely(ret))
1914 		return ret;
1915 	counters->sa_encrypted_pkts[0] =
1916 		packed_record[0] | (packed_record[1] << 16);
1917 	counters->sa_encrypted_pkts[1] =
1918 		packed_record[2] | (packed_record[3] << 16);
1919 
1920 	return 0;
1921 }
1922 
1923 int aq_mss_get_egress_sa_counters(struct aq_hw_s *hw,
1924 				  struct aq_mss_egress_sa_counters *counters,
1925 				  u16 sa_index)
1926 {
1927 	memset(counters, 0, sizeof(*counters));
1928 
1929 	return AQ_API_CALL_SAFE(get_egress_sa_counters, hw, counters, sa_index);
1930 }
1931 
1932 static int
1933 get_egress_common_counters(struct aq_hw_s *hw,
1934 			   struct aq_mss_egress_common_counters *counters)
1935 {
1936 	u16 packed_record[4];
1937 	int ret;
1938 
1939 	ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 0);
1940 	if (unlikely(ret))
1941 		return ret;
1942 	counters->ctl_pkt[0] = packed_record[0] | (packed_record[1] << 16);
1943 	counters->ctl_pkt[1] = packed_record[2] | (packed_record[3] << 16);
1944 
1945 	ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 1);
1946 	if (unlikely(ret))
1947 		return ret;
1948 	counters->unknown_sa_pkts[0] =
1949 		packed_record[0] | (packed_record[1] << 16);
1950 	counters->unknown_sa_pkts[1] =
1951 		packed_record[2] | (packed_record[3] << 16);
1952 
1953 	ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 2);
1954 	if (unlikely(ret))
1955 		return ret;
1956 	counters->untagged_pkts[0] =
1957 		packed_record[0] | (packed_record[1] << 16);
1958 	counters->untagged_pkts[1] =
1959 		packed_record[2] | (packed_record[3] << 16);
1960 
1961 	ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 3);
1962 	if (unlikely(ret))
1963 		return ret;
1964 	counters->too_long[0] = packed_record[0] | (packed_record[1] << 16);
1965 	counters->too_long[1] = packed_record[2] | (packed_record[3] << 16);
1966 
1967 	ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 4);
1968 	if (unlikely(ret))
1969 		return ret;
1970 	counters->ecc_error_pkts[0] =
1971 		packed_record[0] | (packed_record[1] << 16);
1972 	counters->ecc_error_pkts[1] =
1973 		packed_record[2] | (packed_record[3] << 16);
1974 
1975 	ret = get_raw_egress_record(hw, packed_record, 4, 3, 256 + 5);
1976 	if (unlikely(ret))
1977 		return ret;
1978 	counters->unctrl_hit_drop_redir[0] =
1979 		packed_record[0] | (packed_record[1] << 16);
1980 	counters->unctrl_hit_drop_redir[1] =
1981 		packed_record[2] | (packed_record[3] << 16);
1982 
1983 	return 0;
1984 }
1985 
1986 int aq_mss_get_egress_common_counters(struct aq_hw_s *hw,
1987 	struct aq_mss_egress_common_counters *counters)
1988 {
1989 	memset(counters, 0, sizeof(*counters));
1990 
1991 	return AQ_API_CALL_SAFE(get_egress_common_counters, hw, counters);
1992 }
1993 
1994 static int clear_egress_counters(struct aq_hw_s *hw)
1995 {
1996 	struct mss_egress_ctl_register ctl_reg;
1997 	int ret;
1998 
1999 	memset(&ctl_reg, 0, sizeof(ctl_reg));
2000 
2001 	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1, MSS_EGRESS_CTL_REGISTER_ADDR,
2002 			       &ctl_reg.word_0);
2003 	if (unlikely(ret))
2004 		return ret;
2005 	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2006 			       MSS_EGRESS_CTL_REGISTER_ADDR + 4,
2007 			       &ctl_reg.word_1);
2008 	if (unlikely(ret))
2009 		return ret;
2010 
2011 	/* Toggle the Egress MIB clear bit 0->1->0 */
2012 	ctl_reg.bits_0.clear_counter = 0;
2013 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2014 				MSS_EGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2015 	if (unlikely(ret))
2016 		return ret;
2017 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2018 				MSS_EGRESS_CTL_REGISTER_ADDR + 4,
2019 				ctl_reg.word_1);
2020 	if (unlikely(ret))
2021 		return ret;
2022 
2023 	ctl_reg.bits_0.clear_counter = 1;
2024 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2025 				MSS_EGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2026 	if (unlikely(ret))
2027 		return ret;
2028 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2029 				MSS_EGRESS_CTL_REGISTER_ADDR + 4,
2030 				ctl_reg.word_1);
2031 	if (unlikely(ret))
2032 		return ret;
2033 
2034 	ctl_reg.bits_0.clear_counter = 0;
2035 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2036 				MSS_EGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2037 	if (unlikely(ret))
2038 		return ret;
2039 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2040 				MSS_EGRESS_CTL_REGISTER_ADDR + 4,
2041 				ctl_reg.word_1);
2042 	if (unlikely(ret))
2043 		return ret;
2044 
2045 	return 0;
2046 }
2047 
2048 int aq_mss_clear_egress_counters(struct aq_hw_s *hw)
2049 {
2050 	return AQ_API_CALL_SAFE(clear_egress_counters, hw);
2051 }
2052 
2053 static int get_ingress_sa_counters(struct aq_hw_s *hw,
2054 				   struct aq_mss_ingress_sa_counters *counters,
2055 				   u16 sa_index)
2056 {
2057 	u16 packed_record[4];
2058 	int ret;
2059 
2060 	if (sa_index >= NUMROWS_INGRESSSARECORD)
2061 		return -EINVAL;
2062 
2063 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2064 				     sa_index * 12 + 0);
2065 	if (unlikely(ret))
2066 		return ret;
2067 	counters->untagged_hit_pkts[0] =
2068 		packed_record[0] | (packed_record[1] << 16);
2069 	counters->untagged_hit_pkts[1] =
2070 		packed_record[2] | (packed_record[3] << 16);
2071 
2072 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2073 				     sa_index * 12 + 1);
2074 	if (unlikely(ret))
2075 		return ret;
2076 	counters->ctrl_hit_drop_redir_pkts[0] =
2077 		packed_record[0] | (packed_record[1] << 16);
2078 	counters->ctrl_hit_drop_redir_pkts[1] =
2079 		packed_record[2] | (packed_record[3] << 16);
2080 
2081 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2082 				     sa_index * 12 + 2);
2083 	if (unlikely(ret))
2084 		return ret;
2085 	counters->not_using_sa[0] = packed_record[0] | (packed_record[1] << 16);
2086 	counters->not_using_sa[1] = packed_record[2] | (packed_record[3] << 16);
2087 
2088 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2089 				     sa_index * 12 + 3);
2090 	if (unlikely(ret))
2091 		return ret;
2092 	counters->unused_sa[0] = packed_record[0] | (packed_record[1] << 16);
2093 	counters->unused_sa[1] = packed_record[2] | (packed_record[3] << 16);
2094 
2095 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2096 				     sa_index * 12 + 4);
2097 	if (unlikely(ret))
2098 		return ret;
2099 	counters->not_valid_pkts[0] =
2100 		packed_record[0] | (packed_record[1] << 16);
2101 	counters->not_valid_pkts[1] =
2102 		packed_record[2] | (packed_record[3] << 16);
2103 
2104 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2105 				     sa_index * 12 + 5);
2106 	if (unlikely(ret))
2107 		return ret;
2108 	counters->invalid_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2109 	counters->invalid_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2110 
2111 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2112 				     sa_index * 12 + 6);
2113 	if (unlikely(ret))
2114 		return ret;
2115 	counters->ok_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2116 	counters->ok_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2117 
2118 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2119 				     sa_index * 12 + 7);
2120 	if (unlikely(ret))
2121 		return ret;
2122 	counters->late_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2123 	counters->late_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2124 
2125 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2126 				     sa_index * 12 + 8);
2127 	if (unlikely(ret))
2128 		return ret;
2129 	counters->delayed_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2130 	counters->delayed_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2131 
2132 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2133 				     sa_index * 12 + 9);
2134 	if (unlikely(ret))
2135 		return ret;
2136 	counters->unchecked_pkts[0] =
2137 		packed_record[0] | (packed_record[1] << 16);
2138 	counters->unchecked_pkts[1] =
2139 		packed_record[2] | (packed_record[3] << 16);
2140 
2141 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2142 				     sa_index * 12 + 10);
2143 	if (unlikely(ret))
2144 		return ret;
2145 	counters->validated_octets[0] =
2146 		packed_record[0] | (packed_record[1] << 16);
2147 	counters->validated_octets[1] =
2148 		packed_record[2] | (packed_record[3] << 16);
2149 
2150 	ret = get_raw_ingress_record(hw, packed_record, 4, 6,
2151 				     sa_index * 12 + 11);
2152 	if (unlikely(ret))
2153 		return ret;
2154 	counters->decrypted_octets[0] =
2155 		packed_record[0] | (packed_record[1] << 16);
2156 	counters->decrypted_octets[1] =
2157 		packed_record[2] | (packed_record[3] << 16);
2158 
2159 	return 0;
2160 }
2161 
2162 int aq_mss_get_ingress_sa_counters(struct aq_hw_s *hw,
2163 				   struct aq_mss_ingress_sa_counters *counters,
2164 				   u16 sa_index)
2165 {
2166 	memset(counters, 0, sizeof(*counters));
2167 
2168 	return AQ_API_CALL_SAFE(get_ingress_sa_counters, hw, counters,
2169 				sa_index);
2170 }
2171 
2172 static int
2173 get_ingress_common_counters(struct aq_hw_s *hw,
2174 			    struct aq_mss_ingress_common_counters *counters)
2175 {
2176 	u16 packed_record[4];
2177 	int ret;
2178 
2179 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 0);
2180 	if (unlikely(ret))
2181 		return ret;
2182 	counters->ctl_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2183 	counters->ctl_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2184 
2185 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 1);
2186 	if (unlikely(ret))
2187 		return ret;
2188 	counters->tagged_miss_pkts[0] =
2189 		packed_record[0] | (packed_record[1] << 16);
2190 	counters->tagged_miss_pkts[1] =
2191 		packed_record[2] | (packed_record[3] << 16);
2192 
2193 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 2);
2194 	if (unlikely(ret))
2195 		return ret;
2196 	counters->untagged_miss_pkts[0] =
2197 		packed_record[0] | (packed_record[1] << 16);
2198 	counters->untagged_miss_pkts[1] =
2199 		packed_record[2] | (packed_record[3] << 16);
2200 
2201 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 3);
2202 	if (unlikely(ret))
2203 		return ret;
2204 	counters->notag_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2205 	counters->notag_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2206 
2207 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 4);
2208 	if (unlikely(ret))
2209 		return ret;
2210 	counters->untagged_pkts[0] =
2211 		packed_record[0] | (packed_record[1] << 16);
2212 	counters->untagged_pkts[1] =
2213 		packed_record[2] | (packed_record[3] << 16);
2214 
2215 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 5);
2216 	if (unlikely(ret))
2217 		return ret;
2218 	counters->bad_tag_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2219 	counters->bad_tag_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2220 
2221 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 6);
2222 	if (unlikely(ret))
2223 		return ret;
2224 	counters->no_sci_pkts[0] = packed_record[0] | (packed_record[1] << 16);
2225 	counters->no_sci_pkts[1] = packed_record[2] | (packed_record[3] << 16);
2226 
2227 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 7);
2228 	if (unlikely(ret))
2229 		return ret;
2230 	counters->unknown_sci_pkts[0] =
2231 		packed_record[0] | (packed_record[1] << 16);
2232 	counters->unknown_sci_pkts[1] =
2233 		packed_record[2] | (packed_record[3] << 16);
2234 
2235 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 8);
2236 	if (unlikely(ret))
2237 		return ret;
2238 	counters->ctrl_prt_pass_pkts[0] =
2239 		packed_record[0] | (packed_record[1] << 16);
2240 	counters->ctrl_prt_pass_pkts[1] =
2241 		packed_record[2] | (packed_record[3] << 16);
2242 
2243 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 9);
2244 	if (unlikely(ret))
2245 		return ret;
2246 	counters->unctrl_prt_pass_pkts[0] =
2247 		packed_record[0] | (packed_record[1] << 16);
2248 	counters->unctrl_prt_pass_pkts[1] =
2249 		packed_record[2] | (packed_record[3] << 16);
2250 
2251 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 10);
2252 	if (unlikely(ret))
2253 		return ret;
2254 	counters->ctrl_prt_fail_pkts[0] =
2255 		packed_record[0] | (packed_record[1] << 16);
2256 	counters->ctrl_prt_fail_pkts[1] =
2257 		packed_record[2] | (packed_record[3] << 16);
2258 
2259 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 11);
2260 	if (unlikely(ret))
2261 		return ret;
2262 	counters->unctrl_prt_fail_pkts[0] =
2263 		packed_record[0] | (packed_record[1] << 16);
2264 	counters->unctrl_prt_fail_pkts[1] =
2265 		packed_record[2] | (packed_record[3] << 16);
2266 
2267 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 12);
2268 	if (unlikely(ret))
2269 		return ret;
2270 	counters->too_long_pkts[0] =
2271 		packed_record[0] | (packed_record[1] << 16);
2272 	counters->too_long_pkts[1] =
2273 		packed_record[2] | (packed_record[3] << 16);
2274 
2275 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 13);
2276 	if (unlikely(ret))
2277 		return ret;
2278 	counters->igpoc_ctl_pkts[0] =
2279 		packed_record[0] | (packed_record[1] << 16);
2280 	counters->igpoc_ctl_pkts[1] =
2281 		packed_record[2] | (packed_record[3] << 16);
2282 
2283 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 14);
2284 	if (unlikely(ret))
2285 		return ret;
2286 	counters->ecc_error_pkts[0] =
2287 		packed_record[0] | (packed_record[1] << 16);
2288 	counters->ecc_error_pkts[1] =
2289 		packed_record[2] | (packed_record[3] << 16);
2290 
2291 	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 15);
2292 	if (unlikely(ret))
2293 		return ret;
2294 	counters->unctrl_hit_drop_redir[0] =
2295 		packed_record[0] | (packed_record[1] << 16);
2296 	counters->unctrl_hit_drop_redir[1] =
2297 		packed_record[2] | (packed_record[3] << 16);
2298 
2299 	return 0;
2300 }
2301 
2302 int aq_mss_get_ingress_common_counters(struct aq_hw_s *hw,
2303 	struct aq_mss_ingress_common_counters *counters)
2304 {
2305 	memset(counters, 0, sizeof(*counters));
2306 
2307 	return AQ_API_CALL_SAFE(get_ingress_common_counters, hw, counters);
2308 }
2309 
2310 static int clear_ingress_counters(struct aq_hw_s *hw)
2311 {
2312 	struct mss_ingress_ctl_register ctl_reg;
2313 	int ret;
2314 
2315 	memset(&ctl_reg, 0, sizeof(ctl_reg));
2316 
2317 	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2318 			       MSS_INGRESS_CTL_REGISTER_ADDR, &ctl_reg.word_0);
2319 	if (unlikely(ret))
2320 		return ret;
2321 	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2322 			       MSS_INGRESS_CTL_REGISTER_ADDR + 4,
2323 			       &ctl_reg.word_1);
2324 	if (unlikely(ret))
2325 		return ret;
2326 
2327 	/* Toggle the Ingress MIB clear bit 0->1->0 */
2328 	ctl_reg.bits_0.clear_count = 0;
2329 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2330 				MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2331 	if (unlikely(ret))
2332 		return ret;
2333 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2334 				MSS_INGRESS_CTL_REGISTER_ADDR + 4,
2335 				ctl_reg.word_1);
2336 	if (unlikely(ret))
2337 		return ret;
2338 
2339 	ctl_reg.bits_0.clear_count = 1;
2340 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2341 				MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2342 	if (unlikely(ret))
2343 		return ret;
2344 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2345 				MSS_INGRESS_CTL_REGISTER_ADDR + 4,
2346 				ctl_reg.word_1);
2347 	if (unlikely(ret))
2348 		return ret;
2349 
2350 	ctl_reg.bits_0.clear_count = 0;
2351 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2352 				MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);
2353 	if (unlikely(ret))
2354 		return ret;
2355 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2356 				MSS_INGRESS_CTL_REGISTER_ADDR + 4,
2357 				ctl_reg.word_1);
2358 	if (unlikely(ret))
2359 		return ret;
2360 
2361 	return 0;
2362 }
2363 
2364 int aq_mss_clear_ingress_counters(struct aq_hw_s *hw)
2365 {
2366 	return AQ_API_CALL_SAFE(clear_ingress_counters, hw);
2367 }
2368 
2369 static int get_egress_sa_expired(struct aq_hw_s *hw, u32 *expired)
2370 {
2371 	u16 val;
2372 	int ret;
2373 
2374 	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2375 			       MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR,
2376 			       &val);
2377 	if (unlikely(ret))
2378 		return ret;
2379 
2380 	*expired = val;
2381 
2382 	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2383 			       MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR + 1,
2384 			       &val);
2385 	if (unlikely(ret))
2386 		return ret;
2387 
2388 	*expired |= val << 16;
2389 
2390 	return 0;
2391 }
2392 
2393 int aq_mss_get_egress_sa_expired(struct aq_hw_s *hw, u32 *expired)
2394 {
2395 	*expired = 0;
2396 
2397 	return AQ_API_CALL_SAFE(get_egress_sa_expired, hw, expired);
2398 }
2399 
2400 static int get_egress_sa_threshold_expired(struct aq_hw_s *hw,
2401 					   u32 *expired)
2402 {
2403 	u16 val;
2404 	int ret;
2405 
2406 	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2407 		MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR, &val);
2408 	if (unlikely(ret))
2409 		return ret;
2410 
2411 	*expired = val;
2412 
2413 	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,
2414 		MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR + 1, &val);
2415 	if (unlikely(ret))
2416 		return ret;
2417 
2418 	*expired |= val << 16;
2419 
2420 	return 0;
2421 }
2422 
2423 int aq_mss_get_egress_sa_threshold_expired(struct aq_hw_s *hw,
2424 					   u32 *expired)
2425 {
2426 	*expired = 0;
2427 
2428 	return AQ_API_CALL_SAFE(get_egress_sa_threshold_expired, hw, expired);
2429 }
2430 
2431 static int set_egress_sa_expired(struct aq_hw_s *hw, u32 expired)
2432 {
2433 	int ret;
2434 
2435 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2436 				MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR,
2437 				expired & 0xFFFF);
2438 	if (unlikely(ret))
2439 		return ret;
2440 
2441 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2442 				MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR + 1,
2443 				expired >> 16);
2444 	if (unlikely(ret))
2445 		return ret;
2446 
2447 	return 0;
2448 }
2449 
2450 int aq_mss_set_egress_sa_expired(struct aq_hw_s *hw, u32 expired)
2451 {
2452 	return AQ_API_CALL_SAFE(set_egress_sa_expired, hw, expired);
2453 }
2454 
2455 static int set_egress_sa_threshold_expired(struct aq_hw_s *hw, u32 expired)
2456 {
2457 	int ret;
2458 
2459 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2460 		MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR,
2461 		expired & 0xFFFF);
2462 	if (unlikely(ret))
2463 		return ret;
2464 
2465 	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
2466 		MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR + 1,
2467 		expired >> 16);
2468 	if (unlikely(ret))
2469 		return ret;
2470 
2471 	return 0;
2472 }
2473 
2474 int aq_mss_set_egress_sa_threshold_expired(struct aq_hw_s *hw, u32 expired)
2475 {
2476 	return AQ_API_CALL_SAFE(set_egress_sa_threshold_expired, hw, expired);
2477 }
2478