summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c141
1 files changed, 91 insertions, 50 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 95caad764fb7..fa1a714a78f0 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1532,15 +1532,19 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist,
while (!list_empty(iocblist)) {
list_remove_head(iocblist, piocb, struct lpfc_iocbq, list);
- if (!piocb->iocb_cmpl) {
+ if (piocb->wqe_cmpl) {
if (piocb->iocb_flag & LPFC_IO_NVME)
- lpfc_nvme_cancel_iocb(phba, piocb);
+ lpfc_nvme_cancel_iocb(phba, piocb,
+ ulpstatus, ulpWord4);
else
lpfc_sli_release_iocbq(phba, piocb);
- } else {
+
+ } else if (piocb->iocb_cmpl) {
piocb->iocb.ulpStatus = ulpstatus;
piocb->iocb.un.ulpWord[4] = ulpWord4;
(piocb->iocb_cmpl) (phba, piocb, piocb);
+ } else {
+ lpfc_sli_release_iocbq(phba, piocb);
}
}
return;
@@ -3007,23 +3011,44 @@ lpfc_nvme_unsol_ls_handler(struct lpfc_hba *phba, struct lpfc_iocbq *piocb)
axchg->payload = nvmebuf->dbuf.virt;
INIT_LIST_HEAD(&axchg->list);
- if (phba->nvmet_support)
+ if (phba->nvmet_support) {
ret = lpfc_nvmet_handle_lsreq(phba, axchg);
- else
+ spin_lock_irq(&ndlp->lock);
+ if (!ret && !(ndlp->fc4_xpt_flags & NLP_XPT_HAS_HH)) {
+ ndlp->fc4_xpt_flags |= NLP_XPT_HAS_HH;
+ spin_unlock_irq(&ndlp->lock);
+
+ /* This reference is a single occurrence to hold the
+ * node valid until the nvmet transport calls
+ * host_release.
+ */
+ if (!lpfc_nlp_get(ndlp))
+ goto out_fail;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_NODE,
+ "6206 NVMET unsol ls_req ndlp %p "
+ "DID x%x xflags x%x refcnt %d\n",
+ ndlp, ndlp->nlp_DID,
+ ndlp->fc4_xpt_flags,
+ kref_read(&ndlp->kref));
+ } else {
+ spin_unlock_irq(&ndlp->lock);
+ }
+ } else {
ret = lpfc_nvme_handle_lsreq(phba, axchg);
+ }
/* if zero, LS was successfully handled. If non-zero, LS not handled */
if (!ret)
return;
+out_fail:
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6155 Drop NVME LS from DID %06X: SID %06X OXID x%X "
"NVMe%s handler failed %d\n",
did, sid, oxid,
(phba->nvmet_support) ? "T" : "I", ret);
-out_fail:
-
/* recycle receive buffer */
lpfc_in_buf_free(phba, &nvmebuf->dbuf);
@@ -4221,6 +4246,8 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);
spin_unlock_irq(&phba->hbalock);
}
+ /* Make sure HBA is alive */
+ lpfc_issue_hb_tmo(phba);
/* Cancel all the IOCBs from the completions list */
lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
@@ -4359,6 +4386,8 @@ lpfc_sli_brdready_s3(struct lpfc_hba *phba, uint32_t mask)
if (lpfc_readl(phba->HSregaddr, &status))
return 1;
+ phba->hba_flag |= HBA_NEEDS_CFG_PORT;
+
/*
* Check status register every 100ms for 5 retries, then every
* 500ms for 5, then every 2.5 sec for 5, then reset board and
@@ -4687,6 +4716,7 @@ lpfc_sli_brdreset(struct lpfc_hba *phba)
/* perform board reset */
phba->fc_eventTag = 0;
phba->link_events = 0;
+ phba->hba_flag |= HBA_NEEDS_CFG_PORT;
if (phba->pport) {
phba->pport->fc_myDID = 0;
phba->pport->fc_prevDID = 0;
@@ -5020,6 +5050,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
return -EIO;
}
+ phba->hba_flag |= HBA_NEEDS_CFG_PORT;
+
/* Clear all interrupt enable conditions */
writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
@@ -5316,45 +5348,18 @@ int
lpfc_sli_hba_setup(struct lpfc_hba *phba)
{
uint32_t rc;
- int mode = 3, i;
+ int i;
int longs;
- switch (phba->cfg_sli_mode) {
- case 2:
- if (phba->cfg_enable_npiv) {
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "1824 NPIV enabled: Override sli_mode "
- "parameter (%d) to auto (0).\n",
- phba->cfg_sli_mode);
- break;
- }
- mode = 2;
- break;
- case 0:
- case 3:
- break;
- default:
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "1819 Unrecognized sli_mode parameter: %d.\n",
- phba->cfg_sli_mode);
-
- break;
+ /* Enable ISR already does config_port because of config_msi mbx */
+ if (phba->hba_flag & HBA_NEEDS_CFG_PORT) {
+ rc = lpfc_sli_config_port(phba, LPFC_SLI_REV3);
+ if (rc)
+ return -EIO;
+ phba->hba_flag &= ~HBA_NEEDS_CFG_PORT;
}
phba->fcp_embed_io = 0; /* SLI4 FC support only */
- rc = lpfc_sli_config_port(phba, mode);
-
- if (rc && phba->cfg_sli_mode == 3)
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "1820 Unable to select SLI-3. "
- "Not supported by adapter.\n");
- if (rc && mode != 2)
- rc = lpfc_sli_config_port(phba, 2);
- else if (rc && mode == 2)
- rc = lpfc_sli_config_port(phba, 3);
- if (rc)
- goto lpfc_sli_hba_setup_error;
-
/* Enable PCIe device Advanced Error Reporting (AER) if configured */
if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) {
rc = pci_enable_pcie_error_reporting(phba->pcidev);
@@ -7486,7 +7491,7 @@ static void lpfc_sli4_dip(struct lpfc_hba *phba)
return;
if (bf_get(lpfc_sliport_status_dip, &reg_data))
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"2904 Firmware Dump Image Present"
" on Adapter");
}
@@ -8041,7 +8046,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
/* Start heart beat timer */
mod_timer(&phba->hb_tmofunc,
jiffies + msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
- phba->hb_outstanding = 0;
+ phba->hba_flag &= ~(HBA_HBEAT_INP | HBA_HBEAT_TMO);
phba->last_completion_time = jiffies;
/* start eq_delay heartbeat */
@@ -8291,8 +8296,10 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
struct lpfc_sli *psli = &phba->sli;
- /* If the mailbox completed, process the completion and return */
- if (lpfc_sli4_process_missed_mbox_completions(phba))
+ /* If the mailbox completed, process the completion */
+ lpfc_sli4_process_missed_mbox_completions(phba);
+
+ if (!(psli->sli_flag & LPFC_SLI_ACTIVE))
return;
if (pmbox != NULL)
@@ -8333,8 +8340,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
psli->sli_flag &= ~LPFC_SLI_ACTIVE;
spin_unlock_irq(&phba->hbalock);
- lpfc_sli_abort_fcp_rings(phba);
-
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0345 Resetting board due to mailbox timeout\n");
@@ -11215,6 +11220,9 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
}
spin_unlock_irqrestore(&phba->hbalock, flags);
+ /* Make sure HBA is alive */
+ lpfc_issue_hb_tmo(phba);
+
/* Cancel all the IOCBs from the completions list */
lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
IOERR_SLI_DOWN);
@@ -11805,7 +11813,7 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
struct lpfc_io_buf *lpfc_cmd;
int rc = 1;
- if (iocbq->vport != vport)
+ if (!iocbq || iocbq->vport != vport)
return rc;
if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
@@ -13026,7 +13034,21 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
spin_unlock_irqrestore(
&phba->pport->work_port_lock,
iflag);
- lpfc_mbox_cmpl_put(phba, pmb);
+
+ /* Do NOT queue MBX_HEARTBEAT to the worker
+ * thread for processing.
+ */
+ if (pmbox->mbxCommand == MBX_HEARTBEAT) {
+ /* Process mbox now */
+ phba->sli.mbox_active = NULL;
+ phba->sli.sli_flag &=
+ ~LPFC_SLI_MBOX_ACTIVE;
+ if (pmb->mbox_cmpl)
+ pmb->mbox_cmpl(phba, pmb);
+ } else {
+ /* Queue to worker thread to process */
+ lpfc_mbox_cmpl_put(phba, pmb);
+ }
}
} else
spin_unlock_irqrestore(&phba->hbalock, iflag);
@@ -13622,7 +13644,26 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe)
phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags);
- /* There is mailbox completion work to do */
+ /* Do NOT queue MBX_HEARTBEAT to the worker thread for processing. */
+ if (pmbox->mbxCommand == MBX_HEARTBEAT) {
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ /* Release the mailbox command posting token */
+ phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ phba->sli.mbox_active = NULL;
+ if (bf_get(lpfc_trailer_consumed, mcqe))
+ lpfc_sli4_mq_release(phba->sli4_hba.mbx_wq);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+ /* Post the next mbox command, if there is one */
+ lpfc_sli4_post_async_mbox(phba);
+
+ /* Process cmpl now */
+ if (pmb->mbox_cmpl)
+ pmb->mbox_cmpl(phba, pmb);
+ return false;
+ }
+
+ /* There is mailbox completion work to queue to the worker thread */
spin_lock_irqsave(&phba->hbalock, iflags);
__lpfc_mbox_cmpl_put(phba, pmb);
phba->work_ha |= HA_MBATT;