[SCSI] lpfc 8.3.3 : Fix a couple of spin_lock and memory issues and a crash
Contains the following changes: - Fixed error paths retaking a spin lock which they already hold - Added code to free memory in a couple of error paths - Added code to free RPI bit map while unloading driver - Added code to write zero to memory object allocated through dma_alloc_coherent - Fixed crash/hang with target or LUN resets Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
Родитель
0c2875893e
Коммит
d11e31ddb9
|
@ -3540,6 +3540,7 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
|
||||||
|
|
||||||
/* Free the allocated rpi headers. */
|
/* Free the allocated rpi headers. */
|
||||||
lpfc_sli4_remove_rpi_hdrs(phba);
|
lpfc_sli4_remove_rpi_hdrs(phba);
|
||||||
|
lpfc_sli4_remove_rpis(phba);
|
||||||
|
|
||||||
/* Free the ELS sgl list */
|
/* Free the ELS sgl list */
|
||||||
lpfc_free_active_sgl(phba);
|
lpfc_free_active_sgl(phba);
|
||||||
|
|
|
@ -1631,6 +1631,7 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
|
||||||
/* In case of malloc fails, proceed with whatever we have */
|
/* In case of malloc fails, proceed with whatever we have */
|
||||||
if (!viraddr)
|
if (!viraddr)
|
||||||
break;
|
break;
|
||||||
|
memset(viraddr, 0, PAGE_SIZE);
|
||||||
mbox->sge_array->addr[pagen] = viraddr;
|
mbox->sge_array->addr[pagen] = viraddr;
|
||||||
/* Keep the first page for later sub-header construction */
|
/* Keep the first page for later sub-header construction */
|
||||||
if (pagen == 0)
|
if (pagen == 0)
|
||||||
|
|
|
@ -4139,8 +4139,11 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba,
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
data_length = mqe->un.mb_words[5];
|
data_length = mqe->un.mb_words[5];
|
||||||
if (data_length > DMP_FCOEPARAM_RGN_SIZE)
|
if (data_length > DMP_FCOEPARAM_RGN_SIZE) {
|
||||||
|
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||||
|
kfree(mp);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
lpfc_parse_fcoe_conf(phba, mp->virt, data_length);
|
lpfc_parse_fcoe_conf(phba, mp->virt, data_length);
|
||||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||||
|
@ -7350,6 +7353,32 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lpfc_chk_iocb_flg - Test IOCB flag with lock held.
|
||||||
|
* @phba: Pointer to HBA context object..
|
||||||
|
* @piocbq: Pointer to command iocb.
|
||||||
|
* @flag: Flag to test.
|
||||||
|
*
|
||||||
|
* This routine grabs the hbalock and then test the iocb_flag to
|
||||||
|
* see if the passed in flag is set.
|
||||||
|
* Returns:
|
||||||
|
* 1 if flag is set.
|
||||||
|
* 0 if flag is not set.
|
||||||
|
**/
|
||||||
|
static int
|
||||||
|
lpfc_chk_iocb_flg(struct lpfc_hba *phba,
|
||||||
|
struct lpfc_iocbq *piocbq, uint32_t flag)
|
||||||
|
{
|
||||||
|
unsigned long iflags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||||
|
ret = piocbq->iocb_flag & flag;
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands
|
* lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands
|
||||||
* @phba: Pointer to HBA context object..
|
* @phba: Pointer to HBA context object..
|
||||||
|
@ -7417,7 +7446,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
|
||||||
if (retval == IOCB_SUCCESS) {
|
if (retval == IOCB_SUCCESS) {
|
||||||
timeout_req = timeout * HZ;
|
timeout_req = timeout * HZ;
|
||||||
timeleft = wait_event_timeout(done_q,
|
timeleft = wait_event_timeout(done_q,
|
||||||
piocb->iocb_flag & LPFC_IO_WAKE,
|
lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE),
|
||||||
timeout_req);
|
timeout_req);
|
||||||
|
|
||||||
if (piocb->iocb_flag & LPFC_IO_WAKE) {
|
if (piocb->iocb_flag & LPFC_IO_WAKE) {
|
||||||
|
@ -7602,20 +7631,16 @@ lpfc_sli_eratt_read(struct lpfc_hba *phba)
|
||||||
if ((HS_FFER1 & phba->work_hs) &&
|
if ((HS_FFER1 & phba->work_hs) &&
|
||||||
((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
|
((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
|
||||||
HS_FFER6 | HS_FFER7) & phba->work_hs)) {
|
HS_FFER6 | HS_FFER7) & phba->work_hs)) {
|
||||||
spin_lock_irq(&phba->hbalock);
|
|
||||||
phba->hba_flag |= DEFER_ERATT;
|
phba->hba_flag |= DEFER_ERATT;
|
||||||
spin_unlock_irq(&phba->hbalock);
|
|
||||||
/* Clear all interrupt enable conditions */
|
/* Clear all interrupt enable conditions */
|
||||||
writel(0, phba->HCregaddr);
|
writel(0, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr);
|
readl(phba->HCregaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the driver HA work bitmap */
|
/* Set the driver HA work bitmap */
|
||||||
spin_lock_irq(&phba->hbalock);
|
|
||||||
phba->work_ha |= HA_ERATT;
|
phba->work_ha |= HA_ERATT;
|
||||||
/* Indicate polling handles this ERATT */
|
/* Indicate polling handles this ERATT */
|
||||||
phba->hba_flag |= HBA_ERATT_HANDLED;
|
phba->hba_flag |= HBA_ERATT_HANDLED;
|
||||||
spin_unlock_irq(&phba->hbalock);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -7661,12 +7686,10 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba)
|
||||||
return 0;
|
return 0;
|
||||||
phba->work_status[0] = uerr_sta_lo;
|
phba->work_status[0] = uerr_sta_lo;
|
||||||
phba->work_status[1] = uerr_sta_hi;
|
phba->work_status[1] = uerr_sta_hi;
|
||||||
spin_lock_irq(&phba->hbalock);
|
|
||||||
/* Set the driver HA work bitmap */
|
/* Set the driver HA work bitmap */
|
||||||
phba->work_ha |= HA_ERATT;
|
phba->work_ha |= HA_ERATT;
|
||||||
/* Indicate polling handles this ERATT */
|
/* Indicate polling handles this ERATT */
|
||||||
phba->hba_flag |= HBA_ERATT_HANDLED;
|
phba->hba_flag |= HBA_ERATT_HANDLED;
|
||||||
spin_unlock_irq(&phba->hbalock);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9349,6 +9372,7 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
|
||||||
kfree(dmabuf);
|
kfree(dmabuf);
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
memset(dmabuf->virt, 0, PAGE_SIZE);
|
||||||
dmabuf->buffer_tag = x;
|
dmabuf->buffer_tag = x;
|
||||||
list_add_tail(&dmabuf->list, &queue->page_list);
|
list_add_tail(&dmabuf->list, &queue->page_list);
|
||||||
/* initialize queue's entry array */
|
/* initialize queue's entry array */
|
||||||
|
@ -9771,7 +9795,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
|
||||||
/* link the wq onto the parent cq child list */
|
/* link the wq onto the parent cq child list */
|
||||||
list_add_tail(&wq->list, &cq->child_list);
|
list_add_tail(&wq->list, &cq->child_list);
|
||||||
out:
|
out:
|
||||||
if (rc == MBX_TIMEOUT)
|
if (rc != MBX_TIMEOUT)
|
||||||
mempool_free(mbox, phba->mbox_mem_pool);
|
mempool_free(mbox, phba->mbox_mem_pool);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче