cxgb4/cxgb4vf: Display advertised FEC in ethtool
authorVishal Kulkarni <vishal@chelsio.com>
Fri, 29 Mar 2019 12:54:03 +0000 (18:24 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 29 Mar 2019 20:47:38 +0000 (13:47 -0700)
This patch advertises Forward Error Correction in ethtool

Signed-off-by: Casey Leedom <leedom@chelsio.com>
Signed-off-by: Vishal Kulkarni <vishal@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c

index 956219c..a8fe080 100644 (file)
@@ -1575,9 +1575,11 @@ int t4_slow_intr_handler(struct adapter *adapter);
 
 int t4_wait_dev_ready(void __iomem *regs);
 
+fw_port_cap32_t t4_link_acaps(struct adapter *adapter, unsigned int port,
+                             struct link_config *lc);
 int t4_link_l1cfg_core(struct adapter *adap, unsigned int mbox,
                       unsigned int port, struct link_config *lc,
-                      bool sleep_ok, int timeout);
+                      u8 sleep_ok, int timeout);
 
 static inline int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox,
                                unsigned int port, struct link_config *lc)
index bec4711..9e58930 100644 (file)
@@ -442,7 +442,7 @@ static unsigned int speed_to_fw_caps(int speed)
  *     Link Mode Mask.
  */
 static void fw_caps_to_lmm(enum fw_port_type port_type,
-                          unsigned int fw_caps,
+                          fw_port_cap32_t fw_caps,
                           unsigned long *link_mode_mask)
 {
        #define SET_LMM(__lmm_name) \
@@ -632,7 +632,10 @@ static int get_link_ksettings(struct net_device *dev,
 
        fw_caps_to_lmm(pi->port_type, pi->link_cfg.pcaps,
                       link_ksettings->link_modes.supported);
-       fw_caps_to_lmm(pi->port_type, pi->link_cfg.acaps,
+       fw_caps_to_lmm(pi->port_type,
+                      t4_link_acaps(pi->adapter,
+                                    pi->lport,
+                                    &pi->link_cfg),
                       link_ksettings->link_modes.advertising);
        fw_caps_to_lmm(pi->port_type, pi->link_cfg.lpacaps,
                       link_ksettings->link_modes.lp_advertising);
@@ -642,22 +645,6 @@ static int get_link_ksettings(struct net_device *dev,
                       : SPEED_UNKNOWN);
        base->duplex = DUPLEX_FULL;
 
-       if (pi->link_cfg.fc & PAUSE_RX) {
-               if (pi->link_cfg.fc & PAUSE_TX) {
-                       ethtool_link_ksettings_add_link_mode(link_ksettings,
-                                                            advertising,
-                                                            Pause);
-               } else {
-                       ethtool_link_ksettings_add_link_mode(link_ksettings,
-                                                            advertising,
-                                                            Asym_Pause);
-               }
-       } else if (pi->link_cfg.fc & PAUSE_TX) {
-               ethtool_link_ksettings_add_link_mode(link_ksettings,
-                                                    advertising,
-                                                    Asym_Pause);
-       }
-
        base->autoneg = pi->link_cfg.autoneg;
        if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)
                ethtool_link_ksettings_add_link_mode(link_ksettings,
index a354404..f9b70be 100644 (file)
@@ -3964,6 +3964,14 @@ void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
        }
 }
 
+/* The ADVERT_MASK is used to mask out all of the Advertised Firmware Port
+ * Capabilities which we control with separate controls -- see, for instance,
+ * Pause Frames and Forward Error Correction.  In order to determine what the
+ * full set of Advertised Port Capabilities are, the base Advertised Port
+ * Capabilities (masked by ADVERT_MASK) must be combined with the Advertised
+ * Port Capabilities associated with those other controls.  See
+ * t4_link_acaps() for how this is done.
+ */
 #define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \
                     FW_PORT_CAP32_ANEG)
 
@@ -4061,6 +4069,9 @@ static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause)
 /* Translate Common Code Pause specification into Firmware Port Capabilities */
 static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
 {
+       /* Translate orthogonal RX/TX Pause Controls for L1 Configure
+        * commands, etc.
+        */
        fw_port_cap32_t fw_pause = 0;
 
        if (cc_pause & PAUSE_RX)
@@ -4070,6 +4081,19 @@ static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
        if (!(cc_pause & PAUSE_AUTONEG))
                fw_pause |= FW_PORT_CAP32_FORCE_PAUSE;
 
+       /* Translate orthogonal Pause controls into IEEE 802.3 Pause,
+        * Asymetrical Pause for use in reporting to upper layer OS code, etc.
+        * Note that these bits are ignored in L1 Configure commands.
+        */
+       if (cc_pause & PAUSE_RX) {
+               if (cc_pause & PAUSE_TX)
+                       fw_pause |= FW_PORT_CAP32_802_3_PAUSE;
+               else
+                       fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
+       } else if (cc_pause & PAUSE_TX) {
+               fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
+       }
+
        return fw_pause;
 }
 
@@ -4100,31 +4124,22 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
 }
 
 /**
- *     t4_link_l1cfg - apply link configuration to MAC/PHY
+ *     t4_link_acaps - compute Link Advertised Port Capabilities
  *     @adapter: the adapter
- *     @mbox: the Firmware Mailbox to use
  *     @port: the Port ID
  *     @lc: the Port's Link Configuration
- *     @sleep_ok: if true we may sleep while awaiting command completion
- *     @timeout: time to wait for command to finish before timing out
- *             (negative implies @sleep_ok=false)
  *
- *     Set up a port's MAC and PHY according to a desired link configuration.
- *     - If the PHY can auto-negotiate first decide what to advertise, then
- *       enable/disable auto-negotiation as desired, and reset.
- *     - If the PHY does not auto-negotiate just reset it.
- *     - If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
- *       otherwise do it later based on the outcome of auto-negotiation.
+ *     Synthesize the Advertised Port Capabilities we'll be using based on
+ *     the base Advertised Port Capabilities (which have been filtered by
+ *     ADVERT_MASK) plus the individual controls for things like Pause
+ *     Frames, Forward Error Correction, MDI, etc.
  */
-int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
-                      unsigned int port, struct link_config *lc,
-                      bool sleep_ok, int timeout)
+fw_port_cap32_t t4_link_acaps(struct adapter *adapter, unsigned int port,
+                             struct link_config *lc)
 {
-       unsigned int fw_caps = adapter->params.fw_caps_support;
-       fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap;
-       struct fw_port_cmd cmd;
+       fw_port_cap32_t fw_fc, fw_fec, acaps;
        unsigned int fw_mdi;
-       int ret;
+       char cc_fec;
 
        fw_mdi = (FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO) & lc->pcaps);
 
@@ -4151,18 +4166,15 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
         * init_link_config().
         */
        if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
-               if (lc->autoneg == AUTONEG_ENABLE)
-                       return -EINVAL;
-
-               rcap = lc->acaps | fw_fc | fw_fec;
+               acaps = lc->acaps | fw_fc | fw_fec;
                lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
                lc->fec = cc_fec;
        } else if (lc->autoneg == AUTONEG_DISABLE) {
-               rcap = lc->speed_caps | fw_fc | fw_fec | fw_mdi;
+               acaps = lc->speed_caps | fw_fc | fw_fec | fw_mdi;
                lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
                lc->fec = cc_fec;
        } else {
-               rcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
+               acaps = lc->acaps | fw_fc | fw_fec | fw_mdi;
        }
 
        /* Some Requested Port Capabilities are trivially wrong if they exceed
@@ -4173,15 +4185,50 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
         * we need to exclude this from this check in order to maintain
         * compatibility ...
         */
-       if ((rcap & ~lc->pcaps) & ~FW_PORT_CAP32_FORCE_PAUSE) {
-               dev_err(adapter->pdev_dev,
-                       "Requested Port Capabilities %#x exceed Physical Port Capabilities %#x\n",
-                       rcap, lc->pcaps);
+       if ((acaps & ~lc->pcaps) & ~FW_PORT_CAP32_FORCE_PAUSE) {
+               dev_err(adapter->pdev_dev, "Requested Port Capabilities %#x exceed Physical Port Capabilities %#x\n",
+                       acaps, lc->pcaps);
+               return -EINVAL;
+       }
+
+       return acaps;
+}
+
+/**
+ *     t4_link_l1cfg_core - apply link configuration to MAC/PHY
+ *     @adapter: the adapter
+ *     @mbox: the Firmware Mailbox to use
+ *     @port: the Port ID
+ *     @lc: the Port's Link Configuration
+ *     @sleep_ok: if true we may sleep while awaiting command completion
+ *     @timeout: time to wait for command to finish before timing out
+ *             (negative implies @sleep_ok=false)
+ *
+ *     Set up a port's MAC and PHY according to a desired link configuration.
+ *     - If the PHY can auto-negotiate first decide what to advertise, then
+ *       enable/disable auto-negotiation as desired, and reset.
+ *     - If the PHY does not auto-negotiate just reset it.
+ *     - If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
+ *       otherwise do it later based on the outcome of auto-negotiation.
+ */
+int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
+                      unsigned int port, struct link_config *lc,
+                      u8 sleep_ok, int timeout)
+{
+       unsigned int fw_caps = adapter->params.fw_caps_support;
+       struct fw_port_cmd cmd;
+       fw_port_cap32_t rcap;
+       int ret;
+
+       if (!(lc->pcaps & FW_PORT_CAP32_ANEG) &&
+           lc->autoneg == AUTONEG_ENABLE) {
                return -EINVAL;
        }
 
-       /* And send that on to the Firmware ...
+       /* Compute our Requested Port Capabilities and send that on to the
+        * Firmware.
         */
+       rcap = t4_link_acaps(adapter, port, lc);
        memset(&cmd, 0, sizeof(cmd));
        cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
                                       FW_CMD_REQUEST_F | FW_CMD_EXEC_F |
@@ -4211,7 +4258,7 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
                        rcap, -ret);
                return ret;
        }
-       return ret;
+       return 0;
 }
 
 /**
index adc4d48..a8c4e0c 100644 (file)
@@ -1479,22 +1479,6 @@ static int cxgb4vf_get_link_ksettings(struct net_device *dev,
                base->duplex = DUPLEX_UNKNOWN;
        }
 
-       if (pi->link_cfg.fc & PAUSE_RX) {
-               if (pi->link_cfg.fc & PAUSE_TX) {
-                       ethtool_link_ksettings_add_link_mode(link_ksettings,
-                                                            advertising,
-                                                            Pause);
-               } else {
-                       ethtool_link_ksettings_add_link_mode(link_ksettings,
-                                                            advertising,
-                                                            Asym_Pause);
-               }
-       } else if (pi->link_cfg.fc & PAUSE_TX) {
-               ethtool_link_ksettings_add_link_mode(link_ksettings,
-                                                    advertising,
-                                                    Asym_Pause);
-       }
-
        base->autoneg = pi->link_cfg.autoneg;
        if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)
                ethtool_link_ksettings_add_link_mode(link_ksettings,
index 84dff74..8a389d6 100644 (file)
@@ -313,7 +313,17 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
        return ret;
 }
 
+/* In the Physical Function Driver Common Code, the ADVERT_MASK is used to
+ * mask out bits in the Advertised Port Capabilities which are managed via
+ * separate controls, like Pause Frames and Forward Error Correction.  In the
+ * Virtual Function Common Code, since we never perform L1 Configuration on
+ * the Link, the only things we really need to filter out are things which
+ * we decode and report separately like Speed.
+ */
 #define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \
+                    FW_PORT_CAP32_802_3_PAUSE | \
+                    FW_PORT_CAP32_802_3_ASM_DIR | \
+                    FW_PORT_CAP32_FEC_V(FW_PORT_CAP32_FEC_M) | \
                     FW_PORT_CAP32_ANEG)
 
 /**