[SCSI] lpfc 8.3.29: Remove GFP_KERNEL allocation while lock is held

Note: this is a replacement patch for the issue pointed out in
http://www.gossamer-threads.com/lists/linux/kernel/1477270

Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
James Smart 2012-01-18 16:25:55 -05:00 committed by James Bottomley
parent 728599090a
commit b42c07c8ad
1 changed files with 57 additions and 79 deletions

View File

@ -557,81 +557,6 @@ __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag)
return sglq; return sglq;
} }
/**
* __lpfc_set_rrq_active - set RRQ active bit in the ndlp's xri_bitmap.
* @phba: Pointer to HBA context object.
* @ndlp: nodelist pointer for this target.
* @xritag: xri used in this exchange.
* @rxid: Remote Exchange ID.
* @send_rrq: Flag used to determine if we should send rrq els cmd.
*
* This function is called with hbalock held.
* The active bit is set in the ndlp's active rrq xri_bitmap. Allocates an
* rrq struct and adds it to the active_rrq_list.
*
* returns 0 for rrq slot for this xri
* < 0 Were not able to get rrq mem or invalid parameter.
**/
static int
__lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
{
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.
*/
if (NLP_CHK_FREE_REQ(ndlp))
goto out;
if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING))
goto out;
if (test_and_set_bit(xritag, ndlp->active_rrqs.xri_bitmap))
goto out;
rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
if (rrq) {
rrq->send_rrq = send_rrq;
rrq->xritag = xritag;
rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
rrq->ndlp = ndlp;
rrq->nlp_DID = ndlp->nlp_DID;
rrq->vport = ndlp->vport;
rrq->rxid = rxid;
empty = list_empty(&phba->active_rrq_list);
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;
if (empty)
lpfc_worker_wake_up(phba);
}
return 0;
}
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. * @phba: Pointer to HBA context object.
@ -860,15 +785,68 @@ lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
**/ **/
int int
lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
uint16_t xritag, uint16_t rxid, uint16_t send_rrq) uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
{ {
int ret;
unsigned long iflags; unsigned long iflags;
struct lpfc_node_rrq *rrq;
int empty;
if (!ndlp)
return -EINVAL;
if (!phba->cfg_enable_rrq)
return -EINVAL;
spin_lock_irqsave(&phba->hbalock, iflags); spin_lock_irqsave(&phba->hbalock, iflags);
ret = __lpfc_set_rrq_active(phba, ndlp, xritag, rxid, send_rrq); if (phba->pport->load_flag & FC_UNLOADING) {
phba->hba_flag &= ~HBA_RRQ_ACTIVE;
goto out;
}
/*
* set the active bit even if there is no mem available.
*/
if (NLP_CHK_FREE_REQ(ndlp))
goto out;
if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING))
goto out;
if (test_and_set_bit(xritag, ndlp->active_rrqs.xri_bitmap))
goto out;
spin_unlock_irqrestore(&phba->hbalock, iflags); spin_unlock_irqrestore(&phba->hbalock, iflags);
return ret; rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
if (!rrq) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"3155 Unable to allocate RRQ xri:0x%x rxid:0x%x"
" DID:0x%x Send:%d\n",
xritag, rxid, ndlp->nlp_DID, send_rrq);
return -EINVAL;
}
rrq->send_rrq = send_rrq;
rrq->xritag = xritag;
rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
rrq->ndlp = ndlp;
rrq->nlp_DID = ndlp->nlp_DID;
rrq->vport = ndlp->vport;
rrq->rxid = rxid;
rrq->send_rrq = send_rrq;
spin_lock_irqsave(&phba->hbalock, iflags);
empty = list_empty(&phba->active_rrq_list);
list_add_tail(&rrq->list, &phba->active_rrq_list);
phba->hba_flag |= HBA_RRQ_ACTIVE;
if (empty)
lpfc_worker_wake_up(phba);
spin_unlock_irqrestore(&phba->hbalock, iflags);
return 0;
out:
spin_unlock_irqrestore(&phba->hbalock, iflags);
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, ndlp->nlp_DID, send_rrq);
return -EINVAL;
} }
/** /**