net/cxgbe: rework and simplify link handling
authorKarra Satwik <kaara.satwik@chelsio.com>
Sun, 20 Dec 2020 22:47:41 +0000 (04:17 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 19 Jan 2021 02:30:14 +0000 (03:30 +0100)
Rework and simplify link handling code. Remove redundant
variables in link configuration structure and directly
extract information from the 32-bit link capabilities.

Signed-off-by: Karra Satwik <kaara.satwik@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
drivers/net/cxgbe/base/adapter.h
drivers/net/cxgbe/base/common.h
drivers/net/cxgbe/base/t4_hw.c
drivers/net/cxgbe/base/t4fw_interface.h
drivers/net/cxgbe/base/t4vf_hw.c
drivers/net/cxgbe/cxgbe_ethdev.c
drivers/net/cxgbe/cxgbe_main.c

index 6ff009a..a5a3313 100644 (file)
@@ -39,9 +39,6 @@ struct port_info {
        short int xact_addr_filt;       /* index of exact MAC address filter */
 
        u16    viid;                    /* associated virtual interface id */
-       s8     mdio_addr;               /* address of the PHY */
-       u8     port_type;               /* firmware port type */
-       u8     mod_type;                /* firmware module type */
        u8     port_id;                 /* physical port ID */
        u8     pidx;                    /* port index for this PF */
        u8     tx_chan;                 /* associated channel */
@@ -63,12 +60,6 @@ struct port_info {
        u8 vivld;
 };
 
-/* Enable or disable autonegotiation.  If this is set to enable,
- * the forced link modes above are completely ignored.
- */
-#define AUTONEG_DISABLE         0x00
-#define AUTONEG_ENABLE          0x01
-
 enum {                                 /* adapter flags */
        FULL_INIT_DONE     = (1 << 0),
        USING_MSI          = (1 << 1),
@@ -801,7 +792,6 @@ void t4_free_mem(void *addr);
 #define t4_os_free(_ptr)       t4_free_mem((_ptr))
 
 void t4_os_portmod_changed(const struct adapter *adap, int port_id);
-void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
 
 void reclaim_completed_tx(struct sge_txq *q);
 void t4_free_sge_resources(struct adapter *adap);
index 86f3dc8..a244df7 100644 (file)
@@ -38,18 +38,6 @@ enum dev_master { MASTER_CANT, MASTER_MAY, MASTER_MUST };
 
 enum dev_state { DEV_STATE_UNINIT, DEV_STATE_INIT, DEV_STATE_ERR };
 
-enum cc_pause {
-       PAUSE_RX      = 1 << 0,
-       PAUSE_TX      = 1 << 1,
-       PAUSE_AUTONEG = 1 << 2
-};
-
-enum cc_fec {
-       FEC_AUTO     = 1 << 0,    /* IEEE 802.3 "automatic" */
-       FEC_RS       = 1 << 1,    /* Reed-Solomon */
-       FEC_BASER_RS = 1 << 2,    /* BaseR/Reed-Solomon */
-};
-
 enum { MEM_EDC0, MEM_EDC1, MEM_MC, MEM_MC0 = MEM_MC, MEM_MC1 };
 
 struct port_stats {
@@ -281,28 +269,19 @@ struct adapter_params {
 
 /* Firmware Port Capabilities types.
  */
-typedef u32 fw_port_cap32_t;    /* 32-bit Port Capabilities integral value */
-
 struct link_config {
-       fw_port_cap32_t pcaps;          /* link capabilities */
-       fw_port_cap32_t acaps;          /* advertised capabilities */
-
-       u32 requested_speed;            /* speed (Mb/s) user has requested */
-       u32 speed;                      /* actual link speed (Mb/s) */
-
-       enum cc_pause requested_fc;     /* flow control user has requested */
-       enum cc_pause fc;               /* actual link flow control */
+       u32 pcaps;         /* Physically supported link caps */
+       u32 acaps;         /* Advertised link caps */
 
-       enum cc_fec auto_fec;           /* Forward Error Correction
-                                        * "automatic" (IEEE 802.3)
-                                        */
-       enum cc_fec requested_fec;      /* Forward Error Correction requested */
-       enum cc_fec fec;                /* Forward Error Correction actual */
+       u32 link_caps;     /* Current link caps */
+       u32 admin_caps;    /* Admin configured link caps  */
 
-       unsigned char autoneg;          /* autonegotiating? */
+       u8 mdio_addr;      /* Address of the PHY */
+       u8 port_type;      /* Firmware port type */
+       u8 mod_type;       /* Firmware module type */
 
-       unsigned char link_ok;          /* link up? */
-       unsigned char link_down_rc;     /* link down reason */
+       u8 link_ok;        /* Link up? */
+       u8 link_down_rc;   /* Link down reason */
 };
 
 #include "adapter.h"
@@ -338,8 +317,21 @@ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
                            unsigned int mask, unsigned int val);
 void t4_intr_enable(struct adapter *adapter);
 void t4_intr_disable(struct adapter *adapter);
-int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
-                 struct link_config *lc);
+int t4_link_l1cfg_core(struct port_info *pi, u32 caps, u8 sleep_ok);
+static inline int t4_link_l1cfg(struct port_info *pi, u32 caps)
+{
+       return t4_link_l1cfg_core(pi, caps, true);
+}
+
+static inline int t4_link_l1cfg_ns(struct port_info *pi, u32 caps)
+{
+       return t4_link_l1cfg_core(pi, caps, false);
+}
+
+int t4_set_link_speed(struct port_info *pi, u32 speed, u32 *new_caps);
+int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
+                     u8 pause_rx, u32 *new_caps);
+unsigned int t4_fwcap_to_speed(u32 caps);
 void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
                  const unsigned short *alpha, const unsigned short *beta);
 int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
@@ -496,8 +488,8 @@ void t4_get_port_stats_offset(struct adapter *adap, int idx,
                              struct port_stats *stats,
                              struct port_stats *offset);
 void t4_clr_port_stats(struct adapter *adap, int idx);
-void init_link_config(struct link_config *lc, fw_port_cap32_t pcaps,
-                     fw_port_cap32_t acaps);
+void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
+                        u8 mdio_addr, u8 port_type, u8 mod_type);
 void t4_reset_link_config(struct adapter *adap, int idx);
 int t4_get_version_info(struct adapter *adapter);
 void t4_dump_version_info(struct adapter *adapter);
index 4422774..c88367f 100644 (file)
@@ -2809,67 +2809,11 @@ void t4_dump_version_info(struct adapter *adapter)
                         G_FW_HDR_FW_VER_BUILD(adapter->params.er_vers));
 }
 
-#define ADVERT_MASK (V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED) | \
-                    FW_PORT_CAP32_ANEG)
-
-/* Translate Firmware Pause specification to Common Code */
-static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause)
-{
-       enum cc_pause cc_pause = 0;
-
-       if (fw_pause & FW_PORT_CAP32_FC_RX)
-               cc_pause |= PAUSE_RX;
-       if (fw_pause & FW_PORT_CAP32_FC_TX)
-               cc_pause |= PAUSE_TX;
-
-       return cc_pause;
-}
-
-/* Translate Common Code Pause Frame specification into Firmware */
-static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
-{
-       fw_port_cap32_t fw_pause = 0;
-
-       if (cc_pause & PAUSE_RX)
-               fw_pause |= FW_PORT_CAP32_FC_RX;
-       if (cc_pause & PAUSE_TX)
-               fw_pause |= FW_PORT_CAP32_FC_TX;
-
-       return fw_pause;
-}
-
-/* Translate Firmware Forward Error Correction specification to Common Code */
-static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec)
-{
-       enum cc_fec cc_fec = 0;
-
-       if (fw_fec & FW_PORT_CAP32_FEC_RS)
-               cc_fec |= FEC_RS;
-       if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS)
-               cc_fec |= FEC_BASER_RS;
-
-       return cc_fec;
-}
-
-/* Translate Common Code Forward Error Correction specification to Firmware */
-static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
-{
-       fw_port_cap32_t fw_fec = 0;
-
-       if (cc_fec & FEC_RS)
-               fw_fec |= FW_PORT_CAP32_FEC_RS;
-       if (cc_fec & FEC_BASER_RS)
-               fw_fec |= FW_PORT_CAP32_FEC_BASER_RS;
-
-       return fw_fec;
-}
-
 /**
- * t4_link_l1cfg - 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
+ * t4_link_l1cfg_core - apply link configuration to MAC/PHY
+ * @pi: the port info
+ * @caps: link capabilities to configure
+ * @sleep_ok: if true we may sleep while awaiting command completion
  *
  * 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
@@ -2878,57 +2822,36 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
  * - 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(struct adapter *adap, unsigned int mbox, unsigned int port,
-                 struct link_config *lc)
+int t4_link_l1cfg_core(struct port_info *pi, u32 caps, u8 sleep_ok)
 {
-       unsigned int fw_mdi = V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
-       fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap;
+       struct link_config *lc = &pi->link_cfg;
+       struct adapter *adap = pi->adapter;
        struct fw_port_cmd cmd;
+       int ret;
 
-       lc->link_ok = 0;
-
-       fw_fc = cc_to_fwcap_pause(lc->requested_fc);
-
-       /* Convert Common Code Forward Error Control settings into the
-        * Firmware's API.  If the current Requested FEC has "Automatic"
-        * (IEEE 802.3) specified, then we use whatever the Firmware
-        * sent us as part of it's IEEE 802.3-based interpratation of
-        * the Transceiver Module EPROM FEC parameters.  Otherwise we
-        * use whatever is in the current Requested FEC settings.
-        */
-       if (lc->requested_fec & FEC_AUTO)
-               cc_fec = lc->auto_fec;
-       else
-               cc_fec = lc->requested_fec;
-       fw_fec = cc_to_fwcap_fec(cc_fec);
-
-       /* Figure out what our Requested Port Capabilities are going to be.
-        */
-       if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
-               rcap = (lc->pcaps & ADVERT_MASK) | fw_fc | fw_fec;
-               lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
-               lc->fec = cc_fec;
-       } else if (lc->autoneg == AUTONEG_DISABLE) {
-               rcap = lc->requested_speed | 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;
-       }
-
-       /* And send that on to the Firmware ...
-        */
        memset(&cmd, 0, sizeof(cmd));
        cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
                                       F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
-                                      V_FW_PORT_CMD_PORTID(port));
+                                      V_FW_PORT_CMD_PORTID(pi->port_id));
        cmd.action_to_len16 =
                cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG32) |
                            FW_LEN16(cmd));
 
-       cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap);
+       cmd.u.l1cfg32.rcap32 = cpu_to_be32(caps);
 
-       return t4_wr_mbox(adap, mbox, &cmd, sizeof(cmd), NULL);
+       if (sleep_ok)
+               ret = t4_wr_mbox(adap, adap->mbox, &cmd, sizeof(cmd), NULL);
+       else
+               ret = t4_wr_mbox_ns(adap, adap->mbox, &cmd, sizeof(cmd), NULL);
+
+       if (ret == FW_SUCCESS)
+               lc->link_caps = caps;
+       else
+               dev_err(adap,
+                       "Requested Port Capabilities %#x rejected, error %d\n",
+                       caps, ret);
+
+       return ret;
 }
 
 /**
@@ -4426,8 +4349,32 @@ static const char *t4_link_down_rc_str(unsigned char link_down_rc)
        return reason[link_down_rc];
 }
 
+static u32 t4_speed_to_fwcap(u32 speed)
+{
+       switch (speed) {
+       case 100000:
+               return FW_PORT_CAP32_SPEED_100G;
+       case 50000:
+               return FW_PORT_CAP32_SPEED_50G;
+       case 40000:
+               return FW_PORT_CAP32_SPEED_40G;
+       case 25000:
+               return FW_PORT_CAP32_SPEED_25G;
+       case 10000:
+               return FW_PORT_CAP32_SPEED_10G;
+       case 1000:
+               return FW_PORT_CAP32_SPEED_1G;
+       case 100:
+               return FW_PORT_CAP32_SPEED_100M;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 /* Return the highest speed set in the port capabilities, in Mb/s. */
-static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
+unsigned int t4_fwcap_to_speed(u32 caps)
 {
 #define TEST_SPEED_RETURN(__caps_speed, __speed) \
        do { \
@@ -4448,6 +4395,84 @@ static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
        return 0;
 }
 
+static void t4_set_link_autoneg_speed(struct port_info *pi, u32 *new_caps)
+{
+       struct link_config *lc = &pi->link_cfg;
+       u32 caps = *new_caps;
+
+       caps &= ~V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED);
+       caps |= G_FW_PORT_CAP32_SPEED(lc->acaps);
+
+       *new_caps = caps;
+}
+
+int t4_set_link_speed(struct port_info *pi, u32 speed, u32 *new_caps)
+{
+       u32 fw_speed_cap = t4_speed_to_fwcap(speed);
+       struct link_config *lc = &pi->link_cfg;
+       u32 caps = *new_caps;
+
+       if (!(lc->pcaps & fw_speed_cap))
+               return -EOPNOTSUPP;
+
+       caps &= ~V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED);
+       caps |= fw_speed_cap;
+
+       *new_caps = caps;
+
+       return 0;
+}
+
+int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
+                     u8 pause_rx, u32 *new_caps)
+{
+       struct link_config *lc = &pi->link_cfg;
+       u32 caps = *new_caps;
+       u32 max_speed;
+
+       max_speed = t4_fwcap_to_speed(lc->link_caps);
+
+       if (autoneg) {
+               if (!(lc->pcaps & FW_PORT_CAP32_ANEG))
+                       return -EINVAL;
+
+               caps |= FW_PORT_CAP32_ANEG;
+               t4_set_link_autoneg_speed(pi, &caps);
+       } else {
+               if (!max_speed)
+                       max_speed = t4_fwcap_to_speed(lc->acaps);
+
+               caps &= ~FW_PORT_CAP32_ANEG;
+               t4_set_link_speed(pi, max_speed, &caps);
+       }
+
+       if (lc->pcaps & FW_PORT_CAP32_MDIAUTO)
+               caps |= V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
+
+       caps &= ~V_FW_PORT_CAP32_FC(M_FW_PORT_CAP32_FC);
+       caps &= ~V_FW_PORT_CAP32_802_3(M_FW_PORT_CAP32_802_3);
+       if (pause_tx && pause_rx) {
+               caps |= FW_PORT_CAP32_FC_TX | FW_PORT_CAP32_FC_RX;
+               if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
+                       caps |= FW_PORT_CAP32_802_3_PAUSE;
+       } else if (pause_tx) {
+               caps |= FW_PORT_CAP32_FC_TX;
+               if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
+                       caps |= FW_PORT_CAP32_802_3_ASM_DIR;
+       } else if (pause_rx) {
+               caps |= FW_PORT_CAP32_FC_RX;
+               if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
+                       caps |= FW_PORT_CAP32_802_3_PAUSE;
+
+               if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
+                       caps |= FW_PORT_CAP32_802_3_ASM_DIR;
+       }
+
+       *new_caps = caps;
+
+       return 0;
+}
+
 /**
  * t4_handle_get_port_info - process a FW reply message
  * @pi: the port info
@@ -4459,10 +4484,10 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 {
        const struct fw_port_cmd *cmd = (const void *)rpl;
        u8 link_ok, link_down_rc, mod_type, port_type;
-       u32 action, pcaps, acaps, linkattr, lstatus;
+       u32 action, pcaps, acaps, link_caps, lstatus;
        struct link_config *lc = &pi->link_cfg;
        struct adapter *adapter = pi->adapter;
-       unsigned int speed, fc, fec;
+       u8 mod_changed = 0;
 
        /* Extract the various fields from the Port Information message.
         */
@@ -4481,21 +4506,16 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 
        pcaps = be32_to_cpu(cmd->u.info32.pcaps32);
        acaps = be32_to_cpu(cmd->u.info32.acaps32);
-       linkattr = be32_to_cpu(cmd->u.info32.linkattr32);
-
-       fec = fwcap_to_cc_fec(acaps);
-
-       fc = fwcap_to_cc_pause(linkattr);
-       speed = fwcap_to_speed(linkattr);
+       link_caps = be32_to_cpu(cmd->u.info32.linkattr32);
 
-       if (mod_type != pi->mod_type) {
-               lc->auto_fec = fec;
-               pi->port_type = port_type;
-               pi->mod_type = mod_type;
+       if (mod_type != lc->mod_type) {
+               t4_init_link_config(pi, pcaps, acaps, lc->mdio_addr,
+                                   port_type, mod_type);
                t4_os_portmod_changed(adapter, pi->pidx);
+               mod_changed = 1;
        }
-       if (link_ok != lc->link_ok || speed != lc->speed ||
-           fc != lc->fc || fec != lc->fec) { /* something changed */
+       if (link_ok != lc->link_ok || acaps != lc->acaps ||
+           link_caps != lc->link_caps) { /* something changed */
                if (!link_ok && lc->link_ok) {
                        lc->link_down_rc = link_down_rc;
                        dev_warn(adap, "Port %d link down, reason: %s\n",
@@ -4503,23 +4523,19 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
                                 t4_link_down_rc_str(link_down_rc));
                }
                lc->link_ok = link_ok;
-               lc->speed = speed;
-               lc->fc = fc;
-               lc->fec = fec;
-               lc->pcaps = pcaps;
-               lc->acaps = acaps & ADVERT_MASK;
-
-               if (lc->acaps & FW_PORT_CAP32_ANEG) {
-                       lc->autoneg = AUTONEG_ENABLE;
-               } else {
-                       /* When Autoneg is disabled, user needs to set
-                        * single speed.
-                        * Similar to cxgb4_ethtool.c: set_link_ksettings
-                        */
-                       lc->acaps = 0;
-                       lc->requested_speed = fwcap_to_speed(acaps);
-                       lc->autoneg = AUTONEG_DISABLE;
-               }
+               lc->acaps = acaps;
+               lc->link_caps = link_caps;
+       }
+
+       if (mod_changed) {
+               u32 mod_caps = lc->admin_caps;
+               int ret;
+
+               ret = t4_link_l1cfg_ns(pi, mod_caps);
+               if (ret != FW_SUCCESS)
+                       dev_warn(adapter,
+                                "Attempt to update new Transceiver Module settings %#x failed with error: %d\n",
+                                mod_caps, ret);
        }
 }
 
@@ -4595,45 +4611,49 @@ void t4_reset_link_config(struct adapter *adap, int idx)
        struct link_config *lc = &pi->link_cfg;
 
        lc->link_ok = 0;
-       lc->requested_speed = 0;
-       lc->requested_fc = 0;
-       lc->speed = 0;
-       lc->fc = 0;
+       lc->link_down_rc = 0;
+       lc->link_caps = 0;
 }
 
 /**
- * init_link_config - initialize a link's SW state
- * @lc: structure holding the link state
+ * t4_init_link_config - initialize a link's SW state
+ * @pi: the port info
  * @pcaps: link Port Capabilities
  * @acaps: link current Advertised Port Capabilities
+ * @mdio_addr : address of the PHY
+ * @port_type : firmware port type
+ * @mod_type  : firmware module type
  *
  * Initializes the SW state maintained for each link, including the link's
  * capabilities and default speed/flow-control/autonegotiation settings.
  */
-void init_link_config(struct link_config *lc, fw_port_cap32_t pcaps,
-                     fw_port_cap32_t acaps)
+void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
+                        u8 mdio_addr, u8 port_type, u8 mod_type)
 {
+       struct link_config *lc = &pi->link_cfg;
+
        lc->pcaps = pcaps;
-       lc->requested_speed = 0;
-       lc->speed = 0;
-       lc->requested_fc = 0;
-       lc->fc = 0;
+       lc->acaps = acaps;
+       lc->admin_caps = acaps;
+       lc->link_caps = 0;
 
-       /**
-        * For Forward Error Control, we default to whatever the Firmware
-        * tells us the Link is currently advertising.
-        */
-       lc->auto_fec = fwcap_to_cc_fec(acaps);
-       lc->requested_fec = FEC_AUTO;
-       lc->fec = lc->auto_fec;
-
-       if (lc->pcaps & FW_PORT_CAP32_ANEG) {
-               lc->acaps = lc->pcaps & ADVERT_MASK;
-               lc->autoneg = AUTONEG_ENABLE;
-               lc->requested_fc |= PAUSE_AUTONEG;
-       } else {
-               lc->acaps = 0;
-               lc->autoneg = AUTONEG_DISABLE;
+       lc->mdio_addr = mdio_addr;
+       lc->port_type = port_type;
+       lc->mod_type = mod_type;
+
+       lc->link_ok = 0;
+       lc->link_down_rc = 0;
+
+       /* Turn Tx and Rx pause off by default */
+       lc->admin_caps &= ~V_FW_PORT_CAP32_FC(M_FW_PORT_CAP32_FC);
+       lc->admin_caps &= ~V_FW_PORT_CAP32_802_3(M_FW_PORT_CAP32_802_3);
+       if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE)
+               lc->admin_caps &= ~FW_PORT_CAP32_FORCE_PAUSE;
+
+       /* Reset MDI to AUTO */
+       if (lc->pcaps & FW_PORT_CAP32_MDIAUTO) {
+               lc->admin_caps &= ~V_FW_PORT_CAP32_MDI(M_FW_PORT_CAP32_MDI);
+               lc->admin_caps |= V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
        }
 }
 
@@ -5271,12 +5291,11 @@ int t4_init_rss_mode(struct adapter *adap, int mbox)
 
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
-       fw_port_cap32_t pcaps, acaps;
+       u32 param, val, pcaps, acaps;
        enum fw_port_type port_type;
        struct fw_port_cmd cmd;
        u8 vivld = 0, vin = 0;
        int ret, i, j = 0;
-       u32 param, val;
        int mdio_addr;
        u8 addr[6];
 
@@ -5342,11 +5361,8 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
                        pi->vin =  G_FW_VIID_VIN(pi->viid);
                }
 
-               pi->port_type = port_type;
-               pi->mdio_addr = mdio_addr;
-               pi->mod_type = FW_PORT_MOD_TYPE_NA;
-
-               init_link_config(&pi->link_cfg, pcaps, acaps);
+               t4_init_link_config(pi, pcaps, acaps, mdio_addr, port_type,
+                                   FW_PORT_MOD_TYPE_NA);
                j++;
        }
        return 0;
index 1531412..cfd03cf 100644 (file)
@@ -1615,6 +1615,7 @@ struct fw_vi_stats_cmd {
 #define FW_PORT_CAP32_MDIAUTO           0x00400000UL
 #define FW_PORT_CAP32_FEC_RS            0x00800000UL
 #define FW_PORT_CAP32_FEC_BASER_RS      0x01000000UL
+#define FW_PORT_CAP32_FORCE_PAUSE       0x10000000UL
 
 #define S_FW_PORT_CAP32_SPEED           0
 #define M_FW_PORT_CAP32_SPEED           0xfff
@@ -1622,8 +1623,16 @@ struct fw_vi_stats_cmd {
 #define G_FW_PORT_CAP32_SPEED(x) \
        (((x) >> S_FW_PORT_CAP32_SPEED) & M_FW_PORT_CAP32_SPEED)
 
+#define S_FW_PORT_CAP32_FC             16
+#define M_FW_PORT_CAP32_FC             0x3
+#define V_FW_PORT_CAP32_FC(x)          ((x) << S_FW_PORT_CAP32_FC)
+
+#define S_FW_PORT_CAP32_802_3          18
+#define M_FW_PORT_CAP32_802_3          0x3
+#define V_FW_PORT_CAP32_802_3(x)       ((x) << S_FW_PORT_CAP32_802_3)
+
 enum fw_port_mdi32 {
-       FW_PORT_CAP32_MDI_AUTO,
+       FW_PORT_CAP32_MDI_AUTO = 1,
 };
 
 #define S_FW_PORT_CAP32_MDI 21
index 6454029..cd011bc 100644 (file)
@@ -768,9 +768,8 @@ int t4vf_port_init(struct adapter *adapter)
 {
        struct fw_port_cmd port_cmd, port_rpl, rpl;
        struct fw_vi_cmd vi_cmd, vi_rpl;
-       fw_port_cap32_t pcaps, acaps;
+       u32 param, val, pcaps, acaps;
        enum fw_port_type port_type;
-       u32 param, val;
        int mdio_addr;
        int ret, i;
 
@@ -844,10 +843,8 @@ int t4vf_port_init(struct adapter *adapter)
                pcaps = be32_to_cpu(port_rpl.u.info32.pcaps32);
                acaps = be32_to_cpu(port_rpl.u.info32.acaps32);
 
-               p->port_type = port_type;
-               p->mdio_addr = mdio_addr;
-               p->mod_type = FW_PORT_MOD_TYPE_NA;
-               init_link_config(&p->link_cfg, pcaps, acaps);
+               t4_init_link_config(p, pcaps, acaps, mdio_addr, port_type,
+                                   FW_PORT_MOD_TYPE_NA);
        }
        return 0;
 }
index 98d0362..c58e639 100644 (file)
@@ -193,11 +193,12 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev,
                          int wait_to_complete)
 {
        struct port_info *pi = eth_dev->data->dev_private;
+       unsigned int i, work_done, budget = 32;
+       struct link_config *lc = &pi->link_cfg;
        struct adapter *adapter = pi->adapter;
-       struct sge *s = &adapter->sge;
        struct rte_eth_link new_link = { 0 };
-       unsigned int i, work_done, budget = 32;
        u8 old_link = pi->link_cfg.link_ok;
+       struct sge *s = &adapter->sge;
 
        for (i = 0; i < CXGBE_LINK_STATUS_POLL_CNT; i++) {
                if (!s->fw_evtq.desc)
@@ -218,9 +219,9 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev,
 
        new_link.link_status = cxgbe_force_linkup(adapter) ?
                               ETH_LINK_UP : pi->link_cfg.link_ok;
-       new_link.link_autoneg = pi->link_cfg.autoneg;
+       new_link.link_autoneg = (lc->link_caps & FW_PORT_CAP32_ANEG) ? 1 : 0;
        new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
-       new_link.link_speed = pi->link_cfg.speed;
+       new_link.link_speed = t4_fwcap_to_speed(lc->link_caps);
 
        return rte_eth_linkstatus_set(eth_dev, &new_link);
 }
@@ -787,11 +788,17 @@ static int cxgbe_flow_ctrl_get(struct rte_eth_dev *eth_dev,
 {
        struct port_info *pi = eth_dev->data->dev_private;
        struct link_config *lc = &pi->link_cfg;
-       int rx_pause, tx_pause;
+       u8 rx_pause = 0, tx_pause = 0;
+       u32 caps = lc->link_caps;
 
-       fc_conf->autoneg = lc->fc & PAUSE_AUTONEG;
-       rx_pause = lc->fc & PAUSE_RX;
-       tx_pause = lc->fc & PAUSE_TX;
+       if (caps & FW_PORT_CAP32_ANEG)
+               fc_conf->autoneg = 1;
+
+       if (caps & FW_PORT_CAP32_FC_TX)
+               tx_pause = 1;
+
+       if (caps & FW_PORT_CAP32_FC_RX)
+               rx_pause = 1;
 
        if (rx_pause && tx_pause)
                fc_conf->mode = RTE_FC_FULL;
@@ -808,30 +815,39 @@ static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev,
                               struct rte_eth_fc_conf *fc_conf)
 {
        struct port_info *pi = eth_dev->data->dev_private;
-       struct adapter *adapter = pi->adapter;
        struct link_config *lc = &pi->link_cfg;
+       u32 new_caps = lc->admin_caps;
+       u8 tx_pause = 0, rx_pause = 0;
+       int ret;
 
-       if (lc->pcaps & FW_PORT_CAP32_ANEG) {
-               if (fc_conf->autoneg)
-                       lc->requested_fc |= PAUSE_AUTONEG;
-               else
-                       lc->requested_fc &= ~PAUSE_AUTONEG;
+       if (fc_conf->mode == RTE_FC_FULL) {
+               tx_pause = 1;
+               rx_pause = 1;
+       } else if (fc_conf->mode == RTE_FC_TX_PAUSE) {
+               tx_pause = 1;
+       } else if (fc_conf->mode == RTE_FC_RX_PAUSE) {
+               rx_pause = 1;
        }
 
-       if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
-           (fc_conf->mode & RTE_FC_RX_PAUSE))
-               lc->requested_fc |= PAUSE_RX;
-       else
-               lc->requested_fc &= ~PAUSE_RX;
+       ret = t4_set_link_pause(pi, fc_conf->autoneg, tx_pause,
+                               rx_pause, &new_caps);
+       if (ret != 0)
+               return ret;
 
-       if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
-           (fc_conf->mode & RTE_FC_TX_PAUSE))
-               lc->requested_fc |= PAUSE_TX;
-       else
-               lc->requested_fc &= ~PAUSE_TX;
+       if (!fc_conf->autoneg) {
+               if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE)
+                       new_caps |= FW_PORT_CAP32_FORCE_PAUSE;
+       } else {
+               new_caps &= ~FW_PORT_CAP32_FORCE_PAUSE;
+       }
+
+       if (new_caps != lc->admin_caps) {
+               ret = t4_link_l1cfg(pi, new_caps);
+               if (ret == 0)
+                       lc->admin_caps = new_caps;
+       }
 
-       return t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan,
-                            &pi->link_cfg);
+       return ret;
 }
 
 const uint32_t *
index 53b08a6..3b56ecc 100644 (file)
@@ -732,7 +732,7 @@ void cxgbe_print_port_info(struct adapter *adap)
                        --bufp;
                sprintf(bufp, "BASE-%s",
                        t4_get_port_type_description(
-                                       (enum fw_port_type)pi->port_type));
+                               (enum fw_port_type)pi->link_cfg.port_type));
 
                dev_info(adap,
                         " " PCI_PRI_FMT " Chelsio rev %d %s %s\n",
@@ -1575,23 +1575,23 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id)
 
        const struct port_info *pi = adap2pinfo(adap, port_id);
 
-       if (pi->mod_type == FW_PORT_MOD_TYPE_NONE)
+       if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_NONE)
                dev_info(adap, "Port%d: port module unplugged\n", pi->port_id);
-       else if (pi->mod_type < ARRAY_SIZE(mod_str))
+       else if (pi->link_cfg.mod_type < ARRAY_SIZE(mod_str))
                dev_info(adap, "Port%d: %s port module inserted\n", pi->port_id,
-                        mod_str[pi->mod_type]);
-       else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
+                        mod_str[pi->link_cfg.mod_type]);
+       else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
                dev_info(adap, "Port%d: unsupported port module inserted\n",
                         pi->port_id);
-       else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
+       else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
                dev_info(adap, "Port%d: unknown port module inserted\n",
                         pi->port_id);
-       else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR)
+       else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_ERROR)
                dev_info(adap, "Port%d: transceiver module error\n",
                         pi->port_id);
        else
                dev_info(adap, "Port%d: unknown module type %d inserted\n",
-                        pi->port_id, pi->mod_type);
+                        pi->port_id, pi->link_cfg.mod_type);
 }
 
 bool cxgbe_force_linkup(struct adapter *adap)
@@ -1636,8 +1636,7 @@ int cxgbe_link_start(struct port_info *pi)
                }
        }
        if (ret == 0 && is_pf4(adapter))
-               ret = t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan,
-                                   &pi->link_cfg);
+               ret = t4_link_l1cfg(pi, pi->link_cfg.admin_caps);
        if (ret == 0) {
                /*
                 * Enabling a Virtual Interface can result in an interrupt
@@ -1905,7 +1904,7 @@ void cxgbe_get_speed_caps(struct port_info *pi, u32 *speed_caps)
 {
        *speed_caps = 0;
 
-       fw_caps_to_speed_caps(pi->port_type, pi->link_cfg.pcaps,
+       fw_caps_to_speed_caps(pi->link_cfg.port_type, pi->link_cfg.pcaps,
                              speed_caps);
 
        if (!(pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG))