0001
0002
0003
0004
0005
0006
0007
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
0472 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_SET1, BIT(idx));
0473
0474
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
0487 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_CLEAR1, BIT(idx));
0488
0489
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
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
0555 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0556 control);
0557
0558
0559 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0560 vsc8584_macsec_flow_context_id(flow));
0561
0562
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
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
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
0581 vsc8584_macsec_phy_write(phydev, bank,
0582 MSCC_MS_XFORM_REC(index, rec++),
0583 priv->secy->replay_window);
0584
0585
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }