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 | |
| 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>
| -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 | } |
