diff options
author | James Smart <james.smart@emulex.com> | 2010-02-12 14:43:01 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-02-17 18:41:19 -0500 |
commit | 72100cc43262fa39821b3debc04be1a7a17b3428 (patch) | |
tree | 2f313571ee9c9cf4d4a16f2a6e69f82c569b9757 /drivers/scsi/lpfc | |
parent | 84d1b006978e78e27f22beb5cfbc4d349bac6df7 (diff) |
[SCSI] lpfc 8.3.9: Fix locking and memory issues
- Use the hbalock when changing the fc_flag.
- Use the host_lock when changeing the sli_flag.
- Prevent NULL pointer dereference after dma_alloc_coherent failure.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 33 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 5 |
4 files changed, 32 insertions, 17 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index b890e2dc15db..2359d0bfb734 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -757,11 +757,13 @@ lpfc_linkdown(struct lpfc_hba *phba) | |||
757 | 757 | ||
758 | spin_lock_irq(&phba->hbalock); | 758 | spin_lock_irq(&phba->hbalock); |
759 | phba->fcf.fcf_flag &= ~(FCF_AVAILABLE | FCF_SCAN_DONE); | 759 | phba->fcf.fcf_flag &= ~(FCF_AVAILABLE | FCF_SCAN_DONE); |
760 | spin_unlock_irq(&phba->hbalock); | ||
760 | if (phba->link_state > LPFC_LINK_DOWN) { | 761 | if (phba->link_state > LPFC_LINK_DOWN) { |
761 | phba->link_state = LPFC_LINK_DOWN; | 762 | phba->link_state = LPFC_LINK_DOWN; |
763 | spin_lock_irq(shost->host_lock); | ||
762 | phba->pport->fc_flag &= ~FC_LBIT; | 764 | phba->pport->fc_flag &= ~FC_LBIT; |
765 | spin_unlock_irq(shost->host_lock); | ||
763 | } | 766 | } |
764 | spin_unlock_irq(&phba->hbalock); | ||
765 | vports = lpfc_create_vport_work_array(phba); | 767 | vports = lpfc_create_vport_work_array(phba); |
766 | if (vports != NULL) | 768 | if (vports != NULL) |
767 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { | 769 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
@@ -1802,6 +1804,8 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1802 | { | 1804 | { |
1803 | struct lpfc_vport *vport = mboxq->vport; | 1805 | struct lpfc_vport *vport = mboxq->vport; |
1804 | struct lpfc_nodelist *ndlp; | 1806 | struct lpfc_nodelist *ndlp; |
1807 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1808 | |||
1805 | if (mboxq->u.mb.mbxStatus) { | 1809 | if (mboxq->u.mb.mbxStatus) { |
1806 | lpfc_printf_vlog(vport, KERN_ERR, | 1810 | lpfc_printf_vlog(vport, KERN_ERR, |
1807 | LOG_MBOX, | 1811 | LOG_MBOX, |
@@ -1811,9 +1815,9 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1811 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 1815 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
1812 | return; | 1816 | return; |
1813 | } | 1817 | } |
1814 | spin_lock_irq(&phba->hbalock); | 1818 | spin_lock_irq(shost->host_lock); |
1815 | vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI; | 1819 | vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI; |
1816 | spin_unlock_irq(&phba->hbalock); | 1820 | spin_unlock_irq(shost->host_lock); |
1817 | 1821 | ||
1818 | /* If this port is physical port or FDISC is done, do reg_vpi */ | 1822 | /* If this port is physical port or FDISC is done, do reg_vpi */ |
1819 | if ((phba->pport == vport) || (vport->port_state == LPFC_FDISC)) { | 1823 | if ((phba->pport == vport) || (vport->port_state == LPFC_FDISC)) { |
@@ -1924,6 +1928,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1924 | { | 1928 | { |
1925 | struct lpfc_dmabuf *dmabuf = mboxq->context1; | 1929 | struct lpfc_dmabuf *dmabuf = mboxq->context1; |
1926 | struct lpfc_vport *vport = mboxq->vport; | 1930 | struct lpfc_vport *vport = mboxq->vport; |
1931 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1927 | 1932 | ||
1928 | if (mboxq->u.mb.mbxStatus) { | 1933 | if (mboxq->u.mb.mbxStatus) { |
1929 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, | 1934 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
@@ -1941,10 +1946,11 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1941 | goto fail_free_mem; | 1946 | goto fail_free_mem; |
1942 | } | 1947 | } |
1943 | /* The VPI is implicitly registered when the VFI is registered */ | 1948 | /* The VPI is implicitly registered when the VFI is registered */ |
1949 | spin_lock_irq(shost->host_lock); | ||
1944 | vport->vpi_state |= LPFC_VPI_REGISTERED; | 1950 | vport->vpi_state |= LPFC_VPI_REGISTERED; |
1945 | vport->fc_flag |= FC_VFI_REGISTERED; | 1951 | vport->fc_flag |= FC_VFI_REGISTERED; |
1946 | |||
1947 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | 1952 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; |
1953 | spin_unlock_irq(shost->host_lock); | ||
1948 | 1954 | ||
1949 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { | 1955 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { |
1950 | lpfc_start_fdiscs(phba); | 1956 | lpfc_start_fdiscs(phba); |
@@ -2269,10 +2275,12 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2269 | } | 2275 | } |
2270 | 2276 | ||
2271 | phba->fc_eventTag = la->eventTag; | 2277 | phba->fc_eventTag = la->eventTag; |
2278 | spin_lock_irq(&phba->hbalock); | ||
2272 | if (la->mm) | 2279 | if (la->mm) |
2273 | phba->sli.sli_flag |= LPFC_MENLO_MAINT; | 2280 | phba->sli.sli_flag |= LPFC_MENLO_MAINT; |
2274 | else | 2281 | else |
2275 | phba->sli.sli_flag &= ~LPFC_MENLO_MAINT; | 2282 | phba->sli.sli_flag &= ~LPFC_MENLO_MAINT; |
2283 | spin_unlock_irq(&phba->hbalock); | ||
2276 | 2284 | ||
2277 | phba->link_events++; | 2285 | phba->link_events++; |
2278 | if (la->attType == AT_LINK_UP && (!la->mm)) { | 2286 | if (la->attType == AT_LINK_UP && (!la->mm)) { |
@@ -2401,10 +2409,10 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2401 | mb->mbxStatus); | 2409 | mb->mbxStatus); |
2402 | break; | 2410 | break; |
2403 | } | 2411 | } |
2404 | spin_lock_irq(&phba->hbalock); | 2412 | spin_lock_irq(shost->host_lock); |
2405 | vport->vpi_state &= ~LPFC_VPI_REGISTERED; | 2413 | vport->vpi_state &= ~LPFC_VPI_REGISTERED; |
2406 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 2414 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
2407 | spin_unlock_irq(&phba->hbalock); | 2415 | spin_unlock_irq(shost->host_lock); |
2408 | vport->unreg_vpi_cmpl = VPORT_OK; | 2416 | vport->unreg_vpi_cmpl = VPORT_OK; |
2409 | mempool_free(pmb, phba->mbox_mem_pool); | 2417 | mempool_free(pmb, phba->mbox_mem_pool); |
2410 | /* | 2418 | /* |
@@ -2462,8 +2470,10 @@ lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2462 | goto out; | 2470 | goto out; |
2463 | } | 2471 | } |
2464 | 2472 | ||
2473 | spin_lock_irq(shost->host_lock); | ||
2465 | vport->vpi_state |= LPFC_VPI_REGISTERED; | 2474 | vport->vpi_state |= LPFC_VPI_REGISTERED; |
2466 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | 2475 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; |
2476 | spin_unlock_irq(shost->host_lock); | ||
2467 | vport->num_disc_nodes = 0; | 2477 | vport->num_disc_nodes = 0; |
2468 | /* go thru NPR list and issue ELS PLOGIs */ | 2478 | /* go thru NPR list and issue ELS PLOGIs */ |
2469 | if (vport->fc_npr_cnt) | 2479 | if (vport->fc_npr_cnt) |
@@ -4620,6 +4630,7 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) | |||
4620 | LPFC_MBOXQ_t *mbox; | 4630 | LPFC_MBOXQ_t *mbox; |
4621 | struct lpfc_vport **vports; | 4631 | struct lpfc_vport **vports; |
4622 | struct lpfc_nodelist *ndlp; | 4632 | struct lpfc_nodelist *ndlp; |
4633 | struct Scsi_Host *shost; | ||
4623 | int i, rc; | 4634 | int i, rc; |
4624 | 4635 | ||
4625 | /* Unregister RPIs */ | 4636 | /* Unregister RPIs */ |
@@ -4638,10 +4649,11 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) | |||
4638 | if (ndlp) | 4649 | if (ndlp) |
4639 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); | 4650 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); |
4640 | lpfc_mbx_unreg_vpi(vports[i]); | 4651 | lpfc_mbx_unreg_vpi(vports[i]); |
4641 | spin_lock_irq(&phba->hbalock); | 4652 | shost = lpfc_shost_from_vport(vports[i]); |
4653 | spin_lock_irq(shost->host_lock); | ||
4642 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | 4654 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; |
4643 | vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; | 4655 | vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; |
4644 | spin_unlock_irq(&phba->hbalock); | 4656 | spin_unlock_irq(shost->host_lock); |
4645 | } | 4657 | } |
4646 | lpfc_destroy_vport_work_array(phba, vports); | 4658 | lpfc_destroy_vport_work_array(phba, vports); |
4647 | 4659 | ||
@@ -4671,9 +4683,10 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) | |||
4671 | return -EIO; | 4683 | return -EIO; |
4672 | } | 4684 | } |
4673 | 4685 | ||
4674 | spin_lock_irq(&phba->hbalock); | 4686 | shost = lpfc_shost_from_vport(phba->pport); |
4687 | spin_lock_irq(shost->host_lock); | ||
4675 | phba->pport->fc_flag &= ~FC_VFI_REGISTERED; | 4688 | phba->pport->fc_flag &= ~FC_VFI_REGISTERED; |
4676 | spin_unlock_irq(&phba->hbalock); | 4689 | spin_unlock_irq(shost->host_lock); |
4677 | 4690 | ||
4678 | return 0; | 4691 | return 0; |
4679 | } | 4692 | } |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 89d886c72e0a..d29ac7c317d9 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -2363,6 +2363,7 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
2363 | struct lpfc_vport *vport = phba->pport; | 2363 | struct lpfc_vport *vport = phba->pport; |
2364 | struct lpfc_nodelist *ndlp, *next_ndlp; | 2364 | struct lpfc_nodelist *ndlp, *next_ndlp; |
2365 | struct lpfc_vport **vports; | 2365 | struct lpfc_vport **vports; |
2366 | struct Scsi_Host *shost; | ||
2366 | int i; | 2367 | int i; |
2367 | 2368 | ||
2368 | if (vport->fc_flag & FC_OFFLINE_MODE) | 2369 | if (vport->fc_flag & FC_OFFLINE_MODE) |
@@ -2376,13 +2377,14 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
2376 | vports = lpfc_create_vport_work_array(phba); | 2377 | vports = lpfc_create_vport_work_array(phba); |
2377 | if (vports != NULL) { | 2378 | if (vports != NULL) { |
2378 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { | 2379 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
2379 | struct Scsi_Host *shost; | ||
2380 | |||
2381 | if (vports[i]->load_flag & FC_UNLOADING) | 2380 | if (vports[i]->load_flag & FC_UNLOADING) |
2382 | continue; | 2381 | continue; |
2382 | shost = lpfc_shost_from_vport(vports[i]); | ||
2383 | spin_lock_irq(shost->host_lock); | ||
2383 | vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; | 2384 | vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; |
2384 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 2385 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
2385 | vports[i]->fc_flag &= ~FC_VFI_REGISTERED; | 2386 | vports[i]->fc_flag &= ~FC_VFI_REGISTERED; |
2387 | spin_unlock_irq(shost->host_lock); | ||
2386 | 2388 | ||
2387 | shost = lpfc_shost_from_vport(vports[i]); | 2389 | shost = lpfc_shost_from_vport(vports[i]); |
2388 | list_for_each_entry_safe(ndlp, next_ndlp, | 2390 | list_for_each_entry_safe(ndlp, next_ndlp, |
@@ -2789,8 +2791,6 @@ lpfc_stop_port_s4(struct lpfc_hba *phba) | |||
2789 | lpfc_stop_hba_timers(phba); | 2791 | lpfc_stop_hba_timers(phba); |
2790 | phba->pport->work_port_events = 0; | 2792 | phba->pport->work_port_events = 0; |
2791 | phba->sli4_hba.intr_enable = 0; | 2793 | phba->sli4_hba.intr_enable = 0; |
2792 | /* Hard clear it for now, shall have more graceful way to wait later */ | ||
2793 | phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; | ||
2794 | } | 2794 | } |
2795 | 2795 | ||
2796 | /** | 2796 | /** |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 6c1d8b3fe8cc..6c4dce1a30ca 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -1707,7 +1707,8 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | |||
1707 | alloc_len - sizeof(union lpfc_sli4_cfg_shdr); | 1707 | alloc_len - sizeof(union lpfc_sli4_cfg_shdr); |
1708 | } | 1708 | } |
1709 | /* The sub-header is in DMA memory, which needs endian converstion */ | 1709 | /* The sub-header is in DMA memory, which needs endian converstion */ |
1710 | lpfc_sli_pcimem_bcopy(cfg_shdr, cfg_shdr, | 1710 | if (cfg_shdr) |
1711 | lpfc_sli_pcimem_bcopy(cfg_shdr, cfg_shdr, | ||
1711 | sizeof(union lpfc_sli4_cfg_shdr)); | 1712 | sizeof(union lpfc_sli4_cfg_shdr)); |
1712 | 1713 | ||
1713 | return alloc_len; | 1714 | return alloc_len; |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 281ff033a7b2..dc86e873102a 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -505,6 +505,7 @@ enable_vport(struct fc_vport *fc_vport) | |||
505 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; | 505 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; |
506 | struct lpfc_hba *phba = vport->phba; | 506 | struct lpfc_hba *phba = vport->phba; |
507 | struct lpfc_nodelist *ndlp = NULL; | 507 | struct lpfc_nodelist *ndlp = NULL; |
508 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
508 | 509 | ||
509 | if ((phba->link_state < LPFC_LINK_UP) || | 510 | if ((phba->link_state < LPFC_LINK_UP) || |
510 | (phba->fc_topology == TOPOLOGY_LOOP)) { | 511 | (phba->fc_topology == TOPOLOGY_LOOP)) { |
@@ -512,10 +513,10 @@ enable_vport(struct fc_vport *fc_vport) | |||
512 | return VPORT_OK; | 513 | return VPORT_OK; |
513 | } | 514 | } |
514 | 515 | ||
515 | spin_lock_irq(&phba->hbalock); | 516 | spin_lock_irq(shost->host_lock); |
516 | vport->load_flag |= FC_LOADING; | 517 | vport->load_flag |= FC_LOADING; |
517 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 518 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
518 | spin_unlock_irq(&phba->hbalock); | 519 | spin_unlock_irq(shost->host_lock); |
519 | 520 | ||
520 | /* Use the Physical nodes Fabric NDLP to determine if the link is | 521 | /* Use the Physical nodes Fabric NDLP to determine if the link is |
521 | * up and ready to FDISC. | 522 | * up and ready to FDISC. |