diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:39 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:38:11 -0400 |
commit | 858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8 (patch) | |
tree | 9591b15b4424066023e375ad0aa33fdd37e1c452 /drivers/scsi/lpfc/lpfc_init.c | |
parent | 92d7f7b0cde3ad2260e7462b40867b57efd49851 (diff) |
[SCSI] lpfc: bug fixes
Following the NPIV support, the following changes have been accumulated
in the testing and qualification of the driver:
- Fix affinity of ELS ring to slow/deferred event processing
- Fix Ring attention masks
- Defer dev_loss_tmo timeout handling to worker thread
- Consolidate link down error classification for better error checking
- Remove unused/deprecated nlp_initiator_tmr timer
- Fix for async scan - move adapter init code back into pci_probe_one
context. Fix async scan interfaces.
- Expand validation of ability to create vports
- Extract VPI resource cnt from firmware
- Tuning of Login/Reject policies to better deal with overwhelmned targets
- Misc ELS and discovery fixes
- Export the npiv_enable attribute to sysfs
- Mailbox handling fix
- Add debugfs support
- A few other small misc fixes:
- wrong return values, double-frees, bad locking
- Added adapter failure heartbeat
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.c | 228 |
1 files changed, 181 insertions, 47 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4dd0f1aa09e8..350522cbf343 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -391,6 +391,9 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
391 | */ | 391 | */ |
392 | timeout = phba->fc_ratov << 1; | 392 | timeout = phba->fc_ratov << 1; |
393 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); | 393 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); |
394 | mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
395 | phba->hb_outstanding = 0; | ||
396 | phba->last_completion_time = jiffies; | ||
394 | 397 | ||
395 | lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); | 398 | lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); |
396 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 399 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
@@ -485,6 +488,119 @@ lpfc_hba_down_post(struct lpfc_hba *phba) | |||
485 | return 0; | 488 | return 0; |
486 | } | 489 | } |
487 | 490 | ||
491 | /* HBA heart beat timeout handler */ | ||
492 | void | ||
493 | lpfc_hb_timeout(unsigned long ptr) | ||
494 | { | ||
495 | struct lpfc_hba *phba; | ||
496 | unsigned long iflag; | ||
497 | |||
498 | phba = (struct lpfc_hba *)ptr; | ||
499 | spin_lock_irqsave(&phba->pport->work_port_lock, iflag); | ||
500 | if (!(phba->pport->work_port_events & WORKER_HB_TMO)) | ||
501 | phba->pport->work_port_events |= WORKER_HB_TMO; | ||
502 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); | ||
503 | |||
504 | if (phba->work_wait) | ||
505 | wake_up(phba->work_wait); | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | static void | ||
510 | lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | ||
511 | { | ||
512 | unsigned long drvr_flag; | ||
513 | |||
514 | spin_lock_irqsave(&phba->hbalock, drvr_flag); | ||
515 | phba->hb_outstanding = 0; | ||
516 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | ||
517 | |||
518 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
519 | if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) && | ||
520 | !(phba->link_state == LPFC_HBA_ERROR) && | ||
521 | !(phba->pport->fc_flag & FC_UNLOADING)) | ||
522 | mod_timer(&phba->hb_tmofunc, | ||
523 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
524 | return; | ||
525 | } | ||
526 | |||
527 | void | ||
528 | lpfc_hb_timeout_handler(struct lpfc_hba *phba) | ||
529 | { | ||
530 | LPFC_MBOXQ_t *pmboxq; | ||
531 | int retval; | ||
532 | struct lpfc_sli *psli = &phba->sli; | ||
533 | |||
534 | if ((phba->link_state == LPFC_HBA_ERROR) || | ||
535 | (phba->pport->fc_flag & FC_UNLOADING) || | ||
536 | (phba->pport->fc_flag & FC_OFFLINE_MODE)) | ||
537 | return; | ||
538 | |||
539 | spin_lock_irq(&phba->pport->work_port_lock); | ||
540 | /* If the timer is already canceled do nothing */ | ||
541 | if (!(phba->pport->work_port_events & WORKER_HB_TMO)) { | ||
542 | spin_unlock_irq(&phba->pport->work_port_lock); | ||
543 | return; | ||
544 | } | ||
545 | |||
546 | if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ, | ||
547 | jiffies)) { | ||
548 | spin_unlock_irq(&phba->pport->work_port_lock); | ||
549 | if (!phba->hb_outstanding) | ||
550 | mod_timer(&phba->hb_tmofunc, | ||
551 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
552 | else | ||
553 | mod_timer(&phba->hb_tmofunc, | ||
554 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | ||
555 | return; | ||
556 | } | ||
557 | spin_unlock_irq(&phba->pport->work_port_lock); | ||
558 | |||
559 | /* If there is no heart beat outstanding, issue a heartbeat command */ | ||
560 | if (!phba->hb_outstanding) { | ||
561 | pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); | ||
562 | if (!pmboxq) { | ||
563 | mod_timer(&phba->hb_tmofunc, | ||
564 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
565 | return; | ||
566 | } | ||
567 | |||
568 | lpfc_heart_beat(phba, pmboxq); | ||
569 | pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; | ||
570 | pmboxq->vport = phba->pport; | ||
571 | retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | ||
572 | |||
573 | if (retval != MBX_BUSY && retval != MBX_SUCCESS) { | ||
574 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
575 | mod_timer(&phba->hb_tmofunc, | ||
576 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
577 | return; | ||
578 | } | ||
579 | mod_timer(&phba->hb_tmofunc, | ||
580 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | ||
581 | phba->hb_outstanding = 1; | ||
582 | return; | ||
583 | } else { | ||
584 | /* | ||
585 | * If heart beat timeout called with hb_outstanding set we | ||
586 | * need to take the HBA offline. | ||
587 | */ | ||
588 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
589 | "%d:0459 Adapter heartbeat failure, taking " | ||
590 | "this port offline.\n", phba->brd_no); | ||
591 | |||
592 | spin_lock_irq(&phba->hbalock); | ||
593 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
594 | spin_unlock_irq(&phba->hbalock); | ||
595 | |||
596 | lpfc_offline_prep(phba); | ||
597 | lpfc_offline(phba); | ||
598 | lpfc_unblock_mgmt_io(phba); | ||
599 | phba->link_state = LPFC_HBA_ERROR; | ||
600 | lpfc_hba_down_post(phba); | ||
601 | } | ||
602 | } | ||
603 | |||
488 | /************************************************************************/ | 604 | /************************************************************************/ |
489 | /* */ | 605 | /* */ |
490 | /* lpfc_handle_eratt */ | 606 | /* lpfc_handle_eratt */ |
@@ -1190,9 +1306,6 @@ lpfc_cleanup(struct lpfc_vport *vport) | |||
1190 | lpfc_can_disctmo(vport); | 1306 | lpfc_can_disctmo(vport); |
1191 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) | 1307 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) |
1192 | lpfc_nlp_put(ndlp); | 1308 | lpfc_nlp_put(ndlp); |
1193 | |||
1194 | INIT_LIST_HEAD(&vport->fc_nodes); | ||
1195 | |||
1196 | return; | 1309 | return; |
1197 | } | 1310 | } |
1198 | 1311 | ||
@@ -1238,6 +1351,8 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba) | |||
1238 | lpfc_stop_vport_timers(vport); | 1351 | lpfc_stop_vport_timers(vport); |
1239 | del_timer_sync(&phba->sli.mbox_tmo); | 1352 | del_timer_sync(&phba->sli.mbox_tmo); |
1240 | del_timer_sync(&phba->fabric_block_timer); | 1353 | del_timer_sync(&phba->fabric_block_timer); |
1354 | phba->hb_outstanding = 0; | ||
1355 | del_timer_sync(&phba->hb_tmofunc); | ||
1241 | return; | 1356 | return; |
1242 | } | 1357 | } |
1243 | 1358 | ||
@@ -1474,8 +1589,8 @@ destroy_port(struct lpfc_vport *vport) | |||
1474 | struct lpfc_hba *phba = vport->phba; | 1589 | struct lpfc_hba *phba = vport->phba; |
1475 | 1590 | ||
1476 | kfree(vport->vname); | 1591 | kfree(vport->vname); |
1477 | lpfc_free_sysfs_attr(vport); | ||
1478 | 1592 | ||
1593 | lpfc_debugfs_terminate(vport); | ||
1479 | fc_remove_host(shost); | 1594 | fc_remove_host(shost); |
1480 | scsi_remove_host(shost); | 1595 | scsi_remove_host(shost); |
1481 | 1596 | ||
@@ -1500,50 +1615,29 @@ lpfc_get_instance(void) | |||
1500 | return instance; | 1615 | return instance; |
1501 | } | 1616 | } |
1502 | 1617 | ||
1503 | static void | 1618 | /* |
1504 | lpfc_remove_device(struct lpfc_vport *vport) | 1619 | * Note: there is no scan_start function as adapter initialization |
1505 | { | 1620 | * will have asynchronously kicked off the link initialization. |
1506 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1621 | */ |
1507 | |||
1508 | lpfc_free_sysfs_attr(vport); | ||
1509 | |||
1510 | spin_lock_irq(shost->host_lock); | ||
1511 | vport->fc_flag |= FC_UNLOADING; | ||
1512 | spin_unlock_irq(shost->host_lock); | ||
1513 | |||
1514 | fc_remove_host(shost); | ||
1515 | scsi_remove_host(shost); | ||
1516 | } | ||
1517 | |||
1518 | void lpfc_scan_start(struct Scsi_Host *shost) | ||
1519 | { | ||
1520 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
1521 | struct lpfc_hba *phba = vport->phba; | ||
1522 | |||
1523 | if (lpfc_sli_hba_setup(phba)) | ||
1524 | goto error; | ||
1525 | |||
1526 | /* | ||
1527 | * hba setup may have changed the hba_queue_depth so we need to adjust | ||
1528 | * the value of can_queue. | ||
1529 | */ | ||
1530 | shost->can_queue = phba->cfg_hba_queue_depth - 10; | ||
1531 | return; | ||
1532 | |||
1533 | error: | ||
1534 | lpfc_remove_device(vport); | ||
1535 | } | ||
1536 | 1622 | ||
1537 | int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) | 1623 | int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) |
1538 | { | 1624 | { |
1539 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | 1625 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; |
1540 | struct lpfc_hba *phba = vport->phba; | 1626 | struct lpfc_hba *phba = vport->phba; |
1627 | int stat = 0; | ||
1541 | 1628 | ||
1629 | spin_lock_irq(shost->host_lock); | ||
1630 | |||
1631 | if (vport->fc_flag & FC_UNLOADING) { | ||
1632 | stat = 1; | ||
1633 | goto finished; | ||
1634 | } | ||
1542 | if (time >= 30 * HZ) { | 1635 | if (time >= 30 * HZ) { |
1543 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 1636 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
1544 | "%d:0461 Scanning longer than 30 " | 1637 | "%d:0461 Scanning longer than 30 " |
1545 | "seconds. Continuing initialization\n", | 1638 | "seconds. Continuing initialization\n", |
1546 | phba->brd_no); | 1639 | phba->brd_no); |
1640 | stat = 1; | ||
1547 | goto finished; | 1641 | goto finished; |
1548 | } | 1642 | } |
1549 | if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) { | 1643 | if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) { |
@@ -1551,21 +1645,24 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
1551 | "%d:0465 Link down longer than 15 " | 1645 | "%d:0465 Link down longer than 15 " |
1552 | "seconds. Continuing initialization\n", | 1646 | "seconds. Continuing initialization\n", |
1553 | phba->brd_no); | 1647 | phba->brd_no); |
1648 | stat = 1; | ||
1554 | goto finished; | 1649 | goto finished; |
1555 | } | 1650 | } |
1556 | 1651 | ||
1557 | if (vport->port_state != LPFC_VPORT_READY) | 1652 | if (vport->port_state != LPFC_VPORT_READY) |
1558 | return 0; | 1653 | goto finished; |
1559 | if (vport->num_disc_nodes || vport->fc_prli_sent) | 1654 | if (vport->num_disc_nodes || vport->fc_prli_sent) |
1560 | return 0; | 1655 | goto finished; |
1561 | if (vport->fc_map_cnt == 0 && time < 2 * HZ) | 1656 | if (vport->fc_map_cnt == 0 && time < 2 * HZ) |
1562 | return 0; | 1657 | goto finished; |
1563 | if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0) | 1658 | if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0) |
1564 | return 0; | 1659 | goto finished; |
1660 | |||
1661 | stat = 1; | ||
1565 | 1662 | ||
1566 | finished: | 1663 | finished: |
1567 | lpfc_host_attrib_init(shost); | 1664 | spin_unlock_irq(shost->host_lock); |
1568 | return 1; | 1665 | return stat; |
1569 | } | 1666 | } |
1570 | 1667 | ||
1571 | void lpfc_host_attrib_init(struct Scsi_Host *shost) | 1668 | void lpfc_host_attrib_init(struct Scsi_Host *shost) |
@@ -1656,7 +1753,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1656 | /* Initialize timers used by driver */ | 1753 | /* Initialize timers used by driver */ |
1657 | init_timer(&phba->fc_estabtmo); | 1754 | init_timer(&phba->fc_estabtmo); |
1658 | phba->fc_estabtmo.function = lpfc_establish_link_tmo; | 1755 | phba->fc_estabtmo.function = lpfc_establish_link_tmo; |
1659 | phba->fc_estabtmo.data = (unsigned long) phba; | 1756 | phba->fc_estabtmo.data = (unsigned long)phba; |
1757 | |||
1758 | init_timer(&phba->hb_tmofunc); | ||
1759 | phba->hb_tmofunc.function = lpfc_hb_timeout; | ||
1760 | phba->hb_tmofunc.data = (unsigned long)phba; | ||
1761 | |||
1660 | psli = &phba->sli; | 1762 | psli = &phba->sli; |
1661 | init_timer(&psli->mbox_tmo); | 1763 | init_timer(&psli->mbox_tmo); |
1662 | psli->mbox_tmo.function = lpfc_mbox_timeout; | 1764 | psli->mbox_tmo.function = lpfc_mbox_timeout; |
@@ -1791,6 +1893,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1791 | 1893 | ||
1792 | shost = lpfc_shost_from_vport(vport); | 1894 | shost = lpfc_shost_from_vport(vport); |
1793 | phba->pport = vport; | 1895 | phba->pport = vport; |
1896 | lpfc_debugfs_initialize(vport); | ||
1794 | 1897 | ||
1795 | pci_set_drvdata(pdev, shost); | 1898 | pci_set_drvdata(pdev, shost); |
1796 | 1899 | ||
@@ -1820,15 +1923,32 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1820 | if (lpfc_alloc_sysfs_attr(vport)) | 1923 | if (lpfc_alloc_sysfs_attr(vport)) |
1821 | goto out_free_irq; | 1924 | goto out_free_irq; |
1822 | 1925 | ||
1823 | scsi_scan_host(shost); | 1926 | if (lpfc_sli_hba_setup(phba)) |
1927 | goto out_remove_device; | ||
1928 | |||
1929 | /* | ||
1930 | * hba setup may have changed the hba_queue_depth so we need to adjust | ||
1931 | * the value of can_queue. | ||
1932 | */ | ||
1933 | shost->can_queue = phba->cfg_hba_queue_depth - 10; | ||
1934 | |||
1935 | lpfc_host_attrib_init(shost); | ||
1936 | |||
1824 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) { | 1937 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) { |
1825 | spin_lock_irq(shost->host_lock); | 1938 | spin_lock_irq(shost->host_lock); |
1826 | lpfc_poll_start_timer(phba); | 1939 | lpfc_poll_start_timer(phba); |
1827 | spin_unlock_irq(shost->host_lock); | 1940 | spin_unlock_irq(shost->host_lock); |
1828 | } | 1941 | } |
1829 | 1942 | ||
1943 | scsi_scan_host(shost); | ||
1944 | |||
1830 | return 0; | 1945 | return 0; |
1831 | 1946 | ||
1947 | out_remove_device: | ||
1948 | lpfc_free_sysfs_attr(vport); | ||
1949 | spin_lock_irq(shost->host_lock); | ||
1950 | vport->fc_flag |= FC_UNLOADING; | ||
1951 | spin_unlock_irq(shost->host_lock); | ||
1832 | out_free_irq: | 1952 | out_free_irq: |
1833 | lpfc_stop_phba_timers(phba); | 1953 | lpfc_stop_phba_timers(phba); |
1834 | phba->pport->work_port_events = 0; | 1954 | phba->pport->work_port_events = 0; |
@@ -1865,6 +1985,8 @@ out_disable_device: | |||
1865 | pci_disable_device(pdev); | 1985 | pci_disable_device(pdev); |
1866 | out: | 1986 | out: |
1867 | pci_set_drvdata(pdev, NULL); | 1987 | pci_set_drvdata(pdev, NULL); |
1988 | if (shost) | ||
1989 | scsi_host_put(shost); | ||
1868 | return error; | 1990 | return error; |
1869 | } | 1991 | } |
1870 | 1992 | ||
@@ -1878,6 +2000,12 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
1878 | list_for_each_entry(port_iterator, &phba->port_list, listentry) | 2000 | list_for_each_entry(port_iterator, &phba->port_list, listentry) |
1879 | port_iterator->load_flag |= FC_UNLOADING; | 2001 | port_iterator->load_flag |= FC_UNLOADING; |
1880 | 2002 | ||
2003 | kfree(vport->vname); | ||
2004 | lpfc_free_sysfs_attr(vport); | ||
2005 | |||
2006 | fc_remove_host(shost); | ||
2007 | scsi_remove_host(shost); | ||
2008 | |||
1881 | /* | 2009 | /* |
1882 | * Bring down the SLI Layer. This step disable all interrupts, | 2010 | * Bring down the SLI Layer. This step disable all interrupts, |
1883 | * clears the rings, discards all mailbox commands, and resets | 2011 | * clears the rings, discards all mailbox commands, and resets |
@@ -1887,6 +2015,13 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
1887 | lpfc_sli_brdrestart(phba); | 2015 | lpfc_sli_brdrestart(phba); |
1888 | 2016 | ||
1889 | lpfc_stop_phba_timers(phba); | 2017 | lpfc_stop_phba_timers(phba); |
2018 | spin_lock_irq(&phba->hbalock); | ||
2019 | list_del_init(&vport->listentry); | ||
2020 | spin_unlock_irq(&phba->hbalock); | ||
2021 | |||
2022 | |||
2023 | lpfc_debugfs_terminate(vport); | ||
2024 | lpfc_cleanup(vport); | ||
1890 | 2025 | ||
1891 | kthread_stop(phba->worker_thread); | 2026 | kthread_stop(phba->worker_thread); |
1892 | 2027 | ||
@@ -1894,9 +2029,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
1894 | free_irq(phba->pcidev->irq, phba); | 2029 | free_irq(phba->pcidev->irq, phba); |
1895 | pci_disable_msi(phba->pcidev); | 2030 | pci_disable_msi(phba->pcidev); |
1896 | 2031 | ||
1897 | destroy_port(vport); | ||
1898 | |||
1899 | pci_set_drvdata(pdev, NULL); | 2032 | pci_set_drvdata(pdev, NULL); |
2033 | scsi_host_put(shost); | ||
1900 | 2034 | ||
1901 | /* | 2035 | /* |
1902 | * Call scsi_free before mem_free since scsi bufs are released to their | 2036 | * Call scsi_free before mem_free since scsi bufs are released to their |