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.c730
1 files changed, 464 insertions, 266 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index a359d2b873ce..4746dcd756dd 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2009 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2011 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -96,7 +96,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)
/* set consumption flag every once in a while */
if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL))
bf_set(wqe_wqec, &wqe->generic.wqe_com, 1);
-
+ if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
+ bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
/* Update the host index before invoking device */
@@ -534,15 +535,35 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
uint16_t adj_xri;
struct lpfc_node_rrq *rrq;
int empty;
+ uint32_t did = 0;
+
+
+ if (!ndlp)
+ return -EINVAL;
+
+ if (!phba->cfg_enable_rrq)
+ return -EINVAL;
+
+ if (phba->pport->load_flag & FC_UNLOADING) {
+ phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+ goto out;
+ }
+ did = ndlp->nlp_DID;
/*
* set the active bit even if there is no mem available.
*/
adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
- if (!ndlp)
- return -EINVAL;
+
+ if (NLP_CHK_FREE_REQ(ndlp))
+ goto out;
+
+ if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING))
+ goto out;
+
if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap))
- return -EINVAL;
+ goto out;
+
rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
if (rrq) {
rrq->send_rrq = send_rrq;
@@ -553,14 +574,7 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
rrq->vport = ndlp->vport;
rrq->rxid = rxid;
empty = list_empty(&phba->active_rrq_list);
- if (phba->cfg_enable_rrq && send_rrq)
- /*
- * We need the xri before we can add this to the
- * phba active rrq list.
- */
- rrq->send_rrq = send_rrq;
- else
- rrq->send_rrq = 0;
+ rrq->send_rrq = send_rrq;
list_add_tail(&rrq->list, &phba->active_rrq_list);
if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) {
phba->hba_flag |= HBA_RRQ_ACTIVE;
@@ -569,40 +583,49 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
}
return 0;
}
- return -ENOMEM;
+out:
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "2921 Can't set rrq active xri:0x%x rxid:0x%x"
+ " DID:0x%x Send:%d\n",
+ xritag, rxid, did, send_rrq);
+ return -EINVAL;
}
/**
- * __lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
+ * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
* @phba: Pointer to HBA context object.
* @xritag: xri used in this exchange.
* @rrq: The RRQ to be cleared.
*
- * This function is called with hbalock held. This function
**/
-static void
-__lpfc_clr_rrq_active(struct lpfc_hba *phba,
- uint16_t xritag,
- struct lpfc_node_rrq *rrq)
+void
+lpfc_clr_rrq_active(struct lpfc_hba *phba,
+ uint16_t xritag,
+ struct lpfc_node_rrq *rrq)
{
uint16_t adj_xri;
- struct lpfc_nodelist *ndlp;
+ struct lpfc_nodelist *ndlp = NULL;
- ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID);
+ if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp))
+ ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID);
/* The target DID could have been swapped (cable swap)
* we should use the ndlp from the findnode if it is
* available.
*/
- if (!ndlp)
+ if ((!ndlp) && rrq->ndlp)
ndlp = rrq->ndlp;
+ if (!ndlp)
+ goto out;
+
adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) {
rrq->send_rrq = 0;
rrq->xritag = 0;
rrq->rrq_stop_time = 0;
}
+out:
mempool_free(rrq, phba->rrq_pool);
}
@@ -627,34 +650,34 @@ lpfc_handle_rrq_active(struct lpfc_hba *phba)
struct lpfc_node_rrq *nextrrq;
unsigned long next_time;
unsigned long iflags;
+ LIST_HEAD(send_rrq);
spin_lock_irqsave(&phba->hbalock, iflags);
phba->hba_flag &= ~HBA_RRQ_ACTIVE;
next_time = jiffies + HZ * (phba->fc_ratov + 1);
list_for_each_entry_safe(rrq, nextrrq,
- &phba->active_rrq_list, list) {
- if (time_after(jiffies, rrq->rrq_stop_time)) {
- list_del(&rrq->list);
- if (!rrq->send_rrq)
- /* this call will free the rrq */
- __lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
- else {
- /* if we send the rrq then the completion handler
- * will clear the bit in the xribitmap.
- */
- spin_unlock_irqrestore(&phba->hbalock, iflags);
- if (lpfc_send_rrq(phba, rrq)) {
- lpfc_clr_rrq_active(phba, rrq->xritag,
- rrq);
- }
- spin_lock_irqsave(&phba->hbalock, iflags);
- }
- } else if (time_before(rrq->rrq_stop_time, next_time))
+ &phba->active_rrq_list, list) {
+ if (time_after(jiffies, rrq->rrq_stop_time))
+ list_move(&rrq->list, &send_rrq);
+ else if (time_before(rrq->rrq_stop_time, next_time))
next_time = rrq->rrq_stop_time;
}
spin_unlock_irqrestore(&phba->hbalock, iflags);
if (!list_empty(&phba->active_rrq_list))
mod_timer(&phba->rrq_tmr, next_time);
+ list_for_each_entry_safe(rrq, nextrrq, &send_rrq, list) {
+ list_del(&rrq->list);
+ if (!rrq->send_rrq)
+ /* this call will free the rrq */
+ lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+ else if (lpfc_send_rrq(phba, rrq)) {
+ /* if we send the rrq then the completion handler
+ * will clear the bit in the xribitmap.
+ */
+ lpfc_clr_rrq_active(phba, rrq->xritag,
+ rrq);
+ }
+ }
}
/**
@@ -692,29 +715,37 @@ lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did)
/**
* lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport.
* @vport: Pointer to vport context object.
- *
- * Remove all active RRQs for this vport from the phba->active_rrq_list and
- * clear the rrq.
+ * @ndlp: Pointer to the lpfc_node_list structure.
+ * If ndlp is NULL Remove all active RRQs for this vport from the
+ * phba->active_rrq_list and clear the rrq.
+ * If ndlp is not NULL then only remove rrqs for this vport & this ndlp.
**/
void
-lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport)
+lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_node_rrq *rrq;
struct lpfc_node_rrq *nextrrq;
unsigned long iflags;
+ LIST_HEAD(rrq_list);
if (phba->sli_rev != LPFC_SLI_REV4)
return;
- spin_lock_irqsave(&phba->hbalock, iflags);
- list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
- if (rrq->vport == vport) {
- list_del(&rrq->list);
- __lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
- }
+ if (!ndlp) {
+ lpfc_sli4_vport_delete_els_xri_aborted(vport);
+ lpfc_sli4_vport_delete_fcp_xri_aborted(vport);
}
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list)
+ if ((rrq->vport == vport) && (!ndlp || rrq->ndlp == ndlp))
+ list_move(&rrq->list, &rrq_list);
spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+ list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) {
+ list_del(&rrq->list);
+ lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+ }
}
/**
@@ -732,24 +763,27 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba)
struct lpfc_node_rrq *nextrrq;
unsigned long next_time;
unsigned long iflags;
+ LIST_HEAD(rrq_list);
if (phba->sli_rev != LPFC_SLI_REV4)
return;
spin_lock_irqsave(&phba->hbalock, iflags);
phba->hba_flag &= ~HBA_RRQ_ACTIVE;
next_time = jiffies + HZ * (phba->fc_ratov * 2);
- list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+ list_splice_init(&phba->active_rrq_list, &rrq_list);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+ list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) {
list_del(&rrq->list);
- __lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+ lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
}
- spin_unlock_irqrestore(&phba->hbalock, iflags);
if (!list_empty(&phba->active_rrq_list))
mod_timer(&phba->rrq_tmr, next_time);
}
/**
- * __lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
+ * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
* @phba: Pointer to HBA context object.
* @ndlp: Targets nodelist pointer for this exchange.
* @xritag the xri in the bitmap to test.
@@ -758,8 +792,8 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba)
* returns 0 = rrq not active for this xri
* 1 = rrq is valid for this xri.
**/
-static int
-__lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+int
+lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
uint16_t xritag)
{
uint16_t adj_xri;
@@ -802,52 +836,6 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
}
/**
- * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
- * @phba: Pointer to HBA context object.
- * @xritag: xri used in this exchange.
- * @rrq: The RRQ to be cleared.
- *
- * This function is takes the hbalock.
- **/
-void
-lpfc_clr_rrq_active(struct lpfc_hba *phba,
- uint16_t xritag,
- struct lpfc_node_rrq *rrq)
-{
- unsigned long iflags;
-
- spin_lock_irqsave(&phba->hbalock, iflags);
- __lpfc_clr_rrq_active(phba, xritag, rrq);
- spin_unlock_irqrestore(&phba->hbalock, iflags);
- return;
-}
-
-
-
-/**
- * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
- * @phba: Pointer to HBA context object.
- * @ndlp: Targets nodelist pointer for this exchange.
- * @xritag the xri in the bitmap to test.
- *
- * This function takes the hbalock.
- * returns 0 = rrq not active for this xri
- * 1 = rrq is valid for this xri.
- **/
-int
-lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
- uint16_t xritag)
-{
- int ret;
- unsigned long iflags;
-
- spin_lock_irqsave(&phba->hbalock, iflags);
- ret = __lpfc_test_rrq_active(phba, ndlp, xritag);
- spin_unlock_irqrestore(&phba->hbalock, iflags);
- return ret;
-}
-
-/**
* __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool
* @phba: Pointer to HBA context object.
* @piocb: Pointer to the iocbq.
@@ -884,7 +872,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
return NULL;
adj_xri = sglq->sli4_xritag -
phba->sli4_hba.max_cfg_param.xri_base;
- if (__lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
+ if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
/* This xri has an rrq outstanding for this DID.
* put it back in the list and get another xri.
*/
@@ -969,7 +957,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
} else {
sglq->state = SGL_FREED;
sglq->ndlp = NULL;
- list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list);
+ list_add_tail(&sglq->list,
+ &phba->sli4_hba.lpfc_sgl_list);
/* Check if TXQ queue needs to be serviced */
if (pring->txq_cnt)
@@ -3488,7 +3477,8 @@ lpfc_sli_brdready_s3(struct lpfc_hba *phba, uint32_t mask)
int retval = 0;
/* Read the HBA Host Status Register */
- status = readl(phba->HSregaddr);
+ if (lpfc_readl(phba->HSregaddr, &status))
+ return 1;
/*
* Check status register every 100ms for 5 retries, then every
@@ -3513,7 +3503,10 @@ lpfc_sli_brdready_s3(struct lpfc_hba *phba, uint32_t mask)
lpfc_sli_brdrestart(phba);
}
/* Read the HBA Host Status Register */
- status = readl(phba->HSregaddr);
+ if (lpfc_readl(phba->HSregaddr, &status)) {
+ retval = 1;
+ break;
+ }
}
/* Check to see if any errors occurred during init */
@@ -3595,7 +3588,7 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
uint32_t __iomem *resp_buf;
uint32_t __iomem *mbox_buf;
volatile uint32_t mbox;
- uint32_t hc_copy;
+ uint32_t hc_copy, ha_copy, resp_data;
int i;
uint8_t hdrtype;
@@ -3612,12 +3605,15 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
resp_buf = phba->MBslimaddr;
/* Disable the error attention */
- hc_copy = readl(phba->HCregaddr);
+ if (lpfc_readl(phba->HCregaddr, &hc_copy))
+ return;
writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
phba->link_flag |= LS_IGNORE_ERATT;
- if (readl(phba->HAregaddr) & HA_ERATT) {
+ if (lpfc_readl(phba->HAregaddr, &ha_copy))
+ return;
+ if (ha_copy & HA_ERATT) {
/* Clear Chip error bit */
writel(HA_ERATT, phba->HAregaddr);
phba->pport->stopped = 1;
@@ -3631,11 +3627,18 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
mbox_buf = phba->MBslimaddr;
writel(mbox, mbox_buf);
- for (i = 0;
- readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN) && i < 50; i++)
- mdelay(1);
-
- if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
+ for (i = 0; i < 50; i++) {
+ if (lpfc_readl((resp_buf + 1), &resp_data))
+ return;
+ if (resp_data != ~(BARRIER_TEST_PATTERN))
+ mdelay(1);
+ else
+ break;
+ }
+ resp_data = 0;
+ if (lpfc_readl((resp_buf + 1), &resp_data))
+ return;
+ if (resp_data != ~(BARRIER_TEST_PATTERN)) {
if (phba->sli.sli_flag & LPFC_SLI_ACTIVE ||
phba->pport->stopped)
goto restore_hc;
@@ -3644,13 +3647,26 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
}
((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST;
- for (i = 0; readl(resp_buf) != mbox && i < 500; i++)
- mdelay(1);
+ resp_data = 0;
+ for (i = 0; i < 500; i++) {
+ if (lpfc_readl(resp_buf, &resp_data))
+ return;
+ if (resp_data != mbox)
+ mdelay(1);
+ else
+ break;
+ }
clear_errat:
- while (!(readl(phba->HAregaddr) & HA_ERATT) && ++i < 500)
- mdelay(1);
+ while (++i < 500) {
+ if (lpfc_readl(phba->HAregaddr, &ha_copy))
+ return;
+ if (!(ha_copy & HA_ERATT))
+ mdelay(1);
+ else
+ break;
+ }
if (readl(phba->HAregaddr) & HA_ERATT) {
writel(HA_ERATT, phba->HAregaddr);
@@ -3697,7 +3713,11 @@ lpfc_sli_brdkill(struct lpfc_hba *phba)
/* Disable the error attention */
spin_lock_irq(&phba->hbalock);
- status = readl(phba->HCregaddr);
+ if (lpfc_readl(phba->HCregaddr, &status)) {
+ spin_unlock_irq(&phba->hbalock);
+ mempool_free(pmb, phba->mbox_mem_pool);
+ return 1;
+ }
status &= ~HC_ERINT_ENA;
writel(status, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
@@ -3731,11 +3751,12 @@ lpfc_sli_brdkill(struct lpfc_hba *phba)
* 3 seconds we still set HBA_ERROR state because the status of the
* board is now undefined.
*/
- ha_copy = readl(phba->HAregaddr);
-
+ if (lpfc_readl(phba->HAregaddr, &ha_copy))
+ return 1;
while ((i++ < 30) && !(ha_copy & HA_ERATT)) {
mdelay(100);
- ha_copy = readl(phba->HAregaddr);
+ if (lpfc_readl(phba->HAregaddr, &ha_copy))
+ return 1;
}
del_timer_sync(&psli->mbox_tmo);
@@ -4029,7 +4050,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
uint32_t status, i = 0;
/* Read the HBA Host Status Register */
- status = readl(phba->HSregaddr);
+ if (lpfc_readl(phba->HSregaddr, &status))
+ return -EIO;
/* Check status register to see what current state is */
i = 0;
@@ -4084,7 +4106,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
lpfc_sli_brdrestart(phba);
}
/* Read the HBA Host Status Register */
- status = readl(phba->HSregaddr);
+ if (lpfc_readl(phba->HSregaddr, &status))
+ return -EIO;
}
/* Check to see if any errors occurred during init */
@@ -4817,7 +4840,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
"0378 No support for fcpi mode.\n");
ftr_rsp++;
}
-
+ if (bf_get(lpfc_mbx_rq_ftr_rsp_perfh, &mqe->un.req_ftrs))
+ phba->sli3_options |= LPFC_SLI4_PERFH_ENABLED;
+ else
+ phba->sli3_options &= ~LPFC_SLI4_PERFH_ENABLED;
/*
* If the port cannot support the host's requested features
* then turn off the global config parameters to disable the
@@ -5004,7 +5030,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
spin_lock_irq(&phba->hbalock);
phba->link_state = LPFC_LINK_DOWN;
spin_unlock_irq(&phba->hbalock);
- rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+ if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK)
+ rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
out_unset_queue:
/* Unset all the queues set up in this routine when error out */
if (rc)
@@ -5143,7 +5170,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
MAILBOX_t *mb;
struct lpfc_sli *psli = &phba->sli;
uint32_t status, evtctr;
- uint32_t ha_copy;
+ uint32_t ha_copy, hc_copy;
int i;
unsigned long timeout;
unsigned long drvr_flag = 0;
@@ -5209,15 +5236,17 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
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);
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT) {
+ if (lpfc_readl(phba->HCregaddr, &hc_copy) ||
+ !(hc_copy & HC_MBINT_ENA)) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"(%d):2528 Mailbox command x%x cannot "
"issue Data: x%x x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0,
pmbox->u.mb.mbxCommand, psli->sli_flag, flag);
- goto out_not_finished;
+ goto out_not_finished;
+ }
}
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
@@ -5415,11 +5444,19 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
word0 = le32_to_cpu(word0);
} else {
/* First read mbox status word */
- word0 = readl(phba->MBslimaddr);
+ if (lpfc_readl(phba->MBslimaddr, &word0)) {
+ spin_unlock_irqrestore(&phba->hbalock,
+ drvr_flag);
+ goto out_not_finished;
+ }
}
/* Read the HBA Host Attention Register */
- ha_copy = readl(phba->HAregaddr);
+ if (lpfc_readl(phba->HAregaddr, &ha_copy)) {
+ spin_unlock_irqrestore(&phba->hbalock,
+ drvr_flag);
+ goto out_not_finished;
+ }
timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
mb->mbxCommand) *
1000) + jiffies;
@@ -5470,7 +5507,11 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
word0 = readl(phba->MBslimaddr);
}
/* Read the HBA Host Attention Register */
- ha_copy = readl(phba->HAregaddr);
+ if (lpfc_readl(phba->HAregaddr, &ha_copy)) {
+ spin_unlock_irqrestore(&phba->hbalock,
+ drvr_flag);
+ goto out_not_finished;
+ }
}
if (psli->sli_flag & LPFC_SLI_ACTIVE) {
@@ -6270,7 +6311,6 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
bf_set(lpfc_sli4_sge_last, sgl, 1);
else
bf_set(lpfc_sli4_sge_last, sgl, 0);
- sgl->word2 = cpu_to_le32(sgl->word2);
/* swap the size field back to the cpu so we
* can assign it to the sgl.
*/
@@ -6290,6 +6330,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
bf_set(lpfc_sli4_sge_offset, sgl, offset);
offset += bde.tus.f.bdeSize;
}
+ sgl->word2 = cpu_to_le32(sgl->word2);
bpl++;
sgl++;
}
@@ -6535,9 +6576,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize /
sizeof(struct ulp_bde64);
for (i = 0; i < numBdes; i++) {
- if (bpl[i].tus.f.bdeFlags != BUFF_TYPE_BDE_64)
- break;
bde.tus.w = le32_to_cpu(bpl[i].tus.w);
+ if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64)
+ break;
xmit_len += bde.tus.f.bdeSize;
}
/* word3 iocb=IO_TAG wqe=request_payload_len */
@@ -6627,15 +6668,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
xritag = 0;
break;
case CMD_XMIT_BLS_RSP64_CX:
- /* As BLS ABTS-ACC WQE is very different from other WQEs,
+ /* As BLS ABTS RSP WQE is very different from other WQEs,
* we re-construct this WQE here based on information in
* iocbq from scratch.
*/
memset(wqe, 0, sizeof(union lpfc_wqe));
/* OX_ID is invariable to who sent ABTS to CT exchange */
bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp,
- bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_acc));
- if (bf_get(lpfc_abts_orig, &iocbq->iocb.un.bls_acc) ==
+ bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_rsp));
+ if (bf_get(lpfc_abts_orig, &iocbq->iocb.un.bls_rsp) ==
LPFC_ABTS_UNSOL_INT) {
/* ABTS sent by initiator to CT exchange, the
* RX_ID field will be filled with the newly
@@ -6649,7 +6690,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
* RX_ID from ABTS.
*/
bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp,
- bf_get(lpfc_abts_rxid, &iocbq->iocb.un.bls_acc));
+ bf_get(lpfc_abts_rxid, &iocbq->iocb.un.bls_rsp));
}
bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff);
bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1);
@@ -6660,6 +6701,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
LPFC_WQE_LENLOC_NONE);
/* Overwrite the pre-set comnd type with OTHER_COMMAND */
command_type = OTHER_COMMAND;
+ if (iocbq->iocb.un.xseq64.w5.hcsw.Rctl == FC_RCTL_BA_RJT) {
+ bf_set(xmit_bls_rsp64_rjt_vspec, &wqe->xmit_bls_rsp,
+ bf_get(lpfc_vndr_code, &iocbq->iocb.un.bls_rsp));
+ bf_set(xmit_bls_rsp64_rjt_expc, &wqe->xmit_bls_rsp,
+ bf_get(lpfc_rsn_expln, &iocbq->iocb.un.bls_rsp));
+ bf_set(xmit_bls_rsp64_rjt_rsnc, &wqe->xmit_bls_rsp,
+ bf_get(lpfc_rsn_code, &iocbq->iocb.un.bls_rsp));
+ }
+
break;
case CMD_XRI_ABORTED_CX:
case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
@@ -6708,7 +6758,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
if (piocb->sli4_xritag == NO_XRI) {
if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
- piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
+ piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN ||
+ piocb->iocb.ulpCommand == CMD_XMIT_BLS_RSP64_CX)
sglq = NULL;
else {
if (pring->txq_cnt) {
@@ -8201,7 +8252,8 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
piocb->iocb_flag &= ~LPFC_IO_WAKE;
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
- creg_val = readl(phba->HCregaddr);
+ if (lpfc_readl(phba->HCregaddr, &creg_val))
+ return IOCB_ERROR;
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
writel(creg_val, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
@@ -8243,7 +8295,8 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
}
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
- creg_val = readl(phba->HCregaddr);
+ if (lpfc_readl(phba->HCregaddr, &creg_val))
+ return IOCB_ERROR;
creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
writel(creg_val, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
@@ -8394,10 +8447,13 @@ lpfc_sli_eratt_read(struct lpfc_hba *phba)
uint32_t ha_copy;
/* Read chip Host Attention (HA) register */
- ha_copy = readl(phba->HAregaddr);
+ if (lpfc_readl(phba->HAregaddr, &ha_copy))
+ goto unplug_err;
+
if (ha_copy & HA_ERATT) {
/* Read host status register to retrieve error event */
- lpfc_sli_read_hs(phba);
+ if (lpfc_sli_read_hs(phba))
+ goto unplug_err;
/* Check if there is a deferred error condition is active */
if ((HS_FFER1 & phba->work_hs) &&
@@ -8416,6 +8472,15 @@ lpfc_sli_eratt_read(struct lpfc_hba *phba)
return 1;
}
return 0;
+
+unplug_err:
+ /* Set the driver HS work bitmap */
+ phba->work_hs |= UNPLUG_ERR;
+ /* Set the driver HA work bitmap */
+ phba->work_ha |= HA_ERATT;
+ /* Indicate polling handles this ERATT */
+ phba->hba_flag |= HBA_ERATT_HANDLED;
+ return 1;
}
/**
@@ -8443,8 +8508,15 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba)
if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
switch (if_type) {
case LPFC_SLI_INTF_IF_TYPE_0:
- uerr_sta_lo = readl(phba->sli4_hba.u.if_type0.UERRLOregaddr);
- uerr_sta_hi = readl(phba->sli4_hba.u.if_type0.UERRHIregaddr);
+ if (lpfc_readl(phba->sli4_hba.u.if_type0.UERRLOregaddr,
+ &uerr_sta_lo) ||
+ lpfc_readl(phba->sli4_hba.u.if_type0.UERRHIregaddr,
+ &uerr_sta_hi)) {
+ phba->work_hs |= UNPLUG_ERR;
+ phba->work_ha |= HA_ERATT;
+ phba->hba_flag |= HBA_ERATT_HANDLED;
+ return 1;
+ }
if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
(~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -8463,9 +8535,15 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba)
}
break;
case LPFC_SLI_INTF_IF_TYPE_2:
- portstat_reg.word0 =
- readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
- portsmphr = readl(phba->sli4_hba.PSMPHRregaddr);
+ if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+ &portstat_reg.word0) ||
+ lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
+ &portsmphr)){
+ phba->work_hs |= UNPLUG_ERR;
+ phba->work_ha |= HA_ERATT;
+ phba->hba_flag |= HBA_ERATT_HANDLED;
+ return 1;
+ }
if (bf_get(lpfc_sliport_status_err, &portstat_reg)) {
phba->work_status[0] =
readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
@@ -8646,7 +8724,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
return IRQ_NONE;
/* Need to read HA REG for slow-path events */
spin_lock_irqsave(&phba->hbalock, iflag);
- ha_copy = readl(phba->HAregaddr);
+ if (lpfc_readl(phba->HAregaddr, &ha_copy))
+ goto unplug_error;
/* If somebody is waiting to handle an eratt don't process it
* here. The brdkill function will do this.
*/
@@ -8672,7 +8751,9 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
}
/* Clear up only attention source related to slow-path */
- hc_copy = readl(phba->HCregaddr);
+ if (lpfc_readl(phba->HCregaddr, &hc_copy))
+ goto unplug_error;
+
writel(hc_copy & ~(HC_MBINT_ENA | HC_R2INT_ENA |
HC_LAINT_ENA | HC_ERINT_ENA),
phba->HCregaddr);
@@ -8695,7 +8776,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
*/
spin_lock_irqsave(&phba->hbalock, iflag);
phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
- control = readl(phba->HCregaddr);
+ if (lpfc_readl(phba->HCregaddr, &control))
+ goto unplug_error;
control &= ~HC_LAINT_ENA;
writel(control, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
@@ -8715,7 +8797,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
status >>= (4*LPFC_ELS_RING);
if (status & HA_RXMASK) {
spin_lock_irqsave(&phba->hbalock, iflag);
- control = readl(phba->HCregaddr);
+ if (lpfc_readl(phba->HCregaddr, &control))
+ goto unplug_error;
lpfc_debugfs_slow_ring_trc(phba,
"ISR slow ring: ctl:x%x stat:x%x isrcnt:x%x",
@@ -8748,7 +8831,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
}
spin_lock_irqsave(&phba->hbalock, iflag);
if (work_ha_copy & HA_ERATT) {
- lpfc_sli_read_hs(phba);
+ if (lpfc_sli_read_hs(phba))
+ goto unplug_error;
/*
* Check if there is a deferred error condition
* is active
@@ -8879,6 +8963,9 @@ send_current_mbox:
lpfc_worker_wake_up(phba);
}
return IRQ_HANDLED;
+unplug_error:
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
+ return IRQ_HANDLED;
} /* lpfc_sli_sp_intr_handler */
@@ -8926,7 +9013,8 @@ lpfc_sli_fp_intr_handler(int irq, void *dev_id)
if (lpfc_intr_state_check(phba))
return IRQ_NONE;
/* Need to read HA REG for FCP ring and other ring events */
- ha_copy = readl(phba->HAregaddr);
+ if (lpfc_readl(phba->HAregaddr, &ha_copy))
+ return IRQ_HANDLED;
/* Clear up only attention source related to fast-path */
spin_lock_irqsave(&phba->hbalock, iflag);
/*
@@ -9011,7 +9099,11 @@ lpfc_sli_intr_handler(int irq, void *dev_id)
return IRQ_NONE;
spin_lock(&phba->hbalock);
- phba->ha_copy = readl(phba->HAregaddr);
+ if (lpfc_readl(phba->HAregaddr, &phba->ha_copy)) {
+ spin_unlock(&phba->hbalock);
+ return IRQ_HANDLED;
+ }
+
if (unlikely(!phba->ha_copy)) {
spin_unlock(&phba->hbalock);
return IRQ_NONE;
@@ -9033,7 +9125,10 @@ lpfc_sli_intr_handler(int irq, void *dev_id)
}
/* Clear attention sources except link and error attentions */
- hc_copy = readl(phba->HCregaddr);
+ if (lpfc_readl(phba->HCregaddr, &hc_copy)) {
+ spin_unlock(&phba->hbalock);
+ return IRQ_HANDLED;
+ }
writel(hc_copy & ~(HC_MBINT_ENA | HC_R0INT_ENA | HC_R1INT_ENA
| HC_R2INT_ENA | HC_LAINT_ENA | HC_ERINT_ENA),
phba->HCregaddr);
@@ -10410,7 +10505,6 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
if (!phba->sli4_hba.pc_sli4_params.supported)
hw_page_size = SLI4_PAGE_SIZE;
-
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox)
return -ENOMEM;
@@ -10420,11 +10514,22 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
LPFC_MBOX_OPCODE_CQ_CREATE,
length, LPFC_SLI4_MBX_EMBED);
cq_create = &mbox->u.mqe.un.cq_create;
+ shdr = (union lpfc_sli4_cfg_shdr *) &cq_create->header.cfg_shdr;
bf_set(lpfc_mbx_cq_create_num_pages, &cq_create->u.request,
cq->page_count);
bf_set(lpfc_cq_context_event, &cq_create->u.request.context, 1);
bf_set(lpfc_cq_context_valid, &cq_create->u.request.context, 1);
- bf_set(lpfc_cq_eq_id, &cq_create->u.request.context, eq->queue_id);
+ bf_set(lpfc_mbox_hdr_version, &shdr->request,
+ phba->sli4_hba.pc_sli4_params.cqv);
+ if (phba->sli4_hba.pc_sli4_params.cqv == LPFC_Q_CREATE_VERSION_2) {
+ bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request,
+ (PAGE_SIZE/SLI4_PAGE_SIZE));
+ bf_set(lpfc_cq_eq_id_2, &cq_create->u.request.context,
+ eq->queue_id);
+ } else {
+ bf_set(lpfc_cq_eq_id, &cq_create->u.request.context,
+ eq->queue_id);
+ }
switch (cq->entry_count) {
default:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@@ -10456,7 +10561,6 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */
- shdr = (union lpfc_sli4_cfg_shdr *) &cq_create->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);
if (shdr_status || shdr_add_status || rc) {
@@ -10478,6 +10582,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
cq->type = type;
cq->subtype = subtype;
cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response);
+ cq->assoc_qid = eq->queue_id;
cq->host_index = 0;
cq->hba_index = 0;
@@ -10521,20 +10626,20 @@ lpfc_mq_create_fb_init(struct lpfc_hba *phba, struct lpfc_queue *mq,
bf_set(lpfc_mq_context_valid, &mq_create->u.request.context, 1);
switch (mq->entry_count) {
case 16:
- bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
- LPFC_MQ_CNT_16);
+ bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
+ LPFC_MQ_RING_SIZE_16);
break;
case 32:
- bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
- LPFC_MQ_CNT_32);
+ bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
+ LPFC_MQ_RING_SIZE_32);
break;
case 64:
- bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
- LPFC_MQ_CNT_64);
+ bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
+ LPFC_MQ_RING_SIZE_64);
break;
case 128:
- bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
- LPFC_MQ_CNT_128);
+ bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
+ LPFC_MQ_RING_SIZE_128);
break;
}
list_for_each_entry(dmabuf, &mq->page_list, list) {
@@ -10592,6 +10697,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
length, LPFC_SLI4_MBX_EMBED);
mq_create_ext = &mbox->u.mqe.un.mq_create_ext;
+ shdr = (union lpfc_sli4_cfg_shdr *) &mq_create_ext->header.cfg_shdr;
bf_set(lpfc_mbx_mq_create_ext_num_pages,
&mq_create_ext->u.request, mq->page_count);
bf_set(lpfc_mbx_mq_create_ext_async_evt_link,
@@ -10604,9 +10710,15 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
&mq_create_ext->u.request, 1);
bf_set(lpfc_mbx_mq_create_ext_async_evt_sli,
&mq_create_ext->u.request, 1);
- bf_set(lpfc_mq_context_cq_id,
- &mq_create_ext->u.request.context, cq->queue_id);
bf_set(lpfc_mq_context_valid, &mq_create_ext->u.request.context, 1);
+ bf_set(lpfc_mbox_hdr_version, &shdr->request,
+ phba->sli4_hba.pc_sli4_params.mqv);
+ if (phba->sli4_hba.pc_sli4_params.mqv == LPFC_Q_CREATE_VERSION_1)
+ bf_set(lpfc_mbx_mq_create_ext_cq_id, &mq_create_ext->u.request,
+ cq->queue_id);
+ else
+ bf_set(lpfc_mq_context_cq_id, &mq_create_ext->u.request.context,
+ cq->queue_id);
switch (mq->entry_count) {
default:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@@ -10616,20 +10728,24 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
return -EINVAL;
/* otherwise default to smallest count (drop through) */
case 16:
- bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
- LPFC_MQ_CNT_16);
+ bf_set(lpfc_mq_context_ring_size,
+ &mq_create_ext->u.request.context,
+ LPFC_MQ_RING_SIZE_16);
break;
case 32:
- bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
- LPFC_MQ_CNT_32);
+ bf_set(lpfc_mq_context_ring_size,
+ &mq_create_ext->u.request.context,
+ LPFC_MQ_RING_SIZE_32);
break;
case 64:
- bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
- LPFC_MQ_CNT_64);
+ bf_set(lpfc_mq_context_ring_size,
+ &mq_create_ext->u.request.context,
+ LPFC_MQ_RING_SIZE_64);
break;
case 128:
- bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
- LPFC_MQ_CNT_128);
+ bf_set(lpfc_mq_context_ring_size,
+ &mq_create_ext->u.request.context,
+ LPFC_MQ_RING_SIZE_128);
break;
}
list_for_each_entry(dmabuf, &mq->page_list, list) {
@@ -10640,7 +10756,6 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
putPaddrHigh(dmabuf->phys);
}
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
- shdr = (union lpfc_sli4_cfg_shdr *) &mq_create_ext->header.cfg_shdr;
mq->queue_id = bf_get(lpfc_mbx_mq_create_q_id,
&mq_create_ext->u.response);
if (rc != MBX_SUCCESS) {
@@ -10672,6 +10787,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
goto out;
}
mq->type = LPFC_MQ;
+ mq->assoc_qid = cq->queue_id;
mq->subtype = subtype;
mq->host_index = 0;
mq->hba_index = 0;
@@ -10716,6 +10832,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
uint32_t shdr_status, shdr_add_status;
union lpfc_sli4_cfg_shdr *shdr;
uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
+ struct dma_address *page;
if (!phba->sli4_hba.pc_sli4_params.supported)
hw_page_size = SLI4_PAGE_SIZE;
@@ -10729,20 +10846,42 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
LPFC_MBOX_OPCODE_FCOE_WQ_CREATE,
length, LPFC_SLI4_MBX_EMBED);
wq_create = &mbox->u.mqe.un.wq_create;
+ shdr = (union lpfc_sli4_cfg_shdr *) &wq_create->header.cfg_shdr;
bf_set(lpfc_mbx_wq_create_num_pages, &wq_create->u.request,
wq->page_count);
bf_set(lpfc_mbx_wq_create_cq_id, &wq_create->u.request,
cq->queue_id);
+ bf_set(lpfc_mbox_hdr_version, &shdr->request,
+ phba->sli4_hba.pc_sli4_params.wqv);
+ if (phba->sli4_hba.pc_sli4_params.wqv == LPFC_Q_CREATE_VERSION_1) {
+ bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1,
+ wq->entry_count);
+ switch (wq->entry_size) {
+ default:
+ case 64:
+ bf_set(lpfc_mbx_wq_create_wqe_size,
+ &wq_create->u.request_1,
+ LPFC_WQ_WQE_SIZE_64);
+ break;
+ case 128:
+ bf_set(lpfc_mbx_wq_create_wqe_size,
+ &wq_create->u.request_1,
+ LPFC_WQ_WQE_SIZE_128);
+ break;
+ }
+ bf_set(lpfc_mbx_wq_create_page_size, &wq_create->u.request_1,
+ (PAGE_SIZE/SLI4_PAGE_SIZE));
+ page = wq_create->u.request_1.page;
+ } else {
+ page = wq_create->u.request.page;
+ }
list_for_each_entry(dmabuf, &wq->page_list, list) {
memset(dmabuf->virt, 0, hw_page_size);
- wq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
- putPaddrLow(dmabuf->phys);
- wq_create->u.request.page[dmabuf->buffer_tag].addr_hi =
- putPaddrHigh(dmabuf->phys);
+ page[dmabuf->buffer_tag].addr_lo = putPaddrLow(dmabuf->phys);
+ page[dmabuf->buffer_tag].addr_hi = putPaddrHigh(dmabuf->phys);
}
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */
- shdr = (union lpfc_sli4_cfg_shdr *) &wq_create->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);
if (shdr_status || shdr_add_status || rc) {
@@ -10759,6 +10898,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
goto out;
}
wq->type = LPFC_WQ;
+ wq->assoc_qid = cq->queue_id;
wq->subtype = subtype;
wq->host_index = 0;
wq->hba_index = 0;
@@ -10819,37 +10959,51 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
LPFC_MBOX_OPCODE_FCOE_RQ_CREATE,
length, LPFC_SLI4_MBX_EMBED);
rq_create = &mbox->u.mqe.un.rq_create;
- switch (hrq->entry_count) {
- default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2535 Unsupported RQ count. (%d)\n",
- hrq->entry_count);
- if (hrq->entry_count < 512)
- return -EINVAL;
- /* otherwise default to smallest count (drop through) */
- case 512:
- bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
- LPFC_RQ_RING_SIZE_512);
- break;
- case 1024:
- bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
- LPFC_RQ_RING_SIZE_1024);
- break;
- case 2048:
- bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
- LPFC_RQ_RING_SIZE_2048);
- break;
- case 4096:
- bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
- LPFC_RQ_RING_SIZE_4096);
- break;
+ shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr;
+ bf_set(lpfc_mbox_hdr_version, &shdr->request,
+ phba->sli4_hba.pc_sli4_params.rqv);
+ if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
+ bf_set(lpfc_rq_context_rqe_count_1,
+ &rq_create->u.request.context,
+ hrq->entry_count);
+ rq_create->u.request.context.buffer_size = LPFC_HDR_BUF_SIZE;
+ } else {
+ switch (hrq->entry_count) {
+ default:
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2535 Unsupported RQ count. (%d)\n",
+ hrq->entry_count);
+ if (hrq->entry_count < 512)
+ return -EINVAL;
+ /* otherwise default to smallest count (drop through) */
+ case 512:
+ bf_set(lpfc_rq_context_rqe_count,
+ &rq_create->u.request.context,
+ LPFC_RQ_RING_SIZE_512);
+ break;
+ case 1024:
+ bf_set(lpfc_rq_context_rqe_count,
+ &rq_create->u.request.context,
+ LPFC_RQ_RING_SIZE_1024);
+ break;
+ case 2048:
+ bf_set(lpfc_rq_context_rqe_count,
+ &rq_create->u.request.context,
+ LPFC_RQ_RING_SIZE_2048);
+ break;
+ case 4096:
+ bf_set(lpfc_rq_context_rqe_count,
+ &rq_create->u.request.context,
+ LPFC_RQ_RING_SIZE_4096);
+ break;
+ }
+ bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
+ LPFC_HDR_BUF_SIZE);
}
bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
cq->queue_id);
bf_set(lpfc_mbx_rq_create_num_pages, &rq_create->u.request,
hrq->page_count);
- bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
- LPFC_HDR_BUF_SIZE);
list_for_each_entry(dmabuf, &hrq->page_list, list) {
memset(dmabuf->virt, 0, hw_page_size);
rq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
@@ -10859,7 +11013,6 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
}
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */
- shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->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);
if (shdr_status || shdr_add_status || rc) {
@@ -10876,6 +11029,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
goto out;
}
hrq->type = LPFC_HRQ;
+ hrq->assoc_qid = cq->queue_id;
hrq->subtype = subtype;
hrq->host_index = 0;
hrq->hba_index = 0;
@@ -10884,37 +11038,50 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
LPFC_MBOX_OPCODE_FCOE_RQ_CREATE,
length, LPFC_SLI4_MBX_EMBED);
- switch (drq->entry_count) {
- default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2536 Unsupported RQ count. (%d)\n",
- drq->entry_count);
- if (drq->entry_count < 512)
- return -EINVAL;
- /* otherwise default to smallest count (drop through) */
- case 512:
- bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
- LPFC_RQ_RING_SIZE_512);
- break;
- case 1024:
- bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
- LPFC_RQ_RING_SIZE_1024);
- break;
- case 2048:
- bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
- LPFC_RQ_RING_SIZE_2048);
- break;
- case 4096:
- bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
- LPFC_RQ_RING_SIZE_4096);
- break;
+ bf_set(lpfc_mbox_hdr_version, &shdr->request,
+ phba->sli4_hba.pc_sli4_params.rqv);
+ if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
+ bf_set(lpfc_rq_context_rqe_count_1,
+ &rq_create->u.request.context,
+ hrq->entry_count);
+ rq_create->u.request.context.buffer_size = LPFC_DATA_BUF_SIZE;
+ } else {
+ switch (drq->entry_count) {
+ default:
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2536 Unsupported RQ count. (%d)\n",
+ drq->entry_count);
+ if (drq->entry_count < 512)
+ return -EINVAL;
+ /* otherwise default to smallest count (drop through) */
+ case 512:
+ bf_set(lpfc_rq_context_rqe_count,
+ &rq_create->u.request.context,
+ LPFC_RQ_RING_SIZE_512);
+ break;
+ case 1024:
+ bf_set(lpfc_rq_context_rqe_count,
+ &rq_create->u.request.context,
+ LPFC_RQ_RING_SIZE_1024);
+ break;
+ case 2048:
+ bf_set(lpfc_rq_context_rqe_count,
+ &rq_create->u.request.context,
+ LPFC_RQ_RING_SIZE_2048);
+ break;
+ case 4096:
+ bf_set(lpfc_rq_context_rqe_count,
+ &rq_create->u.request.context,
+ LPFC_RQ_RING_SIZE_4096);
+ break;
+ }
+ bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
+ LPFC_DATA_BUF_SIZE);
}
bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
cq->queue_id);
bf_set(lpfc_mbx_rq_create_num_pages, &rq_create->u.request,
drq->page_count);
- bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
- LPFC_DATA_BUF_SIZE);
list_for_each_entry(dmabuf, &drq->page_list, list) {
rq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
putPaddrLow(dmabuf->phys);
@@ -10936,6 +11103,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
goto out;
}
drq->type = LPFC_DRQ;
+ drq->assoc_qid = cq->queue_id;
drq->subtype = subtype;
drq->host_index = 0;
drq->hba_index = 0;
@@ -11189,7 +11357,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
if (!mbox)
return -ENOMEM;
length = (sizeof(struct lpfc_mbx_rq_destroy) -
- sizeof(struct mbox_header));
+ sizeof(struct lpfc_sli4_cfg_mhdr));
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
LPFC_MBOX_OPCODE_FCOE_RQ_DESTROY,
length, LPFC_SLI4_MBX_EMBED);
@@ -11279,7 +11447,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba,
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES,
sizeof(struct lpfc_mbx_post_sgl_pages) -
- sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED);
+ sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED);
post_sgl_pages = (struct lpfc_mbx_post_sgl_pages *)
&mbox->u.mqe.un.post_sgl_pages;
@@ -11582,6 +11750,7 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
static char *rctl_names[] = FC_RCTL_NAMES_INIT;
char *type_names[] = FC_TYPE_NAMES_INIT;
struct fc_vft_header *fc_vft_hdr;
+ uint32_t *header = (uint32_t *) fc_hdr;
switch (fc_hdr->fh_r_ctl) {
case FC_RCTL_DD_UNCAT: /* uncategorized information */
@@ -11630,10 +11799,15 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
default:
goto drop;
}
+
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "2538 Received frame rctl:%s type:%s\n",
+ "2538 Received frame rctl:%s type:%s "
+ "Frame Data:%08x %08x %08x %08x %08x %08x\n",
rctl_names[fc_hdr->fh_r_ctl],
- type_names[fc_hdr->fh_type]);
+ type_names[fc_hdr->fh_type],
+ be32_to_cpu(header[0]), be32_to_cpu(header[1]),
+ be32_to_cpu(header[2]), be32_to_cpu(header[3]),
+ be32_to_cpu(header[4]), be32_to_cpu(header[5]));
return 0;
drop:
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
@@ -11930,17 +12104,17 @@ lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport,
}
/**
- * lpfc_sli4_seq_abort_acc_cmpl - Accept seq abort iocb complete handler
+ * lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler
* @phba: Pointer to HBA context object.
* @cmd_iocbq: pointer to the command iocbq structure.
* @rsp_iocbq: pointer to the response iocbq structure.
*
- * This function handles the sequence abort accept iocb command complete
+ * This function handles the sequence abort response iocb command complete
* event. It properly releases the memory allocated to the sequence abort
* accept iocb.
**/
static void
-lpfc_sli4_seq_abort_acc_cmpl(struct lpfc_hba *phba,
+lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba,
struct lpfc_iocbq *cmd_iocbq,
struct lpfc_iocbq *rsp_iocbq)
{
@@ -11949,15 +12123,15 @@ lpfc_sli4_seq_abort_acc_cmpl(struct lpfc_hba *phba,
}
/**
- * lpfc_sli4_seq_abort_acc - Accept sequence abort
+ * lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort
* @phba: Pointer to HBA context object.
* @fc_hdr: pointer to a FC frame header.
*
- * This function sends a basic accept to a previous unsol sequence abort
+ * This function sends a basic response to a previous unsol sequence abort
* event after aborting the sequence handling.
**/
static void
-lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
+lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
struct fc_frame_header *fc_hdr)
{
struct lpfc_iocbq *ctiocb = NULL;
@@ -11965,6 +12139,7 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
uint16_t oxid, rxid;
uint32_t sid, fctl;
IOCB_t *icmd;
+ int rc;
if (!lpfc_is_link_up(phba))
return;
@@ -11985,7 +12160,7 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
+ phba->sli4_hba.max_cfg_param.xri_base))
lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0);
- /* Allocate buffer for acc iocb */
+ /* Allocate buffer for rsp iocb */
ctiocb = lpfc_sli_get_iocbq(phba);
if (!ctiocb)
return;
@@ -12010,32 +12185,54 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
ctiocb->iocb_cmpl = NULL;
ctiocb->vport = phba->pport;
- ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_acc_cmpl;
+ ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl;
+ ctiocb->sli4_xritag = NO_XRI;
+
+ /* If the oxid maps to the FCP XRI range or if it is out of range,
+ * send a BLS_RJT. The driver no longer has that exchange.
+ * Override the IOCB for a BA_RJT.
+ */
+ if (oxid > (phba->sli4_hba.max_cfg_param.max_xri +
+ phba->sli4_hba.max_cfg_param.xri_base) ||
+ oxid > (lpfc_sli4_get_els_iocb_cnt(phba) +
+ phba->sli4_hba.max_cfg_param.xri_base)) {
+ icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT;
+ bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0);
+ bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID);
+ bf_set(lpfc_rsn_code, &icmd->un.bls_rsp, FC_BA_RJT_UNABLE);
+ }
if (fctl & FC_FC_EX_CTX) {
/* ABTS sent by responder to CT exchange, construction
* of BA_ACC will use OX_ID from ABTS for the XRI_TAG
* field and RX_ID from ABTS for RX_ID field.
*/
- bf_set(lpfc_abts_orig, &icmd->un.bls_acc, LPFC_ABTS_UNSOL_RSP);
- bf_set(lpfc_abts_rxid, &icmd->un.bls_acc, rxid);
- ctiocb->sli4_xritag = oxid;
+ bf_set(lpfc_abts_orig, &icmd->un.bls_rsp, LPFC_ABTS_UNSOL_RSP);
+ bf_set(lpfc_abts_rxid, &icmd->un.bls_rsp, rxid);
} else {
/* ABTS sent by initiator to CT exchange, construction
* of BA_ACC will need to allocate a new XRI as for the
* XRI_TAG and RX_ID fields.
*/
- bf_set(lpfc_abts_orig, &icmd->un.bls_acc, LPFC_ABTS_UNSOL_INT);
- bf_set(lpfc_abts_rxid, &icmd->un.bls_acc, NO_XRI);
- ctiocb->sli4_xritag = NO_XRI;
+ bf_set(lpfc_abts_orig, &icmd->un.bls_rsp, LPFC_ABTS_UNSOL_INT);
+ bf_set(lpfc_abts_rxid, &icmd->un.bls_rsp, NO_XRI);
}
- bf_set(lpfc_abts_oxid, &icmd->un.bls_acc, oxid);
+ bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid);
- /* Xmit CT abts accept on exchange <xid> */
+ /* Xmit CT abts response on exchange <xid> */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "1200 Xmit CT ABTS ACC on exchange x%x Data: x%x\n",
- CMD_XMIT_BLS_RSP64_CX, phba->link_state);
- lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
+ "1200 Send BLS cmd x%x on oxid x%x Data: x%x\n",
+ icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state);
+
+ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
+ if (rc == IOCB_ERROR) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+ "2925 Failed to issue CT ABTS RSP x%x on "
+ "xri x%x, Data x%x\n",
+ icmd->un.xseq64.w5.hcsw.Rctl, oxid,
+ phba->link_state);
+ lpfc_sli_release_iocbq(phba, ctiocb);
+ }
}
/**
@@ -12083,7 +12280,7 @@ lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport,
lpfc_in_buf_free(phba, &dmabuf->dbuf);
}
/* Send basic accept (BA_ACC) to the abort requester */
- lpfc_sli4_seq_abort_acc(phba, &fc_hdr);
+ lpfc_sli4_seq_abort_rsp(phba, &fc_hdr);
}
/**
@@ -12402,7 +12599,8 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE,
sizeof(struct lpfc_mbx_post_hdr_tmpl) -
- sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED);
+ sizeof(struct lpfc_sli4_cfg_mhdr),
+ LPFC_SLI4_MBX_EMBED);
bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt,
hdr_tmpl, rpi_page->page_count);
bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl,
OpenPOWER on IntegriCloud