net/mlx5/linux: fix firmware version
[dpdk.git] / drivers / net / cxgbe / base / t4_hw.c
index 31762c9..7ebf4a9 100644 (file)
@@ -16,7 +16,7 @@
 #include <rte_eal.h>
 #include <rte_alarm.h>
 #include <rte_ether.h>
-#include <rte_ethdev_driver.h>
+#include <ethdev_driver.h>
 #include <rte_malloc.h>
 #include <rte_random.h>
 #include <rte_dev.h>
@@ -246,7 +246,7 @@ static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
                         u32 mbox_addr)
 {
        for ( ; nflit; nflit--, mbox_addr += 8)
-               *rpl++ = htobe64(t4_read_reg64(adap, mbox_addr));
+               *rpl++ = cpu_to_be64(t4_read_reg64(adap, mbox_addr));
 }
 
 /*
@@ -335,7 +335,7 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox,
                return -EINVAL;
        }
 
-       bzero(p, size);
+       memset(p, 0, size);
        memcpy(p, (const __be64 *)cmd, size);
 
        /*
@@ -2517,6 +2517,10 @@ int t4_get_pfres(struct adapter *adapter)
 
        word = be32_to_cpu(rpl.type_to_neq);
        pfres->neq = G_FW_PFVF_CMD_NEQ(word);
+
+       word = be32_to_cpu(rpl.r_caps_to_nethctrl);
+       pfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word);
+
        return 0;
 }
 
@@ -2805,142 +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)
-/**
- *     fwcaps16_to_caps32 - convert 16-bit Port Capabilities to 32-bits
- *     @caps16: a 16-bit Port Capabilities value
- *
- *     Returns the equivalent 32-bit Port Capabilities value.
- */
-fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16)
-{
-       fw_port_cap32_t caps32 = 0;
-
-#define CAP16_TO_CAP32(__cap) \
-       do { \
-               if (caps16 & FW_PORT_CAP_##__cap) \
-                       caps32 |= FW_PORT_CAP32_##__cap; \
-       } while (0)
-
-       CAP16_TO_CAP32(SPEED_100M);
-       CAP16_TO_CAP32(SPEED_1G);
-       CAP16_TO_CAP32(SPEED_25G);
-       CAP16_TO_CAP32(SPEED_10G);
-       CAP16_TO_CAP32(SPEED_40G);
-       CAP16_TO_CAP32(SPEED_100G);
-       CAP16_TO_CAP32(FC_RX);
-       CAP16_TO_CAP32(FC_TX);
-       CAP16_TO_CAP32(ANEG);
-       CAP16_TO_CAP32(MDIX);
-       CAP16_TO_CAP32(MDIAUTO);
-       CAP16_TO_CAP32(FEC_RS);
-       CAP16_TO_CAP32(FEC_BASER_RS);
-       CAP16_TO_CAP32(802_3_PAUSE);
-       CAP16_TO_CAP32(802_3_ASM_DIR);
-
-#undef CAP16_TO_CAP32
-
-       return caps32;
-}
-
-/**
- *     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 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
@@ -2949,63 +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);
-       unsigned int fw_caps = adap->params.fw_caps_support;
-       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_caps == FW_CAPS16 ?
-                                                FW_PORT_ACTION_L1_CFG :
-                                                FW_PORT_ACTION_L1_CFG32) |
+               cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG32) |
                            FW_LEN16(cmd));
 
-       if (fw_caps == FW_CAPS16)
-               cmd.u.l1cfg.rcap = cpu_to_be32(fwcaps32_to_caps16(rcap));
+       cmd.u.l1cfg32.rcap32 = cpu_to_be32(caps);
+
+       if (sleep_ok)
+               ret = t4_wr_mbox(adap, adap->mbox, &cmd, sizeof(cmd), NULL);
        else
-               cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap);
+               ret = t4_wr_mbox_ns(adap, adap->mbox, &cmd, sizeof(cmd), NULL);
 
-       return t4_wr_mbox(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;
 }
 
 /**
@@ -4017,7 +3863,8 @@ int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
 int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
                     unsigned int port, unsigned int pf, unsigned int vf,
                     unsigned int nmac, u8 *mac, unsigned int *rss_size,
-                    unsigned int portfunc, unsigned int idstype)
+                    unsigned int portfunc, unsigned int idstype,
+                    u8 *vivld, u8 *vin)
 {
        int ret;
        struct fw_vi_cmd c;
@@ -4055,6 +3902,10 @@ int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
        }
        if (rss_size)
                *rss_size = G_FW_VI_CMD_RSSSIZE(be16_to_cpu(c.norss_rsssize));
+       if (vivld)
+               *vivld = G_FW_VI_CMD_VFVLD(be32_to_cpu(c.alloc_to_len16));
+       if (vin)
+               *vin = G_FW_VI_CMD_VIN(be32_to_cpu(c.alloc_to_len16));
        return G_FW_VI_CMD_VIID(cpu_to_be16(c.type_to_viid));
 }
 
@@ -4075,10 +3926,10 @@ int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
  */
 int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
                unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
-               unsigned int *rss_size)
+               unsigned int *rss_size, u8 *vivld, u8 *vin)
 {
        return t4_alloc_vi_func(adap, mbox, port, pf, vf, nmac, mac, rss_size,
-                               FW_VI_FUNC_ETH, 0);
+                               FW_VI_FUNC_ETH, 0, vivld, vin);
 }
 
 /**
@@ -4161,6 +4012,112 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
                return t4vf_wr_mbox(adap, &c, sizeof(c), NULL);
 }
 
+/**
+ *     t4_alloc_raw_mac_filt - Adds a raw mac entry in mps tcam
+ *     @adap: the adapter
+ *     @viid: the VI id
+ *     @mac: the MAC address
+ *     @mask: the mask
+ *     @idx: index at which to add this entry
+ *     @port_id: the port index
+ *     @lookup_type: MAC address for inner (1) or outer (0) header
+ *     @sleep_ok: call is allowed to sleep
+ *
+ *     Adds the mac entry at the specified index using raw mac interface.
+ *
+ *     Returns a negative error number or the allocated index for this mac.
+ */
+int t4_alloc_raw_mac_filt(struct adapter *adap, unsigned int viid,
+                         const u8 *addr, const u8 *mask, unsigned int idx,
+                         u8 lookup_type, u8 port_id, bool sleep_ok)
+{
+       int ret = 0;
+       struct fw_vi_mac_cmd c;
+       struct fw_vi_mac_raw *p = &c.u.raw;
+       u32 val;
+
+       memset(&c, 0, sizeof(c));
+       c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
+                                  F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+                                  V_FW_VI_MAC_CMD_VIID(viid));
+       val = V_FW_CMD_LEN16(1) |
+             V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_RAW);
+       c.freemacs_to_len16 = cpu_to_be32(val);
+
+       /* Specify that this is an inner mac address */
+       p->raw_idx_pkd = cpu_to_be32(V_FW_VI_MAC_CMD_RAW_IDX(idx));
+
+       /* Lookup Type. Outer header: 0, Inner header: 1 */
+       p->data0_pkd = cpu_to_be32(V_DATALKPTYPE(lookup_type) |
+                                  V_DATAPORTNUM(port_id));
+       /* Lookup mask and port mask */
+       p->data0m_pkd = cpu_to_be64(V_DATALKPTYPE(M_DATALKPTYPE) |
+                                   V_DATAPORTNUM(M_DATAPORTNUM));
+
+       /* Copy the address and the mask */
+       memcpy((u8 *)&p->data1[0] + 2, addr, ETHER_ADDR_LEN);
+       memcpy((u8 *)&p->data1m[0] + 2, mask, ETHER_ADDR_LEN);
+
+       ret = t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, sleep_ok);
+       if (ret == 0) {
+               ret = G_FW_VI_MAC_CMD_RAW_IDX(be32_to_cpu(p->raw_idx_pkd));
+               if (ret != (int)idx)
+                       ret = -ENOMEM;
+       }
+
+       return ret;
+}
+
+/**
+ *     t4_free_raw_mac_filt - Frees a raw mac entry in mps tcam
+ *     @adap: the adapter
+ *     @viid: the VI id
+ *     @addr: the MAC address
+ *     @mask: the mask
+ *     @idx: index of the entry in mps tcam
+ *     @lookup_type: MAC address for inner (1) or outer (0) header
+ *     @port_id: the port index
+ *     @sleep_ok: call is allowed to sleep
+ *
+ *     Removes the mac entry at the specified index using raw mac interface.
+ *
+ *     Returns a negative error number on failure.
+ */
+int t4_free_raw_mac_filt(struct adapter *adap, unsigned int viid,
+                        const u8 *addr, const u8 *mask, unsigned int idx,
+                        u8 lookup_type, u8 port_id, bool sleep_ok)
+{
+       struct fw_vi_mac_cmd c;
+       struct fw_vi_mac_raw *p = &c.u.raw;
+       u32 raw;
+
+       memset(&c, 0, sizeof(c));
+       c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
+                                  F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+                                  V_FW_CMD_EXEC(0) |
+                                  V_FW_VI_MAC_CMD_VIID(viid));
+       raw = V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_RAW);
+       c.freemacs_to_len16 = cpu_to_be32(V_FW_VI_MAC_CMD_FREEMACS(0U) |
+                                         raw |
+                                         V_FW_CMD_LEN16(1));
+
+       p->raw_idx_pkd = cpu_to_be32(V_FW_VI_MAC_CMD_RAW_IDX(idx) |
+                                    FW_VI_MAC_ID_BASED_FREE);
+
+       /* Lookup Type. Outer header: 0, Inner header: 1 */
+       p->data0_pkd = cpu_to_be32(V_DATALKPTYPE(lookup_type) |
+                                  V_DATAPORTNUM(port_id));
+       /* Lookup mask and port mask */
+       p->data0m_pkd = cpu_to_be64(V_DATALKPTYPE(M_DATALKPTYPE) |
+                                   V_DATAPORTNUM(M_DATAPORTNUM));
+
+       /* Copy the address and the mask */
+       memcpy((u8 *)&p->data1[0] + 2, addr, ETHER_ADDR_LEN);
+       memcpy((u8 *)&p->data1m[0] + 2, mask, ETHER_ADDR_LEN);
+
+       return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, sleep_ok);
+}
+
 /**
  * t4_change_mac - modifies the exact-match filter for a MAC address
  * @adap: the adapter
@@ -4392,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 { \
@@ -4414,6 +4395,154 @@ 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;
+}
+
+int t4_set_link_fec(struct port_info *pi, u8 fec_rs, u8 fec_baser,
+                   u8 fec_none, u32 *new_caps)
+{
+       struct link_config *lc = &pi->link_cfg;
+       u32 max_speed, caps = *new_caps;
+
+       if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
+               return -EOPNOTSUPP;
+
+       /* Link might be down. In that case consider the max
+        * speed advertised
+        */
+       max_speed = t4_fwcap_to_speed(lc->link_caps);
+       if (!max_speed)
+               max_speed = t4_fwcap_to_speed(lc->acaps);
+
+       caps &= ~V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC);
+       if (fec_rs) {
+               switch (max_speed) {
+               case 100000:
+               case 25000:
+                       caps |= FW_PORT_CAP32_FEC_RS;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       }
+
+       if (fec_baser) {
+               switch (max_speed) {
+               case 50000:
+               case 25000:
+                       caps |= FW_PORT_CAP32_FEC_BASER_RS;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       }
+
+       if (fec_none)
+               caps |= FW_PORT_CAP32_FEC_NO_FEC;
+
+       if (!(caps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC))) {
+               /* No explicit encoding is requested.
+                * So, default back to AUTO.
+                */
+               switch (max_speed) {
+               case 100000:
+                       caps |= FW_PORT_CAP32_FEC_RS |
+                               FW_PORT_CAP32_FEC_NO_FEC;
+                       break;
+               case 50000:
+                       caps |= FW_PORT_CAP32_FEC_BASER_RS |
+                               FW_PORT_CAP32_FEC_NO_FEC;
+                       break;
+               case 25000:
+                       caps |= FW_PORT_CAP32_FEC_RS |
+                               FW_PORT_CAP32_FEC_BASER_RS |
+                               FW_PORT_CAP32_FEC_NO_FEC;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       }
+
+       *new_caps = caps;
+
+       return 0;
+}
+
 /**
  * t4_handle_get_port_info - process a FW reply message
  * @pi: the port info
@@ -4424,109 +4553,60 @@ static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
 static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 {
        const struct fw_port_cmd *cmd = (const void *)rpl;
-       int action = G_FW_PORT_CMD_ACTION(be32_to_cpu(cmd->action_to_len16));
-       fw_port_cap32_t pcaps, acaps, linkattr;
+       u8 link_ok, link_down_rc, mod_type, port_type;
+       u32 action, pcaps, acaps, link_caps, lstatus;
        struct link_config *lc = &pi->link_cfg;
        struct adapter *adapter = pi->adapter;
-       enum fw_port_module_type mod_type;
-       enum fw_port_type port_type;
-       unsigned int speed, fc, fec;
-       int link_ok, linkdnrc;
+       u8 mod_changed = 0;
 
        /* Extract the various fields from the Port Information message.
         */
-       switch (action) {
-       case FW_PORT_ACTION_GET_PORT_INFO: {
-               u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
-
-               link_ok = (lstatus & F_FW_PORT_CMD_LSTATUS) != 0;
-               linkdnrc = G_FW_PORT_CMD_LINKDNRC(lstatus);
-               port_type = G_FW_PORT_CMD_PTYPE(lstatus);
-               mod_type = G_FW_PORT_CMD_MODTYPE(lstatus);
-               pcaps = fwcaps16_to_caps32(be16_to_cpu(cmd->u.info.pcap));
-               acaps = fwcaps16_to_caps32(be16_to_cpu(cmd->u.info.acap));
-
-               /* Unfortunately the format of the Link Status in the old
-                * 16-bit Port Information message isn't the same as the
-                * 16-bit Port Capabilities bitfield used everywhere else ...
-                */
-               linkattr = 0;
-               if (lstatus & F_FW_PORT_CMD_RXPAUSE)
-                       linkattr |= FW_PORT_CAP32_FC_RX;
-               if (lstatus & F_FW_PORT_CMD_TXPAUSE)
-                       linkattr |= FW_PORT_CAP32_FC_TX;
-               if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
-                       linkattr |= FW_PORT_CAP32_SPEED_100M;
-               if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
-                       linkattr |= FW_PORT_CAP32_SPEED_1G;
-               if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
-                       linkattr |= FW_PORT_CAP32_SPEED_10G;
-               if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_25G))
-                       linkattr |= FW_PORT_CAP32_SPEED_25G;
-               if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
-                       linkattr |= FW_PORT_CAP32_SPEED_40G;
-               if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100G))
-                       linkattr |= FW_PORT_CAP32_SPEED_100G;
-
-               break;
-               }
-
-       case FW_PORT_ACTION_GET_PORT_INFO32: {
-               u32 lstatus32 =
-                       be32_to_cpu(cmd->u.info32.lstatus32_to_cbllen32);
-
-               link_ok = (lstatus32 & F_FW_PORT_CMD_LSTATUS32) != 0;
-               linkdnrc = G_FW_PORT_CMD_LINKDNRC32(lstatus32);
-               port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
-               mod_type = G_FW_PORT_CMD_MODTYPE32(lstatus32);
-               pcaps = be32_to_cpu(cmd->u.info32.pcaps32);
-               acaps = be32_to_cpu(cmd->u.info32.acaps32);
-               linkattr = be32_to_cpu(cmd->u.info32.linkattr32);
-               break;
-               }
-
-       default:
+       action = be32_to_cpu(cmd->action_to_len16);
+       if (G_FW_PORT_CMD_ACTION(action) != FW_PORT_ACTION_GET_PORT_INFO32) {
                dev_warn(adapter, "Handle Port Information: Bad Command/Action %#x\n",
-                        be32_to_cpu(cmd->action_to_len16));
+                        action);
                return;
        }
 
-       fec = fwcap_to_cc_fec(acaps);
+       lstatus = be32_to_cpu(cmd->u.info32.lstatus32_to_cbllen32);
+       link_ok = (lstatus & F_FW_PORT_CMD_LSTATUS32) ? 1 : 0;
+       link_down_rc = G_FW_PORT_CMD_LINKDNRC32(lstatus);
+       port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus);
+       mod_type = G_FW_PORT_CMD_MODTYPE32(lstatus);
 
-       fc = fwcap_to_cc_pause(linkattr);
-       speed = fwcap_to_speed(linkattr);
+       pcaps = be32_to_cpu(cmd->u.info32.pcaps32);
+       acaps = be32_to_cpu(cmd->u.info32.acaps32);
+       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 = linkdnrc;
+                       lc->link_down_rc = link_down_rc;
                        dev_warn(adap, "Port %d link down, reason: %s\n",
-                                pi->tx_chan, t4_link_down_rc_str(linkdnrc));
+                                pi->port_id,
+                                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;
+               t4_os_link_changed(adapter, pi->pidx);
+       }
+
+       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);
        }
 }
 
@@ -4576,9 +4656,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
        unsigned int action =
                G_FW_PORT_CMD_ACTION(be32_to_cpu(p->action_to_len16));
 
-       if (opcode == FW_PORT_CMD &&
-           (action == FW_PORT_ACTION_GET_PORT_INFO ||
-            action == FW_PORT_ACTION_GET_PORT_INFO32)) {
+       if (opcode == FW_PORT_CMD && action == FW_PORT_ACTION_GET_PORT_INFO32) {
                /* link/module state change message */
                int chan = G_FW_PORT_CMD_PORTID(be32_to_cpu(p->op_to_portid));
                struct port_info *pi = NULL;
@@ -4604,45 +4682,67 @@ 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)
 {
+       u8 fec_rs = 0, fec_baser = 0, fec_none = 0;
+       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 FEC caps to default values */
+       if (lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)) {
+               if (lc->acaps & FW_PORT_CAP32_FEC_RS)
+                       fec_rs = 1;
+               else if (lc->acaps & FW_PORT_CAP32_FEC_BASER_RS)
+                       fec_baser = 1;
+               else
+                       fec_none = 1;
+
+               lc->admin_caps &= ~V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC);
+               t4_set_link_fec(pi, fec_rs, fec_baser, fec_none,
+                               &lc->admin_caps);
+       }
+
+       if (lc->pcaps & FW_PORT_CAP32_FORCE_FEC)
+               lc->admin_caps &= ~FW_PORT_CAP32_FORCE_FEC;
+
+       /* 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);
        }
 }
 
@@ -4929,6 +5029,10 @@ int t4_prep_adapter(struct adapter *adapter)
                adapter->params.arch.mps_rplc_size = 128;
                adapter->params.arch.nchan = NCHAN;
                adapter->params.arch.vfcount = 128;
+               /* Congestion map is for 4 channels so that
+                * MPS can have 4 priority per port.
+                */
+               adapter->params.arch.cng_ch_bits_log = 2;
                break;
        case CHELSIO_T6:
                adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T6, pl_rev);
@@ -4938,6 +5042,10 @@ int t4_prep_adapter(struct adapter *adapter)
                adapter->params.arch.mps_rplc_size = 256;
                adapter->params.arch.nchan = 2;
                adapter->params.arch.vfcount = 256;
+               /* Congestion map is for 2 channels so that
+                * MPS can have 8 priority per port.
+                */
+               adapter->params.arch.cng_ch_bits_log = 3;
                break;
        default:
                dev_err(adapter, "%s: Device %d is not supported\n",
@@ -5104,8 +5212,8 @@ int t4_init_sge_params(struct adapter *adapter)
  */
 int t4_init_tp_params(struct adapter *adap)
 {
-       int chan;
-       u32 v;
+       int chan, ret;
+       u32 param, v;
 
        v = t4_read_reg(adap, A_TP_TIMER_RESOLUTION);
        adap->params.tp.tre = G_TIMERRESOLUTION(v);
@@ -5116,11 +5224,47 @@ int t4_init_tp_params(struct adapter *adap)
                adap->params.tp.tx_modq[chan] = chan;
 
        /*
-        * Cache the adapter's Compressed Filter Mode and global Incress
+        * Cache the adapter's Compressed Filter Mode/Mask and global Ingress
         * Configuration.
         */
-       t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
-                        &adap->params.tp.vlan_pri_map, 1, A_TP_VLAN_PRI_MAP);
+       param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+                V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FILTER) |
+                V_FW_PARAMS_PARAM_Y(FW_PARAM_DEV_FILTER_MODE_MASK));
+
+       /* Read current value */
+       ret = t4_query_params(adap, adap->mbox, adap->pf, 0,
+                             1, &param, &v);
+       if (!ret) {
+               dev_info(adap, "Current filter mode/mask 0x%x:0x%x\n",
+                        G_FW_PARAMS_PARAM_FILTER_MODE(v),
+                        G_FW_PARAMS_PARAM_FILTER_MASK(v));
+               adap->params.tp.vlan_pri_map =
+                       G_FW_PARAMS_PARAM_FILTER_MODE(v);
+               adap->params.tp.filter_mask =
+                       G_FW_PARAMS_PARAM_FILTER_MASK(v);
+       } else {
+               dev_info(adap,
+                        "Failed to read filter mode/mask via fw api, using indirect-reg-read\n");
+
+               /* In case of older-fw (which doesn't expose the api
+                * FW_PARAM_DEV_FILTER_MODE_MASK) and newer-driver (which uses
+                * the fw api) combination, fall-back to older method of reading
+                * the filter mode from indirect-register
+                */
+               t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+                                &adap->params.tp.vlan_pri_map, 1,
+                                A_TP_VLAN_PRI_MAP);
+
+               /* With the older-fw and newer-driver combination we might run
+                * into an issue when user wants to use hash filter region but
+                * the filter_mask is zero, in this case filter_mask validation
+                * is tough. To avoid that we set the filter_mask same as filter
+                * mode, which will behave exactly as the older way of ignoring
+                * the filter mask validation.
+                */
+               adap->params.tp.filter_mask = adap->params.tp.vlan_pri_map;
+       }
+
        t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
                         &adap->params.tp.ingress_config, 1,
                         A_TP_INGRESS_CONFIG);
@@ -5145,13 +5289,9 @@ int t4_init_tp_params(struct adapter *adap)
                                                               F_PROTOCOL);
        adap->params.tp.ethertype_shift = t4_filter_field_shift(adap,
                                                                F_ETHERTYPE);
-
-       /*
-        * If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
-        * represents the presense of an Outer VLAN instead of a VNIC ID.
-        */
-       if ((adap->params.tp.ingress_config & F_VNIC) == 0)
-               adap->params.tp.vnic_shift = -1;
+       adap->params.tp.macmatch_shift = t4_filter_field_shift(adap,
+                                                              F_MACMATCH);
+       adap->params.tp.tos_shift = t4_filter_field_shift(adap, F_TOS);
 
        v = t4_read_reg(adap, LE_3_DB_HASH_MASK_GEN_IPV4_T6_A);
        adap->params.tp.hash_filter_mask = v;
@@ -5240,82 +5380,56 @@ int t4_init_rss_mode(struct adapter *adap, int mbox)
 
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
-       unsigned int fw_caps = adap->params.fw_caps_support;
-       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;
        int mdio_addr;
-       u32 action;
        u8 addr[6];
 
+       param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) |
+                V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_PORT_CAPS32));
+       val = 1;
+       ret = t4_set_params(adap, mbox, pf, vf, 1, &param, &val);
+       if (ret < 0)
+               return ret;
+
        memset(&cmd, 0, sizeof(cmd));
 
        for_each_port(adap, i) {
                struct port_info *pi = adap2pinfo(adap, i);
                unsigned int rss_size = 0;
+               u32 lstatus32;
 
                while ((adap->params.portvec & (1 << j)) == 0)
                        j++;
 
-               /* If we haven't yet determined whether we're talking to
-                * Firmware which knows the new 32-bit Port Capabilities, it's
-                * time to find out now.  This will also tell new Firmware to
-                * send us Port Status Updates using the new 32-bit Port
-                * Capabilities version of the Port Information message.
-                */
-               if (fw_caps == FW_CAPS_UNKNOWN) {
-                       u32 param, val, caps;
-
-                       caps = FW_PARAMS_PARAM_PFVF_PORT_CAPS32;
-                       param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) |
-                                V_FW_PARAMS_PARAM_X(caps));
-                       val = 1;
-                       ret = t4_set_params(adap, mbox, pf, vf, 1, &param,
-                                           &val);
-                       fw_caps = ret == 0 ? FW_CAPS32 : FW_CAPS16;
-                       adap->params.fw_caps_support = fw_caps;
-               }
-
                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_READ |
                                               V_FW_PORT_CMD_PORTID(j));
-               action = fw_caps == FW_CAPS16 ? FW_PORT_ACTION_GET_PORT_INFO :
-                                               FW_PORT_ACTION_GET_PORT_INFO32;
-               cmd.action_to_len16 = cpu_to_be32(V_FW_PORT_CMD_ACTION(action) |
+               val = FW_PORT_ACTION_GET_PORT_INFO32;
+               cmd.action_to_len16 = cpu_to_be32(V_FW_PORT_CMD_ACTION(val) |
                                                  FW_LEN16(cmd));
                ret = t4_wr_mbox(pi->adapter, mbox, &cmd, sizeof(cmd), &cmd);
                if (ret)
                        return ret;
 
-               /* Extract the various fields from the Port Information message.
+               /* Extract the various fields from the Port Information
+                * message.
                 */
-               if (fw_caps == FW_CAPS16) {
-                       u32 lstatus =
-                               be32_to_cpu(cmd.u.info.lstatus_to_modtype);
-
-                       port_type = G_FW_PORT_CMD_PTYPE(lstatus);
-                       mdio_addr = (lstatus & F_FW_PORT_CMD_MDIOCAP) ?
-                                   (int)G_FW_PORT_CMD_MDIOADDR(lstatus) : -1;
-                       pcaps = be16_to_cpu(cmd.u.info.pcap);
-                       acaps = be16_to_cpu(cmd.u.info.acap);
-                       pcaps = fwcaps16_to_caps32(pcaps);
-                       acaps = fwcaps16_to_caps32(acaps);
-               } else {
-                       u32 lstatus32 =
-                               be32_to_cpu(cmd.u.info32.lstatus32_to_cbllen32);
-
-                       port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
-                       mdio_addr = (lstatus32 & F_FW_PORT_CMD_MDIOCAP32) ?
-                                   (int)G_FW_PORT_CMD_MDIOADDR32(lstatus32) :
-                                   -1;
-                       pcaps = be32_to_cpu(cmd.u.info32.pcaps32);
-                       acaps = be32_to_cpu(cmd.u.info32.acaps32);
-               }
+               lstatus32 = be32_to_cpu(cmd.u.info32.lstatus32_to_cbllen32);
+
+               port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
+               mdio_addr = (lstatus32 & F_FW_PORT_CMD_MDIOCAP32) ?
+                           (int)G_FW_PORT_CMD_MDIOADDR32(lstatus32) : -1;
+               pcaps = be32_to_cpu(cmd.u.info32.pcaps32);
+               acaps = be32_to_cpu(cmd.u.info32.acaps32);
 
-               ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size);
+               ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size,
+                                 &vivld, &vin);
                if (ret < 0)
                        return ret;
 
@@ -5324,11 +5438,20 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
                pi->rss_size = rss_size;
                t4_os_set_hw_addr(adap, i, addr);
 
-               pi->port_type = port_type;
-               pi->mdio_addr = mdio_addr;
-               pi->mod_type = FW_PORT_MOD_TYPE_NA;
+               /* If fw supports returning the VIN as part of FW_VI_CMD,
+                * save the returned values.
+                */
+               if (adap->params.viid_smt_extn_support) {
+                       pi->vivld = vivld;
+                       pi->vin = vin;
+               } else {
+                       /* Retrieve the values from VIID */
+                       pi->vivld = G_FW_VIID_VIVLD(pi->viid);
+                       pi->vin =  G_FW_VIID_VIN(pi->viid);
+               }
 
-               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;