]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: lpfc: Fix EEH support for NVMe I/O
authorJames Smart <jsmart2021@gmail.com>
Fri, 10 Sep 2021 23:31:54 +0000 (16:31 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 15 Sep 2021 03:33:21 +0000 (23:33 -0400)
Injecting errors on the PCI slot while the driver is handling NVMe I/O will
cause crashes and hangs.

There are several rather difficult scenarios occurring. The main issue is
that the adapter can report a PCI error before or simultaneously to the PCI
subsystem reporting the error. Both paths have different entry points and
currently there is no interlock between them. Thus multiple teardown paths
are competing and all heck breaks loose.

Complicating things is the NVMs path. To a large degree, I/O was able to be
shutdown for a full FC port on the SCSI stack. But on NVMe, there isn't a
similar call. At best, it works on a per-controller basis, but even at the
controller level, it's a controller "reset" call. All of which means I/O is
still flowing on different CPUs with reset paths expecting hw access
(mailbox commands) to execute properly.

The following modifications are made:

 - A new flag is set in PCI error entrypoints so the driver can track being
   called by that path.

 - An interlock is added in the SLI hw error path and the PCI error path
   such that only one of the paths proceeds with the teardown logic.

 - RPI cleanup is patched such that RPIs are marked unregistered w/o mbx
   cmds in cases of hw error.

 - If entering the SLI port re-init calls, a case where SLI error teardown
   was quick and beat the PCI calls now reporting error, check whether the
   SLI port is still live on the PCI bus.

 - In the PCI reset code to bring the adapter back, recheck the IRQ
   settings. Different checks for SLI3 vs SLI4.

 - In I/O completions, that may be called as part of the cleanup or
   underway just before the hw error, check the state of the adapter.  If
   in error, shortcut handling that would expect further adapter
   completions as the hw error won't be sending them.

 - In routines waiting on I/O completions, which may have been in progress
   prior to the hw error, detect the device is being torn down and abort
   from their waits and just give up. This points to a larger issue in the
   driver on ref-counting for data structures, as it doesn't have
   ref-counting on q and port structures. We'll do this fix for now as it
   would be a major rework to be done differently.

 - Fix the NVMe cleanup to simulate NVMe I/O completions if I/O is being
   failed back due to hw error.

 - In I/O buf allocation, done at the start of new I/Os, check hw state and
   fail if hw error.

Link: https://lore.kernel.org/r/20210910233159.115896-10-jsmart2021@gmail.com
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nvme.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h

index befeb7c34290378820647d5012e70c663fc74347..2f6b81bc24517db2556f179b08e0b33e63e973a0 100644 (file)
@@ -1028,6 +1028,7 @@ struct lpfc_hba {
                                         * Firmware supports Forced Link Speed
                                         * capability
                                         */
+#define HBA_PCI_ERR            0x80000 /* The PCI slot is offline */
 #define HBA_FLOGI_ISSUED       0x100000 /* FLOGI was issued */
 #define HBA_CGN_RSVD1          0x200000 /* Reserved CGN flag */
 #define HBA_CGN_DAY_WRAP       0x400000 /* HBA Congestion info day wraps */
index 12abfc027a67ce4d5fd32baf845b0e1e248d6eff..0b1e1cc00e0197167c1fbfe9972d849845aa6213 100644 (file)
@@ -5250,6 +5250,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 
                        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
                        if (rc == MBX_NOT_FINISHED) {
+                               ndlp->nlp_flag &= ~NLP_UNREG_INP;
                                mempool_free(mbox, phba->mbox_mem_pool);
                                acc_plogi = 1;
                        }
index 0ec322f0e3cb99f602a42fab0344529c05260e3b..3fd730613de3ef1774aa751f29ad9fb24a1257ca 100644 (file)
@@ -1606,6 +1606,11 @@ void
 lpfc_sli4_offline_eratt(struct lpfc_hba *phba)
 {
        spin_lock_irq(&phba->hbalock);
+       if (phba->link_state == LPFC_HBA_ERROR &&
+           phba->hba_flag & HBA_PCI_ERR) {
+               spin_unlock_irq(&phba->hbalock);
+               return;
+       }
        phba->link_state = LPFC_HBA_ERROR;
        spin_unlock_irq(&phba->hbalock);
 
@@ -1945,7 +1950,6 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
        if (pci_channel_offline(phba->pcidev)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
                                "3166 pci channel is offline\n");
-               lpfc_sli4_offline_eratt(phba);
                return;
        }
 
@@ -3643,6 +3647,7 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
        struct lpfc_vport **vports;
        struct Scsi_Host *shost;
        int i;
+       int offline = 0;
 
        if (vport->fc_flag & FC_OFFLINE_MODE)
                return;
@@ -3651,6 +3656,8 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
 
        lpfc_linkdown(phba);
 
+       offline =  pci_channel_offline(phba->pcidev);
+
        /* Issue an unreg_login to all nodes on all vports */
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL) {
@@ -3673,7 +3680,14 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
                                ndlp->nlp_flag &= ~NLP_NPR_ADISC;
                                spin_unlock_irq(&ndlp->lock);
 
-                               lpfc_unreg_rpi(vports[i], ndlp);
+                               if (offline) {
+                                       spin_lock_irq(&ndlp->lock);
+                                       ndlp->nlp_flag &= ~(NLP_UNREG_INP |
+                                                           NLP_RPI_REGISTERED);
+                                       spin_unlock_irq(&ndlp->lock);
+                               } else {
+                                       lpfc_unreg_rpi(vports[i], ndlp);
+                               }
                                /*
                                 * Whenever an SLI4 port goes offline, free the
                                 * RPI. Get a new RPI when the adapter port
@@ -14080,6 +14094,10 @@ lpfc_pci_resume_one_s3(struct device *dev_d)
                return error;
        }
 
+       /* Init cpu_map array */
+       lpfc_cpu_map_array_init(phba);
+       /* Init hba_eq_hdl array */
+       lpfc_hba_eq_hdl_array_init(phba);
        /* Configure and enable interrupt */
        intr_mode = lpfc_sli_enable_intr(phba, phba->intr_mode);
        if (intr_mode == LPFC_INTR_ERROR) {
@@ -15033,14 +15051,17 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state)
                lpfc_sli4_prep_dev_for_recover(phba);
                return PCI_ERS_RESULT_CAN_RECOVER;
        case pci_channel_io_frozen:
+               phba->hba_flag |= HBA_PCI_ERR;
                /* Fatal error, prepare for slot reset */
                lpfc_sli4_prep_dev_for_reset(phba);
                return PCI_ERS_RESULT_NEED_RESET;
        case pci_channel_io_perm_failure:
+               phba->hba_flag |= HBA_PCI_ERR;
                /* Permanent failure, prepare for device down */
                lpfc_sli4_prep_dev_for_perm_failure(phba);
                return PCI_ERS_RESULT_DISCONNECT;
        default:
+               phba->hba_flag |= HBA_PCI_ERR;
                /* Unknown state, prepare and request slot reset */
                lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
                                "2825 Unknown PCI error state: x%x\n", state);
@@ -15084,6 +15105,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
 
        pci_restore_state(pdev);
 
+       phba->hba_flag &= ~HBA_PCI_ERR;
        /*
         * As the new kernel behavior of pci_restore_state() API call clears
         * device saved_state flag, need to save the restored state again.
@@ -15106,6 +15128,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
        } else
                phba->intr_mode = intr_mode;
+       lpfc_cpu_affinity_check(phba, phba->cfg_irq_chann);
 
        /* Log the current active interrupt mode */
        lpfc_log_intr_mode(phba, phba->intr_mode);
@@ -15307,6 +15330,10 @@ lpfc_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
        struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
        pci_ers_result_t rc = PCI_ERS_RESULT_DISCONNECT;
 
+       if (phba->link_state == LPFC_HBA_ERROR &&
+           phba->hba_flag & HBA_IOQ_FLUSH)
+               return PCI_ERS_RESULT_NEED_RESET;
+
        switch (phba->pci_dev_grp) {
        case LPFC_PCI_DEV_LP:
                rc = lpfc_io_error_detected_s3(pdev, state);
index bd88477f9b82bac9ea0c79f66610972192e769db..33266e1b24ab64c6f44432ccc89f3bef6a230b13 100644 (file)
@@ -937,6 +937,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        int cpu;
 #endif
+       int offline = 0;
 
        /* Sanity check on return of outstanding command */
        if (!lpfc_ncmd) {
@@ -1098,11 +1099,12 @@ out_err:
                        nCmd->transferred_length = 0;
                        nCmd->rcv_rsplen = 0;
                        nCmd->status = NVME_SC_INTERNAL;
+                       offline = pci_channel_offline(vport->phba->pcidev);
                }
        }
 
        /* pick up SLI4 exhange busy condition */
-       if (bf_get(lpfc_wcqe_c_xb, wcqe))
+       if (bf_get(lpfc_wcqe_c_xb, wcqe) && !offline)
                lpfc_ncmd->flags |= LPFC_SBUF_XBUSY;
        else
                lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY;
@@ -2169,6 +2171,10 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
                        abts_nvme = 0;
                        for (i = 0; i < phba->cfg_hdw_queue; i++) {
                                qp = &phba->sli4_hba.hdwq[i];
+                               if (!vport || !vport->localport ||
+                                   !qp || !qp->io_wq)
+                                       return;
+
                                pring = qp->io_wq->pring;
                                if (!pring)
                                        continue;
@@ -2176,6 +2182,10 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
                                abts_scsi += qp->abts_scsi_io_bufs;
                                abts_nvme += qp->abts_nvme_io_bufs;
                        }
+                       if (!vport || !vport->localport ||
+                           vport->phba->hba_flag & HBA_PCI_ERR)
+                               return;
+
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
                                         "6176 Lport x%px Localport x%px wait "
                                         "timed out. Pending %d [%d:%d]. "
@@ -2215,6 +2225,8 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
                return;
 
        localport = vport->localport;
+       if (!localport)
+               return;
        lport = (struct lpfc_nvme_lport *)localport->private;
 
        lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME,
@@ -2531,7 +2543,8 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                 * return values is ignored.  The upcall is a courtesy to the
                 * transport.
                 */
-               if (vport->load_flag & FC_UNLOADING)
+               if (vport->load_flag & FC_UNLOADING ||
+                   unlikely(vport->phba->hba_flag & HBA_PCI_ERR))
                        (void)nvme_fc_set_remoteport_devloss(remoteport, 0);
 
                ret = nvme_fc_unregister_remoteport(remoteport);
@@ -2559,6 +2572,42 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                         vport->localport, ndlp->rport, ndlp->nlp_DID);
 }
 
+/**
+ * lpfc_sli4_nvme_pci_offline_aborted - Fast-path process of NVME xri abort
+ * @phba: pointer to lpfc hba data structure.
+ * @lpfc_ncmd: The nvme job structure for the request being aborted.
+ *
+ * This routine is invoked by the worker thread to process a SLI4 fast-path
+ * NVME aborted xri.  Aborted NVME IO commands are completed to the transport
+ * here.
+ **/
+void
+lpfc_sli4_nvme_pci_offline_aborted(struct lpfc_hba *phba,
+                                  struct lpfc_io_buf *lpfc_ncmd)
+{
+       struct nvmefc_fcp_req *nvme_cmd = NULL;
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
+                       "6533 %s nvme_cmd %p tag x%x abort complete and "
+                       "xri released\n", __func__,
+                       lpfc_ncmd->nvmeCmd,
+                       lpfc_ncmd->cur_iocbq.iotag);
+
+       /* Aborted NVME commands are required to not complete
+        * before the abort exchange command fully completes.
+        * Once completed, it is available via the put list.
+        */
+       if (lpfc_ncmd->nvmeCmd) {
+               nvme_cmd = lpfc_ncmd->nvmeCmd;
+               nvme_cmd->transferred_length = 0;
+               nvme_cmd->rcv_rsplen = 0;
+               nvme_cmd->status = NVME_SC_INTERNAL;
+               nvme_cmd->done(nvme_cmd);
+               lpfc_ncmd->nvmeCmd = NULL;
+       }
+       lpfc_release_nvme_buf(phba, lpfc_ncmd);
+}
+
 /**
  * lpfc_sli4_nvme_xri_aborted - Fast-path process of NVME xri abort
  * @phba: pointer to lpfc hba data structure.
index 0fde1e874c7a308e0850bc7bf6acd332415686cb..b70f71b5c1f7021220faf4ab97739bf2370f5d8d 100644 (file)
@@ -493,8 +493,8 @@ void
 lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
                         struct sli4_wcqe_xri_aborted *axri, int idx)
 {
-       uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
-       uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
+       u16 xri = 0;
+       u16 rxid = 0;
        struct lpfc_io_buf *psb, *next_psb;
        struct lpfc_sli4_hdw_queue *qp;
        unsigned long iflag = 0;
@@ -504,15 +504,22 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
        int rrq_empty = 0;
        struct lpfc_sli_ring *pring = phba->sli4_hba.els_wq->pring;
        struct scsi_cmnd *cmd;
+       int offline = 0;
 
        if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
                return;
-
+       offline = pci_channel_offline(phba->pcidev);
+       if (!offline) {
+               xri = bf_get(lpfc_wcqe_xa_xri, axri);
+               rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
+       }
        qp = &phba->sli4_hba.hdwq[idx];
        spin_lock_irqsave(&phba->hbalock, iflag);
        spin_lock(&qp->abts_io_buf_list_lock);
        list_for_each_entry_safe(psb, next_psb,
                &qp->lpfc_abts_io_buf_list, list) {
+               if (offline)
+                       xri = psb->cur_iocbq.sli4_xritag;
                if (psb->cur_iocbq.sli4_xritag == xri) {
                        list_del_init(&psb->list);
                        psb->flags &= ~LPFC_SBUF_XBUSY;
@@ -521,8 +528,15 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
                                qp->abts_nvme_io_bufs--;
                                spin_unlock(&qp->abts_io_buf_list_lock);
                                spin_unlock_irqrestore(&phba->hbalock, iflag);
-                               lpfc_sli4_nvme_xri_aborted(phba, axri, psb);
-                               return;
+                               if (!offline) {
+                                       lpfc_sli4_nvme_xri_aborted(phba, axri,
+                                                                  psb);
+                                       return;
+                               }
+                               lpfc_sli4_nvme_pci_offline_aborted(phba, psb);
+                               spin_lock_irqsave(&phba->hbalock, iflag);
+                               spin_lock(&qp->abts_io_buf_list_lock);
+                               continue;
                        }
                        qp->abts_scsi_io_bufs--;
                        spin_unlock(&qp->abts_io_buf_list_lock);
@@ -534,13 +548,13 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
 
                        rrq_empty = list_empty(&phba->active_rrq_list);
                        spin_unlock_irqrestore(&phba->hbalock, iflag);
-                       if (ndlp) {
+                       if (ndlp && !offline) {
                                lpfc_set_rrq_active(phba, ndlp,
                                        psb->cur_iocbq.sli4_lxritag, rxid, 1);
                                lpfc_sli4_abts_err_handler(phba, ndlp, axri);
                        }
 
-                       if (phba->cfg_fcp_wait_abts_rsp) {
+                       if (phba->cfg_fcp_wait_abts_rsp || offline) {
                                spin_lock_irqsave(&psb->buf_lock, iflag);
                                cmd = psb->pCmd;
                                psb->pCmd = NULL;
@@ -567,25 +581,30 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
                        lpfc_release_scsi_buf_s4(phba, psb);
                        if (rrq_empty)
                                lpfc_worker_wake_up(phba);
-                       return;
+                       if (!offline)
+                               return;
+                       spin_lock_irqsave(&phba->hbalock, iflag);
+                       spin_lock(&qp->abts_io_buf_list_lock);
+                       continue;
                }
        }
        spin_unlock(&qp->abts_io_buf_list_lock);
-       for (i = 1; i <= phba->sli.last_iotag; i++) {
-               iocbq = phba->sli.iocbq_lookup[i];
-
-               if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
-                   (iocbq->iocb_flag & LPFC_IO_LIBDFC))
-                       continue;
-               if (iocbq->sli4_xritag != xri)
-                       continue;
-               psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
-               psb->flags &= ~LPFC_SBUF_XBUSY;
-               spin_unlock_irqrestore(&phba->hbalock, iflag);
-               if (!list_empty(&pring->txq))
-                       lpfc_worker_wake_up(phba);
-               return;
+       if (!offline) {
+               for (i = 1; i <= phba->sli.last_iotag; i++) {
+                       iocbq = phba->sli.iocbq_lookup[i];
 
+                       if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
+                           (iocbq->iocb_flag & LPFC_IO_LIBDFC))
+                               continue;
+                       if (iocbq->sli4_xritag != xri)
+                               continue;
+                       psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
+                       psb->flags &= ~LPFC_SBUF_XBUSY;
+                       spin_unlock_irqrestore(&phba->hbalock, iflag);
+                       if (!list_empty(&pring->txq))
+                               lpfc_worker_wake_up(phba);
+                       return;
+               }
        }
        spin_unlock_irqrestore(&phba->hbalock, iflag);
 }
index e8f6ad4847681c1f7a990486636631267a76e819..651e6ee64e88b4466d39fd0dcb176a2499aa089a 100644 (file)
@@ -1404,7 +1404,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
                }
 
                if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) &&
-                       (sglq->state != SGL_XRI_ABORTED)) {
+                   (!(unlikely(pci_channel_offline(phba->pcidev)))) &&
+                   sglq->state != SGL_XRI_ABORTED) {
                        spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock,
                                          iflag);
 
@@ -4583,10 +4584,12 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)
                        lpfc_sli_cancel_iocbs(phba, &txq,
                                              IOSTAT_LOCAL_REJECT,
                                              IOERR_SLI_DOWN);
-                       /* Flush the txcmpq */
+                       /* Flush the txcmplq */
                        lpfc_sli_cancel_iocbs(phba, &txcmplq,
                                              IOSTAT_LOCAL_REJECT,
                                              IOERR_SLI_DOWN);
+                       if (unlikely(pci_channel_offline(phba->pcidev)))
+                               lpfc_sli4_io_xri_aborted(phba, NULL, 0);
                }
        } else {
                pring = &psli->sli3_ring[LPFC_FCP_RING];
@@ -22019,8 +22022,26 @@ lpfc_get_io_buf_from_multixri_pools(struct lpfc_hba *phba,
 
        qp = &phba->sli4_hba.hdwq[hwqid];
        lpfc_ncmd = NULL;
+       if (!qp) {
+               lpfc_printf_log(phba, KERN_INFO,
+                               LOG_SLI | LOG_NVME_ABTS | LOG_FCP,
+                               "5556 NULL qp for hwqid  x%x\n", hwqid);
+               return lpfc_ncmd;
+       }
        multixri_pool = qp->p_multixri_pool;
+       if (!multixri_pool) {
+               lpfc_printf_log(phba, KERN_INFO,
+                               LOG_SLI | LOG_NVME_ABTS | LOG_FCP,
+                               "5557 NULL multixri for hwqid  x%x\n", hwqid);
+               return lpfc_ncmd;
+       }
        pvt_pool = &multixri_pool->pvt_pool;
+       if (!pvt_pool) {
+               lpfc_printf_log(phba, KERN_INFO,
+                               LOG_SLI | LOG_NVME_ABTS | LOG_FCP,
+                               "5558 NULL pvt_pool for hwqid  x%x\n", hwqid);
+               return lpfc_ncmd;
+       }
        multixri_pool->io_req_count++;
 
        /* If pvt_pool is empty, move some XRIs from public to private pool */
@@ -22096,6 +22117,12 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba,
 
        qp = &phba->sli4_hba.hdwq[hwqid];
        lpfc_cmd = NULL;
+       if (!qp) {
+               lpfc_printf_log(phba, KERN_WARNING,
+                               LOG_SLI | LOG_NVME_ABTS | LOG_FCP,
+                               "5555 NULL qp for hwqid  x%x\n", hwqid);
+               return lpfc_cmd;
+       }
 
        if (phba->cfg_xri_rebalancing)
                lpfc_cmd = lpfc_get_io_buf_from_multixri_pools(
index 99c5d1e4da5efb93cd2dcac2d2ebcfead9f25a3f..5962cf508842f7cef31749b1878c2018820bd83e 100644 (file)
@@ -1116,6 +1116,8 @@ void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *);
 int lpfc_sli4_resume_rpi(struct lpfc_nodelist *,
                        void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *);
 void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba);
+void lpfc_sli4_nvme_pci_offline_aborted(struct lpfc_hba *phba,
+                                       struct lpfc_io_buf *lpfc_ncmd);
 void lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba,
                                struct sli4_wcqe_xri_aborted *axri,
                                struct lpfc_io_buf *lpfc_ncmd);