diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-06-10 17:23:06 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-15 11:09:33 -0400 |
commit | d11e31ddb9718755dc96e1c018843ae6f5bb085e (patch) | |
tree | c6314c3e2b528077c8ff7c4ade53aa4ab74407ba /drivers/scsi/lpfc | |
parent | 0c2875893ef27b93d5d3221f8f98ae944d6be5fa (diff) |
[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>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 42 |
3 files changed, 35 insertions, 9 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4363331aba77..fc67cc65c63b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -3540,6 +3540,7 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) | |||
3540 | 3540 | ||
3541 | /* Free the allocated rpi headers. */ | 3541 | /* Free the allocated rpi headers. */ |
3542 | lpfc_sli4_remove_rpi_hdrs(phba); | 3542 | lpfc_sli4_remove_rpi_hdrs(phba); |
3543 | lpfc_sli4_remove_rpis(phba); | ||
3543 | 3544 | ||
3544 | /* Free the ELS sgl list */ | 3545 | /* Free the ELS sgl list */ |
3545 | lpfc_free_active_sgl(phba); | 3546 | lpfc_free_active_sgl(phba); |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index bb3dc1dcffe0..3423571dd1b3 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -1631,6 +1631,7 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | |||
1631 | /* In case of malloc fails, proceed with whatever we have */ | 1631 | /* In case of malloc fails, proceed with whatever we have */ |
1632 | if (!viraddr) | 1632 | if (!viraddr) |
1633 | break; | 1633 | break; |
1634 | memset(viraddr, 0, PAGE_SIZE); | ||
1634 | mbox->sge_array->addr[pagen] = viraddr; | 1635 | mbox->sge_array->addr[pagen] = viraddr; |
1635 | /* Keep the first page for later sub-header construction */ | 1636 | /* Keep the first page for later sub-header construction */ |
1636 | if (pagen == 0) | 1637 | if (pagen == 0) |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index ba698d5f31af..acc43b061ba1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -4139,8 +4139,11 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba, | |||
4139 | return -EIO; | 4139 | return -EIO; |
4140 | } | 4140 | } |
4141 | data_length = mqe->un.mb_words[5]; | 4141 | data_length = mqe->un.mb_words[5]; |
4142 | if (data_length > DMP_FCOEPARAM_RGN_SIZE) | 4142 | if (data_length > DMP_FCOEPARAM_RGN_SIZE) { |
4143 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
4144 | kfree(mp); | ||
4143 | return -EIO; | 4145 | return -EIO; |
4146 | } | ||
4144 | 4147 | ||
4145 | lpfc_parse_fcoe_conf(phba, mp->virt, data_length); | 4148 | lpfc_parse_fcoe_conf(phba, mp->virt, data_length); |
4146 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 4149 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
@@ -7351,6 +7354,32 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, | |||
7351 | } | 7354 | } |
7352 | 7355 | ||
7353 | /** | 7356 | /** |
7357 | * lpfc_chk_iocb_flg - Test IOCB flag with lock held. | ||
7358 | * @phba: Pointer to HBA context object.. | ||
7359 | * @piocbq: Pointer to command iocb. | ||
7360 | * @flag: Flag to test. | ||
7361 | * | ||
7362 | * This routine grabs the hbalock and then test the iocb_flag to | ||
7363 | * see if the passed in flag is set. | ||
7364 | * Returns: | ||
7365 | * 1 if flag is set. | ||
7366 | * 0 if flag is not set. | ||
7367 | **/ | ||
7368 | static int | ||
7369 | lpfc_chk_iocb_flg(struct lpfc_hba *phba, | ||
7370 | struct lpfc_iocbq *piocbq, uint32_t flag) | ||
7371 | { | ||
7372 | unsigned long iflags; | ||
7373 | int ret; | ||
7374 | |||
7375 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
7376 | ret = piocbq->iocb_flag & flag; | ||
7377 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
7378 | return ret; | ||
7379 | |||
7380 | } | ||
7381 | |||
7382 | /** | ||
7354 | * lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands | 7383 | * lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands |
7355 | * @phba: Pointer to HBA context object.. | 7384 | * @phba: Pointer to HBA context object.. |
7356 | * @pring: Pointer to sli ring. | 7385 | * @pring: Pointer to sli ring. |
@@ -7417,7 +7446,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, | |||
7417 | if (retval == IOCB_SUCCESS) { | 7446 | if (retval == IOCB_SUCCESS) { |
7418 | timeout_req = timeout * HZ; | 7447 | timeout_req = timeout * HZ; |
7419 | timeleft = wait_event_timeout(done_q, | 7448 | timeleft = wait_event_timeout(done_q, |
7420 | piocb->iocb_flag & LPFC_IO_WAKE, | 7449 | lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE), |
7421 | timeout_req); | 7450 | timeout_req); |
7422 | 7451 | ||
7423 | if (piocb->iocb_flag & LPFC_IO_WAKE) { | 7452 | if (piocb->iocb_flag & LPFC_IO_WAKE) { |
@@ -7602,20 +7631,16 @@ lpfc_sli_eratt_read(struct lpfc_hba *phba) | |||
7602 | if ((HS_FFER1 & phba->work_hs) && | 7631 | if ((HS_FFER1 & phba->work_hs) && |
7603 | ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 | | 7632 | ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 | |
7604 | HS_FFER6 | HS_FFER7) & phba->work_hs)) { | 7633 | HS_FFER6 | HS_FFER7) & phba->work_hs)) { |
7605 | spin_lock_irq(&phba->hbalock); | ||
7606 | phba->hba_flag |= DEFER_ERATT; | 7634 | phba->hba_flag |= DEFER_ERATT; |
7607 | spin_unlock_irq(&phba->hbalock); | ||
7608 | /* Clear all interrupt enable conditions */ | 7635 | /* Clear all interrupt enable conditions */ |
7609 | writel(0, phba->HCregaddr); | 7636 | writel(0, phba->HCregaddr); |
7610 | readl(phba->HCregaddr); | 7637 | readl(phba->HCregaddr); |
7611 | } | 7638 | } |
7612 | 7639 | ||
7613 | /* Set the driver HA work bitmap */ | 7640 | /* Set the driver HA work bitmap */ |
7614 | spin_lock_irq(&phba->hbalock); | ||
7615 | phba->work_ha |= HA_ERATT; | 7641 | phba->work_ha |= HA_ERATT; |
7616 | /* Indicate polling handles this ERATT */ | 7642 | /* Indicate polling handles this ERATT */ |
7617 | phba->hba_flag |= HBA_ERATT_HANDLED; | 7643 | phba->hba_flag |= HBA_ERATT_HANDLED; |
7618 | spin_unlock_irq(&phba->hbalock); | ||
7619 | return 1; | 7644 | return 1; |
7620 | } | 7645 | } |
7621 | return 0; | 7646 | return 0; |
@@ -7661,12 +7686,10 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) | |||
7661 | return 0; | 7686 | return 0; |
7662 | phba->work_status[0] = uerr_sta_lo; | 7687 | phba->work_status[0] = uerr_sta_lo; |
7663 | phba->work_status[1] = uerr_sta_hi; | 7688 | phba->work_status[1] = uerr_sta_hi; |
7664 | spin_lock_irq(&phba->hbalock); | ||
7665 | /* Set the driver HA work bitmap */ | 7689 | /* Set the driver HA work bitmap */ |
7666 | phba->work_ha |= HA_ERATT; | 7690 | phba->work_ha |= HA_ERATT; |
7667 | /* Indicate polling handles this ERATT */ | 7691 | /* Indicate polling handles this ERATT */ |
7668 | phba->hba_flag |= HBA_ERATT_HANDLED; | 7692 | phba->hba_flag |= HBA_ERATT_HANDLED; |
7669 | spin_unlock_irq(&phba->hbalock); | ||
7670 | return 1; | 7693 | return 1; |
7671 | } | 7694 | } |
7672 | } | 7695 | } |
@@ -9349,6 +9372,7 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size, | |||
9349 | kfree(dmabuf); | 9372 | kfree(dmabuf); |
9350 | goto out_fail; | 9373 | goto out_fail; |
9351 | } | 9374 | } |
9375 | memset(dmabuf->virt, 0, PAGE_SIZE); | ||
9352 | dmabuf->buffer_tag = x; | 9376 | dmabuf->buffer_tag = x; |
9353 | list_add_tail(&dmabuf->list, &queue->page_list); | 9377 | list_add_tail(&dmabuf->list, &queue->page_list); |
9354 | /* initialize queue's entry array */ | 9378 | /* initialize queue's entry array */ |
@@ -9771,7 +9795,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, | |||
9771 | /* link the wq onto the parent cq child list */ | 9795 | /* link the wq onto the parent cq child list */ |
9772 | list_add_tail(&wq->list, &cq->child_list); | 9796 | list_add_tail(&wq->list, &cq->child_list); |
9773 | out: | 9797 | out: |
9774 | if (rc == MBX_TIMEOUT) | 9798 | if (rc != MBX_TIMEOUT) |
9775 | mempool_free(mbox, phba->mbox_mem_pool); | 9799 | mempool_free(mbox, phba->mbox_mem_pool); |
9776 | return status; | 9800 | return status; |
9777 | } | 9801 | } |