| From 781449a4ae3b381950ee9aec4d8a54e35f66ab9b Mon Sep 17 00:00:00 2001 |
| From: Antoine Tenart <antoine.tenart@bootlin.com> |
| Date: Mon, 13 Jan 2020 23:31:48 +0100 |
| Subject: net: phy: mscc: PN rollover support |
| |
| This patch adds support for handling MACsec PN rollover in the mscc PHY |
| driver. When a flow rolls over, an interrupt is fired. This patch adds |
| the logic to check all flows and identify the one rolling over in the |
| handle_interrupt PHY helper, then disables the flow and report the event |
| to the MACsec core. |
| |
| Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| --- |
| drivers/net/phy/mscc.c | 60 ++++++++++++++++++++++++++++++++++++++++++- |
| drivers/net/phy/mscc_macsec.h | 2 ++ |
| 2 files changed, 61 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/net/phy/mscc.c |
| +++ b/drivers/net/phy/mscc.c |
| @@ -80,7 +80,7 @@ enum rgmii_rx_clock_delay { |
| #define MSCC_PHY_EXT_PHY_CNTL_2 24 |
| |
| #define MII_VSC85XX_INT_MASK 25 |
| -#define MII_VSC85XX_INT_MASK_MASK 0xa000 |
| +#define MII_VSC85XX_INT_MASK_MASK 0xa020 |
| #define MII_VSC85XX_INT_MASK_WOL 0x0040 |
| #define MII_VSC85XX_INT_STATUS 26 |
| |
| @@ -207,6 +207,9 @@ enum macsec_bank { |
| #define SECURE_ON_ENABLE 0x8000 |
| #define SECURE_ON_PASSWD_LEN_4 0x4000 |
| |
| +#define MSCC_PHY_EXTENDED_INT 28 |
| +#define MSCC_PHY_EXTENDED_INT_MS_EGR BIT(9) |
| + |
| /* Extended Page 3 Registers */ |
| #define MSCC_PHY_SERDES_TX_VALID_CNT 21 |
| #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22 |
| @@ -2805,6 +2808,43 @@ err: |
| return ret; |
| } |
| |
| +static int vsc8584_handle_interrupt(struct phy_device *phydev) |
| +{ |
| +#if IS_ENABLED(CONFIG_MACSEC) |
| + struct vsc8531_private *priv = phydev->priv; |
| + struct macsec_flow *flow, *tmp; |
| + u32 cause, rec; |
| + |
| + /* Check MACsec PN rollover */ |
| + cause = vsc8584_macsec_phy_read(phydev, MACSEC_EGR, |
| + MSCC_MS_INTR_CTRL_STATUS); |
| + cause &= MSCC_MS_INTR_CTRL_STATUS_INTR_CLR_STATUS_M; |
| + if (!(cause & MACSEC_INTR_CTRL_STATUS_ROLLOVER)) |
| + goto skip_rollover; |
| + |
| + rec = 6 + priv->secy->key_len / sizeof(u32); |
| + list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) { |
| + u32 val; |
| + |
| + if (flow->bank != MACSEC_EGR || !flow->has_transformation) |
| + continue; |
| + |
| + val = vsc8584_macsec_phy_read(phydev, MACSEC_EGR, |
| + MSCC_MS_XFORM_REC(flow->index, rec)); |
| + if (val == 0xffffffff) { |
| + vsc8584_macsec_flow_disable(phydev, flow); |
| + macsec_pn_wrapped(priv->secy, flow->tx_sa); |
| + break; |
| + } |
| + } |
| + |
| +skip_rollover: |
| +#endif |
| + |
| + phy_mac_interrupt(phydev); |
| + return 0; |
| +} |
| + |
| static int vsc85xx_config_init(struct phy_device *phydev) |
| { |
| int rc, i, phy_id; |
| @@ -3248,6 +3288,20 @@ static int vsc85xx_config_intr(struct ph |
| int rc; |
| |
| if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { |
| +#if IS_ENABLED(CONFIG_MACSEC) |
| + phy_write(phydev, MSCC_EXT_PAGE_ACCESS, |
| + MSCC_PHY_PAGE_EXTENDED_2); |
| + phy_write(phydev, MSCC_PHY_EXTENDED_INT, |
| + MSCC_PHY_EXTENDED_INT_MS_EGR); |
| + phy_write(phydev, MSCC_EXT_PAGE_ACCESS, |
| + MSCC_PHY_PAGE_STANDARD); |
| + |
| + vsc8584_macsec_phy_write(phydev, MACSEC_EGR, |
| + MSCC_MS_AIC_CTRL, 0xf); |
| + vsc8584_macsec_phy_write(phydev, MACSEC_EGR, |
| + MSCC_MS_INTR_CTRL_STATUS, |
| + MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE(MACSEC_INTR_CTRL_STATUS_ROLLOVER)); |
| +#endif |
| rc = phy_write(phydev, MII_VSC85XX_INT_MASK, |
| MII_VSC85XX_INT_MASK_MASK); |
| } else { |
| @@ -3553,6 +3607,7 @@ static struct phy_driver vsc85xx_driver[ |
| .config_aneg = &vsc85xx_config_aneg, |
| .aneg_done = &genphy_aneg_done, |
| .read_status = &vsc85xx_read_status, |
| + .handle_interrupt = &vsc8584_handle_interrupt, |
| .ack_interrupt = &vsc85xx_ack_interrupt, |
| .config_intr = &vsc85xx_config_intr, |
| .did_interrupt = &vsc8584_did_interrupt, |
| --- a/drivers/net/phy/mscc_macsec.h |
| +++ b/drivers/net/phy/mscc_macsec.h |
| @@ -83,6 +83,7 @@ enum mscc_macsec_validate_levels { |
| #define MSCC_MS_STATUS_CONTEXT_CTRL 0x3d02 |
| #define MSCC_MS_INTR_CTRL_STATUS 0x3d04 |
| #define MSCC_MS_BLOCK_CTX_UPDATE 0x3d0c |
| +#define MSCC_MS_AIC_CTRL 0x3e02 |
| |
| /* MACSEC_ENA_CFG */ |
| #define MSCC_MS_ENA_CFG_CLK_ENA BIT(0) |
| @@ -260,5 +261,6 @@ enum mscc_macsec_validate_levels { |
| #define MSCC_MS_INTR_CTRL_STATUS_INTR_CLR_STATUS_M GENMASK(15, 0) |
| #define MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE(x) ((x) << 16) |
| #define MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE_M GENMASK(31, 16) |
| +#define MACSEC_INTR_CTRL_STATUS_ROLLOVER BIT(5) |
| |
| #endif |