net/cxgbe: update link config for 32-bit port capability
authorRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Wed, 28 Feb 2018 18:04:51 +0000 (23:34 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 30 Mar 2018 12:08:43 +0000 (14:08 +0200)
Update link configuration API to prepare for 32-bit port capability
support. Continue using 16-bit port capability for older firmware.

Original work by Surendra Mobiya <surendra@chelsio.com>

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
drivers/net/cxgbe/base/common.h
drivers/net/cxgbe/base/t4_hw.c
drivers/net/cxgbe/base/t4fw_interface.h
drivers/net/cxgbe/cxgbe_ethdev.c
drivers/net/cxgbe/cxgbe_main.c

index 0bd78c1..9888628 100644 (file)
@@ -62,13 +62,13 @@ enum dev_master { MASTER_CANT, MASTER_MAY, MASTER_MUST };
 
 enum dev_state { DEV_STATE_UNINIT, DEV_STATE_INIT, DEV_STATE_ERR };
 
-enum {
+enum cc_pause {
        PAUSE_RX      = 1 << 0,
        PAUSE_TX      = 1 << 1,
        PAUSE_AUTONEG = 1 << 2
 };
 
-enum {
+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 */
@@ -241,20 +241,30 @@ struct adapter_params {
        bool ulptx_memwrite_dsgl;          /* use of T5 DSGL allowed */
 };
 
+/* Firmware Port Capabilities types.
+ */
+typedef u16 fw_port_cap16_t;    /* 16-bit Port Capabilities integral value */
+typedef u32 fw_port_cap32_t;    /* 32-bit Port Capabilities integral value */
+
 struct link_config {
-       unsigned short supported;        /* link capabilities */
-       unsigned short advertising;      /* advertised capabilities */
-       unsigned int   requested_speed;  /* speed user has requested */
-       unsigned int   speed;            /* actual link speed */
-       unsigned char  requested_fc;     /* flow control user has requested */
-       unsigned char  fc;               /* actual link flow control */
-       unsigned char  auto_fec;         /* Forward Error Correction (FEC)
-                                         * "automatic" (IEEE 802.3)
-                                         */
-       unsigned char  requested_fec;    /* FEC requested */
-       unsigned char  fec;              /* FEC actual */
-       unsigned char  autoneg;          /* autonegotiating? */
-       unsigned char  link_ok;          /* link up? */
+       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 */
+
+       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 */
+
+       unsigned char autoneg;          /* autonegotiating? */
+
+       unsigned char link_ok;          /* link up? */
 };
 
 #include "adapter.h"
index e8545ce..46b296a 100644 (file)
@@ -2789,66 +2789,105 @@ void t4_dump_version_info(struct adapter *adapter)
                         G_FW_HDR_FW_VER_BUILD(adapter->params.er_vers));
 }
 
-#define ADVERT_MASK (V_FW_PORT_CAP_SPEED(M_FW_PORT_CAP_SPEED) | \
-                    FW_PORT_CAP_ANEG)
+#define ADVERT_MASK (V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED) | \
+                    FW_PORT_CAP32_ANEG)
+/**
+ *     fwcaps32_to_caps16 - convert 32-bit Port Capabilities to 16-bits
+ *     @caps32: a 32-bit Port Capabilities value
+ *
+ *     Returns the equivalent 16-bit Port Capabilities value.  Note that
+ *     not all 32-bit Port Capabilities can be represented in the 16-bit
+ *     Port Capabilities and some fields/values may not make it.
+ */
+static fw_port_cap16_t fwcaps32_to_caps16(fw_port_cap32_t caps32)
+{
+       fw_port_cap16_t caps16 = 0;
+
+#define CAP32_TO_CAP16(__cap) \
+       do { \
+               if (caps32 & FW_PORT_CAP32_##__cap) \
+                       caps16 |= FW_PORT_CAP_##__cap; \
+       } while (0)
+
+       CAP32_TO_CAP16(SPEED_100M);
+       CAP32_TO_CAP16(SPEED_1G);
+       CAP32_TO_CAP16(SPEED_10G);
+       CAP32_TO_CAP16(SPEED_25G);
+       CAP32_TO_CAP16(SPEED_40G);
+       CAP32_TO_CAP16(SPEED_100G);
+       CAP32_TO_CAP16(FC_RX);
+       CAP32_TO_CAP16(FC_TX);
+       CAP32_TO_CAP16(802_3_PAUSE);
+       CAP32_TO_CAP16(802_3_ASM_DIR);
+       CAP32_TO_CAP16(ANEG);
+       CAP32_TO_CAP16(MDIX);
+       CAP32_TO_CAP16(MDIAUTO);
+       CAP32_TO_CAP16(FEC_RS);
+       CAP32_TO_CAP16(FEC_BASER_RS);
+
+#undef CAP32_TO_CAP16
+
+       return caps16;
+}
 
 /* Translate Firmware Pause specification to Common Code */
-static inline unsigned int fwcap_to_cc_pause(unsigned int fw_pause)
+static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause)
 {
-       unsigned int cc_pause = 0;
+       enum cc_pause cc_pause = 0;
 
-       if (fw_pause & F_FW_PORT_CMD_RXPAUSE)
+       if (fw_pause & FW_PORT_CAP32_FC_RX)
                cc_pause |= PAUSE_RX;
-       if (fw_pause & F_FW_PORT_CMD_TXPAUSE)
+       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 unsigned int cc_to_fwcap_pause(unsigned int cc_pause)
+static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
 {
-       unsigned int fw_pause = 0;
+       fw_port_cap32_t fw_pause = 0;
 
        if (cc_pause & PAUSE_RX)
-               fw_pause |= F_FW_PORT_CMD_RXPAUSE;
+               fw_pause |= FW_PORT_CAP32_FC_RX;
        if (cc_pause & PAUSE_TX)
-               fw_pause |= F_FW_PORT_CMD_TXPAUSE;
+               fw_pause |= FW_PORT_CAP32_FC_TX;
 
        return fw_pause;
 }
 
 /* Translate Firmware Forward Error Correction specification to Common Code */
-static inline unsigned int fwcap_to_cc_fec(unsigned int fw_fec)
+static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec)
 {
-       unsigned int cc_fec = 0;
+       enum cc_fec cc_fec = 0;
 
-       if (fw_fec & FW_PORT_CAP_FEC_RS)
+       if (fw_fec & FW_PORT_CAP32_FEC_RS)
                cc_fec |= FEC_RS;
-       if (fw_fec & FW_PORT_CAP_FEC_BASER_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 unsigned int cc_to_fwcap_fec(unsigned int cc_fec)
+static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
 {
-       unsigned int fw_fec = 0;
+       fw_port_cap32_t fw_fec = 0;
 
        if (cc_fec & FEC_RS)
-               fw_fec |= FW_PORT_CAP_FEC_RS;
+               fw_fec |= FW_PORT_CAP32_FEC_RS;
        if (cc_fec & FEC_BASER_RS)
-               fw_fec |= FW_PORT_CAP_FEC_BASER_RS;
+               fw_fec |= FW_PORT_CAP32_FEC_BASER_RS;
 
        return fw_fec;
 }
 
 /**
  * t4_link_l1cfg - apply link configuration to MAC/PHY
- * @phy: the PHY to setup
- * @mac: the MAC to setup
- * @lc: the requested link configuration
+ * @adapter: the adapter
+ * @mbox: the Firmware Mailbox to use
+ * @port: the Port ID
+ * @lc: the Port's Link Configuration
  *
  * 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
@@ -2860,9 +2899,9 @@ static inline unsigned int cc_to_fwcap_fec(unsigned int cc_fec)
 int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
                  struct link_config *lc)
 {
-       struct fw_port_cmd c;
-       unsigned int fw_mdi = V_FW_PORT_CAP_MDI(FW_PORT_CAP_MDI_AUTO);
-       unsigned int fw_fc, cc_fec, fw_fec;
+       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 fw_port_cmd cmd;
 
        lc->link_ok = 0;
 
@@ -2881,30 +2920,32 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
                cc_fec = lc->requested_fec;
        fw_fec = cc_to_fwcap_fec(cc_fec);
 
-       memset(&c, 0, sizeof(c));
-       c.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));
-       c.action_to_len16 =
-               cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
-                           FW_LEN16(c));
-
-       if (!(lc->supported & FW_PORT_CAP_ANEG)) {
-               c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) |
-                                            fw_fc | fw_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) {
-               c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fw_fc |
-                                            fw_fec | fw_mdi);
+               rcap = lc->requested_speed | fw_fc | fw_fec | fw_mdi;
                lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
                lc->fec = cc_fec;
        } else {
-               c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fw_fc | fw_fec |
-                                            fw_mdi);
+               rcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
        }
 
-       return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+       /* 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));
+       cmd.action_to_len16 =
+               cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
+                           FW_LEN16(cmd));
+       cmd.u.l1cfg.rcap = cpu_to_be32(fwcaps32_to_caps16(rcap));
+
+       return t4_wr_mbox(adap, mbox, &cmd, sizeof(cmd), NULL);
 }
 
 /**
@@ -4237,6 +4278,28 @@ int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
 
+/* Return the highest speed set in the port capabilities, in Mb/s. */
+static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
+{
+#define TEST_SPEED_RETURN(__caps_speed, __speed) \
+       do { \
+               if (caps & FW_PORT_CAP32_SPEED_##__caps_speed) \
+                       return __speed; \
+       } while (0)
+
+       TEST_SPEED_RETURN(100G, 100000);
+       TEST_SPEED_RETURN(50G,   50000);
+       TEST_SPEED_RETURN(40G,   40000);
+       TEST_SPEED_RETURN(25G,   25000);
+       TEST_SPEED_RETURN(10G,   10000);
+       TEST_SPEED_RETURN(1G,     1000);
+       TEST_SPEED_RETURN(100M,    100);
+
+#undef TEST_SPEED_RETURN
+
+       return 0;
+}
+
 /**
  * t4_handle_fw_rpl - process a FW reply message
  * @adap: the adapter
@@ -4319,7 +4382,21 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
                        lc->speed = speed;
                        lc->fc = fc;
                        lc->fec = fec;
-                       lc->supported = be16_to_cpu(p->u.info.pcap);
+                       lc->pcaps = be16_to_cpu(p->u.info.pcap);
+                       lc->acaps = be16_to_cpu(p->u.info.acap) & ADVERT_MASK;
+                       if (lc->acaps & FW_PORT_CAP32_ANEG) {
+                               lc->autoneg = AUTONEG_ENABLE;
+                       } else {
+                               /* When Autoneg is disabled, user needs to set
+                                * single speed.
+                                */
+                               lc->acaps = 0;
+                               lc->requested_speed =
+                                       be16_to_cpu(p->u.info.acap);
+                               lc->requested_speed =
+                                       fwcap_to_speed(lc->requested_speed);
+                               lc->autoneg = AUTONEG_DISABLE;
+                       }
                }
        } else {
                dev_warn(adap, "Unknown firmware reply %d\n", opcode);
@@ -4352,7 +4429,7 @@ void t4_reset_link_config(struct adapter *adap, int idx)
 static void init_link_config(struct link_config *lc, unsigned int pcaps,
                             unsigned int acaps)
 {
-       lc->supported = pcaps;
+       lc->pcaps = pcaps;
        lc->requested_speed = 0;
        lc->speed = 0;
        lc->requested_fc = 0;
@@ -4366,11 +4443,12 @@ static void init_link_config(struct link_config *lc, unsigned int pcaps,
        lc->requested_fec = FEC_AUTO;
        lc->fec = lc->auto_fec;
 
-       if (lc->supported & FW_PORT_CAP_ANEG) {
-               lc->advertising = lc->supported & ADVERT_MASK;
+       if (lc->pcaps & FW_PORT_CAP32_ANEG) {
+               lc->acaps = lc->pcaps & ADVERT_MASK;
                lc->autoneg = AUTONEG_ENABLE;
+               lc->requested_fc |= PAUSE_AUTONEG;
        } else {
-               lc->advertising = 0;
+               lc->acaps = 0;
                lc->autoneg = AUTONEG_DISABLE;
        }
 }
index 883a1c7..0e13937 100644 (file)
@@ -1154,7 +1154,7 @@ struct fw_vi_stats_cmd {
        } u;
 };
 
-/* port capabilities bitmap */
+/* old 16-bit port capabilities bitmap */
 enum fw_port_cap {
        FW_PORT_CAP_SPEED_100M          = 0x0001,
        FW_PORT_CAP_SPEED_1G            = 0x0002,
@@ -1189,6 +1189,40 @@ enum fw_port_mdi {
 #define V_FW_PORT_CAP_MDI(x) ((x) << S_FW_PORT_CAP_MDI)
 #define G_FW_PORT_CAP_MDI(x) (((x) >> S_FW_PORT_CAP_MDI) & M_FW_PORT_CAP_MDI)
 
+/* new 32-bit port capabilities bitmap (fw_port_cap32_t) */
+#define FW_PORT_CAP32_SPEED_100M        0x00000001UL
+#define FW_PORT_CAP32_SPEED_1G          0x00000002UL
+#define FW_PORT_CAP32_SPEED_10G         0x00000004UL
+#define FW_PORT_CAP32_SPEED_25G         0x00000008UL
+#define FW_PORT_CAP32_SPEED_40G         0x00000010UL
+#define FW_PORT_CAP32_SPEED_50G         0x00000020UL
+#define FW_PORT_CAP32_SPEED_100G        0x00000040UL
+#define FW_PORT_CAP32_FC_RX             0x00010000UL
+#define FW_PORT_CAP32_FC_TX             0x00020000UL
+#define FW_PORT_CAP32_802_3_PAUSE       0x00040000UL
+#define FW_PORT_CAP32_802_3_ASM_DIR     0x00080000UL
+#define FW_PORT_CAP32_ANEG              0x00100000UL
+#define FW_PORT_CAP32_MDIX              0x00200000UL
+#define FW_PORT_CAP32_MDIAUTO           0x00400000UL
+#define FW_PORT_CAP32_FEC_RS            0x00800000UL
+#define FW_PORT_CAP32_FEC_BASER_RS      0x01000000UL
+
+#define S_FW_PORT_CAP32_SPEED           0
+#define M_FW_PORT_CAP32_SPEED           0xfff
+#define V_FW_PORT_CAP32_SPEED(x)        ((x) << S_FW_PORT_CAP32_SPEED)
+#define G_FW_PORT_CAP32_SPEED(x) \
+       (((x) >> S_FW_PORT_CAP32_SPEED) & M_FW_PORT_CAP32_SPEED)
+
+enum fw_port_mdi32 {
+       FW_PORT_CAP32_MDI_AUTO,
+};
+
+#define S_FW_PORT_CAP32_MDI 21
+#define M_FW_PORT_CAP32_MDI 3
+#define V_FW_PORT_CAP32_MDI(x) ((x) << S_FW_PORT_CAP32_MDI)
+#define G_FW_PORT_CAP32_MDI(x) \
+       (((x) >> S_FW_PORT_CAP32_MDI) & M_FW_PORT_CAP32_MDI)
+
 enum fw_port_action {
        FW_PORT_ACTION_L1_CFG           = 0x0001,
        FW_PORT_ACTION_GET_PORT_INFO    = 0x0003,
index a38ef56..643da66 100644 (file)
@@ -752,7 +752,7 @@ static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev,
        struct adapter *adapter = pi->adapter;
        struct link_config *lc = &pi->link_cfg;
 
-       if (lc->supported & FW_PORT_CAP_ANEG) {
+       if (lc->pcaps & FW_PORT_CAP32_ANEG) {
                if (fc_conf->autoneg)
                        lc->requested_fc |= PAUSE_AUTONEG;
                else
index 0c1dc8c..c126e42 100644 (file)
@@ -199,15 +199,16 @@ int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us,
 
 static inline bool is_x_1g_port(const struct link_config *lc)
 {
-       return (lc->supported & FW_PORT_CAP_SPEED_1G) != 0;
+       return (lc->pcaps & FW_PORT_CAP32_SPEED_1G) != 0;
 }
 
 static inline bool is_x_10g_port(const struct link_config *lc)
 {
        unsigned int speeds, high_speeds;
 
-       speeds = V_FW_PORT_CAP_SPEED(G_FW_PORT_CAP_SPEED(lc->supported));
-       high_speeds = speeds & ~(FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G);
+       speeds = V_FW_PORT_CAP32_SPEED(G_FW_PORT_CAP32_SPEED(lc->pcaps));
+       high_speeds = speeds &
+                     ~(FW_PORT_CAP32_SPEED_100M | FW_PORT_CAP32_SPEED_1G);
 
        return high_speeds != 0;
 }
@@ -387,17 +388,19 @@ static void print_port_info(struct adapter *adap)
                const struct port_info *pi = adap2pinfo(adap, i);
                char *bufp = buf;
 
-               if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M)
+               if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100M)
                        bufp += sprintf(bufp, "100M/");
-               if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G)
+               if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_1G)
                        bufp += sprintf(bufp, "1G/");
-               if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
+               if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_10G)
                        bufp += sprintf(bufp, "10G/");
-               if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_25G)
+               if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_25G)
                        bufp += sprintf(bufp, "25G/");
-               if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G)
+               if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_40G)
                        bufp += sprintf(bufp, "40G/");
-               if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100G)
+               if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_50G)
+                       bufp += sprintf(bufp, "50G/");
+               if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100G)
                        bufp += sprintf(bufp, "100G/");
                if (bufp != buf)
                        --bufp;
@@ -1100,7 +1103,7 @@ static void fw_caps_to_speed_caps(enum fw_port_type port_type,
 
 #define FW_CAPS_TO_SPEED(__fw_name) \
        do { \
-               if (fw_caps & FW_PORT_CAP_ ## __fw_name) \
+               if (fw_caps & FW_PORT_CAP32_ ## __fw_name) \
                        SET_SPEED(__fw_name); \
        } while (0)
 
@@ -1155,6 +1158,7 @@ static void fw_caps_to_speed_caps(enum fw_port_type port_type,
        case FW_PORT_TYPE_CR4_QSFP:
                FW_CAPS_TO_SPEED(SPEED_25G);
                FW_CAPS_TO_SPEED(SPEED_40G);
+               FW_CAPS_TO_SPEED(SPEED_50G);
                FW_CAPS_TO_SPEED(SPEED_100G);
                break;
 
@@ -1177,10 +1181,10 @@ 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.supported,
+       fw_caps_to_speed_caps(pi->port_type, pi->link_cfg.pcaps,
                              speed_caps);
 
-       if (!(pi->link_cfg.supported & FW_PORT_CAP_ANEG))
+       if (!(pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG))
                *speed_caps |= ETH_LINK_SPEED_FIXED;
 }