[RFC net-next v1 5/5] net: phy: nxp-c45-tja11xx: implement mdo_insert_tx_tag

From: Radu Pirea (NXP OSS)
Date: Fri Aug 11 2023 - 11:34:06 EST


Implement mdo_insert_tx_tag to insert the TLV header in the ethernet
frame.

The TLV header contains the TX SC that will be used to encrypt the
frame.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@xxxxxxxxxxx>
---
drivers/net/phy/nxp-c45-tja11xx-macsec.c | 59 ++++++++++++++++++++++++
1 file changed, 59 insertions(+)

diff --git a/drivers/net/phy/nxp-c45-tja11xx-macsec.c b/drivers/net/phy/nxp-c45-tja11xx-macsec.c
index da63e35571d0..53f8706bc572 100644
--- a/drivers/net/phy/nxp-c45-tja11xx-macsec.c
+++ b/drivers/net/phy/nxp-c45-tja11xx-macsec.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/processor.h>
+#include <net/dst_metadata.h>
#include <net/macsec.h>

#include "nxp-c45-tja11xx.h"
@@ -23,6 +24,7 @@
#define VEND1_MACSEC_BASE 0x9000

#define MACSEC_CFG 0x0000
+#define MACSEC_CFG_EXTSCS BIT(26)
#define MACSEC_CFG_BYPASS BIT(1)
#define MACSEC_CFG_S0I BIT(0)

@@ -121,6 +123,8 @@
#define ADPTR_CNTRL 0x0F00
#define ADPTR_CNTRL_CONFIG_EN BIT(14)
#define ADPTR_CNTRL_ADPTR_EN BIT(12)
+#define ADPTR_TX_TAG_CNTRL 0x0F0C
+#define ADPTR_TX_TAG_CNTRL_ENA BIT(31)

#define TX_SC_FLT_BASE 0x800
#define TX_SC_FLT_SIZE 0x10
@@ -167,6 +171,14 @@
#define MACSEC_INPBTS 0x0638
#define MACSEC_IPSNFS 0x063C

+#define TJA11XX_TLV_TX_NEEDED_HEADROOM (32)
+#define TJA11XX_TLV_NEEDED_TAILROOM (0)
+
+#define MACSEC_TLV_CP BIT(0)
+#define MACSEC_TLV_SC_ID_OFF (2)
+
+#define ETH_P_TJA11XX_TLV (0x4e58)
+
struct nxp_c45_rx_sc {
struct macsec_rx_sc *rx_sc;
struct macsec_rx_sa *rx_sa_a;
@@ -310,6 +322,7 @@ void nxp_c45_macsec_config_init(struct phy_device *phydev)
MACSEC_EN | ADAPTER_EN);

nxp_c45_macsec_write(phydev, ADPTR_CNTRL, ADPTR_CNTRL_CONFIG_EN);
+ nxp_c45_macsec_write(phydev, ADPTR_TX_TAG_CNTRL, ADPTR_TX_TAG_CNTRL_ENA);
nxp_c45_macsec_write(phydev, ADPTR_CNTRL, ADPTR_CNTRL_CONFIG_EN |
ADPTR_CNTRL_ADPTR_EN);
nxp_c45_macsec_write(phydev, ADPTR_CNTRL,
@@ -322,6 +335,8 @@ void nxp_c45_macsec_config_init(struct phy_device *phydev)
nxp_c45_macsec_write(phydev, MACSEC_UPFR0M1, MACSEC_OVP);
nxp_c45_macsec_write(phydev, MACSEC_UPFR0M2, ETYPE_MASK);
nxp_c45_macsec_write(phydev, MACSEC_UPFR0R, MACSEC_UPFR_EN);
+
+ nxp_c45_macsec_write(phydev, MACSEC_CFG, MACSEC_CFG_EXTSCS);
}

static void nxp_c45_macsec_cfg_ptp(struct phy_device *phydev, bool enable)
@@ -1750,6 +1765,47 @@ static int nxp_c45_mdo_get_rx_sa_stats(struct macsec_context *ctx)
return 0;
}

+struct tja11xx_tlv_header {
+ struct ethhdr eth;
+ u8 subtype;
+ u8 len;
+ u8 payload[28];
+};
+
+static int nxp_c45_mdo_insert_tx_tag(struct macsec_context *ctx)
+{
+ struct nxp_c45_phy *priv = ctx->phydev->priv;
+ struct sk_buff *skb = ctx->skb;
+ struct tja11xx_tlv_header *tlv;
+ struct nxp_c45_secy *phy_secy;
+ struct metadata_dst *md_dst;
+ struct ethhdr *eth;
+ sci_t sci;
+
+ md_dst = skb_metadata_dst(skb);
+ if (!md_dst)
+ return -EINVAL;
+
+ sci = md_dst->u.macsec_info.sci;
+ phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, sci);
+ if (IS_ERR(phy_secy))
+ return PTR_ERR(phy_secy);
+
+ eth = eth_hdr(skb);
+ tlv = skb_push(skb, TJA11XX_TLV_TX_NEEDED_HEADROOM);
+ memmove(tlv, eth, sizeof(*eth));
+ skb_reset_mac_header(skb);
+ tlv->eth.h_proto = htons(ETH_P_TJA11XX_TLV);
+ tlv->subtype = 1;
+ tlv->len = sizeof(tlv->payload);
+ memset(tlv->payload, 0, sizeof(tlv->payload));
+
+ tlv->payload[3] = phy_secy->secy_id << MACSEC_TLV_SC_ID_OFF |
+ MACSEC_TLV_CP;
+
+ return 0;
+}
+
static const struct macsec_ops nxp_c45_macsec_ops = {
.mdo_dev_open = nxp_c45_mdo_dev_open,
.mdo_dev_stop = nxp_c45_mdo_dev_stop,
@@ -1770,6 +1826,9 @@ static const struct macsec_ops nxp_c45_macsec_ops = {
.mdo_get_tx_sa_stats = nxp_c45_mdo_get_tx_sa_stats,
.mdo_get_rx_sc_stats = nxp_c45_mdo_get_rx_sc_stats,
.mdo_get_rx_sa_stats = nxp_c45_mdo_get_rx_sa_stats,
+ .mdo_insert_tx_tag = nxp_c45_mdo_insert_tx_tag,
+ .needed_headroom = TJA11XX_TLV_TX_NEEDED_HEADROOM,
+ .needed_tailroom = TJA11XX_TLV_NEEDED_TAILROOM,
};

int nxp_c45_macsec_probe(struct phy_device *phydev)
--
2.34.1