case CMD_IOCB_RCV_SEQ64_CX:
case CMD_IOCB_RCV_ELS64_CX:
case CMD_IOCB_RCV_CONT64_CX:
+ case CMD_IOCB_RET_XRI64_CX:
type = LPFC_UNSOL_IOCB;
break;
+ case CMD_IOCB_XMIT_MSEQ64_CR:
+ case CMD_IOCB_XMIT_MSEQ64_CX:
+ case CMD_IOCB_RCV_SEQ_LIST64_CX:
+ case CMD_IOCB_RCV_ELS_LIST64_CX:
+ case CMD_IOCB_CLOSE_EXTENDED_CN:
+ case CMD_IOCB_ABORT_EXTENDED_CN:
+ case CMD_IOCB_RET_HBQE64_CN:
+ case CMD_IOCB_FCP_IBIDIR64_CR:
+ case CMD_IOCB_FCP_IBIDIR64_CX:
+ case CMD_IOCB_FCP_ITASKMGT64_CX:
+ case CMD_IOCB_LOGENTRY_CN:
+ case CMD_IOCB_LOGENTRY_ASYNC_CN:
+ printk("%s - Unhandled SLI-3 Command x%x\n",
+ __FUNCTION__, iocb_cmnd);
+ type = LPFC_UNKNOWN_IOCB;
+ break;
default:
type = LPFC_UNKNOWN_IOCB;
break;
phba->work_ha |= HA_ERATT;
phba->work_hs = HS_FFER3;
- /* hbalock should already be held */
- if (phba->work_wait)
- lpfc_worker_wake_up(phba);
+ lpfc_worker_wake_up(phba);
return NULL;
}
{
struct lpfc_dmabuf *dmabuf, *next_dmabuf;
struct hbq_dmabuf *hbq_buf;
+ unsigned long flags;
int i, hbq_count;
+ uint32_t hbqno;
hbq_count = lpfc_sli_hbq_count();
/* Return all memory used by all HBQs */
+ spin_lock_irqsave(&phba->hbalock, flags);
for (i = 0; i < hbq_count; ++i) {
list_for_each_entry_safe(dmabuf, next_dmabuf,
&phba->hbqs[i].hbq_buffer_list, list) {
}
phba->hbqs[i].buffer_count = 0;
}
+ /* Return all HBQ buffer that are in-fly */
+ list_for_each_entry_safe(dmabuf, next_dmabuf,
+ &phba->hbqbuf_in_list, list) {
+ hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf);
+ list_del(&hbq_buf->dbuf.list);
+ if (hbq_buf->tag == -1) {
+ (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer)
+ (phba, hbq_buf);
+ } else {
+ hbqno = hbq_buf->tag >> 16;
+ if (hbqno >= LPFC_MAX_HBQS)
+ (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer)
+ (phba, hbq_buf);
+ else
+ (phba->hbqs[hbqno].hbq_free_buffer)(phba,
+ hbq_buf);
+ }
+ }
+
+ /* Mark the HBQs not in use */
+ phba->hbq_in_use = 0;
+ spin_unlock_irqrestore(&phba->hbalock, flags);
}
static struct lpfc_hbq_entry *
lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
{
uint32_t i, start, end;
+ unsigned long flags;
struct hbq_dmabuf *hbq_buffer;
- if (!phba->hbqs[hbqno].hbq_alloc_buffer) {
+ if (!phba->hbqs[hbqno].hbq_alloc_buffer)
return 0;
- }
start = phba->hbqs[hbqno].buffer_count;
end = count + start;
- if (end > lpfc_hbq_defs[hbqno]->entry_count) {
+ if (end > lpfc_hbq_defs[hbqno]->entry_count)
end = lpfc_hbq_defs[hbqno]->entry_count;
- }
+
+ /* Check whether HBQ is still in use */
+ spin_lock_irqsave(&phba->hbalock, flags);
+ if (!phba->hbq_in_use)
+ goto out;
/* Populate HBQ entries */
for (i = start; i < end; i++) {
hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
if (!hbq_buffer)
- return 1;
+ goto err;
hbq_buffer->tag = (i | (hbqno << 16));
if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer))
phba->hbqs[hbqno].buffer_count++;
else
(phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
}
+
+ out:
+ spin_unlock_irqrestore(&phba->hbalock, flags);
return 0;
+ err:
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ return 1;
}
int
uint32_t hbqno;
void *virt; /* virtual address ptr */
dma_addr_t phys; /* mapped address */
+ unsigned long flags;
+
+ /* Check whether HBQ is still in use */
+ spin_lock_irqsave(&phba->hbalock, flags);
+ if (!phba->hbq_in_use) {
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ return NULL;
+ }
hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
- if (hbq_entry == NULL)
+ if (hbq_entry == NULL) {
+ spin_unlock_irqrestore(&phba->hbalock, flags);
return NULL;
+ }
list_del(&hbq_entry->dbuf.list);
hbqno = tag >> 16;
new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
- if (new_hbq_entry == NULL)
+ if (new_hbq_entry == NULL) {
+ list_add_tail(&hbq_entry->dbuf.list, &phba->hbqbuf_in_list);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
return &hbq_entry->dbuf;
+ }
new_hbq_entry->tag = -1;
phys = new_hbq_entry->dbuf.phys;
virt = new_hbq_entry->dbuf.virt;
hbq_entry->dbuf.phys = phys;
hbq_entry->dbuf.virt = virt;
lpfc_sli_free_hbq(phba, hbq_entry);
+ list_add_tail(&new_hbq_entry->dbuf.list, &phba->hbqbuf_in_list);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+
return &new_hbq_entry->dbuf;
}
uint32_t Rctl, Type;
uint32_t match, i;
struct lpfc_iocbq *iocbq;
+ struct lpfc_dmabuf *dmzbuf;
match = 0;
irsp = &(saveq->iocb);
return 1;
}
+ if ((irsp->ulpCommand == CMD_IOCB_RET_XRI64_CX) &&
+ (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) {
+ if (irsp->ulpBdeCount > 0) {
+ dmzbuf = lpfc_sli_get_buff(phba, pring,
+ irsp->un.ulpWord[3]);
+ lpfc_in_buf_free(phba, dmzbuf);
+ }
+
+ if (irsp->ulpBdeCount > 1) {
+ dmzbuf = lpfc_sli_get_buff(phba, pring,
+ irsp->unsli3.sli3Words[3]);
+ lpfc_in_buf_free(phba, dmzbuf);
+ }
+
+ if (irsp->ulpBdeCount > 2) {
+ dmzbuf = lpfc_sli_get_buff(phba, pring,
+ irsp->unsli3.sli3Words[7]);
+ lpfc_in_buf_free(phba, dmzbuf);
+ }
+
+ return 1;
+ }
+
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
if (irsp->ulpBdeCount != 0) {
saveq->context2 = lpfc_sli_get_buff(phba, pring,
phba->work_ha |= HA_ERATT;
phba->work_hs = HS_FFER3;
- /* hbalock should already be held */
- if (phba->work_wait)
- lpfc_worker_wake_up(phba);
+ lpfc_worker_wake_up(phba);
return;
}
/* Initialize the struct lpfc_sli_hbq structure for each hbq */
phba->link_state = LPFC_INIT_MBX_CMDS;
+ phba->hbq_in_use = 1;
hbq_entry_index = 0;
for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
phba->pport->work_port_events |= WORKER_MBOX_TMO;
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
- if (!tmo_posted) {
- spin_lock_irqsave(&phba->hbalock, iflag);
- if (phba->work_wait)
- lpfc_worker_wake_up(phba);
- spin_unlock_irqrestore(&phba->hbalock, iflag);
- }
+ if (!tmo_posted)
+ lpfc_worker_wake_up(phba);
+ return;
}
void
spin_unlock_irq(&phba->pport->work_port_lock);
spin_lock_irq(&phba->hbalock);
phba->link_state = LPFC_LINK_UNKNOWN;
- phba->pport->fc_flag |= FC_ESTABLISH_LINK;
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock);
lpfc_offline_prep(phba);
lpfc_offline(phba);
lpfc_sli_brdrestart(phba);
- if (lpfc_online(phba) == 0) /* Initialize the HBA */
- mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+ lpfc_online(phba);
lpfc_unblock_mgmt_io(phba);
return;
}
unsigned long drvr_flag = 0;
volatile uint32_t word0, ldata;
void __iomem *to_slim;
+ int processing_queue = 0;
+
+ spin_lock_irqsave(&phba->hbalock, drvr_flag);
+ if (!pmbox) {
+ /* processing mbox queue from intr_handler */
+ processing_queue = 1;
+ phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ pmbox = lpfc_mbox_get(phba);
+ if (!pmbox) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ return MBX_SUCCESS;
+ }
+ }
if (pmbox->mbox_cmpl && pmbox->mbox_cmpl != lpfc_sli_def_mbox_cmpl &&
pmbox->mbox_cmpl != lpfc_sli_wake_mbox_wait) {
if(!pmbox->vport) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
lpfc_printf_log(phba, KERN_ERR,
LOG_MBOX | LOG_VPORT,
"1806 Mbox x%x failed. No vport\n",
pmbox->mb.mbxCommand);
dump_stack();
- return MBX_NOT_FINISHED;
+ goto out_not_finished;
}
}
-
/* If the PCI channel is in offline state, do not post mbox. */
- if (unlikely(pci_channel_offline(phba->pcidev)))
- return MBX_NOT_FINISHED;
+ if (unlikely(pci_channel_offline(phba->pcidev))) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ goto out_not_finished;
+ }
- spin_lock_irqsave(&phba->hbalock, drvr_flag);
psli = &phba->sli;
-
mb = &pmbox->mb;
status = MBX_SUCCESS;
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
- return MBX_NOT_FINISHED;
+ goto out_not_finished;
}
if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
!(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
- return MBX_NOT_FINISHED;
+ goto out_not_finished;
}
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
- return MBX_NOT_FINISHED;
+ goto out_not_finished;
}
if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
- return MBX_NOT_FINISHED;
+ goto out_not_finished;
}
/* Another mailbox command is still being processed, queue this
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
- return MBX_NOT_FINISHED;
+ goto out_not_finished;
}
/* timeout active mbox command */
mod_timer(&psli->mbox_tmo, (jiffies +
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(&phba->hbalock,
drvr_flag);
- return MBX_NOT_FINISHED;
+ goto out_not_finished;
}
/* Check if we took a mbox interrupt while we were
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
return status;
+
+out_not_finished:
+ if (processing_queue) {
+ pmbox->mb.mbxStatus = MBX_NOT_FINISHED;
+ lpfc_mbox_cmpl_put(phba, pmbox);
+ }
+ return MBX_NOT_FINISHED;
}
/*
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
prev_pring_flag = pring->flag;
- if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
+ /* Only slow rings */
+ if (pring->ringno == LPFC_ELS_RING) {
pring->flag |= LPFC_DEFERRED_RING_EVENT;
+ /* Set the lpfc data pending flag */
+ set_bit(LPFC_DATA_READY, &phba->data_flags);
+ }
/*
* Error everything on the txq since these iocbs have not been
* given to the FW yet.
spin_lock_irqsave(&phba->hbalock, flags);
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
- if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
+ /* Only slow rings */
+ if (pring->ringno == LPFC_ELS_RING) {
pring->flag |= LPFC_DEFERRED_RING_EVENT;
+ /* Set the lpfc data pending flag */
+ set_bit(LPFC_DATA_READY, &phba->data_flags);
+ }
/*
* Error everything on the txq since these iocbs have not been
phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
spin_unlock(&phba->pport->work_port_lock);
+ /* Return any pending or completed mbox cmds */
+ list_splice_init(&phba->sli.mboxq, &completions);
if (psli->mbox_active) {
list_add_tail(&psli->mbox_active->list, &completions);
psli->mbox_active = NULL;
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
}
-
- /* Return any pending or completed mbox cmds */
- list_splice_init(&phba->sli.mboxq, &completions);
list_splice_init(&phba->sli.mboxq_cmpl, &completions);
- INIT_LIST_HEAD(&psli->mboxq);
- INIT_LIST_HEAD(&psli->mboxq_cmpl);
-
spin_unlock_irqrestore(&phba->hbalock, flags);
while (!list_empty(&completions)) {
list_remove_head(&completions, pmb, LPFC_MBOXQ_t, list);
pmb->mb.mbxStatus = MBX_NOT_FINISHED;
- if (pmb->mbox_cmpl) {
+ if (pmb->mbox_cmpl)
pmb->mbox_cmpl(phba,pmb);
- }
}
return 1;
}
abort_iocb, abort_iotag, abort_context,
irsp->ulpStatus, irsp->un.ulpWord[4]);
+ /*
+ * If the iocb is not found in Firmware queue the iocb
+ * might have completed already. Do not free it again.
+ */
+ if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
+ spin_unlock_irq(&phba->hbalock);
+ lpfc_sli_release_iocbq(phba, cmdiocb);
+ return;
+ }
/*
* make sure we have the right iocbq before taking it
* off the txcmplq and try to call completion routine.
"pwork:x%x hawork:x%x wait:x%x",
phba->work_ha, work_ha_copy,
(uint32_t)((unsigned long)
- phba->work_wait));
+ &phba->work_waitq));
control &=
~(HC_R0INT_ENA << LPFC_ELS_RING);
"x%x hawork:x%x wait:x%x",
phba->work_ha, work_ha_copy,
(uint32_t)((unsigned long)
- phba->work_wait));
+ &phba->work_waitq));
}
spin_unlock(&phba->hbalock);
}
phba->pport->stopped = 1;
}
+ spin_lock(&phba->hbalock);
if ((work_ha_copy & HA_MBATT) &&
(phba->sli.mbox_active)) {
pmb = phba->sli.mbox_active;
/* First check out the status word */
lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
if (pmbox->mbxOwner != OWN_HOST) {
+ spin_unlock(&phba->hbalock);
/*
* Stray Mailbox Interrupt, mbxCommand <cmd>
* mbxStatus <status>
/* clear mailbox attention bit */
work_ha_copy &= ~HA_MBATT;
} else {
+ phba->sli.mbox_active = NULL;
+ spin_unlock(&phba->hbalock);
phba->last_completion_time = jiffies;
del_timer(&phba->sli.mbox_tmo);
-
- phba->sli.mbox_active = NULL;
if (pmb->mbox_cmpl) {
lpfc_sli_pcimem_bcopy(mbox, pmbox,
MAILBOX_CMD_SIZE);
pmb->context1 = mp;
pmb->context2 = ndlp;
pmb->vport = vport;
- spin_lock(&phba->hbalock);
- phba->sli.sli_flag &=
- ~LPFC_SLI_MBOX_ACTIVE;
- spin_unlock(&phba->hbalock);
+ rc = lpfc_sli_issue_mbox(phba,
+ pmb,
+ MBX_NOWAIT);
+ if (rc != MBX_BUSY)
+ lpfc_printf_log(phba,
+ KERN_ERR,
+ LOG_MBOX | LOG_SLI,
+ "0306 rc should have"
+ "been MBX_BUSY");
goto send_current_mbox;
}
}
spin_unlock(&phba->pport->work_port_lock);
lpfc_mbox_cmpl_put(phba, pmb);
}
- }
+ } else
+ spin_unlock(&phba->hbalock);
if ((work_ha_copy & HA_MBATT) &&
(phba->sli.mbox_active == NULL)) {
-send_next_mbox:
- spin_lock(&phba->hbalock);
- phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
- pmb = lpfc_mbox_get(phba);
- spin_unlock(&phba->hbalock);
send_current_mbox:
/* Process next mailbox command if there is one */
- if (pmb != NULL) {
- rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
- if (rc == MBX_NOT_FINISHED) {
- pmb->mb.mbxStatus = MBX_NOT_FINISHED;
- lpfc_mbox_cmpl_put(phba, pmb);
- goto send_next_mbox;
- }
- }
-
+ do {
+ rc = lpfc_sli_issue_mbox(phba, NULL,
+ MBX_NOWAIT);
+ } while (rc == MBX_NOT_FINISHED);
+ if (rc != MBX_SUCCESS)
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
+ LOG_SLI, "0349 rc should be "
+ "MBX_SUCCESS");
}
spin_lock(&phba->hbalock);
phba->work_ha |= work_ha_copy;
- if (phba->work_wait)
- lpfc_worker_wake_up(phba);
spin_unlock(&phba->hbalock);
+ lpfc_worker_wake_up(phba);
}
ha_copy &= ~(phba->work_ha_mask);