#define HBA_FCP_IOQ_FLUSH      0x8000 /* FCP I/O queues being flushed */
 #define HBA_FW_DUMP_OP         0x10000 /* Skips fn reset before FW dump */
 #define HBA_RECOVERABLE_UE     0x20000 /* Firmware supports recoverable UE */
+#define HBA_FORCED_LINK_SPEED  0x40000 /*
+                                        * Firmware supports Forced Link Speed
+                                        * capability
+                                        */
        uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
        struct lpfc_dmabuf slim2p;
 
 
        int nolip = 0;
        const char *val_buf = buf;
        int err;
-       uint32_t prev_val;
+       uint32_t prev_val, if_type;
+
+       if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+       if (if_type == LPFC_SLI_INTF_IF_TYPE_2 &&
+           phba->hba_flag & HBA_FORCED_LINK_SPEED)
+               return -EPERM;
 
        if (!strncmp(buf, "nolip ", strlen("nolip "))) {
                nolip = 1;
 
        return rc;
 }
 
+static int
+lpfc_forced_link_speed(struct fc_bsg_job *job)
+{
+       struct Scsi_Host *shost = job->shost;
+       struct lpfc_vport *vport = shost_priv(shost);
+       struct lpfc_hba *phba = vport->phba;
+       struct forced_link_speed_support_reply *forced_reply;
+       int rc = 0;
+
+       if (job->request_len <
+           sizeof(struct fc_bsg_request) +
+           sizeof(struct get_forced_link_speed_support)) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+                               "0048 Received FORCED_LINK_SPEED request "
+                               "below minimum size\n");
+               rc = -EINVAL;
+               goto job_error;
+       }
+
+       forced_reply = (struct forced_link_speed_support_reply *)
+               job->reply->reply_data.vendor_reply.vendor_rsp;
+
+       if (job->reply_len <
+           sizeof(struct fc_bsg_request) +
+           sizeof(struct forced_link_speed_support_reply)) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+                               "0049 Received FORCED_LINK_SPEED reply below "
+                               "minimum size\n");
+               rc = -EINVAL;
+               goto job_error;
+       }
+
+       forced_reply->supported = (phba->hba_flag & HBA_FORCED_LINK_SPEED)
+                                  ? LPFC_FORCED_LINK_SPEED_SUPPORTED
+                                  : LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED;
+job_error:
+       job->reply->result = rc;
+       if (rc == 0)
+               job->job_done(job);
+       return rc;
+}
+
 /**
  * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
  * @job: fc_bsg_job to handle
        case LPFC_BSG_VENDOR_MENLO_DATA:
                rc = lpfc_menlo_cmd(job);
                break;
+       case LPFC_BSG_VENDOR_FORCED_LINK_SPEED:
+               rc = lpfc_forced_link_speed(job);
+               break;
        default:
                rc = -EINVAL;
                job->reply->reply_payload_rcv_len = 0;
 
 #define LPFC_BSG_VENDOR_MENLO_DATA             9
 #define LPFC_BSG_VENDOR_DIAG_MODE_END          10
 #define LPFC_BSG_VENDOR_LINK_DIAG_TEST         11
+#define LPFC_BSG_VENDOR_FORCED_LINK_SPEED      14
 
 struct set_ct_event {
        uint32_t command;
        } un;
 };
 
+#define LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED   0
+#define LPFC_FORCED_LINK_SPEED_SUPPORTED       1
+struct get_forced_link_speed_support {
+       uint32_t command;
+};
+struct forced_link_speed_support_reply {
+       uint8_t supported;
+};
+
 /* driver only */
 #define SLI_CONFIG_NOT_HANDLED         0
 #define SLI_CONFIG_HANDLED             1
 
 #define lpfc_mbx_rd_conf_r_a_tov_SHIFT         0
 #define lpfc_mbx_rd_conf_r_a_tov_MASK          0x0000FFFF
 #define lpfc_mbx_rd_conf_r_a_tov_WORD          word6
+#define lpfc_mbx_rd_conf_link_speed_SHIFT      16
+#define lpfc_mbx_rd_conf_link_speed_MASK       0x0000FFFF
+#define lpfc_mbx_rd_conf_link_speed_WORD       word6
        uint32_t rsvd_7;
        uint32_t rsvd_8;
        uint32_t word9;
 
        struct lpfc_mbx_get_func_cfg *get_func_cfg;
        struct lpfc_rsrc_desc_fcfcoe *desc;
        char *pdesc_0;
+       uint16_t forced_link_speed;
+       uint32_t if_type;
        int length, i, rc = 0, rc2;
 
        pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (rc)
                goto read_cfg_out;
 
+       /* Update link speed if forced link speed is supported */
+       if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+       if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+               forced_link_speed =
+                       bf_get(lpfc_mbx_rd_conf_link_speed, rd_config);
+               if (forced_link_speed) {
+                       phba->hba_flag |= HBA_FORCED_LINK_SPEED;
+
+                       switch (forced_link_speed) {
+                       case LINK_SPEED_1G:
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_1G;
+                               break;
+                       case LINK_SPEED_2G:
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_2G;
+                               break;
+                       case LINK_SPEED_4G:
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_4G;
+                               break;
+                       case LINK_SPEED_8G:
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_8G;
+                               break;
+                       case LINK_SPEED_10G:
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_10G;
+                               break;
+                       case LINK_SPEED_16G:
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_16G;
+                               break;
+                       case LINK_SPEED_32G:
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_32G;
+                               break;
+                       case 0xffff:
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_AUTO;
+                               break;
+                       default:
+                               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                               "0047 Unrecognized link "
+                                               "speed : %d\n",
+                                               forced_link_speed);
+                               phba->cfg_link_speed =
+                                       LPFC_USER_LINK_SPEED_AUTO;
+                       }
+               }
+       }
+
        /* Reset the DFT_HBA_Q_DEPTH to the max xri  */
        length = phba->sli4_hba.max_cfg_param.max_xri -
                        lpfc_sli4_get_els_iocb_cnt(phba);