Skip to content

Commit

Permalink
[SCSI] lpfc 8.1.12 : Modify ELS abort handling to prevent double comp…
Browse files Browse the repository at this point in the history
…letion

Modify ELS abort handling to prevent double completion

Rework portions of ELS abort handling to prevent double completion
 - Rework ELS iotags and correct abort routine
 - Move the (badly wrong) ELS completion logic from the initial ELS
   abort request function to the ELS completion function.
 - Fixup the iocb completion handling to account for the ELS abort
   completions.

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
James Smart authored and James Bottomley committed May 6, 2007
1 parent 1dcb58e commit 0795107
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 181 deletions.
7 changes: 3 additions & 4 deletions drivers/scsi/lpfc/lpfc_crtn.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,

int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
struct serv_parm *, uint32_t);
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp,
int);
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
int lpfc_els_abort_flogi(struct lpfc_hba *);
int lpfc_initial_flogi(struct lpfc_hba *);
int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
Expand Down Expand Up @@ -162,8 +161,8 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
struct lpfc_sli_ring *,
dma_addr_t);
int lpfc_sli_issue_abort_iotag32(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
uint64_t, lpfc_ctx_cmd);
int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
Expand Down
64 changes: 4 additions & 60 deletions drivers/scsi/lpfc/lpfc_els.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,24 +582,8 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba)
icmd = &iocb->iocb;
if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
ndlp = (struct lpfc_nodelist *)(iocb->context1);
if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
list_del(&iocb->list);
pring->txcmplq_cnt--;

if ((icmd->un.elsreq64.bdl.ulpIoTag32)) {
lpfc_sli_issue_abort_iotag32
(phba, pring, iocb);
}
if (iocb->iocb_cmpl) {
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
icmd->un.ulpWord[4] =
IOERR_SLI_ABORTED;
spin_unlock_irq(phba->host->host_lock);
(iocb->iocb_cmpl) (phba, iocb, iocb);
spin_lock_irq(phba->host->host_lock);
} else
lpfc_sli_release_iocbq(phba, iocb);
}
if (ndlp && (ndlp->nlp_DID == Fabric_DID))
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
}
}
spin_unlock_irq(phba->host->host_lock);
Expand Down Expand Up @@ -3245,7 +3229,6 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
struct lpfc_iocbq *tmp_iocb, *piocb;
IOCB_t *cmd = NULL;
struct lpfc_dmabuf *pcmd;
struct list_head *dlp;
uint32_t *elscmd;
uint32_t els_command;
uint32_t timeout;
Expand All @@ -3262,7 +3245,6 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
timeout = (uint32_t)(phba->fc_ratov << 1);

pring = &phba->sli.ring[LPFC_ELS_RING];
dlp = &pring->txcmplq;

list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
cmd = &piocb->iocb;
Expand All @@ -3288,19 +3270,12 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
continue;
}

list_del(&piocb->list);
pring->txcmplq_cnt--;

if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
struct lpfc_nodelist *ndlp;
spin_unlock_irq(phba->host->host_lock);
ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext);
spin_lock_irq(phba->host->host_lock);
remote_ID = ndlp->nlp_DID;
if (cmd->un.elsreq64.bdl.ulpIoTag32) {
lpfc_sli_issue_abort_iotag32(phba,
pring, piocb);
}
} else {
remote_ID = cmd->un.elsreq64.remoteID;
}
Expand All @@ -3312,17 +3287,7 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
phba->brd_no, els_command,
remote_ID, cmd->ulpCommand, cmd->ulpIoTag);

/*
* The iocb has timed out; abort it.
*/
if (piocb->iocb_cmpl) {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
spin_unlock_irq(phba->host->host_lock);
(piocb->iocb_cmpl) (phba, piocb, piocb);
spin_lock_irq(phba->host->host_lock);
} else
lpfc_sli_release_iocbq(phba, piocb);
lpfc_sli_issue_abort_iotag(phba, pring, piocb);
}
if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
Expand All @@ -3336,9 +3301,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *tmp_iocb, *piocb;
IOCB_t *cmd = NULL;
struct lpfc_dmabuf *pcmd;
uint32_t *elscmd;
uint32_t els_command;

pring = &phba->sli.ring[LPFC_ELS_RING];
spin_lock_irq(phba->host->host_lock);
Expand All @@ -3357,10 +3319,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
continue;
}

pcmd = (struct lpfc_dmabuf *) piocb->context2;
elscmd = (uint32_t *) (pcmd->virt);
els_command = *elscmd;

list_del(&piocb->list);
pring->txq_cnt--;

Expand All @@ -3381,22 +3339,8 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
continue;
}
pcmd = (struct lpfc_dmabuf *) piocb->context2;
elscmd = (uint32_t *) (pcmd->virt);
els_command = *elscmd;

list_del(&piocb->list);
pring->txcmplq_cnt--;

cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;

if (piocb->iocb_cmpl) {
spin_unlock_irq(phba->host->host_lock);
(piocb->iocb_cmpl) (phba, piocb, piocb);
spin_lock_irq(phba->host->host_lock);
} else
lpfc_sli_release_iocbq(phba, piocb);
lpfc_sli_issue_abort_iotag(phba, pring, piocb);
}
spin_unlock_irq(phba->host->host_lock);
return;
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/lpfc/lpfc_hbadisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1596,7 +1596,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
}
spin_unlock_irq(phba->host->host_lock);

lpfc_els_abort(phba,ndlp,0);
lpfc_els_abort(phba,ndlp);
spin_lock_irq(phba->host->host_lock);
ndlp->nlp_flag &= ~NLP_DELAY_TMO;
spin_unlock_irq(phba->host->host_lock);
Expand Down
76 changes: 22 additions & 54 deletions drivers/scsi/lpfc/lpfc_nportdisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba,
* routine effectively results in a "software abort".
*/
int
lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
int send_abts)
lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
{
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
Expand Down Expand Up @@ -215,48 +214,17 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
spin_unlock_irq(phba->host->host_lock);
} while (found);

/* Everything on txcmplq will be returned by firmware
* with a no rpi / linkdown / abort error. For ring 0,
* ELS discovery, we want to get rid of it right here.
*/
/* Next check the txcmplq */
do {
found = 0;
spin_lock_irq(phba->host->host_lock);
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq,
list) {
/* Check to see if iocb matches the nport we are looking
for */
if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) {
found = 1;
/* It matches, so deque and call compl with an
error */
list_del(&iocb->list);
pring->txcmplq_cnt--;

icmd = &iocb->iocb;
/* If the driver is completing an ELS
* command early, flush it out of the firmware.
*/
if (send_abts &&
(icmd->ulpCommand == CMD_ELS_REQUEST64_CR) &&
(icmd->un.elsreq64.bdl.ulpIoTag32)) {
lpfc_sli_issue_abort_iotag32(phba,
pring, iocb);
}
if (iocb->iocb_cmpl) {
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
spin_unlock_irq(phba->host->host_lock);
(iocb->iocb_cmpl) (phba, iocb, iocb);
spin_lock_irq(phba->host->host_lock);
} else
lpfc_sli_release_iocbq(phba, iocb);
break;
}
spin_lock_irq(phba->host->host_lock);
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
/* Check to see if iocb matches the nport we are looking
for */
if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) {
icmd = &iocb->iocb;
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
}
spin_unlock_irq(phba->host->host_lock);
} while(found);
}
spin_unlock_irq(phba->host->host_lock);

/* If we are delaying issuing an ELS command, cancel it */
if (ndlp->nlp_flag & NLP_DELAY_TMO)
Expand Down Expand Up @@ -404,7 +372,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
*/
if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);
}

lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
Expand Down Expand Up @@ -697,7 +665,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;

/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
Expand All @@ -712,7 +680,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;

/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

if (evt == NLP_EVT_RCV_LOGO) {
lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
Expand Down Expand Up @@ -855,7 +823,7 @@ lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
}
else {
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
return NLP_STE_FREED_NODE;
Expand All @@ -868,7 +836,7 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
uint32_t evt)
{
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
ndlp->nlp_state = NLP_STE_NPR_NODE;
Expand All @@ -888,7 +856,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
struct lpfc_iocbq *cmdiocb;

/* software abort outstanding ADISC */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

cmdiocb = (struct lpfc_iocbq *) arg;

Expand Down Expand Up @@ -926,7 +894,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;

/* software abort outstanding ADISC */
lpfc_els_abort(phba, ndlp, 0);
lpfc_els_abort(phba, ndlp);

lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
Expand Down Expand Up @@ -1016,7 +984,7 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
}
else {
/* software abort outstanding ADISC */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
return NLP_STE_FREED_NODE;
Expand All @@ -1029,7 +997,7 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
uint32_t evt)
{
/* software abort outstanding ADISC */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
ndlp->nlp_state = NLP_STE_NPR_NODE;
Expand Down Expand Up @@ -1230,7 +1198,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;

/* Software abort outstanding PRLI before sending acc */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
Expand Down Expand Up @@ -1330,7 +1298,7 @@ lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
}
else {
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
return NLP_STE_FREED_NODE;
Expand Down Expand Up @@ -1359,7 +1327,7 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
{
/* software abort outstanding PRLI */
lpfc_els_abort(phba, ndlp, 1);
lpfc_els_abort(phba, ndlp);

ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
ndlp->nlp_state = NLP_STE_NPR_NODE;
Expand Down
Loading

0 comments on commit 0795107

Please sign in to comment.