From a93ff37a8a869c7065a1b05f75e69bfb74eb599c Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 22 Oct 2010 11:06:08 -0400 Subject: [SCSI] lpfc 8.3.18: Add logic to detect last devloss timeout Added driver logic to detect the last devloss timeout of remote nodes which was still in use of FCF. At that point, the driver should set the last in-use remote node devloss timeout flag if it was not already set and should perform proper action on the in-use FCF and recover of FCF from firmware, depending on the state the driver's FIP engine is in. Find eligible FCF through FCF table rescan or the next new FCF event when FCF table rescan turned out empty eligible FCF, and the successful flogi into an FCF shall clear the HBA_DEVLOSS_TMO flag, indicating the successful recovery from devloss timeout. [jejb: add delay.h include to lpfc_hbadisc.c to fix ppc compile] Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_sli.c | 72 +++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 48 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_sli.c') diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 0d1e187b005..9d2e1347cb1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -5921,7 +5921,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, * lpfc_sli4_scmd_to_wqidx_distr - scsi command to SLI4 WQ index distribution * @phba: Pointer to HBA context object. * - * This routine performs a round robin SCSI command to SLI4 FCP WQ index + * This routine performs a roundrobin SCSI command to SLI4 FCP WQ index * distribution. This is called by __lpfc_sli_issue_iocb_s4() with the hbalock * held. * @@ -12242,13 +12242,15 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) /* Issue the mailbox command asynchronously */ mboxq->vport = phba->pport; mboxq->mbox_cmpl = lpfc_mbx_cmpl_fcf_scan_read_fcf_rec; + + spin_lock_irq(&phba->hbalock); + phba->hba_flag |= FCF_TS_INPROG; + spin_unlock_irq(&phba->hbalock); + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) error = -EIO; else { - spin_lock_irq(&phba->hbalock); - phba->hba_flag |= FCF_DISC_INPROGRESS; - spin_unlock_irq(&phba->hbalock); /* Reset eligible FCF count for new scan */ if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) phba->fcf.eligible_fcf_cnt = 0; @@ -12258,21 +12260,21 @@ fail_fcf_scan: if (error) { if (mboxq) lpfc_sli4_mbox_cmd_free(phba, mboxq); - /* FCF scan failed, clear FCF_DISC_INPROGRESS flag */ + /* FCF scan failed, clear FCF_TS_INPROG flag */ spin_lock_irq(&phba->hbalock); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~FCF_TS_INPROG; spin_unlock_irq(&phba->hbalock); } return error; } /** - * lpfc_sli4_fcf_rr_read_fcf_rec - Read hba fcf record for round robin fcf. + * lpfc_sli4_fcf_rr_read_fcf_rec - Read hba fcf record for roundrobin fcf. * @phba: pointer to lpfc hba data structure. * @fcf_index: FCF table entry offset. * * This routine is invoked to read an FCF record indicated by @fcf_index - * and to use it for FLOGI round robin FCF failover. + * and to use it for FLOGI roundrobin FCF failover. * * Return 0 if the mailbox command is submitted sucessfully, none 0 * otherwise. @@ -12318,7 +12320,7 @@ fail_fcf_read: * @fcf_index: FCF table entry offset. * * This routine is invoked to read an FCF record indicated by @fcf_index to - * determine whether it's eligible for FLOGI round robin failover list. + * determine whether it's eligible for FLOGI roundrobin failover list. * * Return 0 if the mailbox command is submitted sucessfully, none 0 * otherwise. @@ -12364,7 +12366,7 @@ fail_fcf_read: * * This routine is to get the next eligible FCF record index in a round * robin fashion. If the next eligible FCF record index equals to the - * initial round robin FCF record index, LPFC_FCOE_FCF_NEXT_NONE (0xFFFF) + * initial roundrobin FCF record index, LPFC_FCOE_FCF_NEXT_NONE (0xFFFF) * shall be returned, otherwise, the next eligible FCF record's index * shall be returned. **/ @@ -12392,28 +12394,10 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba) return LPFC_FCOE_FCF_NEXT_NONE; } - /* Check roundrobin failover index bmask stop condition */ - if (next_fcf_index == phba->fcf.fcf_rr_init_indx) { - if (!(phba->fcf.fcf_flag & FCF_REDISC_RRU)) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, - "2847 Round robin failover FCF index " - "search hit stop condition:x%x\n", - next_fcf_index); - return LPFC_FCOE_FCF_NEXT_NONE; - } - /* The roundrobin failover index bmask updated, start over */ - lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2848 Round robin failover FCF index bmask " - "updated, start over\n"); - spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag &= ~FCF_REDISC_RRU; - spin_unlock_irq(&phba->hbalock); - return phba->fcf.fcf_rr_init_indx; - } - lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2845 Get next round robin failover " - "FCF index x%x\n", next_fcf_index); + "2845 Get next roundrobin failover FCF (x%x)\n", + next_fcf_index); + return next_fcf_index; } @@ -12422,7 +12406,7 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba) * @phba: pointer to lpfc hba data structure. * * This routine sets the FCF record index in to the eligible bmask for - * round robin failover search. It checks to make sure that the index + * roundrobin failover search. It checks to make sure that the index * does not go beyond the range of the driver allocated bmask dimension * before setting the bit. * @@ -12434,22 +12418,16 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index) { if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) { lpfc_printf_log(phba, KERN_ERR, LOG_FIP, - "2610 HBA FCF index reached driver's " - "book keeping dimension: fcf_index:%d, " - "driver_bmask_max:%d\n", + "2610 FCF (x%x) reached driver's book " + "keeping dimension:x%x\n", fcf_index, LPFC_SLI4_FCF_TBL_INDX_MAX); return -EINVAL; } /* Set the eligible FCF record index bmask */ set_bit(fcf_index, phba->fcf.fcf_rr_bmask); - /* Set the roundrobin index bmask updated */ - spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag |= FCF_REDISC_RRU; - spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2790 Set FCF index x%x to round robin failover " + "2790 Set FCF (x%x) to roundrobin FCF failover " "bmask\n", fcf_index); return 0; @@ -12460,7 +12438,7 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index) * @phba: pointer to lpfc hba data structure. * * This routine clears the FCF record index from the eligible bmask for - * round robin failover search. It checks to make sure that the index + * roundrobin failover search. It checks to make sure that the index * does not go beyond the range of the driver allocated bmask dimension * before clearing the bit. **/ @@ -12469,9 +12447,8 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index) { if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) { lpfc_printf_log(phba, KERN_ERR, LOG_FIP, - "2762 HBA FCF index goes beyond driver's " - "book keeping dimension: fcf_index:%d, " - "driver_bmask_max:%d\n", + "2762 FCF (x%x) reached driver's book " + "keeping dimension:x%x\n", fcf_index, LPFC_SLI4_FCF_TBL_INDX_MAX); return; } @@ -12479,7 +12456,7 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index) clear_bit(fcf_index, phba->fcf.fcf_rr_bmask); lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2791 Clear FCF index x%x from round robin failover " + "2791 Clear FCF (x%x) from roundrobin failover " "bmask\n", fcf_index); } @@ -12530,8 +12507,7 @@ lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) } } else { lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2775 Start FCF rediscovery quiescent period " - "wait timer before scaning FCF table\n"); + "2775 Start FCF rediscover quiescent timer\n"); /* * Start FCF rediscovery wait timer for pending FCF * before rescan FCF record table. -- cgit v1.2.3-70-g09d2 From 5af5eee7ca4051d8ca31edeb5216831da9625b5c Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 22 Oct 2010 11:06:38 -0400 Subject: [SCSI] lpfc 8.3.18: Adapter Shutdown and Unregistration cleanup Adapter Shutdown and Unregistration cleanup - Correct the logic around hba shutdown. Prior to final reset, the driver must wait for all XRIs to return from the adapter. Added logic to poll, progressively slowing the poll rate as delay gets longer. - Correct behavior around the rsvd1 field in UNREG_RPI_ALL mailbox completion and final rpi cleanup. - Updated logic to move pending VPI registrations to their completion in cases where a CVL may be received while registration in progress. - Added unreg all rpi mailbox command before unreg vpi. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_crtn.h | 3 + drivers/scsi/lpfc/lpfc_els.c | 10 +++ drivers/scsi/lpfc/lpfc_hbadisc.c | 9 +++ drivers/scsi/lpfc/lpfc_init.c | 52 +++++++++++++ drivers/scsi/lpfc/lpfc_mbox.c | 28 +++++++ drivers/scsi/lpfc/lpfc_sli.c | 158 ++++++++++++++++++++++++++++++++------- drivers/scsi/lpfc/lpfc_sli4.h | 3 + 7 files changed, 235 insertions(+), 28 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_sli.c') diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index b15d13e5617..a5f5a093a8a 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -44,6 +44,8 @@ int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); +void lpfc_sli4_unreg_all_rpis(struct lpfc_vport *); + void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *, struct lpfc_nodelist *); @@ -272,6 +274,7 @@ int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); void lpfc_sli_bemem_bcopy(void *, void *, uint32_t); void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *); +void lpfc_sli_hba_iocb_abort(struct lpfc_hba *); void lpfc_sli_flush_fcp_rings(struct lpfc_hba *); int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_dmabuf *); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index b115e92025e..e61b57df241 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -580,6 +580,10 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_unreg_rpi(vport, np); } lpfc_cleanup_pending_mbox(vport); + + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vport); + if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { lpfc_mbx_unreg_vpi(vport); spin_lock_irq(shost->host_lock); @@ -6482,6 +6486,8 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) default: /* Try to recover from this error */ + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vport); lpfc_mbx_unreg_vpi(vport); spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; @@ -6749,6 +6755,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_unreg_rpi(vport, np); } lpfc_cleanup_pending_mbox(vport); + + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vport); + lpfc_mbx_unreg_vpi(vport); spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 05c9398a723..a5d1695dac3 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -794,6 +794,8 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) : NLP_EVT_DEVICE_RECOVERY); } if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) { + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vport); lpfc_mbx_unreg_vpi(vport); spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; @@ -4080,6 +4082,11 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) LPFC_MBOXQ_t *mbox; int rc; + if (phba->sli_rev == LPFC_SLI_REV4) { + lpfc_sli4_unreg_all_rpis(vport); + return; + } + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (mbox) { lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox); @@ -5354,6 +5361,8 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) if (ndlp) lpfc_cancel_retry_delay_tmo(vports[i], ndlp); lpfc_cleanup_pending_mbox(vports[i]); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vports[i]); lpfc_mbx_unreg_vpi(vports[i]); shost = lpfc_shost_from_vport(vports[i]); spin_lock_irq(shost->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 814d0b324d7..b3065791f30 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -813,6 +813,7 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba) return 0; } + /** * lpfc_hba_down_post_s4 - Perform lpfc uninitialization after HBA reset * @phba: pointer to lpfc HBA data structure. @@ -7266,6 +7267,51 @@ lpfc_sli4_unset_hba(struct lpfc_hba *phba) return; } +/** + * lpfc_sli4_xri_exchange_busy_wait - Wait for device XRI exchange busy + * @phba: Pointer to HBA context object. + * + * This function is called in the SLI4 code path to wait for completion + * of device's XRIs exchange busy. It will check the XRI exchange busy + * on outstanding FCP and ELS I/Os every 10ms for up to 10 seconds; after + * that, it will check the XRI exchange busy on outstanding FCP and ELS + * I/Os every 30 seconds, log error message, and wait forever. Only when + * all XRI exchange busy complete, the driver unload shall proceed with + * invoking the function reset ioctl mailbox command to the CNA and the + * the rest of the driver unload resource release. + **/ +static void +lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba) +{ + int wait_time = 0; + int fcp_xri_cmpl = list_empty(&phba->sli4_hba.lpfc_abts_scsi_buf_list); + int els_xri_cmpl = list_empty(&phba->sli4_hba.lpfc_abts_els_sgl_list); + + while (!fcp_xri_cmpl || !els_xri_cmpl) { + if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) { + if (!fcp_xri_cmpl) + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2877 FCP XRI exchange busy " + "wait time: %d seconds.\n", + wait_time/1000); + if (!els_xri_cmpl) + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2878 ELS XRI exchange busy " + "wait time: %d seconds.\n", + wait_time/1000); + msleep(LPFC_XRI_EXCH_BUSY_WAIT_T2); + wait_time += LPFC_XRI_EXCH_BUSY_WAIT_T2; + } else { + msleep(LPFC_XRI_EXCH_BUSY_WAIT_T1); + wait_time += LPFC_XRI_EXCH_BUSY_WAIT_T1; + } + fcp_xri_cmpl = + list_empty(&phba->sli4_hba.lpfc_abts_scsi_buf_list); + els_xri_cmpl = + list_empty(&phba->sli4_hba.lpfc_abts_els_sgl_list); + } +} + /** * lpfc_sli4_hba_unset - Unset the fcoe hba * @phba: Pointer to HBA context object. @@ -7311,6 +7357,12 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) spin_unlock_irq(&phba->hbalock); } + /* Abort all iocbs associated with the hba */ + lpfc_sli_hba_iocb_abort(phba); + + /* Wait for completion of device XRI exchange busy */ + lpfc_sli4_xri_exchange_busy_wait(phba); + /* Disable PCI subsystem interrupt */ lpfc_sli4_disable_intr(phba); diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 0dfa310cd60..62d0957e1d4 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -796,6 +796,34 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, return; } +/** + * lpfc_sli4_unreg_all_rpis - unregister all RPIs for a vport on SLI4 HBA. + * @vport: pointer to a vport object. + * + * This routine sends mailbox command to unregister all active RPIs for + * a vport. + **/ +void +lpfc_sli4_unreg_all_rpis(struct lpfc_vport *vport) +{ + struct lpfc_hba *phba = vport->phba; + LPFC_MBOXQ_t *mbox; + int rc; + + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (mbox) { + lpfc_unreg_login(phba, vport->vpi, + vport->vpi + phba->vpi_base, mbox); + mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000 ; + mbox->vport = vport; + mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + mbox->context1 = NULL; + rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) + mempool_free(mbox, phba->mbox_mem_pool); + } +} + /** * lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier * @phba: pointer to lpfc hba data structure. diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 9d2e1347cb1..ce4145377ef 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1735,6 +1735,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) struct lpfc_vport *vport = pmb->vport; struct lpfc_dmabuf *mp; struct lpfc_nodelist *ndlp; + struct Scsi_Host *shost; uint16_t rpi, vpi; int rc; @@ -1746,7 +1747,8 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) && - (phba->sli_rev == LPFC_SLI_REV4)) + (phba->sli_rev == LPFC_SLI_REV4) && + (pmb->u.mb.un.varUnregLogin.rsvd1 == 0x0)) lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi); /* @@ -1765,16 +1767,14 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) return; } - /* Unreg VPI, if the REG_VPI succeed after VLink failure */ if ((pmb->u.mb.mbxCommand == MBX_REG_VPI) && !(phba->pport->load_flag & FC_UNLOADING) && !pmb->u.mb.mbxStatus) { - lpfc_unreg_vpi(phba, pmb->u.mb.un.varRegVpi.vpi, pmb); - pmb->vport = vport; - pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); - if (rc != MBX_NOT_FINISHED) - return; + shost = lpfc_shost_from_vport(vport); + spin_lock_irq(shost->host_lock); + vport->vpi_state |= LPFC_VPI_REGISTERED; + vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; + spin_unlock_irq(shost->host_lock); } if (pmb->u.mb.mbxCommand == MBX_REG_LOGIN64) { @@ -7257,25 +7257,26 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_sli_issue_abort_iotag - Abort function for a command iocb + * lpfc_sli_abort_iotag_issue - Issue abort for a command iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @cmdiocb: Pointer to driver command iocb object. * - * This function issues an abort iocb for the provided command - * iocb. This function is called with hbalock held. - * The function returns 0 when it fails due to memory allocation - * failure or when the command iocb is an abort request. + * This function issues an abort iocb for the provided command iocb down to + * the port. Other than the case the outstanding command iocb is an abort + * request, this function issues abort out unconditionally. This function is + * called with hbalock held. The function returns 0 when it fails due to + * memory allocation failure or when the command iocb is an abort request. **/ -int -lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, +static int +lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *cmdiocb) { struct lpfc_vport *vport = cmdiocb->vport; struct lpfc_iocbq *abtsiocbp; IOCB_t *icmd = NULL; IOCB_t *iabt = NULL; - int retval = IOCB_ERROR; + int retval; /* * There are certain command types we don't want to abort. And we @@ -7288,18 +7289,6 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) return 0; - /* If we're unloading, don't abort iocb on the ELS ring, but change the - * callback so that nothing happens when it finishes. - */ - if ((vport->load_flag & FC_UNLOADING) && - (pring->ringno == LPFC_ELS_RING)) { - if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) - cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; - else - cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; - goto abort_iotag_exit; - } - /* issue ABTS for this IOCB based on iotag */ abtsiocbp = __lpfc_sli_get_iocbq(phba); if (abtsiocbp == NULL) @@ -7344,6 +7333,63 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (retval) __lpfc_sli_release_iocbq(phba, abtsiocbp); + + /* + * Caller to this routine should check for IOCB_ERROR + * and handle it properly. This routine no longer removes + * iocb off txcmplq and call compl in case of IOCB_ERROR. + */ + return retval; +} + +/** + * lpfc_sli_issue_abort_iotag - Abort function for a command iocb + * @phba: Pointer to HBA context object. + * @pring: Pointer to driver SLI ring object. + * @cmdiocb: Pointer to driver command iocb object. + * + * This function issues an abort iocb for the provided command iocb. In case + * of unloading, the abort iocb will not be issued to commands on the ELS + * ring. Instead, the callback function shall be changed to those commands + * so that nothing happens when them finishes. This function is called with + * hbalock held. The function returns 0 when the command iocb is an abort + * request. + **/ +int +lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + struct lpfc_iocbq *cmdiocb) +{ + struct lpfc_vport *vport = cmdiocb->vport; + int retval = IOCB_ERROR; + IOCB_t *icmd = NULL; + + /* + * There are certain command types we don't want to abort. And we + * don't want to abort commands that are already in the process of + * being aborted. + */ + icmd = &cmdiocb->iocb; + if (icmd->ulpCommand == CMD_ABORT_XRI_CN || + icmd->ulpCommand == CMD_CLOSE_XRI_CN || + (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) + return 0; + + /* + * If we're unloading, don't abort iocb on the ELS ring, but change + * the callback so that nothing happens when it finishes. + */ + if ((vport->load_flag & FC_UNLOADING) && + (pring->ringno == LPFC_ELS_RING)) { + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) + cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; + else + cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; + goto abort_iotag_exit; + } + + /* Now, we try to issue the abort to the cmdiocb out */ + retval = lpfc_sli_abort_iotag_issue(phba, pring, cmdiocb); + abort_iotag_exit: /* * Caller to this routine should check for IOCB_ERROR @@ -7353,6 +7399,62 @@ abort_iotag_exit: return retval; } +/** + * lpfc_sli_iocb_ring_abort - Unconditionally abort all iocbs on an iocb ring + * @phba: Pointer to HBA context object. + * @pring: Pointer to driver SLI ring object. + * + * This function aborts all iocbs in the given ring and frees all the iocb + * objects in txq. This function issues abort iocbs unconditionally for all + * the iocb commands in txcmplq. The iocbs in the txcmplq is not guaranteed + * to complete before the return of this function. The caller is not required + * to hold any locks. + **/ +static void +lpfc_sli_iocb_ring_abort(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) +{ + LIST_HEAD(completions); + struct lpfc_iocbq *iocb, *next_iocb; + + if (pring->ringno == LPFC_ELS_RING) + lpfc_fabric_abort_hba(phba); + + spin_lock_irq(&phba->hbalock); + + /* Take off all the iocbs on txq for cancelling */ + list_splice_init(&pring->txq, &completions); + pring->txq_cnt = 0; + + /* Next issue ABTS for everything on the txcmplq */ + list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) + lpfc_sli_abort_iotag_issue(phba, pring, iocb); + + spin_unlock_irq(&phba->hbalock); + + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); +} + +/** + * lpfc_sli_hba_iocb_abort - Abort all iocbs to an hba. + * @phba: pointer to lpfc HBA data structure. + * + * This routine will abort all pending and outstanding iocbs to an HBA. + **/ +void +lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba) +{ + struct lpfc_sli *psli = &phba->sli; + struct lpfc_sli_ring *pring; + int i; + + for (i = 0; i < psli->num_rings; i++) { + pring = &psli->ring[i]; + lpfc_sli_iocb_ring_abort(phba, pring); + } +} + /** * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN * @iocbq: Pointer to driver iocb object. diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 98da223e19e..c4483feb8b7 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -19,6 +19,9 @@ *******************************************************************/ #define LPFC_ACTIVE_MBOX_WAIT_CNT 100 +#define LPFC_XRI_EXCH_BUSY_WAIT_TMO 10000 +#define LPFC_XRI_EXCH_BUSY_WAIT_T1 10 +#define LPFC_XRI_EXCH_BUSY_WAIT_T2 30000 #define LPFC_RELEASE_NOTIFICATION_INTERVAL 32 #define LPFC_GET_QE_REL_INT 32 #define LPFC_RPI_LOW_WATER_MARK 10 -- cgit v1.2.3-70-g09d2 From f0d9bccc9084b8fe86fa2830a434259d140679c9 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 22 Oct 2010 11:07:09 -0400 Subject: [SCSI] lpfc 8.3.18: Add new WQE support - Add new WQE fields as defined by new SLI interface to support new hardware. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 9 +- drivers/scsi/lpfc/lpfc_hw4.h | 167 +++++++++++++------------------ drivers/scsi/lpfc/lpfc_sli.c | 228 +++++++++++++++++++++++-------------------- 3 files changed, 197 insertions(+), 207 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_sli.c') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e61b57df241..884f4d32179 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -177,15 +177,18 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, (elscmd == ELS_CMD_LOGO))) switch (elscmd) { case ELS_CMD_FLOGI: - elsiocb->iocb_flag |= ((ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) + elsiocb->iocb_flag |= + ((LPFC_ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; case ELS_CMD_FDISC: - elsiocb->iocb_flag |= ((ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) + elsiocb->iocb_flag |= + ((LPFC_ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; case ELS_CMD_LOGO: - elsiocb->iocb_flag |= ((ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) + elsiocb->iocb_flag |= + ((LPFC_ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; } diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index bbdcf96800f..6e4bc34e1d0 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -424,79 +424,6 @@ struct lpfc_rcqe { #define FCOE_SOFn3 0x36 }; -struct lpfc_wqe_generic{ - struct ulp_bde64 bde; - uint32_t word3; - uint32_t word4; - uint32_t word5; - uint32_t word6; -#define lpfc_wqe_gen_context_SHIFT 16 -#define lpfc_wqe_gen_context_MASK 0x0000FFFF -#define lpfc_wqe_gen_context_WORD word6 -#define lpfc_wqe_gen_xri_SHIFT 0 -#define lpfc_wqe_gen_xri_MASK 0x0000FFFF -#define lpfc_wqe_gen_xri_WORD word6 - uint32_t word7; -#define lpfc_wqe_gen_lnk_SHIFT 23 -#define lpfc_wqe_gen_lnk_MASK 0x00000001 -#define lpfc_wqe_gen_lnk_WORD word7 -#define lpfc_wqe_gen_erp_SHIFT 22 -#define lpfc_wqe_gen_erp_MASK 0x00000001 -#define lpfc_wqe_gen_erp_WORD word7 -#define lpfc_wqe_gen_pu_SHIFT 20 -#define lpfc_wqe_gen_pu_MASK 0x00000003 -#define lpfc_wqe_gen_pu_WORD word7 -#define lpfc_wqe_gen_class_SHIFT 16 -#define lpfc_wqe_gen_class_MASK 0x00000007 -#define lpfc_wqe_gen_class_WORD word7 -#define lpfc_wqe_gen_command_SHIFT 8 -#define lpfc_wqe_gen_command_MASK 0x000000FF -#define lpfc_wqe_gen_command_WORD word7 -#define lpfc_wqe_gen_status_SHIFT 4 -#define lpfc_wqe_gen_status_MASK 0x0000000F -#define lpfc_wqe_gen_status_WORD word7 -#define lpfc_wqe_gen_ct_SHIFT 2 -#define lpfc_wqe_gen_ct_MASK 0x00000003 -#define lpfc_wqe_gen_ct_WORD word7 - uint32_t abort_tag; - uint32_t word9; -#define lpfc_wqe_gen_request_tag_SHIFT 0 -#define lpfc_wqe_gen_request_tag_MASK 0x0000FFFF -#define lpfc_wqe_gen_request_tag_WORD word9 - uint32_t word10; -#define lpfc_wqe_gen_ccp_SHIFT 24 -#define lpfc_wqe_gen_ccp_MASK 0x000000FF -#define lpfc_wqe_gen_ccp_WORD word10 -#define lpfc_wqe_gen_ccpe_SHIFT 23 -#define lpfc_wqe_gen_ccpe_MASK 0x00000001 -#define lpfc_wqe_gen_ccpe_WORD word10 -#define lpfc_wqe_gen_pv_SHIFT 19 -#define lpfc_wqe_gen_pv_MASK 0x00000001 -#define lpfc_wqe_gen_pv_WORD word10 -#define lpfc_wqe_gen_pri_SHIFT 16 -#define lpfc_wqe_gen_pri_MASK 0x00000007 -#define lpfc_wqe_gen_pri_WORD word10 - uint32_t word11; -#define lpfc_wqe_gen_cq_id_SHIFT 16 -#define lpfc_wqe_gen_cq_id_MASK 0x0000FFFF -#define lpfc_wqe_gen_cq_id_WORD word11 -#define LPFC_WQE_CQ_ID_DEFAULT 0xffff -#define lpfc_wqe_gen_wqec_SHIFT 7 -#define lpfc_wqe_gen_wqec_MASK 0x00000001 -#define lpfc_wqe_gen_wqec_WORD word11 -#define ELS_ID_FLOGI 3 -#define ELS_ID_FDISC 2 -#define ELS_ID_LOGO 1 -#define ELS_ID_DEFAULT 0 -#define lpfc_wqe_gen_els_id_SHIFT 4 -#define lpfc_wqe_gen_els_id_MASK 0x00000003 -#define lpfc_wqe_gen_els_id_WORD word11 -#define lpfc_wqe_gen_cmd_type_SHIFT 0 -#define lpfc_wqe_gen_cmd_type_MASK 0x0000000F -#define lpfc_wqe_gen_cmd_type_WORD word11 - uint32_t payload[4]; -}; - struct lpfc_rqe { uint32_t address_hi; uint32_t address_lo; @@ -2279,9 +2206,36 @@ struct wqe_common { #define wqe_reqtag_MASK 0x0000FFFF #define wqe_reqtag_WORD word9 #define wqe_rcvoxid_SHIFT 16 -#define wqe_rcvoxid_MASK 0x0000FFFF -#define wqe_rcvoxid_WORD word9 +#define wqe_rcvoxid_MASK 0x0000FFFF +#define wqe_rcvoxid_WORD word9 uint32_t word10; +#define wqe_ebde_cnt_SHIFT 0 +#define wqe_ebde_cnt_MASK 0x00000007 +#define wqe_ebde_cnt_WORD word10 +#define wqe_lenloc_SHIFT 7 +#define wqe_lenloc_MASK 0x00000003 +#define wqe_lenloc_WORD word10 +#define LPFC_WQE_LENLOC_NONE 0 +#define LPFC_WQE_LENLOC_WORD3 1 +#define LPFC_WQE_LENLOC_WORD12 2 +#define LPFC_WQE_LENLOC_WORD4 3 +#define wqe_qosd_SHIFT 9 +#define wqe_qosd_MASK 0x00000001 +#define wqe_qosd_WORD word10 +#define wqe_xbl_SHIFT 11 +#define wqe_xbl_MASK 0x00000001 +#define wqe_xbl_WORD word10 +#define wqe_iod_SHIFT 13 +#define wqe_iod_MASK 0x00000001 +#define wqe_iod_WORD word10 +#define LPFC_WQE_IOD_WRITE 0 +#define LPFC_WQE_IOD_READ 1 +#define wqe_dbde_SHIFT 14 +#define wqe_dbde_MASK 0x00000001 +#define wqe_dbde_WORD word10 +#define wqe_wqes_SHIFT 15 +#define wqe_wqes_MASK 0x00000001 +#define wqe_wqes_WORD word10 #define wqe_pri_SHIFT 16 #define wqe_pri_MASK 0x00000007 #define wqe_pri_WORD word10 @@ -2295,18 +2249,26 @@ struct wqe_common { #define wqe_ccpe_MASK 0x00000001 #define wqe_ccpe_WORD word10 #define wqe_ccp_SHIFT 24 -#define wqe_ccp_MASK 0x000000ff -#define wqe_ccp_WORD word10 +#define wqe_ccp_MASK 0x000000ff +#define wqe_ccp_WORD word10 uint32_t word11; -#define wqe_cmd_type_SHIFT 0 -#define wqe_cmd_type_MASK 0x0000000f -#define wqe_cmd_type_WORD word11 -#define wqe_wqec_SHIFT 7 -#define wqe_wqec_MASK 0x00000001 -#define wqe_wqec_WORD word11 -#define wqe_cqid_SHIFT 16 -#define wqe_cqid_MASK 0x0000ffff -#define wqe_cqid_WORD word11 +#define wqe_cmd_type_SHIFT 0 +#define wqe_cmd_type_MASK 0x0000000f +#define wqe_cmd_type_WORD word11 +#define wqe_els_id_SHIFT 4 +#define wqe_els_id_MASK 0x00000003 +#define wqe_els_id_WORD word11 +#define LPFC_ELS_ID_FLOGI 3 +#define LPFC_ELS_ID_FDISC 2 +#define LPFC_ELS_ID_LOGO 1 +#define LPFC_ELS_ID_DEFAULT 0 +#define wqe_wqec_SHIFT 7 +#define wqe_wqec_MASK 0x00000001 +#define wqe_wqec_WORD word11 +#define wqe_cqid_SHIFT 16 +#define wqe_cqid_MASK 0x0000ffff +#define wqe_cqid_WORD word11 +#define LPFC_WQE_CQ_ID_DEFAULT 0xffff }; struct wqe_did { @@ -2325,6 +2287,15 @@ struct wqe_did { #define wqe_xmit_bls_xo_WORD word5 }; +struct lpfc_wqe_generic{ + struct ulp_bde64 bde; + uint32_t word3; + uint32_t word4; + uint32_t word5; + struct wqe_common wqe_com; + uint32_t payload[4]; +}; + struct els_request64_wqe { struct ulp_bde64 bde; uint32_t payload_len; @@ -2356,9 +2327,9 @@ struct els_request64_wqe { struct xmit_els_rsp64_wqe { struct ulp_bde64 bde; - uint32_t rsvd3; + uint32_t response_payload_len; uint32_t rsvd4; - struct wqe_did wqe_dest; + struct wqe_did wqe_dest; struct wqe_common wqe_com; /* words 6-11 */ uint32_t rsvd_12_15[4]; }; @@ -2427,7 +2398,7 @@ struct wqe_rctl_dfctl { struct xmit_seq64_wqe { struct ulp_bde64 bde; - uint32_t paylaod_offset; + uint32_t rsvd3; uint32_t relative_offset; struct wqe_rctl_dfctl wge_ctl; struct wqe_common wqe_com; /* words 6-11 */ @@ -2437,7 +2408,7 @@ struct xmit_seq64_wqe { }; struct xmit_bcast64_wqe { struct ulp_bde64 bde; - uint32_t paylaod_len; + uint32_t seq_payload_len; uint32_t rsvd4; struct wqe_rctl_dfctl wge_ctl; /* word 5 */ struct wqe_common wqe_com; /* words 6-11 */ @@ -2446,8 +2417,8 @@ struct xmit_bcast64_wqe { struct gen_req64_wqe { struct ulp_bde64 bde; - uint32_t command_len; - uint32_t payload_len; + uint32_t request_payload_len; + uint32_t relative_offset; struct wqe_rctl_dfctl wge_ctl; /* word 5 */ struct wqe_common wqe_com; /* words 6-11 */ uint32_t rsvd_12_15[4]; @@ -2480,7 +2451,7 @@ struct abort_cmd_wqe { struct fcp_iwrite64_wqe { struct ulp_bde64 bde; - uint32_t payload_len; + uint32_t payload_offset_len; uint32_t total_xfer_len; uint32_t initial_xfer_len; struct wqe_common wqe_com; /* words 6-11 */ @@ -2489,7 +2460,7 @@ struct fcp_iwrite64_wqe { struct fcp_iread64_wqe { struct ulp_bde64 bde; - uint32_t payload_len; /* word 3 */ + uint32_t payload_offset_len; /* word 3 */ uint32_t total_xfer_len; /* word 4 */ uint32_t rsrvd5; /* word 5 */ struct wqe_common wqe_com; /* words 6-11 */ @@ -2497,10 +2468,12 @@ struct fcp_iread64_wqe { }; struct fcp_icmnd64_wqe { - struct ulp_bde64 bde; /* words 0-2 */ - uint32_t rsrvd[3]; /* words 3-5 */ + struct ulp_bde64 bde; /* words 0-2 */ + uint32_t rsrvd3; /* word 3 */ + uint32_t rsrvd4; /* word 4 */ + uint32_t rsrvd5; /* word 5 */ struct wqe_common wqe_com; /* words 6-11 */ - uint32_t rsvd_12_15[4]; /* word 12-15 */ + uint32_t rsvd_12_15[4]; /* word 12-15 */ }; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index ce4145377ef..554efa6623f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -95,7 +95,7 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) return -ENOMEM; /* set consumption flag every once in a while */ if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL)) - bf_set(lpfc_wqe_gen_wqec, &wqe->generic, 1); + bf_set(wqe_wqec, &wqe->generic.wqe_com, 1); lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); @@ -5965,7 +5965,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, uint16_t abrt_iotag; struct lpfc_iocbq *abrtiocbq; struct ulp_bde64 *bpl = NULL; - uint32_t els_id = ELS_ID_DEFAULT; + uint32_t els_id = LPFC_ELS_ID_DEFAULT; int numBdes, i; struct ulp_bde64 bde; @@ -5982,7 +5982,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); abort_tag = (uint32_t) iocbq->iotag; xritag = iocbq->sli4_xritag; - wqe->words[7] = 0; /* The ct field has moved so reset */ + wqe->generic.wqe_com.word7 = 0; /* The ct field has moved so reset */ /* words0-2 bpl convert bde */ if (iocbq->iocb.un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) { numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize / @@ -6033,109 +6033,117 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, * contains the FCFI and remote N_Port_ID is * in word 5. */ - ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l); - bf_set(lpfc_wqe_gen_context, &wqe->generic, - iocbq->iocb.ulpContext); - - bf_set(lpfc_wqe_gen_ct, &wqe->generic, ct); - bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + iocbq->iocb.ulpContext); + bf_set(wqe_ct, &wqe->els_req.wqe_com, ct); + bf_set(wqe_pu, &wqe->els_req.wqe_com, 0); /* CCP CCPE PV PRI in word10 were set in the memcpy */ - if (command_type == ELS_COMMAND_FIP) { els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) >> LPFC_FIP_ELS_ID_SHIFT); } - bf_set(lpfc_wqe_gen_els_id, &wqe->generic, els_id); - + bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); + bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); + bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0); break; case CMD_XMIT_SEQUENCE64_CX: - bf_set(lpfc_wqe_gen_context, &wqe->generic, - iocbq->iocb.un.ulpWord[3]); - wqe->generic.word3 = 0; - bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext); + bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, + iocbq->iocb.un.ulpWord[3]); + bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, + iocbq->iocb.ulpContext); /* The entire sequence is transmitted for this IOCB */ xmit_len = total_len; cmnd = CMD_XMIT_SEQUENCE64_CR; case CMD_XMIT_SEQUENCE64_CR: - /* word3 iocb=io_tag32 wqe=payload_offset */ - /* payload offset used for multilpe outstanding - * sequences on the same exchange - */ - wqe->words[3] = 0; + /* word3 iocb=io_tag32 wqe=reserved */ + wqe->xmit_sequence.rsvd3 = 0; /* word4 relative_offset memcpy */ /* word5 r_ctl/df_ctl memcpy */ - bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); + bf_set(wqe_pu, &wqe->xmit_sequence.wqe_com, 0); + bf_set(wqe_dbde, &wqe->xmit_sequence.wqe_com, 1); + bf_set(wqe_iod, &wqe->xmit_sequence.wqe_com, + LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->xmit_sequence.wqe_com, + LPFC_WQE_LENLOC_WORD12); + bf_set(wqe_ebde_cnt, &wqe->xmit_sequence.wqe_com, 0); wqe->xmit_sequence.xmit_len = xmit_len; command_type = OTHER_COMMAND; break; case CMD_XMIT_BCAST64_CN: - /* word3 iocb=iotag32 wqe=payload_len */ - wqe->words[3] = 0; /* no definition for this in wqe */ + /* word3 iocb=iotag32 wqe=seq_payload_len */ + wqe->xmit_bcast64.seq_payload_len = xmit_len; /* word4 iocb=rsvd wqe=rsvd */ /* word5 iocb=rctl/type/df_ctl wqe=rctl/type/df_ctl memcpy */ /* word6 iocb=ctxt_tag/io_tag wqe=ctxt_tag/xri */ - bf_set(lpfc_wqe_gen_ct, &wqe->generic, + bf_set(wqe_ct, &wqe->xmit_bcast64.wqe_com, ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); + bf_set(wqe_dbde, &wqe->xmit_bcast64.wqe_com, 1); + bf_set(wqe_iod, &wqe->xmit_bcast64.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->xmit_bcast64.wqe_com, + LPFC_WQE_LENLOC_WORD3); + bf_set(wqe_ebde_cnt, &wqe->xmit_bcast64.wqe_com, 0); break; case CMD_FCP_IWRITE64_CR: command_type = FCP_COMMAND_DATA_OUT; - /* The struct for wqe fcp_iwrite has 3 fields that are somewhat - * confusing. - * word3 is payload_len: byte offset to the sgl entry for the - * fcp_command. - * word4 is total xfer len, same as the IOCB->ulpParameter. - * word5 is initial xfer len 0 = wait for xfer-ready - */ - - /* Always wait for xfer-ready before sending data */ - wqe->fcp_iwrite.initial_xfer_len = 0; - /* word 4 (xfer length) should have been set on the memcpy */ - - /* allow write to fall through to read */ + /* word3 iocb=iotag wqe=payload_offset_len */ + /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ + wqe->fcp_iwrite.payload_offset_len = + xmit_len + sizeof(struct fcp_rsp); + /* word4 iocb=parameter wqe=total_xfer_length memcpy */ + /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ + bf_set(wqe_erp, &wqe->fcp_iwrite.wqe_com, + iocbq->iocb.ulpFCP2Rcvy); + bf_set(wqe_lnk, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpXS); + /* Always open the exchange */ + bf_set(wqe_xc, &wqe->fcp_iwrite.wqe_com, 0); + bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, + LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_ebde_cnt, &wqe->fcp_iwrite.wqe_com, 0); + bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU); + break; case CMD_FCP_IREAD64_CR: - /* FCP_CMD is always the 1st sgl entry */ - wqe->fcp_iread.payload_len = + /* word3 iocb=iotag wqe=payload_offset_len */ + /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ + wqe->fcp_iread.payload_offset_len = xmit_len + sizeof(struct fcp_rsp); - - /* word 4 (xfer length) should have been set on the memcpy */ - - bf_set(lpfc_wqe_gen_erp, &wqe->generic, - iocbq->iocb.ulpFCP2Rcvy); - bf_set(lpfc_wqe_gen_lnk, &wqe->generic, iocbq->iocb.ulpXS); - /* The XC bit and the XS bit are similar. The driver never - * tracked whether or not the exchange was previouslly open. - * XC = Exchange create, 0 is create. 1 is already open. - * XS = link cmd: 1 do not close the exchange after command. - * XS = 0 close exchange when command completes. - * The only time we would not set the XC bit is when the XS bit - * is set and we are sending our 2nd or greater command on - * this exchange. - */ + /* word4 iocb=parameter wqe=total_xfer_length memcpy */ + /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ + bf_set(wqe_erp, &wqe->fcp_iread.wqe_com, + iocbq->iocb.ulpFCP2Rcvy); + bf_set(wqe_lnk, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpXS); /* Always open the exchange */ bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0); - - wqe->words[10] &= 0xffff0000; /* zero out ebde count */ - bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU); - break; + bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, + LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_ebde_cnt, &wqe->fcp_iread.wqe_com, 0); + bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU); + break; case CMD_FCP_ICMND64_CR: + /* word3 iocb=IO_TAG wqe=reserved */ + wqe->fcp_icmd.rsrvd3 = 0; + bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); /* 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, 0); + bf_set(wqe_xc, &wqe->fcp_icmd.wqe_com, 0); + bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, + LPFC_WQE_LENLOC_NONE); + bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0); break; case CMD_GEN_REQUEST64_CR: - /* word3 command length is described as byte offset to the - * rsp_data. Would always be 16, sizeof(struct sli4_sge) - * sgl[0] = cmnd - * sgl[1] = rsp. - * - */ - wqe->gen_req.command_len = xmit_len; - /* Word4 parameter copied in the memcpy */ - /* Word5 [rctl, type, df_ctl, la] copied in memcpy */ + /* word3 iocb=IO_TAG wqe=request_payload_len */ + wqe->gen_req.request_payload_len = xmit_len; + /* word4 iocb=parameter wqe=relative_offset memcpy */ + /* word5 [rctl, type, df_ctl, la] copied in memcpy */ /* word6 context tag copied in memcpy */ if (iocbq->iocb.ulpCt_h || iocbq->iocb.ulpCt_l) { ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l); @@ -6144,31 +6152,39 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, ct, iocbq->iocb.ulpCommand); return IOCB_ERROR; } - bf_set(lpfc_wqe_gen_ct, &wqe->generic, 0); - bf_set(wqe_tmo, &wqe->gen_req.wqe_com, - iocbq->iocb.ulpTimeout); - - bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU); + bf_set(wqe_ct, &wqe->gen_req.wqe_com, 0); + bf_set(wqe_tmo, &wqe->gen_req.wqe_com, iocbq->iocb.ulpTimeout); + bf_set(wqe_pu, &wqe->gen_req.wqe_com, iocbq->iocb.ulpPU); + bf_set(wqe_dbde, &wqe->gen_req.wqe_com, 1); + bf_set(wqe_iod, &wqe->gen_req.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0); command_type = OTHER_COMMAND; break; case CMD_XMIT_ELS_RSP64_CX: /* words0-2 BDE memcpy */ - /* word3 iocb=iotag32 wqe=rsvd */ - wqe->words[3] = 0; + /* word3 iocb=iotag32 wqe=response_payload_len */ + wqe->xmit_els_rsp.response_payload_len = xmit_len; /* word4 iocb=did wge=rsvd. */ - wqe->words[4] = 0; + wqe->xmit_els_rsp.rsvd4 = 0; /* word5 iocb=rsvd wge=did */ bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, iocbq->iocb.un.elsreq64.remoteID); - - bf_set(lpfc_wqe_gen_ct, &wqe->generic, - ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); - - bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU); - bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext); + bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, + ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); + bf_set(wqe_pu, &wqe->xmit_els_rsp.wqe_com, iocbq->iocb.ulpPU); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + iocbq->iocb.ulpContext); if (!iocbq->iocb.ulpCt_h && iocbq->iocb.ulpCt_l) - bf_set(lpfc_wqe_gen_context, &wqe->generic, + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, iocbq->vport->vpi + phba->vpi_base); + bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1); + bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, + LPFC_WQE_LENLOC_WORD3); + bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); command_type = OTHER_COMMAND; break; case CMD_CLOSE_XRI_CN: @@ -6193,15 +6209,19 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, else bf_set(abort_cmd_ia, &wqe->abort_cmd, 0); bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); - wqe->words[5] = 0; - bf_set(lpfc_wqe_gen_ct, &wqe->generic, + /* word5 iocb=CONTEXT_TAG|IO_TAG wqe=reserved */ + wqe->abort_cmd.rsrvd5 = 0; + bf_set(wqe_ct, &wqe->abort_cmd.wqe_com, ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); abort_tag = iocbq->iocb.un.acxri.abortIoTag; /* * The abort handler will send us CMD_ABORT_XRI_CN or * CMD_CLOSE_XRI_CN and the fw only accepts CMD_ABORT_XRI_CX */ - bf_set(lpfc_wqe_gen_command, &wqe->generic, CMD_ABORT_XRI_CX); + bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX); + bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->abort_cmd.wqe_com, + LPFC_WQE_LENLOC_NONE); cmnd = CMD_ABORT_XRI_CX; command_type = OTHER_COMMAND; xritag = 0; @@ -6235,18 +6255,14 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1); bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com, iocbq->iocb.ulpContext); + bf_set(wqe_qosd, &wqe->xmit_bls_rsp.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->xmit_bls_rsp.wqe_com, + LPFC_WQE_LENLOC_NONE); /* Overwrite the pre-set comnd type with OTHER_COMMAND */ command_type = OTHER_COMMAND; break; case CMD_XRI_ABORTED_CX: case CMD_CREATE_XRI_CR: /* Do we expect to use this? */ - /* words0-2 are all 0's no bde */ - /* word3 and word4 are rsvrd */ - wqe->words[3] = 0; - wqe->words[4] = 0; - /* word5 iocb=rsvd wge=did */ - /* There is no remote port id in the IOCB? */ - /* Let this fall through and fail */ case CMD_IOCB_FCP_IBIDIR64_CR: /* bidirectional xfer */ case CMD_FCP_TSEND64_CX: /* Target mode send xfer-ready */ case CMD_FCP_TRSP64_CX: /* Target mode rcv */ @@ -6257,16 +6273,14 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->iocb.ulpCommand); return IOCB_ERROR; break; - } - bf_set(lpfc_wqe_gen_xri, &wqe->generic, xritag); - bf_set(lpfc_wqe_gen_request_tag, &wqe->generic, iocbq->iotag); - wqe->generic.abort_tag = abort_tag; - bf_set(lpfc_wqe_gen_cmd_type, &wqe->generic, command_type); - bf_set(lpfc_wqe_gen_command, &wqe->generic, cmnd); - bf_set(lpfc_wqe_gen_class, &wqe->generic, iocbq->iocb.ulpClass); - bf_set(lpfc_wqe_gen_cq_id, &wqe->generic, LPFC_WQE_CQ_ID_DEFAULT); - + bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); + bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); + wqe->generic.wqe_com.abort_tag = abort_tag; + bf_set(wqe_cmd_type, &wqe->generic.wqe_com, command_type); + bf_set(wqe_cmnd, &wqe->generic.wqe_com, cmnd); + bf_set(wqe_class, &wqe->generic.wqe_com, iocbq->iocb.ulpClass); + bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); return 0; } -- cgit v1.2.3-70-g09d2