return -EIO;
}
data_length = mqe->un.mb_words[5];
- if (data_length > DMP_FCOEPARAM_RGN_SIZE)
+ if (data_length > DMP_RGN23_SIZE) {
+ lpfc_mbuf_free(phba, mp->virt, mp->phys);
+ kfree(mp);
return -EIO;
+ }
lpfc_parse_fcoe_conf(phba, mp->virt, data_length);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
return -EIO;
}
- lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "(%d):0380 Mailbox cmd x%x Status x%x "
- "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x "
- "x%x x%x x%x x%x x%x x%x x%x x%x x%x "
- "CQ: x%x x%x x%x x%x\n",
- mboxq->vport ? mboxq->vport->vpi : 0,
- bf_get(lpfc_mqe_command, mqe),
- bf_get(lpfc_mqe_status, mqe),
- mqe->un.mb_words[0], mqe->un.mb_words[1],
- mqe->un.mb_words[2], mqe->un.mb_words[3],
- mqe->un.mb_words[4], mqe->un.mb_words[5],
- mqe->un.mb_words[6], mqe->un.mb_words[7],
- mqe->un.mb_words[8], mqe->un.mb_words[9],
- mqe->un.mb_words[10], mqe->un.mb_words[11],
- mqe->un.mb_words[12], mqe->un.mb_words[13],
- mqe->un.mb_words[14], mqe->un.mb_words[15],
- mqe->un.mb_words[16], mqe->un.mb_words[50],
- mboxq->mcqe.word0,
- mboxq->mcqe.mcqe_tag0, mboxq->mcqe.mcqe_tag1,
- mboxq->mcqe.trailer);
-
/*
* The available vpd length cannot be bigger than the
* DMA buffer passed to the port. Catch the less than
goto out_free_vpd;
mqe = &mboxq->u.mqe;
- if ((bf_get(lpfc_mbx_rd_rev_sli_lvl,
- &mqe->un.read_rev) != LPFC_SLI_REV4) ||
- (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev) == 0)) {
+ phba->sli_rev = bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev);
+ if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev))
+ phba->hba_flag |= HBA_FCOE_SUPPORT;
+ if (phba->sli_rev != LPFC_SLI_REV4 ||
+ !(phba->hba_flag & HBA_FCOE_SUPPORT)) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"0376 READ_REV Error. SLI Level %d "
"FCoE enabled %d\n",
- bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev),
- bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev));
+ phba->sli_rev, phba->hba_flag & HBA_FCOE_SUPPORT);
rc = -EIO;
goto out_free_vpd;
}
- /* Single threaded at this point, no need for lock */
- spin_lock_irq(&phba->hbalock);
- phba->hba_flag |= HBA_FCOE_SUPPORT;
- spin_unlock_irq(&phba->hbalock);
/*
* Evaluate the read rev and vpd data. Populate the driver
* state with the results. If this routine fails, the failure
rc = 0;
}
- /* By now, we should determine the SLI revision, hard code for now */
- phba->sli_rev = LPFC_SLI_REV4;
+ /* Save information as VPD data */
+ phba->vpd.rev.biuRev = mqe->un.read_rev.first_hw_rev;
+ phba->vpd.rev.smRev = mqe->un.read_rev.second_hw_rev;
+ phba->vpd.rev.endecRev = mqe->un.read_rev.third_hw_rev;
+ phba->vpd.rev.fcphHigh = bf_get(lpfc_mbx_rd_rev_fcph_high,
+ &mqe->un.read_rev);
+ phba->vpd.rev.fcphLow = bf_get(lpfc_mbx_rd_rev_fcph_low,
+ &mqe->un.read_rev);
+ phba->vpd.rev.feaLevelHigh = bf_get(lpfc_mbx_rd_rev_ftr_lvl_high,
+ &mqe->un.read_rev);
+ phba->vpd.rev.feaLevelLow = bf_get(lpfc_mbx_rd_rev_ftr_lvl_low,
+ &mqe->un.read_rev);
+ phba->vpd.rev.sli1FwRev = mqe->un.read_rev.fw_id_rev;
+ memcpy(phba->vpd.rev.sli1FwName, mqe->un.read_rev.fw_name, 16);
+ phba->vpd.rev.sli2FwRev = mqe->un.read_rev.ulp_fw_id_rev;
+ memcpy(phba->vpd.rev.sli2FwName, mqe->un.read_rev.ulp_fw_name, 16);
+ phba->vpd.rev.opFwRev = mqe->un.read_rev.fw_id_rev;
+ memcpy(phba->vpd.rev.opFwName, mqe->un.read_rev.fw_name, 16);
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+ "(%d):0380 READ_REV Status x%x "
+ "fw_rev:%s fcphHi:%x fcphLo:%x flHi:%x flLo:%x\n",
+ mboxq->vport ? mboxq->vport->vpi : 0,
+ bf_get(lpfc_mqe_status, mqe),
+ phba->vpd.rev.opFwName,
+ phba->vpd.rev.fcphHigh, phba->vpd.rev.fcphLow,
+ phba->vpd.rev.feaLevelHigh, phba->vpd.rev.feaLevelLow);
/*
* Discover the port's supported feature set and match it against the
rc = -ENODEV;
goto out_free_vpd;
}
- /* Temporary initialization of lpfc_fip_flag to non-fip */
- bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 0);
+ if (phba->cfg_enable_fip)
+ bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 1);
+ else
+ bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 0);
/* Set up all the queues to the device */
rc = lpfc_sli4_queue_setup(phba);
lpfc_sli4_rb_setup(phba);
/* Start the ELS watchdog timer */
- /*
- * The driver for SLI4 is not yet ready to process timeouts
- * or interrupts. Once it is, the comment bars can be removed.
- */
- /* mod_timer(&vport->els_tmofunc,
- * jiffies + HZ * (phba->fc_ratov*2)); */
+ mod_timer(&vport->els_tmofunc,
+ jiffies + HZ * (phba->fc_ratov * 2));
/* Start heart beat timer */
mod_timer(&phba->hb_tmofunc,
spin_lock_irqsave(&phba->hbalock, drvr_flag);
if (!pmbox) {
+ phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
/* processing mbox queue from intr_handler */
if (unlikely(psli->sli_flag & LPFC_SLI_ASYNC_MBX_BLK)) {
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
return MBX_SUCCESS;
}
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_NOT_FINISHED;
}
+/**
+ * lpfc_sli4_async_mbox_block - Block posting SLI4 asynchronous mailbox command
+ * @phba: Pointer to HBA context object.
+ *
+ * The function blocks the posting of SLI4 asynchronous mailbox commands from
+ * the driver internal pending mailbox queue. It will then try to wait out the
+ * possible outstanding mailbox command before return.
+ *
+ * Returns:
+ * 0 - the outstanding mailbox command completed; otherwise, the wait for
+ * the outstanding mailbox command timed out.
+ **/
+static int
+lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
+{
+ struct lpfc_sli *psli = &phba->sli;
+ uint8_t actcmd = MBX_HEARTBEAT;
+ int rc = 0;
+ unsigned long timeout;
+
+ /* Mark the asynchronous mailbox command posting as blocked */
+ spin_lock_irq(&phba->hbalock);
+ psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK;
+ if (phba->sli.mbox_active)
+ actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
+ spin_unlock_irq(&phba->hbalock);
+ /* Determine how long we might wait for the active mailbox
+ * command to be gracefully completed by firmware.
+ */
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) +
+ jiffies;
+ /* Wait for the outstnading mailbox command to complete */
+ while (phba->sli.mbox_active) {
+ /* Check active mailbox complete status every 2ms */
+ msleep(2);
+ if (time_after(jiffies, timeout)) {
+ /* Timeout, marked the outstanding cmd not complete */
+ rc = 1;
+ break;
+ }
+ }
+
+ /* Can not cleanly block async mailbox command, fails it */
+ if (rc) {
+ spin_lock_irq(&phba->hbalock);
+ psli->sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
+ spin_unlock_irq(&phba->hbalock);
+ }
+ return rc;
+}
+
+/**
+ * lpfc_sli4_async_mbox_unblock - Block posting SLI4 async mailbox command
+ * @phba: Pointer to HBA context object.
+ *
+ * The function unblocks and resume posting of SLI4 asynchronous mailbox
+ * commands from the driver internal pending mailbox queue. It makes sure
+ * that there is no outstanding mailbox command before resuming posting
+ * asynchronous mailbox commands. If, for any reason, there is outstanding
+ * mailbox command, it will try to wait it out before resuming asynchronous
+ * mailbox command posting.
+ **/
+static void
+lpfc_sli4_async_mbox_unblock(struct lpfc_hba *phba)
+{
+ struct lpfc_sli *psli = &phba->sli;
+
+ spin_lock_irq(&phba->hbalock);
+ if (!(psli->sli_flag & LPFC_SLI_ASYNC_MBX_BLK)) {
+ /* Asynchronous mailbox posting is not blocked, do nothing */
+ spin_unlock_irq(&phba->hbalock);
+ return;
+ }
+
+ /* Outstanding synchronous mailbox command is guaranteed to be done,
+ * successful or timeout, after timing-out the outstanding mailbox
+ * command shall always be removed, so just unblock posting async
+ * mailbox command and resume
+ */
+ psli->sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
+ spin_unlock_irq(&phba->hbalock);
+
+ /* wake up worker thread to post asynchronlous mailbox command */
+ lpfc_worker_wake_up(phba);
+}
+
/**
* lpfc_sli4_post_sync_mbox - Post an SLI4 mailbox to the bootstrap mailbox
* @phba: Pointer to HBA context object.
unsigned long iflags;
int rc;
+ rc = lpfc_mbox_dev_check(phba);
+ if (unlikely(rc)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ "(%d):2544 Mailbox command x%x (x%x) "
+ "cannot issue Data: x%x x%x\n",
+ mboxq->vport ? mboxq->vport->vpi : 0,
+ mboxq->u.mb.mbxCommand,
+ lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ psli->sli_flag, flag);
+ goto out_not_finished;
+ }
+
/* Detect polling mode and jump to a handler */
if (!phba->sli4_hba.intr_enable) {
if (flag == MBX_POLL)
psli->sli_flag, flag);
return rc;
} else if (flag == MBX_POLL) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2542 Mailbox command x%x (x%x) "
- "cannot issue Data: x%x x%x\n",
+ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+ "(%d):2542 Try to issue mailbox command "
+ "x%x (x%x) synchronously ahead of async"
+ "mailbox command queue: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
lpfc_sli4_mbox_opcode_get(phba, mboxq),
psli->sli_flag, flag);
- return -EIO;
+ /* Try to block the asynchronous mailbox posting */
+ rc = lpfc_sli4_async_mbox_block(phba);
+ if (!rc) {
+ /* Successfully blocked, now issue sync mbox cmd */
+ rc = lpfc_sli4_post_sync_mbox(phba, mboxq);
+ if (rc != MBX_SUCCESS)
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_MBOX | LOG_SLI,
+ "(%d):2597 Mailbox command "
+ "x%x (x%x) cannot issue "
+ "Data: x%x x%x\n",
+ mboxq->vport ?
+ mboxq->vport->vpi : 0,
+ mboxq->u.mb.mbxCommand,
+ lpfc_sli4_mbox_opcode_get(phba,
+ mboxq),
+ psli->sli_flag, flag);
+ /* Unblock the async mailbox posting afterward */
+ lpfc_sli4_async_mbox_unblock(phba);
+ }
+ return rc;
}
/* Now, interrupt mode asynchrous mailbox command */
psli->sli_flag, flag);
goto out_not_finished;
}
- rc = lpfc_mbox_dev_check(phba);
- if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2544 Mailbox command x%x (x%x) "
- "cannot issue Data: x%x x%x\n",
- mboxq->vport ? mboxq->vport->vpi : 0,
- mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
- psli->sli_flag, flag);
- goto out_not_finished;
- }
/* Put the mailbox command to the driver internal FIFO */
psli->slistat.mbox_busy++;
/**
* lpfc_sli4_scmd_to_wqidx_distr - scsi command to SLI4 WQ index distribution
* @phba: Pointer to HBA context object.
- * @piocb: Pointer to command iocb.
*
* This routine performs a round robin SCSI command to SLI4 FCP WQ index
- * distribution.
+ * distribution. This is called by __lpfc_sli_issue_iocb_s4() with the hbalock
+ * held.
*
* Return: index into SLI4 fast-path FCP queue index.
**/
static uint32_t
-lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba, struct lpfc_iocbq *piocb)
+lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba)
{
- static uint32_t fcp_qidx;
+ ++phba->fcp_qidx;
+ if (phba->fcp_qidx >= phba->cfg_fcp_wq_count)
+ phba->fcp_qidx = 0;
- return fcp_qidx++ % phba->cfg_fcp_wq_count;
+ return phba->fcp_qidx;
}
/**
fip = bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags);
/* The fcp commands will set command type */
- if ((!(iocbq->iocb_flag & LPFC_IO_FCP)) && (!fip))
- command_type = ELS_COMMAND_NON_FIP;
- else if (!(iocbq->iocb_flag & LPFC_IO_FCP))
- command_type = ELS_COMMAND_FIP;
- else if (iocbq->iocb_flag & LPFC_IO_FCP)
+ if (iocbq->iocb_flag & LPFC_IO_FCP)
command_type = FCP_COMMAND;
- else {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2019 Invalid cmd 0x%x\n",
- iocbq->iocb.ulpCommand);
- return IOCB_ERROR;
- }
+ else if (fip && (iocbq->iocb_flag & LPFC_FIP_ELS))
+ command_type = ELS_COMMAND_FIP;
+ else
+ command_type = ELS_COMMAND_NON_FIP;
+
/* Some of the fields are in the right position already */
memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe));
abort_tag = (uint32_t) iocbq->iotag;
bf_set(lpfc_wqe_gen_context, &wqe->generic,
iocbq->iocb.ulpContext);
- if (iocbq->vport->fc_myDID != 0) {
- bf_set(els_req64_sid, &wqe->els_req,
- iocbq->vport->fc_myDID);
- bf_set(els_req64_sp, &wqe->els_req, 1);
- }
bf_set(lpfc_wqe_gen_ct, &wqe->generic, ct);
bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0);
/* CCP CCPE PV PRI in word10 were set in the memcpy */
* is set and we are sending our 2nd or greater command on
* this exchange.
*/
+ /* Always open the exchange */
+ bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0);
- /* ALLOW read & write to fall through to ICMD64 */
+ wqe->words[10] &= 0xffff0000; /* zero out ebde count */
+ bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU);
+ break;
case CMD_FCP_ICMND64_CR:
/* Always open the exchange */
bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0);
+ wqe->words[4] = 0;
wqe->words[10] &= 0xffff0000; /* zero out ebde count */
- bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU);
+ bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0);
break;
case CMD_GEN_REQUEST64_CR:
/* word3 command length is described as byte offset to the
return IOCB_ERROR;
if (piocb->iocb_flag & LPFC_IO_FCP) {
- fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba, piocb);
+ fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba);
if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[fcp_wqidx], &wqe))
return IOCB_ERROR;
} else {
}
+/**
+ * lpfc_sli_bemem_bcopy - SLI memory copy function
+ * @srcp: Source memory pointer.
+ * @destp: Destination memory pointer.
+ * @cnt: Number of words required to be copied.
+ *
+ * This function is used for copying data between a data structure
+ * with big endian representation to local endianness.
+ * This function can be called with or without lock.
+ **/
+void
+lpfc_sli_bemem_bcopy(void *srcp, void *destp, uint32_t cnt)
+{
+ uint32_t *src = srcp;
+ uint32_t *dest = destp;
+ uint32_t ldata;
+ int i;
+
+ for (i = 0; i < (int)cnt; i += sizeof(uint32_t)) {
+ ldata = *src;
+ ldata = be32_to_cpu(ldata);
+ *dest = ldata;
+ src++;
+ dest++;
+ }
+}
+
/**
* lpfc_sli_ringpostbuf_put - Function to add a buffer to postbufq
* @phba: Pointer to HBA context object.
return;
}
+/**
+ * lpfc_chk_iocb_flg - Test IOCB flag with lock held.
+ * @phba: Pointer to HBA context object..
+ * @piocbq: Pointer to command iocb.
+ * @flag: Flag to test.
+ *
+ * This routine grabs the hbalock and then test the iocb_flag to
+ * see if the passed in flag is set.
+ * Returns:
+ * 1 if flag is set.
+ * 0 if flag is not set.
+ **/
+static int
+lpfc_chk_iocb_flg(struct lpfc_hba *phba,
+ struct lpfc_iocbq *piocbq, uint32_t flag)
+{
+ unsigned long iflags;
+ int ret;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ ret = piocbq->iocb_flag & flag;
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return ret;
+
+}
+
/**
* lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands
* @phba: Pointer to HBA context object..
if (retval == IOCB_SUCCESS) {
timeout_req = timeout * HZ;
timeleft = wait_event_timeout(done_q,
- piocb->iocb_flag & LPFC_IO_WAKE,
+ lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE),
timeout_req);
if (piocb->iocb_flag & LPFC_IO_WAKE) {
if ((HS_FFER1 & phba->work_hs) &&
((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
HS_FFER6 | HS_FFER7) & phba->work_hs)) {
- spin_lock_irq(&phba->hbalock);
phba->hba_flag |= DEFER_ERATT;
- spin_unlock_irq(&phba->hbalock);
/* Clear all interrupt enable conditions */
writel(0, phba->HCregaddr);
readl(phba->HCregaddr);
}
/* Set the driver HA work bitmap */
- spin_lock_irq(&phba->hbalock);
phba->work_ha |= HA_ERATT;
/* Indicate polling handles this ERATT */
phba->hba_flag |= HBA_ERATT_HANDLED;
- spin_unlock_irq(&phba->hbalock);
return 1;
}
return 0;
"online0_reg=0x%x, online1_reg=0x%x\n",
uerr_sta_lo, uerr_sta_hi,
onlnreg0, onlnreg1);
- /* TEMP: as the driver error recover logic is not
- * fully developed, we just log the error message
- * and the device error attention action is now
- * temporarily disabled.
- */
- return 0;
phba->work_status[0] = uerr_sta_lo;
phba->work_status[1] = uerr_sta_hi;
- spin_lock_irq(&phba->hbalock);
/* Set the driver HA work bitmap */
phba->work_ha |= HA_ERATT;
/* Indicate polling handles this ERATT */
phba->hba_flag |= HBA_ERATT_HANDLED;
- spin_unlock_irq(&phba->hbalock);
return 1;
}
}
kfree(dmabuf);
goto out_fail;
}
+ memset(dmabuf->virt, 0, PAGE_SIZE);
dmabuf->buffer_tag = x;
list_add_tail(&dmabuf->list, &queue->page_list);
/* initialize queue's entry array */
eq->host_index = 0;
eq->hba_index = 0;
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, phba->mbox_mem_pool);
+ mempool_free(mbox, phba->mbox_mem_pool);
return status;
}
cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response);
cq->host_index = 0;
cq->hba_index = 0;
-out:
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, phba->mbox_mem_pool);
+out:
+ mempool_free(mbox, phba->mbox_mem_pool);
return status;
}
/* link the mq onto the parent cq child list */
list_add_tail(&mq->list, &cq->child_list);
out:
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, phba->mbox_mem_pool);
+ mempool_free(mbox, phba->mbox_mem_pool);
return status;
}
/* link the wq onto the parent cq child list */
list_add_tail(&wq->list, &cq->child_list);
out:
- if (rc == MBX_TIMEOUT)
- mempool_free(mbox, phba->mbox_mem_pool);
+ mempool_free(mbox, phba->mbox_mem_pool);
return status;
}
list_add_tail(&drq->list, &cq->child_list);
out:
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, phba->mbox_mem_pool);
+ mempool_free(mbox, phba->mbox_mem_pool);
return status;
}
/* Remove eq from any list */
list_del_init(&eq->list);
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, eq->phba->mbox_mem_pool);
+ mempool_free(mbox, eq->phba->mbox_mem_pool);
return status;
}
}
/* Remove cq from any list */
list_del_init(&cq->list);
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, cq->phba->mbox_mem_pool);
+ mempool_free(mbox, cq->phba->mbox_mem_pool);
return status;
}
}
/* Remove mq from any list */
list_del_init(&mq->list);
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, mq->phba->mbox_mem_pool);
+ mempool_free(mbox, mq->phba->mbox_mem_pool);
return status;
}
}
/* Remove wq from any list */
list_del_init(&wq->list);
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, wq->phba->mbox_mem_pool);
+ mempool_free(mbox, wq->phba->mbox_mem_pool);
return status;
}
}
list_del_init(&hrq->list);
list_del_init(&drq->list);
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, hrq->phba->mbox_mem_pool);
+ mempool_free(mbox, hrq->phba->mbox_mem_pool);
return status;
}
first_iocbq = lpfc_sli_get_iocbq(vport->phba);
if (first_iocbq) {
/* Initialize the first IOCB. */
+ first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0;
first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS;
first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX;
first_iocbq->iocb.ulpContext = be16_to_cpu(fc_hdr->fh_ox_id);
first_iocbq->iocb.un.cont64[0].tus.f.bdeSize =
LPFC_DATA_BUF_SIZE;
first_iocbq->iocb.un.rcvels.remoteID = sid;
+ first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
+ bf_get(lpfc_rcqe_length, &seq_dmabuf->rcqe);
}
iocbq = first_iocbq;
/*
iocbq->iocb.ulpBdeCount++;
iocbq->iocb.unsli3.rcvsli3.bde2.tus.f.bdeSize =
LPFC_DATA_BUF_SIZE;
+ first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
+ bf_get(lpfc_rcqe_length, &seq_dmabuf->rcqe);
} else {
iocbq = lpfc_sli_get_iocbq(vport->phba);
if (!iocbq) {
iocbq->iocb.ulpBdeCount = 1;
iocbq->iocb.un.cont64[0].tus.f.bdeSize =
LPFC_DATA_BUF_SIZE;
+ first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
+ bf_get(lpfc_rcqe_length, &seq_dmabuf->rcqe);
iocbq->iocb.un.rcvels.remoteID = sid;
list_add_tail(&iocbq->list, &first_iocbq->list);
}
rpi_page->start_rpi);
hdr_tmpl->rpi_paddr_lo = putPaddrLow(rpi_page->dmabuf->phys);
hdr_tmpl->rpi_paddr_hi = putPaddrHigh(rpi_page->dmabuf->phys);
- if (!phba->sli4_hba.intr_enable)
- rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- else
- rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
shdr = (union lpfc_sli4_cfg_shdr *) &hdr_tmpl->header.cfg_shdr;
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
bf_set(lpfc_fcf_record_fc_map_1, fcf_record, phba->fc_map[1]);
bf_set(lpfc_fcf_record_fc_map_2, fcf_record, phba->fc_map[2]);
bf_set(lpfc_fcf_record_fcf_valid, fcf_record, 1);
+ bf_set(lpfc_fcf_record_fcf_avail, fcf_record, 1);
bf_set(lpfc_fcf_record_fcf_index, fcf_record, fcf_index);
bf_set(lpfc_fcf_record_mac_addr_prov, fcf_record,
LPFC_FCF_FPMA | LPFC_FCF_SPMA);
uint32_t alloc_len, req_len;
struct lpfc_mbx_read_fcf_tbl *read_fcf;
+ phba->fcoe_eventtag_at_fcf_scan = phba->fcoe_eventtag;
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
if (rc == MBX_NOT_FINISHED) {
lpfc_sli4_mbox_cmd_free(phba, mboxq);
error = -EIO;
- } else
+ } else {
+ spin_lock_irq(&phba->hbalock);
+ phba->hba_flag |= FCF_DISC_INPROGRESS;
+ spin_unlock_irq(&phba->hbalock);
error = 0;
+ }
return error;
}
+
+/**
+ * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This function read region 23 and parse TLV for port status to
+ * decide if the user disaled the port. If the TLV indicates the
+ * port is disabled, the hba_flag is set accordingly.
+ **/
+void
+lpfc_sli_read_link_ste(struct lpfc_hba *phba)
+{
+ LPFC_MBOXQ_t *pmb = NULL;
+ MAILBOX_t *mb;
+ uint8_t *rgn23_data = NULL;
+ uint32_t offset = 0, data_size, sub_tlv_len, tlv_offset;
+ int rc;
+
+ pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!pmb) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2600 lpfc_sli_read_serdes_param failed to"
+ " allocate mailbox memory\n");
+ goto out;
+ }
+ mb = &pmb->u.mb;
+
+ /* Get adapter Region 23 data */
+ rgn23_data = kzalloc(DMP_RGN23_SIZE, GFP_KERNEL);
+ if (!rgn23_data)
+ goto out;
+
+ do {
+ lpfc_dump_mem(phba, pmb, offset, DMP_REGION_23);
+ rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+
+ if (rc != MBX_SUCCESS) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "2601 lpfc_sli_read_link_ste failed to"
+ " read config region 23 rc 0x%x Status 0x%x\n",
+ rc, mb->mbxStatus);
+ mb->un.varDmp.word_cnt = 0;
+ }
+ /*
+ * dump mem may return a zero when finished or we got a
+ * mailbox error, either way we are done.
+ */
+ if (mb->un.varDmp.word_cnt == 0)
+ break;
+ if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset)
+ mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset;
+
+ lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
+ rgn23_data + offset,
+ mb->un.varDmp.word_cnt);
+ offset += mb->un.varDmp.word_cnt;
+ } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE);
+
+ data_size = offset;
+ offset = 0;
+
+ if (!data_size)
+ goto out;
+
+ /* Check the region signature first */
+ if (memcmp(&rgn23_data[offset], LPFC_REGION23_SIGNATURE, 4)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2619 Config region 23 has bad signature\n");
+ goto out;
+ }
+ offset += 4;
+
+ /* Check the data structure version */
+ if (rgn23_data[offset] != LPFC_REGION23_VERSION) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2620 Config region 23 has bad version\n");
+ goto out;
+ }
+ offset += 4;
+
+ /* Parse TLV entries in the region */
+ while (offset < data_size) {
+ if (rgn23_data[offset] == LPFC_REGION23_LAST_REC)
+ break;
+ /*
+ * If the TLV is not driver specific TLV or driver id is
+ * not linux driver id, skip the record.
+ */
+ if ((rgn23_data[offset] != DRIVER_SPECIFIC_TYPE) ||
+ (rgn23_data[offset + 2] != LINUX_DRIVER_ID) ||
+ (rgn23_data[offset + 3] != 0)) {
+ offset += rgn23_data[offset + 1] * 4 + 4;
+ continue;
+ }
+
+ /* Driver found a driver specific TLV in the config region */
+ sub_tlv_len = rgn23_data[offset + 1] * 4;
+ offset += 4;
+ tlv_offset = 0;
+
+ /*
+ * Search for configured port state sub-TLV.
+ */
+ while ((offset < data_size) &&
+ (tlv_offset < sub_tlv_len)) {
+ if (rgn23_data[offset] == LPFC_REGION23_LAST_REC) {
+ offset += 4;
+ tlv_offset += 4;
+ break;
+ }
+ if (rgn23_data[offset] != PORT_STE_TYPE) {
+ offset += rgn23_data[offset + 1] * 4 + 4;
+ tlv_offset += rgn23_data[offset + 1] * 4 + 4;
+ continue;
+ }
+
+ /* This HBA contains PORT_STE configured */
+ if (!rgn23_data[offset + 2])
+ phba->hba_flag |= LINK_DISABLED;
+
+ goto out;
+ }
+ }
+out:
+ if (pmb)
+ mempool_free(pmb, phba->mbox_mem_pool);
+ kfree(rgn23_data);
+ return;
+}