include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / scsi / lpfc / lpfc_init.c
index 52fc758..774663e 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/spinlock.h>
 #include <linux/ctype.h>
 #include <linux/aer.h>
+#include <linux/slab.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -350,7 +351,12 @@ lpfc_config_port_post(struct lpfc_hba *phba)
        mb = &pmb->u.mb;
 
        /* Get login parameters for NID.  */
-       lpfc_read_sparam(phba, pmb, 0);
+       rc = lpfc_read_sparam(phba, pmb, 0);
+       if (rc) {
+               mempool_free(pmb, phba->mbox_mem_pool);
+               return -ENOMEM;
+       }
+
        pmb->vport = vport;
        if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -359,7 +365,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
                                mb->mbxCommand, mb->mbxStatus);
                phba->link_state = LPFC_HBA_ERROR;
                mp = (struct lpfc_dmabuf *) pmb->context1;
-               mempool_free( pmb, phba->mbox_mem_pool);
+               mempool_free(pmb, phba->mbox_mem_pool);
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
                return -EIO;
@@ -544,7 +550,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
                        mempool_free(pmb, phba->mbox_mem_pool);
                        return -EIO;
                }
-       } else {
+       } else if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) {
                lpfc_init_link(phba, pmb, phba->cfg_topology,
                        phba->cfg_link_speed);
                pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
@@ -571,6 +577,11 @@ lpfc_config_port_post(struct lpfc_hba *phba)
        }
        /* MBOX buffer will be freed in mbox compl */
        pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmb) {
+               phba->link_state = LPFC_HBA_ERROR;
+               return -ENOMEM;
+       }
+
        lpfc_config_async(phba, pmb, LPFC_ELS_RING);
        pmb->mbox_cmpl = lpfc_config_async_cmpl;
        pmb->vport = phba->pport;
@@ -588,6 +599,11 @@ lpfc_config_port_post(struct lpfc_hba *phba)
 
        /* Get Option rom version */
        pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmb) {
+               phba->link_state = LPFC_HBA_ERROR;
+               return -ENOMEM;
+       }
+
        lpfc_dump_wakeup_param(phba, pmb);
        pmb->mbox_cmpl = lpfc_dump_wakeup_param_cmpl;
        pmb->vport = phba->pport;
@@ -603,6 +619,102 @@ lpfc_config_port_post(struct lpfc_hba *phba)
 }
 
 /**
+ * lpfc_hba_init_link - Initialize the FC link
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine will issue the INIT_LINK mailbox command call.
+ * It is available to other drivers through the lpfc_hba data
+ * structure for use as a delayed link up mechanism with the
+ * module parameter lpfc_suppress_link_up.
+ *
+ * Return code
+ *             0 - success
+ *             Any other value - error
+ **/
+int
+lpfc_hba_init_link(struct lpfc_hba *phba)
+{
+       struct lpfc_vport *vport = phba->pport;
+       LPFC_MBOXQ_t *pmb;
+       MAILBOX_t *mb;
+       int rc;
+
+       pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmb) {
+               phba->link_state = LPFC_HBA_ERROR;
+               return -ENOMEM;
+       }
+       mb = &pmb->u.mb;
+       pmb->vport = vport;
+
+       lpfc_init_link(phba, pmb, phba->cfg_topology,
+               phba->cfg_link_speed);
+       pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+       lpfc_set_loopback_flag(phba);
+       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+       if (rc != MBX_SUCCESS) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "0498 Adapter failed to init, mbxCmd x%x "
+                       "INIT_LINK, mbxStatus x%x\n",
+                       mb->mbxCommand, mb->mbxStatus);
+               /* Clear all interrupt enable conditions */
+               writel(0, phba->HCregaddr);
+               readl(phba->HCregaddr); /* flush */
+               /* Clear all pending interrupts */
+               writel(0xffffffff, phba->HAregaddr);
+               readl(phba->HAregaddr); /* flush */
+               phba->link_state = LPFC_HBA_ERROR;
+               if (rc != MBX_BUSY)
+                       mempool_free(pmb, phba->mbox_mem_pool);
+               return -EIO;
+       }
+       phba->cfg_suppress_link_up = LPFC_INITIALIZE_LINK;
+
+       return 0;
+}
+
+/**
+ * lpfc_hba_down_link - this routine downs the FC link
+ *
+ * This routine will issue the DOWN_LINK mailbox command call.
+ * It is available to other drivers through the lpfc_hba data
+ * structure for use to stop the link.
+ *
+ * Return code
+ *             0 - success
+ *             Any other value - error
+ **/
+int
+lpfc_hba_down_link(struct lpfc_hba *phba)
+{
+       LPFC_MBOXQ_t *pmb;
+       int rc;
+
+       pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmb) {
+               phba->link_state = LPFC_HBA_ERROR;
+               return -ENOMEM;
+       }
+
+       lpfc_printf_log(phba,
+               KERN_ERR, LOG_INIT,
+               "0491 Adapter Link is disabled.\n");
+       lpfc_down_link(phba, pmb);
+       pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+       if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) {
+               lpfc_printf_log(phba,
+               KERN_ERR, LOG_INIT,
+               "2522 Adapter failed to issue DOWN_LINK"
+               " mbox command rc 0x%x\n", rc);
+
+               mempool_free(pmb, phba->mbox_mem_pool);
+               return -EIO;
+       }
+       return 0;
+}
+
+/**
  * lpfc_hba_down_prep - Perform lpfc uninitialization prior to HBA reset
  * @phba: pointer to lpfc HBA data structure.
  *
@@ -711,6 +823,8 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
        LIST_HEAD(aborts);
        int ret;
        unsigned long iflag = 0;
+       struct lpfc_sglq *sglq_entry = NULL;
+
        ret = lpfc_hba_down_post_s3(phba);
        if (ret)
                return ret;
@@ -726,6 +840,10 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
         * list.
         */
        spin_lock(&phba->sli4_hba.abts_sgl_list_lock);
+       list_for_each_entry(sglq_entry,
+               &phba->sli4_hba.lpfc_abts_els_sgl_list, list)
+               sglq_entry->state = SGL_FREED;
+
        list_splice_init(&phba->sli4_hba.lpfc_abts_els_sgl_list,
                        &phba->sli4_hba.lpfc_sgl_list);
        spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
@@ -2073,6 +2191,46 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
 }
 
 /**
+ * __lpfc_sli4_stop_fcf_redisc_wait_timer - Stop FCF rediscovery wait timer
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine stops the SLI4 FCF rediscover wait timer if it's on. The
+ * caller of this routine should already hold the host lock.
+ **/
+void
+__lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *phba)
+{
+       /* Clear pending FCF rediscovery wait and failover in progress flags */
+       phba->fcf.fcf_flag &= ~(FCF_REDISC_PEND |
+                               FCF_DEAD_DISC |
+                               FCF_ACVL_DISC);
+       /* Now, try to stop the timer */
+       del_timer(&phba->fcf.redisc_wait);
+}
+
+/**
+ * lpfc_sli4_stop_fcf_redisc_wait_timer - Stop FCF rediscovery wait timer
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine stops the SLI4 FCF rediscover wait timer if it's on. It
+ * checks whether the FCF rediscovery wait timer is pending with the host
+ * lock held before proceeding with disabling the timer and clearing the
+ * wait timer pendig flag.
+ **/
+void
+lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *phba)
+{
+       spin_lock_irq(&phba->hbalock);
+       if (!(phba->fcf.fcf_flag & FCF_REDISC_PEND)) {
+               /* FCF rediscovery timer already fired or stopped */
+               spin_unlock_irq(&phba->hbalock);
+               return;
+       }
+       __lpfc_sli4_stop_fcf_redisc_wait_timer(phba);
+       spin_unlock_irq(&phba->hbalock);
+}
+
+/**
  * lpfc_stop_hba_timers - Stop all the timers associated with an HBA
  * @phba: pointer to lpfc hba data structure.
  *
@@ -2096,6 +2254,7 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba)
                break;
        case LPFC_PCI_DEV_OC:
                /* Stop any OneConnect device sepcific driver timers */
+               lpfc_sli4_stop_fcf_redisc_wait_timer(phba);
                break;
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -2228,6 +2387,7 @@ lpfc_offline_prep(struct lpfc_hba * phba)
        struct lpfc_vport *vport = phba->pport;
        struct lpfc_nodelist  *ndlp, *next_ndlp;
        struct lpfc_vport **vports;
+       struct Scsi_Host *shost;
        int i;
 
        if (vport->fc_flag & FC_OFFLINE_MODE)
@@ -2241,13 +2401,14 @@ lpfc_offline_prep(struct lpfc_hba * phba)
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL) {
                for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
-                       struct Scsi_Host *shost;
-
                        if (vports[i]->load_flag & FC_UNLOADING)
                                continue;
+                       shost = lpfc_shost_from_vport(vports[i]);
+                       spin_lock_irq(shost->host_lock);
                        vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED;
                        vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
                        vports[i]->fc_flag &= ~FC_VFI_REGISTERED;
+                       spin_unlock_irq(shost->host_lock);
 
                        shost = lpfc_shost_from_vport(vports[i]);
                        list_for_each_entry_safe(ndlp, next_ndlp,
@@ -2404,7 +2565,8 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
        shost->this_id = -1;
        shost->max_cmd_len = 16;
        if (phba->sli_rev == LPFC_SLI_REV4) {
-               shost->dma_boundary = LPFC_SLI4_MAX_SEGMENT_SIZE;
+               shost->dma_boundary =
+                       phba->sli4_hba.pc_sli4_params.sge_supp_len;
                shost->sg_tablesize = phba->cfg_sg_seg_cnt;
        }
 
@@ -2438,6 +2600,14 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
        init_timer(&vport->els_tmofunc);
        vport->els_tmofunc.function = lpfc_els_timeout;
        vport->els_tmofunc.data = (unsigned long)vport;
+       if (phba->pcidev->device == PCI_DEVICE_ID_HORNET) {
+               phba->menlo_flag |= HBA_MENLO_SUPPORT;
+               /* check for menlo minimum sg count */
+               if (phba->cfg_sg_seg_cnt < LPFC_DEFAULT_MENLO_SG_SEG_CNT) {
+                       phba->cfg_sg_seg_cnt = LPFC_DEFAULT_MENLO_SG_SEG_CNT;
+                       shost->sg_tablesize = phba->cfg_sg_seg_cnt;
+               }
+       }
 
        error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
        if (error)
@@ -2653,8 +2823,6 @@ lpfc_stop_port_s4(struct lpfc_hba *phba)
        lpfc_stop_hba_timers(phba);
        phba->pport->work_port_events = 0;
        phba->sli4_hba.intr_enable = 0;
-       /* Hard clear it for now, shall have more graceful way to wait later */
-       phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
 }
 
 /**
@@ -2706,7 +2874,7 @@ lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba)
        del_fcf_record = &mboxq->u.mqe.un.del_fcf_entry;
        bf_set(lpfc_mbx_del_fcf_tbl_count, del_fcf_record, 1);
        bf_set(lpfc_mbx_del_fcf_tbl_index, del_fcf_record,
-              phba->fcf.fcf_indx);
+              phba->fcf.current_rec.fcf_indx);
 
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
@@ -2730,6 +2898,60 @@ lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba)
 }
 
 /**
+ * lpfc_fcf_redisc_wait_start_timer - Start fcf rediscover wait timer
+ * @phba: Pointer to hba for which this call is being executed.
+ *
+ * This routine starts the timer waiting for the FCF rediscovery to complete.
+ **/
+void
+lpfc_fcf_redisc_wait_start_timer(struct lpfc_hba *phba)
+{
+       unsigned long fcf_redisc_wait_tmo =
+               (jiffies + msecs_to_jiffies(LPFC_FCF_REDISCOVER_WAIT_TMO));
+       /* Start fcf rediscovery wait period timer */
+       mod_timer(&phba->fcf.redisc_wait, fcf_redisc_wait_tmo);
+       spin_lock_irq(&phba->hbalock);
+       /* Allow action to new fcf asynchronous event */
+       phba->fcf.fcf_flag &= ~(FCF_AVAILABLE | FCF_SCAN_DONE);
+       /* Mark the FCF rediscovery pending state */
+       phba->fcf.fcf_flag |= FCF_REDISC_PEND;
+       spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_fcf_redisc_wait_tmo - FCF table rediscover wait timeout
+ * @ptr: Map to lpfc_hba data structure pointer.
+ *
+ * This routine is invoked when waiting for FCF table rediscover has been
+ * timed out. If new FCF record(s) has (have) been discovered during the
+ * wait period, a new FCF event shall be added to the FCOE async event
+ * list, and then worker thread shall be waked up for processing from the
+ * worker thread context.
+ **/
+void
+lpfc_sli4_fcf_redisc_wait_tmo(unsigned long ptr)
+{
+       struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+
+       /* Don't send FCF rediscovery event if timer cancelled */
+       spin_lock_irq(&phba->hbalock);
+       if (!(phba->fcf.fcf_flag & FCF_REDISC_PEND)) {
+               spin_unlock_irq(&phba->hbalock);
+               return;
+       }
+       /* Clear FCF rediscovery timer pending flag */
+       phba->fcf.fcf_flag &= ~FCF_REDISC_PEND;
+       /* FCF rediscovery event to worker thread */
+       phba->fcf.fcf_flag |= FCF_REDISC_EVT;
+       spin_unlock_irq(&phba->hbalock);
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+                       "2776 FCF rediscover wait timer expired, post "
+                       "a worker thread event for FCF table scan\n");
+       /* wake up worker thread */
+       lpfc_worker_wake_up(phba);
+}
+
+/**
  * lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support
  * @phba: pointer to lpfc hba data structure.
  *
@@ -2996,6 +3218,68 @@ out_free_pmb:
 }
 
 /**
+ * lpfc_sli4_perform_vport_cvl - Perform clear virtual link on a vport
+ * @vport: pointer to vport data structure.
+ *
+ * This routine is to perform Clear Virtual Link (CVL) on a vport in
+ * response to a CVL event.
+ *
+ * Return the pointer to the ndlp with the vport if successful, otherwise
+ * return NULL.
+ **/
+static struct lpfc_nodelist *
+lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport)
+{
+       struct lpfc_nodelist *ndlp;
+       struct Scsi_Host *shost;
+       struct lpfc_hba *phba;
+
+       if (!vport)
+               return NULL;
+       ndlp = lpfc_findnode_did(vport, Fabric_DID);
+       if (!ndlp)
+               return NULL;
+       phba = vport->phba;
+       if (!phba)
+               return NULL;
+       if (phba->pport->port_state <= LPFC_FLOGI)
+               return NULL;
+       /* If virtual link is not yet instantiated ignore CVL */
+       if (vport->port_state <= LPFC_FDISC)
+               return NULL;
+       shost = lpfc_shost_from_vport(vport);
+       if (!shost)
+               return NULL;
+       lpfc_linkdown_port(vport);
+       lpfc_cleanup_pending_mbox(vport);
+       spin_lock_irq(shost->host_lock);
+       vport->fc_flag |= FC_VPORT_CVL_RCVD;
+       spin_unlock_irq(shost->host_lock);
+
+       return ndlp;
+}
+
+/**
+ * lpfc_sli4_perform_all_vport_cvl - Perform clear virtual link on all vports
+ * @vport: pointer to lpfc hba data structure.
+ *
+ * This routine is to perform Clear Virtual Link (CVL) on all vports in
+ * response to a FCF dead event.
+ **/
+static void
+lpfc_sli4_perform_all_vport_cvl(struct lpfc_hba *phba)
+{
+       struct lpfc_vport **vports;
+       int i;
+
+       vports = lpfc_create_vport_work_array(phba);
+       if (vports)
+               for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++)
+                       lpfc_sli4_perform_vport_cvl(vports[i]);
+       lpfc_destroy_vport_work_array(phba, vports);
+}
+
+/**
  * lpfc_sli4_async_fcoe_evt - Process the asynchronous fcoe event
  * @phba: pointer to lpfc hba data structure.
  * @acqe_link: pointer to the async fcoe completion queue entry.
@@ -3011,7 +3295,6 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
        struct lpfc_vport *vport;
        struct lpfc_nodelist *ndlp;
        struct Scsi_Host  *shost;
-       uint32_t link_state;
        int active_vlink_present;
        struct lpfc_vport **vports;
        int i;
@@ -3020,28 +3303,60 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
        phba->fcoe_eventtag = acqe_fcoe->event_tag;
        switch (event_type) {
        case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
-               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-                       "2546 New FCF found index 0x%x tag 0x%x\n",
-                       acqe_fcoe->index,
-                       acqe_fcoe->event_tag);
-               /*
-                * If the current FCF is in discovered state, or
-                * FCF discovery is in progress do nothing.
-                */
+       case LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD:
+               lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
+                       "2546 New FCF found/FCF parameter modified event: "
+                       "evt_tag:x%x, fcf_index:x%x\n",
+                       acqe_fcoe->event_tag, acqe_fcoe->index);
+
                spin_lock_irq(&phba->hbalock);
-               if ((phba->fcf.fcf_flag & FCF_DISCOVERED) ||
-                  (phba->hba_flag & FCF_DISC_INPROGRESS)) {
+               if ((phba->fcf.fcf_flag & FCF_SCAN_DONE) ||
+                   (phba->hba_flag & FCF_DISC_INPROGRESS)) {
+                       /*
+                        * If the current FCF is in discovered state or
+                        * FCF discovery is in progress, do nothing.
+                        */
+                       spin_unlock_irq(&phba->hbalock);
+                       break;
+               }
+
+               if (phba->fcf.fcf_flag & FCF_REDISC_EVT) {
+                       /*
+                        * If fast FCF failover rescan event is pending,
+                        * do nothing.
+                        */
                        spin_unlock_irq(&phba->hbalock);
                        break;
                }
                spin_unlock_irq(&phba->hbalock);
 
-               /* Read the FCF table and re-discover SAN. */
-               rc = lpfc_sli4_read_fcf_record(phba, LPFC_FCOE_FCF_GET_FIRST);
+               if ((phba->fcf.fcf_flag & FCF_DISCOVERY) &&
+                   !(phba->fcf.fcf_flag & FCF_REDISC_FOV)) {
+                       /*
+                        * During period of FCF discovery, read the FCF
+                        * table record indexed by the event to update
+                        * FCF round robin failover eligible FCF bmask.
+                        */
+                       lpfc_printf_log(phba, KERN_INFO, LOG_FIP |
+                                       LOG_DISCOVERY,
+                                       "2779 Read new FCF record with "
+                                       "fcf_index:x%x for updating FCF "
+                                       "round robin failover bmask\n",
+                                       acqe_fcoe->index);
+                       rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index);
+               }
+
+               /* Otherwise, scan the entire FCF table and re-discover SAN */
+               lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
+                               "2770 Start FCF table scan due to new FCF "
+                               "event: evt_tag:x%x, fcf_index:x%x\n",
+                               acqe_fcoe->event_tag, acqe_fcoe->index);
+               rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba,
+                                                    LPFC_FCOE_FCF_GET_FIRST);
                if (rc)
-                       lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-                                       "2547 Read FCF record failed 0x%x\n",
-                                       rc);
+                       lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
+                                       "2547 Issue FCF scan read FCF mailbox "
+                                       "command failed 0x%x\n", rc);
                break;
 
        case LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL:
@@ -3052,47 +3367,63 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
                break;
 
        case LPFC_FCOE_EVENT_TYPE_FCF_DEAD:
-               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+               lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
                        "2549 FCF disconnected from network index 0x%x"
                        " tag 0x%x\n", acqe_fcoe->index,
                        acqe_fcoe->event_tag);
                /* If the event is not for currently used fcf do nothing */
-               if (phba->fcf.fcf_indx != acqe_fcoe->index)
+               if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index)
                        break;
-               /*
-                * Currently, driver support only one FCF - so treat this as
-                * a link down, but save the link state because we don't want
-                * it to be changed to Link Down unless it is already down.
+               /* We request port to rediscover the entire FCF table for
+                * a fast recovery from case that the current FCF record
+                * is no longer valid if we are not in the middle of FCF
+                * failover process already.
                 */
-               link_state = phba->link_state;
-               lpfc_linkdown(phba);
-               phba->link_state = link_state;
-               /* Unregister FCF if no devices connected to it */
-               lpfc_unregister_unused_fcf(phba);
+               spin_lock_irq(&phba->hbalock);
+               if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
+                       spin_unlock_irq(&phba->hbalock);
+                       /* Update FLOGI FCF failover eligible FCF bmask */
+                       lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index);
+                       break;
+               }
+               /* Mark the fast failover process in progress */
+               phba->fcf.fcf_flag |= FCF_DEAD_DISC;
+               spin_unlock_irq(&phba->hbalock);
+               lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
+                               "2771 Start FCF fast failover process due to "
+                               "FCF DEAD event: evt_tag:x%x, fcf_index:x%x "
+                               "\n", acqe_fcoe->event_tag, acqe_fcoe->index);
+               rc = lpfc_sli4_redisc_fcf_table(phba);
+               if (rc) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
+                                       LOG_DISCOVERY,
+                                       "2772 Issue FCF rediscover mabilbox "
+                                       "command failed, fail through to FCF "
+                                       "dead event\n");
+                       spin_lock_irq(&phba->hbalock);
+                       phba->fcf.fcf_flag &= ~FCF_DEAD_DISC;
+                       spin_unlock_irq(&phba->hbalock);
+                       /*
+                        * Last resort will fail over by treating this
+                        * as a link down to FCF registration.
+                        */
+                       lpfc_sli4_fcf_dead_failthrough(phba);
+               } else
+                       /* Handling fast FCF failover to a DEAD FCF event
+                        * is considered equalivant to receiving CVL to all
+                        * vports.
+                        */
+                       lpfc_sli4_perform_all_vport_cvl(phba);
                break;
        case LPFC_FCOE_EVENT_TYPE_CVL:
-               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+               lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
                        "2718 Clear Virtual Link Received for VPI 0x%x"
                        " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
                vport = lpfc_find_vport_by_vpid(phba,
                                acqe_fcoe->index - phba->vpi_base);
-               if (!vport)
-                       break;
-               ndlp = lpfc_findnode_did(vport, Fabric_DID);
+               ndlp = lpfc_sli4_perform_vport_cvl(vport);
                if (!ndlp)
                        break;
-               shost = lpfc_shost_from_vport(vport);
-               if (phba->pport->port_state <= LPFC_FLOGI)
-                       break;
-               /* If virtual link is not yet instantiated ignore CVL */
-               if (vport->port_state <= LPFC_FDISC)
-                       break;
-
-               lpfc_linkdown_port(vport);
-               lpfc_cleanup_pending_mbox(vport);
-               spin_lock_irq(shost->host_lock);
-               vport->fc_flag |= FC_VPORT_CVL_RCVD;
-               spin_unlock_irq(shost->host_lock);
                active_vlink_present = 0;
 
                vports = lpfc_create_vport_work_array(phba);
@@ -3115,13 +3446,49 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
                         * re-instantiate the Vlink using FDISC.
                         */
                        mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+                       shost = lpfc_shost_from_vport(vport);
                        spin_lock_irq(shost->host_lock);
                        ndlp->nlp_flag |= NLP_DELAY_TMO;
                        spin_unlock_irq(shost->host_lock);
                        ndlp->nlp_last_elscmd = ELS_CMD_FDISC;
                        vport->port_state = LPFC_FDISC;
                } else {
-                       lpfc_retry_pport_discovery(phba);
+                       /*
+                        * Otherwise, we request port to rediscover
+                        * the entire FCF table for a fast recovery
+                        * from possible case that the current FCF
+                        * is no longer valid if we are not already
+                        * in the FCF failover process.
+                        */
+                       spin_lock_irq(&phba->hbalock);
+                       if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
+                               spin_unlock_irq(&phba->hbalock);
+                               break;
+                       }
+                       /* Mark the fast failover process in progress */
+                       phba->fcf.fcf_flag |= FCF_ACVL_DISC;
+                       spin_unlock_irq(&phba->hbalock);
+                       lpfc_printf_log(phba, KERN_INFO, LOG_FIP |
+                                       LOG_DISCOVERY,
+                                       "2773 Start FCF fast failover due "
+                                       "to CVL event: evt_tag:x%x\n",
+                                       acqe_fcoe->event_tag);
+                       rc = lpfc_sli4_redisc_fcf_table(phba);
+                       if (rc) {
+                               lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
+                                               LOG_DISCOVERY,
+                                               "2774 Issue FCF rediscover "
+                                               "mabilbox command failed, "
+                                               "through to CVL event\n");
+                               spin_lock_irq(&phba->hbalock);
+                               phba->fcf.fcf_flag &= ~FCF_ACVL_DISC;
+                               spin_unlock_irq(&phba->hbalock);
+                               /*
+                                * Last resort will be re-try on the
+                                * the current registered FCF entry.
+                                */
+                               lpfc_retry_pport_discovery(phba);
+                       }
                }
                break;
        default:
@@ -3198,6 +3565,37 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba)
 }
 
 /**
+ * lpfc_sli4_fcf_redisc_event_proc - Process fcf table rediscovery event
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked by the worker thread to process FCF table
+ * rediscovery pending completion event.
+ **/
+void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *phba)
+{
+       int rc;
+
+       spin_lock_irq(&phba->hbalock);
+       /* Clear FCF rediscovery timeout event */
+       phba->fcf.fcf_flag &= ~FCF_REDISC_EVT;
+       /* Clear driver fast failover FCF record flag */
+       phba->fcf.failover_rec.flag = 0;
+       /* Set state for FCF fast failover */
+       phba->fcf.fcf_flag |= FCF_REDISC_FOV;
+       spin_unlock_irq(&phba->hbalock);
+
+       /* Scan FCF table from the first entry to re-discover SAN */
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
+                       "2777 Start FCF table scan after FCF "
+                       "rediscovery quiescent period over\n");
+       rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST);
+       if (rc)
+               lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
+                               "2747 Issue FCF scan read FCF mailbox "
+                               "command failed 0x%x\n", rc);
+}
+
+/**
  * lpfc_api_table_setup - Set up per hba pci-device group func api jump table
  * @phba: pointer to lpfc hba data structure.
  * @dev_grp: The HBA PCI-Device group number.
@@ -3482,8 +3880,11 @@ static int
 lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
 {
        struct lpfc_sli *psli;
-       int rc;
-       int i, hbq_count;
+       LPFC_MBOXQ_t *mboxq;
+       int rc, i, hbq_count, buf_size, dma_buf_size, max_buf_size;
+       uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0};
+       struct lpfc_mqe *mqe;
+       int longs;
 
        /* Before proceed, wait for POST done and device ready */
        rc = lpfc_sli4_post_status_check(phba);
@@ -3512,6 +3913,11 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        init_timer(&phba->eratt_poll);
        phba->eratt_poll.function = lpfc_poll_eratt;
        phba->eratt_poll.data = (unsigned long) phba;
+       /* FCF rediscover timer */
+       init_timer(&phba->fcf.redisc_wait);
+       phba->fcf.redisc_wait.function = lpfc_sli4_fcf_redisc_wait_tmo;
+       phba->fcf.redisc_wait.data = (unsigned long)phba;
+
        /*
         * We need to do a READ_CONFIG mailbox command here before
         * calling lpfc_get_cfgparam. For VFs this will report the
@@ -3536,31 +3942,26 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
         * used to create the sg_dma_buf_pool must be dynamically calculated.
         * 2 segments are added since the IOCB needs a command and response bde.
         * To insure that the scsi sgl does not cross a 4k page boundary only
-        * sgl sizes of 1k, 2k, 4k, and 8k are supported.
-        * Table of sgl sizes and seg_cnt:
-        * sgl size,    sg_seg_cnt      total seg
-        * 1k           50              52
-        * 2k           114             116
-        * 4k           242             244
-        * 8k           498             500
-        * cmd(32) + rsp(160) + (52 * sizeof(sli4_sge)) = 1024
-        * cmd(32) + rsp(160) + (116 * sizeof(sli4_sge)) = 2048
-        * cmd(32) + rsp(160) + (244 * sizeof(sli4_sge)) = 4096
-        * cmd(32) + rsp(160) + (500 * sizeof(sli4_sge)) = 8192
+        * sgl sizes of must be a power of 2.
         */
-       if (phba->cfg_sg_seg_cnt <= LPFC_DEFAULT_SG_SEG_CNT)
-               phba->cfg_sg_seg_cnt = 50;
-       else if (phba->cfg_sg_seg_cnt <= 114)
-               phba->cfg_sg_seg_cnt = 114;
-       else if (phba->cfg_sg_seg_cnt <= 242)
-               phba->cfg_sg_seg_cnt = 242;
+       buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) +
+                   ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge)));
+       /* Feature Level 1 hardware is limited to 2 pages */
+       if ((bf_get(lpfc_sli_intf_featurelevel1, &phba->sli4_hba.sli_intf) ==
+            LPFC_SLI_INTF_FEATURELEVEL1_1))
+               max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE;
        else
-               phba->cfg_sg_seg_cnt = 498;
-
-       phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd)
-                                       + sizeof(struct fcp_rsp);
-       phba->cfg_sg_dma_buf_size +=
-               ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge));
+               max_buf_size = LPFC_SLI4_MAX_BUF_SIZE;
+       for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE;
+            dma_buf_size < max_buf_size && buf_size > dma_buf_size;
+            dma_buf_size = dma_buf_size << 1)
+               ;
+       if (dma_buf_size == max_buf_size)
+               phba->cfg_sg_seg_cnt = (dma_buf_size -
+                       sizeof(struct fcp_cmnd) - sizeof(struct fcp_rsp) -
+                       (2 * sizeof(struct sli4_sge))) /
+                               sizeof(struct sli4_sge);
+       phba->cfg_sg_dma_buf_size = dma_buf_size;
 
        /* Initialize buffer queue management fields */
        hbq_count = lpfc_sli_hbq_count();
@@ -3660,13 +4061,24 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                goto out_free_active_sgl;
        }
 
+       /* Allocate eligible FCF bmask memory for FCF round robin failover */
+       longs = (LPFC_SLI4_FCF_TBL_INDX_MAX + BITS_PER_LONG - 1)/BITS_PER_LONG;
+       phba->fcf.fcf_rr_bmask = kzalloc(longs * sizeof(unsigned long),
+                                        GFP_KERNEL);
+       if (!phba->fcf.fcf_rr_bmask) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "2759 Failed allocate memory for FCF round "
+                               "robin failover bmask\n");
+               goto out_remove_rpi_hdrs;
+       }
+
        phba->sli4_hba.fcp_eq_hdl = kzalloc((sizeof(struct lpfc_fcp_eq_hdl) *
                                    phba->cfg_fcp_eq_count), GFP_KERNEL);
        if (!phba->sli4_hba.fcp_eq_hdl) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "2572 Failed allocate memory for fast-path "
                                "per-EQ handle array\n");
-               goto out_remove_rpi_hdrs;
+               goto out_free_fcf_rr_bmask;
        }
 
        phba->sli4_hba.msix_entries = kzalloc((sizeof(struct msix_entry) *
@@ -3678,10 +4090,49 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                goto out_free_fcp_eq_hdl;
        }
 
+       mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
+                                                      GFP_KERNEL);
+       if (!mboxq) {
+               rc = -ENOMEM;
+               goto out_free_fcp_eq_hdl;
+       }
+
+       /* Get the Supported Pages. It is always available. */
+       lpfc_supported_pages(mboxq);
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+       if (unlikely(rc)) {
+               rc = -EIO;
+               mempool_free(mboxq, phba->mbox_mem_pool);
+               goto out_free_fcp_eq_hdl;
+       }
+
+       mqe = &mboxq->u.mqe;
+       memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3),
+              LPFC_MAX_SUPPORTED_PAGES);
+       for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) {
+               switch (pn_page[i]) {
+               case LPFC_SLI4_PARAMETERS:
+                       phba->sli4_hba.pc_sli4_params.supported = 1;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* Read the port's SLI4 Parameters capabilities if supported. */
+       if (phba->sli4_hba.pc_sli4_params.supported)
+               rc = lpfc_pc_sli4_params_get(phba, mboxq);
+       mempool_free(mboxq, phba->mbox_mem_pool);
+       if (rc) {
+               rc = -EIO;
+               goto out_free_fcp_eq_hdl;
+       }
        return rc;
 
 out_free_fcp_eq_hdl:
        kfree(phba->sli4_hba.fcp_eq_hdl);
+out_free_fcf_rr_bmask:
+       kfree(phba->fcf.fcf_rr_bmask);
 out_remove_rpi_hdrs:
        lpfc_sli4_remove_rpi_hdrs(phba);
 out_free_active_sgl:
@@ -3727,6 +4178,9 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
        lpfc_sli4_remove_rpi_hdrs(phba);
        lpfc_sli4_remove_rpis(phba);
 
+       /* Free eligible FCF index bmask */
+       kfree(phba->fcf.fcf_rr_bmask);
+
        /* Free the ELS sgl list */
        lpfc_free_active_sgl(phba);
        lpfc_free_sgl_list(phba);
@@ -3773,6 +4227,8 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
 int
 lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
 {
+       phba->lpfc_hba_init_link = lpfc_hba_init_link;
+       phba->lpfc_hba_down_link = lpfc_hba_down_link;
        switch (dev_grp) {
        case LPFC_PCI_DEV_LP:
                phba->lpfc_hba_down_post = lpfc_hba_down_post_s3;
@@ -4120,6 +4576,7 @@ lpfc_init_sgl_list(struct lpfc_hba *phba)
 
                /* The list order is used by later block SGL registraton */
                spin_lock_irq(&phba->hbalock);
+               sglq_entry->state = SGL_FREED;
                list_add_tail(&sglq_entry->list, &phba->sli4_hba.lpfc_sgl_list);
                phba->sli4_hba.lpfc_els_sgl_array[i] = sglq_entry;
                phba->sli4_hba.total_sglq_bufs++;
@@ -4681,7 +5138,7 @@ lpfc_sli_pci_mem_unset(struct lpfc_hba *phba)
 int
 lpfc_sli4_post_status_check(struct lpfc_hba *phba)
 {
-       struct lpfc_register sta_reg, uerrlo_reg, uerrhi_reg, scratchpad;
+       struct lpfc_register sta_reg, uerrlo_reg, uerrhi_reg;
        int i, port_error = -ENODEV;
 
        if (!phba->sli4_hba.STAregaddr)
@@ -4717,14 +5174,21 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba)
                        bf_get(lpfc_hst_state_port_status, &sta_reg));
 
        /* Log device information */
-       scratchpad.word0 =  readl(phba->sli4_hba.SCRATCHPADregaddr);
-       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                       "2534 Device Info: ChipType=0x%x, SliRev=0x%x, "
-                       "FeatureL1=0x%x, FeatureL2=0x%x\n",
-                       bf_get(lpfc_scratchpad_chiptype, &scratchpad),
-                       bf_get(lpfc_scratchpad_slirev, &scratchpad),
-                       bf_get(lpfc_scratchpad_featurelevel1, &scratchpad),
-                       bf_get(lpfc_scratchpad_featurelevel2, &scratchpad));
+       phba->sli4_hba.sli_intf.word0 = readl(phba->sli4_hba.SLIINTFregaddr);
+       if (bf_get(lpfc_sli_intf_valid,
+                  &phba->sli4_hba.sli_intf) == LPFC_SLI_INTF_VALID) {
+               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "2534 Device Info: ChipType=0x%x, SliRev=0x%x, "
+                               "FeatureL1=0x%x, FeatureL2=0x%x\n",
+                               bf_get(lpfc_sli_intf_sli_family,
+                                      &phba->sli4_hba.sli_intf),
+                               bf_get(lpfc_sli_intf_slirev,
+                                      &phba->sli4_hba.sli_intf),
+                               bf_get(lpfc_sli_intf_featurelevel1,
+                                      &phba->sli4_hba.sli_intf),
+                               bf_get(lpfc_sli_intf_featurelevel2,
+                                      &phba->sli4_hba.sli_intf));
+       }
        phba->sli4_hba.ue_mask_lo = readl(phba->sli4_hba.UEMASKLOregaddr);
        phba->sli4_hba.ue_mask_hi = readl(phba->sli4_hba.UEMASKHIregaddr);
        /* With uncoverable error, log the error message and return error */
@@ -4763,8 +5227,8 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba)
                                        LPFC_UE_MASK_LO;
        phba->sli4_hba.UEMASKHIregaddr = phba->sli4_hba.conf_regs_memmap_p +
                                        LPFC_UE_MASK_HI;
-       phba->sli4_hba.SCRATCHPADregaddr = phba->sli4_hba.conf_regs_memmap_p +
-                                       LPFC_SCRATCHPAD;
+       phba->sli4_hba.SLIINTFregaddr = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_SLI_INTF;
 }
 
 /**
@@ -6039,7 +6503,7 @@ lpfc_sli4_fcfi_unreg(struct lpfc_hba *phba, uint16_t fcfi)
                spin_lock_irqsave(&phba->hbalock, flags);
                /* Mark the FCFI is no longer registered */
                phba->fcf.fcf_flag &=
-                       ~(FCF_AVAILABLE | FCF_REGISTERED | FCF_DISCOVERED);
+                       ~(FCF_AVAILABLE | FCF_REGISTERED | FCF_SCAN_DONE);
                spin_unlock_irqrestore(&phba->hbalock, flags);
        }
 }
@@ -6079,16 +6543,20 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
 
        /* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the
         * number of bytes required by each mapping. They are actually
-        * mapping to the PCI BAR regions 1, 2, and 4 by the SLI4 device.
+        * mapping to the PCI BAR regions 0 or 1, 2, and 4 by the SLI4 device.
         */
-       phba->pci_bar0_map = pci_resource_start(pdev, LPFC_SLI4_BAR0);
-       bar0map_len = pci_resource_len(pdev, LPFC_SLI4_BAR0);
-
-       phba->pci_bar1_map = pci_resource_start(pdev, LPFC_SLI4_BAR1);
-       bar1map_len = pci_resource_len(pdev, LPFC_SLI4_BAR1);
+       if (pci_resource_start(pdev, 0)) {
+               phba->pci_bar0_map = pci_resource_start(pdev, 0);
+               bar0map_len = pci_resource_len(pdev, 0);
+       } else {
+               phba->pci_bar0_map = pci_resource_start(pdev, 1);
+               bar0map_len = pci_resource_len(pdev, 1);
+       }
+       phba->pci_bar1_map = pci_resource_start(pdev, 2);
+       bar1map_len = pci_resource_len(pdev, 2);
 
-       phba->pci_bar2_map = pci_resource_start(pdev, LPFC_SLI4_BAR2);
-       bar2map_len = pci_resource_len(pdev, LPFC_SLI4_BAR2);
+       phba->pci_bar2_map = pci_resource_start(pdev, 4);
+       bar2map_len = pci_resource_len(pdev, 4);
 
        /* Map SLI4 PCI Config Space Register base to a kernel virtual addr */
        phba->sli4_hba.conf_regs_memmap_p =
@@ -6833,6 +7301,73 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
        phba->pport->work_port_events = 0;
 }
 
+ /**
+ * lpfc_pc_sli4_params_get - Get the SLI4_PARAMS port capabilities.
+ * @phba: Pointer to HBA context object.
+ * @mboxq: Pointer to the mailboxq memory for the mailbox command response.
+ *
+ * This function is called in the SLI4 code path to read the port's
+ * sli4 capabilities.
+ *
+ * This function may be be called from any context that can block-wait
+ * for the completion.  The expectation is that this routine is called
+ * typically from probe_one or from the online routine.
+ **/
+int
+lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+{
+       int rc;
+       struct lpfc_mqe *mqe;
+       struct lpfc_pc_sli4_params *sli4_params;
+       uint32_t mbox_tmo;
+
+       rc = 0;
+       mqe = &mboxq->u.mqe;
+
+       /* Read the port's SLI4 Parameters port capabilities */
+       lpfc_sli4_params(mboxq);
+       if (!phba->sli4_hba.intr_enable)
+               rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+       else {
+               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_PORT_CAPABILITIES);
+               rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+       }
+
+       if (unlikely(rc))
+               return 1;
+
+       sli4_params = &phba->sli4_hba.pc_sli4_params;
+       sli4_params->if_type = bf_get(if_type, &mqe->un.sli4_params);
+       sli4_params->sli_rev = bf_get(sli_rev, &mqe->un.sli4_params);
+       sli4_params->sli_family = bf_get(sli_family, &mqe->un.sli4_params);
+       sli4_params->featurelevel_1 = bf_get(featurelevel_1,
+                                            &mqe->un.sli4_params);
+       sli4_params->featurelevel_2 = bf_get(featurelevel_2,
+                                            &mqe->un.sli4_params);
+       sli4_params->proto_types = mqe->un.sli4_params.word3;
+       sli4_params->sge_supp_len = mqe->un.sli4_params.sge_supp_len;
+       sli4_params->if_page_sz = bf_get(if_page_sz, &mqe->un.sli4_params);
+       sli4_params->rq_db_window = bf_get(rq_db_window, &mqe->un.sli4_params);
+       sli4_params->loopbk_scope = bf_get(loopbk_scope, &mqe->un.sli4_params);
+       sli4_params->eq_pages_max = bf_get(eq_pages, &mqe->un.sli4_params);
+       sli4_params->eqe_size = bf_get(eqe_size, &mqe->un.sli4_params);
+       sli4_params->cq_pages_max = bf_get(cq_pages, &mqe->un.sli4_params);
+       sli4_params->cqe_size = bf_get(cqe_size, &mqe->un.sli4_params);
+       sli4_params->mq_pages_max = bf_get(mq_pages, &mqe->un.sli4_params);
+       sli4_params->mqe_size = bf_get(mqe_size, &mqe->un.sli4_params);
+       sli4_params->mq_elem_cnt = bf_get(mq_elem_cnt, &mqe->un.sli4_params);
+       sli4_params->wq_pages_max = bf_get(wq_pages, &mqe->un.sli4_params);
+       sli4_params->wqe_size = bf_get(wqe_size, &mqe->un.sli4_params);
+       sli4_params->rq_pages_max = bf_get(rq_pages, &mqe->un.sli4_params);
+       sli4_params->rqe_size = bf_get(rqe_size, &mqe->un.sli4_params);
+       sli4_params->hdr_pages_max = bf_get(hdr_pages, &mqe->un.sli4_params);
+       sli4_params->hdr_size = bf_get(hdr_size, &mqe->un.sli4_params);
+       sli4_params->hdr_pp_align = bf_get(hdr_pp_align, &mqe->un.sli4_params);
+       sli4_params->sgl_pages_max = bf_get(sgl_pages, &mqe->un.sli4_params);
+       sli4_params->sgl_pp_align = bf_get(sgl_pp_align, &mqe->un.sli4_params);
+       return rc;
+}
+
 /**
  * lpfc_pci_probe_one_s3 - PCI probe func to reg SLI-3 device to PCI subsystem.
  * @pdev: pointer to PCI device
@@ -7174,6 +7709,12 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev)
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
 
+       /*
+        * As the new kernel behavior of pci_restore_state() API call clears
+        * device saved_state flag, need to save the restored state again.
+        */
+       pci_save_state(pdev);
+
        if (pdev->is_busmaster)
                pci_set_master(pdev);
 
@@ -7357,6 +7898,13 @@ lpfc_io_slot_reset_s3(struct pci_dev *pdev)
        }
 
        pci_restore_state(pdev);
+
+       /*
+        * As the new kernel behavior of pci_restore_state() API call clears
+        * device saved_state flag, need to save the restored state again.
+        */
+       pci_save_state(pdev);
+
        if (pdev->is_busmaster)
                pci_set_master(pdev);
 
@@ -7766,6 +8314,13 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev)
        /* Restore device state from PCI config space */
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
+
+       /*
+        * As the new kernel behavior of pci_restore_state() API call clears
+        * device saved_state flag, need to save the restored state again.
+        */
+       pci_save_state(pdev);
+
        if (pdev->is_busmaster)
                pci_set_master(pdev);
 
@@ -7885,11 +8440,11 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        int rc;
        struct lpfc_sli_intf intf;
 
-       if (pci_read_config_dword(pdev, LPFC_SLIREV_CONF_WORD, &intf.word0))
+       if (pci_read_config_dword(pdev, LPFC_SLI_INTF, &intf.word0))
                return -ENODEV;
 
        if ((bf_get(lpfc_sli_intf_valid, &intf) == LPFC_SLI_INTF_VALID) &&
-               (bf_get(lpfc_sli_intf_rev, &intf) == LPFC_SLIREV_CONF_SLI4))
+           (bf_get(lpfc_sli_intf_slirev, &intf) == LPFC_SLI_INTF_REV_SLI4))
                rc = lpfc_pci_probe_one_s4(pdev, pid);
        else
                rc = lpfc_pci_probe_one_s3(pdev, pid);