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 ******************************************************************************/
30static 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
38static 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
43static 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
49static 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
59static 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 */
120static 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. */
169static 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
213static 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
261static int
262set_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
286int 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
294static 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
340int 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
350static int
351set_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
436int 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
448static int
449get_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
548int 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
558static 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
598int 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
609static 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
652int 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
661static 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
696int 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
707static 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
745int 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
754static int
755set_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
801int 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
813static 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
858int 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
867static int
868set_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
947int 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
955static int
956get_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
1049int 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
1059static int
1060set_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
1089int 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
1097static int
1098get_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
1141int 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
1151static 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
1179int 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
1186static 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
1228int 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
1237static 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
1366int 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
1373static 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
1516int 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
1525static 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
1565int 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
1572static 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
1615int 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
1624static 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
1654int 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
1665static 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
1698int 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
1707static 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
1751clear_key:
1752	memzero_explicit(packed_record, sizeof(packed_record));
1753	return ret;
1754}
1755
1756int 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
1768static 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
1815int 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
1824static 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
1869int 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
1878static 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
1923int 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
1932static int
1933get_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
1986int 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
1994static 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
2048int aq_mss_clear_egress_counters(struct aq_hw_s *hw)
2049{
2050	return AQ_API_CALL_SAFE(clear_egress_counters, hw);
2051}
2052
2053static 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
2162int 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
2172static int
2173get_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
2302int 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
2310static 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
2364int aq_mss_clear_ingress_counters(struct aq_hw_s *hw)
2365{
2366	return AQ_API_CALL_SAFE(clear_ingress_counters, hw);
2367}
2368
2369static 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
2393int 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
2400static 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
2423int 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
2431static 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
2450int 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
2455static 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
2474int 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