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

From: Radu Pirea (NXP OSS)
Date: Thu Aug 24 2023 - 05:17:41 EST


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

If extscs parameter is set to 1, then the TLV header will contain the
TX SC that will be used to encrypt the frame, otherwise the TX SC will
be selected using the MAC source address.

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

diff --git a/drivers/net/phy/nxp-c45-tja11xx-macsec.c b/drivers/net/phy/nxp-c45-tja11xx-macsec.c
index edfdd2540d39..f06505c04b13 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,18 @@
#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)
+
+bool extscs;
+module_param(extscs, bool, 0);
+MODULE_PARM_DESC(extscs, "Select the TX SC using TLV header information.");
+
struct nxp_c45_rx_sc {
struct macsec_rx_sc *rx_sc;
struct macsec_rx_sa *rx_sa_a;
@@ -315,6 +331,8 @@ void nxp_c45_macsec_config_init(struct phy_device *phydev)

nxp_c45_macsec_write(phydev, ADPTR_CNTRL, ADPTR_CNTRL_CONFIG_EN |
ADPTR_CNTRL_ADPTR_EN);
+ nxp_c45_macsec_write(phydev, ADPTR_TX_TAG_CNTRL,
+ ADPTR_TX_TAG_CNTRL_ENA);
nxp_c45_macsec_write(phydev, ADPTR_CNTRL, ADPTR_CNTRL_ADPTR_EN);

nxp_c45_macsec_write(phydev, MACSEC_TPNET, PN_WRAP_THRESHOLD);
@@ -324,6 +342,9 @@ 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);
+
+ if (extscs)
+ nxp_c45_macsec_write(phydev, MACSEC_CFG, MACSEC_CFG_EXTSCS);
}

static void nxp_c45_macsec_cfg_ptp(struct phy_device *phydev, bool enable)
@@ -1741,6 +1762,48 @@ 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 phy_device *phydev,
+ struct sk_buff *skb)
+{
+ struct nxp_c45_phy *priv = phydev->priv;
+ struct tja11xx_tlv_header *tlv;
+ struct nxp_c45_secy *phy_secy;
+ struct metadata_dst *md_dst;
+ struct ethhdr *eth;
+ sci_t sci;
+
+ 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));
+
+ if (!extscs)
+ return 0;
+
+ /* md_dst should be always set if MACsec is offloaded. */
+ md_dst = skb_metadata_dst(skb);
+ 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);
+
+ 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,
@@ -1761,6 +1824,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