cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

macsec_api.c (67290B)


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