diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-01-11 01:52:54 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-23 12:29:22 -0500 |
commit | 0937282036d9ae798e02c9c69a8b2ef044048855 (patch) | |
tree | 55c8ef65c9c55e74e8985b58396516b3d3b925ad /drivers/scsi/lpfc/lpfc_init.c | |
parent | 13815c8344a238c204e4f4339b22dc4833c6df0f (diff) |
[SCSI] lpfc 8.2.4 : Miscellaneous Fixes
Miscellaneous Fixes:
- Fix a couple of sparse complaints
- Reset the FCP recovery flag when the node is not a FCP2 device.
- Speed up offline prep delays
- Fixed a memory leak in lpfc_mem_alloc failure path
- Fixed external loopback test.
- Fixed error code returned from the driver when HBA is over heated.
- Correct Max NPIV vport to limits read from adapter
- Add missing locks around fc_flag and FC_NEEDS_REG_VPI
- Add missing hba ids for device identification
- Added support for SET_VARIABLE and MBX_WRITE_WWN mailbox commands
- Changed all temperature event messages from warning to error
- Fix reporting of link speed when link is down
- Added support for MBX_WRITE_WWN mailbox command
- Change del_timer_sync() in ISR to del_timer() in interrupt handler
- Correct instances of beXX_to_cpu() that should be cpu_to_beXX()
- Perform target flush before releasing node references on module unload
- Avoid bogus devloss_tmo messages when driver unloads
- Fix panic when HBA generates ERATT interupt
- Fix mbox race condition and a workaround on back-to-back mailbox commands
- Force NPIV off for pt2pt mode between 2 NPorts
- Stop worker thread before removing fc_host.
- Fix up discovery timeout error case due to missing clear_la
- Tighten mailbox polling code to speed up detection of fast completions
- Only allow DUMP_MEMORY if adapter offline due to overtemp errors
- Added extended error information to the log messages in chip init.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 119 |
1 files changed, 80 insertions, 39 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c6b30a8617bc..e17bb900aad1 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -484,6 +484,9 @@ lpfc_hba_down_post(struct lpfc_hba *phba) | |||
484 | struct lpfc_sli *psli = &phba->sli; | 484 | struct lpfc_sli *psli = &phba->sli; |
485 | struct lpfc_sli_ring *pring; | 485 | struct lpfc_sli_ring *pring; |
486 | struct lpfc_dmabuf *mp, *next_mp; | 486 | struct lpfc_dmabuf *mp, *next_mp; |
487 | struct lpfc_iocbq *iocb; | ||
488 | IOCB_t *cmd = NULL; | ||
489 | LIST_HEAD(completions); | ||
487 | int i; | 490 | int i; |
488 | 491 | ||
489 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) | 492 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) |
@@ -499,10 +502,36 @@ lpfc_hba_down_post(struct lpfc_hba *phba) | |||
499 | } | 502 | } |
500 | } | 503 | } |
501 | 504 | ||
505 | spin_lock_irq(&phba->hbalock); | ||
502 | for (i = 0; i < psli->num_rings; i++) { | 506 | for (i = 0; i < psli->num_rings; i++) { |
503 | pring = &psli->ring[i]; | 507 | pring = &psli->ring[i]; |
508 | |||
509 | /* At this point in time the HBA is either reset or DOA. Either | ||
510 | * way, nothing should be on txcmplq as it will NEVER complete. | ||
511 | */ | ||
512 | list_splice_init(&pring->txcmplq, &completions); | ||
513 | pring->txcmplq_cnt = 0; | ||
514 | spin_unlock_irq(&phba->hbalock); | ||
515 | |||
516 | while (!list_empty(&completions)) { | ||
517 | iocb = list_get_first(&completions, struct lpfc_iocbq, | ||
518 | list); | ||
519 | cmd = &iocb->iocb; | ||
520 | list_del_init(&iocb->list); | ||
521 | |||
522 | if (!iocb->iocb_cmpl) | ||
523 | lpfc_sli_release_iocbq(phba, iocb); | ||
524 | else { | ||
525 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
526 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
527 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
528 | } | ||
529 | } | ||
530 | |||
504 | lpfc_sli_abort_iocb_ring(phba, pring); | 531 | lpfc_sli_abort_iocb_ring(phba, pring); |
532 | spin_lock_irq(&phba->hbalock); | ||
505 | } | 533 | } |
534 | spin_unlock_irq(&phba->hbalock); | ||
506 | 535 | ||
507 | return 0; | 536 | return 0; |
508 | } | 537 | } |
@@ -641,6 +670,26 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
641 | } | 670 | } |
642 | } | 671 | } |
643 | 672 | ||
673 | static void | ||
674 | lpfc_offline_eratt(struct lpfc_hba *phba) | ||
675 | { | ||
676 | struct lpfc_sli *psli = &phba->sli; | ||
677 | |||
678 | spin_lock_irq(&phba->hbalock); | ||
679 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
680 | spin_unlock_irq(&phba->hbalock); | ||
681 | lpfc_offline_prep(phba); | ||
682 | |||
683 | lpfc_offline(phba); | ||
684 | lpfc_reset_barrier(phba); | ||
685 | lpfc_sli_brdreset(phba); | ||
686 | lpfc_hba_down_post(phba); | ||
687 | lpfc_sli_brdready(phba, HS_MBRDY); | ||
688 | lpfc_unblock_mgmt_io(phba); | ||
689 | phba->link_state = LPFC_HBA_ERROR; | ||
690 | return; | ||
691 | } | ||
692 | |||
644 | /************************************************************************/ | 693 | /************************************************************************/ |
645 | /* */ | 694 | /* */ |
646 | /* lpfc_handle_eratt */ | 695 | /* lpfc_handle_eratt */ |
@@ -681,14 +730,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
681 | vports = lpfc_create_vport_work_array(phba); | 730 | vports = lpfc_create_vport_work_array(phba); |
682 | if (vports != NULL) | 731 | if (vports != NULL) |
683 | for(i = 0; | 732 | for(i = 0; |
684 | i < LPFC_MAX_VPORTS && vports[i] != NULL; | 733 | i <= phba->max_vpi && vports[i] != NULL; |
685 | i++){ | 734 | i++){ |
686 | shost = lpfc_shost_from_vport(vports[i]); | 735 | shost = lpfc_shost_from_vport(vports[i]); |
687 | spin_lock_irq(shost->host_lock); | 736 | spin_lock_irq(shost->host_lock); |
688 | vports[i]->fc_flag |= FC_ESTABLISH_LINK; | 737 | vports[i]->fc_flag |= FC_ESTABLISH_LINK; |
689 | spin_unlock_irq(shost->host_lock); | 738 | spin_unlock_irq(shost->host_lock); |
690 | } | 739 | } |
691 | lpfc_destroy_vport_work_array(vports); | 740 | lpfc_destroy_vport_work_array(phba, vports); |
692 | spin_lock_irq(&phba->hbalock); | 741 | spin_lock_irq(&phba->hbalock); |
693 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | 742 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; |
694 | spin_unlock_irq(&phba->hbalock); | 743 | spin_unlock_irq(&phba->hbalock); |
@@ -737,14 +786,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
737 | | PCI_VENDOR_ID_EMULEX); | 786 | | PCI_VENDOR_ID_EMULEX); |
738 | 787 | ||
739 | spin_lock_irq(&phba->hbalock); | 788 | spin_lock_irq(&phba->hbalock); |
740 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
741 | phba->over_temp_state = HBA_OVER_TEMP; | 789 | phba->over_temp_state = HBA_OVER_TEMP; |
742 | spin_unlock_irq(&phba->hbalock); | 790 | spin_unlock_irq(&phba->hbalock); |
743 | lpfc_offline_prep(phba); | 791 | lpfc_offline_eratt(phba); |
744 | lpfc_offline(phba); | ||
745 | lpfc_unblock_mgmt_io(phba); | ||
746 | phba->link_state = LPFC_HBA_ERROR; | ||
747 | lpfc_hba_down_post(phba); | ||
748 | 792 | ||
749 | } else { | 793 | } else { |
750 | /* The if clause above forces this code path when the status | 794 | /* The if clause above forces this code path when the status |
@@ -763,14 +807,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
763 | sizeof(event_data), (char *) &event_data, | 807 | sizeof(event_data), (char *) &event_data, |
764 | SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); | 808 | SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); |
765 | 809 | ||
766 | spin_lock_irq(&phba->hbalock); | 810 | lpfc_offline_eratt(phba); |
767 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
768 | spin_unlock_irq(&phba->hbalock); | ||
769 | lpfc_offline_prep(phba); | ||
770 | lpfc_offline(phba); | ||
771 | lpfc_unblock_mgmt_io(phba); | ||
772 | phba->link_state = LPFC_HBA_ERROR; | ||
773 | lpfc_hba_down_post(phba); | ||
774 | } | 811 | } |
775 | } | 812 | } |
776 | 813 | ||
@@ -790,21 +827,25 @@ lpfc_handle_latt(struct lpfc_hba *phba) | |||
790 | LPFC_MBOXQ_t *pmb; | 827 | LPFC_MBOXQ_t *pmb; |
791 | volatile uint32_t control; | 828 | volatile uint32_t control; |
792 | struct lpfc_dmabuf *mp; | 829 | struct lpfc_dmabuf *mp; |
793 | int rc = -ENOMEM; | 830 | int rc = 0; |
794 | 831 | ||
795 | pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 832 | pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
796 | if (!pmb) | 833 | if (!pmb) { |
834 | rc = 1; | ||
797 | goto lpfc_handle_latt_err_exit; | 835 | goto lpfc_handle_latt_err_exit; |
836 | } | ||
798 | 837 | ||
799 | mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 838 | mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
800 | if (!mp) | 839 | if (!mp) { |
840 | rc = 2; | ||
801 | goto lpfc_handle_latt_free_pmb; | 841 | goto lpfc_handle_latt_free_pmb; |
842 | } | ||
802 | 843 | ||
803 | mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); | 844 | mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); |
804 | if (!mp->virt) | 845 | if (!mp->virt) { |
846 | rc = 3; | ||
805 | goto lpfc_handle_latt_free_mp; | 847 | goto lpfc_handle_latt_free_mp; |
806 | 848 | } | |
807 | rc = -EIO; | ||
808 | 849 | ||
809 | /* Cleanup any outstanding ELS commands */ | 850 | /* Cleanup any outstanding ELS commands */ |
810 | lpfc_els_flush_all_cmd(phba); | 851 | lpfc_els_flush_all_cmd(phba); |
@@ -814,8 +855,10 @@ lpfc_handle_latt(struct lpfc_hba *phba) | |||
814 | pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; | 855 | pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; |
815 | pmb->vport = vport; | 856 | pmb->vport = vport; |
816 | rc = lpfc_sli_issue_mbox (phba, pmb, MBX_NOWAIT); | 857 | rc = lpfc_sli_issue_mbox (phba, pmb, MBX_NOWAIT); |
817 | if (rc == MBX_NOT_FINISHED) | 858 | if (rc == MBX_NOT_FINISHED) { |
859 | rc = 4; | ||
818 | goto lpfc_handle_latt_free_mbuf; | 860 | goto lpfc_handle_latt_free_mbuf; |
861 | } | ||
819 | 862 | ||
820 | /* Clear Link Attention in HA REG */ | 863 | /* Clear Link Attention in HA REG */ |
821 | spin_lock_irq(&phba->hbalock); | 864 | spin_lock_irq(&phba->hbalock); |
@@ -847,10 +890,8 @@ lpfc_handle_latt_err_exit: | |||
847 | lpfc_linkdown(phba); | 890 | lpfc_linkdown(phba); |
848 | phba->link_state = LPFC_HBA_ERROR; | 891 | phba->link_state = LPFC_HBA_ERROR; |
849 | 892 | ||
850 | /* The other case is an error from issue_mbox */ | 893 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, |
851 | if (rc == -ENOMEM) | 894 | "0300 LATT: Cannot issue READ_LA: Data:%d\n", rc); |
852 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, | ||
853 | "0300 READ_LA: no buffers\n"); | ||
854 | 895 | ||
855 | return; | 896 | return; |
856 | } | 897 | } |
@@ -1421,14 +1462,14 @@ lpfc_establish_link_tmo(unsigned long ptr) | |||
1421 | phba->pport->fc_flag, phba->pport->port_state); | 1462 | phba->pport->fc_flag, phba->pport->port_state); |
1422 | vports = lpfc_create_vport_work_array(phba); | 1463 | vports = lpfc_create_vport_work_array(phba); |
1423 | if (vports != NULL) | 1464 | if (vports != NULL) |
1424 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 1465 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { |
1425 | struct Scsi_Host *shost; | 1466 | struct Scsi_Host *shost; |
1426 | shost = lpfc_shost_from_vport(vports[i]); | 1467 | shost = lpfc_shost_from_vport(vports[i]); |
1427 | spin_lock_irqsave(shost->host_lock, iflag); | 1468 | spin_lock_irqsave(shost->host_lock, iflag); |
1428 | vports[i]->fc_flag &= ~FC_ESTABLISH_LINK; | 1469 | vports[i]->fc_flag &= ~FC_ESTABLISH_LINK; |
1429 | spin_unlock_irqrestore(shost->host_lock, iflag); | 1470 | spin_unlock_irqrestore(shost->host_lock, iflag); |
1430 | } | 1471 | } |
1431 | lpfc_destroy_vport_work_array(vports); | 1472 | lpfc_destroy_vport_work_array(phba, vports); |
1432 | } | 1473 | } |
1433 | 1474 | ||
1434 | void | 1475 | void |
@@ -1493,7 +1534,7 @@ lpfc_online(struct lpfc_hba *phba) | |||
1493 | 1534 | ||
1494 | vports = lpfc_create_vport_work_array(phba); | 1535 | vports = lpfc_create_vport_work_array(phba); |
1495 | if (vports != NULL) | 1536 | if (vports != NULL) |
1496 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 1537 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { |
1497 | struct Scsi_Host *shost; | 1538 | struct Scsi_Host *shost; |
1498 | shost = lpfc_shost_from_vport(vports[i]); | 1539 | shost = lpfc_shost_from_vport(vports[i]); |
1499 | spin_lock_irq(shost->host_lock); | 1540 | spin_lock_irq(shost->host_lock); |
@@ -1502,7 +1543,7 @@ lpfc_online(struct lpfc_hba *phba) | |||
1502 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 1543 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
1503 | spin_unlock_irq(shost->host_lock); | 1544 | spin_unlock_irq(shost->host_lock); |
1504 | } | 1545 | } |
1505 | lpfc_destroy_vport_work_array(vports); | 1546 | lpfc_destroy_vport_work_array(phba, vports); |
1506 | 1547 | ||
1507 | lpfc_unblock_mgmt_io(phba); | 1548 | lpfc_unblock_mgmt_io(phba); |
1508 | return 0; | 1549 | return 0; |
@@ -1536,7 +1577,7 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
1536 | /* Issue an unreg_login to all nodes on all vports */ | 1577 | /* Issue an unreg_login to all nodes on all vports */ |
1537 | vports = lpfc_create_vport_work_array(phba); | 1578 | vports = lpfc_create_vport_work_array(phba); |
1538 | if (vports != NULL) { | 1579 | if (vports != NULL) { |
1539 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 1580 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { |
1540 | struct Scsi_Host *shost; | 1581 | struct Scsi_Host *shost; |
1541 | 1582 | ||
1542 | if (vports[i]->load_flag & FC_UNLOADING) | 1583 | if (vports[i]->load_flag & FC_UNLOADING) |
@@ -1560,7 +1601,7 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
1560 | } | 1601 | } |
1561 | } | 1602 | } |
1562 | } | 1603 | } |
1563 | lpfc_destroy_vport_work_array(vports); | 1604 | lpfc_destroy_vport_work_array(phba, vports); |
1564 | 1605 | ||
1565 | lpfc_sli_flush_mbox_queue(phba); | 1606 | lpfc_sli_flush_mbox_queue(phba); |
1566 | } | 1607 | } |
@@ -1579,9 +1620,9 @@ lpfc_offline(struct lpfc_hba *phba) | |||
1579 | lpfc_stop_phba_timers(phba); | 1620 | lpfc_stop_phba_timers(phba); |
1580 | vports = lpfc_create_vport_work_array(phba); | 1621 | vports = lpfc_create_vport_work_array(phba); |
1581 | if (vports != NULL) | 1622 | if (vports != NULL) |
1582 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) | 1623 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) |
1583 | lpfc_stop_vport_timers(vports[i]); | 1624 | lpfc_stop_vport_timers(vports[i]); |
1584 | lpfc_destroy_vport_work_array(vports); | 1625 | lpfc_destroy_vport_work_array(phba, vports); |
1585 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | 1626 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, |
1586 | "0460 Bring Adapter offline\n"); | 1627 | "0460 Bring Adapter offline\n"); |
1587 | /* Bring down the SLI Layer and cleanup. The HBA is offline | 1628 | /* Bring down the SLI Layer and cleanup. The HBA is offline |
@@ -1592,14 +1633,14 @@ lpfc_offline(struct lpfc_hba *phba) | |||
1592 | spin_unlock_irq(&phba->hbalock); | 1633 | spin_unlock_irq(&phba->hbalock); |
1593 | vports = lpfc_create_vport_work_array(phba); | 1634 | vports = lpfc_create_vport_work_array(phba); |
1594 | if (vports != NULL) | 1635 | if (vports != NULL) |
1595 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 1636 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { |
1596 | shost = lpfc_shost_from_vport(vports[i]); | 1637 | shost = lpfc_shost_from_vport(vports[i]); |
1597 | spin_lock_irq(shost->host_lock); | 1638 | spin_lock_irq(shost->host_lock); |
1598 | vports[i]->work_port_events = 0; | 1639 | vports[i]->work_port_events = 0; |
1599 | vports[i]->fc_flag |= FC_OFFLINE_MODE; | 1640 | vports[i]->fc_flag |= FC_OFFLINE_MODE; |
1600 | spin_unlock_irq(shost->host_lock); | 1641 | spin_unlock_irq(shost->host_lock); |
1601 | } | 1642 | } |
1602 | lpfc_destroy_vport_work_array(vports); | 1643 | lpfc_destroy_vport_work_array(phba, vports); |
1603 | } | 1644 | } |
1604 | 1645 | ||
1605 | /****************************************************************************** | 1646 | /****************************************************************************** |
@@ -2149,6 +2190,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2149 | kfree(vport->vname); | 2190 | kfree(vport->vname); |
2150 | lpfc_free_sysfs_attr(vport); | 2191 | lpfc_free_sysfs_attr(vport); |
2151 | 2192 | ||
2193 | kthread_stop(phba->worker_thread); | ||
2194 | |||
2152 | fc_remove_host(shost); | 2195 | fc_remove_host(shost); |
2153 | scsi_remove_host(shost); | 2196 | scsi_remove_host(shost); |
2154 | lpfc_cleanup(vport); | 2197 | lpfc_cleanup(vport); |
@@ -2168,8 +2211,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2168 | 2211 | ||
2169 | lpfc_debugfs_terminate(vport); | 2212 | lpfc_debugfs_terminate(vport); |
2170 | 2213 | ||
2171 | kthread_stop(phba->worker_thread); | ||
2172 | |||
2173 | /* Release the irq reservation */ | 2214 | /* Release the irq reservation */ |
2174 | free_irq(phba->pcidev->irq, phba); | 2215 | free_irq(phba->pcidev->irq, phba); |
2175 | if (phba->using_msi) | 2216 | if (phba->using_msi) |