be2iscsi: Fix WRB leak in login/logout path
Login/Logout loop was hanging after few hours. /var/log/message showed that alloc_wrb_handle() function was not able to allocate any new WRB. Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not send nopout Sep 11 11:25:22 Jhelum10 kernel: scsi host10: BM_4989 : Alloc of WRB_HANDLE Failed for the CID : 384 Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not allocate pdu for mgmt task. Driver allocates WRB to pass login negotiated parameters information to FW in beiscsi_offload_connection(). This allocated WRB was not freed so there was WRB_Leak happening. Put WRB used for posting the login-negotiated parameters back in pool. Signed-off-by: Jitendra Bhivare <jitendra.bhivare@avagotech.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
9c4f8b0173
commit
cb564c6b44
@ -1180,6 +1180,22 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
|
|||||||
phba->io_sgl_free_index++;
|
phba->io_sgl_free_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct wrb_handle *
|
||||||
|
beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context,
|
||||||
|
unsigned int wrbs_per_cxn)
|
||||||
|
{
|
||||||
|
struct wrb_handle *pwrb_handle;
|
||||||
|
|
||||||
|
pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index];
|
||||||
|
pwrb_context->wrb_handles_available--;
|
||||||
|
if (pwrb_context->alloc_index == (wrbs_per_cxn - 1))
|
||||||
|
pwrb_context->alloc_index = 0;
|
||||||
|
else
|
||||||
|
pwrb_context->alloc_index++;
|
||||||
|
|
||||||
|
return pwrb_handle;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* alloc_wrb_handle - To allocate a wrb handle
|
* alloc_wrb_handle - To allocate a wrb handle
|
||||||
* @phba: The hba pointer
|
* @phba: The hba pointer
|
||||||
@ -1189,30 +1205,30 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
|
|||||||
* This happens under session_lock until submission to chip
|
* This happens under session_lock until submission to chip
|
||||||
*/
|
*/
|
||||||
struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
|
struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
|
||||||
struct hwi_wrb_context **pcontext)
|
struct hwi_wrb_context **pcontext)
|
||||||
{
|
{
|
||||||
struct hwi_wrb_context *pwrb_context;
|
struct hwi_wrb_context *pwrb_context;
|
||||||
struct hwi_controller *phwi_ctrlr;
|
struct hwi_controller *phwi_ctrlr;
|
||||||
struct wrb_handle *pwrb_handle;
|
|
||||||
uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
|
uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
|
||||||
|
|
||||||
phwi_ctrlr = phba->phwi_ctrlr;
|
phwi_ctrlr = phba->phwi_ctrlr;
|
||||||
pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
|
pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
|
||||||
if (pwrb_context->wrb_handles_available >= 2) {
|
/* return the context address */
|
||||||
pwrb_handle = pwrb_context->pwrb_handle_base[
|
*pcontext = pwrb_context;
|
||||||
pwrb_context->alloc_index];
|
return beiscsi_get_wrb_handle(pwrb_context, phba->params.wrbs_per_cxn);
|
||||||
pwrb_context->wrb_handles_available--;
|
}
|
||||||
if (pwrb_context->alloc_index ==
|
|
||||||
(phba->params.wrbs_per_cxn - 1))
|
|
||||||
pwrb_context->alloc_index = 0;
|
|
||||||
else
|
|
||||||
pwrb_context->alloc_index++;
|
|
||||||
|
|
||||||
/* Return the context address */
|
static inline void
|
||||||
*pcontext = pwrb_context;
|
beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context,
|
||||||
} else
|
struct wrb_handle *pwrb_handle,
|
||||||
pwrb_handle = NULL;
|
unsigned int wrbs_per_cxn)
|
||||||
return pwrb_handle;
|
{
|
||||||
|
pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle;
|
||||||
|
pwrb_context->wrb_handles_available++;
|
||||||
|
if (pwrb_context->free_index == (wrbs_per_cxn - 1))
|
||||||
|
pwrb_context->free_index = 0;
|
||||||
|
else
|
||||||
|
pwrb_context->free_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1227,13 +1243,9 @@ static void
|
|||||||
free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,
|
free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,
|
||||||
struct wrb_handle *pwrb_handle)
|
struct wrb_handle *pwrb_handle)
|
||||||
{
|
{
|
||||||
pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle;
|
beiscsi_put_wrb_handle(pwrb_context,
|
||||||
pwrb_context->wrb_handles_available++;
|
pwrb_handle,
|
||||||
if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1))
|
phba->params.wrbs_per_cxn);
|
||||||
pwrb_context->free_index = 0;
|
|
||||||
else
|
|
||||||
pwrb_context->free_index++;
|
|
||||||
|
|
||||||
beiscsi_log(phba, KERN_INFO,
|
beiscsi_log(phba, KERN_INFO,
|
||||||
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
|
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
|
||||||
"BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x"
|
"BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x"
|
||||||
@ -4711,6 +4723,20 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
|
|||||||
doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
|
doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
|
||||||
iowrite32(doorbell, phba->db_va +
|
iowrite32(doorbell, phba->db_va +
|
||||||
beiscsi_conn->doorbell_offset);
|
beiscsi_conn->doorbell_offset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is no completion for CONTEXT_UPDATE. The completion of next
|
||||||
|
* WRB posted guarantees FW's processing and DMA'ing of it.
|
||||||
|
* Use beiscsi_put_wrb_handle to put it back in the pool which makes
|
||||||
|
* sure zero'ing or reuse of the WRB only after wrbs_per_cxn.
|
||||||
|
*/
|
||||||
|
beiscsi_put_wrb_handle(pwrb_context, pwrb_handle,
|
||||||
|
phba->params.wrbs_per_cxn);
|
||||||
|
beiscsi_log(phba, KERN_INFO,
|
||||||
|
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
|
||||||
|
"BM_%d : put CONTEXT_UPDATE pwrb_handle=%p free_index=0x%x wrb_handles_available=%d\n",
|
||||||
|
pwrb_handle, pwrb_context->free_index,
|
||||||
|
pwrb_context->wrb_handles_available);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt,
|
static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt,
|
||||||
|
Loading…
Reference in New Issue
Block a user