aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2010-02-12 14:43:01 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-02-17 18:41:19 -0500
commit72100cc43262fa39821b3debc04be1a7a17b3428 (patch)
tree2f313571ee9c9cf4d4a16f2a6e69f82c569b9757
parent84d1b006978e78e27f22beb5cfbc4d349bac6df7 (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>
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c33
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c5
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.