Commit 781449a4 authored by Antoine Tenart's avatar Antoine Tenart Committed by David S. Miller
Browse files

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: default avatarAntoine Tenart <antoine.tenart@bootlin.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5c937de7
Loading
Loading
Loading
Loading
+59 −1
Original line number Diff line number Diff line
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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