cgx_lmactype_string[LMAC_MODE_USXGMII] = "USXGMII";
 }
 
+static int cgx_link_usertable_index_map(int speed)
+{
+       switch (speed) {
+       case SPEED_10:
+               return CGX_LINK_10M;
+       case SPEED_100:
+               return CGX_LINK_100M;
+       case SPEED_1000:
+               return CGX_LINK_1G;
+       case SPEED_2500:
+               return CGX_LINK_2HG;
+       case SPEED_5000:
+               return CGX_LINK_5G;
+       case SPEED_10000:
+               return CGX_LINK_10G;
+       case SPEED_20000:
+               return CGX_LINK_20G;
+       case SPEED_25000:
+               return CGX_LINK_25G;
+       case SPEED_40000:
+               return CGX_LINK_40G;
+       case SPEED_50000:
+               return CGX_LINK_50G;
+       case 80000:
+               return CGX_LINK_80G;
+       case SPEED_100000:
+               return CGX_LINK_100G;
+       case SPEED_UNKNOWN:
+               return CGX_LINK_NONE;
+       }
+       return CGX_LINK_NONE;
+}
+
 static inline void link_status_user_format(u64 lstat,
                                           struct cgx_link_user_info *linfo,
                                           struct cgx *cgx, u8 lmac_id)
        linfo->link_up = FIELD_GET(RESP_LINKSTAT_UP, lstat);
        linfo->full_duplex = FIELD_GET(RESP_LINKSTAT_FDUPLEX, lstat);
        linfo->speed = cgx_speed_mbps[FIELD_GET(RESP_LINKSTAT_SPEED, lstat)];
+       linfo->an = FIELD_GET(RESP_LINKSTAT_AN, lstat);
        linfo->fec = FIELD_GET(RESP_LINKSTAT_FEC, lstat);
        linfo->lmac_type_id = cgx_get_lmac_type(cgx, lmac_id);
        lmac_string = cgx_lmactype_string[linfo->lmac_type_id];
        lmac->link_info = event.link_uinfo;
        linfo = &lmac->link_info;
 
+       if (err_type == CGX_ERR_SPEED_CHANGE_INVALID)
+               return;
+
        /* Ensure callback doesn't get unregistered until we finish it */
        spin_lock(&lmac->event_cb_lock);
 
 
        id = FIELD_GET(EVTREG_ID, event);
        if (id == CGX_CMD_LINK_BRING_UP ||
-           id == CGX_CMD_LINK_BRING_DOWN)
+           id == CGX_CMD_LINK_BRING_DOWN ||
+           id == CGX_CMD_MODE_CHANGE)
                return true;
        else
                return false;
        return err;
 }
 
+int cgx_set_link_mode(void *cgxd, struct cgx_set_link_mode_args args,
+                     int cgx_id, int lmac_id)
+{
+       struct cgx *cgx = cgxd;
+       u64 req = 0, resp;
+
+       if (!cgx)
+               return -ENODEV;
+
+       req = FIELD_SET(CMDREG_ID, CGX_CMD_MODE_CHANGE, req);
+       req = FIELD_SET(CMDMODECHANGE_SPEED,
+                       cgx_link_usertable_index_map(args.speed), req);
+       req = FIELD_SET(CMDMODECHANGE_DUPLEX, args.duplex, req);
+       req = FIELD_SET(CMDMODECHANGE_AN, args.an, req);
+       req = FIELD_SET(CMDMODECHANGE_PORT, args.ports, req);
+       req = FIELD_SET(CMDMODECHANGE_FLAGS, args.flags, req);
+       return cgx_fwi_cmd_generic(req, &resp, cgx, lmac_id);
+}
 int cgx_set_fec(u64 fec, int cgx_id, int lmac_id)
 {
        u64 req = 0, resp;
 
 int cgx_set_fec(u64 fec, int cgx_id, int lmac_id);
 int cgx_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp);
 int cgx_get_phy_fec_stats(void *cgxd, int lmac_id);
+int cgx_set_link_mode(void *cgxd, struct cgx_set_link_mode_args args,
+                     int cgx_id, int lmac_id);
 
 #endif /* CGX_H */
 
        CGX_ERR_TRAINING_FAIL,
        CGX_ERR_RX_EQU_FAIL,
        CGX_ERR_SPUX_BER_FAIL,
-       CGX_ERR_SPUX_RSFEC_ALGN_FAIL,   /* = 22 */
+       CGX_ERR_SPUX_RSFEC_ALGN_FAIL,
+       CGX_ERR_SPUX_MARKER_LOCK_FAIL,
+       CGX_ERR_SET_FEC_INVALID,
+       CGX_ERR_SET_FEC_FAIL,
+       CGX_ERR_MODULE_INVALID,
+       CGX_ERR_MODULE_NOT_PRESENT,
+       CGX_ERR_SPEED_CHANGE_INVALID,
 };
 
 /* LINK speed types */
        CGX_LINK_25G,
        CGX_LINK_40G,
        CGX_LINK_50G,
+       CGX_LINK_80G,
        CGX_LINK_100G,
        CGX_LINK_SPEED_MAX,
 };
        CGX_CMD_INTERNAL_LBK,
        CGX_CMD_EXTERNAL_LBK,
        CGX_CMD_HIGIG,
-       CGX_CMD_LINK_STATE_CHANGE,
+       CGX_CMD_LINK_STAT_CHANGE,
        CGX_CMD_MODE_CHANGE,            /* hot plug support */
        CGX_CMD_INTF_SHUTDOWN,
        CGX_CMD_GET_MKEX_PRFL_SIZE,
 #define CMDLINKCHANGE_SPEED    GENMASK_ULL(13, 10)
 
 #define CMDSETFEC                      GENMASK_ULL(9, 8)
+/* command argument to be passed for cmd ID - CGX_CMD_MODE_CHANGE */
+#define CMDMODECHANGE_SPEED            GENMASK_ULL(11, 8)
+#define CMDMODECHANGE_DUPLEX           GENMASK_ULL(12, 12)
+#define CMDMODECHANGE_AN               GENMASK_ULL(13, 13)
+#define CMDMODECHANGE_PORT             GENMASK_ULL(21, 14)
+#define CMDMODECHANGE_FLAGS            GENMASK_ULL(29, 22)
+
 #endif /* __CGX_FW_INTF_H__ */
 
 M(CGX_FEC_STATS,       0x211, cgx_fec_stats, msg_req, cgx_fec_stats_rsp) \
 M(CGX_GET_PHY_FEC_STATS, 0x212, cgx_get_phy_fec_stats, msg_req, msg_rsp) \
 M(CGX_FW_DATA_GET,     0x213, cgx_get_aux_link_info, msg_req, cgx_fw_data) \
+M(CGX_SET_LINK_MODE,   0x214, cgx_set_link_mode, cgx_set_link_mode_req,\
+                              cgx_set_link_mode_rsp)   \
  /* NPA mbox IDs (range 0x400 - 0x5FF) */                              \
 /* NPA mbox IDs (range 0x400 - 0x5FF) */                               \
 M(NPA_LF_ALLOC,                0x400, npa_lf_alloc,                            \
        uint64_t full_duplex:1;
        uint64_t lmac_type_id:4;
        uint64_t speed:20; /* speed in Mbps */
+       uint64_t an:1;          /* AN supported or not */
        uint64_t fec:2;  /* FEC type if enabled else 0 */
 #define LMACTYPE_STR_LEN 16
        char lmac_type[LMACTYPE_STR_LEN];
        struct cgx_lmac_fwdata_s fwdata;
 };
 
+struct cgx_set_link_mode_args {
+       u32 speed;
+       u8 duplex;
+       u8 an;
+       u8 ports;
+       u8 flags;
+};
+
+struct cgx_set_link_mode_req {
+       struct mbox_msghdr hdr;
+       struct cgx_set_link_mode_args args;
+};
+
+struct cgx_set_link_mode_rsp {
+       struct mbox_msghdr hdr;
+       int status;
+};
+
 /* NPA mbox message formats */
 
 /* NPA mailbox error codes
 
               sizeof(struct cgx_lmac_fwdata_s));
        return 0;
 }
+
+int rvu_mbox_handler_cgx_set_link_mode(struct rvu *rvu,
+                                      struct cgx_set_link_mode_req *req,
+                                      struct cgx_set_link_mode_rsp *rsp)
+{
+       int pf = rvu_get_pf(req->hdr.pcifunc);
+       u8 cgx_idx, lmac;
+       void *cgxd;
+
+       if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
+               return -EPERM;
+
+       rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac);
+       cgxd = rvu_cgx_pdata(cgx_idx, rvu);
+       rsp->status = cgx_set_link_mode(cgxd, req->args, cgx_idx, lmac);
+       return 0;
+}