brintos

brintos / linux-shallow public Read only

0
0
Text · 65.8 KiB · 4319249 Raw
2478 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Atlantic Network Driver3 * 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 wrappers29 ******************************************************************************/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 status57 ******************************************************************************/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 first71	 * 2. Then write 1E.80A172	 *73	 * For HHD devices: These writes need to be performed consecutively, and74	 * to ensure this we use the PIF mailbox to delegate the reads/writes to75	 * the FW.76	 *77	 * For EUR devices: Not need to use the PIF mailbox; it is safe to78	 * 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 int262set_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 even305	 * row, throw that value away, and finally read the desired row.306	 * This is a workaround for EUR devices that allows us to read307	 * 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 int351set_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 int449get_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 even460	 * 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 int755set_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 int868set_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 int956get_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 even967	 * 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 int1060set_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 int1098get_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 even1109	 * 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 even1197	 * 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 even1384	 * 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 int1933get_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 int2173get_ingress_common_counters(struct aq_hw_s *hw,2174			    struct aq_mss_ingress_common_counters *counters)2175{2176	u16 packed_record[4];2177	int ret;2178 2179	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 0);2180	if (unlikely(ret))2181		return ret;2182	counters->ctl_pkts[0] = packed_record[0] | (packed_record[1] << 16);2183	counters->ctl_pkts[1] = packed_record[2] | (packed_record[3] << 16);2184 2185	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 1);2186	if (unlikely(ret))2187		return ret;2188	counters->tagged_miss_pkts[0] =2189		packed_record[0] | (packed_record[1] << 16);2190	counters->tagged_miss_pkts[1] =2191		packed_record[2] | (packed_record[3] << 16);2192 2193	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 2);2194	if (unlikely(ret))2195		return ret;2196	counters->untagged_miss_pkts[0] =2197		packed_record[0] | (packed_record[1] << 16);2198	counters->untagged_miss_pkts[1] =2199		packed_record[2] | (packed_record[3] << 16);2200 2201	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 3);2202	if (unlikely(ret))2203		return ret;2204	counters->notag_pkts[0] = packed_record[0] | (packed_record[1] << 16);2205	counters->notag_pkts[1] = packed_record[2] | (packed_record[3] << 16);2206 2207	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 4);2208	if (unlikely(ret))2209		return ret;2210	counters->untagged_pkts[0] =2211		packed_record[0] | (packed_record[1] << 16);2212	counters->untagged_pkts[1] =2213		packed_record[2] | (packed_record[3] << 16);2214 2215	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 5);2216	if (unlikely(ret))2217		return ret;2218	counters->bad_tag_pkts[0] = packed_record[0] | (packed_record[1] << 16);2219	counters->bad_tag_pkts[1] = packed_record[2] | (packed_record[3] << 16);2220 2221	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 6);2222	if (unlikely(ret))2223		return ret;2224	counters->no_sci_pkts[0] = packed_record[0] | (packed_record[1] << 16);2225	counters->no_sci_pkts[1] = packed_record[2] | (packed_record[3] << 16);2226 2227	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 7);2228	if (unlikely(ret))2229		return ret;2230	counters->unknown_sci_pkts[0] =2231		packed_record[0] | (packed_record[1] << 16);2232	counters->unknown_sci_pkts[1] =2233		packed_record[2] | (packed_record[3] << 16);2234 2235	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 8);2236	if (unlikely(ret))2237		return ret;2238	counters->ctrl_prt_pass_pkts[0] =2239		packed_record[0] | (packed_record[1] << 16);2240	counters->ctrl_prt_pass_pkts[1] =2241		packed_record[2] | (packed_record[3] << 16);2242 2243	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 9);2244	if (unlikely(ret))2245		return ret;2246	counters->unctrl_prt_pass_pkts[0] =2247		packed_record[0] | (packed_record[1] << 16);2248	counters->unctrl_prt_pass_pkts[1] =2249		packed_record[2] | (packed_record[3] << 16);2250 2251	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 10);2252	if (unlikely(ret))2253		return ret;2254	counters->ctrl_prt_fail_pkts[0] =2255		packed_record[0] | (packed_record[1] << 16);2256	counters->ctrl_prt_fail_pkts[1] =2257		packed_record[2] | (packed_record[3] << 16);2258 2259	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 11);2260	if (unlikely(ret))2261		return ret;2262	counters->unctrl_prt_fail_pkts[0] =2263		packed_record[0] | (packed_record[1] << 16);2264	counters->unctrl_prt_fail_pkts[1] =2265		packed_record[2] | (packed_record[3] << 16);2266 2267	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 12);2268	if (unlikely(ret))2269		return ret;2270	counters->too_long_pkts[0] =2271		packed_record[0] | (packed_record[1] << 16);2272	counters->too_long_pkts[1] =2273		packed_record[2] | (packed_record[3] << 16);2274 2275	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 13);2276	if (unlikely(ret))2277		return ret;2278	counters->igpoc_ctl_pkts[0] =2279		packed_record[0] | (packed_record[1] << 16);2280	counters->igpoc_ctl_pkts[1] =2281		packed_record[2] | (packed_record[3] << 16);2282 2283	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 14);2284	if (unlikely(ret))2285		return ret;2286	counters->ecc_error_pkts[0] =2287		packed_record[0] | (packed_record[1] << 16);2288	counters->ecc_error_pkts[1] =2289		packed_record[2] | (packed_record[3] << 16);2290 2291	ret = get_raw_ingress_record(hw, packed_record, 4, 6, 385 + 15);2292	if (unlikely(ret))2293		return ret;2294	counters->unctrl_hit_drop_redir[0] =2295		packed_record[0] | (packed_record[1] << 16);2296	counters->unctrl_hit_drop_redir[1] =2297		packed_record[2] | (packed_record[3] << 16);2298 2299	return 0;2300}2301 2302int aq_mss_get_ingress_common_counters(struct aq_hw_s *hw,2303	struct aq_mss_ingress_common_counters *counters)2304{2305	memset(counters, 0, sizeof(*counters));2306 2307	return AQ_API_CALL_SAFE(get_ingress_common_counters, hw, counters);2308}2309 2310static int clear_ingress_counters(struct aq_hw_s *hw)2311{2312	struct mss_ingress_ctl_register ctl_reg;2313	int ret;2314 2315	memset(&ctl_reg, 0, sizeof(ctl_reg));2316 2317	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,2318			       MSS_INGRESS_CTL_REGISTER_ADDR, &ctl_reg.word_0);2319	if (unlikely(ret))2320		return ret;2321	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,2322			       MSS_INGRESS_CTL_REGISTER_ADDR + 4,2323			       &ctl_reg.word_1);2324	if (unlikely(ret))2325		return ret;2326 2327	/* Toggle the Ingress MIB clear bit 0->1->0 */2328	ctl_reg.bits_0.clear_count = 0;2329	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2330				MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);2331	if (unlikely(ret))2332		return ret;2333	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2334				MSS_INGRESS_CTL_REGISTER_ADDR + 4,2335				ctl_reg.word_1);2336	if (unlikely(ret))2337		return ret;2338 2339	ctl_reg.bits_0.clear_count = 1;2340	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2341				MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);2342	if (unlikely(ret))2343		return ret;2344	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2345				MSS_INGRESS_CTL_REGISTER_ADDR + 4,2346				ctl_reg.word_1);2347	if (unlikely(ret))2348		return ret;2349 2350	ctl_reg.bits_0.clear_count = 0;2351	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2352				MSS_INGRESS_CTL_REGISTER_ADDR, ctl_reg.word_0);2353	if (unlikely(ret))2354		return ret;2355	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2356				MSS_INGRESS_CTL_REGISTER_ADDR + 4,2357				ctl_reg.word_1);2358	if (unlikely(ret))2359		return ret;2360 2361	return 0;2362}2363 2364int aq_mss_clear_ingress_counters(struct aq_hw_s *hw)2365{2366	return AQ_API_CALL_SAFE(clear_ingress_counters, hw);2367}2368 2369static int get_egress_sa_expired(struct aq_hw_s *hw, u32 *expired)2370{2371	u16 val;2372	int ret;2373 2374	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,2375			       MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR,2376			       &val);2377	if (unlikely(ret))2378		return ret;2379 2380	*expired = val;2381 2382	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,2383			       MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR + 1,2384			       &val);2385	if (unlikely(ret))2386		return ret;2387 2388	*expired |= val << 16;2389 2390	return 0;2391}2392 2393int aq_mss_get_egress_sa_expired(struct aq_hw_s *hw, u32 *expired)2394{2395	*expired = 0;2396 2397	return AQ_API_CALL_SAFE(get_egress_sa_expired, hw, expired);2398}2399 2400static int get_egress_sa_threshold_expired(struct aq_hw_s *hw,2401					   u32 *expired)2402{2403	u16 val;2404	int ret;2405 2406	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,2407		MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR, &val);2408	if (unlikely(ret))2409		return ret;2410 2411	*expired = val;2412 2413	ret = aq_mss_mdio_read(hw, MDIO_MMD_VEND1,2414		MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR + 1, &val);2415	if (unlikely(ret))2416		return ret;2417 2418	*expired |= val << 16;2419 2420	return 0;2421}2422 2423int aq_mss_get_egress_sa_threshold_expired(struct aq_hw_s *hw,2424					   u32 *expired)2425{2426	*expired = 0;2427 2428	return AQ_API_CALL_SAFE(get_egress_sa_threshold_expired, hw, expired);2429}2430 2431static int set_egress_sa_expired(struct aq_hw_s *hw, u32 expired)2432{2433	int ret;2434 2435	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2436				MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR,2437				expired & 0xFFFF);2438	if (unlikely(ret))2439		return ret;2440 2441	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2442				MSS_EGRESS_SA_EXPIRED_STATUS_REGISTER_ADDR + 1,2443				expired >> 16);2444	if (unlikely(ret))2445		return ret;2446 2447	return 0;2448}2449 2450int aq_mss_set_egress_sa_expired(struct aq_hw_s *hw, u32 expired)2451{2452	return AQ_API_CALL_SAFE(set_egress_sa_expired, hw, expired);2453}2454 2455static int set_egress_sa_threshold_expired(struct aq_hw_s *hw, u32 expired)2456{2457	int ret;2458 2459	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2460		MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR,2461		expired & 0xFFFF);2462	if (unlikely(ret))2463		return ret;2464 2465	ret = aq_mss_mdio_write(hw, MDIO_MMD_VEND1,2466		MSS_EGRESS_SA_THRESHOLD_EXPIRED_STATUS_REGISTER_ADDR + 1,2467		expired >> 16);2468	if (unlikely(ret))2469		return ret;2470 2471	return 0;2472}2473 2474int aq_mss_set_egress_sa_threshold_expired(struct aq_hw_s *hw, u32 expired)2475{2476	return AQ_API_CALL_SAFE(set_egress_sa_threshold_expired, hw, expired);2477}2478