nfp: add helpers for FEC support
authorDirk van der Merwe <dirk.vandermerwe@netronome.com>
Sat, 4 Nov 2017 15:48:59 +0000 (16:48 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 5 Nov 2017 14:23:26 +0000 (23:23 +0900)
Implement helpers to determine and modify FEC modes via the NSP.
The NSP advertises FEC capabilities on a per port basis and provides
support for:
* Auto mode selection
* Reed Solomon
* BaseR
* None/Off

Signed-off-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c

index 47486d4..650ca1a 100644 (file)
@@ -79,6 +79,18 @@ enum nfp_eth_aneg {
        NFP_ANEG_DISABLED,
 };
 
+enum nfp_eth_fec {
+       NFP_FEC_AUTO_BIT = 0,
+       NFP_FEC_BASER_BIT,
+       NFP_FEC_REED_SOLOMON_BIT,
+       NFP_FEC_DISABLED_BIT,
+};
+
+#define NFP_FEC_AUTO           BIT(NFP_FEC_AUTO_BIT)
+#define NFP_FEC_BASER          BIT(NFP_FEC_BASER_BIT)
+#define NFP_FEC_REED_SOLOMON   BIT(NFP_FEC_REED_SOLOMON_BIT)
+#define NFP_FEC_DISABLED       BIT(NFP_FEC_DISABLED_BIT)
+
 /**
  * struct nfp_eth_table - ETH table information
  * @count:     number of table entries
@@ -93,6 +105,7 @@ enum nfp_eth_aneg {
  * @speed:     interface speed (in Mbps)
  * @interface: interface (module) plugged in
  * @media:     media type of the @interface
+ * @fec:       forward error correction mode
  * @aneg:      auto negotiation mode
  * @mac_addr:  interface MAC address
  * @label_port:        port id
@@ -105,6 +118,7 @@ enum nfp_eth_aneg {
  * @port_type: one of %PORT_* defines for ethtool
  * @port_lanes:        total number of lanes on the port (sum of lanes of all subports)
  * @is_split:  is interface part of a split port
+ * @fec_modes_supported:       bitmap of FEC modes supported
  */
 struct nfp_eth_table {
        unsigned int count;
@@ -120,6 +134,7 @@ struct nfp_eth_table {
                unsigned int interface;
                enum nfp_eth_media media;
 
+               enum nfp_eth_fec fec;
                enum nfp_eth_aneg aneg;
 
                u8 mac_addr[ETH_ALEN];
@@ -139,6 +154,8 @@ struct nfp_eth_table {
                unsigned int port_lanes;
 
                bool is_split;
+
+               unsigned int fec_modes_supported;
        } ports[0];
 };
 
@@ -149,6 +166,19 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp);
 int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable);
 int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx,
                           bool configed);
+int
+nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode);
+
+static inline bool nfp_eth_can_support_fec(struct nfp_eth_table_port *eth_port)
+{
+       return !!eth_port->fec_modes_supported;
+}
+
+static inline unsigned int
+nfp_eth_supported_fec_modes(struct nfp_eth_table_port *eth_port)
+{
+       return eth_port->fec_modes_supported;
+}
 
 struct nfp_nsp *nfp_eth_config_start(struct nfp_cpp *cpp, unsigned int idx);
 int nfp_eth_config_commit_end(struct nfp_nsp *nsp);
index 4725139..7ca5896 100644 (file)
@@ -55,6 +55,8 @@
 #define NSP_ETH_PORT_INDEX             GENMASK_ULL(15, 8)
 #define NSP_ETH_PORT_LABEL             GENMASK_ULL(53, 48)
 #define NSP_ETH_PORT_PHYLABEL          GENMASK_ULL(59, 54)
+#define NSP_ETH_PORT_FEC_SUPP_BASER    BIT_ULL(60)
+#define NSP_ETH_PORT_FEC_SUPP_RS       BIT_ULL(61)
 
 #define NSP_ETH_PORT_LANES_MASK                cpu_to_le64(NSP_ETH_PORT_LANES)
 
@@ -67,6 +69,7 @@
 #define NSP_ETH_STATE_MEDIA            GENMASK_ULL(21, 20)
 #define NSP_ETH_STATE_OVRD_CHNG                BIT_ULL(22)
 #define NSP_ETH_STATE_ANEG             GENMASK_ULL(25, 23)
+#define NSP_ETH_STATE_FEC              GENMASK_ULL(27, 26)
 
 #define NSP_ETH_CTRL_CONFIGURED                BIT_ULL(0)
 #define NSP_ETH_CTRL_ENABLED           BIT_ULL(1)
@@ -75,6 +78,7 @@
 #define NSP_ETH_CTRL_SET_RATE          BIT_ULL(4)
 #define NSP_ETH_CTRL_SET_LANES         BIT_ULL(5)
 #define NSP_ETH_CTRL_SET_ANEG          BIT_ULL(6)
+#define NSP_ETH_CTRL_SET_FEC           BIT_ULL(7)
 
 enum nfp_eth_raw {
        NSP_ETH_RAW_PORT = 0,
@@ -152,6 +156,7 @@ nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src,
                       unsigned int index, struct nfp_eth_table_port *dst)
 {
        unsigned int rate;
+       unsigned int fec;
        u64 port, state;
 
        port = le64_to_cpu(src->port);
@@ -183,6 +188,18 @@ nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src,
 
        dst->override_changed = FIELD_GET(NSP_ETH_STATE_OVRD_CHNG, state);
        dst->aneg = FIELD_GET(NSP_ETH_STATE_ANEG, state);
+
+       if (nfp_nsp_get_abi_ver_minor(nsp) < 22)
+               return;
+
+       fec = FIELD_GET(NSP_ETH_PORT_FEC_SUPP_BASER, port);
+       dst->fec_modes_supported |= fec << NFP_FEC_BASER_BIT;
+       fec = FIELD_GET(NSP_ETH_PORT_FEC_SUPP_RS, port);
+       dst->fec_modes_supported |= fec << NFP_FEC_REED_SOLOMON_BIT;
+       if (dst->fec_modes_supported)
+               dst->fec_modes_supported |= NFP_FEC_AUTO | NFP_FEC_DISABLED;
+
+       dst->fec = 1 << FIELD_GET(NSP_ETH_STATE_FEC, state);
 }
 
 static void
@@ -528,6 +545,53 @@ int __nfp_eth_set_aneg(struct nfp_nsp *nsp, enum nfp_eth_aneg mode)
 }
 
 /**
+ * __nfp_eth_set_fec() - set PHY forward error correction control bit
+ * @nsp:       NFP NSP handle returned from nfp_eth_config_start()
+ * @mode:      Desired fec mode
+ *
+ * Set the PHY module forward error correction mode.
+ * Will write to hwinfo overrides in the flash (persistent config).
+ *
+ * Return: 0 or -ERRNO.
+ */
+static int __nfp_eth_set_fec(struct nfp_nsp *nsp, enum nfp_eth_fec mode)
+{
+       return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
+                                     NSP_ETH_STATE_FEC, mode,
+                                     NSP_ETH_CTRL_SET_FEC);
+}
+
+/**
+ * nfp_eth_set_fec() - set PHY forward error correction control mode
+ * @cpp:       NFP CPP handle
+ * @idx:       NFP chip-wide port index
+ * @mode:      Desired fec mode
+ *
+ * Return:
+ * 0 - configuration successful;
+ * 1 - no changes were needed;
+ * -ERRNO - configuration failed.
+ */
+int
+nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode)
+{
+       struct nfp_nsp *nsp;
+       int err;
+
+       nsp = nfp_eth_config_start(cpp, idx);
+       if (IS_ERR(nsp))
+               return PTR_ERR(nsp);
+
+       err = __nfp_eth_set_fec(nsp, mode);
+       if (err) {
+               nfp_eth_config_cleanup_end(nsp);
+               return err;
+       }
+
+       return nfp_eth_config_commit_end(nsp);
+}
+
+/**
  * __nfp_eth_set_speed() - set interface speed/rate
  * @nsp:       NFP NSP handle returned from nfp_eth_config_start()
  * @speed:     Desired speed (per lane)