Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Apr 14-17, 2025
Register
Loading...
   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}
1