Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
0002 /*
0003  * Driver for Microsemi VSC85xx PHYs - MACsec support
0004  *
0005  * Author: Antoine Tenart
0006  * License: Dual MIT/GPL
0007  * Copyright (c) 2020 Microsemi Corporation
0008  */
0009 
0010 #include <linux/phy.h>
0011 #include <dt-bindings/net/mscc-phy-vsc8531.h>
0012 
0013 #include <crypto/aes.h>
0014 
0015 #include <net/macsec.h>
0016 
0017 #include "mscc.h"
0018 #include "mscc_mac.h"
0019 #include "mscc_macsec.h"
0020 #include "mscc_fc_buffer.h"
0021 
0022 static u32 vsc8584_macsec_phy_read(struct phy_device *phydev,
0023                    enum macsec_bank bank, u32 reg)
0024 {
0025     u32 val, val_l = 0, val_h = 0;
0026     unsigned long deadline;
0027     int rc;
0028 
0029     rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
0030     if (rc < 0)
0031         goto failed;
0032 
0033     __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
0034             MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
0035 
0036     if (bank >> 2 == 0x1)
0037         /* non-MACsec access */
0038         bank &= 0x3;
0039     else
0040         bank = 0;
0041 
0042     __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
0043             MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_READ |
0044             MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
0045             MSCC_PHY_MACSEC_19_TARGET(bank));
0046 
0047     deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
0048     do {
0049         val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
0050     } while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
0051 
0052     val_l = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_17);
0053     val_h = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_18);
0054 
0055 failed:
0056     phy_restore_page(phydev, rc, rc);
0057 
0058     return (val_h << 16) | val_l;
0059 }
0060 
0061 static void vsc8584_macsec_phy_write(struct phy_device *phydev,
0062                      enum macsec_bank bank, u32 reg, u32 val)
0063 {
0064     unsigned long deadline;
0065     int rc;
0066 
0067     rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
0068     if (rc < 0)
0069         goto failed;
0070 
0071     __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
0072             MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
0073 
0074     if ((bank >> 2 == 0x1) || (bank >> 2 == 0x3))
0075         bank &= 0x3;
0076     else
0077         /* MACsec access */
0078         bank = 0;
0079 
0080     __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_17, (u16)val);
0081     __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_18, (u16)(val >> 16));
0082 
0083     __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
0084             MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
0085             MSCC_PHY_MACSEC_19_TARGET(bank));
0086 
0087     deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
0088     do {
0089         val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
0090     } while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
0091 
0092 failed:
0093     phy_restore_page(phydev, rc, rc);
0094 }
0095 
0096 static void vsc8584_macsec_classification(struct phy_device *phydev,
0097                       enum macsec_bank bank)
0098 {
0099     /* enable VLAN tag parsing */
0100     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_CP_TAG,
0101                  MSCC_MS_SAM_CP_TAG_PARSE_STAG |
0102                  MSCC_MS_SAM_CP_TAG_PARSE_QTAG |
0103                  MSCC_MS_SAM_CP_TAG_PARSE_QINQ);
0104 }
0105 
0106 static void vsc8584_macsec_flow_default_action(struct phy_device *phydev,
0107                            enum macsec_bank bank,
0108                            bool block)
0109 {
0110     u32 port = (bank == MACSEC_INGR) ?
0111             MSCC_MS_PORT_UNCONTROLLED : MSCC_MS_PORT_COMMON;
0112     u32 action = MSCC_MS_FLOW_BYPASS;
0113 
0114     if (block)
0115         action = MSCC_MS_FLOW_DROP;
0116 
0117     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_NCP,
0118                  /* MACsec untagged */
0119                  MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
0120                  MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0121                  MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DEST_PORT(port) |
0122                  /* MACsec tagged */
0123                  MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
0124                  MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0125                  MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DEST_PORT(port) |
0126                  /* Bad tag */
0127                  MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
0128                  MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0129                  MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DEST_PORT(port) |
0130                  /* Kay tag */
0131                  MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
0132                  MSCC_MS_SAM_NM_FLOW_NCP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0133                  MSCC_MS_SAM_NM_FLOW_NCP_KAY_DEST_PORT(port));
0134     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_CP,
0135                  /* MACsec untagged */
0136                  MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
0137                  MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0138                  MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DEST_PORT(port) |
0139                  /* MACsec tagged */
0140                  MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
0141                  MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0142                  MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DEST_PORT(port) |
0143                  /* Bad tag */
0144                  MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
0145                  MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0146                  MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DEST_PORT(port) |
0147                  /* Kay tag */
0148                  MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
0149                  MSCC_MS_SAM_NM_FLOW_CP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0150                  MSCC_MS_SAM_NM_FLOW_CP_KAY_DEST_PORT(port));
0151 }
0152 
0153 static void vsc8584_macsec_integrity_checks(struct phy_device *phydev,
0154                         enum macsec_bank bank)
0155 {
0156     u32 val;
0157 
0158     if (bank != MACSEC_INGR)
0159         return;
0160 
0161     /* Set default rules to pass unmatched frames */
0162     val = vsc8584_macsec_phy_read(phydev, bank,
0163                       MSCC_MS_PARAMS2_IG_CC_CONTROL);
0164     val |= MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_CTRL_ACT |
0165            MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_ACT;
0166     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CC_CONTROL,
0167                  val);
0168 
0169     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CP_TAG,
0170                  MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_STAG |
0171                  MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QTAG |
0172                  MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QINQ);
0173 }
0174 
0175 static void vsc8584_macsec_block_init(struct phy_device *phydev,
0176                       enum macsec_bank bank)
0177 {
0178     u32 val;
0179     int i;
0180 
0181     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
0182                  MSCC_MS_ENA_CFG_SW_RST |
0183                  MSCC_MS_ENA_CFG_MACSEC_BYPASS_ENA);
0184 
0185     /* Set the MACsec block out of s/w reset and enable clocks */
0186     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
0187                  MSCC_MS_ENA_CFG_CLK_ENA);
0188 
0189     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_STATUS_CONTEXT_CTRL,
0190                  bank == MACSEC_INGR ? 0xe5880214 : 0xe5880218);
0191     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_MISC_CONTROL,
0192                  MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX(bank == MACSEC_INGR ? 57 : 40) |
0193                  MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE(bank == MACSEC_INGR ? 1 : 2));
0194 
0195     /* Clear the counters */
0196     val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
0197     val |= MSCC_MS_COUNT_CONTROL_AUTO_CNTR_RESET;
0198     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
0199 
0200     /* Enable octet increment mode */
0201     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PP_CTRL,
0202                  MSCC_MS_PP_CTRL_MACSEC_OCTET_INCR_MODE);
0203 
0204     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_BLOCK_CTX_UPDATE, 0x3);
0205 
0206     val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
0207     val |= MSCC_MS_COUNT_CONTROL_RESET_ALL;
0208     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
0209 
0210     /* Set the MTU */
0211     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_NON_VLAN_MTU_CHECK,
0212                  MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE(32761) |
0213                  MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMP_DROP);
0214 
0215     for (i = 0; i < 8; i++)
0216         vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_VLAN_MTU_CHECK(i),
0217                      MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE(32761) |
0218                      MSCC_MS_VLAN_MTU_CHECK_MTU_COMP_DROP);
0219 
0220     if (bank == MACSEC_EGR) {
0221         val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_INTR_CTRL_STATUS);
0222         val &= ~MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE_M;
0223         vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_INTR_CTRL_STATUS, val);
0224 
0225         vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_FC_CFG,
0226                      MSCC_MS_FC_CFG_FCBUF_ENA |
0227                      MSCC_MS_FC_CFG_LOW_THRESH(0x1) |
0228                      MSCC_MS_FC_CFG_HIGH_THRESH(0x4) |
0229                      MSCC_MS_FC_CFG_LOW_BYTES_VAL(0x4) |
0230                      MSCC_MS_FC_CFG_HIGH_BYTES_VAL(0x6));
0231     }
0232 
0233     vsc8584_macsec_classification(phydev, bank);
0234     vsc8584_macsec_flow_default_action(phydev, bank, false);
0235     vsc8584_macsec_integrity_checks(phydev, bank);
0236 
0237     /* Enable the MACsec block */
0238     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
0239                  MSCC_MS_ENA_CFG_CLK_ENA |
0240                  MSCC_MS_ENA_CFG_MACSEC_ENA |
0241                  MSCC_MS_ENA_CFG_MACSEC_SPEED_MODE(0x5));
0242 }
0243 
0244 static void vsc8584_macsec_mac_init(struct phy_device *phydev,
0245                     enum macsec_bank bank)
0246 {
0247     u32 val;
0248     int i;
0249 
0250     /* Clear host & line stats */
0251     for (i = 0; i < 36; i++)
0252         vsc8584_macsec_phy_write(phydev, bank, 0x1c + i, 0);
0253 
0254     val = vsc8584_macsec_phy_read(phydev, bank,
0255                       MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL);
0256     val &= ~MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE_M;
0257     val |= MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE(2) |
0258            MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE(0xffff);
0259     vsc8584_macsec_phy_write(phydev, bank,
0260                  MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL, val);
0261 
0262     val = vsc8584_macsec_phy_read(phydev, bank,
0263                       MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2);
0264     val |= 0xffff;
0265     vsc8584_macsec_phy_write(phydev, bank,
0266                  MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2, val);
0267 
0268     val = vsc8584_macsec_phy_read(phydev, bank,
0269                       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL);
0270     if (bank == HOST_MAC)
0271         val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_TIMER_ENA |
0272                MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA;
0273     else
0274         val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_REACT_ENA |
0275                MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA |
0276                MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_MODE |
0277                MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_EARLY_PAUSE_DETECT_ENA;
0278     vsc8584_macsec_phy_write(phydev, bank,
0279                  MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL, val);
0280 
0281     vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_PKTINF_CFG,
0282                  MSCC_MAC_CFG_PKTINF_CFG_STRIP_FCS_ENA |
0283                  MSCC_MAC_CFG_PKTINF_CFG_INSERT_FCS_ENA |
0284                  MSCC_MAC_CFG_PKTINF_CFG_LPI_RELAY_ENA |
0285                  MSCC_MAC_CFG_PKTINF_CFG_STRIP_PREAMBLE_ENA |
0286                  MSCC_MAC_CFG_PKTINF_CFG_INSERT_PREAMBLE_ENA |
0287                  (bank == HOST_MAC ?
0288                   MSCC_MAC_CFG_PKTINF_CFG_ENABLE_TX_PADDING : 0) |
0289                  (IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING) ?
0290                   MSCC_MAC_CFG_PKTINF_CFG_MACSEC_BYPASS_NUM_PTP_STALL_CLKS(0x8) : 0));
0291 
0292     val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MODE_CFG);
0293     val &= ~MSCC_MAC_CFG_MODE_CFG_DISABLE_DIC;
0294     vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MODE_CFG, val);
0295 
0296     val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG);
0297     val &= ~MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_M;
0298     val |= MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN(10240);
0299     vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG, val);
0300 
0301     vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ADV_CHK_CFG,
0302                  MSCC_MAC_CFG_ADV_CHK_CFG_SFD_CHK_ENA |
0303                  MSCC_MAC_CFG_ADV_CHK_CFG_PRM_CHK_ENA |
0304                  MSCC_MAC_CFG_ADV_CHK_CFG_OOR_ERR_ENA |
0305                  MSCC_MAC_CFG_ADV_CHK_CFG_INR_ERR_ENA);
0306 
0307     val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_LFS_CFG);
0308     val &= ~MSCC_MAC_CFG_LFS_CFG_LFS_MODE_ENA;
0309     vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_LFS_CFG, val);
0310 
0311     vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ENA_CFG,
0312                  MSCC_MAC_CFG_ENA_CFG_RX_CLK_ENA |
0313                  MSCC_MAC_CFG_ENA_CFG_TX_CLK_ENA |
0314                  MSCC_MAC_CFG_ENA_CFG_RX_ENA |
0315                  MSCC_MAC_CFG_ENA_CFG_TX_ENA);
0316 }
0317 
0318 /* Must be called with mdio_lock taken */
0319 static int __vsc8584_macsec_init(struct phy_device *phydev)
0320 {
0321     struct vsc8531_private *priv = phydev->priv;
0322     enum macsec_bank proc_bank;
0323     u32 val;
0324 
0325     vsc8584_macsec_block_init(phydev, MACSEC_INGR);
0326     vsc8584_macsec_block_init(phydev, MACSEC_EGR);
0327     vsc8584_macsec_mac_init(phydev, HOST_MAC);
0328     vsc8584_macsec_mac_init(phydev, LINE_MAC);
0329 
0330     vsc8584_macsec_phy_write(phydev, FC_BUFFER,
0331                  MSCC_FCBUF_FC_READ_THRESH_CFG,
0332                  MSCC_FCBUF_FC_READ_THRESH_CFG_TX_THRESH(4) |
0333                  MSCC_FCBUF_FC_READ_THRESH_CFG_RX_THRESH(5));
0334 
0335     val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG);
0336     val |= MSCC_FCBUF_MODE_CFG_PAUSE_GEN_ENA |
0337            MSCC_FCBUF_MODE_CFG_RX_PPM_RATE_ADAPT_ENA |
0338            MSCC_FCBUF_MODE_CFG_TX_PPM_RATE_ADAPT_ENA;
0339     vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG, val);
0340 
0341     vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG,
0342                  MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_THRESH(8) |
0343                  MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_OFFSET(9));
0344 
0345     val = vsc8584_macsec_phy_read(phydev, FC_BUFFER,
0346                       MSCC_FCBUF_TX_DATA_QUEUE_CFG);
0347     val &= ~(MSCC_FCBUF_TX_DATA_QUEUE_CFG_START_M |
0348          MSCC_FCBUF_TX_DATA_QUEUE_CFG_END_M);
0349     val |= MSCC_FCBUF_TX_DATA_QUEUE_CFG_START(0) |
0350         MSCC_FCBUF_TX_DATA_QUEUE_CFG_END(5119);
0351     vsc8584_macsec_phy_write(phydev, FC_BUFFER,
0352                  MSCC_FCBUF_TX_DATA_QUEUE_CFG, val);
0353 
0354     val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG);
0355     val |= MSCC_FCBUF_ENA_CFG_TX_ENA | MSCC_FCBUF_ENA_CFG_RX_ENA;
0356     vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG, val);
0357 
0358     proc_bank = (priv->addr < 2) ? PROC_0 : PROC_2;
0359 
0360     val = vsc8584_macsec_phy_read(phydev, proc_bank,
0361                       MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL);
0362     val &= ~MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE_M;
0363     val |= MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE(4);
0364     vsc8584_macsec_phy_write(phydev, proc_bank,
0365                  MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL, val);
0366 
0367     return 0;
0368 }
0369 
0370 static void vsc8584_macsec_flow(struct phy_device *phydev,
0371                 struct macsec_flow *flow)
0372 {
0373     struct vsc8531_private *priv = phydev->priv;
0374     enum macsec_bank bank = flow->bank;
0375     u32 val, match = 0, mask = 0, action = 0, idx = flow->index;
0376 
0377     if (flow->match.tagged)
0378         match |= MSCC_MS_SAM_MISC_MATCH_TAGGED;
0379     if (flow->match.untagged)
0380         match |= MSCC_MS_SAM_MISC_MATCH_UNTAGGED;
0381 
0382     if (bank == MACSEC_INGR && flow->assoc_num >= 0) {
0383         match |= MSCC_MS_SAM_MISC_MATCH_AN(flow->assoc_num);
0384         mask |= MSCC_MS_SAM_MASK_AN_MASK(0x3);
0385     }
0386 
0387     if (bank == MACSEC_INGR && flow->match.sci && flow->rx_sa->sc->sci) {
0388         u64 sci = (__force u64)flow->rx_sa->sc->sci;
0389 
0390         match |= MSCC_MS_SAM_MISC_MATCH_TCI(BIT(3));
0391         mask |= MSCC_MS_SAM_MASK_TCI_MASK(BIT(3)) |
0392             MSCC_MS_SAM_MASK_SCI_MASK;
0393 
0394         vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_LO(idx),
0395                      lower_32_bits(sci));
0396         vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_HI(idx),
0397                      upper_32_bits(sci));
0398     }
0399 
0400     if (flow->match.etype) {
0401         mask |= MSCC_MS_SAM_MASK_MAC_ETYPE_MASK;
0402 
0403         vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MAC_SA_MATCH_HI(idx),
0404                      MSCC_MS_SAM_MAC_SA_MATCH_HI_ETYPE((__force u32)htons(flow->etype)));
0405     }
0406 
0407     match |= MSCC_MS_SAM_MISC_MATCH_PRIORITY(flow->priority);
0408 
0409     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MISC_MATCH(idx), match);
0410     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MASK(idx), mask);
0411 
0412     /* Action for matching packets */
0413     if (flow->action.drop)
0414         action = MSCC_MS_FLOW_DROP;
0415     else if (flow->action.bypass || flow->port == MSCC_MS_PORT_UNCONTROLLED)
0416         action = MSCC_MS_FLOW_BYPASS;
0417     else
0418         action = (bank == MACSEC_INGR) ?
0419              MSCC_MS_FLOW_INGRESS : MSCC_MS_FLOW_EGRESS;
0420 
0421     val = MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE(action) |
0422           MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION(MSCC_MS_ACTION_DROP) |
0423           MSCC_MS_SAM_FLOW_CTRL_DEST_PORT(flow->port);
0424 
0425     if (action == MSCC_MS_FLOW_BYPASS)
0426         goto write_ctrl;
0427 
0428     if (bank == MACSEC_INGR) {
0429         if (priv->secy->replay_protect)
0430             val |= MSCC_MS_SAM_FLOW_CTRL_REPLAY_PROTECT;
0431         if (priv->secy->validate_frames == MACSEC_VALIDATE_STRICT)
0432             val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_STRICT);
0433         else if (priv->secy->validate_frames == MACSEC_VALIDATE_CHECK)
0434             val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_CHECK);
0435     } else if (bank == MACSEC_EGR) {
0436         if (priv->secy->protect_frames)
0437             val |= MSCC_MS_SAM_FLOW_CTRL_PROTECT_FRAME;
0438         if (priv->secy->tx_sc.encrypt)
0439             val |= MSCC_MS_SAM_FLOW_CTRL_CONF_PROTECT;
0440         if (priv->secy->tx_sc.send_sci)
0441             val |= MSCC_MS_SAM_FLOW_CTRL_INCLUDE_SCI;
0442     }
0443 
0444 write_ctrl:
0445     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
0446 }
0447 
0448 static struct macsec_flow *vsc8584_macsec_find_flow(struct macsec_context *ctx,
0449                             enum macsec_bank bank)
0450 {
0451     struct vsc8531_private *priv = ctx->phydev->priv;
0452     struct macsec_flow *pos, *tmp;
0453 
0454     list_for_each_entry_safe(pos, tmp, &priv->macsec_flows, list)
0455         if (pos->assoc_num == ctx->sa.assoc_num && pos->bank == bank)
0456             return pos;
0457 
0458     return ERR_PTR(-ENOENT);
0459 }
0460 
0461 static void vsc8584_macsec_flow_enable(struct phy_device *phydev,
0462                        struct macsec_flow *flow)
0463 {
0464     enum macsec_bank bank = flow->bank;
0465     u32 val, idx = flow->index;
0466 
0467     if ((flow->bank == MACSEC_INGR && flow->rx_sa && !flow->rx_sa->active) ||
0468         (flow->bank == MACSEC_EGR && flow->tx_sa && !flow->tx_sa->active))
0469         return;
0470 
0471     /* Enable */
0472     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_SET1, BIT(idx));
0473 
0474     /* Set in-use */
0475     val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
0476     val |= MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
0477     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
0478 }
0479 
0480 static void vsc8584_macsec_flow_disable(struct phy_device *phydev,
0481                     struct macsec_flow *flow)
0482 {
0483     enum macsec_bank bank = flow->bank;
0484     u32 val, idx = flow->index;
0485 
0486     /* Disable */
0487     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_CLEAR1, BIT(idx));
0488 
0489     /* Clear in-use */
0490     val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
0491     val &= ~MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
0492     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
0493 }
0494 
0495 static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow)
0496 {
0497     if (flow->bank == MACSEC_INGR)
0498         return flow->index + MSCC_MS_MAX_FLOWS;
0499 
0500     return flow->index;
0501 }
0502 
0503 /* Derive the AES key to get a key for the hash autentication */
0504 static int vsc8584_macsec_derive_key(const u8 key[MACSEC_MAX_KEY_LEN],
0505                      u16 key_len, u8 hkey[16])
0506 {
0507     const u8 input[AES_BLOCK_SIZE] = {0};
0508     struct crypto_aes_ctx ctx;
0509     int ret;
0510 
0511     ret = aes_expandkey(&ctx, key, key_len);
0512     if (ret)
0513         return ret;
0514 
0515     aes_encrypt(&ctx, hkey, input);
0516     memzero_explicit(&ctx, sizeof(ctx));
0517     return 0;
0518 }
0519 
0520 static int vsc8584_macsec_transformation(struct phy_device *phydev,
0521                      struct macsec_flow *flow)
0522 {
0523     struct vsc8531_private *priv = phydev->priv;
0524     enum macsec_bank bank = flow->bank;
0525     int i, ret, index = flow->index;
0526     u32 rec = 0, control = 0;
0527     u8 hkey[16];
0528     u64 sci;
0529 
0530     ret = vsc8584_macsec_derive_key(flow->key, priv->secy->key_len, hkey);
0531     if (ret)
0532         return ret;
0533 
0534     switch (priv->secy->key_len) {
0535     case 16:
0536         control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_128);
0537         break;
0538     case 32:
0539         control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_256);
0540         break;
0541     default:
0542         return -EINVAL;
0543     }
0544 
0545     control |= (bank == MACSEC_EGR) ?
0546            (CONTROL_TYPE_EGRESS | CONTROL_AN(priv->secy->tx_sc.encoding_sa)) :
0547            (CONTROL_TYPE_INGRESS | CONTROL_SEQ_MASK);
0548 
0549     control |= CONTROL_UPDATE_SEQ | CONTROL_ENCRYPT_AUTH | CONTROL_KEY_IN_CTX |
0550            CONTROL_IV0 | CONTROL_IV1 | CONTROL_IV_IN_SEQ |
0551            CONTROL_DIGEST_TYPE(0x2) | CONTROL_SEQ_TYPE(0x1) |
0552            CONTROL_AUTH_ALG(AUTH_ALG_AES_GHAS) | CONTROL_CONTEXT_ID;
0553 
0554     /* Set the control word */
0555     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0556                  control);
0557 
0558     /* Set the context ID. Must be unique. */
0559     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0560                  vsc8584_macsec_flow_context_id(flow));
0561 
0562     /* Set the encryption/decryption key */
0563     for (i = 0; i < priv->secy->key_len / sizeof(u32); i++)
0564         vsc8584_macsec_phy_write(phydev, bank,
0565                      MSCC_MS_XFORM_REC(index, rec++),
0566                      ((u32 *)flow->key)[i]);
0567 
0568     /* Set the authentication key */
0569     for (i = 0; i < 4; i++)
0570         vsc8584_macsec_phy_write(phydev, bank,
0571                      MSCC_MS_XFORM_REC(index, rec++),
0572                      ((u32 *)hkey)[i]);
0573 
0574     /* Initial sequence number */
0575     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0576                  bank == MACSEC_INGR ?
0577                  flow->rx_sa->next_pn : flow->tx_sa->next_pn);
0578 
0579     if (bank == MACSEC_INGR)
0580         /* Set the mask (replay window size) */
0581         vsc8584_macsec_phy_write(phydev, bank,
0582                      MSCC_MS_XFORM_REC(index, rec++),
0583                      priv->secy->replay_window);
0584 
0585     /* Set the input vectors */
0586     sci = (__force u64)(bank == MACSEC_INGR ? flow->rx_sa->sc->sci : priv->secy->sci);
0587     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0588                  lower_32_bits(sci));
0589     vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0590                  upper_32_bits(sci));
0591 
0592     while (rec < 20)
0593         vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0594                      0);
0595 
0596     flow->has_transformation = true;
0597     return 0;
0598 }
0599 
0600 static struct macsec_flow *vsc8584_macsec_alloc_flow(struct vsc8531_private *priv,
0601                              enum macsec_bank bank)
0602 {
0603     unsigned long *bitmap = bank == MACSEC_INGR ?
0604                 &priv->ingr_flows : &priv->egr_flows;
0605     struct macsec_flow *flow;
0606     int index;
0607 
0608     index = find_first_zero_bit(bitmap, MSCC_MS_MAX_FLOWS);
0609 
0610     if (index == MSCC_MS_MAX_FLOWS)
0611         return ERR_PTR(-ENOMEM);
0612 
0613     flow = kzalloc(sizeof(*flow), GFP_KERNEL);
0614     if (!flow)
0615         return ERR_PTR(-ENOMEM);
0616 
0617     set_bit(index, bitmap);
0618     flow->index = index;
0619     flow->bank = bank;
0620     flow->priority = 8;
0621     flow->assoc_num = -1;
0622 
0623     list_add_tail(&flow->list, &priv->macsec_flows);
0624     return flow;
0625 }
0626 
0627 static void vsc8584_macsec_free_flow(struct vsc8531_private *priv,
0628                      struct macsec_flow *flow)
0629 {
0630     unsigned long *bitmap = flow->bank == MACSEC_INGR ?
0631                 &priv->ingr_flows : &priv->egr_flows;
0632 
0633     list_del(&flow->list);
0634     clear_bit(flow->index, bitmap);
0635     kfree(flow);
0636 }
0637 
0638 static int vsc8584_macsec_add_flow(struct phy_device *phydev,
0639                    struct macsec_flow *flow, bool update)
0640 {
0641     int ret;
0642 
0643     flow->port = MSCC_MS_PORT_CONTROLLED;
0644     vsc8584_macsec_flow(phydev, flow);
0645 
0646     if (update)
0647         return 0;
0648 
0649     ret = vsc8584_macsec_transformation(phydev, flow);
0650     if (ret) {
0651         vsc8584_macsec_free_flow(phydev->priv, flow);
0652         return ret;
0653     }
0654 
0655     return 0;
0656 }
0657 
0658 static int vsc8584_macsec_default_flows(struct phy_device *phydev)
0659 {
0660     struct macsec_flow *flow;
0661 
0662     /* Add a rule to let the MKA traffic go through, ingress */
0663     flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_INGR);
0664     if (IS_ERR(flow))
0665         return PTR_ERR(flow);
0666 
0667     flow->priority = 15;
0668     flow->port = MSCC_MS_PORT_UNCONTROLLED;
0669     flow->match.tagged = 1;
0670     flow->match.untagged = 1;
0671     flow->match.etype = 1;
0672     flow->etype = ETH_P_PAE;
0673     flow->action.bypass = 1;
0674 
0675     vsc8584_macsec_flow(phydev, flow);
0676     vsc8584_macsec_flow_enable(phydev, flow);
0677 
0678     /* Add a rule to let the MKA traffic go through, egress */
0679     flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_EGR);
0680     if (IS_ERR(flow))
0681         return PTR_ERR(flow);
0682 
0683     flow->priority = 15;
0684     flow->port = MSCC_MS_PORT_COMMON;
0685     flow->match.untagged = 1;
0686     flow->match.etype = 1;
0687     flow->etype = ETH_P_PAE;
0688     flow->action.bypass = 1;
0689 
0690     vsc8584_macsec_flow(phydev, flow);
0691     vsc8584_macsec_flow_enable(phydev, flow);
0692 
0693     return 0;
0694 }
0695 
0696 static void vsc8584_macsec_del_flow(struct phy_device *phydev,
0697                     struct macsec_flow *flow)
0698 {
0699     vsc8584_macsec_flow_disable(phydev, flow);
0700     vsc8584_macsec_free_flow(phydev->priv, flow);
0701 }
0702 
0703 static int __vsc8584_macsec_add_rxsa(struct macsec_context *ctx,
0704                      struct macsec_flow *flow, bool update)
0705 {
0706     struct phy_device *phydev = ctx->phydev;
0707     struct vsc8531_private *priv = phydev->priv;
0708 
0709     if (!flow) {
0710         flow = vsc8584_macsec_alloc_flow(priv, MACSEC_INGR);
0711         if (IS_ERR(flow))
0712             return PTR_ERR(flow);
0713 
0714         memcpy(flow->key, ctx->sa.key, priv->secy->key_len);
0715     }
0716 
0717     flow->assoc_num = ctx->sa.assoc_num;
0718     flow->rx_sa = ctx->sa.rx_sa;
0719 
0720     /* Always match tagged packets on ingress */
0721     flow->match.tagged = 1;
0722     flow->match.sci = 1;
0723 
0724     if (priv->secy->validate_frames != MACSEC_VALIDATE_DISABLED)
0725         flow->match.untagged = 1;
0726 
0727     return vsc8584_macsec_add_flow(phydev, flow, update);
0728 }
0729 
0730 static int __vsc8584_macsec_add_txsa(struct macsec_context *ctx,
0731                      struct macsec_flow *flow, bool update)
0732 {
0733     struct phy_device *phydev = ctx->phydev;
0734     struct vsc8531_private *priv = phydev->priv;
0735 
0736     if (!flow) {
0737         flow = vsc8584_macsec_alloc_flow(priv, MACSEC_EGR);
0738         if (IS_ERR(flow))
0739             return PTR_ERR(flow);
0740 
0741         memcpy(flow->key, ctx->sa.key, priv->secy->key_len);
0742     }
0743 
0744     flow->assoc_num = ctx->sa.assoc_num;
0745     flow->tx_sa = ctx->sa.tx_sa;
0746 
0747     /* Always match untagged packets on egress */
0748     flow->match.untagged = 1;
0749 
0750     return vsc8584_macsec_add_flow(phydev, flow, update);
0751 }
0752 
0753 static int vsc8584_macsec_dev_open(struct macsec_context *ctx)
0754 {
0755     struct vsc8531_private *priv = ctx->phydev->priv;
0756     struct macsec_flow *flow, *tmp;
0757 
0758     /* No operation to perform before the commit step */
0759     if (ctx->prepare)
0760         return 0;
0761 
0762     list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
0763         vsc8584_macsec_flow_enable(ctx->phydev, flow);
0764 
0765     return 0;
0766 }
0767 
0768 static int vsc8584_macsec_dev_stop(struct macsec_context *ctx)
0769 {
0770     struct vsc8531_private *priv = ctx->phydev->priv;
0771     struct macsec_flow *flow, *tmp;
0772 
0773     /* No operation to perform before the commit step */
0774     if (ctx->prepare)
0775         return 0;
0776 
0777     list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
0778         vsc8584_macsec_flow_disable(ctx->phydev, flow);
0779 
0780     return 0;
0781 }
0782 
0783 static int vsc8584_macsec_add_secy(struct macsec_context *ctx)
0784 {
0785     struct vsc8531_private *priv = ctx->phydev->priv;
0786     struct macsec_secy *secy = ctx->secy;
0787 
0788     if (ctx->prepare) {
0789         if (priv->secy)
0790             return -EEXIST;
0791 
0792         return 0;
0793     }
0794 
0795     priv->secy = secy;
0796 
0797     vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR,
0798                        secy->validate_frames != MACSEC_VALIDATE_DISABLED);
0799     vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR,
0800                        secy->validate_frames != MACSEC_VALIDATE_DISABLED);
0801 
0802     return vsc8584_macsec_default_flows(ctx->phydev);
0803 }
0804 
0805 static int vsc8584_macsec_del_secy(struct macsec_context *ctx)
0806 {
0807     struct vsc8531_private *priv = ctx->phydev->priv;
0808     struct macsec_flow *flow, *tmp;
0809 
0810     /* No operation to perform before the commit step */
0811     if (ctx->prepare)
0812         return 0;
0813 
0814     list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
0815         vsc8584_macsec_del_flow(ctx->phydev, flow);
0816 
0817     vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR, false);
0818     vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR, false);
0819 
0820     priv->secy = NULL;
0821     return 0;
0822 }
0823 
0824 static int vsc8584_macsec_upd_secy(struct macsec_context *ctx)
0825 {
0826     /* No operation to perform before the commit step */
0827     if (ctx->prepare)
0828         return 0;
0829 
0830     vsc8584_macsec_del_secy(ctx);
0831     return vsc8584_macsec_add_secy(ctx);
0832 }
0833 
0834 static int vsc8584_macsec_add_rxsc(struct macsec_context *ctx)
0835 {
0836     /* Nothing to do */
0837     return 0;
0838 }
0839 
0840 static int vsc8584_macsec_upd_rxsc(struct macsec_context *ctx)
0841 {
0842     return -EOPNOTSUPP;
0843 }
0844 
0845 static int vsc8584_macsec_del_rxsc(struct macsec_context *ctx)
0846 {
0847     struct vsc8531_private *priv = ctx->phydev->priv;
0848     struct macsec_flow *flow, *tmp;
0849 
0850     /* No operation to perform before the commit step */
0851     if (ctx->prepare)
0852         return 0;
0853 
0854     list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
0855         if (flow->bank == MACSEC_INGR && flow->rx_sa &&
0856             flow->rx_sa->sc->sci == ctx->rx_sc->sci)
0857             vsc8584_macsec_del_flow(ctx->phydev, flow);
0858     }
0859 
0860     return 0;
0861 }
0862 
0863 static int vsc8584_macsec_add_rxsa(struct macsec_context *ctx)
0864 {
0865     struct macsec_flow *flow = NULL;
0866 
0867     if (ctx->prepare)
0868         return __vsc8584_macsec_add_rxsa(ctx, flow, false);
0869 
0870     flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
0871     if (IS_ERR(flow))
0872         return PTR_ERR(flow);
0873 
0874     vsc8584_macsec_flow_enable(ctx->phydev, flow);
0875     return 0;
0876 }
0877 
0878 static int vsc8584_macsec_upd_rxsa(struct macsec_context *ctx)
0879 {
0880     struct macsec_flow *flow;
0881 
0882     flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
0883     if (IS_ERR(flow))
0884         return PTR_ERR(flow);
0885 
0886     if (ctx->prepare) {
0887         /* Make sure the flow is disabled before updating it */
0888         vsc8584_macsec_flow_disable(ctx->phydev, flow);
0889 
0890         return __vsc8584_macsec_add_rxsa(ctx, flow, true);
0891     }
0892 
0893     vsc8584_macsec_flow_enable(ctx->phydev, flow);
0894     return 0;
0895 }
0896 
0897 static int vsc8584_macsec_del_rxsa(struct macsec_context *ctx)
0898 {
0899     struct macsec_flow *flow;
0900 
0901     flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
0902 
0903     if (IS_ERR(flow))
0904         return PTR_ERR(flow);
0905     if (ctx->prepare)
0906         return 0;
0907 
0908     vsc8584_macsec_del_flow(ctx->phydev, flow);
0909     return 0;
0910 }
0911 
0912 static int vsc8584_macsec_add_txsa(struct macsec_context *ctx)
0913 {
0914     struct macsec_flow *flow = NULL;
0915 
0916     if (ctx->prepare)
0917         return __vsc8584_macsec_add_txsa(ctx, flow, false);
0918 
0919     flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
0920     if (IS_ERR(flow))
0921         return PTR_ERR(flow);
0922 
0923     vsc8584_macsec_flow_enable(ctx->phydev, flow);
0924     return 0;
0925 }
0926 
0927 static int vsc8584_macsec_upd_txsa(struct macsec_context *ctx)
0928 {
0929     struct macsec_flow *flow;
0930 
0931     flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
0932     if (IS_ERR(flow))
0933         return PTR_ERR(flow);
0934 
0935     if (ctx->prepare) {
0936         /* Make sure the flow is disabled before updating it */
0937         vsc8584_macsec_flow_disable(ctx->phydev, flow);
0938 
0939         return __vsc8584_macsec_add_txsa(ctx, flow, true);
0940     }
0941 
0942     vsc8584_macsec_flow_enable(ctx->phydev, flow);
0943     return 0;
0944 }
0945 
0946 static int vsc8584_macsec_del_txsa(struct macsec_context *ctx)
0947 {
0948     struct macsec_flow *flow;
0949 
0950     flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
0951 
0952     if (IS_ERR(flow))
0953         return PTR_ERR(flow);
0954     if (ctx->prepare)
0955         return 0;
0956 
0957     vsc8584_macsec_del_flow(ctx->phydev, flow);
0958     return 0;
0959 }
0960 
0961 static const struct macsec_ops vsc8584_macsec_ops = {
0962     .mdo_dev_open = vsc8584_macsec_dev_open,
0963     .mdo_dev_stop = vsc8584_macsec_dev_stop,
0964     .mdo_add_secy = vsc8584_macsec_add_secy,
0965     .mdo_upd_secy = vsc8584_macsec_upd_secy,
0966     .mdo_del_secy = vsc8584_macsec_del_secy,
0967     .mdo_add_rxsc = vsc8584_macsec_add_rxsc,
0968     .mdo_upd_rxsc = vsc8584_macsec_upd_rxsc,
0969     .mdo_del_rxsc = vsc8584_macsec_del_rxsc,
0970     .mdo_add_rxsa = vsc8584_macsec_add_rxsa,
0971     .mdo_upd_rxsa = vsc8584_macsec_upd_rxsa,
0972     .mdo_del_rxsa = vsc8584_macsec_del_rxsa,
0973     .mdo_add_txsa = vsc8584_macsec_add_txsa,
0974     .mdo_upd_txsa = vsc8584_macsec_upd_txsa,
0975     .mdo_del_txsa = vsc8584_macsec_del_txsa,
0976 };
0977 
0978 int vsc8584_macsec_init(struct phy_device *phydev)
0979 {
0980     struct vsc8531_private *vsc8531 = phydev->priv;
0981 
0982     switch (phydev->phy_id & phydev->drv->phy_id_mask) {
0983     case PHY_ID_VSC856X:
0984     case PHY_ID_VSC8582:
0985     case PHY_ID_VSC8584:
0986         INIT_LIST_HEAD(&vsc8531->macsec_flows);
0987         vsc8531->secy = NULL;
0988 
0989         phydev->macsec_ops = &vsc8584_macsec_ops;
0990 
0991         return __vsc8584_macsec_init(phydev);
0992     }
0993 
0994     return 0;
0995 }
0996 
0997 void vsc8584_handle_macsec_interrupt(struct phy_device *phydev)
0998 {
0999     struct vsc8531_private *priv = phydev->priv;
1000     struct macsec_flow *flow, *tmp;
1001     u32 cause, rec;
1002 
1003     /* Check MACsec PN rollover */
1004     cause = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
1005                     MSCC_MS_INTR_CTRL_STATUS);
1006     cause &= MSCC_MS_INTR_CTRL_STATUS_INTR_CLR_STATUS_M;
1007     if (!(cause & MACSEC_INTR_CTRL_STATUS_ROLLOVER))
1008         return;
1009 
1010     rec = 6 + priv->secy->key_len / sizeof(u32);
1011     list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
1012         u32 val;
1013 
1014         if (flow->bank != MACSEC_EGR || !flow->has_transformation)
1015             continue;
1016 
1017         val = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
1018                           MSCC_MS_XFORM_REC(flow->index, rec));
1019         if (val == 0xffffffff) {
1020             vsc8584_macsec_flow_disable(phydev, flow);
1021             macsec_pn_wrapped(priv->secy, flow->tx_sa);
1022             return;
1023         }
1024     }
1025 }
1026 
1027 void vsc8584_config_macsec_intr(struct phy_device *phydev)
1028 {
1029     phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
1030     phy_write(phydev, MSCC_PHY_EXTENDED_INT, MSCC_PHY_EXTENDED_INT_MS_EGR);
1031     phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1032 
1033     vsc8584_macsec_phy_write(phydev, MACSEC_EGR, MSCC_MS_AIC_CTRL, 0xf);
1034     vsc8584_macsec_phy_write(phydev, MACSEC_EGR, MSCC_MS_INTR_CTRL_STATUS,
1035                  MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE(MACSEC_INTR_CTRL_STATUS_ROLLOVER));
1036 }