net: phy: mscc: PN rollover support
authorAntoine Tenart <antoine.tenart@bootlin.com>
Mon, 13 Jan 2020 22:31:48 +0000 (23:31 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 14 Jan 2020 19:31:41 +0000 (11:31 -0800)
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
drivers/net/phy/mscc_macsec.h

index ccf1781..937ac7d 100644 (file)
@@ -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
@@ -2831,6 +2834,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;
@@ -3274,6 +3314,20 @@ static int vsc85xx_config_intr(struct phy_device *phydev)
        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 {
@@ -3623,6 +3677,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,
@@ -3675,6 +3730,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,
@@ -3699,6 +3755,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,
@@ -3723,6 +3780,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,
index 9b5d0af..d9ab6ab 100644 (file)
@@ -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