162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Atlantic Network Driver 362306a36Sopenharmony_ci * Copyright (C) 2020 Marvell International Ltd. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "aq_macsec.h" 762306a36Sopenharmony_ci#include "aq_nic.h" 862306a36Sopenharmony_ci#include <linux/rtnetlink.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "macsec/macsec_api.h" 1162306a36Sopenharmony_ci#define AQ_MACSEC_KEY_LEN_128_BIT 16 1262306a36Sopenharmony_ci#define AQ_MACSEC_KEY_LEN_192_BIT 24 1362306a36Sopenharmony_ci#define AQ_MACSEC_KEY_LEN_256_BIT 32 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cienum aq_clear_type { 1662306a36Sopenharmony_ci /* update HW configuration */ 1762306a36Sopenharmony_ci AQ_CLEAR_HW = BIT(0), 1862306a36Sopenharmony_ci /* update SW configuration (busy bits, pointers) */ 1962306a36Sopenharmony_ci AQ_CLEAR_SW = BIT(1), 2062306a36Sopenharmony_ci /* update both HW and SW configuration */ 2162306a36Sopenharmony_ci AQ_CLEAR_ALL = AQ_CLEAR_HW | AQ_CLEAR_SW, 2262306a36Sopenharmony_ci}; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic int aq_clear_txsc(struct aq_nic_s *nic, const int txsc_idx, 2562306a36Sopenharmony_ci enum aq_clear_type clear_type); 2662306a36Sopenharmony_cistatic int aq_clear_txsa(struct aq_nic_s *nic, struct aq_macsec_txsc *aq_txsc, 2762306a36Sopenharmony_ci const int sa_num, enum aq_clear_type clear_type); 2862306a36Sopenharmony_cistatic int aq_clear_rxsc(struct aq_nic_s *nic, const int rxsc_idx, 2962306a36Sopenharmony_ci enum aq_clear_type clear_type); 3062306a36Sopenharmony_cistatic int aq_clear_rxsa(struct aq_nic_s *nic, struct aq_macsec_rxsc *aq_rxsc, 3162306a36Sopenharmony_ci const int sa_num, enum aq_clear_type clear_type); 3262306a36Sopenharmony_cistatic int aq_clear_secy(struct aq_nic_s *nic, const struct macsec_secy *secy, 3362306a36Sopenharmony_ci enum aq_clear_type clear_type); 3462306a36Sopenharmony_cistatic int aq_apply_macsec_cfg(struct aq_nic_s *nic); 3562306a36Sopenharmony_cistatic int aq_apply_secy_cfg(struct aq_nic_s *nic, 3662306a36Sopenharmony_ci const struct macsec_secy *secy); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic void aq_ether_addr_to_mac(u32 mac[2], const unsigned char *emac) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci u32 tmp[2] = { 0 }; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci memcpy(((u8 *)tmp) + 2, emac, ETH_ALEN); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci mac[0] = swab32(tmp[1]); 4562306a36Sopenharmony_ci mac[1] = swab32(tmp[0]); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* There's a 1:1 mapping between SecY and TX SC */ 4962306a36Sopenharmony_cistatic int aq_get_txsc_idx_from_secy(struct aq_macsec_cfg *macsec_cfg, 5062306a36Sopenharmony_ci const struct macsec_secy *secy) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci int i; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (unlikely(!secy)) 5562306a36Sopenharmony_ci return -1; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 5862306a36Sopenharmony_ci if (macsec_cfg->aq_txsc[i].sw_secy == secy) 5962306a36Sopenharmony_ci return i; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci return -1; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int aq_get_rxsc_idx_from_rxsc(struct aq_macsec_cfg *macsec_cfg, 6562306a36Sopenharmony_ci const struct macsec_rx_sc *rxsc) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci int i; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (unlikely(!rxsc)) 7062306a36Sopenharmony_ci return -1; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 7362306a36Sopenharmony_ci if (macsec_cfg->aq_rxsc[i].sw_rxsc == rxsc) 7462306a36Sopenharmony_ci return i; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return -1; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic int aq_get_txsc_idx_from_sc_idx(const enum aq_macsec_sc_sa sc_sa, 8162306a36Sopenharmony_ci const int sc_idx) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci switch (sc_sa) { 8462306a36Sopenharmony_ci case aq_macsec_sa_sc_4sa_8sc: 8562306a36Sopenharmony_ci return sc_idx >> 2; 8662306a36Sopenharmony_ci case aq_macsec_sa_sc_2sa_16sc: 8762306a36Sopenharmony_ci return sc_idx >> 1; 8862306a36Sopenharmony_ci case aq_macsec_sa_sc_1sa_32sc: 8962306a36Sopenharmony_ci return sc_idx; 9062306a36Sopenharmony_ci default: 9162306a36Sopenharmony_ci WARN_ONCE(true, "Invalid sc_sa"); 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci return -1; 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* Rotate keys u32[8] */ 9762306a36Sopenharmony_cistatic void aq_rotate_keys(u32 (*key)[8], const int key_len) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci u32 tmp[8] = { 0 }; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci memcpy(&tmp, key, sizeof(tmp)); 10262306a36Sopenharmony_ci memset(*key, 0, sizeof(*key)); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (key_len == AQ_MACSEC_KEY_LEN_128_BIT) { 10562306a36Sopenharmony_ci (*key)[0] = swab32(tmp[3]); 10662306a36Sopenharmony_ci (*key)[1] = swab32(tmp[2]); 10762306a36Sopenharmony_ci (*key)[2] = swab32(tmp[1]); 10862306a36Sopenharmony_ci (*key)[3] = swab32(tmp[0]); 10962306a36Sopenharmony_ci } else if (key_len == AQ_MACSEC_KEY_LEN_192_BIT) { 11062306a36Sopenharmony_ci (*key)[0] = swab32(tmp[5]); 11162306a36Sopenharmony_ci (*key)[1] = swab32(tmp[4]); 11262306a36Sopenharmony_ci (*key)[2] = swab32(tmp[3]); 11362306a36Sopenharmony_ci (*key)[3] = swab32(tmp[2]); 11462306a36Sopenharmony_ci (*key)[4] = swab32(tmp[1]); 11562306a36Sopenharmony_ci (*key)[5] = swab32(tmp[0]); 11662306a36Sopenharmony_ci } else if (key_len == AQ_MACSEC_KEY_LEN_256_BIT) { 11762306a36Sopenharmony_ci (*key)[0] = swab32(tmp[7]); 11862306a36Sopenharmony_ci (*key)[1] = swab32(tmp[6]); 11962306a36Sopenharmony_ci (*key)[2] = swab32(tmp[5]); 12062306a36Sopenharmony_ci (*key)[3] = swab32(tmp[4]); 12162306a36Sopenharmony_ci (*key)[4] = swab32(tmp[3]); 12262306a36Sopenharmony_ci (*key)[5] = swab32(tmp[2]); 12362306a36Sopenharmony_ci (*key)[6] = swab32(tmp[1]); 12462306a36Sopenharmony_ci (*key)[7] = swab32(tmp[0]); 12562306a36Sopenharmony_ci } else { 12662306a36Sopenharmony_ci pr_warn("Rotate_keys: invalid key_len\n"); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci#define STATS_2x32_TO_64(stat_field) \ 13162306a36Sopenharmony_ci (((u64)stat_field[1] << 32) | stat_field[0]) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int aq_get_macsec_common_stats(struct aq_hw_s *hw, 13462306a36Sopenharmony_ci struct aq_macsec_common_stats *stats) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct aq_mss_ingress_common_counters ingress_counters; 13762306a36Sopenharmony_ci struct aq_mss_egress_common_counters egress_counters; 13862306a36Sopenharmony_ci int ret; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* MACSEC counters */ 14162306a36Sopenharmony_ci ret = aq_mss_get_ingress_common_counters(hw, &ingress_counters); 14262306a36Sopenharmony_ci if (unlikely(ret)) 14362306a36Sopenharmony_ci return ret; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci stats->in.ctl_pkts = STATS_2x32_TO_64(ingress_counters.ctl_pkts); 14662306a36Sopenharmony_ci stats->in.tagged_miss_pkts = 14762306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.tagged_miss_pkts); 14862306a36Sopenharmony_ci stats->in.untagged_miss_pkts = 14962306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.untagged_miss_pkts); 15062306a36Sopenharmony_ci stats->in.notag_pkts = STATS_2x32_TO_64(ingress_counters.notag_pkts); 15162306a36Sopenharmony_ci stats->in.untagged_pkts = 15262306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.untagged_pkts); 15362306a36Sopenharmony_ci stats->in.bad_tag_pkts = 15462306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.bad_tag_pkts); 15562306a36Sopenharmony_ci stats->in.no_sci_pkts = STATS_2x32_TO_64(ingress_counters.no_sci_pkts); 15662306a36Sopenharmony_ci stats->in.unknown_sci_pkts = 15762306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.unknown_sci_pkts); 15862306a36Sopenharmony_ci stats->in.ctrl_prt_pass_pkts = 15962306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.ctrl_prt_pass_pkts); 16062306a36Sopenharmony_ci stats->in.unctrl_prt_pass_pkts = 16162306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.unctrl_prt_pass_pkts); 16262306a36Sopenharmony_ci stats->in.ctrl_prt_fail_pkts = 16362306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.ctrl_prt_fail_pkts); 16462306a36Sopenharmony_ci stats->in.unctrl_prt_fail_pkts = 16562306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.unctrl_prt_fail_pkts); 16662306a36Sopenharmony_ci stats->in.too_long_pkts = 16762306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.too_long_pkts); 16862306a36Sopenharmony_ci stats->in.igpoc_ctl_pkts = 16962306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.igpoc_ctl_pkts); 17062306a36Sopenharmony_ci stats->in.ecc_error_pkts = 17162306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.ecc_error_pkts); 17262306a36Sopenharmony_ci stats->in.unctrl_hit_drop_redir = 17362306a36Sopenharmony_ci STATS_2x32_TO_64(ingress_counters.unctrl_hit_drop_redir); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci ret = aq_mss_get_egress_common_counters(hw, &egress_counters); 17662306a36Sopenharmony_ci if (unlikely(ret)) 17762306a36Sopenharmony_ci return ret; 17862306a36Sopenharmony_ci stats->out.ctl_pkts = STATS_2x32_TO_64(egress_counters.ctl_pkt); 17962306a36Sopenharmony_ci stats->out.unknown_sa_pkts = 18062306a36Sopenharmony_ci STATS_2x32_TO_64(egress_counters.unknown_sa_pkts); 18162306a36Sopenharmony_ci stats->out.untagged_pkts = 18262306a36Sopenharmony_ci STATS_2x32_TO_64(egress_counters.untagged_pkts); 18362306a36Sopenharmony_ci stats->out.too_long = STATS_2x32_TO_64(egress_counters.too_long); 18462306a36Sopenharmony_ci stats->out.ecc_error_pkts = 18562306a36Sopenharmony_ci STATS_2x32_TO_64(egress_counters.ecc_error_pkts); 18662306a36Sopenharmony_ci stats->out.unctrl_hit_drop_redir = 18762306a36Sopenharmony_ci STATS_2x32_TO_64(egress_counters.unctrl_hit_drop_redir); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return 0; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic int aq_get_rxsa_stats(struct aq_hw_s *hw, const int sa_idx, 19362306a36Sopenharmony_ci struct aq_macsec_rx_sa_stats *stats) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci struct aq_mss_ingress_sa_counters i_sa_counters; 19662306a36Sopenharmony_ci int ret; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci ret = aq_mss_get_ingress_sa_counters(hw, &i_sa_counters, sa_idx); 19962306a36Sopenharmony_ci if (unlikely(ret)) 20062306a36Sopenharmony_ci return ret; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci stats->untagged_hit_pkts = 20362306a36Sopenharmony_ci STATS_2x32_TO_64(i_sa_counters.untagged_hit_pkts); 20462306a36Sopenharmony_ci stats->ctrl_hit_drop_redir_pkts = 20562306a36Sopenharmony_ci STATS_2x32_TO_64(i_sa_counters.ctrl_hit_drop_redir_pkts); 20662306a36Sopenharmony_ci stats->not_using_sa = STATS_2x32_TO_64(i_sa_counters.not_using_sa); 20762306a36Sopenharmony_ci stats->unused_sa = STATS_2x32_TO_64(i_sa_counters.unused_sa); 20862306a36Sopenharmony_ci stats->not_valid_pkts = STATS_2x32_TO_64(i_sa_counters.not_valid_pkts); 20962306a36Sopenharmony_ci stats->invalid_pkts = STATS_2x32_TO_64(i_sa_counters.invalid_pkts); 21062306a36Sopenharmony_ci stats->ok_pkts = STATS_2x32_TO_64(i_sa_counters.ok_pkts); 21162306a36Sopenharmony_ci stats->late_pkts = STATS_2x32_TO_64(i_sa_counters.late_pkts); 21262306a36Sopenharmony_ci stats->delayed_pkts = STATS_2x32_TO_64(i_sa_counters.delayed_pkts); 21362306a36Sopenharmony_ci stats->unchecked_pkts = STATS_2x32_TO_64(i_sa_counters.unchecked_pkts); 21462306a36Sopenharmony_ci stats->validated_octets = 21562306a36Sopenharmony_ci STATS_2x32_TO_64(i_sa_counters.validated_octets); 21662306a36Sopenharmony_ci stats->decrypted_octets = 21762306a36Sopenharmony_ci STATS_2x32_TO_64(i_sa_counters.decrypted_octets); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci return 0; 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic int aq_get_txsa_stats(struct aq_hw_s *hw, const int sa_idx, 22362306a36Sopenharmony_ci struct aq_macsec_tx_sa_stats *stats) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci struct aq_mss_egress_sa_counters e_sa_counters; 22662306a36Sopenharmony_ci int ret; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci ret = aq_mss_get_egress_sa_counters(hw, &e_sa_counters, sa_idx); 22962306a36Sopenharmony_ci if (unlikely(ret)) 23062306a36Sopenharmony_ci return ret; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci stats->sa_hit_drop_redirect = 23362306a36Sopenharmony_ci STATS_2x32_TO_64(e_sa_counters.sa_hit_drop_redirect); 23462306a36Sopenharmony_ci stats->sa_protected2_pkts = 23562306a36Sopenharmony_ci STATS_2x32_TO_64(e_sa_counters.sa_protected2_pkts); 23662306a36Sopenharmony_ci stats->sa_protected_pkts = 23762306a36Sopenharmony_ci STATS_2x32_TO_64(e_sa_counters.sa_protected_pkts); 23862306a36Sopenharmony_ci stats->sa_encrypted_pkts = 23962306a36Sopenharmony_ci STATS_2x32_TO_64(e_sa_counters.sa_encrypted_pkts); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci return 0; 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic int aq_get_txsa_next_pn(struct aq_hw_s *hw, const int sa_idx, u32 *pn) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci struct aq_mss_egress_sa_record sa_rec; 24762306a36Sopenharmony_ci int ret; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci ret = aq_mss_get_egress_sa_record(hw, &sa_rec, sa_idx); 25062306a36Sopenharmony_ci if (likely(!ret)) 25162306a36Sopenharmony_ci *pn = sa_rec.next_pn; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return ret; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int aq_get_rxsa_next_pn(struct aq_hw_s *hw, const int sa_idx, u32 *pn) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci struct aq_mss_ingress_sa_record sa_rec; 25962306a36Sopenharmony_ci int ret; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci ret = aq_mss_get_ingress_sa_record(hw, &sa_rec, sa_idx); 26262306a36Sopenharmony_ci if (likely(!ret)) 26362306a36Sopenharmony_ci *pn = (!sa_rec.sat_nextpn) ? sa_rec.next_pn : 0; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci return ret; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic int aq_get_txsc_stats(struct aq_hw_s *hw, const int sc_idx, 26962306a36Sopenharmony_ci struct aq_macsec_tx_sc_stats *stats) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct aq_mss_egress_sc_counters e_sc_counters; 27262306a36Sopenharmony_ci int ret; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci ret = aq_mss_get_egress_sc_counters(hw, &e_sc_counters, sc_idx); 27562306a36Sopenharmony_ci if (unlikely(ret)) 27662306a36Sopenharmony_ci return ret; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci stats->sc_protected_pkts = 27962306a36Sopenharmony_ci STATS_2x32_TO_64(e_sc_counters.sc_protected_pkts); 28062306a36Sopenharmony_ci stats->sc_encrypted_pkts = 28162306a36Sopenharmony_ci STATS_2x32_TO_64(e_sc_counters.sc_encrypted_pkts); 28262306a36Sopenharmony_ci stats->sc_protected_octets = 28362306a36Sopenharmony_ci STATS_2x32_TO_64(e_sc_counters.sc_protected_octets); 28462306a36Sopenharmony_ci stats->sc_encrypted_octets = 28562306a36Sopenharmony_ci STATS_2x32_TO_64(e_sc_counters.sc_encrypted_octets); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci return 0; 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic int aq_mdo_dev_open(struct macsec_context *ctx) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 29362306a36Sopenharmony_ci int ret = 0; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev)) 29662306a36Sopenharmony_ci ret = aq_apply_secy_cfg(nic, ctx->secy); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci return ret; 29962306a36Sopenharmony_ci} 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic int aq_mdo_dev_stop(struct macsec_context *ctx) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 30462306a36Sopenharmony_ci int i; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 30762306a36Sopenharmony_ci if (nic->macsec_cfg->txsc_idx_busy & BIT(i)) 30862306a36Sopenharmony_ci aq_clear_secy(nic, nic->macsec_cfg->aq_txsc[i].sw_secy, 30962306a36Sopenharmony_ci AQ_CLEAR_HW); 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci return 0; 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic int aq_set_txsc(struct aq_nic_s *nic, const int txsc_idx) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc = &nic->macsec_cfg->aq_txsc[txsc_idx]; 31862306a36Sopenharmony_ci struct aq_mss_egress_class_record tx_class_rec = { 0 }; 31962306a36Sopenharmony_ci const struct macsec_secy *secy = aq_txsc->sw_secy; 32062306a36Sopenharmony_ci struct aq_mss_egress_sc_record sc_rec = { 0 }; 32162306a36Sopenharmony_ci unsigned int sc_idx = aq_txsc->hw_sc_idx; 32262306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 32362306a36Sopenharmony_ci int ret = 0; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci aq_ether_addr_to_mac(tx_class_rec.mac_sa, secy->netdev->dev_addr); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci put_unaligned_be64((__force u64)secy->sci, tx_class_rec.sci); 32862306a36Sopenharmony_ci tx_class_rec.sci_mask = 0; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci tx_class_rec.sa_mask = 0x3f; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci tx_class_rec.action = 0; /* forward to SA/SC table */ 33362306a36Sopenharmony_ci tx_class_rec.valid = 1; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci tx_class_rec.sc_idx = sc_idx; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci tx_class_rec.sc_sa = nic->macsec_cfg->sc_sa; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci ret = aq_mss_set_egress_class_record(hw, &tx_class_rec, txsc_idx); 34062306a36Sopenharmony_ci if (ret) 34162306a36Sopenharmony_ci return ret; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci sc_rec.protect = secy->protect_frames; 34462306a36Sopenharmony_ci if (secy->tx_sc.encrypt) 34562306a36Sopenharmony_ci sc_rec.tci |= BIT(1); 34662306a36Sopenharmony_ci if (secy->tx_sc.scb) 34762306a36Sopenharmony_ci sc_rec.tci |= BIT(2); 34862306a36Sopenharmony_ci if (secy->tx_sc.send_sci) 34962306a36Sopenharmony_ci sc_rec.tci |= BIT(3); 35062306a36Sopenharmony_ci if (secy->tx_sc.end_station) 35162306a36Sopenharmony_ci sc_rec.tci |= BIT(4); 35262306a36Sopenharmony_ci /* The C bit is clear if and only if the Secure Data is 35362306a36Sopenharmony_ci * exactly the same as the User Data and the ICV is 16 octets long. 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_ci if (!(secy->icv_len == 16 && !secy->tx_sc.encrypt)) 35662306a36Sopenharmony_ci sc_rec.tci |= BIT(0); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci sc_rec.an_roll = 0; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci switch (secy->key_len) { 36162306a36Sopenharmony_ci case AQ_MACSEC_KEY_LEN_128_BIT: 36262306a36Sopenharmony_ci sc_rec.sak_len = 0; 36362306a36Sopenharmony_ci break; 36462306a36Sopenharmony_ci case AQ_MACSEC_KEY_LEN_192_BIT: 36562306a36Sopenharmony_ci sc_rec.sak_len = 1; 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci case AQ_MACSEC_KEY_LEN_256_BIT: 36862306a36Sopenharmony_ci sc_rec.sak_len = 2; 36962306a36Sopenharmony_ci break; 37062306a36Sopenharmony_ci default: 37162306a36Sopenharmony_ci WARN_ONCE(true, "Invalid sc_sa"); 37262306a36Sopenharmony_ci return -EINVAL; 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci sc_rec.curr_an = secy->tx_sc.encoding_sa; 37662306a36Sopenharmony_ci sc_rec.valid = 1; 37762306a36Sopenharmony_ci sc_rec.fresh = 1; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci return aq_mss_set_egress_sc_record(hw, &sc_rec, sc_idx); 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic u32 aq_sc_idx_max(const enum aq_macsec_sc_sa sc_sa) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci u32 result = 0; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci switch (sc_sa) { 38762306a36Sopenharmony_ci case aq_macsec_sa_sc_4sa_8sc: 38862306a36Sopenharmony_ci result = 8; 38962306a36Sopenharmony_ci break; 39062306a36Sopenharmony_ci case aq_macsec_sa_sc_2sa_16sc: 39162306a36Sopenharmony_ci result = 16; 39262306a36Sopenharmony_ci break; 39362306a36Sopenharmony_ci case aq_macsec_sa_sc_1sa_32sc: 39462306a36Sopenharmony_ci result = 32; 39562306a36Sopenharmony_ci break; 39662306a36Sopenharmony_ci default: 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci return result; 40162306a36Sopenharmony_ci} 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_cistatic u32 aq_to_hw_sc_idx(const u32 sc_idx, const enum aq_macsec_sc_sa sc_sa) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci switch (sc_sa) { 40662306a36Sopenharmony_ci case aq_macsec_sa_sc_4sa_8sc: 40762306a36Sopenharmony_ci return sc_idx << 2; 40862306a36Sopenharmony_ci case aq_macsec_sa_sc_2sa_16sc: 40962306a36Sopenharmony_ci return sc_idx << 1; 41062306a36Sopenharmony_ci case aq_macsec_sa_sc_1sa_32sc: 41162306a36Sopenharmony_ci return sc_idx; 41262306a36Sopenharmony_ci default: 41362306a36Sopenharmony_ci WARN_ONCE(true, "Invalid sc_sa"); 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci return sc_idx; 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic enum aq_macsec_sc_sa sc_sa_from_num_an(const int num_an) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci enum aq_macsec_sc_sa sc_sa = aq_macsec_sa_sc_not_used; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci switch (num_an) { 42462306a36Sopenharmony_ci case 4: 42562306a36Sopenharmony_ci sc_sa = aq_macsec_sa_sc_4sa_8sc; 42662306a36Sopenharmony_ci break; 42762306a36Sopenharmony_ci case 2: 42862306a36Sopenharmony_ci sc_sa = aq_macsec_sa_sc_2sa_16sc; 42962306a36Sopenharmony_ci break; 43062306a36Sopenharmony_ci case 1: 43162306a36Sopenharmony_ci sc_sa = aq_macsec_sa_sc_1sa_32sc; 43262306a36Sopenharmony_ci break; 43362306a36Sopenharmony_ci default: 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci return sc_sa; 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_cistatic int aq_mdo_add_secy(struct macsec_context *ctx) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 44362306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 44462306a36Sopenharmony_ci const struct macsec_secy *secy = ctx->secy; 44562306a36Sopenharmony_ci enum aq_macsec_sc_sa sc_sa; 44662306a36Sopenharmony_ci u32 txsc_idx; 44762306a36Sopenharmony_ci int ret = 0; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci if (secy->xpn) 45062306a36Sopenharmony_ci return -EOPNOTSUPP; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci sc_sa = sc_sa_from_num_an(MACSEC_NUM_AN); 45362306a36Sopenharmony_ci if (sc_sa == aq_macsec_sa_sc_not_used) 45462306a36Sopenharmony_ci return -EINVAL; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (hweight32(cfg->txsc_idx_busy) >= aq_sc_idx_max(sc_sa)) 45762306a36Sopenharmony_ci return -ENOSPC; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci txsc_idx = ffz(cfg->txsc_idx_busy); 46062306a36Sopenharmony_ci if (txsc_idx == AQ_MACSEC_MAX_SC) 46162306a36Sopenharmony_ci return -ENOSPC; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci cfg->sc_sa = sc_sa; 46462306a36Sopenharmony_ci cfg->aq_txsc[txsc_idx].hw_sc_idx = aq_to_hw_sc_idx(txsc_idx, sc_sa); 46562306a36Sopenharmony_ci cfg->aq_txsc[txsc_idx].sw_secy = secy; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev) && netif_running(secy->netdev)) 46862306a36Sopenharmony_ci ret = aq_set_txsc(nic, txsc_idx); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci set_bit(txsc_idx, &cfg->txsc_idx_busy); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci return ret; 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic int aq_mdo_upd_secy(struct macsec_context *ctx) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 47862306a36Sopenharmony_ci const struct macsec_secy *secy = ctx->secy; 47962306a36Sopenharmony_ci int txsc_idx; 48062306a36Sopenharmony_ci int ret = 0; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_secy(nic->macsec_cfg, secy); 48362306a36Sopenharmony_ci if (txsc_idx < 0) 48462306a36Sopenharmony_ci return -ENOENT; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev) && netif_running(secy->netdev)) 48762306a36Sopenharmony_ci ret = aq_set_txsc(nic, txsc_idx); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci return ret; 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistatic int aq_clear_txsc(struct aq_nic_s *nic, const int txsc_idx, 49362306a36Sopenharmony_ci enum aq_clear_type clear_type) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci struct aq_macsec_txsc *tx_sc = &nic->macsec_cfg->aq_txsc[txsc_idx]; 49662306a36Sopenharmony_ci struct aq_mss_egress_class_record tx_class_rec = { 0 }; 49762306a36Sopenharmony_ci struct aq_mss_egress_sc_record sc_rec = { 0 }; 49862306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 49962306a36Sopenharmony_ci int ret = 0; 50062306a36Sopenharmony_ci int sa_num; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci for_each_set_bit (sa_num, &tx_sc->tx_sa_idx_busy, AQ_MACSEC_MAX_SA) { 50362306a36Sopenharmony_ci ret = aq_clear_txsa(nic, tx_sc, sa_num, clear_type); 50462306a36Sopenharmony_ci if (ret) 50562306a36Sopenharmony_ci return ret; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (clear_type & AQ_CLEAR_HW) { 50962306a36Sopenharmony_ci ret = aq_mss_set_egress_class_record(hw, &tx_class_rec, 51062306a36Sopenharmony_ci txsc_idx); 51162306a36Sopenharmony_ci if (ret) 51262306a36Sopenharmony_ci return ret; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci sc_rec.fresh = 1; 51562306a36Sopenharmony_ci ret = aq_mss_set_egress_sc_record(hw, &sc_rec, 51662306a36Sopenharmony_ci tx_sc->hw_sc_idx); 51762306a36Sopenharmony_ci if (ret) 51862306a36Sopenharmony_ci return ret; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (clear_type & AQ_CLEAR_SW) { 52262306a36Sopenharmony_ci clear_bit(txsc_idx, &nic->macsec_cfg->txsc_idx_busy); 52362306a36Sopenharmony_ci nic->macsec_cfg->aq_txsc[txsc_idx].sw_secy = NULL; 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci return ret; 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic int aq_mdo_del_secy(struct macsec_context *ctx) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 53262306a36Sopenharmony_ci int ret = 0; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (!nic->macsec_cfg) 53562306a36Sopenharmony_ci return 0; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci ret = aq_clear_secy(nic, ctx->secy, AQ_CLEAR_ALL); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci return ret; 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic int aq_update_txsa(struct aq_nic_s *nic, const unsigned int sc_idx, 54362306a36Sopenharmony_ci const struct macsec_secy *secy, 54462306a36Sopenharmony_ci const struct macsec_tx_sa *tx_sa, 54562306a36Sopenharmony_ci const unsigned char *key, const unsigned char an) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci const u32 next_pn = tx_sa->next_pn_halves.lower; 54862306a36Sopenharmony_ci struct aq_mss_egress_sakey_record key_rec; 54962306a36Sopenharmony_ci const unsigned int sa_idx = sc_idx | an; 55062306a36Sopenharmony_ci struct aq_mss_egress_sa_record sa_rec; 55162306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 55262306a36Sopenharmony_ci int ret = 0; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci memset(&sa_rec, 0, sizeof(sa_rec)); 55562306a36Sopenharmony_ci sa_rec.valid = tx_sa->active; 55662306a36Sopenharmony_ci sa_rec.fresh = 1; 55762306a36Sopenharmony_ci sa_rec.next_pn = next_pn; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci ret = aq_mss_set_egress_sa_record(hw, &sa_rec, sa_idx); 56062306a36Sopenharmony_ci if (ret) 56162306a36Sopenharmony_ci return ret; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (!key) 56462306a36Sopenharmony_ci return ret; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci memset(&key_rec, 0, sizeof(key_rec)); 56762306a36Sopenharmony_ci memcpy(&key_rec.key, key, secy->key_len); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci aq_rotate_keys(&key_rec.key, secy->key_len); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci ret = aq_mss_set_egress_sakey_record(hw, &key_rec, sa_idx); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci memzero_explicit(&key_rec, sizeof(key_rec)); 57462306a36Sopenharmony_ci return ret; 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistatic int aq_mdo_add_txsa(struct macsec_context *ctx) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 58062306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 58162306a36Sopenharmony_ci const struct macsec_secy *secy = ctx->secy; 58262306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc; 58362306a36Sopenharmony_ci int txsc_idx; 58462306a36Sopenharmony_ci int ret = 0; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_secy(cfg, secy); 58762306a36Sopenharmony_ci if (txsc_idx < 0) 58862306a36Sopenharmony_ci return -EINVAL; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci aq_txsc = &cfg->aq_txsc[txsc_idx]; 59162306a36Sopenharmony_ci set_bit(ctx->sa.assoc_num, &aq_txsc->tx_sa_idx_busy); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci memcpy(aq_txsc->tx_sa_key[ctx->sa.assoc_num], ctx->sa.key, 59462306a36Sopenharmony_ci secy->key_len); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev) && netif_running(secy->netdev)) 59762306a36Sopenharmony_ci ret = aq_update_txsa(nic, aq_txsc->hw_sc_idx, secy, 59862306a36Sopenharmony_ci ctx->sa.tx_sa, ctx->sa.key, 59962306a36Sopenharmony_ci ctx->sa.assoc_num); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci return ret; 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_cistatic int aq_mdo_upd_txsa(struct macsec_context *ctx) 60562306a36Sopenharmony_ci{ 60662306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 60762306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 60862306a36Sopenharmony_ci const struct macsec_secy *secy = ctx->secy; 60962306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc; 61062306a36Sopenharmony_ci int txsc_idx; 61162306a36Sopenharmony_ci int ret = 0; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_secy(cfg, secy); 61462306a36Sopenharmony_ci if (txsc_idx < 0) 61562306a36Sopenharmony_ci return -EINVAL; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci aq_txsc = &cfg->aq_txsc[txsc_idx]; 61862306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev) && netif_running(secy->netdev)) 61962306a36Sopenharmony_ci ret = aq_update_txsa(nic, aq_txsc->hw_sc_idx, secy, 62062306a36Sopenharmony_ci ctx->sa.tx_sa, NULL, ctx->sa.assoc_num); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci return ret; 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_cistatic int aq_clear_txsa(struct aq_nic_s *nic, struct aq_macsec_txsc *aq_txsc, 62662306a36Sopenharmony_ci const int sa_num, enum aq_clear_type clear_type) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci const int sa_idx = aq_txsc->hw_sc_idx | sa_num; 62962306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 63062306a36Sopenharmony_ci int ret = 0; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci if (clear_type & AQ_CLEAR_SW) 63362306a36Sopenharmony_ci clear_bit(sa_num, &aq_txsc->tx_sa_idx_busy); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci if ((clear_type & AQ_CLEAR_HW) && netif_carrier_ok(nic->ndev)) { 63662306a36Sopenharmony_ci struct aq_mss_egress_sakey_record key_rec; 63762306a36Sopenharmony_ci struct aq_mss_egress_sa_record sa_rec; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci memset(&sa_rec, 0, sizeof(sa_rec)); 64062306a36Sopenharmony_ci sa_rec.fresh = 1; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci ret = aq_mss_set_egress_sa_record(hw, &sa_rec, sa_idx); 64362306a36Sopenharmony_ci if (ret) 64462306a36Sopenharmony_ci return ret; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci memset(&key_rec, 0, sizeof(key_rec)); 64762306a36Sopenharmony_ci return aq_mss_set_egress_sakey_record(hw, &key_rec, sa_idx); 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci return 0; 65162306a36Sopenharmony_ci} 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_cistatic int aq_mdo_del_txsa(struct macsec_context *ctx) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 65662306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 65762306a36Sopenharmony_ci int txsc_idx; 65862306a36Sopenharmony_ci int ret = 0; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_secy(cfg, ctx->secy); 66162306a36Sopenharmony_ci if (txsc_idx < 0) 66262306a36Sopenharmony_ci return -EINVAL; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci ret = aq_clear_txsa(nic, &cfg->aq_txsc[txsc_idx], ctx->sa.assoc_num, 66562306a36Sopenharmony_ci AQ_CLEAR_ALL); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci return ret; 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic int aq_rxsc_validate_frames(const enum macsec_validation_type validate) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci switch (validate) { 67362306a36Sopenharmony_ci case MACSEC_VALIDATE_DISABLED: 67462306a36Sopenharmony_ci return 2; 67562306a36Sopenharmony_ci case MACSEC_VALIDATE_CHECK: 67662306a36Sopenharmony_ci return 1; 67762306a36Sopenharmony_ci case MACSEC_VALIDATE_STRICT: 67862306a36Sopenharmony_ci return 0; 67962306a36Sopenharmony_ci default: 68062306a36Sopenharmony_ci WARN_ONCE(true, "Invalid validation type"); 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci return 0; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic int aq_set_rxsc(struct aq_nic_s *nic, const u32 rxsc_idx) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci const struct aq_macsec_rxsc *aq_rxsc = 68962306a36Sopenharmony_ci &nic->macsec_cfg->aq_rxsc[rxsc_idx]; 69062306a36Sopenharmony_ci struct aq_mss_ingress_preclass_record pre_class_record; 69162306a36Sopenharmony_ci const struct macsec_rx_sc *rx_sc = aq_rxsc->sw_rxsc; 69262306a36Sopenharmony_ci const struct macsec_secy *secy = aq_rxsc->sw_secy; 69362306a36Sopenharmony_ci const u32 hw_sc_idx = aq_rxsc->hw_sc_idx; 69462306a36Sopenharmony_ci struct aq_mss_ingress_sc_record sc_record; 69562306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 69662306a36Sopenharmony_ci int ret = 0; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci memset(&pre_class_record, 0, sizeof(pre_class_record)); 69962306a36Sopenharmony_ci put_unaligned_be64((__force u64)rx_sc->sci, pre_class_record.sci); 70062306a36Sopenharmony_ci pre_class_record.sci_mask = 0xff; 70162306a36Sopenharmony_ci /* match all MACSEC ethertype packets */ 70262306a36Sopenharmony_ci pre_class_record.eth_type = ETH_P_MACSEC; 70362306a36Sopenharmony_ci pre_class_record.eth_type_mask = 0x3; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci aq_ether_addr_to_mac(pre_class_record.mac_sa, (char *)&rx_sc->sci); 70662306a36Sopenharmony_ci pre_class_record.sa_mask = 0x3f; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci pre_class_record.an_mask = nic->macsec_cfg->sc_sa; 70962306a36Sopenharmony_ci pre_class_record.sc_idx = hw_sc_idx; 71062306a36Sopenharmony_ci /* strip SecTAG & forward for decryption */ 71162306a36Sopenharmony_ci pre_class_record.action = 0x0; 71262306a36Sopenharmony_ci pre_class_record.valid = 1; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci ret = aq_mss_set_ingress_preclass_record(hw, &pre_class_record, 71562306a36Sopenharmony_ci 2 * rxsc_idx + 1); 71662306a36Sopenharmony_ci if (ret) 71762306a36Sopenharmony_ci return ret; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* If SCI is absent, then match by SA alone */ 72062306a36Sopenharmony_ci pre_class_record.sci_mask = 0; 72162306a36Sopenharmony_ci pre_class_record.sci_from_table = 1; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci ret = aq_mss_set_ingress_preclass_record(hw, &pre_class_record, 72462306a36Sopenharmony_ci 2 * rxsc_idx); 72562306a36Sopenharmony_ci if (ret) 72662306a36Sopenharmony_ci return ret; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci memset(&sc_record, 0, sizeof(sc_record)); 72962306a36Sopenharmony_ci sc_record.validate_frames = 73062306a36Sopenharmony_ci aq_rxsc_validate_frames(secy->validate_frames); 73162306a36Sopenharmony_ci if (secy->replay_protect) { 73262306a36Sopenharmony_ci sc_record.replay_protect = 1; 73362306a36Sopenharmony_ci sc_record.anti_replay_window = secy->replay_window; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci sc_record.valid = 1; 73662306a36Sopenharmony_ci sc_record.fresh = 1; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci ret = aq_mss_set_ingress_sc_record(hw, &sc_record, hw_sc_idx); 73962306a36Sopenharmony_ci if (ret) 74062306a36Sopenharmony_ci return ret; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci return ret; 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic int aq_mdo_add_rxsc(struct macsec_context *ctx) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 74862306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 74962306a36Sopenharmony_ci const u32 rxsc_idx_max = aq_sc_idx_max(cfg->sc_sa); 75062306a36Sopenharmony_ci u32 rxsc_idx; 75162306a36Sopenharmony_ci int ret = 0; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci if (hweight32(cfg->rxsc_idx_busy) >= rxsc_idx_max) 75462306a36Sopenharmony_ci return -ENOSPC; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci rxsc_idx = ffz(cfg->rxsc_idx_busy); 75762306a36Sopenharmony_ci if (rxsc_idx >= rxsc_idx_max) 75862306a36Sopenharmony_ci return -ENOSPC; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci cfg->aq_rxsc[rxsc_idx].hw_sc_idx = aq_to_hw_sc_idx(rxsc_idx, 76162306a36Sopenharmony_ci cfg->sc_sa); 76262306a36Sopenharmony_ci cfg->aq_rxsc[rxsc_idx].sw_secy = ctx->secy; 76362306a36Sopenharmony_ci cfg->aq_rxsc[rxsc_idx].sw_rxsc = ctx->rx_sc; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev) && netif_running(ctx->secy->netdev)) 76662306a36Sopenharmony_ci ret = aq_set_rxsc(nic, rxsc_idx); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci if (ret < 0) 76962306a36Sopenharmony_ci return ret; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci set_bit(rxsc_idx, &cfg->rxsc_idx_busy); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci return 0; 77462306a36Sopenharmony_ci} 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_cistatic int aq_mdo_upd_rxsc(struct macsec_context *ctx) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 77962306a36Sopenharmony_ci int rxsc_idx; 78062306a36Sopenharmony_ci int ret = 0; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(nic->macsec_cfg, ctx->rx_sc); 78362306a36Sopenharmony_ci if (rxsc_idx < 0) 78462306a36Sopenharmony_ci return -ENOENT; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev) && netif_running(ctx->secy->netdev)) 78762306a36Sopenharmony_ci ret = aq_set_rxsc(nic, rxsc_idx); 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci return ret; 79062306a36Sopenharmony_ci} 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic int aq_clear_rxsc(struct aq_nic_s *nic, const int rxsc_idx, 79362306a36Sopenharmony_ci enum aq_clear_type clear_type) 79462306a36Sopenharmony_ci{ 79562306a36Sopenharmony_ci struct aq_macsec_rxsc *rx_sc = &nic->macsec_cfg->aq_rxsc[rxsc_idx]; 79662306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 79762306a36Sopenharmony_ci int ret = 0; 79862306a36Sopenharmony_ci int sa_num; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci for_each_set_bit (sa_num, &rx_sc->rx_sa_idx_busy, AQ_MACSEC_MAX_SA) { 80162306a36Sopenharmony_ci ret = aq_clear_rxsa(nic, rx_sc, sa_num, clear_type); 80262306a36Sopenharmony_ci if (ret) 80362306a36Sopenharmony_ci return ret; 80462306a36Sopenharmony_ci } 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci if (clear_type & AQ_CLEAR_HW) { 80762306a36Sopenharmony_ci struct aq_mss_ingress_preclass_record pre_class_record; 80862306a36Sopenharmony_ci struct aq_mss_ingress_sc_record sc_record; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci memset(&pre_class_record, 0, sizeof(pre_class_record)); 81162306a36Sopenharmony_ci memset(&sc_record, 0, sizeof(sc_record)); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci ret = aq_mss_set_ingress_preclass_record(hw, &pre_class_record, 81462306a36Sopenharmony_ci 2 * rxsc_idx); 81562306a36Sopenharmony_ci if (ret) 81662306a36Sopenharmony_ci return ret; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci ret = aq_mss_set_ingress_preclass_record(hw, &pre_class_record, 81962306a36Sopenharmony_ci 2 * rxsc_idx + 1); 82062306a36Sopenharmony_ci if (ret) 82162306a36Sopenharmony_ci return ret; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci sc_record.fresh = 1; 82462306a36Sopenharmony_ci ret = aq_mss_set_ingress_sc_record(hw, &sc_record, 82562306a36Sopenharmony_ci rx_sc->hw_sc_idx); 82662306a36Sopenharmony_ci if (ret) 82762306a36Sopenharmony_ci return ret; 82862306a36Sopenharmony_ci } 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci if (clear_type & AQ_CLEAR_SW) { 83162306a36Sopenharmony_ci clear_bit(rxsc_idx, &nic->macsec_cfg->rxsc_idx_busy); 83262306a36Sopenharmony_ci rx_sc->sw_secy = NULL; 83362306a36Sopenharmony_ci rx_sc->sw_rxsc = NULL; 83462306a36Sopenharmony_ci } 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci return ret; 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_cistatic int aq_mdo_del_rxsc(struct macsec_context *ctx) 84062306a36Sopenharmony_ci{ 84162306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 84262306a36Sopenharmony_ci enum aq_clear_type clear_type = AQ_CLEAR_SW; 84362306a36Sopenharmony_ci int rxsc_idx; 84462306a36Sopenharmony_ci int ret = 0; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(nic->macsec_cfg, ctx->rx_sc); 84762306a36Sopenharmony_ci if (rxsc_idx < 0) 84862306a36Sopenharmony_ci return -ENOENT; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev)) 85162306a36Sopenharmony_ci clear_type = AQ_CLEAR_ALL; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci ret = aq_clear_rxsc(nic, rxsc_idx, clear_type); 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci return ret; 85662306a36Sopenharmony_ci} 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_cistatic int aq_update_rxsa(struct aq_nic_s *nic, const unsigned int sc_idx, 85962306a36Sopenharmony_ci const struct macsec_secy *secy, 86062306a36Sopenharmony_ci const struct macsec_rx_sa *rx_sa, 86162306a36Sopenharmony_ci const unsigned char *key, const unsigned char an) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci struct aq_mss_ingress_sakey_record sa_key_record; 86462306a36Sopenharmony_ci const u32 next_pn = rx_sa->next_pn_halves.lower; 86562306a36Sopenharmony_ci struct aq_mss_ingress_sa_record sa_record; 86662306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 86762306a36Sopenharmony_ci const int sa_idx = sc_idx | an; 86862306a36Sopenharmony_ci int ret = 0; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci memset(&sa_record, 0, sizeof(sa_record)); 87162306a36Sopenharmony_ci sa_record.valid = rx_sa->active; 87262306a36Sopenharmony_ci sa_record.fresh = 1; 87362306a36Sopenharmony_ci sa_record.next_pn = next_pn; 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci ret = aq_mss_set_ingress_sa_record(hw, &sa_record, sa_idx); 87662306a36Sopenharmony_ci if (ret) 87762306a36Sopenharmony_ci return ret; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci if (!key) 88062306a36Sopenharmony_ci return ret; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci memset(&sa_key_record, 0, sizeof(sa_key_record)); 88362306a36Sopenharmony_ci memcpy(&sa_key_record.key, key, secy->key_len); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci switch (secy->key_len) { 88662306a36Sopenharmony_ci case AQ_MACSEC_KEY_LEN_128_BIT: 88762306a36Sopenharmony_ci sa_key_record.key_len = 0; 88862306a36Sopenharmony_ci break; 88962306a36Sopenharmony_ci case AQ_MACSEC_KEY_LEN_192_BIT: 89062306a36Sopenharmony_ci sa_key_record.key_len = 1; 89162306a36Sopenharmony_ci break; 89262306a36Sopenharmony_ci case AQ_MACSEC_KEY_LEN_256_BIT: 89362306a36Sopenharmony_ci sa_key_record.key_len = 2; 89462306a36Sopenharmony_ci break; 89562306a36Sopenharmony_ci default: 89662306a36Sopenharmony_ci return -1; 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci aq_rotate_keys(&sa_key_record.key, secy->key_len); 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci ret = aq_mss_set_ingress_sakey_record(hw, &sa_key_record, sa_idx); 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci memzero_explicit(&sa_key_record, sizeof(sa_key_record)); 90462306a36Sopenharmony_ci return ret; 90562306a36Sopenharmony_ci} 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cistatic int aq_mdo_add_rxsa(struct macsec_context *ctx) 90862306a36Sopenharmony_ci{ 90962306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 91062306a36Sopenharmony_ci const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc; 91162306a36Sopenharmony_ci const struct macsec_secy *secy = ctx->secy; 91262306a36Sopenharmony_ci struct aq_macsec_rxsc *aq_rxsc; 91362306a36Sopenharmony_ci int rxsc_idx; 91462306a36Sopenharmony_ci int ret = 0; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(nic->macsec_cfg, rx_sc); 91762306a36Sopenharmony_ci if (rxsc_idx < 0) 91862306a36Sopenharmony_ci return -EINVAL; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci aq_rxsc = &nic->macsec_cfg->aq_rxsc[rxsc_idx]; 92162306a36Sopenharmony_ci set_bit(ctx->sa.assoc_num, &aq_rxsc->rx_sa_idx_busy); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci memcpy(aq_rxsc->rx_sa_key[ctx->sa.assoc_num], ctx->sa.key, 92462306a36Sopenharmony_ci secy->key_len); 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev) && netif_running(secy->netdev)) 92762306a36Sopenharmony_ci ret = aq_update_rxsa(nic, aq_rxsc->hw_sc_idx, secy, 92862306a36Sopenharmony_ci ctx->sa.rx_sa, ctx->sa.key, 92962306a36Sopenharmony_ci ctx->sa.assoc_num); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci return ret; 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cistatic int aq_mdo_upd_rxsa(struct macsec_context *ctx) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 93762306a36Sopenharmony_ci const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc; 93862306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 93962306a36Sopenharmony_ci const struct macsec_secy *secy = ctx->secy; 94062306a36Sopenharmony_ci int rxsc_idx; 94162306a36Sopenharmony_ci int ret = 0; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(cfg, rx_sc); 94462306a36Sopenharmony_ci if (rxsc_idx < 0) 94562306a36Sopenharmony_ci return -EINVAL; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci if (netif_carrier_ok(nic->ndev) && netif_running(secy->netdev)) 94862306a36Sopenharmony_ci ret = aq_update_rxsa(nic, cfg->aq_rxsc[rxsc_idx].hw_sc_idx, 94962306a36Sopenharmony_ci secy, ctx->sa.rx_sa, NULL, 95062306a36Sopenharmony_ci ctx->sa.assoc_num); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci return ret; 95362306a36Sopenharmony_ci} 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_cistatic int aq_clear_rxsa(struct aq_nic_s *nic, struct aq_macsec_rxsc *aq_rxsc, 95662306a36Sopenharmony_ci const int sa_num, enum aq_clear_type clear_type) 95762306a36Sopenharmony_ci{ 95862306a36Sopenharmony_ci int sa_idx = aq_rxsc->hw_sc_idx | sa_num; 95962306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 96062306a36Sopenharmony_ci int ret = 0; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci if (clear_type & AQ_CLEAR_SW) 96362306a36Sopenharmony_ci clear_bit(sa_num, &aq_rxsc->rx_sa_idx_busy); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci if ((clear_type & AQ_CLEAR_HW) && netif_carrier_ok(nic->ndev)) { 96662306a36Sopenharmony_ci struct aq_mss_ingress_sakey_record sa_key_record; 96762306a36Sopenharmony_ci struct aq_mss_ingress_sa_record sa_record; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci memset(&sa_key_record, 0, sizeof(sa_key_record)); 97062306a36Sopenharmony_ci memset(&sa_record, 0, sizeof(sa_record)); 97162306a36Sopenharmony_ci sa_record.fresh = 1; 97262306a36Sopenharmony_ci ret = aq_mss_set_ingress_sa_record(hw, &sa_record, sa_idx); 97362306a36Sopenharmony_ci if (ret) 97462306a36Sopenharmony_ci return ret; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci return aq_mss_set_ingress_sakey_record(hw, &sa_key_record, 97762306a36Sopenharmony_ci sa_idx); 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci return ret; 98162306a36Sopenharmony_ci} 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_cistatic int aq_mdo_del_rxsa(struct macsec_context *ctx) 98462306a36Sopenharmony_ci{ 98562306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 98662306a36Sopenharmony_ci const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc; 98762306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 98862306a36Sopenharmony_ci int rxsc_idx; 98962306a36Sopenharmony_ci int ret = 0; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(cfg, rx_sc); 99262306a36Sopenharmony_ci if (rxsc_idx < 0) 99362306a36Sopenharmony_ci return -EINVAL; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci ret = aq_clear_rxsa(nic, &cfg->aq_rxsc[rxsc_idx], ctx->sa.assoc_num, 99662306a36Sopenharmony_ci AQ_CLEAR_ALL); 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci return ret; 99962306a36Sopenharmony_ci} 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_cistatic int aq_mdo_get_dev_stats(struct macsec_context *ctx) 100262306a36Sopenharmony_ci{ 100362306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 100462306a36Sopenharmony_ci struct aq_macsec_common_stats *stats = &nic->macsec_cfg->stats; 100562306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci aq_get_macsec_common_stats(hw, stats); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci ctx->stats.dev_stats->OutPktsUntagged = stats->out.untagged_pkts; 101062306a36Sopenharmony_ci ctx->stats.dev_stats->InPktsUntagged = stats->in.untagged_pkts; 101162306a36Sopenharmony_ci ctx->stats.dev_stats->OutPktsTooLong = stats->out.too_long; 101262306a36Sopenharmony_ci ctx->stats.dev_stats->InPktsNoTag = stats->in.notag_pkts; 101362306a36Sopenharmony_ci ctx->stats.dev_stats->InPktsBadTag = stats->in.bad_tag_pkts; 101462306a36Sopenharmony_ci ctx->stats.dev_stats->InPktsUnknownSCI = stats->in.unknown_sci_pkts; 101562306a36Sopenharmony_ci ctx->stats.dev_stats->InPktsNoSCI = stats->in.no_sci_pkts; 101662306a36Sopenharmony_ci ctx->stats.dev_stats->InPktsOverrun = 0; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci return 0; 101962306a36Sopenharmony_ci} 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_cistatic int aq_mdo_get_tx_sc_stats(struct macsec_context *ctx) 102262306a36Sopenharmony_ci{ 102362306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 102462306a36Sopenharmony_ci struct aq_macsec_tx_sc_stats *stats; 102562306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 102662306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc; 102762306a36Sopenharmony_ci int txsc_idx; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_secy(nic->macsec_cfg, ctx->secy); 103062306a36Sopenharmony_ci if (txsc_idx < 0) 103162306a36Sopenharmony_ci return -ENOENT; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci aq_txsc = &nic->macsec_cfg->aq_txsc[txsc_idx]; 103462306a36Sopenharmony_ci stats = &aq_txsc->stats; 103562306a36Sopenharmony_ci aq_get_txsc_stats(hw, aq_txsc->hw_sc_idx, stats); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci ctx->stats.tx_sc_stats->OutPktsProtected = stats->sc_protected_pkts; 103862306a36Sopenharmony_ci ctx->stats.tx_sc_stats->OutPktsEncrypted = stats->sc_encrypted_pkts; 103962306a36Sopenharmony_ci ctx->stats.tx_sc_stats->OutOctetsProtected = stats->sc_protected_octets; 104062306a36Sopenharmony_ci ctx->stats.tx_sc_stats->OutOctetsEncrypted = stats->sc_encrypted_octets; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci return 0; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_cistatic int aq_mdo_get_tx_sa_stats(struct macsec_context *ctx) 104662306a36Sopenharmony_ci{ 104762306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 104862306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 104962306a36Sopenharmony_ci struct aq_macsec_tx_sa_stats *stats; 105062306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 105162306a36Sopenharmony_ci const struct macsec_secy *secy; 105262306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc; 105362306a36Sopenharmony_ci struct macsec_tx_sa *tx_sa; 105462306a36Sopenharmony_ci unsigned int sa_idx; 105562306a36Sopenharmony_ci int txsc_idx; 105662306a36Sopenharmony_ci u32 next_pn; 105762306a36Sopenharmony_ci int ret; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_secy(cfg, ctx->secy); 106062306a36Sopenharmony_ci if (txsc_idx < 0) 106162306a36Sopenharmony_ci return -EINVAL; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci aq_txsc = &cfg->aq_txsc[txsc_idx]; 106462306a36Sopenharmony_ci sa_idx = aq_txsc->hw_sc_idx | ctx->sa.assoc_num; 106562306a36Sopenharmony_ci stats = &aq_txsc->tx_sa_stats[ctx->sa.assoc_num]; 106662306a36Sopenharmony_ci ret = aq_get_txsa_stats(hw, sa_idx, stats); 106762306a36Sopenharmony_ci if (ret) 106862306a36Sopenharmony_ci return ret; 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci ctx->stats.tx_sa_stats->OutPktsProtected = stats->sa_protected_pkts; 107162306a36Sopenharmony_ci ctx->stats.tx_sa_stats->OutPktsEncrypted = stats->sa_encrypted_pkts; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci secy = aq_txsc->sw_secy; 107462306a36Sopenharmony_ci tx_sa = rcu_dereference_bh(secy->tx_sc.sa[ctx->sa.assoc_num]); 107562306a36Sopenharmony_ci ret = aq_get_txsa_next_pn(hw, sa_idx, &next_pn); 107662306a36Sopenharmony_ci if (ret == 0) { 107762306a36Sopenharmony_ci spin_lock_bh(&tx_sa->lock); 107862306a36Sopenharmony_ci tx_sa->next_pn = next_pn; 107962306a36Sopenharmony_ci spin_unlock_bh(&tx_sa->lock); 108062306a36Sopenharmony_ci } 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci return ret; 108362306a36Sopenharmony_ci} 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_cistatic int aq_mdo_get_rx_sc_stats(struct macsec_context *ctx) 108662306a36Sopenharmony_ci{ 108762306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 108862306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 108962306a36Sopenharmony_ci struct aq_macsec_rx_sa_stats *stats; 109062306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 109162306a36Sopenharmony_ci struct aq_macsec_rxsc *aq_rxsc; 109262306a36Sopenharmony_ci unsigned int sa_idx; 109362306a36Sopenharmony_ci int rxsc_idx; 109462306a36Sopenharmony_ci int ret = 0; 109562306a36Sopenharmony_ci int i; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(cfg, ctx->rx_sc); 109862306a36Sopenharmony_ci if (rxsc_idx < 0) 109962306a36Sopenharmony_ci return -ENOENT; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci aq_rxsc = &cfg->aq_rxsc[rxsc_idx]; 110262306a36Sopenharmony_ci for (i = 0; i < MACSEC_NUM_AN; i++) { 110362306a36Sopenharmony_ci if (!test_bit(i, &aq_rxsc->rx_sa_idx_busy)) 110462306a36Sopenharmony_ci continue; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci stats = &aq_rxsc->rx_sa_stats[i]; 110762306a36Sopenharmony_ci sa_idx = aq_rxsc->hw_sc_idx | i; 110862306a36Sopenharmony_ci ret = aq_get_rxsa_stats(hw, sa_idx, stats); 110962306a36Sopenharmony_ci if (ret) 111062306a36Sopenharmony_ci break; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InOctetsValidated += 111362306a36Sopenharmony_ci stats->validated_octets; 111462306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InOctetsDecrypted += 111562306a36Sopenharmony_ci stats->decrypted_octets; 111662306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InPktsUnchecked += 111762306a36Sopenharmony_ci stats->unchecked_pkts; 111862306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InPktsDelayed += stats->delayed_pkts; 111962306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InPktsOK += stats->ok_pkts; 112062306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InPktsInvalid += stats->invalid_pkts; 112162306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InPktsLate += stats->late_pkts; 112262306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InPktsNotValid += stats->not_valid_pkts; 112362306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InPktsNotUsingSA += stats->not_using_sa; 112462306a36Sopenharmony_ci ctx->stats.rx_sc_stats->InPktsUnusedSA += stats->unused_sa; 112562306a36Sopenharmony_ci } 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci return ret; 112862306a36Sopenharmony_ci} 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_cistatic int aq_mdo_get_rx_sa_stats(struct macsec_context *ctx) 113162306a36Sopenharmony_ci{ 113262306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); 113362306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 113462306a36Sopenharmony_ci struct aq_macsec_rx_sa_stats *stats; 113562306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 113662306a36Sopenharmony_ci struct aq_macsec_rxsc *aq_rxsc; 113762306a36Sopenharmony_ci struct macsec_rx_sa *rx_sa; 113862306a36Sopenharmony_ci unsigned int sa_idx; 113962306a36Sopenharmony_ci int rxsc_idx; 114062306a36Sopenharmony_ci u32 next_pn; 114162306a36Sopenharmony_ci int ret; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(cfg, ctx->rx_sc); 114462306a36Sopenharmony_ci if (rxsc_idx < 0) 114562306a36Sopenharmony_ci return -EINVAL; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci aq_rxsc = &cfg->aq_rxsc[rxsc_idx]; 114862306a36Sopenharmony_ci stats = &aq_rxsc->rx_sa_stats[ctx->sa.assoc_num]; 114962306a36Sopenharmony_ci sa_idx = aq_rxsc->hw_sc_idx | ctx->sa.assoc_num; 115062306a36Sopenharmony_ci ret = aq_get_rxsa_stats(hw, sa_idx, stats); 115162306a36Sopenharmony_ci if (ret) 115262306a36Sopenharmony_ci return ret; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci ctx->stats.rx_sa_stats->InPktsOK = stats->ok_pkts; 115562306a36Sopenharmony_ci ctx->stats.rx_sa_stats->InPktsInvalid = stats->invalid_pkts; 115662306a36Sopenharmony_ci ctx->stats.rx_sa_stats->InPktsNotValid = stats->not_valid_pkts; 115762306a36Sopenharmony_ci ctx->stats.rx_sa_stats->InPktsNotUsingSA = stats->not_using_sa; 115862306a36Sopenharmony_ci ctx->stats.rx_sa_stats->InPktsUnusedSA = stats->unused_sa; 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci rx_sa = rcu_dereference_bh(aq_rxsc->sw_rxsc->sa[ctx->sa.assoc_num]); 116162306a36Sopenharmony_ci ret = aq_get_rxsa_next_pn(hw, sa_idx, &next_pn); 116262306a36Sopenharmony_ci if (ret == 0) { 116362306a36Sopenharmony_ci spin_lock_bh(&rx_sa->lock); 116462306a36Sopenharmony_ci rx_sa->next_pn = next_pn; 116562306a36Sopenharmony_ci spin_unlock_bh(&rx_sa->lock); 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci return ret; 116962306a36Sopenharmony_ci} 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_cistatic int apply_txsc_cfg(struct aq_nic_s *nic, const int txsc_idx) 117262306a36Sopenharmony_ci{ 117362306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc = &nic->macsec_cfg->aq_txsc[txsc_idx]; 117462306a36Sopenharmony_ci const struct macsec_secy *secy = aq_txsc->sw_secy; 117562306a36Sopenharmony_ci struct macsec_tx_sa *tx_sa; 117662306a36Sopenharmony_ci int ret = 0; 117762306a36Sopenharmony_ci int i; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci if (!netif_running(secy->netdev)) 118062306a36Sopenharmony_ci return ret; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci ret = aq_set_txsc(nic, txsc_idx); 118362306a36Sopenharmony_ci if (ret) 118462306a36Sopenharmony_ci return ret; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci for (i = 0; i < MACSEC_NUM_AN; i++) { 118762306a36Sopenharmony_ci tx_sa = rcu_dereference_bh(secy->tx_sc.sa[i]); 118862306a36Sopenharmony_ci if (tx_sa) { 118962306a36Sopenharmony_ci ret = aq_update_txsa(nic, aq_txsc->hw_sc_idx, secy, 119062306a36Sopenharmony_ci tx_sa, aq_txsc->tx_sa_key[i], i); 119162306a36Sopenharmony_ci if (ret) 119262306a36Sopenharmony_ci return ret; 119362306a36Sopenharmony_ci } 119462306a36Sopenharmony_ci } 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci return ret; 119762306a36Sopenharmony_ci} 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_cistatic int apply_rxsc_cfg(struct aq_nic_s *nic, const int rxsc_idx) 120062306a36Sopenharmony_ci{ 120162306a36Sopenharmony_ci struct aq_macsec_rxsc *aq_rxsc = &nic->macsec_cfg->aq_rxsc[rxsc_idx]; 120262306a36Sopenharmony_ci const struct macsec_secy *secy = aq_rxsc->sw_secy; 120362306a36Sopenharmony_ci struct macsec_rx_sa *rx_sa; 120462306a36Sopenharmony_ci int ret = 0; 120562306a36Sopenharmony_ci int i; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci if (!netif_running(secy->netdev)) 120862306a36Sopenharmony_ci return ret; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci ret = aq_set_rxsc(nic, rxsc_idx); 121162306a36Sopenharmony_ci if (ret) 121262306a36Sopenharmony_ci return ret; 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci for (i = 0; i < MACSEC_NUM_AN; i++) { 121562306a36Sopenharmony_ci rx_sa = rcu_dereference_bh(aq_rxsc->sw_rxsc->sa[i]); 121662306a36Sopenharmony_ci if (rx_sa) { 121762306a36Sopenharmony_ci ret = aq_update_rxsa(nic, aq_rxsc->hw_sc_idx, secy, 121862306a36Sopenharmony_ci rx_sa, aq_rxsc->rx_sa_key[i], i); 121962306a36Sopenharmony_ci if (ret) 122062306a36Sopenharmony_ci return ret; 122162306a36Sopenharmony_ci } 122262306a36Sopenharmony_ci } 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci return ret; 122562306a36Sopenharmony_ci} 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_cistatic int aq_clear_secy(struct aq_nic_s *nic, const struct macsec_secy *secy, 122862306a36Sopenharmony_ci enum aq_clear_type clear_type) 122962306a36Sopenharmony_ci{ 123062306a36Sopenharmony_ci struct macsec_rx_sc *rx_sc; 123162306a36Sopenharmony_ci int txsc_idx; 123262306a36Sopenharmony_ci int rxsc_idx; 123362306a36Sopenharmony_ci int ret = 0; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_secy(nic->macsec_cfg, secy); 123662306a36Sopenharmony_ci if (txsc_idx >= 0) { 123762306a36Sopenharmony_ci ret = aq_clear_txsc(nic, txsc_idx, clear_type); 123862306a36Sopenharmony_ci if (ret) 123962306a36Sopenharmony_ci return ret; 124062306a36Sopenharmony_ci } 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci for (rx_sc = rcu_dereference_bh(secy->rx_sc); rx_sc; 124362306a36Sopenharmony_ci rx_sc = rcu_dereference_bh(rx_sc->next)) { 124462306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(nic->macsec_cfg, rx_sc); 124562306a36Sopenharmony_ci if (rxsc_idx < 0) 124662306a36Sopenharmony_ci continue; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci ret = aq_clear_rxsc(nic, rxsc_idx, clear_type); 124962306a36Sopenharmony_ci if (ret) 125062306a36Sopenharmony_ci return ret; 125162306a36Sopenharmony_ci } 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci return ret; 125462306a36Sopenharmony_ci} 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_cistatic int aq_apply_secy_cfg(struct aq_nic_s *nic, 125762306a36Sopenharmony_ci const struct macsec_secy *secy) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci struct macsec_rx_sc *rx_sc; 126062306a36Sopenharmony_ci int txsc_idx; 126162306a36Sopenharmony_ci int rxsc_idx; 126262306a36Sopenharmony_ci int ret = 0; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_secy(nic->macsec_cfg, secy); 126562306a36Sopenharmony_ci if (txsc_idx >= 0) 126662306a36Sopenharmony_ci apply_txsc_cfg(nic, txsc_idx); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci for (rx_sc = rcu_dereference_bh(secy->rx_sc); rx_sc && rx_sc->active; 126962306a36Sopenharmony_ci rx_sc = rcu_dereference_bh(rx_sc->next)) { 127062306a36Sopenharmony_ci rxsc_idx = aq_get_rxsc_idx_from_rxsc(nic->macsec_cfg, rx_sc); 127162306a36Sopenharmony_ci if (unlikely(rxsc_idx < 0)) 127262306a36Sopenharmony_ci continue; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci ret = apply_rxsc_cfg(nic, rxsc_idx); 127562306a36Sopenharmony_ci if (ret) 127662306a36Sopenharmony_ci return ret; 127762306a36Sopenharmony_ci } 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci return ret; 128062306a36Sopenharmony_ci} 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_cistatic int aq_apply_macsec_cfg(struct aq_nic_s *nic) 128362306a36Sopenharmony_ci{ 128462306a36Sopenharmony_ci int ret = 0; 128562306a36Sopenharmony_ci int i; 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 128862306a36Sopenharmony_ci if (nic->macsec_cfg->txsc_idx_busy & BIT(i)) { 128962306a36Sopenharmony_ci ret = apply_txsc_cfg(nic, i); 129062306a36Sopenharmony_ci if (ret) 129162306a36Sopenharmony_ci return ret; 129262306a36Sopenharmony_ci } 129362306a36Sopenharmony_ci } 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 129662306a36Sopenharmony_ci if (nic->macsec_cfg->rxsc_idx_busy & BIT(i)) { 129762306a36Sopenharmony_ci ret = apply_rxsc_cfg(nic, i); 129862306a36Sopenharmony_ci if (ret) 129962306a36Sopenharmony_ci return ret; 130062306a36Sopenharmony_ci } 130162306a36Sopenharmony_ci } 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci return ret; 130462306a36Sopenharmony_ci} 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_cistatic int aq_sa_from_sa_idx(const enum aq_macsec_sc_sa sc_sa, const int sa_idx) 130762306a36Sopenharmony_ci{ 130862306a36Sopenharmony_ci switch (sc_sa) { 130962306a36Sopenharmony_ci case aq_macsec_sa_sc_4sa_8sc: 131062306a36Sopenharmony_ci return sa_idx & 3; 131162306a36Sopenharmony_ci case aq_macsec_sa_sc_2sa_16sc: 131262306a36Sopenharmony_ci return sa_idx & 1; 131362306a36Sopenharmony_ci case aq_macsec_sa_sc_1sa_32sc: 131462306a36Sopenharmony_ci return 0; 131562306a36Sopenharmony_ci default: 131662306a36Sopenharmony_ci WARN_ONCE(true, "Invalid sc_sa"); 131762306a36Sopenharmony_ci } 131862306a36Sopenharmony_ci return -EINVAL; 131962306a36Sopenharmony_ci} 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_cistatic int aq_sc_idx_from_sa_idx(const enum aq_macsec_sc_sa sc_sa, 132262306a36Sopenharmony_ci const int sa_idx) 132362306a36Sopenharmony_ci{ 132462306a36Sopenharmony_ci switch (sc_sa) { 132562306a36Sopenharmony_ci case aq_macsec_sa_sc_4sa_8sc: 132662306a36Sopenharmony_ci return sa_idx & ~3; 132762306a36Sopenharmony_ci case aq_macsec_sa_sc_2sa_16sc: 132862306a36Sopenharmony_ci return sa_idx & ~1; 132962306a36Sopenharmony_ci case aq_macsec_sa_sc_1sa_32sc: 133062306a36Sopenharmony_ci return sa_idx; 133162306a36Sopenharmony_ci default: 133262306a36Sopenharmony_ci WARN_ONCE(true, "Invalid sc_sa"); 133362306a36Sopenharmony_ci } 133462306a36Sopenharmony_ci return -EINVAL; 133562306a36Sopenharmony_ci} 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_cistatic void aq_check_txsa_expiration(struct aq_nic_s *nic) 133862306a36Sopenharmony_ci{ 133962306a36Sopenharmony_ci u32 egress_sa_expired, egress_sa_threshold_expired; 134062306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 134162306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 134262306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc; 134362306a36Sopenharmony_ci const struct macsec_secy *secy; 134462306a36Sopenharmony_ci int sc_idx = 0, txsc_idx = 0; 134562306a36Sopenharmony_ci enum aq_macsec_sc_sa sc_sa; 134662306a36Sopenharmony_ci struct macsec_tx_sa *tx_sa; 134762306a36Sopenharmony_ci unsigned char an = 0; 134862306a36Sopenharmony_ci int ret; 134962306a36Sopenharmony_ci int i; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci sc_sa = cfg->sc_sa; 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci ret = aq_mss_get_egress_sa_expired(hw, &egress_sa_expired); 135462306a36Sopenharmony_ci if (unlikely(ret)) 135562306a36Sopenharmony_ci return; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci ret = aq_mss_get_egress_sa_threshold_expired(hw, 135862306a36Sopenharmony_ci &egress_sa_threshold_expired); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SA; i++) { 136162306a36Sopenharmony_ci if (egress_sa_expired & BIT(i)) { 136262306a36Sopenharmony_ci an = aq_sa_from_sa_idx(sc_sa, i); 136362306a36Sopenharmony_ci sc_idx = aq_sc_idx_from_sa_idx(sc_sa, i); 136462306a36Sopenharmony_ci txsc_idx = aq_get_txsc_idx_from_sc_idx(sc_sa, sc_idx); 136562306a36Sopenharmony_ci if (txsc_idx < 0) 136662306a36Sopenharmony_ci continue; 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci aq_txsc = &cfg->aq_txsc[txsc_idx]; 136962306a36Sopenharmony_ci if (!(cfg->txsc_idx_busy & BIT(txsc_idx))) { 137062306a36Sopenharmony_ci netdev_warn(nic->ndev, 137162306a36Sopenharmony_ci "PN threshold expired on invalid TX SC"); 137262306a36Sopenharmony_ci continue; 137362306a36Sopenharmony_ci } 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci secy = aq_txsc->sw_secy; 137662306a36Sopenharmony_ci if (!netif_running(secy->netdev)) { 137762306a36Sopenharmony_ci netdev_warn(nic->ndev, 137862306a36Sopenharmony_ci "PN threshold expired on down TX SC"); 137962306a36Sopenharmony_ci continue; 138062306a36Sopenharmony_ci } 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci if (unlikely(!(aq_txsc->tx_sa_idx_busy & BIT(an)))) { 138362306a36Sopenharmony_ci netdev_warn(nic->ndev, 138462306a36Sopenharmony_ci "PN threshold expired on invalid TX SA"); 138562306a36Sopenharmony_ci continue; 138662306a36Sopenharmony_ci } 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci tx_sa = rcu_dereference_bh(secy->tx_sc.sa[an]); 138962306a36Sopenharmony_ci macsec_pn_wrapped((struct macsec_secy *)secy, tx_sa); 139062306a36Sopenharmony_ci } 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci aq_mss_set_egress_sa_expired(hw, egress_sa_expired); 139462306a36Sopenharmony_ci if (likely(!ret)) 139562306a36Sopenharmony_ci aq_mss_set_egress_sa_threshold_expired(hw, 139662306a36Sopenharmony_ci egress_sa_threshold_expired); 139762306a36Sopenharmony_ci} 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci#define AQ_LOCKED_MDO_DEF(mdo) \ 140062306a36Sopenharmony_cistatic int aq_locked_mdo_##mdo(struct macsec_context *ctx) \ 140162306a36Sopenharmony_ci{ \ 140262306a36Sopenharmony_ci struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); \ 140362306a36Sopenharmony_ci int ret; \ 140462306a36Sopenharmony_ci mutex_lock(&nic->macsec_mutex); \ 140562306a36Sopenharmony_ci ret = aq_mdo_##mdo(ctx); \ 140662306a36Sopenharmony_ci mutex_unlock(&nic->macsec_mutex); \ 140762306a36Sopenharmony_ci return ret; \ 140862306a36Sopenharmony_ci} 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(dev_open) 141162306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(dev_stop) 141262306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(add_secy) 141362306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(upd_secy) 141462306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(del_secy) 141562306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(add_rxsc) 141662306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(upd_rxsc) 141762306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(del_rxsc) 141862306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(add_rxsa) 141962306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(upd_rxsa) 142062306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(del_rxsa) 142162306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(add_txsa) 142262306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(upd_txsa) 142362306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(del_txsa) 142462306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(get_dev_stats) 142562306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(get_tx_sc_stats) 142662306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(get_tx_sa_stats) 142762306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(get_rx_sc_stats) 142862306a36Sopenharmony_ciAQ_LOCKED_MDO_DEF(get_rx_sa_stats) 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ciconst struct macsec_ops aq_macsec_ops = { 143162306a36Sopenharmony_ci .mdo_dev_open = aq_locked_mdo_dev_open, 143262306a36Sopenharmony_ci .mdo_dev_stop = aq_locked_mdo_dev_stop, 143362306a36Sopenharmony_ci .mdo_add_secy = aq_locked_mdo_add_secy, 143462306a36Sopenharmony_ci .mdo_upd_secy = aq_locked_mdo_upd_secy, 143562306a36Sopenharmony_ci .mdo_del_secy = aq_locked_mdo_del_secy, 143662306a36Sopenharmony_ci .mdo_add_rxsc = aq_locked_mdo_add_rxsc, 143762306a36Sopenharmony_ci .mdo_upd_rxsc = aq_locked_mdo_upd_rxsc, 143862306a36Sopenharmony_ci .mdo_del_rxsc = aq_locked_mdo_del_rxsc, 143962306a36Sopenharmony_ci .mdo_add_rxsa = aq_locked_mdo_add_rxsa, 144062306a36Sopenharmony_ci .mdo_upd_rxsa = aq_locked_mdo_upd_rxsa, 144162306a36Sopenharmony_ci .mdo_del_rxsa = aq_locked_mdo_del_rxsa, 144262306a36Sopenharmony_ci .mdo_add_txsa = aq_locked_mdo_add_txsa, 144362306a36Sopenharmony_ci .mdo_upd_txsa = aq_locked_mdo_upd_txsa, 144462306a36Sopenharmony_ci .mdo_del_txsa = aq_locked_mdo_del_txsa, 144562306a36Sopenharmony_ci .mdo_get_dev_stats = aq_locked_mdo_get_dev_stats, 144662306a36Sopenharmony_ci .mdo_get_tx_sc_stats = aq_locked_mdo_get_tx_sc_stats, 144762306a36Sopenharmony_ci .mdo_get_tx_sa_stats = aq_locked_mdo_get_tx_sa_stats, 144862306a36Sopenharmony_ci .mdo_get_rx_sc_stats = aq_locked_mdo_get_rx_sc_stats, 144962306a36Sopenharmony_ci .mdo_get_rx_sa_stats = aq_locked_mdo_get_rx_sa_stats, 145062306a36Sopenharmony_ci}; 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ciint aq_macsec_init(struct aq_nic_s *nic) 145362306a36Sopenharmony_ci{ 145462306a36Sopenharmony_ci struct aq_macsec_cfg *cfg; 145562306a36Sopenharmony_ci u32 caps_lo; 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci if (!nic->aq_fw_ops->get_link_capabilities) 145862306a36Sopenharmony_ci return 0; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci caps_lo = nic->aq_fw_ops->get_link_capabilities(nic->aq_hw); 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci if (!(caps_lo & BIT(CAPS_LO_MACSEC))) 146362306a36Sopenharmony_ci return 0; 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci nic->macsec_cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); 146662306a36Sopenharmony_ci if (!nic->macsec_cfg) 146762306a36Sopenharmony_ci return -ENOMEM; 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci nic->ndev->features |= NETIF_F_HW_MACSEC; 147062306a36Sopenharmony_ci nic->ndev->macsec_ops = &aq_macsec_ops; 147162306a36Sopenharmony_ci mutex_init(&nic->macsec_mutex); 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci return 0; 147462306a36Sopenharmony_ci} 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_civoid aq_macsec_free(struct aq_nic_s *nic) 147762306a36Sopenharmony_ci{ 147862306a36Sopenharmony_ci kfree(nic->macsec_cfg); 147962306a36Sopenharmony_ci nic->macsec_cfg = NULL; 148062306a36Sopenharmony_ci} 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ciint aq_macsec_enable(struct aq_nic_s *nic) 148362306a36Sopenharmony_ci{ 148462306a36Sopenharmony_ci u32 ctl_ether_types[1] = { ETH_P_PAE }; 148562306a36Sopenharmony_ci struct macsec_msg_fw_response resp = { 0 }; 148662306a36Sopenharmony_ci struct macsec_msg_fw_request msg = { 0 }; 148762306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 148862306a36Sopenharmony_ci int num_ctl_ether_types = 0; 148962306a36Sopenharmony_ci int index = 0, tbl_idx; 149062306a36Sopenharmony_ci int ret; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci if (!nic->macsec_cfg) 149362306a36Sopenharmony_ci return 0; 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci mutex_lock(&nic->macsec_mutex); 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci if (nic->aq_fw_ops->send_macsec_req) { 149862306a36Sopenharmony_ci struct macsec_cfg_request cfg = { 0 }; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci cfg.enabled = 1; 150162306a36Sopenharmony_ci cfg.egress_threshold = 0xffffffff; 150262306a36Sopenharmony_ci cfg.ingress_threshold = 0xffffffff; 150362306a36Sopenharmony_ci cfg.interrupts_enabled = 1; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci msg.msg_type = macsec_cfg_msg; 150662306a36Sopenharmony_ci msg.cfg = cfg; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci ret = nic->aq_fw_ops->send_macsec_req(hw, &msg, &resp); 150962306a36Sopenharmony_ci if (ret) 151062306a36Sopenharmony_ci goto unlock; 151162306a36Sopenharmony_ci } 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci /* Init Ethertype bypass filters */ 151462306a36Sopenharmony_ci for (index = 0; index < ARRAY_SIZE(ctl_ether_types); index++) { 151562306a36Sopenharmony_ci struct aq_mss_ingress_prectlf_record rx_prectlf_rec; 151662306a36Sopenharmony_ci struct aq_mss_egress_ctlf_record tx_ctlf_rec; 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci if (ctl_ether_types[index] == 0) 151962306a36Sopenharmony_ci continue; 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci memset(&tx_ctlf_rec, 0, sizeof(tx_ctlf_rec)); 152262306a36Sopenharmony_ci tx_ctlf_rec.eth_type = ctl_ether_types[index]; 152362306a36Sopenharmony_ci tx_ctlf_rec.match_type = 4; /* Match eth_type only */ 152462306a36Sopenharmony_ci tx_ctlf_rec.match_mask = 0xf; /* match for eth_type */ 152562306a36Sopenharmony_ci tx_ctlf_rec.action = 0; /* Bypass MACSEC modules */ 152662306a36Sopenharmony_ci tbl_idx = NUMROWS_EGRESSCTLFRECORD - num_ctl_ether_types - 1; 152762306a36Sopenharmony_ci aq_mss_set_egress_ctlf_record(hw, &tx_ctlf_rec, tbl_idx); 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci memset(&rx_prectlf_rec, 0, sizeof(rx_prectlf_rec)); 153062306a36Sopenharmony_ci rx_prectlf_rec.eth_type = ctl_ether_types[index]; 153162306a36Sopenharmony_ci rx_prectlf_rec.match_type = 4; /* Match eth_type only */ 153262306a36Sopenharmony_ci rx_prectlf_rec.match_mask = 0xf; /* match for eth_type */ 153362306a36Sopenharmony_ci rx_prectlf_rec.action = 0; /* Bypass MACSEC modules */ 153462306a36Sopenharmony_ci tbl_idx = 153562306a36Sopenharmony_ci NUMROWS_INGRESSPRECTLFRECORD - num_ctl_ether_types - 1; 153662306a36Sopenharmony_ci aq_mss_set_ingress_prectlf_record(hw, &rx_prectlf_rec, tbl_idx); 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci num_ctl_ether_types++; 153962306a36Sopenharmony_ci } 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci ret = aq_apply_macsec_cfg(nic); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ciunlock: 154462306a36Sopenharmony_ci mutex_unlock(&nic->macsec_mutex); 154562306a36Sopenharmony_ci return ret; 154662306a36Sopenharmony_ci} 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_civoid aq_macsec_work(struct aq_nic_s *nic) 154962306a36Sopenharmony_ci{ 155062306a36Sopenharmony_ci if (!nic->macsec_cfg) 155162306a36Sopenharmony_ci return; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci if (!netif_carrier_ok(nic->ndev)) 155462306a36Sopenharmony_ci return; 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci mutex_lock(&nic->macsec_mutex); 155762306a36Sopenharmony_ci aq_check_txsa_expiration(nic); 155862306a36Sopenharmony_ci mutex_unlock(&nic->macsec_mutex); 155962306a36Sopenharmony_ci} 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ciint aq_macsec_rx_sa_cnt(struct aq_nic_s *nic) 156262306a36Sopenharmony_ci{ 156362306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 156462306a36Sopenharmony_ci int i, cnt = 0; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci if (!cfg) 156762306a36Sopenharmony_ci return 0; 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci mutex_lock(&nic->macsec_mutex); 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 157262306a36Sopenharmony_ci if (!test_bit(i, &cfg->rxsc_idx_busy)) 157362306a36Sopenharmony_ci continue; 157462306a36Sopenharmony_ci cnt += hweight_long(cfg->aq_rxsc[i].rx_sa_idx_busy); 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci mutex_unlock(&nic->macsec_mutex); 157862306a36Sopenharmony_ci return cnt; 157962306a36Sopenharmony_ci} 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ciint aq_macsec_tx_sc_cnt(struct aq_nic_s *nic) 158262306a36Sopenharmony_ci{ 158362306a36Sopenharmony_ci int cnt; 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci if (!nic->macsec_cfg) 158662306a36Sopenharmony_ci return 0; 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci mutex_lock(&nic->macsec_mutex); 158962306a36Sopenharmony_ci cnt = hweight_long(nic->macsec_cfg->txsc_idx_busy); 159062306a36Sopenharmony_ci mutex_unlock(&nic->macsec_mutex); 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci return cnt; 159362306a36Sopenharmony_ci} 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_ciint aq_macsec_tx_sa_cnt(struct aq_nic_s *nic) 159662306a36Sopenharmony_ci{ 159762306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 159862306a36Sopenharmony_ci int i, cnt = 0; 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci if (!cfg) 160162306a36Sopenharmony_ci return 0; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci mutex_lock(&nic->macsec_mutex); 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 160662306a36Sopenharmony_ci if (!test_bit(i, &cfg->txsc_idx_busy)) 160762306a36Sopenharmony_ci continue; 160862306a36Sopenharmony_ci cnt += hweight_long(cfg->aq_txsc[i].tx_sa_idx_busy); 160962306a36Sopenharmony_ci } 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci mutex_unlock(&nic->macsec_mutex); 161262306a36Sopenharmony_ci return cnt; 161362306a36Sopenharmony_ci} 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_cistatic int aq_macsec_update_stats(struct aq_nic_s *nic) 161662306a36Sopenharmony_ci{ 161762306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 161862306a36Sopenharmony_ci struct aq_hw_s *hw = nic->aq_hw; 161962306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc; 162062306a36Sopenharmony_ci struct aq_macsec_rxsc *aq_rxsc; 162162306a36Sopenharmony_ci int i, sa_idx, assoc_num; 162262306a36Sopenharmony_ci int ret = 0; 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci aq_get_macsec_common_stats(hw, &cfg->stats); 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 162762306a36Sopenharmony_ci if (!(cfg->txsc_idx_busy & BIT(i))) 162862306a36Sopenharmony_ci continue; 162962306a36Sopenharmony_ci aq_txsc = &cfg->aq_txsc[i]; 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci ret = aq_get_txsc_stats(hw, aq_txsc->hw_sc_idx, 163262306a36Sopenharmony_ci &aq_txsc->stats); 163362306a36Sopenharmony_ci if (ret) 163462306a36Sopenharmony_ci return ret; 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci for (assoc_num = 0; assoc_num < MACSEC_NUM_AN; assoc_num++) { 163762306a36Sopenharmony_ci if (!test_bit(assoc_num, &aq_txsc->tx_sa_idx_busy)) 163862306a36Sopenharmony_ci continue; 163962306a36Sopenharmony_ci sa_idx = aq_txsc->hw_sc_idx | assoc_num; 164062306a36Sopenharmony_ci ret = aq_get_txsa_stats(hw, sa_idx, 164162306a36Sopenharmony_ci &aq_txsc->tx_sa_stats[assoc_num]); 164262306a36Sopenharmony_ci if (ret) 164362306a36Sopenharmony_ci return ret; 164462306a36Sopenharmony_ci } 164562306a36Sopenharmony_ci } 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { 164862306a36Sopenharmony_ci if (!(test_bit(i, &cfg->rxsc_idx_busy))) 164962306a36Sopenharmony_ci continue; 165062306a36Sopenharmony_ci aq_rxsc = &cfg->aq_rxsc[i]; 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci for (assoc_num = 0; assoc_num < MACSEC_NUM_AN; assoc_num++) { 165362306a36Sopenharmony_ci if (!test_bit(assoc_num, &aq_rxsc->rx_sa_idx_busy)) 165462306a36Sopenharmony_ci continue; 165562306a36Sopenharmony_ci sa_idx = aq_rxsc->hw_sc_idx | assoc_num; 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci ret = aq_get_rxsa_stats(hw, sa_idx, 165862306a36Sopenharmony_ci &aq_rxsc->rx_sa_stats[assoc_num]); 165962306a36Sopenharmony_ci if (ret) 166062306a36Sopenharmony_ci return ret; 166162306a36Sopenharmony_ci } 166262306a36Sopenharmony_ci } 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci return ret; 166562306a36Sopenharmony_ci} 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ciu64 *aq_macsec_get_stats(struct aq_nic_s *nic, u64 *data) 166862306a36Sopenharmony_ci{ 166962306a36Sopenharmony_ci struct aq_macsec_cfg *cfg = nic->macsec_cfg; 167062306a36Sopenharmony_ci struct aq_macsec_common_stats *common_stats; 167162306a36Sopenharmony_ci struct aq_macsec_tx_sc_stats *txsc_stats; 167262306a36Sopenharmony_ci struct aq_macsec_tx_sa_stats *txsa_stats; 167362306a36Sopenharmony_ci struct aq_macsec_rx_sa_stats *rxsa_stats; 167462306a36Sopenharmony_ci struct aq_macsec_txsc *aq_txsc; 167562306a36Sopenharmony_ci struct aq_macsec_rxsc *aq_rxsc; 167662306a36Sopenharmony_ci unsigned int assoc_num; 167762306a36Sopenharmony_ci unsigned int sc_num; 167862306a36Sopenharmony_ci unsigned int i = 0U; 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci if (!cfg) 168162306a36Sopenharmony_ci return data; 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci mutex_lock(&nic->macsec_mutex); 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci aq_macsec_update_stats(nic); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci common_stats = &cfg->stats; 168862306a36Sopenharmony_ci data[i] = common_stats->in.ctl_pkts; 168962306a36Sopenharmony_ci data[++i] = common_stats->in.tagged_miss_pkts; 169062306a36Sopenharmony_ci data[++i] = common_stats->in.untagged_miss_pkts; 169162306a36Sopenharmony_ci data[++i] = common_stats->in.notag_pkts; 169262306a36Sopenharmony_ci data[++i] = common_stats->in.untagged_pkts; 169362306a36Sopenharmony_ci data[++i] = common_stats->in.bad_tag_pkts; 169462306a36Sopenharmony_ci data[++i] = common_stats->in.no_sci_pkts; 169562306a36Sopenharmony_ci data[++i] = common_stats->in.unknown_sci_pkts; 169662306a36Sopenharmony_ci data[++i] = common_stats->in.ctrl_prt_pass_pkts; 169762306a36Sopenharmony_ci data[++i] = common_stats->in.unctrl_prt_pass_pkts; 169862306a36Sopenharmony_ci data[++i] = common_stats->in.ctrl_prt_fail_pkts; 169962306a36Sopenharmony_ci data[++i] = common_stats->in.unctrl_prt_fail_pkts; 170062306a36Sopenharmony_ci data[++i] = common_stats->in.too_long_pkts; 170162306a36Sopenharmony_ci data[++i] = common_stats->in.igpoc_ctl_pkts; 170262306a36Sopenharmony_ci data[++i] = common_stats->in.ecc_error_pkts; 170362306a36Sopenharmony_ci data[++i] = common_stats->in.unctrl_hit_drop_redir; 170462306a36Sopenharmony_ci data[++i] = common_stats->out.ctl_pkts; 170562306a36Sopenharmony_ci data[++i] = common_stats->out.unknown_sa_pkts; 170662306a36Sopenharmony_ci data[++i] = common_stats->out.untagged_pkts; 170762306a36Sopenharmony_ci data[++i] = common_stats->out.too_long; 170862306a36Sopenharmony_ci data[++i] = common_stats->out.ecc_error_pkts; 170962306a36Sopenharmony_ci data[++i] = common_stats->out.unctrl_hit_drop_redir; 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci for (sc_num = 0; sc_num < AQ_MACSEC_MAX_SC; sc_num++) { 171262306a36Sopenharmony_ci if (!(test_bit(sc_num, &cfg->txsc_idx_busy))) 171362306a36Sopenharmony_ci continue; 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci aq_txsc = &cfg->aq_txsc[sc_num]; 171662306a36Sopenharmony_ci txsc_stats = &aq_txsc->stats; 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_ci data[++i] = txsc_stats->sc_protected_pkts; 171962306a36Sopenharmony_ci data[++i] = txsc_stats->sc_encrypted_pkts; 172062306a36Sopenharmony_ci data[++i] = txsc_stats->sc_protected_octets; 172162306a36Sopenharmony_ci data[++i] = txsc_stats->sc_encrypted_octets; 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci for (assoc_num = 0; assoc_num < MACSEC_NUM_AN; assoc_num++) { 172462306a36Sopenharmony_ci if (!test_bit(assoc_num, &aq_txsc->tx_sa_idx_busy)) 172562306a36Sopenharmony_ci continue; 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci txsa_stats = &aq_txsc->tx_sa_stats[assoc_num]; 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci data[++i] = txsa_stats->sa_hit_drop_redirect; 173062306a36Sopenharmony_ci data[++i] = txsa_stats->sa_protected2_pkts; 173162306a36Sopenharmony_ci data[++i] = txsa_stats->sa_protected_pkts; 173262306a36Sopenharmony_ci data[++i] = txsa_stats->sa_encrypted_pkts; 173362306a36Sopenharmony_ci } 173462306a36Sopenharmony_ci } 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci for (sc_num = 0; sc_num < AQ_MACSEC_MAX_SC; sc_num++) { 173762306a36Sopenharmony_ci if (!(test_bit(sc_num, &cfg->rxsc_idx_busy))) 173862306a36Sopenharmony_ci continue; 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci aq_rxsc = &cfg->aq_rxsc[sc_num]; 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci for (assoc_num = 0; assoc_num < MACSEC_NUM_AN; assoc_num++) { 174362306a36Sopenharmony_ci if (!test_bit(assoc_num, &aq_rxsc->rx_sa_idx_busy)) 174462306a36Sopenharmony_ci continue; 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci rxsa_stats = &aq_rxsc->rx_sa_stats[assoc_num]; 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci data[++i] = rxsa_stats->untagged_hit_pkts; 174962306a36Sopenharmony_ci data[++i] = rxsa_stats->ctrl_hit_drop_redir_pkts; 175062306a36Sopenharmony_ci data[++i] = rxsa_stats->not_using_sa; 175162306a36Sopenharmony_ci data[++i] = rxsa_stats->unused_sa; 175262306a36Sopenharmony_ci data[++i] = rxsa_stats->not_valid_pkts; 175362306a36Sopenharmony_ci data[++i] = rxsa_stats->invalid_pkts; 175462306a36Sopenharmony_ci data[++i] = rxsa_stats->ok_pkts; 175562306a36Sopenharmony_ci data[++i] = rxsa_stats->late_pkts; 175662306a36Sopenharmony_ci data[++i] = rxsa_stats->delayed_pkts; 175762306a36Sopenharmony_ci data[++i] = rxsa_stats->unchecked_pkts; 175862306a36Sopenharmony_ci data[++i] = rxsa_stats->validated_octets; 175962306a36Sopenharmony_ci data[++i] = rxsa_stats->decrypted_octets; 176062306a36Sopenharmony_ci } 176162306a36Sopenharmony_ci } 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci i++; 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci data += i; 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci mutex_unlock(&nic->macsec_mutex); 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci return data; 177062306a36Sopenharmony_ci} 1771