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