mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 01:04:19 +08:00
[SCSI] lpfc 8.3.21: RRQ Implementation fixes
RRQ Implementation fixes - Added checks to prevent a call to findnode_did in clr_active_rrq - Added the del_sync_timer call for the rrq_tmr to the stop_hba_timers routine. - Added a check in __lpfc_set_active_rrq for the driver unloading to prevent adding an rrq when the driver is being removed. - Add code to scsi_iocb_cmpl to check for the remote stop and add the rrq. - Added the same check to els retry. - Added code to compare the source did in the els rrq to the vports did and chose the right exchange ID. - Initialize the start_cmd pointer to indicate when we have looped through all of the scsi buffers. - Remove the need for the lock around the clearing of the active bit in the rrq. - Added code to clean the els and fcp xri aborted list and remove the all of the RRQs for a deleted vport. Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
fedd3b7b93
commit
1151e3ec15
@ -423,6 +423,6 @@ int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *);
|
||||
int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *,
|
||||
uint16_t, uint16_t, uint16_t);
|
||||
void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
|
||||
void lpfc_cleanup_vports_rrqs(struct lpfc_vport *);
|
||||
void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
|
||||
struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
|
||||
uint32_t);
|
||||
|
@ -2816,9 +2816,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
|
||||
switch (irsp->ulpStatus) {
|
||||
case IOSTAT_FCP_RSP_ERROR:
|
||||
case IOSTAT_REMOTE_STOP:
|
||||
break;
|
||||
|
||||
case IOSTAT_REMOTE_STOP:
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
/* This IO was aborted by the target, we don't
|
||||
* know the rxid and because we did not send the
|
||||
* ABTS we cannot generate and RRQ.
|
||||
*/
|
||||
lpfc_set_rrq_active(phba, ndlp,
|
||||
cmdiocb->sli4_xritag, 0, 0);
|
||||
}
|
||||
break;
|
||||
case IOSTAT_LOCAL_REJECT:
|
||||
switch ((irsp->un.ulpWord[4] & 0xff)) {
|
||||
case IOERR_LOOP_OPEN_FAILURE:
|
||||
@ -4014,28 +4022,34 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport,
|
||||
uint8_t *pcmd;
|
||||
struct RRQ *rrq;
|
||||
uint16_t rxid;
|
||||
uint16_t xri;
|
||||
struct lpfc_node_rrq *prrq;
|
||||
|
||||
|
||||
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt);
|
||||
pcmd += sizeof(uint32_t);
|
||||
rrq = (struct RRQ *)pcmd;
|
||||
rxid = bf_get(rrq_oxid, rrq);
|
||||
rrq->rrq_exchg = be32_to_cpu(rrq->rrq_exchg);
|
||||
rxid = be16_to_cpu(bf_get(rrq_rxid, rrq));
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x"
|
||||
" x%x x%x\n",
|
||||
bf_get(rrq_did, rrq),
|
||||
bf_get(rrq_oxid, rrq),
|
||||
be32_to_cpu(bf_get(rrq_did, rrq)),
|
||||
be16_to_cpu(bf_get(rrq_oxid, rrq)),
|
||||
rxid,
|
||||
iocb->iotag, iocb->iocb.ulpContext);
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||
"Clear RRQ: did:x%x flg:x%x exchg:x%.08x",
|
||||
ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg);
|
||||
prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID);
|
||||
if (vport->fc_myDID == be32_to_cpu(bf_get(rrq_did, rrq)))
|
||||
xri = be16_to_cpu(bf_get(rrq_oxid, rrq));
|
||||
else
|
||||
xri = rxid;
|
||||
prrq = lpfc_get_active_rrq(vport, xri, ndlp->nlp_DID);
|
||||
if (prrq)
|
||||
lpfc_clr_rrq_active(phba, rxid, prrq);
|
||||
lpfc_clr_rrq_active(phba, xri, prrq);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7582,6 +7596,32 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
|
||||
IOERR_SLI_ABORTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_vport_delete_els_xri_aborted -Remove all ndlp references for vport
|
||||
* @vport: pointer to lpfc vport data structure.
|
||||
*
|
||||
* This routine is invoked by the vport cleanup for deletions and the cleanup
|
||||
* for an ndlp on removal.
|
||||
**/
|
||||
void
|
||||
lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
|
||||
unsigned long iflag = 0;
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||
spin_lock(&phba->sli4_hba.abts_sgl_list_lock);
|
||||
list_for_each_entry_safe(sglq_entry, sglq_next,
|
||||
&phba->sli4_hba.lpfc_abts_els_sgl_list, list) {
|
||||
if (sglq_entry->ndlp && sglq_entry->ndlp->vport == vport)
|
||||
sglq_entry->ndlp = NULL;
|
||||
}
|
||||
spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_els_xri_aborted - Slow-path process of els xri abort
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
|
@ -3160,7 +3160,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
vport->unreg_vpi_cmpl = VPORT_OK;
|
||||
mempool_free(pmb, phba->mbox_mem_pool);
|
||||
lpfc_cleanup_vports_rrqs(vport);
|
||||
lpfc_cleanup_vports_rrqs(vport, NULL);
|
||||
/*
|
||||
* This shost reference might have been taken at the beginning of
|
||||
* lpfc_vport_delete()
|
||||
@ -3900,6 +3900,8 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
|
||||
return;
|
||||
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
|
||||
if (vport->phba->sli_rev == LPFC_SLI_REV4)
|
||||
lpfc_cleanup_vports_rrqs(vport, ndlp);
|
||||
lpfc_nlp_put(ndlp);
|
||||
return;
|
||||
}
|
||||
@ -4289,7 +4291,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||
|
||||
list_del_init(&ndlp->els_retry_evt.evt_listp);
|
||||
list_del_init(&ndlp->dev_loss_evt.evt_listp);
|
||||
|
||||
lpfc_cleanup_vports_rrqs(vport, ndlp);
|
||||
lpfc_unreg_rpi(vport, ndlp);
|
||||
|
||||
return 0;
|
||||
|
@ -945,16 +945,12 @@ static void
|
||||
lpfc_rrq_timeout(unsigned long ptr)
|
||||
{
|
||||
struct lpfc_hba *phba;
|
||||
uint32_t tmo_posted;
|
||||
unsigned long iflag;
|
||||
|
||||
phba = (struct lpfc_hba *)ptr;
|
||||
spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
|
||||
tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE;
|
||||
if (!tmo_posted)
|
||||
phba->hba_flag |= HBA_RRQ_ACTIVE;
|
||||
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
|
||||
if (!tmo_posted)
|
||||
lpfc_worker_wake_up(phba);
|
||||
}
|
||||
|
||||
@ -2280,6 +2276,7 @@ lpfc_cleanup(struct lpfc_vport *vport)
|
||||
/* Wait for any activity on ndlps to settle */
|
||||
msleep(10);
|
||||
}
|
||||
lpfc_cleanup_vports_rrqs(vport, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2355,6 +2352,10 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba)
|
||||
del_timer_sync(&phba->fabric_block_timer);
|
||||
del_timer_sync(&phba->eratt_poll);
|
||||
del_timer_sync(&phba->hb_tmofunc);
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
del_timer_sync(&phba->rrq_tmr);
|
||||
phba->hba_flag &= ~HBA_RRQ_ACTIVE;
|
||||
}
|
||||
phba->hb_outstanding = 0;
|
||||
|
||||
switch (phba->pci_dev_grp) {
|
||||
|
@ -608,6 +608,32 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
|
||||
return bcnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_vport_delete_fcp_xri_aborted -Remove all ndlp references for vport
|
||||
* @vport: pointer to lpfc vport data structure.
|
||||
*
|
||||
* This routine is invoked by the vport cleanup for deletions and the cleanup
|
||||
* for an ndlp on removal.
|
||||
**/
|
||||
void
|
||||
lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_scsi_buf *psb, *next_psb;
|
||||
unsigned long iflag = 0;
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||
spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock);
|
||||
list_for_each_entry_safe(psb, next_psb,
|
||||
&phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {
|
||||
if (psb->rdata && psb->rdata->pnode
|
||||
&& psb->rdata->pnode->vport == vport)
|
||||
psb->rdata = NULL;
|
||||
}
|
||||
spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock);
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
@ -640,7 +666,11 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
spin_unlock(
|
||||
&phba->sli4_hba.abts_scsi_buf_list_lock);
|
||||
if (psb->rdata && psb->rdata->pnode)
|
||||
ndlp = psb->rdata->pnode;
|
||||
else
|
||||
ndlp = NULL;
|
||||
|
||||
rrq_empty = list_empty(&phba->active_rrq_list);
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
||||
if (ndlp)
|
||||
@ -964,35 +994,28 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
|
||||
static struct lpfc_scsi_buf*
|
||||
lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
struct lpfc_scsi_buf *lpfc_cmd = NULL;
|
||||
struct lpfc_scsi_buf *start_lpfc_cmd = NULL;
|
||||
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
|
||||
struct lpfc_scsi_buf *lpfc_cmd ;
|
||||
unsigned long iflag = 0;
|
||||
int found = 0;
|
||||
|
||||
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
|
||||
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
|
||||
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
|
||||
while (!found && lpfc_cmd) {
|
||||
list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list,
|
||||
list) {
|
||||
if (lpfc_test_rrq_active(phba, ndlp,
|
||||
lpfc_cmd->cur_iocbq.sli4_xritag)) {
|
||||
lpfc_release_scsi_buf_s4(phba, lpfc_cmd);
|
||||
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
|
||||
list_remove_head(scsi_buf_list, lpfc_cmd,
|
||||
struct lpfc_scsi_buf, list);
|
||||
spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
|
||||
iflag);
|
||||
if (lpfc_cmd == start_lpfc_cmd) {
|
||||
lpfc_cmd = NULL;
|
||||
break;
|
||||
} else
|
||||
lpfc_cmd->cur_iocbq.sli4_xritag))
|
||||
continue;
|
||||
}
|
||||
list_del(&lpfc_cmd->list);
|
||||
found = 1;
|
||||
lpfc_cmd->seg_cnt = 0;
|
||||
lpfc_cmd->nonsg_phys = 0;
|
||||
lpfc_cmd->prot_seg_cnt = 0;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
|
||||
iflag);
|
||||
if (!found)
|
||||
return NULL;
|
||||
else
|
||||
return lpfc_cmd;
|
||||
}
|
||||
/**
|
||||
@ -2484,6 +2507,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
||||
lpfc_worker_wake_up(phba);
|
||||
break;
|
||||
case IOSTAT_LOCAL_REJECT:
|
||||
case IOSTAT_REMOTE_STOP:
|
||||
if (lpfc_cmd->result == IOERR_INVALID_RPI ||
|
||||
lpfc_cmd->result == IOERR_NO_RESOURCES ||
|
||||
lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
|
||||
@ -2510,6 +2534,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
||||
"on unprotected cmd\n");
|
||||
}
|
||||
}
|
||||
if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP)
|
||||
&& (phba->sli_rev == LPFC_SLI_REV4)
|
||||
&& (pnode && NLP_CHK_NODE_ACT(pnode))) {
|
||||
/* This IO was aborted by the target, we don't
|
||||
* know the rxid and because we did not send the
|
||||
* ABTS we cannot generate and RRQ.
|
||||
*/
|
||||
lpfc_set_rrq_active(phba, pnode,
|
||||
lpfc_cmd->cur_iocbq.sli4_xritag,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
/* else: fall through */
|
||||
default:
|
||||
|
@ -535,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;
|
||||
@ -554,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;
|
||||
list_add_tail(&rrq->list, &phba->active_rrq_list);
|
||||
if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) {
|
||||
phba->hba_flag |= HBA_RRQ_ACTIVE;
|
||||
@ -570,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,
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -628,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))
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -693,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;
|
||||
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) {
|
||||
list_del(&rrq->list);
|
||||
__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -733,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_del(&rrq->list);
|
||||
__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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.
|
||||
@ -759,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 +835,6 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -885,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.
|
||||
*/
|
||||
|
@ -566,6 +566,8 @@ void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *,
|
||||
struct sli4_wcqe_xri_aborted *);
|
||||
void lpfc_sli4_els_xri_aborted(struct lpfc_hba *,
|
||||
struct sli4_wcqe_xri_aborted *);
|
||||
void lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *);
|
||||
void lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *);
|
||||
int lpfc_sli4_brdreset(struct lpfc_hba *);
|
||||
int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *);
|
||||
void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *);
|
||||
|
Loading…
Reference in New Issue
Block a user