aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-08-02 11:09:51 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-08-01 13:18:23 -0400
commit549e55cd2a1b83ea45ac17fb6c309654a3d371a4 (patch)
tree0abf10a28b177e129932c62b3b94994ce4f3aadb /drivers/scsi/lpfc/lpfc_init.c
parenta58cbd5212fff2d4bba0bf58e778f02069597294 (diff)
[SCSI] lpfc 8.2.2 : Fix locking around HBA's port_list
Cleans up a lot of bad behaviors that have been in this area a while Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c134
1 files changed, 75 insertions, 59 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 07bd0dcdf0d6..484070c82974 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -437,16 +437,18 @@ lpfc_config_port_post(struct lpfc_hba *phba)
437int 437int
438lpfc_hba_down_prep(struct lpfc_hba *phba) 438lpfc_hba_down_prep(struct lpfc_hba *phba)
439{ 439{
440 struct lpfc_vport *vport = phba->pport; 440 struct lpfc_vport **vports;
441 int i;
441 442
442 /* Disable interrupts */ 443 /* Disable interrupts */
443 writel(0, phba->HCregaddr); 444 writel(0, phba->HCregaddr);
444 readl(phba->HCregaddr); /* flush */ 445 readl(phba->HCregaddr); /* flush */
445 446
446 list_for_each_entry(vport, &phba->port_list, listentry) { 447 vports = lpfc_create_vport_work_array(phba);
447 lpfc_cleanup_discovery_resources(vport); 448 if (vports != NULL)
448 } 449 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++)
449 450 lpfc_cleanup_discovery_resources(vports[i]);
451 lpfc_destroy_vport_work_array(vports);
450 return 0; 452 return 0;
451} 453}
452 454
@@ -615,9 +617,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
615 struct lpfc_vport *vport = phba->pport; 617 struct lpfc_vport *vport = phba->pport;
616 struct lpfc_sli *psli = &phba->sli; 618 struct lpfc_sli *psli = &phba->sli;
617 struct lpfc_sli_ring *pring; 619 struct lpfc_sli_ring *pring;
618 struct lpfc_vport *port_iterator; 620 struct lpfc_vport **vports;
619 uint32_t event_data; 621 uint32_t event_data;
620 struct Scsi_Host *shost; 622 struct Scsi_Host *shost;
623 int i;
621 624
622 /* If the pci channel is offline, ignore possible errors, 625 /* If the pci channel is offline, ignore possible errors,
623 * since we cannot communicate with the pci card anyway. */ 626 * since we cannot communicate with the pci card anyway. */
@@ -632,14 +635,17 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
632 "Data: x%x x%x x%x\n", 635 "Data: x%x x%x x%x\n",
633 phba->brd_no, phba->work_hs, 636 phba->brd_no, phba->work_hs,
634 phba->work_status[0], phba->work_status[1]); 637 phba->work_status[0], phba->work_status[1]);
635 list_for_each_entry(port_iterator, &phba->port_list, 638 vports = lpfc_create_vport_work_array(phba);
636 listentry) { 639 if (vports != NULL)
637 shost = lpfc_shost_from_vport(port_iterator); 640 for(i = 0;
638 641 i < LPFC_MAX_VPORTS && vports[i] != NULL;
639 spin_lock_irq(shost->host_lock); 642 i++){
640 port_iterator->fc_flag |= FC_ESTABLISH_LINK; 643 shost = lpfc_shost_from_vport(vports[i]);
641 spin_unlock_irq(shost->host_lock); 644 spin_lock_irq(shost->host_lock);
642 } 645 vports[i]->fc_flag |= FC_ESTABLISH_LINK;
646 spin_unlock_irq(shost->host_lock);
647 }
648 lpfc_destroy_vport_work_array(vports);
643 spin_lock_irq(&phba->hbalock); 649 spin_lock_irq(&phba->hbalock);
644 psli->sli_flag &= ~LPFC_SLI2_ACTIVE; 650 psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
645 spin_unlock_irq(&phba->hbalock); 651 spin_unlock_irq(&phba->hbalock);
@@ -708,7 +714,6 @@ lpfc_handle_latt(struct lpfc_hba *phba)
708{ 714{
709 struct lpfc_vport *vport = phba->pport; 715 struct lpfc_vport *vport = phba->pport;
710 struct lpfc_sli *psli = &phba->sli; 716 struct lpfc_sli *psli = &phba->sli;
711 struct lpfc_vport *port_iterator;
712 LPFC_MBOXQ_t *pmb; 717 LPFC_MBOXQ_t *pmb;
713 volatile uint32_t control; 718 volatile uint32_t control;
714 struct lpfc_dmabuf *mp; 719 struct lpfc_dmabuf *mp;
@@ -729,8 +734,7 @@ lpfc_handle_latt(struct lpfc_hba *phba)
729 rc = -EIO; 734 rc = -EIO;
730 735
731 /* Cleanup any outstanding ELS commands */ 736 /* Cleanup any outstanding ELS commands */
732 list_for_each_entry(port_iterator, &phba->port_list, listentry) 737 lpfc_els_flush_all_cmd(phba);
733 lpfc_els_flush_cmd(port_iterator);
734 738
735 psli->slistat.link_event++; 739 psli->slistat.link_event++;
736 lpfc_read_la(phba, pmb, mp); 740 lpfc_read_la(phba, pmb, mp);
@@ -1313,22 +1317,26 @@ static void
1313lpfc_establish_link_tmo(unsigned long ptr) 1317lpfc_establish_link_tmo(unsigned long ptr)
1314{ 1318{
1315 struct lpfc_hba *phba = (struct lpfc_hba *) ptr; 1319 struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
1316 struct lpfc_vport *vport = phba->pport; 1320 struct lpfc_vport **vports;
1317 unsigned long iflag; 1321 unsigned long iflag;
1322 int i;
1318 1323
1319 /* Re-establishing Link, timer expired */ 1324 /* Re-establishing Link, timer expired */
1320 lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, 1325 lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
1321 "%d:1300 Re-establishing Link, timer expired " 1326 "%d:1300 Re-establishing Link, timer expired "
1322 "Data: x%x x%x\n", 1327 "Data: x%x x%x\n",
1323 phba->brd_no, vport->fc_flag, 1328 phba->brd_no, phba->pport->fc_flag,
1324 vport->port_state); 1329 phba->pport->port_state);
1325 list_for_each_entry(vport, &phba->port_list, listentry) { 1330 vports = lpfc_create_vport_work_array(phba);
1326 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 1331 if (vports != NULL)
1327 1332 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
1328 spin_lock_irqsave(shost->host_lock, iflag); 1333 struct Scsi_Host *shost;
1329 vport->fc_flag &= ~FC_ESTABLISH_LINK; 1334 shost = lpfc_shost_from_vport(vports[i]);
1330 spin_unlock_irqrestore(shost->host_lock, iflag); 1335 spin_lock_irqsave(shost->host_lock, iflag);
1331 } 1336 vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
1337 spin_unlock_irqrestore(shost->host_lock, iflag);
1338 }
1339 lpfc_destroy_vport_work_array(vports);
1332} 1340}
1333 1341
1334void 1342void
@@ -1343,12 +1351,16 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
1343static void 1351static void
1344lpfc_stop_phba_timers(struct lpfc_hba *phba) 1352lpfc_stop_phba_timers(struct lpfc_hba *phba)
1345{ 1353{
1346 struct lpfc_vport *vport; 1354 struct lpfc_vport **vports;
1355 int i;
1347 1356
1348 del_timer_sync(&phba->fcp_poll_timer); 1357 del_timer_sync(&phba->fcp_poll_timer);
1349 del_timer_sync(&phba->fc_estabtmo); 1358 del_timer_sync(&phba->fc_estabtmo);
1350 list_for_each_entry(vport, &phba->port_list, listentry) 1359 vports = lpfc_create_vport_work_array(phba);
1351 lpfc_stop_vport_timers(vport); 1360 if (vports != NULL)
1361 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++)
1362 lpfc_stop_vport_timers(vports[i]);
1363 lpfc_destroy_vport_work_array(vports);
1352 del_timer_sync(&phba->sli.mbox_tmo); 1364 del_timer_sync(&phba->sli.mbox_tmo);
1353 del_timer_sync(&phba->fabric_block_timer); 1365 del_timer_sync(&phba->fabric_block_timer);
1354 phba->hb_outstanding = 0; 1366 phba->hb_outstanding = 0;
@@ -1360,6 +1372,8 @@ int
1360lpfc_online(struct lpfc_hba *phba) 1372lpfc_online(struct lpfc_hba *phba)
1361{ 1373{
1362 struct lpfc_vport *vport = phba->pport; 1374 struct lpfc_vport *vport = phba->pport;
1375 struct lpfc_vport **vports;
1376 int i;
1363 1377
1364 if (!phba) 1378 if (!phba)
1365 return 0; 1379 return 0;
@@ -1383,14 +1397,18 @@ lpfc_online(struct lpfc_hba *phba)
1383 return 1; 1397 return 1;
1384 } 1398 }
1385 1399
1386 list_for_each_entry(vport, &phba->port_list, listentry) { 1400 vports = lpfc_create_vport_work_array(phba);
1387 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 1401 if (vports != NULL)
1388 spin_lock_irq(shost->host_lock); 1402 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
1389 vport->fc_flag &= ~FC_OFFLINE_MODE; 1403 struct Scsi_Host *shost;
1390 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) 1404 shost = lpfc_shost_from_vport(vports[i]);
1391 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; 1405 spin_lock_irq(shost->host_lock);
1392 spin_unlock_irq(shost->host_lock); 1406 vports[i]->fc_flag &= ~FC_OFFLINE_MODE;
1393 } 1407 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
1408 vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
1409 spin_unlock_irq(shost->host_lock);
1410 }
1411 lpfc_destroy_vport_work_array(vports);
1394 1412
1395 lpfc_unblock_mgmt_io(phba); 1413 lpfc_unblock_mgmt_io(phba);
1396 return 0; 1414 return 0;
@@ -1440,39 +1458,35 @@ lpfc_offline_prep(struct lpfc_hba * phba)
1440void 1458void
1441lpfc_offline(struct lpfc_hba *phba) 1459lpfc_offline(struct lpfc_hba *phba)
1442{ 1460{
1443 struct lpfc_vport *vport = phba->pport; 1461 struct Scsi_Host *shost;
1444 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 1462 struct lpfc_vport **vports;
1445 struct lpfc_vport *port_iterator; 1463 int i;
1446 1464
1447 if (vport->fc_flag & FC_OFFLINE_MODE) 1465 if (phba->pport->fc_flag & FC_OFFLINE_MODE)
1448 return; 1466 return;
1449 1467
1450 /* stop all timers associated with this hba */ 1468 /* stop all timers associated with this hba */
1451 lpfc_stop_phba_timers(phba); 1469 lpfc_stop_phba_timers(phba);
1452 list_for_each_entry(port_iterator, &phba->port_list, listentry) {
1453 port_iterator->work_port_events = 0;
1454 }
1455
1456 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, 1470 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
1457 "%d:0460 Bring Adapter offline\n", 1471 "%d:0460 Bring Adapter offline\n",
1458 phba->brd_no); 1472 phba->brd_no);
1459
1460 /* Bring down the SLI Layer and cleanup. The HBA is offline 1473 /* Bring down the SLI Layer and cleanup. The HBA is offline
1461 now. */ 1474 now. */
1462 lpfc_sli_hba_down(phba); 1475 lpfc_sli_hba_down(phba);
1463 spin_lock_irq(&phba->hbalock); 1476 spin_lock_irq(&phba->hbalock);
1464 phba->work_ha = 0; 1477 phba->work_ha = 0;
1465 vport->fc_flag |= FC_OFFLINE_MODE;
1466 spin_unlock_irq(&phba->hbalock); 1478 spin_unlock_irq(&phba->hbalock);
1467 list_for_each_entry(port_iterator, &phba->port_list, listentry) { 1479 vports = lpfc_create_vport_work_array(phba);
1468 shost = lpfc_shost_from_vport(port_iterator); 1480 if (vports != NULL)
1469 1481 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
1470 lpfc_cleanup(port_iterator); 1482 shost = lpfc_shost_from_vport(vports[i]);
1471 spin_lock_irq(shost->host_lock); 1483 lpfc_cleanup(vports[i]);
1472 vport->work_port_events = 0; 1484 spin_lock_irq(shost->host_lock);
1473 vport->fc_flag |= FC_OFFLINE_MODE; 1485 vports[i]->work_port_events = 0;
1474 spin_unlock_irq(shost->host_lock); 1486 vports[i]->fc_flag |= FC_OFFLINE_MODE;
1475 } 1487 spin_unlock_irq(shost->host_lock);
1488 }
1489 lpfc_destroy_vport_work_array(vports);
1476} 1490}
1477 1491
1478/****************************************************************************** 1492/******************************************************************************
@@ -1509,7 +1523,6 @@ lpfc_scsi_free(struct lpfc_hba *phba)
1509 return 0; 1523 return 0;
1510} 1524}
1511 1525
1512
1513struct lpfc_vport * 1526struct lpfc_vport *
1514lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) 1527lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport)
1515{ 1528{
@@ -1570,7 +1583,9 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport)
1570 if (error) 1583 if (error)
1571 goto out_put_shost; 1584 goto out_put_shost;
1572 1585
1586 spin_lock_irq(&phba->hbalock);
1573 list_add_tail(&vport->listentry, &phba->port_list); 1587 list_add_tail(&vport->listentry, &phba->port_list);
1588 spin_unlock_irq(&phba->hbalock);
1574 return vport; 1589 return vport;
1575 1590
1576out_put_shost: 1591out_put_shost:
@@ -1990,8 +2005,10 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
1990 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 2005 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1991 struct lpfc_hba *phba = vport->phba; 2006 struct lpfc_hba *phba = vport->phba;
1992 struct lpfc_vport *port_iterator; 2007 struct lpfc_vport *port_iterator;
2008 spin_lock_irq(&phba->hbalock);
1993 list_for_each_entry(port_iterator, &phba->port_list, listentry) 2009 list_for_each_entry(port_iterator, &phba->port_list, listentry)
1994 port_iterator->load_flag |= FC_UNLOADING; 2010 port_iterator->load_flag |= FC_UNLOADING;
2011 spin_unlock_irq(&phba->hbalock);
1995 2012
1996 kfree(vport->vname); 2013 kfree(vport->vname);
1997 lpfc_free_sysfs_attr(vport); 2014 lpfc_free_sysfs_attr(vport);
@@ -2012,7 +2029,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
2012 list_del_init(&vport->listentry); 2029 list_del_init(&vport->listentry);
2013 spin_unlock_irq(&phba->hbalock); 2030 spin_unlock_irq(&phba->hbalock);
2014 2031
2015
2016 lpfc_debugfs_terminate(vport); 2032 lpfc_debugfs_terminate(vport);
2017 lpfc_cleanup(vport); 2033 lpfc_cleanup(vport);
2018 2034