aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2009-06-10 17:23:06 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-06-15 11:09:33 -0400
commitd11e31ddb9718755dc96e1c018843ae6f5bb085e (patch)
treec6314c3e2b528077c8ff7c4ade53aa4ab74407ba /drivers/scsi/lpfc
parent0c2875893ef27b93d5d3221f8f98ae944d6be5fa (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.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c42
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 **/
7368static int
7369lpfc_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);
9773out: 9797out:
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}