linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 00/10] net: macsec: initial support for hardware offloading
@ 2019-01-23 15:56 Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 01/10] net: introduce the MACSEC netdev feature Antoine Tenart
                   ` (9 more replies)
  0 siblings, 10 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

Hello,

This series intends to add support for offloading MACsec transformations
in hardware enabled devices. The series is divided in two parts: the
first 7 patches add the infrastructure support to offload a MACsec
configuration to hardware drivers; and the last 3 patches introduce the
MACsec offloading support in the Microsemi Ocelot networking PHY, making
it the first driver to support the MACsec hardware offloading feature.

The series can also be found at:
https://github.com/atenart/linux/tree/net-next/macsec

If you think I'm missing anyone who would be interested in
participating to the discussion please feel free to Cc them and I'll add
them to the Cc list for the next iteration.

MACsec hardware offloading infrastructure
-----------------------------------------

Linux has a software implementation of the MACsec standard and so far no
hardware offloading feature was developed and submitted. Some hardware
engines can perform MACsec operations, such as the Intel ixgbe NIC and
the Microsemi Ocelot PHY (the one we use in this series). This means the
MACsec offloading infrastructure should support networking PHY and
Ethernet drivers. A preliminary email[1] was sent about this.

The main idea here is to re-use the logic and data structures of the
software MACsec implementation. This allows not to duplicate definitions
and structure storing the same kind of information. It also allows to
use a unified genlink interface for both MACsec implementations (so that
the same userspace tool, `ip macsec`, is used with the same arguments).
The MACsec offloading support cannot be disabled if an interface
supports it at the moment, but this could be implemented later on if
this is a need (we could think of something like
`ip macsec set macsec0 offloading off`).

The MACsec configuration is passed to device drivers supporting it
through macsec_hw_offload() which is called (indirectly) from the MACsec
genl helpers. This function calls the macsec() ops of PHY and Ethernet
drivers in two steps: a preparation one, and a commit one. The first
step is allowed to fail and should be used to check if a provided
configuration is compatible with the features provided by a MACsec
engine, while the second step is not allowed to fail and should only be
used to enable a given MACsec configuration. Two extra calls are made:
when a virtual MACsec interface is created and when it is deleted, so
that the hardware driver can stay in sync.

The Rx and TX handlers are modified to take in account the special case
were the MACsec transformation happens in the hardware, whether in a PHY
or in a MAC, as the packets seen by the networking stack on both the
physical and MACsec virtual interface are exactly the same. This leads
to some limitations: the hardware and software implementations can't be
used on the same physical interface, as the policies would be impossible
to fulfill (such as strict validation of the frames). Also only a single
virtual MACsec interface can be attached to a physical port supporting
hardware offloading as it would be impossible to guess onto which
interface a given packet should go (for ingress traffic).

Another limitation as of now is that the counters and statistics are not
reported back from the hardware to the software MACsec implementation.
This isn't an issue when using offloaded MACsec transformations, but it
should be added in the future so that the MACsec state can be reported
to the user (which would also improve the debug).

[1] https://www.spinics.net/lists/netdev/msg513047.html

Microsemi Ocelot PHY MACsec support
-----------------------------------

In order to add support for the MACsec offloading feature in the
Microsemi Ocelot driver, the __phy_read_page and __phy_write_page
helpers had to be exported. This is because the initialization of the
PHY is done while holding the MDIO bus lock, and we need to change the
page to configure the MACsec block.

The support itself is then added in two patches. The first one adds
support for configuring the MACsec block within the PHY, so that it is
up, running and available for future configuration, but is not doing any
modification on the traffic passing through the PHY. The second patch
implements the phy_driver macsec() helper in the Microsemi Ocelot PHY
driver, and introduce helpers to configure MACsec transformations and
flows to match specific packets.

Comments are of course welcomed. Thanks!
Antoine

Antoine Tenart (10):
  net: introduce the MACSEC netdev feature
  net: macsec: convert to SPDX
  net: macsec: move some definitions in a dedicated header
  net: macsec: introduce the netdev_macsec structure
  net: phy: introduce a phy_driver macsec helper
  net: introduce a net_device_ops macsec helper
  net: macsec: hardware offloading infrastructure
  net: phy: export __phy_read_page/__phy_write_page
  net: phy: mscc: macsec initialization
  net: phy: mscc: macsec support

 drivers/net/macsec.c             | 466 +++++++++------
 drivers/net/phy/Kconfig          |   2 +
 drivers/net/phy/mscc.c           | 960 +++++++++++++++++++++++++++++++
 drivers/net/phy/mscc_fc_buffer.h |  64 +++
 drivers/net/phy/mscc_mac.h       | 159 +++++
 drivers/net/phy/mscc_macsec.h    | 258 +++++++++
 drivers/net/phy/phy-core.c       |   6 +-
 drivers/net/phy/phy.c            |  17 +
 include/linux/netdev_features.h  |   3 +
 include/linux/netdevice.h        |   8 +
 include/linux/phy.h              |  12 +
 include/net/macsec.h             | 223 +++++++
 net/core/ethtool.c               |   1 +
 13 files changed, 1996 insertions(+), 183 deletions(-)
 create mode 100644 drivers/net/phy/mscc_fc_buffer.h
 create mode 100644 drivers/net/phy/mscc_mac.h
 create mode 100644 drivers/net/phy/mscc_macsec.h
 create mode 100644 include/net/macsec.h

-- 
2.20.1


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH net-next 01/10] net: introduce the MACSEC netdev feature
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 02/10] net: macsec: convert to SPDX Antoine Tenart
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch introduce a new netdev feature, which will be used by drivers
to state they can perform MACsec transformations in hardware.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 include/linux/netdev_features.h | 3 +++
 net/core/ethtool.c              | 1 +
 2 files changed, 4 insertions(+)

diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 2b2a6dce1630..f278da0f03cd 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -84,6 +84,8 @@ enum {
 	NETIF_F_GRO_HW_BIT,		/* Hardware Generic receive offload */
 	NETIF_F_HW_TLS_RECORD_BIT,	/* Offload TLS record */
 
+	NETIF_F_HW_MACSEC_BIT,		/* Offload MACsec operations */
+
 	/*
 	 * Add your fresh new feature above and remember to update
 	 * netdev_features_strings[] in net/core/ethtool.c and maybe
@@ -153,6 +155,7 @@ enum {
 #define NETIF_F_GSO_UDP_L4	__NETIF_F(GSO_UDP_L4)
 #define NETIF_F_HW_TLS_TX	__NETIF_F(HW_TLS_TX)
 #define NETIF_F_HW_TLS_RX	__NETIF_F(HW_TLS_RX)
+#define NETIF_F_HW_MACSEC	__NETIF_F(HW_MACSEC)
 
 #define for_each_netdev_feature(mask_addr, bit)	\
 	for_each_set_bit(bit, (unsigned long *)mask_addr, NETDEV_FEATURE_COUNT)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 158264f7cfaf..c43f281db758 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -113,6 +113,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
 	[NETIF_F_HW_TLS_RECORD_BIT] =	"tls-hw-record",
 	[NETIF_F_HW_TLS_TX_BIT] =	 "tls-hw-tx-offload",
 	[NETIF_F_HW_TLS_RX_BIT] =	 "tls-hw-rx-offload",
+	[NETIF_F_HW_MACSEC_BIT] =	 "macsec-hw-offload",
 };
 
 static const char
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 02/10] net: macsec: convert to SPDX
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 01/10] net: introduce the MACSEC netdev feature Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 17:03   ` Andrew Lunn
  2019-01-23 15:56 ` [PATCH net-next 03/10] net: macsec: move some definitions in a dedicated header Antoine Tenart
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This cosmetic patch converts the macsec implementation license header to
the now recommended format, SPDX.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/macsec.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 64a982563d59..56e354305f76 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * drivers/net/macsec.c - MACsec device
  *
  * Copyright (c) 2015 Sabrina Dubroca <sd@queasysnail.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
 #include <linux/types.h>
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 03/10] net: macsec: move some definitions in a dedicated header
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 01/10] net: introduce the MACSEC netdev feature Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 02/10] net: macsec: convert to SPDX Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 20:11   ` Florian Fainelli
  2019-01-23 15:56 ` [PATCH net-next 04/10] net: macsec: introduce the netdev_macsec structure Antoine Tenart
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch moves some structure, type and identifier definitions into a
MACsec specific header. This patch does not modify how the MACsec code
is running and only move things around. This is a preparation for the
future MACsec hardware offloading support, which will re-use those
definitions outside macsec.c.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/macsec.c | 164 +--------------------------------------
 include/net/macsec.h | 178 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 179 insertions(+), 163 deletions(-)
 create mode 100644 include/net/macsec.h

diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 56e354305f76..c3a138dd4386 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -17,10 +17,9 @@
 #include <net/sock.h>
 #include <net/gro_cells.h>
 
+#include <net/macsec.h>
 #include <uapi/linux/if_macsec.h>
 
-typedef u64 __bitwise sci_t;
-
 #define MACSEC_SCI_LEN 8
 
 /* SecTAG length = macsec_eth_header without the optional SCI */
@@ -58,8 +57,6 @@ struct macsec_eth_header {
 #define GCM_AES_IV_LEN 12
 #define DEFAULT_ICV_LEN 16
 
-#define MACSEC_NUM_AN 4 /* 2 bits for the association number */
-
 #define for_each_rxsc(secy, sc)				\
 	for (sc = rcu_dereference_bh(secy->rx_sc);	\
 	     sc;					\
@@ -77,49 +74,6 @@ struct gcm_iv {
 	__be32 pn;
 };
 
-/**
- * struct macsec_key - SA key
- * @id: user-provided key identifier
- * @tfm: crypto struct, key storage
- */
-struct macsec_key {
-	u8 id[MACSEC_KEYID_LEN];
-	struct crypto_aead *tfm;
-};
-
-struct macsec_rx_sc_stats {
-	__u64 InOctetsValidated;
-	__u64 InOctetsDecrypted;
-	__u64 InPktsUnchecked;
-	__u64 InPktsDelayed;
-	__u64 InPktsOK;
-	__u64 InPktsInvalid;
-	__u64 InPktsLate;
-	__u64 InPktsNotValid;
-	__u64 InPktsNotUsingSA;
-	__u64 InPktsUnusedSA;
-};
-
-struct macsec_rx_sa_stats {
-	__u32 InPktsOK;
-	__u32 InPktsInvalid;
-	__u32 InPktsNotValid;
-	__u32 InPktsNotUsingSA;
-	__u32 InPktsUnusedSA;
-};
-
-struct macsec_tx_sa_stats {
-	__u32 OutPktsProtected;
-	__u32 OutPktsEncrypted;
-};
-
-struct macsec_tx_sc_stats {
-	__u64 OutPktsProtected;
-	__u64 OutPktsEncrypted;
-	__u64 OutOctetsProtected;
-	__u64 OutOctetsEncrypted;
-};
-
 struct macsec_dev_stats {
 	__u64 OutPktsUntagged;
 	__u64 InPktsUntagged;
@@ -131,124 +85,8 @@ struct macsec_dev_stats {
 	__u64 InPktsOverrun;
 };
 
-/**
- * struct macsec_rx_sa - receive secure association
- * @active:
- * @next_pn: packet number expected for the next packet
- * @lock: protects next_pn manipulations
- * @key: key structure
- * @stats: per-SA stats
- */
-struct macsec_rx_sa {
-	struct macsec_key key;
-	spinlock_t lock;
-	u32 next_pn;
-	refcount_t refcnt;
-	bool active;
-	struct macsec_rx_sa_stats __percpu *stats;
-	struct macsec_rx_sc *sc;
-	struct rcu_head rcu;
-};
-
-struct pcpu_rx_sc_stats {
-	struct macsec_rx_sc_stats stats;
-	struct u64_stats_sync syncp;
-};
-
-/**
- * struct macsec_rx_sc - receive secure channel
- * @sci: secure channel identifier for this SC
- * @active: channel is active
- * @sa: array of secure associations
- * @stats: per-SC stats
- */
-struct macsec_rx_sc {
-	struct macsec_rx_sc __rcu *next;
-	sci_t sci;
-	bool active;
-	struct macsec_rx_sa __rcu *sa[MACSEC_NUM_AN];
-	struct pcpu_rx_sc_stats __percpu *stats;
-	refcount_t refcnt;
-	struct rcu_head rcu_head;
-};
-
-/**
- * struct macsec_tx_sa - transmit secure association
- * @active:
- * @next_pn: packet number to use for the next packet
- * @lock: protects next_pn manipulations
- * @key: key structure
- * @stats: per-SA stats
- */
-struct macsec_tx_sa {
-	struct macsec_key key;
-	spinlock_t lock;
-	u32 next_pn;
-	refcount_t refcnt;
-	bool active;
-	struct macsec_tx_sa_stats __percpu *stats;
-	struct rcu_head rcu;
-};
-
-struct pcpu_tx_sc_stats {
-	struct macsec_tx_sc_stats stats;
-	struct u64_stats_sync syncp;
-};
-
-/**
- * struct macsec_tx_sc - transmit secure channel
- * @active:
- * @encoding_sa: association number of the SA currently in use
- * @encrypt: encrypt packets on transmit, or authenticate only
- * @send_sci: always include the SCI in the SecTAG
- * @end_station:
- * @scb: single copy broadcast flag
- * @sa: array of secure associations
- * @stats: stats for this TXSC
- */
-struct macsec_tx_sc {
-	bool active;
-	u8 encoding_sa;
-	bool encrypt;
-	bool send_sci;
-	bool end_station;
-	bool scb;
-	struct macsec_tx_sa __rcu *sa[MACSEC_NUM_AN];
-	struct pcpu_tx_sc_stats __percpu *stats;
-};
-
 #define MACSEC_VALIDATE_DEFAULT MACSEC_VALIDATE_STRICT
 
-/**
- * struct macsec_secy - MACsec Security Entity
- * @netdev: netdevice for this SecY
- * @n_rx_sc: number of receive secure channels configured on this SecY
- * @sci: secure channel identifier used for tx
- * @key_len: length of keys used by the cipher suite
- * @icv_len: length of ICV used by the cipher suite
- * @validate_frames: validation mode
- * @operational: MAC_Operational flag
- * @protect_frames: enable protection for this SecY
- * @replay_protect: enable packet number checks on receive
- * @replay_window: size of the replay window
- * @tx_sc: transmit secure channel
- * @rx_sc: linked list of receive secure channels
- */
-struct macsec_secy {
-	struct net_device *netdev;
-	unsigned int n_rx_sc;
-	sci_t sci;
-	u16 key_len;
-	u16 icv_len;
-	enum macsec_validation_type validate_frames;
-	bool operational;
-	bool protect_frames;
-	bool replay_protect;
-	u32 replay_window;
-	struct macsec_tx_sc tx_sc;
-	struct macsec_rx_sc __rcu *rx_sc;
-};
-
 struct pcpu_secy_stats {
 	struct macsec_dev_stats stats;
 	struct u64_stats_sync syncp;
diff --git a/include/net/macsec.h b/include/net/macsec.h
new file mode 100644
index 000000000000..15ff331dd670
--- /dev/null
+++ b/include/net/macsec.h
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * MACsec netdev header, used for h/w accelerated implementations.
+ *
+ * Copyright (c) 2015 Sabrina Dubroca <sd@queasysnail.net>
+ */
+#ifndef _NET_MACSEC_H_
+#define _NET_MACSEC_H_
+
+#include <linux/u64_stats_sync.h>
+#include <uapi/linux/if_link.h>
+#include <uapi/linux/if_macsec.h>
+
+typedef u64 __bitwise sci_t;
+
+#define MACSEC_NUM_AN 4 /* 2 bits for the association number */
+
+/**
+ * struct macsec_key - SA key
+ * @id: user-provided key identifier
+ * @tfm: crypto struct, key storage
+ */
+struct macsec_key {
+	u8 id[MACSEC_KEYID_LEN];
+	struct crypto_aead *tfm;
+};
+
+struct macsec_rx_sc_stats {
+	__u64 InOctetsValidated;
+	__u64 InOctetsDecrypted;
+	__u64 InPktsUnchecked;
+	__u64 InPktsDelayed;
+	__u64 InPktsOK;
+	__u64 InPktsInvalid;
+	__u64 InPktsLate;
+	__u64 InPktsNotValid;
+	__u64 InPktsNotUsingSA;
+	__u64 InPktsUnusedSA;
+};
+
+struct macsec_rx_sa_stats {
+	__u32 InPktsOK;
+	__u32 InPktsInvalid;
+	__u32 InPktsNotValid;
+	__u32 InPktsNotUsingSA;
+	__u32 InPktsUnusedSA;
+};
+
+struct macsec_tx_sa_stats {
+	__u32 OutPktsProtected;
+	__u32 OutPktsEncrypted;
+};
+
+struct macsec_tx_sc_stats {
+	__u64 OutPktsProtected;
+	__u64 OutPktsEncrypted;
+	__u64 OutOctetsProtected;
+	__u64 OutOctetsEncrypted;
+};
+
+/**
+ * struct macsec_rx_sa - receive secure association
+ * @active:
+ * @next_pn: packet number expected for the next packet
+ * @lock: protects next_pn manipulations
+ * @key: key structure
+ * @stats: per-SA stats
+ */
+struct macsec_rx_sa {
+	struct macsec_key key;
+	spinlock_t lock;
+	u32 next_pn;
+	refcount_t refcnt;
+	bool active;
+	struct macsec_rx_sa_stats __percpu *stats;
+	struct macsec_rx_sc *sc;
+	struct rcu_head rcu;
+};
+
+struct pcpu_rx_sc_stats {
+	struct macsec_rx_sc_stats stats;
+	struct u64_stats_sync syncp;
+};
+
+struct pcpu_tx_sc_stats {
+	struct macsec_tx_sc_stats stats;
+	struct u64_stats_sync syncp;
+};
+
+/**
+ * struct macsec_rx_sc - receive secure channel
+ * @sci: secure channel identifier for this SC
+ * @active: channel is active
+ * @sa: array of secure associations
+ * @stats: per-SC stats
+ */
+struct macsec_rx_sc {
+	struct macsec_rx_sc __rcu *next;
+	sci_t sci;
+	bool active;
+	struct macsec_rx_sa __rcu *sa[MACSEC_NUM_AN];
+	struct pcpu_rx_sc_stats __percpu *stats;
+	refcount_t refcnt;
+	struct rcu_head rcu_head;
+};
+
+/**
+ * struct macsec_tx_sa - transmit secure association
+ * @active:
+ * @next_pn: packet number to use for the next packet
+ * @lock: protects next_pn manipulations
+ * @key: key structure
+ * @stats: per-SA stats
+ */
+struct macsec_tx_sa {
+	struct macsec_key key;
+	spinlock_t lock;
+	u32 next_pn;
+	refcount_t refcnt;
+	bool active;
+	bool offloaded;
+	struct macsec_tx_sa_stats __percpu *stats;
+	struct rcu_head rcu;
+};
+
+/**
+ * struct macsec_tx_sc - transmit secure channel
+ * @active:
+ * @encoding_sa: association number of the SA currently in use
+ * @encrypt: encrypt packets on transmit, or authenticate only
+ * @send_sci: always include the SCI in the SecTAG
+ * @end_station:
+ * @scb: single copy broadcast flag
+ * @sa: array of secure associations
+ * @stats: stats for this TXSC
+ */
+struct macsec_tx_sc {
+	bool active;
+	u8 encoding_sa;
+	bool encrypt;
+	bool send_sci;
+	bool end_station;
+	bool scb;
+	struct macsec_tx_sa __rcu *sa[MACSEC_NUM_AN];
+	struct pcpu_tx_sc_stats __percpu *stats;
+};
+
+/**
+ * struct macsec_secy - MACsec Security Entity
+ * @netdev: netdevice for this SecY
+ * @n_rx_sc: number of receive secure channels configured on this SecY
+ * @sci: secure channel identifier used for tx
+ * @key_len: length of keys used by the cipher suite
+ * @icv_len: length of ICV used by the cipher suite
+ * @validate_frames: validation mode
+ * @operational: MAC_Operational flag
+ * @protect_frames: enable protection for this SecY
+ * @replay_protect: enable packet number checks on receive
+ * @replay_window: size of the replay window
+ * @tx_sc: transmit secure channel
+ * @rx_sc: linked list of receive secure channels
+ */
+struct macsec_secy {
+	struct net_device *netdev;
+	unsigned int n_rx_sc;
+	sci_t sci;
+	u16 key_len;
+	u16 icv_len;
+	enum macsec_validation_type validate_frames;
+	bool operational;
+	bool protect_frames;
+	bool replay_protect;
+	u32 replay_window;
+	struct macsec_tx_sc tx_sc;
+	struct macsec_rx_sc __rcu *rx_sc;
+};
+
+#endif /* _NET_MACSEC_H_ */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 04/10] net: macsec: introduce the netdev_macsec structure
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
                   ` (2 preceding siblings ...)
  2019-01-23 15:56 ` [PATCH net-next 03/10] net: macsec: move some definitions in a dedicated header Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 05/10] net: phy: introduce a phy_driver macsec helper Antoine Tenart
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch introduces the netdev_macsec structure. It will be used
in the kernel to exchange information between the common MACsec
implementation (macsec.c) and the MACsec hardware offloading
implementations. This structure contains a command (struct
netdev_macsec_command) and pointers to MACsec specific structures which
contain the actual MACsec configuration.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 include/net/macsec.h | 45 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/include/net/macsec.h b/include/net/macsec.h
index 15ff331dd670..1e4d37c190ed 100644
--- a/include/net/macsec.h
+++ b/include/net/macsec.h
@@ -175,4 +175,49 @@ struct macsec_secy {
 	struct macsec_rx_sc __rcu *rx_sc;
 };
 
+enum netdev_macsec_command {
+	/* Device wide */
+	MACSEC_DEV_OPEN,
+	MACSEC_DEV_STOP,
+
+	/* SecY */
+	MACSEC_ADD_SECY,
+	MACSEC_UPD_SECY,
+	MACSEC_DEL_SECY,
+
+	/* Security channels */
+	MACSEC_ADD_RXSC,
+	MACSEC_UPD_RXSC,
+	MACSEC_DEL_RXSC,
+
+	/* Security associations */
+	MACSEC_ADD_RXSA,
+	MACSEC_UPD_RXSA,
+	MACSEC_DEL_RXSA,
+	MACSEC_ADD_TXSA,
+	MACSEC_UPD_TXSA,
+	MACSEC_DEL_TXSA,
+};
+
+struct netdev_macsec {
+	enum netdev_macsec_command command;
+	u8 prepare:1;
+
+	union {
+		/* MACSEC_*_SECY */
+		const struct macsec_secy *secy;
+		/* MACSEC_*_RXSC */
+		const struct macsec_rx_sc *rx_sc;
+		/* MACSEC_*_RXSA/TXSA */
+		struct {
+			unsigned char assoc_num;
+			u8 key[MACSEC_KEYID_LEN];
+			union {
+				const struct macsec_rx_sa *rx_sa;
+				const struct macsec_tx_sa *tx_sa;
+			};
+		} sa;
+	};
+};
+
 #endif /* _NET_MACSEC_H_ */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 05/10] net: phy: introduce a phy_driver macsec helper
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
                   ` (3 preceding siblings ...)
  2019-01-23 15:56 ` [PATCH net-next 04/10] net: macsec: introduce the netdev_macsec structure Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 17:08   ` Andrew Lunn
  2019-01-23 15:56 ` [PATCH net-next 06/10] net: introduce a net_device_ops " Antoine Tenart
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch introduces a phy_driver MACsec helper to allow PHYs to
implement a MACsec offloading solution. The phy_driver MACsec helper is
called through a wrapper, phy_macsec, to perform this call while holding
the phydev lock.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/phy/phy.c | 17 +++++++++++++++++
 include/linux/phy.h   |  9 +++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 631ed33fe9d9..6b37bb845ce9 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1095,6 +1095,23 @@ int phy_get_eee_err(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_get_eee_err);
 
+int phy_macsec(struct phy_device *phydev, struct netdev_macsec *macsec)
+{
+	int ret = -EOPNOTSUPP;
+
+	if (!phydev->drv)
+		return -EIO;
+
+	mutex_lock(&phydev->lock);
+
+	if (phydev->drv->macsec)
+		ret = phydev->drv->macsec(phydev, macsec);
+
+	mutex_unlock(&phydev->lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_macsec);
+
 /**
  * phy_ethtool_get_eee - get EEE supported and status
  * @phydev: target phy_device struct
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 1f3873a2ff29..21839f352e7c 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -27,6 +27,10 @@
 #include <linux/workqueue.h>
 #include <linux/mod_devicetable.h>
 
+#ifdef CONFIG_MACSEC
+#include <net/macsec.h>
+#endif
+
 #include <linux/atomic.h>
 
 #define PHY_DEFAULT_FEATURES	(SUPPORTED_Autoneg | \
@@ -630,6 +634,10 @@ struct phy_driver {
 			    struct ethtool_tunable *tuna,
 			    const void *data);
 	int (*set_loopback)(struct phy_device *dev, bool enable);
+
+#ifdef CONFIG_MACSEC
+	int (*macsec)(struct phy_device *dev, struct netdev_macsec *macsec);
+#endif
 };
 #define to_phy_driver(d) container_of(to_mdio_common_driver(d),		\
 				      struct phy_driver, mdiodrv)
@@ -1072,6 +1080,7 @@ int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask);
 
 int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
 int phy_get_eee_err(struct phy_device *phydev);
+int phy_macsec(struct phy_device *phydev, struct netdev_macsec *macsec);
 int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
 int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data);
 int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 06/10] net: introduce a net_device_ops macsec helper
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
                   ` (4 preceding siblings ...)
  2019-01-23 15:56 ` [PATCH net-next 05/10] net: phy: introduce a phy_driver macsec helper Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 20:16   ` Florian Fainelli
  2019-01-24 14:58   ` Igor Russkikh
  2019-01-23 15:56 ` [PATCH net-next 07/10] net: macsec: hardware offloading infrastructure Antoine Tenart
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch introduces a net_device_ops MACsec helper to allow net device
drivers to implement a MACsec offloading solution.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 include/linux/netdevice.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e675ef97a426..ee2f40dca515 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -53,6 +53,10 @@
 #include <uapi/linux/pkt_cls.h>
 #include <linux/hashtable.h>
 
+#ifdef CONFIG_MACSEC
+#include <net/macsec.h>
+#endif
+
 struct netpoll_info;
 struct device;
 struct phy_device;
@@ -1441,6 +1445,10 @@ struct net_device_ops {
 						u32 flags);
 	int			(*ndo_xsk_async_xmit)(struct net_device *dev,
 						      u32 queue_id);
+#ifdef CONFIG_MACSEC
+	int			(*ndo_macsec)(struct net_device *dev,
+					      struct netdev_macsec *macsec);
+#endif
 };
 
 /**
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 07/10] net: macsec: hardware offloading infrastructure
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
                   ` (5 preceding siblings ...)
  2019-01-23 15:56 ` [PATCH net-next 06/10] net: introduce a net_device_ops " Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 08/10] net: phy: export __phy_read_page/__phy_write_page Antoine Tenart
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch introduces the MACsec hardware offloading infrastructure.

The main idea here is to re-use the logic and data structures of the
software MACsec implementation. This allows not to duplicate definitions
and structure storing the same kind of information. It also allows to
use a unified genlink interface for both MACsec implementations (so that
the same userspace tool, `ip macsec`, is used with the same arguments).
The MACsec offloading support cannot be disabled if an interface
supports it at the moment.

The MACsec configuration is passed to device drivers supporting it
through macsec_hw_offload() which is called (indirectly) from the MACsec
genl helpers. This function calls the macsec() ops of PHY and Ethernet
drivers in two steps: a preparation one, and a commit one. The first
step is allowed to fail and should be used to check if a provided
configuration is compatible with the features provided by a MACsec
engine, while the second step is not allowed to fail and should only be
used to enable a given MACsec configuration. Two extra calls are made:
when a virtual MACsec interface is created and when it is deleted, so
that the hardware driver can stay in sync.

The Rx and TX handlers are modified to take in account the special case
were the MACsec transformation happens in the hardware, whether in a PHY
or in a MAC, as the packets seen by the networking stack on both the
physical and MACsec virtual interface are exactly the same. This leads
to some limitations: the hardware and software implementations can't be
used on the same physical interface, as the policies would be impossible
to fulfill (such as strict validation of the frames). Also only a single
virtual MACsec interface can be attached to a physical port supporting
hardware offloading as it would be impossible to guess onto which
interface a given packet should go (for ingress traffic).

Another limitation as of now is that the counters and statistics are not
reported back from the hardware to the software MACsec implementation.
This isn't an issue when using offloaded MACsec transformations, but it
should be added in the future so that the MACsec state can be reported
to the user (which would also improve the debug).

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/macsec.c | 296 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 283 insertions(+), 13 deletions(-)

diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index c3a138dd4386..3dfcc92cf83c 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -16,6 +16,7 @@
 #include <net/genetlink.h>
 #include <net/sock.h>
 #include <net/gro_cells.h>
+#include <linux/phy.h>
 
 #include <net/macsec.h>
 #include <uapi/linux/if_macsec.h>
@@ -319,6 +320,25 @@ static void macsec_set_shortlen(struct macsec_eth_header *h, size_t data_len)
 		h->short_length = data_len;
 }
 
+/* Checks if underlying layers implement MACsec offloading functions */
+static inline bool macsec_hw_offload_capable(struct macsec_dev *dev)
+{
+	struct phy_device *phydev;
+
+	if (!dev || !dev->real_dev)
+		return false;
+
+	phydev = dev->real_dev->phydev;
+
+	if (phydev && phydev->drv && phydev->drv->macsec)
+		return true;
+	if (dev->real_dev->features & NETIF_F_HW_MACSEC &&
+	    dev->real_dev->netdev_ops->ndo_macsec)
+		return true;
+
+	return false;
+}
+
 /* validate MACsec packet according to IEEE 802.1AE-2006 9.12 */
 static bool macsec_validate_skb(struct sk_buff *skb, u16 icv_len)
 {
@@ -867,8 +887,10 @@ static struct macsec_rx_sc *find_rx_sc_rtnl(struct macsec_secy *secy, sci_t sci)
 	return NULL;
 }
 
-static void handle_not_macsec(struct sk_buff *skb)
+static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
 {
+	/* Deliver to the uncontrolled port by default */
+	enum rx_handler_result ret = RX_HANDLER_PASS;
 	struct macsec_rxh_data *rxd;
 	struct macsec_dev *macsec;
 
@@ -883,7 +905,8 @@ static void handle_not_macsec(struct sk_buff *skb)
 		struct sk_buff *nskb;
 		struct pcpu_secy_stats *secy_stats = this_cpu_ptr(macsec->stats);
 
-		if (macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
+		if (!macsec_hw_offload_capable(macsec) &&
+		    macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
 			u64_stats_update_begin(&secy_stats->syncp);
 			secy_stats->stats.InPktsNoTag++;
 			u64_stats_update_end(&secy_stats->syncp);
@@ -902,9 +925,17 @@ static void handle_not_macsec(struct sk_buff *skb)
 			secy_stats->stats.InPktsUntagged++;
 			u64_stats_update_end(&secy_stats->syncp);
 		}
+
+		if (netif_running(macsec->secy.netdev) &&
+		    macsec_hw_offload_capable(macsec)) {
+			ret = RX_HANDLER_EXACT;
+			goto out;
+		}
 	}
 
+out:
 	rcu_read_unlock();
+	return ret;
 }
 
 static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
@@ -929,12 +960,8 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
 		goto drop_direct;
 
 	hdr = macsec_ethhdr(skb);
-	if (hdr->eth.h_proto != htons(ETH_P_MACSEC)) {
-		handle_not_macsec(skb);
-
-		/* and deliver to the uncontrolled port */
-		return RX_HANDLER_PASS;
-	}
+	if (hdr->eth.h_proto != htons(ETH_P_MACSEC))
+		return handle_not_macsec(skb);
 
 	skb = skb_unshare(skb, GFP_ATOMIC);
 	if (!skb) {
@@ -1440,6 +1467,137 @@ static const struct nla_policy macsec_genl_sa_policy[NUM_MACSEC_SA_ATTR] = {
 				 .len = MACSEC_MAX_KEY_LEN, },
 };
 
+static int macsec_hw_offload(struct net_device *net,
+			     struct netdev_macsec *macsec)
+{
+	struct macsec_dev *dev = netdev_priv(net);
+	int ret;
+
+	/* Phase I: prepare. The drive should fail here if there are going to be
+	 * issues in the commit phase.
+	 *
+	 * If supported the PHY implementation is called, otherwise the MAC one
+	 * is used.
+	 *
+	 * Phase II: commit. This step cannot fail.
+	 */
+	macsec->prepare = true;
+
+	if (dev->real_dev->phydev) {
+		ret = phy_macsec(dev->real_dev->phydev, macsec);
+		if (ret == -EOPNOTSUPP)
+			goto try_netdev_macsec;
+		if (ret)
+			return ret;
+
+		macsec->prepare = false;
+		ret = phy_macsec(dev->real_dev->phydev, macsec);
+		if (unlikely(ret))
+			goto offload_failed;
+
+		return 0;
+	}
+
+try_netdev_macsec:
+	if (dev->real_dev->netdev_ops->ndo_macsec) {
+		ret = dev->real_dev->netdev_ops->ndo_macsec(net, macsec);
+		if (ret)
+			return ret;
+
+		macsec->prepare = false;
+		ret = dev->real_dev->netdev_ops->ndo_macsec(net, macsec);
+		if (unlikely(ret))
+			goto offload_failed;
+	}
+
+	return 0;
+
+offload_failed:
+	/* This should never happen: commit is not allowed to fail */
+	WARN(1, "MACsec offloading commit failed (%d)\n", ret);
+	return ret;
+}
+
+static int macsec_hw_offload_secy(struct net_device *net,
+				  enum netdev_macsec_command command,
+				  struct macsec_secy *secy)
+{
+	struct macsec_dev *dev = netdev_priv(net);
+	struct netdev_macsec macsec;
+
+	if (!macsec_hw_offload_capable(dev))
+		return 0;
+
+	memset(&macsec, 0, sizeof(macsec));
+	macsec.command = command;
+	macsec.secy = secy;
+
+	return macsec_hw_offload(net, &macsec);
+}
+
+static int macsec_hw_offload_rxsc(struct net_device *net,
+				  enum netdev_macsec_command command,
+				  struct macsec_rx_sc *rx_sc)
+{
+	struct macsec_dev *dev = netdev_priv(net);
+	struct netdev_macsec macsec;
+
+	if (!macsec_hw_offload_capable(dev))
+		return 0;
+
+	memset(&macsec, 0, sizeof(macsec));
+	macsec.command = command;
+	macsec.rx_sc = rx_sc;
+
+	return macsec_hw_offload(net, &macsec);
+}
+
+static int macsec_hw_offload_rxsa(struct net_device *net,
+				  enum netdev_macsec_command command,
+				  struct macsec_rx_sa *rx_sa,
+				  unsigned char assoc_num, u8 *key)
+{
+	struct macsec_secy *secy = &macsec_priv(net)->secy;
+	struct macsec_dev *dev = netdev_priv(net);
+	struct netdev_macsec macsec;
+
+	if (!macsec_hw_offload_capable(dev))
+		return 0;
+
+	memset(&macsec, 0, sizeof(macsec));
+	macsec.command = command;
+	macsec.sa.assoc_num = assoc_num;
+	macsec.sa.rx_sa = rx_sa;
+
+	if (key)
+		memcpy(macsec.sa.key, key, secy->key_len);
+
+	return macsec_hw_offload(net, &macsec);
+}
+
+static int macsec_hw_offload_txsa(struct net_device *net,
+				  enum netdev_macsec_command command,
+				  struct macsec_tx_sa *tx_sa,
+				  unsigned char assoc_num, u8 *key)
+{
+	struct macsec_secy *secy = &macsec_priv(net)->secy;
+	struct macsec_dev *dev = netdev_priv(net);
+	struct netdev_macsec macsec;
+
+	if (!macsec_hw_offload_capable(dev))
+		return 0;
+
+	memset(&macsec, 0, sizeof(macsec));
+	macsec.command = command;
+	macsec.sa.assoc_num = assoc_num;
+	macsec.sa.tx_sa = tx_sa;
+
+	if (key)
+		memcpy(macsec.sa.key, key, secy->key_len);
+
+	return macsec_hw_offload(net, &macsec);
+}
+
 static int parse_sa_config(struct nlattr **attrs, struct nlattr **tb_sa)
 {
 	if (!attrs[MACSEC_ATTR_SA_CONFIG])
@@ -1561,6 +1719,15 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info)
 
 	nla_memcpy(rx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEYID], MACSEC_KEYID_LEN);
 	rx_sa->sc = rx_sc;
+
+	err = macsec_hw_offload_rxsa(dev, MACSEC_ADD_RXSA, rx_sa, assoc_num,
+				     nla_data(tb_sa[MACSEC_SA_ATTR_KEY]));
+	if (err) {
+		kfree(rx_sa);
+		rtnl_unlock();
+		return err;
+	}
+
 	rcu_assign_pointer(rx_sc->sa[assoc_num], rx_sa);
 
 	rtnl_unlock();
@@ -1717,6 +1884,15 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info)
 	if (assoc_num == tx_sc->encoding_sa && tx_sa->active)
 		secy->operational = true;
 
+	err = macsec_hw_offload_txsa(dev, MACSEC_ADD_TXSA, tx_sa, assoc_num,
+				     nla_data(tb_sa[MACSEC_SA_ATTR_KEY]));
+	if (err) {
+		secy->operational = false;
+		kfree(tx_sa);
+		rtnl_unlock();
+		return err;
+	}
+
 	rcu_assign_pointer(tx_sc->sa[assoc_num], tx_sa);
 
 	rtnl_unlock();
@@ -1734,6 +1910,7 @@ static int macsec_del_rxsa(struct sk_buff *skb, struct genl_info *info)
 	u8 assoc_num;
 	struct nlattr *tb_rxsc[MACSEC_RXSC_ATTR_MAX + 1];
 	struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
+	int ret;
 
 	if (!attrs[MACSEC_ATTR_IFINDEX])
 		return -EINVAL;
@@ -1757,6 +1934,13 @@ static int macsec_del_rxsa(struct sk_buff *skb, struct genl_info *info)
 		return -EBUSY;
 	}
 
+	ret = macsec_hw_offload_rxsa(dev, MACSEC_DEL_RXSA, rx_sa, assoc_num,
+				     NULL);
+	if (ret) {
+		rtnl_unlock();
+		return ret;
+	}
+
 	RCU_INIT_POINTER(rx_sc->sa[assoc_num], NULL);
 	clear_rx_sa(rx_sa);
 
@@ -1773,6 +1957,7 @@ static int macsec_del_rxsc(struct sk_buff *skb, struct genl_info *info)
 	struct macsec_rx_sc *rx_sc;
 	sci_t sci;
 	struct nlattr *tb_rxsc[MACSEC_RXSC_ATTR_MAX + 1];
+	int ret;
 
 	if (!attrs[MACSEC_ATTR_IFINDEX])
 		return -EINVAL;
@@ -1799,6 +1984,15 @@ static int macsec_del_rxsc(struct sk_buff *skb, struct genl_info *info)
 		return -ENODEV;
 	}
 
+	ret = macsec_hw_offload_rxsc(dev, MACSEC_DEL_RXSC, rx_sc);
+	if (ret) {
+		/* Revert del_rx_sc() */
+		if (rx_sc->active)
+			secy->n_rx_sc++;
+		rtnl_unlock();
+		return ret;
+	}
+
 	free_rx_sc(rx_sc);
 	rtnl_unlock();
 
@@ -1814,6 +2008,7 @@ static int macsec_del_txsa(struct sk_buff *skb, struct genl_info *info)
 	struct macsec_tx_sa *tx_sa;
 	u8 assoc_num;
 	struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
+	int ret;
 
 	if (!attrs[MACSEC_ATTR_IFINDEX])
 		return -EINVAL;
@@ -1834,6 +2029,13 @@ static int macsec_del_txsa(struct sk_buff *skb, struct genl_info *info)
 		return -EBUSY;
 	}
 
+	ret = macsec_hw_offload_txsa(dev, MACSEC_DEL_TXSA, tx_sa, assoc_num,
+				     NULL);
+	if (ret) {
+		rtnl_unlock();
+		return ret;
+	}
+
 	RCU_INIT_POINTER(tx_sc->sa[assoc_num], NULL);
 	clear_tx_sa(tx_sa);
 
@@ -1872,6 +2074,7 @@ static int macsec_upd_txsa(struct sk_buff *skb, struct genl_info *info)
 	struct macsec_tx_sa *tx_sa;
 	u8 assoc_num;
 	struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
+	int ret;
 
 	if (!attrs[MACSEC_ATTR_IFINDEX])
 		return -EINVAL;
@@ -1902,9 +2105,16 @@ static int macsec_upd_txsa(struct sk_buff *skb, struct genl_info *info)
 	if (assoc_num == tx_sc->encoding_sa)
 		secy->operational = tx_sa->active;
 
+	ret = macsec_hw_offload_txsa(dev, MACSEC_UPD_TXSA, tx_sa, assoc_num,
+				     NULL);
+	if (ret) {
+		tx_sa->active = !tx_sa->active;
+		secy->operational = tx_sa->active;
+	}
+
 	rtnl_unlock();
 
-	return 0;
+	return ret;
 }
 
 static int macsec_upd_rxsa(struct sk_buff *skb, struct genl_info *info)
@@ -1917,6 +2127,7 @@ static int macsec_upd_rxsa(struct sk_buff *skb, struct genl_info *info)
 	u8 assoc_num;
 	struct nlattr *tb_rxsc[MACSEC_RXSC_ATTR_MAX + 1];
 	struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
+	int ret;
 
 	if (!attrs[MACSEC_ATTR_IFINDEX])
 		return -EINVAL;
@@ -1947,8 +2158,13 @@ static int macsec_upd_rxsa(struct sk_buff *skb, struct genl_info *info)
 	if (tb_sa[MACSEC_SA_ATTR_ACTIVE])
 		rx_sa->active = nla_get_u8(tb_sa[MACSEC_SA_ATTR_ACTIVE]);
 
+	ret = macsec_hw_offload_rxsa(dev, MACSEC_UPD_RXSA, rx_sa, assoc_num,
+				     NULL);
+	if (ret)
+		rx_sa->active = !rx_sa->active;
+
 	rtnl_unlock();
-	return 0;
+	return ret;
 }
 
 static int macsec_upd_rxsc(struct sk_buff *skb, struct genl_info *info)
@@ -2545,11 +2761,15 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
 {
 	struct macsec_dev *macsec = netdev_priv(dev);
 	struct macsec_secy *secy = &macsec->secy;
+	struct macsec_tx_sc *tx_sc = &secy->tx_sc;
 	struct pcpu_secy_stats *secy_stats;
+	struct macsec_tx_sa *tx_sa;
 	int ret, len;
 
+	tx_sa = macsec_txsa_get(tx_sc->sa[tx_sc->encoding_sa]);
+
 	/* 10.5 */
-	if (!secy->protect_frames) {
+	if (!secy->protect_frames || macsec_hw_offload_capable(macsec)) {
 		secy_stats = this_cpu_ptr(macsec->stats);
 		u64_stats_update_begin(&secy_stats->syncp);
 		secy_stats->stats.OutPktsUntagged++;
@@ -2662,6 +2882,15 @@ static int macsec_dev_open(struct net_device *dev)
 			goto clear_allmulti;
 	}
 
+	if (macsec_hw_offload_capable(macsec)) {
+		struct netdev_macsec ms;
+
+		memset(&ms, 0, sizeof(ms));
+		ms.command = MACSEC_DEV_OPEN;
+
+		macsec_hw_offload(dev, &ms);
+	}
+
 	if (netif_carrier_ok(real_dev))
 		netif_carrier_on(dev);
 
@@ -2682,6 +2911,15 @@ static int macsec_dev_stop(struct net_device *dev)
 
 	netif_carrier_off(dev);
 
+	if (macsec_hw_offload_capable(macsec)) {
+		struct netdev_macsec ms;
+
+		memset(&ms, 0, sizeof(ms));
+		ms.command = MACSEC_DEV_STOP;
+
+		macsec_hw_offload(dev, &ms);
+	}
+
 	dev_mc_unsync(real_dev, dev);
 	dev_uc_unsync(real_dev, dev);
 
@@ -2921,6 +3159,9 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],
 			     struct nlattr *data[],
 			     struct netlink_ext_ack *extack)
 {
+	struct macsec_dev *macsec = macsec_priv(dev);
+	int ret;
+
 	if (!data)
 		return 0;
 
@@ -2930,7 +3171,11 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],
 	    data[IFLA_MACSEC_PORT])
 		return -EINVAL;
 
-	return macsec_changelink_common(dev, data);
+	ret = macsec_changelink_common(dev, data);
+	if (ret)
+		return ret;
+
+	return macsec_hw_offload_secy(dev, MACSEC_UPD_SECY, &macsec->secy);
 }
 
 static void macsec_del_dev(struct macsec_dev *macsec)
@@ -2973,6 +3218,7 @@ static void macsec_dellink(struct net_device *dev, struct list_head *head)
 	struct net_device *real_dev = macsec->real_dev;
 	struct macsec_rxh_data *rxd = macsec_data_rtnl(real_dev);
 
+	macsec_hw_offload_secy(dev, MACSEC_DEL_SECY, &macsec->secy);
 	macsec_common_dellink(dev, head);
 
 	if (list_empty(&rxd->secys)) {
@@ -3068,7 +3314,8 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
 			  struct netlink_ext_ack *extack)
 {
 	struct macsec_dev *macsec = macsec_priv(dev);
-	struct net_device *real_dev;
+	struct net_device *real_dev, *loop_dev;
+	struct net *loop_net;
 	int err;
 	sci_t sci;
 	u8 icv_len = DEFAULT_ICV_LEN;
@@ -3080,6 +3327,25 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
 	if (!real_dev)
 		return -ENODEV;
 
+	for_each_net(loop_net) {
+		for_each_netdev(loop_net, loop_dev) {
+			struct macsec_dev *priv;
+
+			if (!netif_is_macsec(loop_dev))
+				continue;
+
+			priv = macsec_priv(loop_dev);
+
+			/* A limitation of the MACsec h/w offloading is only a
+			 * single MACsec interface can be created for a given
+			 * real interface.
+			 */
+			if (macsec_hw_offload_capable(priv) &&
+			    priv->real_dev == real_dev)
+				return -EBUSY;
+		}
+	}
+
 	dev->priv_flags |= IFF_MACSEC;
 
 	macsec->real_dev = real_dev;
@@ -3137,6 +3403,10 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
 	if (err < 0)
 		goto del_dev;
 
+	err = macsec_hw_offload_secy(dev, MACSEC_ADD_SECY, &macsec->secy);
+	if (err)
+		goto del_dev;
+
 	netif_stacked_transfer_operstate(real_dev, dev);
 	linkwatch_fire_event(dev);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 08/10] net: phy: export __phy_read_page/__phy_write_page
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
                   ` (6 preceding siblings ...)
  2019-01-23 15:56 ` [PATCH net-next 07/10] net: macsec: hardware offloading infrastructure Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 09/10] net: phy: mscc: macsec initialization Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 10/10] net: phy: mscc: macsec support Antoine Tenart
  9 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch exports the __phy_read_page and __phy_write_page helpers, to
allow reading and setting the current page when a function already holds
the MDIO lock.

This is something the Microsemi PHY driver does during its
initialization because parts of its registers and engines are shared
between ports. With the upcoming MACsec offloading support in this PHY,
we'll need to configure the MACsec engine and to do so changing pages is
required.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/phy/phy-core.c | 6 ++++--
 include/linux/phy.h        | 3 +++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 909b3344babf..be0c65b6e2da 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -538,15 +538,17 @@ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
 }
 EXPORT_SYMBOL_GPL(phy_modify);
 
-static int __phy_read_page(struct phy_device *phydev)
+int __phy_read_page(struct phy_device *phydev)
 {
 	return phydev->drv->read_page(phydev);
 }
+EXPORT_SYMBOL_GPL(__phy_read_page);
 
-static int __phy_write_page(struct phy_device *phydev, int page)
+int __phy_write_page(struct phy_device *phydev, int page)
 {
 	return phydev->drv->write_page(phydev, page);
 }
+EXPORT_SYMBOL_GPL(__phy_write_page);
 
 /**
  * phy_save_page() - take the bus lock and save the current page
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 21839f352e7c..5f17080bc697 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -766,6 +766,9 @@ static inline int __phy_write(struct phy_device *phydev, u32 regnum, u16 val)
 			       val);
 }
 
+int __phy_read_page(struct phy_device *phydev);
+int __phy_write_page(struct phy_device *phydev, int page);
+
 int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
 int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 09/10] net: phy: mscc: macsec initialization
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
                   ` (7 preceding siblings ...)
  2019-01-23 15:56 ` [PATCH net-next 08/10] net: phy: export __phy_read_page/__phy_write_page Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  2019-01-23 15:56 ` [PATCH net-next 10/10] net: phy: mscc: macsec support Antoine Tenart
  9 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch adds support for initializing the MACsec engine found within
the Microsemi Ocelot PHY. The engine is initialized in a passthrough
mode and does not modify any incoming or outgoing packet. But thanks to
this it now can be configured to perform MACsec transformations on
packets, which will be supported by a future patch.

The MACsec read and write functions are wrapped into two versions: one
called during the init phase, and the other one later on. This is
because the init functions in the Microsemi Ocelot PHY driver are called
while the MDIO bus lock is taken.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/phy/mscc.c           | 401 +++++++++++++++++++++++++++++++
 drivers/net/phy/mscc_fc_buffer.h |  64 +++++
 drivers/net/phy/mscc_mac.h       | 159 ++++++++++++
 drivers/net/phy/mscc_macsec.h    | 256 ++++++++++++++++++++
 4 files changed, 880 insertions(+)
 create mode 100644 drivers/net/phy/mscc_fc_buffer.h
 create mode 100644 drivers/net/phy/mscc_mac.h
 create mode 100644 drivers/net/phy/mscc_macsec.h

diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index db50efb30df5..f82d7632fb4a 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -18,6 +18,10 @@
 #include <linux/netdevice.h>
 #include <dt-bindings/net/mscc-phy-vsc8531.h>
 
+#include "mscc_macsec.h"
+#include "mscc_mac.h"
+#include "mscc_fc_buffer.h"
+
 enum rgmii_rx_clock_delay {
 	RGMII_RX_CLK_DELAY_0_2_NS = 0,
 	RGMII_RX_CLK_DELAY_0_8_NS = 1,
@@ -85,12 +89,33 @@ enum rgmii_rx_clock_delay {
 #define LED_MODE_SEL_MASK(x)		  (GENMASK(3, 0) << LED_MODE_SEL_POS(x))
 #define LED_MODE_SEL(x, mode)		  (((mode) << LED_MODE_SEL_POS(x)) & LED_MODE_SEL_MASK(x))
 
+#define MSCC_EXT_PAGE_MACSEC_17		  17
+#define MSCC_EXT_PAGE_MACSEC_18		  18
+
+#define MSCC_EXT_PAGE_MACSEC_19		  19
+#define MSCC_PHY_MACSEC_19_REG_ADDR(x)	  (x)
+#define MSCC_PHY_MACSEC_19_TARGET(x)	  ((x) << 12)
+#define MSCC_PHY_MACSEC_19_READ		  BIT(14)
+#define MSCC_PHY_MACSEC_19_CMD		  BIT(15)
+
+#define MSCC_EXT_PAGE_MACSEC_20		  20
+#define MSCC_PHY_MACSEC_20_TARGET(x)	  (x)
+enum macsec_bank {
+	FC_BUFFER   = 0x04,
+	HOST_MAC    = 0x05,
+	LINE_MAC    = 0x06,
+	IP_1588     = 0x0e,
+	MACSEC_INGR = 0x38,
+	MACSEC_EGR  = 0x3c,
+};
+
 #define MSCC_EXT_PAGE_ACCESS		  31
 #define MSCC_PHY_PAGE_STANDARD		  0x0000 /* Standard registers */
 #define MSCC_PHY_PAGE_EXTENDED		  0x0001 /* Extended registers */
 #define MSCC_PHY_PAGE_EXTENDED_2	  0x0002 /* Extended reg - page 2 */
 #define MSCC_PHY_PAGE_EXTENDED_3	  0x0003 /* Extended reg - page 3 */
 #define MSCC_PHY_PAGE_EXTENDED_4	  0x0004 /* Extended reg - page 4 */
+#define MSCC_PHY_PAGE_MACSEC		  MSCC_PHY_PAGE_EXTENDED_4
 /* Extended reg - GPIO; this is a bank of registers that are shared for all PHYs
  * in the same package.
  */
@@ -1538,6 +1563,377 @@ static int vsc8584_config_pre_init(struct phy_device *phydev)
 	return ret;
 }
 
+static u32 __vsc8584_macsec_phy_read(struct phy_device *phydev,
+				     enum macsec_bank bank, u32 reg, bool init)
+{
+	u32 val, val_l = 0, val_h = 0;
+	unsigned long deadline;
+	int rc;
+
+	if (!init) {
+		rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
+		if (rc < 0)
+			goto failed;
+	} else {
+		__phy_write_page(phydev, MSCC_PHY_PAGE_MACSEC);
+	}
+
+	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
+		    MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
+
+	if (bank >> 2 == 0x1)
+		/* non-MACsec access */
+		bank &= 0x3;
+	else
+		bank = 0;
+
+	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
+		    MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_READ |
+		    MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
+		    MSCC_PHY_MACSEC_19_TARGET(bank));
+
+	deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
+	do {
+		val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
+	} while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
+
+	val_l = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_17);
+	val_h = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_18);
+
+	if (!init) {
+failed:
+		phy_restore_page(phydev, rc, rc);
+	} else {
+		__phy_write_page(phydev, MSCC_PHY_PAGE_STANDARD);
+	}
+
+	return (val_h << 16) | val_l;
+}
+
+static u32 vsc8584_macsec_init_phy_read(struct phy_device *phydev,
+					enum macsec_bank bank, u32 reg)
+{
+	return __vsc8584_macsec_phy_read(phydev, bank, reg, true);
+}
+
+static u32 vsc8584_macsec_phy_read(struct phy_device *phydev,
+				   enum macsec_bank bank, u32 reg)
+{
+	return __vsc8584_macsec_phy_read(phydev, bank, reg, false);
+}
+
+static void __vsc8584_macsec_phy_write(struct phy_device *phydev,
+				       enum macsec_bank bank, u32 reg, u32 val,
+				       bool init)
+{
+	unsigned long deadline;
+	int rc;
+
+	if (!init) {
+		rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
+		if (rc < 0)
+			goto failed;
+	} else {
+		__phy_write_page(phydev, MSCC_PHY_PAGE_MACSEC);
+	}
+
+	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
+		    MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
+
+	if ((bank >> 2 == 0x1) || (bank >> 2 == 0x3))
+		bank &= 0x3;
+	else
+		/* MACsec access */
+		bank = 0;
+
+	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_17, (u16)val);
+	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_18, (u16)(val >> 16));
+
+	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
+		    MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
+		    MSCC_PHY_MACSEC_19_TARGET(bank));
+
+	deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
+	do {
+		val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
+	} while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
+
+	if (!init) {
+failed:
+		phy_restore_page(phydev, rc, rc);
+	} else {
+		__phy_write_page(phydev, MSCC_PHY_PAGE_STANDARD);
+	}
+}
+
+static void vsc8584_macsec_init_phy_write(struct phy_device *phydev,
+					  enum macsec_bank bank, u32 reg,
+					  u32 val)
+{
+	return __vsc8584_macsec_phy_write(phydev, bank, reg, val, true);
+}
+
+static void vsc8584_macsec_phy_write(struct phy_device *phydev,
+				     enum macsec_bank bank, u32 reg, u32 val)
+{
+	return __vsc8584_macsec_phy_write(phydev, bank, reg, val, false);
+}
+
+static void vsc8584_macsec_classification(struct phy_device *phydev,
+					  enum macsec_bank bank)
+{
+	/* enable VLAN tag parsing */
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_SAM_CP_TAG,
+				      MSCC_MS_SAM_CP_TAG_PARSE_STAG |
+				      MSCC_MS_SAM_CP_TAG_PARSE_QTAG |
+				      MSCC_MS_SAM_CP_TAG_PARSE_QINQ);
+}
+
+static void vsc8584_macsec_flow_default_action(struct phy_device *phydev,
+					       enum macsec_bank bank)
+{
+	u32 port = (bank == MACSEC_INGR) ?
+		   MSCC_MS_PORT_CONTROLLED : MSCC_MS_PORT_COMMON;
+
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_NCP,
+				      /* MACsec untagged */
+				      MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+				      MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DEST_PORT(port) |
+				      /* MACsec tagged */
+				      MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+				      MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DEST_PORT(port) |
+				      /* Bad tag */
+				      MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+				      MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DEST_PORT(port) |
+				      /* Kay tag */
+				      MSCC_MS_SAM_NM_FLOW_NCP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+				      MSCC_MS_SAM_NM_FLOW_NCP_KAY_DEST_PORT(port));
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_CP,
+				      /* MACsec untagged */
+				      MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+				      MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DEST_PORT(port) |
+				      /* MACsec tagged */
+				      MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+				      MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DEST_PORT(port) |
+				      /* Bad tag */
+				      MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+				      MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DEST_PORT(port) |
+				      /* Kay tag */
+				      MSCC_MS_SAM_NM_FLOW_CP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+				      MSCC_MS_SAM_NM_FLOW_CP_KAY_DEST_PORT(port));
+}
+
+static void vsc8584_macsec_integrity_checks(struct phy_device *phydev,
+					    enum macsec_bank bank)
+{
+	u32 val;
+
+	if (bank != MACSEC_INGR)
+		return;
+
+	/* Set default rules to pass unmatched frames */
+	val = vsc8584_macsec_init_phy_read(phydev, bank,
+					   MSCC_MS_PARAMS2_IG_CC_CONTROL);
+	val |= MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_CTRL_ACT |
+	       MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_ACT;
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CC_CONTROL,
+				      val);
+
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CP_TAG,
+				      MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_STAG |
+				      MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QTAG |
+				      MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QINQ);
+}
+
+static void vsc8584_macsec_block_init(struct phy_device *phydev,
+				      enum macsec_bank bank)
+{
+	u32 val;
+	int i;
+
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
+				      MSCC_MS_ENA_CFG_SW_RST |
+				      MSCC_MS_ENA_CFG_MACSEC_BYPASS_ENA);
+
+	/* Set the MACsec block out of s/w reset and enable clocks */
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
+				      MSCC_MS_ENA_CFG_CLK_ENA);
+
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_STATUS_CONTEXT_CTRL,
+				      bank == MACSEC_INGR ? 0xe5880214 : 0xe5880218);
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_MISC_CONTROL,
+				      MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX(bank == MACSEC_INGR ? 57 : 40) |
+				      MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE(bank == MACSEC_INGR ? 1 : 2));
+
+	/* Clear the counters */
+	val = vsc8584_macsec_init_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
+	val |= MSCC_MS_COUNT_CONTROL_AUTO_CNTR_RESET;
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
+
+	/* Enable octet increment mode */
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_PP_CTRL,
+				      MSCC_MS_PP_CTRL_MACSEC_OCTET_INCR_MODE);
+
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_BLOCK_CTX_UPDATE, 0x3);
+
+	val = vsc8584_macsec_init_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
+	val |= MSCC_MS_COUNT_CONTROL_RESET_ALL;
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
+
+	/* Set the MTU */
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_NON_VLAN_MTU_CHECK,
+				      MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE(32761) |
+				      MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMP_DROP);
+
+	for (i = 0; i < 8; i++)
+		vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_VLAN_MTU_CHECK(i),
+					      MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE(32761) |
+					      MSCC_MS_VLAN_MTU_CHECK_MTU_COMP_DROP);
+
+	if (bank == MACSEC_EGR) {
+		val = vsc8584_macsec_init_phy_read(phydev, bank, MSCC_MS_INTR_CTRL_STATUS);
+		val &= ~MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE_M;
+		vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_INTR_CTRL_STATUS, val);
+
+		vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_FC_CFG,
+					      MSCC_MS_FC_CFG_FCBUF_ENA |
+					      MSCC_MS_FC_CFG_LOW_THRESH(0x1) |
+					      MSCC_MS_FC_CFG_HIGH_THRESH(0x4) |
+					      MSCC_MS_FC_CFG_LOW_BYTES_VAL(0x4) |
+					      MSCC_MS_FC_CFG_HIGH_BYTES_VAL(0x6));
+	}
+
+	vsc8584_macsec_classification(phydev, bank);
+	vsc8584_macsec_flow_default_action(phydev, bank);
+	vsc8584_macsec_integrity_checks(phydev, bank);
+
+	/* Enable the MACsec block */
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
+				      MSCC_MS_ENA_CFG_CLK_ENA |
+				      MSCC_MS_ENA_CFG_MACSEC_ENA |
+				      MSCC_MS_ENA_CFG_MACSEC_SPEED_MODE(0x5));
+}
+
+static void vsc8584_macsec_mac_init(struct phy_device *phydev,
+				    enum macsec_bank bank)
+{
+	u32 val;
+	int i;
+
+	/* Clear host & line stats */
+	for (i = 0; i < 36; i++)
+		vsc8584_macsec_init_phy_write(phydev, bank, 0x1c + i, 0);
+
+	val = vsc8584_macsec_init_phy_read(phydev, bank,
+					   MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL);
+	val &= ~MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE_M;
+	val |= MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE(2) |
+	       MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE(0xffff);
+	vsc8584_macsec_init_phy_write(phydev, bank,
+				      MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL, val);
+
+	val = vsc8584_macsec_init_phy_read(phydev, bank,
+					   MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2);
+	val |= 0xffff;
+	vsc8584_macsec_init_phy_write(phydev, bank,
+				      MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2, val);
+
+	val = vsc8584_macsec_init_phy_read(phydev, bank,
+					   MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL);
+	if (bank == HOST_MAC)
+		val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_TIMER_ENA |
+		       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA;
+	else
+		val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_REACT_ENA |
+		       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA |
+		       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_MODE |
+		       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_EARLY_PAUSE_DETECT_ENA;
+	vsc8584_macsec_init_phy_write(phydev, bank,
+				      MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL, val);
+
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MAC_CFG_PKTINF_CFG,
+				      MSCC_MAC_CFG_PKTINF_CFG_STRIP_FCS_ENA |
+				      MSCC_MAC_CFG_PKTINF_CFG_INSERT_FCS_ENA |
+				      MSCC_MAC_CFG_PKTINF_CFG_LPI_RELAY_ENA |
+				      MSCC_MAC_CFG_PKTINF_CFG_STRIP_PREAMBLE_ENA |
+				      MSCC_MAC_CFG_PKTINF_CFG_INSERT_PREAMBLE_ENA |
+				      (bank == HOST_MAC ?
+				       MSCC_MAC_CFG_PKTINF_CFG_ENABLE_TX_PADDING : 0));
+
+	val = vsc8584_macsec_init_phy_read(phydev, bank, MSCC_MAC_CFG_MODE_CFG);
+	val &= ~MSCC_MAC_CFG_MODE_CFG_DISABLE_DIC;
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MAC_CFG_MODE_CFG, val);
+
+	val = vsc8584_macsec_init_phy_read(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG);
+	val &= ~MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_M;
+	val |= MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN(10240);
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG, val);
+
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MAC_CFG_ADV_CHK_CFG,
+				      MSCC_MAC_CFG_ADV_CHK_CFG_SFD_CHK_ENA |
+				      MSCC_MAC_CFG_ADV_CHK_CFG_PRM_CHK_ENA |
+				      MSCC_MAC_CFG_ADV_CHK_CFG_OOR_ERR_ENA |
+				      MSCC_MAC_CFG_ADV_CHK_CFG_INR_ERR_ENA);
+
+	val = vsc8584_macsec_init_phy_read(phydev, bank, MSCC_MAC_CFG_LFS_CFG);
+	val &= ~MSCC_MAC_CFG_LFS_CFG_LFS_MODE_ENA;
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MAC_CFG_LFS_CFG, val);
+
+	vsc8584_macsec_init_phy_write(phydev, bank, MSCC_MAC_CFG_ENA_CFG,
+				      MSCC_MAC_CFG_ENA_CFG_RX_CLK_ENA |
+				      MSCC_MAC_CFG_ENA_CFG_TX_CLK_ENA |
+				      MSCC_MAC_CFG_ENA_CFG_RX_ENA |
+				      MSCC_MAC_CFG_ENA_CFG_TX_ENA);
+}
+
+/* Must be called with mdio_lock taken */
+static int vsc8584_macsec_init(struct phy_device *phydev)
+{
+	u32 val;
+
+	vsc8584_macsec_block_init(phydev, MACSEC_INGR);
+	vsc8584_macsec_block_init(phydev, MACSEC_EGR);
+	vsc8584_macsec_mac_init(phydev, HOST_MAC);
+	vsc8584_macsec_mac_init(phydev, LINE_MAC);
+
+	vsc8584_macsec_init_phy_write(phydev, FC_BUFFER,
+				      MSCC_FCBUF_FC_READ_THRESH_CFG,
+				      MSCC_FCBUF_FC_READ_THRESH_CFG_TX_THRESH(4) |
+				      MSCC_FCBUF_FC_READ_THRESH_CFG_RX_THRESH(5));
+
+	val = vsc8584_macsec_init_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG);
+	val |= MSCC_FCBUF_MODE_CFG_PAUSE_GEN_ENA |
+	       MSCC_FCBUF_MODE_CFG_RX_PPM_RATE_ADAPT_ENA |
+	       MSCC_FCBUF_MODE_CFG_TX_PPM_RATE_ADAPT_ENA;
+	vsc8584_macsec_init_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG, val);
+
+	vsc8584_macsec_init_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG,
+				      MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_THRESH(8) |
+				      MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_OFFSET(9));
+
+	val = vsc8584_macsec_init_phy_read(phydev, FC_BUFFER,
+					   MSCC_FCBUF_TX_DATA_QUEUE_CFG);
+	val &= ~(MSCC_FCBUF_TX_DATA_QUEUE_CFG_START_M |
+		 MSCC_FCBUF_TX_DATA_QUEUE_CFG_END_M);
+	val |= MSCC_FCBUF_TX_DATA_QUEUE_CFG_START(0) |
+		MSCC_FCBUF_TX_DATA_QUEUE_CFG_END(5119);
+	vsc8584_macsec_init_phy_write(phydev, FC_BUFFER,
+				      MSCC_FCBUF_TX_DATA_QUEUE_CFG, val);
+
+	val = vsc8584_macsec_init_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG);
+	val |= MSCC_FCBUF_ENA_CFG_TX_ENA | MSCC_FCBUF_ENA_CFG_RX_ENA;
+	vsc8584_macsec_init_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG, val);
+
+	val = vsc8584_macsec_init_phy_read(phydev, IP_1588,
+					   MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL);
+	val &= ~MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE_M;
+	val |= MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE(4);
+	vsc8584_macsec_init_phy_write(phydev, IP_1588,
+				      MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL, val);
+
+	return 0;
+}
+
 /* Check if one PHY has already done the init of the parts common to all PHYs
  * in the Quad PHY package.
  */
@@ -1667,6 +2063,11 @@ static int vsc8584_config_init(struct phy_device *phydev)
 	if (ret)
 		goto err;
 
+	/* MACsec */
+	ret = vsc8584_macsec_init(phydev);
+	if (ret)
+		goto err;
+
 	mutex_unlock(&phydev->mdio.bus->mdio_lock);
 
 	phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
diff --git a/drivers/net/phy/mscc_fc_buffer.h b/drivers/net/phy/mscc_fc_buffer.h
new file mode 100644
index 000000000000..7e9c0e877895
--- /dev/null
+++ b/drivers/net/phy/mscc_fc_buffer.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (C) 2019 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_FC_BUFFER_H_
+#define _MSCC_OCELOT_FC_BUFFER_H_
+
+#define MSCC_FCBUF_ENA_CFG					0x00
+#define MSCC_FCBUF_MODE_CFG					0x01
+#define MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG			0x02
+#define MSCC_FCBUF_TX_CTRL_QUEUE_CFG				0x03
+#define MSCC_FCBUF_TX_DATA_QUEUE_CFG				0x04
+#define MSCC_FCBUF_RX_DATA_QUEUE_CFG				0x05
+#define MSCC_FCBUF_TX_BUFF_XON_XOFF_THRESH_CFG			0x06
+#define MSCC_FCBUF_FC_READ_THRESH_CFG				0x07
+#define MSCC_FCBUF_TX_FRM_GAP_COMP				0x08
+
+#define MSCC_FCBUF_ENA_CFG_TX_ENA				BIT(0)
+#define MSCC_FCBUF_ENA_CFG_RX_ENA				BIT(4)
+
+#define MSCC_FCBUF_MODE_CFG_DROP_BEHAVIOUR			BIT(4)
+#define MSCC_FCBUF_MODE_CFG_PAUSE_REACT_ENA			BIT(8)
+#define MSCC_FCBUF_MODE_CFG_RX_PPM_RATE_ADAPT_ENA		BIT(12)
+#define MSCC_FCBUF_MODE_CFG_TX_PPM_RATE_ADAPT_ENA		BIT(16)
+#define MSCC_FCBUF_MODE_CFG_TX_CTRL_QUEUE_ENA			BIT(20)
+#define MSCC_FCBUF_MODE_CFG_PAUSE_GEN_ENA			BIT(24)
+#define MSCC_FCBUF_MODE_CFG_INCLUDE_PAUSE_RCVD_IN_PAUSE_GEN	BIT(28)
+
+#define MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_THRESH(x)	(x)
+#define MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_THRESH_M	GENMASK(15, 0)
+#define MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_OFFSET(x)	((x) << 16)
+#define MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_OFFSET_M	GENMASK(19, 16)
+#define MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_RX_THRESH(x)	((x) << 20)
+#define MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_RX_THRESH_M	GENMASK(31, 20)
+
+#define MSCC_FCBUF_TX_CTRL_QUEUE_CFG_START(x)			(x)
+#define MSCC_FCBUF_TX_CTRL_QUEUE_CFG_START_M			GENMASK(15, 0)
+#define MSCC_FCBUF_TX_CTRL_QUEUE_CFG_END(x)			((x) << 16)
+#define MSCC_FCBUF_TX_CTRL_QUEUE_CFG_END_M			GENMASK(31, 16)
+
+#define MSCC_FCBUF_TX_DATA_QUEUE_CFG_START(x)			(x)
+#define MSCC_FCBUF_TX_DATA_QUEUE_CFG_START_M			GENMASK(15, 0)
+#define MSCC_FCBUF_TX_DATA_QUEUE_CFG_END(x)			((x) << 16)
+#define MSCC_FCBUF_TX_DATA_QUEUE_CFG_END_M			GENMASK(31, 16)
+
+#define MSCC_FCBUF_RX_DATA_QUEUE_CFG_START(x)			(x)
+#define MSCC_FCBUF_RX_DATA_QUEUE_CFG_START_M			GENMASK(15, 0)
+#define MSCC_FCBUF_RX_DATA_QUEUE_CFG_END(x)			((x) << 16)
+#define MSCC_FCBUF_RX_DATA_QUEUE_CFG_END_M			GENMASK(31, 16)
+
+#define MSCC_FCBUF_TX_BUFF_XON_XOFF_THRESH_CFG_XOFF_THRESH(x)	(x)
+#define MSCC_FCBUF_TX_BUFF_XON_XOFF_THRESH_CFG_XOFF_THRESH_M	GENMASK(15, 0)
+#define MSCC_FCBUF_TX_BUFF_XON_XOFF_THRESH_CFG_XON_THRESH(x)	((x) << 16)
+#define MSCC_FCBUF_TX_BUFF_XON_XOFF_THRESH_CFG_XON_THRESH_M	GENMASK(31, 16)
+
+#define MSCC_FCBUF_FC_READ_THRESH_CFG_TX_THRESH(x)		(x)
+#define MSCC_FCBUF_FC_READ_THRESH_CFG_TX_THRESH_M		GENMASK(15, 0)
+#define MSCC_FCBUF_FC_READ_THRESH_CFG_RX_THRESH(x)		((x) << 16)
+#define MSCC_FCBUF_FC_READ_THRESH_CFG_RX_THRESH_M		GENMASK(31, 16)
+
+#endif
diff --git a/drivers/net/phy/mscc_mac.h b/drivers/net/phy/mscc_mac.h
new file mode 100644
index 000000000000..9420ee5175a6
--- /dev/null
+++ b/drivers/net/phy/mscc_mac.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_LINE_MAC_H_
+#define _MSCC_OCELOT_LINE_MAC_H_
+
+#define MSCC_MAC_CFG_ENA_CFG					0x00
+#define MSCC_MAC_CFG_MODE_CFG					0x01
+#define MSCC_MAC_CFG_MAXLEN_CFG					0x02
+#define MSCC_MAC_CFG_NUM_TAGS_CFG				0x03
+#define MSCC_MAC_CFG_TAGS_CFG					0x04
+#define MSCC_MAC_CFG_ADV_CHK_CFG				0x07
+#define MSCC_MAC_CFG_LFS_CFG					0x08
+#define MSCC_MAC_CFG_LB_CFG					0x09
+#define MSCC_MAC_CFG_PKTINF_CFG					0x0a
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL			0x0b
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2			0x0c
+#define MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL			0x0d
+#define MSCC_MAC_PAUSE_CFG_STATE				0x0e
+#define MSCC_MAC_PAUSE_CFG_MAC_ADDRESS_LSB			0x0f
+#define MSCC_MAC_PAUSE_CFG_MAC_ADDRESS_MSB			0x10
+#define MSCC_MAC_STATUS_RX_LANE_STICKY_0			0x11
+#define MSCC_MAC_STATUS_RX_LANE_STICKY_1			0x12
+#define MSCC_MAC_STATUS_TX_MONITOR_STICKY			0x13
+#define MSCC_MAC_STATUS_TX_MONITOR_STICKY_MASK			0x14
+#define MSCC_MAC_STATUS_STICKY					0x15
+#define MSCC_MAC_STATUS_STICKY_MASK				0x16
+#define MSCC_MAC_STATS_32BIT_RX_HIH_CKSM_ERR_CNT		0x17
+#define MSCC_MAC_STATS_32BIT_RX_XGMII_PROT_ERR_CNT		0x18
+#define MSCC_MAC_STATS_32BIT_RX_SYMBOL_ERR_CNT			0x19
+#define MSCC_MAC_STATS_32BIT_RX_PAUSE_CNT			0x1a
+#define MSCC_MAC_STATS_32BIT_RX_UNSUP_OPCODE_CNT		0x1b
+#define MSCC_MAC_STATS_32BIT_RX_UC_CNT				0x1c
+#define MSCC_MAC_STATS_32BIT_RX_MC_CNT				0x1d
+#define MSCC_MAC_STATS_32BIT_RX_BC_CNT				0x1e
+#define MSCC_MAC_STATS_32BIT_RX_CRC_ERR_CNT			0x1f
+#define MSCC_MAC_STATS_32BIT_RX_UNDERSIZE_CNT			0x20
+#define MSCC_MAC_STATS_32BIT_RX_FRAGMENTS_CNT			0x21
+#define MSCC_MAC_STATS_32BIT_RX_IN_RANGE_LEN_ERR_CNT		0x22
+#define MSCC_MAC_STATS_32BIT_RX_OUT_OF_RANGE_LEN_ERR_CNT	0x23
+#define MSCC_MAC_STATS_32BIT_RX_OVERSIZE_CNT			0x24
+#define MSCC_MAC_STATS_32BIT_RX_JABBERS_CNT			0x25
+#define MSCC_MAC_STATS_32BIT_RX_SIZE64_CNT			0x26
+#define MSCC_MAC_STATS_32BIT_RX_SIZE65TO127_CNT			0x27
+#define MSCC_MAC_STATS_32BIT_RX_SIZE128TO255_CNT		0x28
+#define MSCC_MAC_STATS_32BIT_RX_SIZE256TO511_CNT		0x29
+#define MSCC_MAC_STATS_32BIT_RX_SIZE512TO1023_CNT		0x2a
+#define MSCC_MAC_STATS_32BIT_RX_SIZE1024TO1518_CNT		0x2b
+#define MSCC_MAC_STATS_32BIT_RX_SIZE1519TOMAX_CNT		0x2c
+#define MSCC_MAC_STATS_32BIT_RX_IPG_SHRINK_CNT			0x2d
+#define MSCC_MAC_STATS_32BIT_TX_PAUSE_CNT			0x2e
+#define MSCC_MAC_STATS_32BIT_TX_UC_CNT				0x2f
+#define MSCC_MAC_STATS_32BIT_TX_MC_CNT				0x30
+#define MSCC_MAC_STATS_32BIT_TX_BC_CNT				0x31
+#define MSCC_MAC_STATS_32BIT_TX_SIZE64_CNT			0x32
+#define MSCC_MAC_STATS_32BIT_TX_SIZE65TO127_CNT			0x33
+#define MSCC_MAC_STATS_32BIT_TX_SIZE128TO255_CNT		0x34
+#define MSCC_MAC_STATS_32BIT_TX_SIZE256TO511_CNT		0x35
+#define MSCC_MAC_STATS_32BIT_TX_SIZE512TO1023_CNT		0x36
+#define MSCC_MAC_STATS_32BIT_TX_SIZE1024TO1518_CNT		0x37
+#define MSCC_MAC_STATS_32BIT_TX_SIZE1519TOMAX_CNT		0x38
+#define MSCC_MAC_STATS_40BIT_RX_BAD_BYTES_CNT			0x39
+#define MSCC_MAC_STATS_40BIT_RX_BAD_BYTES_MSB_CNT		0x3a
+#define MSCC_MAC_STATS_40BIT_RX_OK_BYTES_CNT			0x3b
+#define MSCC_MAC_STATS_40BIT_RX_OK_BYTES_MSB_CNT		0x3c
+#define MSCC_MAC_STATS_40BIT_RX_IN_BYTES_CNT			0x3d
+#define MSCC_MAC_STATS_40BIT_RX_IN_BYTES_MSB_CNT		0x3e
+#define MSCC_MAC_STATS_40BIT_TX_OK_BYTES_CNT			0x3f
+#define MSCC_MAC_STATS_40BIT_TX_OK_BYTES_MSB_CNT		0x40
+#define MSCC_MAC_STATS_40BIT_TX_OUT_BYTES_CNT			0x41
+#define MSCC_MAC_STATS_40BIT_TX_OUT_BYTES_MSB_CNT		0x42
+
+#define MSCC_MAC_CFG_ENA_CFG_RX_CLK_ENA				BIT(0)
+#define MSCC_MAC_CFG_ENA_CFG_TX_CLK_ENA				BIT(4)
+#define MSCC_MAC_CFG_ENA_CFG_RX_SW_RST				BIT(8)
+#define MSCC_MAC_CFG_ENA_CFG_TX_SW_RST				BIT(12)
+#define MSCC_MAC_CFG_ENA_CFG_RX_ENA				BIT(16)
+#define MSCC_MAC_CFG_ENA_CFG_TX_ENA				BIT(20)
+
+#define MSCC_MAC_CFG_MODE_CFG_FORCE_CW_UPDATE_INTERVAL(x)	((x) << 20)
+#define MSCC_MAC_CFG_MODE_CFG_FORCE_CW_UPDATE_INTERVAL_M	GENMASK(29, 20)
+#define MSCC_MAC_CFG_MODE_CFG_FORCE_CW_UPDATE			BIT(16)
+#define MSCC_MAC_CFG_MODE_CFG_TUNNEL_PAUSE_FRAMES		BIT(14)
+#define MSCC_MAC_CFG_MODE_CFG_MAC_PREAMBLE_CFG(x)		((x) << 10)
+#define MSCC_MAC_CFG_MODE_CFG_MAC_PREAMBLE_CFG_M		GENMASK(12, 10)
+#define MSCC_MAC_CFG_MODE_CFG_MAC_IPG_CFG			BIT(6)
+#define MSCC_MAC_CFG_MODE_CFG_XGMII_GEN_MODE_ENA		BIT(4)
+#define MSCC_MAC_CFG_MODE_CFG_HIH_CRC_CHECK			BIT(2)
+#define MSCC_MAC_CFG_MODE_CFG_UNDERSIZED_FRAME_DROP_DIS		BIT(1)
+#define MSCC_MAC_CFG_MODE_CFG_DISABLE_DIC			BIT(0)
+
+#define MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_TAG_CHK			BIT(16)
+#define MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN(x)			(x)
+#define MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_M			GENMASK(15, 0)
+
+#define MSCC_MAC_CFG_TAGS_CFG_RSZ				0x4
+#define MSCC_MAC_CFG_TAGS_CFG_TAG_ID(x)				((x) << 16)
+#define MSCC_MAC_CFG_TAGS_CFG_TAG_ID_M				GENMASK(31, 16)
+#define MSCC_MAC_CFG_TAGS_CFG_TAG_ENA				BIT(4)
+
+#define MSCC_MAC_CFG_ADV_CHK_CFG_EXT_EOP_CHK_ENA		BIT(24)
+#define MSCC_MAC_CFG_ADV_CHK_CFG_EXT_SOP_CHK_ENA		BIT(20)
+#define MSCC_MAC_CFG_ADV_CHK_CFG_SFD_CHK_ENA			BIT(16)
+#define MSCC_MAC_CFG_ADV_CHK_CFG_PRM_SHK_CHK_DIS		BIT(12)
+#define MSCC_MAC_CFG_ADV_CHK_CFG_PRM_CHK_ENA			BIT(8)
+#define MSCC_MAC_CFG_ADV_CHK_CFG_OOR_ERR_ENA			BIT(4)
+#define MSCC_MAC_CFG_ADV_CHK_CFG_INR_ERR_ENA			BIT(0)
+
+#define MSCC_MAC_CFG_LFS_CFG_LFS_INH_TX				BIT(8)
+#define MSCC_MAC_CFG_LFS_CFG_LFS_DIS_TX				BIT(4)
+#define MSCC_MAC_CFG_LFS_CFG_LFS_UNIDIR_ENA			BIT(3)
+#define MSCC_MAC_CFG_LFS_CFG_USE_LEADING_EDGE_DETECT		BIT(2)
+#define MSCC_MAC_CFG_LFS_CFG_SPURIOUS_Q_DIS			BIT(1)
+#define MSCC_MAC_CFG_LFS_CFG_LFS_MODE_ENA			BIT(0)
+
+#define MSCC_MAC_CFG_LB_CFG_XGMII_HOST_LB_ENA			BIT(4)
+#define MSCC_MAC_CFG_LB_CFG_XGMII_PHY_LB_ENA			BIT(0)
+
+#define MSCC_MAC_CFG_PKTINF_CFG_STRIP_FCS_ENA			BIT(0)
+#define MSCC_MAC_CFG_PKTINF_CFG_INSERT_FCS_ENA			BIT(4)
+#define MSCC_MAC_CFG_PKTINF_CFG_STRIP_PREAMBLE_ENA		BIT(8)
+#define MSCC_MAC_CFG_PKTINF_CFG_INSERT_PREAMBLE_ENA		BIT(12)
+#define MSCC_MAC_CFG_PKTINF_CFG_LPI_RELAY_ENA			BIT(16)
+#define MSCC_MAC_CFG_PKTINF_CFG_LF_RELAY_ENA			BIT(20)
+#define MSCC_MAC_CFG_PKTINF_CFG_RF_RELAY_ENA			BIT(24)
+#define MSCC_MAC_CFG_PKTINF_CFG_ENABLE_TX_PADDING		BIT(25)
+#define MSCC_MAC_CFG_PKTINF_CFG_ENABLE_RX_PADDING		BIT(26)
+#define MSCC_MAC_CFG_PKTINF_CFG_ENABLE_4BYTE_PREAMBLE		BIT(27)
+#define MSCC_MAC_CFG_PKTINF_CFG_MACSEC_BYPASS_NUM_PTP_STALL_CLKS(x)	((x) << 28)
+#define MSCC_MAC_CFG_PKTINF_CFG_MACSEC_BYPASS_NUM_PTP_STALL_CLKS_M	GENMASK(30, 28)
+
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE(x)		((x) << 16)
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE_M		GENMASK(31, 16)
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_WAIT_FOR_LPI_LOW	BIT(12)
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_USE_PAUSE_STALL_ENA	BIT(8)
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_REPL_MODE	BIT(4)
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_FRC_FRAME	BIT(2)
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE(x)		(x)
+#define MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE_M		GENMASK(1, 0)
+
+#define MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_EARLY_PAUSE_DETECT_ENA	BIT(16)
+#define MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PRE_CRC_MODE		BIT(20)
+#define MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_TIMER_ENA	BIT(12)
+#define MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_REACT_ENA	BIT(8)
+#define MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA	BIT(4)
+#define MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_MODE		BIT(0)
+
+#define MSCC_MAC_PAUSE_CFG_STATE_PAUSE_STATE			BIT(0)
+#define MSCC_MAC_PAUSE_CFG_STATE_MAC_TX_PAUSE_GEN		BIT(4)
+
+#define MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL			0x2
+#define MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE(x)	(x)
+#define MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE_M	GENMASK(2, 0)
+
+#endif /* _MSCC_OCELOT_LINE_MAC_H_ */
diff --git a/drivers/net/phy/mscc_macsec.h b/drivers/net/phy/mscc_macsec.h
new file mode 100644
index 000000000000..52902669e8ca
--- /dev/null
+++ b/drivers/net/phy/mscc_macsec.h
@@ -0,0 +1,256 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_MACSEC_H_
+#define _MSCC_OCELOT_MACSEC_H_
+
+#define CONTROL_TYPE_EGRESS		0x6
+#define CONTROL_TYPE_INGRESS		0xf
+#define CONTROL_IV0			BIT(5)
+#define CONTROL_IV1			BIT(6)
+#define CONTROL_IV2			BIT(7)
+#define CONTROL_UPDATE_SEQ		BIT(13)
+#define CONTROL_IV_IN_SEQ		BIT(14)
+#define CONTROL_ENCRYPT_AUTH		BIT(15)
+#define CONTROL_KEY_IN_CTX		BIT(16)
+#define CONTROL_CRYPTO_ALG(x)		((x) << 17)
+#define     CTRYPTO_ALG_AES_CTR_128	0x5
+#define     CTRYPTO_ALG_AES_CTR_192	0x6
+#define     CTRYPTO_ALG_AES_CTR_256	0x7
+#define CONTROL_DIGEST_TYPE(x)		((x) << 21)
+#define CONTROL_AUTH_ALG(x)		((x) << 23)
+#define     AUTH_ALG_AES_GHAS		0x4
+#define CONTROL_AN(x)			((x) << 26)
+#define CONTROL_SEQ_TYPE(x)		((x) << 28)
+#define CONTROL_SEQ_MASK		BIT(30)
+#define CONTROL_CONTEXT_ID		BIT(31)
+
+enum mscc_macsec_destination_ports {
+	MSCC_MS_PORT_COMMON		= 0,
+	MSCC_MS_PORT_RSVD		= 1,
+	MSCC_MS_PORT_CONTROLLED		= 2,
+	MSCC_MS_PORT_UNCONTROLLED	= 3,
+};
+
+enum mscc_macsec_drop_actions {
+	MSCC_MS_ACTION_BYPASS_CRC	= 0,
+	MSCC_MS_ACTION_BYPASS_BAD	= 1,
+	MSCC_MS_ACTION_DROP		= 2,
+	MSCC_MS_ACTION_BYPASS		= 3,
+};
+
+enum mscc_macsec_flow_types {
+	MSCC_MS_FLOW_BYPASS		= 0,
+	MSCC_MS_FLOW_DROP		= 1,
+	MSCC_MS_FLOW_INGRESS		= 2,
+	MSCC_MS_FLOW_EGRESS		= 3,
+};
+
+enum mscc_macsec_validate_levels {
+	MSCC_MS_VALIDATE_DISABLED	= 0,
+	MSCC_MS_VALIDATE_CHECK		= 1,
+	MSCC_MS_VALIDATE_STRICT		= 2,
+};
+
+#define MSCC_MS_XFORM_REC(x, y)		(((x) << 5) + (y))
+#define MSCC_MS_ENA_CFG			0x800
+#define MSCC_MS_FC_CFG			0x804
+#define MSCC_MS_SAM_MISC_MATCH(x)	(0x1004 + ((x) << 4))
+#define MSCC_MS_SAM_MATCH_SCI_LO(x)	(0x1005 + ((x) << 4))
+#define MSCC_MS_SAM_MATCH_SCI_HI(x)	(0x1006 + ((x) << 4))
+#define MSCC_MS_SAM_MASK(x)		(0x1007 + ((x) << 4))
+#define MSCC_MS_SAM_ENTRY_SET1		0x1808
+#define MSCC_MS_SAM_ENTRY_CLEAR1	0x180c
+#define MSCC_MS_SAM_FLOW_CTRL(x)	(0x1c00 + (x))
+#define MSCC_MS_SAM_CP_TAG		0x1e40
+#define MSCC_MS_SAM_NM_FLOW_NCP		0x1e51
+#define MSCC_MS_SAM_NM_FLOW_CP		0x1e52
+#define MSCC_MS_MISC_CONTROL		0x1e5f
+#define MSCC_MS_COUNT_CONTROL		0x3204
+#define MSCC_MS_PARAMS2_IG_CC_CONTROL	0x3a10
+#define MSCC_MS_PARAMS2_IG_CP_TAG	0x3a14
+#define MSCC_MS_VLAN_MTU_CHECK(x)	(0x3c40 + (x))
+#define MSCC_MS_NON_VLAN_MTU_CHECK	0x3c48
+#define MSCC_MS_PP_CTRL			0x3c4b
+#define MSCC_MS_STATUS_CONTEXT_CTRL	0x3d02
+#define MSCC_MS_INTR_CTRL_STATUS	0x3d04
+#define MSCC_MS_BLOCK_CTX_UPDATE	0x3d0c
+
+/* MACSEC_ENA_CFG */
+#define MSCC_MS_ENA_CFG_CLK_ENA				BIT(0)
+#define MSCC_MS_ENA_CFG_SW_RST				BIT(1)
+#define MSCC_MS_ENA_CFG_MACSEC_BYPASS_ENA		BIT(8)
+#define MSCC_MS_ENA_CFG_MACSEC_ENA			BIT(9)
+#define MSCC_MS_ENA_CFG_MACSEC_SPEED_MODE(x)		((x) << 10)
+#define MSCC_MS_ENA_CFG_MACSEC_SPEED_MODE_M		GENMASK(12, 10)
+
+/* MACSEC_FC_CFG */
+#define MSCC_MS_FC_CFG_FCBUF_ENA			BIT(0)
+#define MSCC_MS_FC_CFG_USE_PKT_EXPANSION_INDICATION	BIT(1)
+#define MSCC_MS_FC_CFG_LOW_THRESH(x)			((x) << 4)
+#define MSCC_MS_FC_CFG_LOW_THRESH_M			GENMASK(7, 4)
+#define MSCC_MS_FC_CFG_HIGH_THRESH(x)			((x) << 8)
+#define MSCC_MS_FC_CFG_HIGH_THRESH_M			GENMASK(11, 8)
+#define MSCC_MS_FC_CFG_LOW_BYTES_VAL(x)			((x) << 12)
+#define MSCC_MS_FC_CFG_LOW_BYTES_VAL_M			GENMASK(14, 12)
+#define MSCC_MS_FC_CFG_HIGH_BYTES_VAL(x)		((x) << 16)
+#define MSCC_MS_FC_CFG_HIGH_BYTES_VAL_M			GENMASK(18, 16)
+
+/* MACSEC_SAM_MISC_MATCH */
+#define MSCC_MS_SAM_MISC_MATCH_VLAN_VALID		BIT(0)
+#define MSCC_MS_SAM_MISC_MATCH_QINQ_FOUND		BIT(1)
+#define MSCC_MS_SAM_MISC_MATCH_STAG_VALID		BIT(2)
+#define MSCC_MS_SAM_MISC_MATCH_QTAG_VALID		BIT(3)
+#define MSCC_MS_SAM_MISC_MATCH_VLAN_UP(x)		((x) << 4)
+#define MSCC_MS_SAM_MISC_MATCH_VLAN_UP_M		GENMASK(6, 4)
+#define MSCC_MS_SAM_MISC_MATCH_CONTROL_PACKET		BIT(7)
+#define MSCC_MS_SAM_MISC_MATCH_UNTAGGED			BIT(8)
+#define MSCC_MS_SAM_MISC_MATCH_TAGGED			BIT(9)
+#define MSCC_MS_SAM_MISC_MATCH_BAD_TAG			BIT(10)
+#define MSCC_MS_SAM_MISC_MATCH_KAY_TAG			BIT(11)
+#define MSCC_MS_SAM_MISC_MATCH_SOURCE_PORT(x)		((x) << 12)
+#define MSCC_MS_SAM_MISC_MATCH_SOURCE_PORT_M		GENMASK(13, 12)
+#define MSCC_MS_SAM_MISC_MATCH_MATCH_PRIORITY(x)	((x) << 16)
+#define MSCC_MS_SAM_MISC_MATCH_MATCH_PRIORITY_M		GENMASK(19, 16)
+#define MSCC_MS_SAM_MISC_MATCH_AN(x)			((x) << 24)
+#define MSCC_MS_SAM_MISC_MATCH_TCI(x)			((x) << 26)
+
+/* MACSEC_SAM_MASK */
+#define MSCC_MS_SAM_MASK_MAC_SA_MASK(x)			(x)
+#define MSCC_MS_SAM_MASK_MAC_SA_MASK_M			GENMASK(5, 0)
+#define MSCC_MS_SAM_MASK_MAC_DA_MASK(x)			((x) << 6)
+#define MSCC_MS_SAM_MASK_MAC_DA_MASK_M			GENMASK(11, 6)
+#define MSCC_MS_SAM_MASK_MAC_ETYPE_MASK			BIT(12)
+#define MSCC_MS_SAM_MASK_VLAN_VLD_MASK			BIT(13)
+#define MSCC_MS_SAM_MASK_QINQ_FOUND_MASK		BIT(14)
+#define MSCC_MS_SAM_MASK_STAG_VLD_MASK			BIT(15)
+#define MSCC_MS_SAM_MASK_QTAG_VLD_MASK			BIT(16)
+#define MSCC_MS_SAM_MASK_VLAN_UP_MASK			BIT(17)
+#define MSCC_MS_SAM_MASK_VLAN_ID_MASK			BIT(18)
+#define MSCC_MS_SAM_MASK_SOURCE_PORT_MASK		BIT(19)
+#define MSCC_MS_SAM_MASK_CTL_PACKET_MASK		BIT(20)
+#define MSCC_MS_SAM_MASK_VLAN_UP_INNER_MASK		BIT(21)
+#define MSCC_MS_SAM_MASK_VLAN_ID_INNER_MASK		BIT(22)
+#define MSCC_MS_SAM_MASK_SCI_MASK			BIT(23)
+#define MSCC_MS_SAM_MASK_AN_MASK(x)			((x) << 24)
+#define MSCC_MS_SAM_MASK_TCI_MASK(x)			((x) << 26)
+
+/* MACSEC_SAM_FLOW_CTRL_EGR */
+#define MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE(x)		(x)
+#define MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE_M		GENMASK(1, 0)
+#define MSCC_MS_SAM_FLOW_CTRL_DEST_PORT(x)		((x) << 2)
+#define MSCC_MS_SAM_FLOW_CTRL_DEST_PORT_M		GENMASK(3, 2)
+#define MSCC_MS_SAM_FLOW_CTRL_RESV_4			BIT(4)
+#define MSCC_MS_SAM_FLOW_CTRL_FLOW_CRYPT_AUTH		BIT(5)
+#define MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION(x)		((x) << 6)
+#define MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION_M		GENMASK(7, 6)
+#define MSCC_MS_SAM_FLOW_CTRL_RESV_15_TO_8(x)		((x) << 8)
+#define MSCC_MS_SAM_FLOW_CTRL_RESV_15_TO_8_M		GENMASK(15, 8)
+#define MSCC_MS_SAM_FLOW_CTRL_PROTECT_FRAME		BIT(16)
+#define MSCC_MS_SAM_FLOW_CTRL_REPLAY_PROTECT		BIT(16)
+#define MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE			BIT(17)
+#define MSCC_MS_SAM_FLOW_CTRL_INCLUDE_SCI		BIT(18)
+#define MSCC_MS_SAM_FLOW_CTRL_USE_ES			BIT(19)
+#define MSCC_MS_SAM_FLOW_CTRL_USE_SCB			BIT(20)
+#define MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(x)	((x) << 19)
+#define MSCC_MS_SAM_FLOW_CTRL_TAG_BYPASS_SIZE(x)	((x) << 21)
+#define MSCC_MS_SAM_FLOW_CTRL_TAG_BYPASS_SIZE_M		GENMASK(22, 21)
+#define MSCC_MS_SAM_FLOW_CTRL_RESV_23			BIT(23)
+#define MSCC_MS_SAM_FLOW_CTRL_CONFIDENTIALITY_OFFSET(x)	((x) << 24)
+#define MSCC_MS_SAM_FLOW_CTRL_CONFIDENTIALITY_OFFSET_M	GENMASK(30, 24)
+#define MSCC_MS_SAM_FLOW_CTRL_CONF_PROTECT		BIT(31)
+
+/* MACSEC_SAM_CP_TAG */
+#define MSCC_MS_SAM_CP_TAG_MAP_TBL(x)			(x)
+#define MSCC_MS_SAM_CP_TAG_MAP_TBL_M			GENMASK(23, 0)
+#define MSCC_MS_SAM_CP_TAG_DEF_UP(x)			((x) << 24)
+#define MSCC_MS_SAM_CP_TAG_DEF_UP_M			GENMASK(26, 24)
+#define MSCC_MS_SAM_CP_TAG_STAG_UP_EN			BIT(27)
+#define MSCC_MS_SAM_CP_TAG_QTAG_UP_EN			BIT(28)
+#define MSCC_MS_SAM_CP_TAG_PARSE_QINQ			BIT(29)
+#define MSCC_MS_SAM_CP_TAG_PARSE_STAG			BIT(30)
+#define MSCC_MS_SAM_CP_TAG_PARSE_QTAG			BIT(31)
+
+/* MACSEC_SAM_NM_FLOW_NCP */
+#define MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(x)	(x)
+#define MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DEST_PORT(x)	((x) << 2)
+#define MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DROP_ACTION(x)	((x) << 6)
+#define MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(x)	((x) << 8)
+#define MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DEST_PORT(x)	((x) << 10)
+#define MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DROP_ACTION(x)	((x) << 14)
+#define MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(x)	((x) << 16)
+#define MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DEST_PORT(x)	((x) << 18)
+#define MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DROP_ACTION(x)	((x) << 22)
+#define MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(x)	((x) << 24)
+#define MSCC_MS_SAM_NM_FLOW_NCP_KAY_DEST_PORT(x)	((x) << 26)
+#define MSCC_MS_SAM_NM_FLOW_NCP_KAY_DROP_ACTION(x)	((x) << 30)
+
+/* MACSEC_SAM_NM_FLOW_CP */
+#define MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_FLOW_TYPE(x)	(x)
+#define MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DEST_PORT(x)	((x) << 2)
+#define MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DROP_ACTION(x)	((x) << 6)
+#define MSCC_MS_SAM_NM_FLOW_CP_TAGGED_FLOW_TYPE(x)	((x) << 8)
+#define MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DEST_PORT(x)	((x) << 10)
+#define MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DROP_ACTION(x)	((x) << 14)
+#define MSCC_MS_SAM_NM_FLOW_CP_BADTAG_FLOW_TYPE(x)	((x) << 16)
+#define MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DEST_PORT(x)	((x) << 18)
+#define MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DROP_ACTION(x)	((x) << 22)
+#define MSCC_MS_SAM_NM_FLOW_CP_KAY_FLOW_TYPE(x)		((x) << 24)
+#define MSCC_MS_SAM_NM_FLOW_CP_KAY_DEST_PORT(x)		((x) << 26)
+#define MSCC_MS_SAM_NM_FLOW_CP_KAY_DROP_ACTION(x)	((x) << 30)
+
+/* MACSEC_MISC_CONTROL */
+#define MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX(x)		(x)
+#define MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX_M		GENMASK(5, 0)
+#define MSCC_MS_MISC_CONTROL_STATIC_BYPASS		BIT(8)
+#define MSCC_MS_MISC_CONTROL_NM_MACSEC_EN		BIT(9)
+#define MSCC_MS_MISC_CONTROL_VALIDATE_FRAMES(x)		((x) << 10)
+#define MSCC_MS_MISC_CONTROL_VALIDATE_FRAMES_M		GENMASK(11, 10)
+#define MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE(x)		((x) << 24)
+#define MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE_M		GENMASK(25, 24)
+
+/* MACSEC_COUNT_CONTROL */
+#define MSCC_MS_COUNT_CONTROL_RESET_ALL			BIT(0)
+#define MSCC_MS_COUNT_CONTROL_DEBUG_ACCESS		BIT(1)
+#define MSCC_MS_COUNT_CONTROL_SATURATE_CNTRS		BIT(2)
+#define MSCC_MS_COUNT_CONTROL_AUTO_CNTR_RESET		BIT(3)
+
+/* MACSEC_PARAMS2_IG_CC_CONTROL */
+#define MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_CTRL_ACT	BIT(14)
+#define MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_ACT	BIT(15)
+
+/* MACSEC_PARAMS2_IG_CP_TAG */
+#define MSCC_MS_PARAMS2_IG_CP_TAG_MAP_TBL(x)		(x)
+#define MSCC_MS_PARAMS2_IG_CP_TAG_MAP_TBL_M		GENMASK(23, 0)
+#define MSCC_MS_PARAMS2_IG_CP_TAG_DEF_UP(x)		((x) << 24)
+#define MSCC_MS_PARAMS2_IG_CP_TAG_DEF_UP_M		GENMASK(26, 24)
+#define MSCC_MS_PARAMS2_IG_CP_TAG_STAG_UP_EN		BIT(27)
+#define MSCC_MS_PARAMS2_IG_CP_TAG_QTAG_UP_EN		BIT(28)
+#define MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QINQ		BIT(29)
+#define MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_STAG		BIT(30)
+#define MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QTAG		BIT(31)
+
+/* MACSEC_VLAN_MTU_CHECK */
+#define MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE(x)		(x)
+#define MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE_M		GENMASK(14, 0)
+#define MSCC_MS_VLAN_MTU_CHECK_MTU_COMP_DROP		BIT(15)
+
+/* MACSEC_NON_VLAN_MTU_CHECK */
+#define MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE(x)	(x)
+#define MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE_M	GENMASK(14, 0)
+#define MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMP_DROP	BIT(15)
+
+/* MACSEC_PP_CTRL */
+#define MSCC_MS_PP_CTRL_MACSEC_OCTET_INCR_MODE		BIT(0)
+
+/* MACSEC_INTR_CTRL_STATUS */
+#define MSCC_MS_INTR_CTRL_STATUS_INTR_CLR_STATUS(x)	(x)
+#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)
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH net-next 10/10] net: phy: mscc: macsec support
  2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
                   ` (8 preceding siblings ...)
  2019-01-23 15:56 ` [PATCH net-next 09/10] net: phy: mscc: macsec initialization Antoine Tenart
@ 2019-01-23 15:56 ` Antoine Tenart
  9 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-23 15:56 UTC (permalink / raw)
  To: davem, sd, andrew, f.fainelli, hkallweit1
  Cc: Antoine Tenart, netdev, linux-kernel, thomas.petazzoni,
	alexandre.belloni, quentin.schulz, allan.nielsen

This patch adds MACsec support to the Microsemi Ocelot PHY, to configure
flows and transformations so that matched packets can be processed by
the MACsec engine, either at egress, or at ingress. This addition allows
a user to create an hardware accelerated virtual MACsec interface on a
port using a Microsemi Ocelot PHY.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/phy/Kconfig       |   2 +
 drivers/net/phy/mscc.c        | 559 ++++++++++++++++++++++++++++++++++
 drivers/net/phy/mscc_macsec.h |   2 +
 3 files changed, 563 insertions(+)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d187cd50eb0..995b9fa697ba 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -381,6 +381,8 @@ config MICROCHIP_T1_PHY
 
 config MICROSEMI_PHY
 	tristate "Microsemi PHYs"
+	select CRYPTO_AES
+	select CRYPTO_ECB
 	---help---
 	  Currently supports VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
 
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index f82d7632fb4a..89614e6b169d 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -18,6 +18,9 @@
 #include <linux/netdevice.h>
 #include <dt-bindings/net/mscc-phy-vsc8531.h>
 
+#include <linux/scatterlist.h>
+#include <crypto/skcipher.h>
+
 #include "mscc_macsec.h"
 #include "mscc_mac.h"
 #include "mscc_fc_buffer.h"
@@ -390,6 +393,29 @@ static const struct vsc85xx_hw_stat vsc8584_hw_stats[] = {
 	},
 };
 
+struct macsec_flow {
+	struct list_head list;
+	enum macsec_bank bank;
+	u32 index;
+	unsigned char assoc_num;
+
+	u8 key[MACSEC_KEYID_LEN];
+
+	union {
+		const struct macsec_rx_sa *rx_sa;
+		const struct macsec_tx_sa *tx_sa;
+	};
+
+	/* Matching */
+	bool tagged;
+	bool untagged;
+	bool control;
+	/* Action */
+	bool bypass;
+	bool drop;
+
+};
+
 struct vsc8531_private {
 	int rate_magic;
 	u16 supp_led_modes;
@@ -403,6 +429,17 @@ struct vsc8531_private {
 	 * package.
 	 */
 	unsigned int base_addr;
+
+	/* MACsec fields:
+	 * - One SecY per device (enforced at the s/w implementation level)
+	 * - macsec_flows: list of h/w flows
+	 * - ingr_flows: bitmap of ingress flows
+	 * - egr_flows: bitmap of egress flows
+	 */
+	const struct macsec_secy *secy;
+	struct list_head macsec_flows;
+	unsigned long ingr_flows;
+	unsigned long egr_flows;
 };
 
 #ifdef CONFIG_OF_MDIO
@@ -1934,6 +1971,524 @@ static int vsc8584_macsec_init(struct phy_device *phydev)
 	return 0;
 }
 
+static void vsc8584_macsec_flow(struct phy_device *phydev,
+				struct macsec_flow *flow)
+{
+	struct vsc8531_private *priv = phydev->priv;
+	enum macsec_bank bank = flow->bank;
+	u32 val, match = 0, mask = 0, action = 0, idx = flow->index;
+
+	if (flow->control) {
+		match |= MSCC_MS_SAM_MISC_MATCH_CONTROL_PACKET;
+		mask |= MSCC_MS_SAM_MASK_CTL_PACKET_MASK;
+	}
+	if (flow->tagged)
+		match |= MSCC_MS_SAM_MISC_MATCH_TAGGED;
+	if (flow->untagged)
+		match |= MSCC_MS_SAM_MISC_MATCH_UNTAGGED;
+
+	if (bank == MACSEC_INGR) {
+		match |= MSCC_MS_SAM_MISC_MATCH_AN(flow->index);
+		mask |= MSCC_MS_SAM_MASK_AN_MASK(0x3);
+	}
+
+	/* If an SCI is present, the SC bit must be set */
+	if (bank == MACSEC_INGR && flow->rx_sa->sc->sci) {
+		match |= MSCC_MS_SAM_MISC_MATCH_TCI(BIT(3));
+		mask |= MSCC_MS_SAM_MASK_TCI_MASK(BIT(3)) |
+			MSCC_MS_SAM_MASK_SCI_MASK;
+
+		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_LO(idx),
+					 lower_32_bits(flow->rx_sa->sc->sci));
+		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_HI(idx),
+					 upper_32_bits(flow->rx_sa->sc->sci));
+	}
+
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MISC_MATCH(idx), match);
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MASK(idx), mask);
+
+	/* Action for matching packets */
+	if (flow->bypass)
+		action = MSCC_MS_FLOW_BYPASS;
+	else if (flow->drop)
+		action = MSCC_MS_FLOW_DROP;
+	else
+		action = (bank == MACSEC_INGR) ?
+			 MSCC_MS_FLOW_INGRESS : MSCC_MS_FLOW_EGRESS;
+
+	val = MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE(action) |
+	      MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION(MSCC_MS_ACTION_DROP) |
+	      MSCC_MS_SAM_FLOW_CTRL_DEST_PORT(MSCC_MS_PORT_CONTROLLED);
+
+	if (bank == MACSEC_INGR) {
+		if (priv->secy->replay_protect)
+			val |= MSCC_MS_SAM_FLOW_CTRL_REPLAY_PROTECT;
+		if (priv->secy->validate_frames == MACSEC_VALIDATE_STRICT)
+			val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_STRICT);
+		else if (priv->secy->validate_frames == MACSEC_VALIDATE_CHECK)
+			val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_CHECK);
+	} else if (bank == MACSEC_EGR) {
+		if (priv->secy->protect_frames)
+			val |= MSCC_MS_SAM_FLOW_CTRL_PROTECT_FRAME;
+		if (priv->secy->tx_sc.encrypt)
+			val |= MSCC_MS_SAM_FLOW_CTRL_CONF_PROTECT;
+		if (priv->secy->tx_sc.send_sci)
+			val |= MSCC_MS_SAM_FLOW_CTRL_INCLUDE_SCI;
+	}
+
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
+}
+
+static enum macsec_bank vsc8584_macsec_command_to_bank(enum netdev_macsec_command command)
+{
+	switch (command) {
+	case MACSEC_ADD_RXSA:
+	case MACSEC_UPD_RXSA:
+	case MACSEC_DEL_RXSA:
+		return MACSEC_INGR;
+	case MACSEC_ADD_TXSA:
+	case MACSEC_UPD_TXSA:
+	case MACSEC_DEL_TXSA:
+		return MACSEC_EGR;
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct macsec_flow *vsc8584_macsec_find_flow(struct vsc8531_private *priv,
+						    enum macsec_bank bank,
+						    struct netdev_macsec *macsec)
+{
+	struct macsec_flow *pos, *tmp;
+	sci_t flow_sci, sci = bank == MACSEC_INGR ?
+			      macsec->sa.rx_sa->sc->sci : priv->secy->sci;
+
+	list_for_each_entry_safe(pos, tmp, &priv->macsec_flows, list) {
+		flow_sci = pos->bank == MACSEC_INGR ?
+			   pos->rx_sa->sc->sci : priv->secy->sci;
+		if (pos->assoc_num == macsec->sa.assoc_num && flow_sci == sci &&
+		    pos->bank == vsc8584_macsec_command_to_bank(macsec->command))
+			return pos;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+static void vsc8584_macsec_flow_enable(struct phy_device *phydev,
+				       struct macsec_flow *flow)
+{
+	enum macsec_bank bank = flow->bank;
+	u32 val, idx = flow->index;
+	bool active = (flow->bank == MACSEC_INGR) ?
+		      flow->rx_sa->active : flow->tx_sa->active;
+
+	if (!active)
+		return;
+
+	/* Enable */
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_SET1, BIT(idx));
+
+	/* Set in-use */
+	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
+	val |= MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
+}
+
+static void vsc8584_macsec_flow_disable(struct phy_device *phydev,
+					struct macsec_flow *flow)
+{
+	enum macsec_bank bank = flow->bank;
+	u32 val, idx = flow->index;
+
+	/* Disable */
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_CLEAR1, BIT(idx));
+
+	/* Clear in-use */
+	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
+	val &= ~MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
+}
+
+static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow)
+{
+	if (flow->bank == MACSEC_INGR)
+		return flow->index + MSCC_MS_MAX_FLOWS;
+
+	return flow->index;
+}
+
+/* Derive the AES key to get a key for the hash autentication */
+static int vsc8584_macsec_derive_key(const u8 key[MACSEC_KEYID_LEN],
+				     u16 key_len, u8 hkey[16])
+{
+	struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
+	struct skcipher_request *req = NULL;
+	struct scatterlist src, dst;
+	DECLARE_CRYPTO_WAIT(wait);
+	u32 input[4] = {0};
+	int ret;
+
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	req = skcipher_request_alloc(tfm, GFP_KERNEL);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+				      CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done,
+				      &wait);
+	ret = crypto_skcipher_setkey(tfm, key, key_len);
+	if (ret < 0)
+		goto out;
+
+	sg_init_one(&src, input, 16);
+	sg_init_one(&dst, hkey, 16);
+	skcipher_request_set_crypt(req, &src, &dst, 16, NULL);
+
+	ret = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
+
+out:
+	skcipher_request_free(req);
+	crypto_free_skcipher(tfm);
+	return ret;
+}
+
+static int vsc8584_macsec_transformation(struct phy_device *phydev,
+					 struct macsec_flow *flow)
+{
+	u32 rec = 0, control = 0, index = flow->index;
+	struct vsc8531_private *priv = phydev->priv;
+	enum macsec_bank bank = flow->bank;
+	u8 hkey[16];
+	int i, ret;
+	sci_t sci;
+
+	ret = vsc8584_macsec_derive_key(flow->key, priv->secy->key_len, hkey);
+	if (ret)
+		return ret;
+
+	switch (priv->secy->key_len) {
+	case 16:
+		control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_128);
+		break;
+	case 32:
+		control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_256);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	control |= (bank == MACSEC_EGR) ?
+		   (CONTROL_TYPE_EGRESS | CONTROL_AN(priv->secy->tx_sc.encoding_sa)) :
+		   (CONTROL_TYPE_INGRESS | CONTROL_SEQ_MASK);
+
+	control |= CONTROL_UPDATE_SEQ | CONTROL_ENCRYPT_AUTH | CONTROL_KEY_IN_CTX |
+		   CONTROL_IV0 | CONTROL_IV1 | CONTROL_IV_IN_SEQ |
+		   CONTROL_DIGEST_TYPE(0x2) | CONTROL_SEQ_TYPE(0x1) |
+		   CONTROL_AUTH_ALG(AUTH_ALG_AES_GHAS) | CONTROL_CONTEXT_ID;
+
+	/* Set the control word */
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
+				 control);
+
+	/* Set the context ID. Must be unique. */
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
+				 vsc8584_macsec_flow_context_id(flow));
+
+	/* Set the encryption/decryption key */
+	for (i = 0; i < priv->secy->key_len / sizeof(u32); i++)
+		vsc8584_macsec_phy_write(phydev, bank,
+					 MSCC_MS_XFORM_REC(index, rec++),
+					 ((u32 *)flow->key)[i]);
+
+	/* Set the authentication key */
+	for (i = 0; i < 4; i++)
+		vsc8584_macsec_phy_write(phydev, bank,
+					 MSCC_MS_XFORM_REC(index, rec++),
+					 ((u32 *)hkey)[i]);
+
+	/* Initial sequence number */
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
+				 bank == MACSEC_INGR ?
+				 flow->rx_sa->next_pn : flow->tx_sa->next_pn);
+
+	if (bank == MACSEC_INGR)
+		/* Set the mask (replay window size) */
+		vsc8584_macsec_phy_write(phydev, bank,
+					 MSCC_MS_XFORM_REC(index, rec++),
+					 priv->secy->replay_window);
+
+	/* Set the input vectors */
+	sci = bank == MACSEC_INGR ? flow->rx_sa->sc->sci : priv->secy->sci;
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
+				 lower_32_bits(sci));
+	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
+				 upper_32_bits(sci));
+
+	while (rec < 20)
+		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
+					 0);
+	return 0;
+}
+
+static struct macsec_flow *vsc8584_macsec_alloc_flow(struct vsc8531_private *priv,
+						     enum macsec_bank bank)
+{
+	struct macsec_flow *flow;
+	unsigned long *bitmap;
+	int index;
+
+	bitmap = bank == MACSEC_INGR ? &priv->ingr_flows : &priv->egr_flows;
+	index = find_first_zero_bit(bitmap, MSCC_MS_MAX_FLOWS);
+
+	if (index == MSCC_MS_MAX_FLOWS)
+		return ERR_PTR(-ENOMEM);
+
+	flow = kzalloc(sizeof(*flow), GFP_KERNEL);
+	if (!flow)
+		return ERR_PTR(-ENOMEM);
+
+	set_bit(index, bitmap);
+	flow->index = index;
+	flow->bank = bank;
+
+	list_add_tail(&flow->list, &priv->macsec_flows);
+	return flow;
+}
+
+static void vsc8584_macsec_free_flow(struct vsc8531_private *priv,
+				     struct macsec_flow *flow)
+{
+	unsigned long *bitmap = flow->bank == MACSEC_INGR ?
+				&priv->ingr_flows : &priv->egr_flows;
+
+	list_del(&flow->list);
+	clear_bit(flow->index, bitmap);
+	kfree(flow);
+}
+
+static int vsc8584_macsec_add_flow(struct phy_device *phydev,
+				   enum netdev_macsec_command command,
+				   struct macsec_flow *flow)
+{
+	int ret;
+
+	vsc8584_macsec_flow(phydev, flow);
+
+	if (command == MACSEC_UPD_RXSA || command == MACSEC_UPD_TXSA)
+		return 0;
+
+	ret = vsc8584_macsec_transformation(phydev, flow);
+	if (ret) {
+		vsc8584_macsec_free_flow(phydev->priv, flow);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void vsc8584_macsec_del_flow(struct phy_device *phydev,
+				    struct macsec_flow *flow)
+{
+	vsc8584_macsec_flow_disable(phydev, flow);
+	vsc8584_macsec_free_flow(phydev->priv, flow);
+}
+
+static int vsc8584_macsec_add_rxsa(struct phy_device *phydev,
+				   struct netdev_macsec *macsec,
+				   struct macsec_flow *flow)
+{
+	struct vsc8531_private *priv = phydev->priv;
+
+	if (!flow) {
+		flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_INGR);
+		if (IS_ERR(flow))
+			return PTR_ERR(flow);
+
+		memcpy(flow->key, macsec->sa.key, priv->secy->key_len);
+	}
+
+	flow->assoc_num = macsec->sa.assoc_num;
+	flow->rx_sa = macsec->sa.rx_sa;
+
+	/* Always match tagged packets on ingress */
+	flow->tagged = true;
+
+	if (priv->secy->validate_frames != MACSEC_VALIDATE_DISABLED)
+		flow->untagged = true;
+
+	return vsc8584_macsec_add_flow(phydev, macsec->command, flow);
+}
+
+static int vsc8584_macsec_add_txsa(struct phy_device *phydev,
+				   struct netdev_macsec *macsec,
+				   struct macsec_flow *flow)
+{
+	struct vsc8531_private *priv = phydev->priv;
+
+	if (!flow) {
+		flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_EGR);
+		if (IS_ERR(flow))
+			return PTR_ERR(flow);
+
+		memcpy(flow->key, macsec->sa.key, priv->secy->key_len);
+	}
+
+	flow->assoc_num = macsec->sa.assoc_num;
+	flow->tx_sa = macsec->sa.tx_sa;
+
+	/* Always match untagged packets on egress */
+	flow->untagged = true;
+
+	return vsc8584_macsec_add_flow(phydev, macsec->command, flow);
+}
+
+/* This function should ensure vsc8584_macsec_commit() will run successfully */
+static int vsc8584_macsec_prepare(struct phy_device *phydev,
+				  struct netdev_macsec *macsec)
+{
+	struct vsc8531_private *priv = phydev->priv;
+	struct macsec_flow *flow = NULL;
+
+	if (macsec->command != MACSEC_ADD_SECY && !priv->secy)
+		return -EINVAL;
+
+	switch (macsec->command) {
+	case MACSEC_ADD_SECY:
+		if (priv->secy)
+			return -EEXIST;
+		return 0;
+	case MACSEC_UPD_RXSA:
+		flow = vsc8584_macsec_find_flow(phydev->priv, MACSEC_INGR,
+						macsec);
+		if (IS_ERR(flow))
+			return -ENOENT;
+
+		/* Make sure the flow is disabled before updating it */
+		vsc8584_macsec_flow_disable(phydev, flow);
+
+		/* Fall-through */
+	case MACSEC_ADD_RXSA:
+		return vsc8584_macsec_add_rxsa(phydev, macsec, flow);
+	case MACSEC_UPD_TXSA:
+		flow = vsc8584_macsec_find_flow(phydev->priv, MACSEC_EGR,
+						macsec);
+		if (IS_ERR(flow))
+			return -ENOENT;
+
+		/* Make sure the flow is disabled before updating it */
+		vsc8584_macsec_flow_disable(phydev, flow);
+
+		/* Fall-through */
+	case MACSEC_ADD_TXSA:
+		return vsc8584_macsec_add_txsa(phydev, macsec, flow);
+	case MACSEC_DEL_RXSA:
+		flow = vsc8584_macsec_find_flow(phydev->priv, MACSEC_INGR,
+						macsec);
+		if (IS_ERR(flow))
+			return -ENOENT;
+		return 0;
+	case MACSEC_DEL_TXSA:
+		flow = vsc8584_macsec_find_flow(phydev->priv, MACSEC_EGR,
+						macsec);
+		if (IS_ERR(flow))
+			return -ENOENT;
+		return 0;
+	/* Handled entirely in the commit phase */
+	case MACSEC_DEL_SECY:
+	case MACSEC_DEL_RXSC:
+	case MACSEC_DEV_OPEN:
+	case MACSEC_DEV_STOP:
+		return 0;
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/* This function should not fail */
+static int vsc8584_macsec_commit(struct phy_device *phydev,
+				 struct netdev_macsec *macsec)
+{
+	struct vsc8531_private *priv = phydev->priv;
+	struct macsec_flow *flow, *tmp;
+
+	switch (macsec->command) {
+	case MACSEC_ADD_SECY:
+		priv->secy = macsec->secy;
+		break;
+	case MACSEC_DEL_SECY:
+		list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
+			vsc8584_macsec_del_flow(phydev, flow);
+
+		priv->secy = NULL;
+		break;
+	case MACSEC_DEL_RXSC:
+		list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
+			if (flow->bank == MACSEC_INGR &&
+			    flow->rx_sa->sc->sci == macsec->rx_sc->sci)
+				vsc8584_macsec_del_flow(phydev, flow);
+		}
+		break;
+	case MACSEC_ADD_RXSA:
+	case MACSEC_UPD_RXSA:
+		flow = vsc8584_macsec_find_flow(phydev->priv, MACSEC_INGR,
+						macsec);
+		if (IS_ERR(flow))
+			return PTR_ERR(flow);
+		vsc8584_macsec_flow_enable(phydev, flow);
+		break;
+	case MACSEC_ADD_TXSA:
+	case MACSEC_UPD_TXSA:
+		flow = vsc8584_macsec_find_flow(phydev->priv, MACSEC_EGR,
+						macsec);
+		if (IS_ERR(flow))
+			return PTR_ERR(flow);
+		vsc8584_macsec_flow_enable(phydev, flow);
+		break;
+	case MACSEC_DEL_RXSA:
+		flow = vsc8584_macsec_find_flow(phydev->priv, MACSEC_INGR,
+						macsec);
+		if (IS_ERR(flow))
+			return PTR_ERR(flow);
+		vsc8584_macsec_del_flow(phydev, flow);
+		break;
+	case MACSEC_DEL_TXSA:
+		flow = vsc8584_macsec_find_flow(phydev->priv, MACSEC_EGR,
+						macsec);
+		if (IS_ERR(flow))
+			return PTR_ERR(flow);
+		vsc8584_macsec_del_flow(phydev, flow);
+		break;
+	case MACSEC_DEV_OPEN:
+		list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
+			vsc8584_macsec_flow_enable(phydev, flow);
+		break;
+	case MACSEC_DEV_STOP:
+		list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
+			vsc8584_macsec_flow_disable(phydev, flow);
+		break;
+	default:
+		/* Nothing to be done */
+		break;
+	}
+
+	return 0;
+}
+
+static int vsc8584_macsec(struct phy_device *phydev,
+			  struct netdev_macsec *macsec)
+{
+	if (macsec->prepare)
+		return vsc8584_macsec_prepare(phydev, macsec);
+
+	return vsc8584_macsec_commit(phydev, macsec);
+}
+
 /* Check if one PHY has already done the init of the parts common to all PHYs
  * in the Quad PHY package.
  */
@@ -2064,6 +2619,9 @@ static int vsc8584_config_init(struct phy_device *phydev)
 		goto err;
 
 	/* MACsec */
+	INIT_LIST_HEAD(&vsc8531->macsec_flows);
+	vsc8531->secy = NULL;
+
 	ret = vsc8584_macsec_init(phydev);
 	if (ret)
 		goto err;
@@ -2428,6 +2986,7 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_sset_count = &vsc85xx_get_sset_count,
 	.get_strings    = &vsc85xx_get_strings,
 	.get_stats      = &vsc85xx_get_stats,
+	.macsec		= &vsc8584_macsec,
 }
 
 };
diff --git a/drivers/net/phy/mscc_macsec.h b/drivers/net/phy/mscc_macsec.h
index 52902669e8ca..cf12d7967133 100644
--- a/drivers/net/phy/mscc_macsec.h
+++ b/drivers/net/phy/mscc_macsec.h
@@ -8,6 +8,8 @@
 #ifndef _MSCC_OCELOT_MACSEC_H_
 #define _MSCC_OCELOT_MACSEC_H_
 
+#define MSCC_MS_MAX_FLOWS		16
+
 #define CONTROL_TYPE_EGRESS		0x6
 #define CONTROL_TYPE_INGRESS		0xf
 #define CONTROL_IV0			BIT(5)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 02/10] net: macsec: convert to SPDX
  2019-01-23 15:56 ` [PATCH net-next 02/10] net: macsec: convert to SPDX Antoine Tenart
@ 2019-01-23 17:03   ` Andrew Lunn
  2019-01-24  8:54     ` Antoine Tenart
  0 siblings, 1 reply; 26+ messages in thread
From: Andrew Lunn @ 2019-01-23 17:03 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, sd, f.fainelli, hkallweit1, netdev, linux-kernel,
	thomas.petazzoni, alexandre.belloni, quentin.schulz,
	allan.nielsen

On Wed, Jan 23, 2019 at 04:56:30PM +0100, Antoine Tenart wrote:
> This cosmetic patch converts the macsec implementation license header to
> the now recommended format, SPDX.
> 
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
> ---
>  drivers/net/macsec.c | 6 +-----
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
> index 64a982563d59..56e354305f76 100644
> --- a/drivers/net/macsec.c
> +++ b/drivers/net/macsec.c
> @@ -1,12 +1,8 @@
> +// SPDX-License-Identifier: GPL-2.0+
>  /*
>   * drivers/net/macsec.c - MACsec device
>   *
>   * Copyright (c) 2015 Sabrina Dubroca <sd@queasysnail.net>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
>   */
>  
>  #include <linux/types.h>

Hi Antoine

linux$ tail -4 drivers/net/macsec.c
MODULE_ALIAS_GENL_FAMILY("macsec");

MODULE_DESCRIPTION("MACsec IEEE 802.1AE");
MODULE_LICENSE("GPL v2");

The license text and the MODULE_LICENSE() don't agree with each other.
It would be good to fix this as well.

Thanks
	Andrew

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 05/10] net: phy: introduce a phy_driver macsec helper
  2019-01-23 15:56 ` [PATCH net-next 05/10] net: phy: introduce a phy_driver macsec helper Antoine Tenart
@ 2019-01-23 17:08   ` Andrew Lunn
  2019-01-24  8:56     ` Antoine Tenart
  0 siblings, 1 reply; 26+ messages in thread
From: Andrew Lunn @ 2019-01-23 17:08 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, sd, f.fainelli, hkallweit1, netdev, linux-kernel,
	thomas.petazzoni, alexandre.belloni, quentin.schulz,
	allan.nielsen

> +int phy_macsec(struct phy_device *phydev, struct netdev_macsec *macsec)
> +{
> +	int ret = -EOPNOTSUPP;
> +
> +	if (!phydev->drv)
> +		return -EIO;
> +
> +	mutex_lock(&phydev->lock);
> +
> +	if (phydev->drv->macsec)
> +		ret = phydev->drv->macsec(phydev, macsec);
> +
> +	mutex_unlock(&phydev->lock);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(phy_macsec);
> +

> @@ -630,6 +634,10 @@ struct phy_driver {
>  			    struct ethtool_tunable *tuna,
>  			    const void *data);
>  	int (*set_loopback)(struct phy_device *dev, bool enable);
> +
> +#ifdef CONFIG_MACSEC
> +	int (*macsec)(struct phy_device *dev, struct netdev_macsec *macsec);
> +#endif

Hi Antoine

So the member only exists if CONFIG_MACSEC is defined. So i think you
need similar protection in phy_macsec() or you are going to try to
access a member which sometimes does not exist.

       Andrew

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 03/10] net: macsec: move some definitions in a dedicated header
  2019-01-23 15:56 ` [PATCH net-next 03/10] net: macsec: move some definitions in a dedicated header Antoine Tenart
@ 2019-01-23 20:11   ` Florian Fainelli
  2019-01-24  1:00     ` David Miller
  2019-01-24  8:58     ` Antoine Tenart
  0 siblings, 2 replies; 26+ messages in thread
From: Florian Fainelli @ 2019-01-23 20:11 UTC (permalink / raw)
  To: Antoine Tenart, davem, sd, andrew, hkallweit1
  Cc: netdev, linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

On 1/23/19 7:56 AM, Antoine Tenart wrote:
> This patch moves some structure, type and identifier definitions into a
> MACsec specific header. This patch does not modify how the MACsec code
> is running and only move things around. This is a preparation for the
> future MACsec hardware offloading support, which will re-use those
> definitions outside macsec.c.
> 
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
> ---
>  drivers/net/macsec.c | 164 +--------------------------------------
>  include/net/macsec.h | 178 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 179 insertions(+), 163 deletions(-)
>  create mode 100644 include/net/macsec.h
> 
> diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
> index 56e354305f76..c3a138dd4386 100644
> --- a/drivers/net/macsec.c
> +++ b/drivers/net/macsec.c
> @@ -17,10 +17,9 @@
>  #include <net/sock.h>
>  #include <net/gro_cells.h>
>  
> +#include <net/macsec.h>
>  #include <uapi/linux/if_macsec.h>

I would probably go with include/linux/if_macsec.h and have
uapi/linux/if_macsec.h include that file directly. This would be
consistent with other types of network interfaces: bridge, vlan etc.
-- 
Florian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 06/10] net: introduce a net_device_ops macsec helper
  2019-01-23 15:56 ` [PATCH net-next 06/10] net: introduce a net_device_ops " Antoine Tenart
@ 2019-01-23 20:16   ` Florian Fainelli
  2019-01-24  9:23     ` Antoine Tenart
  2019-01-24 14:58   ` Igor Russkikh
  1 sibling, 1 reply; 26+ messages in thread
From: Florian Fainelli @ 2019-01-23 20:16 UTC (permalink / raw)
  To: Antoine Tenart, davem, sd, andrew, hkallweit1
  Cc: netdev, linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

On 1/23/19 7:56 AM, Antoine Tenart wrote:
> This patch introduces a net_device_ops MACsec helper to allow net device
> drivers to implement a MACsec offloading solution.
> 
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
> ---
>  include/linux/netdevice.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index e675ef97a426..ee2f40dca515 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -53,6 +53,10 @@
>  #include <uapi/linux/pkt_cls.h>
>  #include <linux/hashtable.h>
>  
> +#ifdef CONFIG_MACSEC
> +#include <net/macsec.h>
> +#endif

You can provide a forward declaration for struct netdev_macsec and not
have to include that header file.

> +
>  struct netpoll_info;
>  struct device;
>  struct phy_device;
> @@ -1441,6 +1445,10 @@ struct net_device_ops {
>  						u32 flags);
>  	int			(*ndo_xsk_async_xmit)(struct net_device *dev,
>  						      u32 queue_id);
> +#ifdef CONFIG_MACSEC
> +	int			(*ndo_macsec)(struct net_device *dev,
> +					      struct netdev_macsec *macsec);

You would really want to define an API which is more oriented towards
configuring/deconfiguring a MACsec association here, e.g.: similar to
what the IPsec offload ndos offer.

It is not clear to me whether after your patch series we still need to
create a macsec virtual device, and that gets offloaded onto its real
device/PHY device, or if we don't need that all?
-- 
Florian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 03/10] net: macsec: move some definitions in a dedicated header
  2019-01-23 20:11   ` Florian Fainelli
@ 2019-01-24  1:00     ` David Miller
  2019-01-24  8:58     ` Antoine Tenart
  1 sibling, 0 replies; 26+ messages in thread
From: David Miller @ 2019-01-24  1:00 UTC (permalink / raw)
  To: f.fainelli
  Cc: antoine.tenart, sd, andrew, hkallweit1, netdev, linux-kernel,
	thomas.petazzoni, alexandre.belloni, quentin.schulz,
	allan.nielsen

From: Florian Fainelli <f.fainelli@gmail.com>
Date: Wed, 23 Jan 2019 12:11:37 -0800

> On 1/23/19 7:56 AM, Antoine Tenart wrote:
>> This patch moves some structure, type and identifier definitions into a
>> MACsec specific header. This patch does not modify how the MACsec code
>> is running and only move things around. This is a preparation for the
>> future MACsec hardware offloading support, which will re-use those
>> definitions outside macsec.c.
>> 
>> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
>> ---
>>  drivers/net/macsec.c | 164 +--------------------------------------
>>  include/net/macsec.h | 178 +++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 179 insertions(+), 163 deletions(-)
>>  create mode 100644 include/net/macsec.h
>> 
>> diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
>> index 56e354305f76..c3a138dd4386 100644
>> --- a/drivers/net/macsec.c
>> +++ b/drivers/net/macsec.c
>> @@ -17,10 +17,9 @@
>>  #include <net/sock.h>
>>  #include <net/gro_cells.h>
>>  
>> +#include <net/macsec.h>
>>  #include <uapi/linux/if_macsec.h>
> 
> I would probably go with include/linux/if_macsec.h and have
> uapi/linux/if_macsec.h include that file directly. This would be
> consistent with other types of network interfaces: bridge, vlan etc.

Agreed.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 02/10] net: macsec: convert to SPDX
  2019-01-23 17:03   ` Andrew Lunn
@ 2019-01-24  8:54     ` Antoine Tenart
  2019-01-24 13:11       ` Andrew Lunn
  0 siblings, 1 reply; 26+ messages in thread
From: Antoine Tenart @ 2019-01-24  8:54 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Antoine Tenart, davem, sd, f.fainelli, hkallweit1, netdev,
	linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

Hi Andrew,

On Wed, Jan 23, 2019 at 06:03:06PM +0100, Andrew Lunn wrote:
> On Wed, Jan 23, 2019 at 04:56:30PM +0100, Antoine Tenart wrote:
> > This cosmetic patch converts the macsec implementation license header to
> > the now recommended format, SPDX.
> > 
> > Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
> > ---
> >  drivers/net/macsec.c | 6 +-----
> >  1 file changed, 1 insertion(+), 5 deletions(-)
> > 
> > diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
> > index 64a982563d59..56e354305f76 100644
> > --- a/drivers/net/macsec.c
> > +++ b/drivers/net/macsec.c
> > @@ -1,12 +1,8 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> >  /*
> >   * drivers/net/macsec.c - MACsec device
> >   *
> >   * Copyright (c) 2015 Sabrina Dubroca <sd@queasysnail.net>
> > - *
> > - * This program is free software; you can redistribute it and/or modify
> > - * it under the terms of the GNU General Public License as published by
> > - * the Free Software Foundation; either version 2 of the License, or
> > - * (at your option) any later version.
> >   */
> >  
> >  #include <linux/types.h>
> 
> linux$ tail -4 drivers/net/macsec.c
> MODULE_ALIAS_GENL_FAMILY("macsec");
> 
> MODULE_DESCRIPTION("MACsec IEEE 802.1AE");
> MODULE_LICENSE("GPL v2");
> 
> The license text and the MODULE_LICENSE() don't agree with each other.
> It would be good to fix this as well.

That's right, I'll fix it in v2. In such cases, the license text takes
precedence over the MODULE_LICENSE() definition ?

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 05/10] net: phy: introduce a phy_driver macsec helper
  2019-01-23 17:08   ` Andrew Lunn
@ 2019-01-24  8:56     ` Antoine Tenart
  0 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-24  8:56 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Antoine Tenart, davem, sd, f.fainelli, hkallweit1, netdev,
	linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

Hi Andrew,

On Wed, Jan 23, 2019 at 06:08:16PM +0100, Andrew Lunn wrote:
> > +int phy_macsec(struct phy_device *phydev, struct netdev_macsec *macsec)
> > +{
> > +	int ret = -EOPNOTSUPP;
> > +
> > +	if (!phydev->drv)
> > +		return -EIO;
> > +
> > +	mutex_lock(&phydev->lock);
> > +
> > +	if (phydev->drv->macsec)
> > +		ret = phydev->drv->macsec(phydev, macsec);
> > +
> > +	mutex_unlock(&phydev->lock);
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(phy_macsec);
> > +
> 
> > @@ -630,6 +634,10 @@ struct phy_driver {
> >  			    struct ethtool_tunable *tuna,
> >  			    const void *data);
> >  	int (*set_loopback)(struct phy_device *dev, bool enable);
> > +
> > +#ifdef CONFIG_MACSEC
> > +	int (*macsec)(struct phy_device *dev, struct netdev_macsec *macsec);
> > +#endif
> 
> 
> So the member only exists if CONFIG_MACSEC is defined. So i think you
> need similar protection in phy_macsec() or you are going to try to
> access a member which sometimes does not exist.

Right, I'll fix that and protect the phy_macsec definition within an
'#ifdef CONFIG_MACSEC'.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 03/10] net: macsec: move some definitions in a dedicated header
  2019-01-23 20:11   ` Florian Fainelli
  2019-01-24  1:00     ` David Miller
@ 2019-01-24  8:58     ` Antoine Tenart
  1 sibling, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-24  8:58 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Antoine Tenart, davem, sd, andrew, hkallweit1, netdev,
	linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

Hi Florian,

On Wed, Jan 23, 2019 at 12:11:37PM -0800, Florian Fainelli wrote:
> On 1/23/19 7:56 AM, Antoine Tenart wrote:
> > This patch moves some structure, type and identifier definitions into a
> > MACsec specific header. This patch does not modify how the MACsec code
> > is running and only move things around. This is a preparation for the
> > future MACsec hardware offloading support, which will re-use those
> > definitions outside macsec.c.
> > 
> > Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
> > ---
> >  drivers/net/macsec.c | 164 +--------------------------------------
> >  include/net/macsec.h | 178 +++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 179 insertions(+), 163 deletions(-)
> >  create mode 100644 include/net/macsec.h
> > 
> > diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
> > index 56e354305f76..c3a138dd4386 100644
> > --- a/drivers/net/macsec.c
> > +++ b/drivers/net/macsec.c
> > @@ -17,10 +17,9 @@
> >  #include <net/sock.h>
> >  #include <net/gro_cells.h>
> >  
> > +#include <net/macsec.h>
> >  #include <uapi/linux/if_macsec.h>
> 
> I would probably go with include/linux/if_macsec.h and have
> uapi/linux/if_macsec.h include that file directly. This would be
> consistent with other types of network interfaces: bridge, vlan etc.

It's always a good idea to stay consistent with what's already done.
I'll update in v2.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 06/10] net: introduce a net_device_ops macsec helper
  2019-01-23 20:16   ` Florian Fainelli
@ 2019-01-24  9:23     ` Antoine Tenart
  2019-01-31  9:26       ` Antoine Tenart
  2019-02-01  3:50       ` Florian Fainelli
  0 siblings, 2 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-24  9:23 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Antoine Tenart, davem, sd, andrew, hkallweit1, netdev,
	linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

Hi Florian,

On Wed, Jan 23, 2019 at 12:16:08PM -0800, Florian Fainelli wrote:
> On 1/23/19 7:56 AM, Antoine Tenart wrote:
> > This patch introduces a net_device_ops MACsec helper to allow net device
> > drivers to implement a MACsec offloading solution.
> > 
> > Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
> > ---
> >  include/linux/netdevice.h | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > index e675ef97a426..ee2f40dca515 100644
> > --- a/include/linux/netdevice.h
> > +++ b/include/linux/netdevice.h
> > @@ -53,6 +53,10 @@
> >  #include <uapi/linux/pkt_cls.h>
> >  #include <linux/hashtable.h>
> >  
> > +#ifdef CONFIG_MACSEC
> > +#include <net/macsec.h>
> > +#endif
> 
> You can provide a forward declaration for struct netdev_macsec and not
> have to include that header file.

OK.

> > +
> >  struct netpoll_info;
> >  struct device;
> >  struct phy_device;
> > @@ -1441,6 +1445,10 @@ struct net_device_ops {
> >  						u32 flags);
> >  	int			(*ndo_xsk_async_xmit)(struct net_device *dev,
> >  						      u32 queue_id);
> > +#ifdef CONFIG_MACSEC
> > +	int			(*ndo_macsec)(struct net_device *dev,
> > +					      struct netdev_macsec *macsec);
> 
> You would really want to define an API which is more oriented towards
> configuring/deconfiguring a MACsec association here, e.g.: similar to
> what the IPsec offload ndos offer.

This means mostly moving from a single function using a command field to
multiple specialized functions to add/remove each element of MACsec
configuration.

I don't have strong opinion on the single helper vs a structure
containing pointers to specialized ones, but out of curiosity what's the
benefit of such a move? Future additions and maintainability?

> It is not clear to me whether after your patch series we still need to
> create a macsec virtual device, and that gets offloaded onto its real
> device/PHY device, or if we don't need that all?

After this series, we will still need the virtual MACsec interface. When
using hardware offloading this interface isn't doing much, but it's the
interface used to configure all the MACsec connexions.

This is because, and that's specific to MACsec (vs IPsec), a software
implementation is already supported and it's using a virtual interface
to perform all the MACsec related operations (vs hooks in the Rx/Tx
paths). I really wanted to avoid having two interfaces and ways of
configuring MACsec depending on if the offloading is used.

This should also allow in the future to disable at run-time the
offloading on a given interface, and to still have MACsec working in
software (or the opposite, with extra work). For this to work, the
virtual interface still has to provide an Rx and a Tx functions so that
programs can bind onto the same interface, regardless of if the
offloading is enabled.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 02/10] net: macsec: convert to SPDX
  2019-01-24  8:54     ` Antoine Tenart
@ 2019-01-24 13:11       ` Andrew Lunn
  2019-01-24 13:29         ` Antoine Tenart
  0 siblings, 1 reply; 26+ messages in thread
From: Andrew Lunn @ 2019-01-24 13:11 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, sd, f.fainelli, hkallweit1, netdev, linux-kernel,
	thomas.petazzoni, alexandre.belloni, quentin.schulz,
	allan.nielsen

> That's right, I'll fix it in v2. In such cases, the license text takes
> precedence over the MODULE_LICENSE() definition ?
 
Hi Antoine

IANAL

I've also not seen any real discussion about this. But when i recently
proposed patches to cleanup similar issues in drivers/net/phy, i gave
the license text precedence, since it is a lot easier for a human to
understand, and it is likely a human made the error....


	    Andrew

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 02/10] net: macsec: convert to SPDX
  2019-01-24 13:11       ` Andrew Lunn
@ 2019-01-24 13:29         ` Antoine Tenart
  0 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-24 13:29 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Antoine Tenart, davem, sd, f.fainelli, hkallweit1, netdev,
	linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

Hi Andrew,

On Thu, Jan 24, 2019 at 02:11:18PM +0100, Andrew Lunn wrote:
> > That's right, I'll fix it in v2. In such cases, the license text takes
> > precedence over the MODULE_LICENSE() definition ?
>  
> I've also not seen any real discussion about this. But when i recently
> proposed patches to cleanup similar issues in drivers/net/phy, i gave
> the license text precedence, since it is a lot easier for a human to
> understand, and it is likely a human made the error....

I would go for this as well, it seems logical for MODULE_LICENSE() to
only be an identifier of what the license described in the license text
is.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 06/10] net: introduce a net_device_ops macsec helper
  2019-01-23 15:56 ` [PATCH net-next 06/10] net: introduce a net_device_ops " Antoine Tenart
  2019-01-23 20:16   ` Florian Fainelli
@ 2019-01-24 14:58   ` Igor Russkikh
  2019-01-24 15:05     ` Antoine Tenart
  1 sibling, 1 reply; 26+ messages in thread
From: Igor Russkikh @ 2019-01-24 14:58 UTC (permalink / raw)
  To: Antoine Tenart, davem, sd, andrew, f.fainelli, hkallweit1
  Cc: netdev, linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen


Hi Antoine,

Its great to see macsec hw offload infrastructure happening!

> @@ -1441,6 +1445,10 @@ struct net_device_ops {
>  						u32 flags);
>  	int			(*ndo_xsk_async_xmit)(struct net_device *dev,
>  						      u32 queue_id);
> +#ifdef CONFIG_MACSEC
> +	int			(*ndo_macsec)(struct net_device *dev,
> +					      struct netdev_macsec *macsec);
> +#endif
>  };

Most of ndo's are named by action verbs. This ndo is abit misleading, reader
may have difficulties understanding what

+	if (phydev->drv->macsec)
+		ret = phydev->drv->macsec(phydev, macsec);

is actually doing.

May be it'd be better renaming to at least ndo_do_macsec(), or ndo_setup_macsec()
?

Similar comment is for

+struct netdev_macsec {

It reads like a macsec device context, but it is a macsec configuration command.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 06/10] net: introduce a net_device_ops macsec helper
  2019-01-24 14:58   ` Igor Russkikh
@ 2019-01-24 15:05     ` Antoine Tenart
  0 siblings, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-24 15:05 UTC (permalink / raw)
  To: Igor Russkikh
  Cc: Antoine Tenart, davem, sd, andrew, f.fainelli, hkallweit1,
	netdev, linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

Hi Igor,

On Thu, Jan 24, 2019 at 02:58:45PM +0000, Igor Russkikh wrote:
> 
> Its great to see macsec hw offload infrastructure happening!
> 
> > @@ -1441,6 +1445,10 @@ struct net_device_ops {
> >  						u32 flags);
> >  	int			(*ndo_xsk_async_xmit)(struct net_device *dev,
> >  						      u32 queue_id);
> > +#ifdef CONFIG_MACSEC
> > +	int			(*ndo_macsec)(struct net_device *dev,
> > +					      struct netdev_macsec *macsec);
> > +#endif
> >  };
> 
> Most of ndo's are named by action verbs. This ndo is abit misleading, reader
> may have difficulties understanding what
> 
> +	if (phydev->drv->macsec)
> +		ret = phydev->drv->macsec(phydev, macsec);
> 
> is actually doing.
> 
> May be it'd be better renaming to at least ndo_do_macsec(), or ndo_setup_macsec()
> ?
> 
> Similar comment is for
> 
> +struct netdev_macsec {
> 
> It reads like a macsec device context, but it is a macsec configuration command.

OK, I'll rename the functions so that they contain a verb.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 06/10] net: introduce a net_device_ops macsec helper
  2019-01-24  9:23     ` Antoine Tenart
@ 2019-01-31  9:26       ` Antoine Tenart
  2019-02-01  3:50       ` Florian Fainelli
  1 sibling, 0 replies; 26+ messages in thread
From: Antoine Tenart @ 2019-01-31  9:26 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Antoine Tenart, davem, sd, andrew, hkallweit1, netdev,
	linux-kernel, thomas.petazzoni, alexandre.belloni,
	quentin.schulz, allan.nielsen

Hi,

On Thu, Jan 24, 2019 at 10:23:49AM +0100, Antoine Tenart wrote:
> On Wed, Jan 23, 2019 at 12:16:08PM -0800, Florian Fainelli wrote:
> > On 1/23/19 7:56 AM, Antoine Tenart wrote:
> > > @@ -1441,6 +1445,10 @@ struct net_device_ops {
> > >  						u32 flags);
> > >  	int			(*ndo_xsk_async_xmit)(struct net_device *dev,
> > >  						      u32 queue_id);
> > > +#ifdef CONFIG_MACSEC
> > > +	int			(*ndo_macsec)(struct net_device *dev,
> > > +					      struct netdev_macsec *macsec);
> > 
> > You would really want to define an API which is more oriented towards
> > configuring/deconfiguring a MACsec association here, e.g.: similar to
> > what the IPsec offload ndos offer.
> 
> This means mostly moving from a single function using a command field to
> multiple specialized functions to add/remove each element of MACsec
> configuration.
> 
> I don't have strong opinion on the single helper vs a structure
> containing pointers to specialized ones, but out of curiosity what's the
> benefit of such a move? Future additions and maintainability?
> 
> > It is not clear to me whether after your patch series we still need to
> > create a macsec virtual device, and that gets offloaded onto its real
> > device/PHY device, or if we don't need that all?
> 
> After this series, we will still need the virtual MACsec interface. When
> using hardware offloading this interface isn't doing much, but it's the
> interface used to configure all the MACsec connexions.
> 
> This is because, and that's specific to MACsec (vs IPsec), a software
> implementation is already supported and it's using a virtual interface
> to perform all the MACsec related operations (vs hooks in the Rx/Tx
> paths). I really wanted to avoid having two interfaces and ways of
> configuring MACsec depending on if the offloading is used.
> 
> This should also allow in the future to disable at run-time the
> offloading on a given interface, and to still have MACsec working in
> software (or the opposite, with extra work). For this to work, the
> virtual interface still has to provide an Rx and a Tx functions so that
> programs can bind onto the same interface, regardless of if the
> offloading is enabled.

Do you need extra information and explanations about this? I believe
this point is very important as the design choices were influenced a lot
by reusing the s/w implementation logic and API.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH net-next 06/10] net: introduce a net_device_ops macsec helper
  2019-01-24  9:23     ` Antoine Tenart
  2019-01-31  9:26       ` Antoine Tenart
@ 2019-02-01  3:50       ` Florian Fainelli
  1 sibling, 0 replies; 26+ messages in thread
From: Florian Fainelli @ 2019-02-01  3:50 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, sd, andrew, hkallweit1, netdev, linux-kernel,
	thomas.petazzoni, alexandre.belloni, quentin.schulz,
	allan.nielsen



On 1/24/19 1:23 AM, Antoine Tenart wrote:
> Hi Florian,
> 
> On Wed, Jan 23, 2019 at 12:16:08PM -0800, Florian Fainelli wrote:
>> On 1/23/19 7:56 AM, Antoine Tenart wrote:
>>> This patch introduces a net_device_ops MACsec helper to allow net device
>>> drivers to implement a MACsec offloading solution.
>>>
>>> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
>>> ---
>>>  include/linux/netdevice.h | 8 ++++++++
>>>  1 file changed, 8 insertions(+)
>>>
>>> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>>> index e675ef97a426..ee2f40dca515 100644
>>> --- a/include/linux/netdevice.h
>>> +++ b/include/linux/netdevice.h
>>> @@ -53,6 +53,10 @@
>>>  #include <uapi/linux/pkt_cls.h>
>>>  #include <linux/hashtable.h>
>>>  
>>> +#ifdef CONFIG_MACSEC
>>> +#include <net/macsec.h>
>>> +#endif
>>
>> You can provide a forward declaration for struct netdev_macsec and not
>> have to include that header file.
> 
> OK.
> 
>>> +
>>>  struct netpoll_info;
>>>  struct device;
>>>  struct phy_device;
>>> @@ -1441,6 +1445,10 @@ struct net_device_ops {
>>>  						u32 flags);
>>>  	int			(*ndo_xsk_async_xmit)(struct net_device *dev,
>>>  						      u32 queue_id);
>>> +#ifdef CONFIG_MACSEC
>>> +	int			(*ndo_macsec)(struct net_device *dev,
>>> +					      struct netdev_macsec *macsec);
>>
>> You would really want to define an API which is more oriented towards
>> configuring/deconfiguring a MACsec association here, e.g.: similar to
>> what the IPsec offload ndos offer.
> 
> This means mostly moving from a single function using a command field to
> multiple specialized functions to add/remove each element of MACsec
> configuration.
> 
> I don't have strong opinion on the single helper vs a structure
> containing pointers to specialized ones, but out of curiosity what's the
> benefit of such a move? Future additions and maintainability?

Having multiple operations typically allows for better granularity when
you have HW that may not be capable of offloading an entire protocol
that way you can easily implement fallbacks within the core of that
protocol handling in Linux.

Maybe if you just rename this netdev_macsec_context that will make it
clearer what this does.

> 
>> It is not clear to me whether after your patch series we still need to
>> create a macsec virtual device, and that gets offloaded onto its real
>> device/PHY device, or if we don't need that all?
> 
> After this series, we will still need the virtual MACsec interface. When
> using hardware offloading this interface isn't doing much, but it's the
> interface used to configure all the MACsec connexions.

By not doing much, you mean its data path is basically unused? That
would be quite a deviation from any other type of offload that Linux has
AFAICT, for instance on VLAN devices you still have some amount of data
on the VLAN net_device, etc.

> 
> This is because, and that's specific to MACsec (vs IPsec), a software
> implementation is already supported and it's using a virtual interface
> to perform all the MACsec related operations (vs hooks in the Rx/Tx
> paths). I really wanted to avoid having two interfaces and ways of
> configuring MACsec depending on if the offloading is used.

The virtual network device makes sense when there is some special
treatment (encap/decap, encryption/decryption) that must happen before
sending a frame/PDU onto the wire. It's the same thing here AFAICT, but
since the HW supports doing it in the PHY directly, it's a tough one.

> 
> This should also allow in the future to disable at run-time the
> offloading on a given interface, and to still have MACsec working in
> software (or the opposite, with extra work). For this to work, the
> virtual interface still has to provide an Rx and a Tx functions so that
> programs can bind onto the same interface, regardless of if the
> offloading is enabled.

It would really be good to hear from Sabrina since she authored support
for MACsec to begin with.
-- 
Florian

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2019-02-01  3:50 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-23 15:56 [PATCH net-next 00/10] net: macsec: initial support for hardware offloading Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 01/10] net: introduce the MACSEC netdev feature Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 02/10] net: macsec: convert to SPDX Antoine Tenart
2019-01-23 17:03   ` Andrew Lunn
2019-01-24  8:54     ` Antoine Tenart
2019-01-24 13:11       ` Andrew Lunn
2019-01-24 13:29         ` Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 03/10] net: macsec: move some definitions in a dedicated header Antoine Tenart
2019-01-23 20:11   ` Florian Fainelli
2019-01-24  1:00     ` David Miller
2019-01-24  8:58     ` Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 04/10] net: macsec: introduce the netdev_macsec structure Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 05/10] net: phy: introduce a phy_driver macsec helper Antoine Tenart
2019-01-23 17:08   ` Andrew Lunn
2019-01-24  8:56     ` Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 06/10] net: introduce a net_device_ops " Antoine Tenart
2019-01-23 20:16   ` Florian Fainelli
2019-01-24  9:23     ` Antoine Tenart
2019-01-31  9:26       ` Antoine Tenart
2019-02-01  3:50       ` Florian Fainelli
2019-01-24 14:58   ` Igor Russkikh
2019-01-24 15:05     ` Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 07/10] net: macsec: hardware offloading infrastructure Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 08/10] net: phy: export __phy_read_page/__phy_write_page Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 09/10] net: phy: mscc: macsec initialization Antoine Tenart
2019-01-23 15:56 ` [PATCH net-next 10/10] net: phy: mscc: macsec support Antoine Tenart

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).