diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-08-02 11:09:51 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-08-01 13:18:23 -0400 |
commit | 549e55cd2a1b83ea45ac17fb6c309654a3d371a4 (patch) | |
tree | 0abf10a28b177e129932c62b3b94994ce4f3aadb /drivers/scsi/lpfc/lpfc_els.c | |
parent | a58cbd5212fff2d4bba0bf58e778f02069597294 (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_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 61 |
1 files changed, 52 insertions, 9 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 68fc975d4e52..b8e048a467d2 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -2800,7 +2800,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2800 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2800 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2801 | struct lpfc_hba *phba = vport->phba; | 2801 | struct lpfc_hba *phba = vport->phba; |
2802 | struct lpfc_dmabuf *pcmd; | 2802 | struct lpfc_dmabuf *pcmd; |
2803 | struct lpfc_vport *next_vport; | ||
2804 | uint32_t *lp, *datap; | 2803 | uint32_t *lp, *datap; |
2805 | IOCB_t *icmd; | 2804 | IOCB_t *icmd; |
2806 | uint32_t payload_len, length, nportid, *cmd; | 2805 | uint32_t payload_len, length, nportid, *cmd; |
@@ -2850,13 +2849,8 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2850 | nportid = ((be32_to_cpu(nportid)) & Mask_DID); | 2849 | nportid = ((be32_to_cpu(nportid)) & Mask_DID); |
2851 | i -= sizeof(uint32_t); | 2850 | i -= sizeof(uint32_t); |
2852 | rscn_id++; | 2851 | rscn_id++; |
2853 | list_for_each_entry(next_vport, &phba->port_list, | 2852 | if (lpfc_find_vport_by_did(phba, nportid)) |
2854 | listentry) { | 2853 | hba_id++; |
2855 | if (nportid == next_vport->fc_myDID) { | ||
2856 | hba_id++; | ||
2857 | break; | ||
2858 | } | ||
2859 | } | ||
2860 | } | 2854 | } |
2861 | if (rscn_id == hba_id) { | 2855 | if (rscn_id == hba_id) { |
2862 | /* ALL NPortIDs in RSCN are on HBA */ | 2856 | /* ALL NPortIDs in RSCN are on HBA */ |
@@ -3740,6 +3734,50 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) | |||
3740 | return; | 3734 | return; |
3741 | } | 3735 | } |
3742 | 3736 | ||
3737 | void | ||
3738 | lpfc_els_flush_all_cmd(struct lpfc_hba *phba) | ||
3739 | { | ||
3740 | LIST_HEAD(completions); | ||
3741 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | ||
3742 | struct lpfc_iocbq *tmp_iocb, *piocb; | ||
3743 | IOCB_t *cmd = NULL; | ||
3744 | |||
3745 | lpfc_fabric_abort_hba(phba); | ||
3746 | spin_lock_irq(&phba->hbalock); | ||
3747 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { | ||
3748 | cmd = &piocb->iocb; | ||
3749 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) | ||
3750 | continue; | ||
3751 | /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ | ||
3752 | if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN || | ||
3753 | cmd->ulpCommand == CMD_QUE_RING_BUF64_CN || | ||
3754 | cmd->ulpCommand == CMD_CLOSE_XRI_CN || | ||
3755 | cmd->ulpCommand == CMD_ABORT_XRI_CN) | ||
3756 | continue; | ||
3757 | list_move_tail(&piocb->list, &completions); | ||
3758 | pring->txq_cnt--; | ||
3759 | } | ||
3760 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | ||
3761 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) | ||
3762 | continue; | ||
3763 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); | ||
3764 | } | ||
3765 | spin_unlock_irq(&phba->hbalock); | ||
3766 | while (!list_empty(&completions)) { | ||
3767 | piocb = list_get_first(&completions, struct lpfc_iocbq, list); | ||
3768 | cmd = &piocb->iocb; | ||
3769 | list_del_init(&piocb->list); | ||
3770 | if (!piocb->iocb_cmpl) | ||
3771 | lpfc_sli_release_iocbq(phba, piocb); | ||
3772 | else { | ||
3773 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
3774 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
3775 | (piocb->iocb_cmpl) (phba, piocb, piocb); | ||
3776 | } | ||
3777 | } | ||
3778 | return; | ||
3779 | } | ||
3780 | |||
3743 | static void | 3781 | static void |
3744 | lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 3782 | lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
3745 | struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb) | 3783 | struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb) |
@@ -4009,11 +4047,16 @@ static struct lpfc_vport * | |||
4009 | lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) | 4047 | lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) |
4010 | { | 4048 | { |
4011 | struct lpfc_vport *vport; | 4049 | struct lpfc_vport *vport; |
4050 | unsigned long flags; | ||
4012 | 4051 | ||
4052 | spin_lock_irqsave(&phba->hbalock, flags); | ||
4013 | list_for_each_entry(vport, &phba->port_list, listentry) { | 4053 | list_for_each_entry(vport, &phba->port_list, listentry) { |
4014 | if (vport->vpi == vpi) | 4054 | if (vport->vpi == vpi) { |
4055 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
4015 | return vport; | 4056 | return vport; |
4057 | } | ||
4016 | } | 4058 | } |
4059 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
4017 | return NULL; | 4060 | return NULL; |
4018 | } | 4061 | } |
4019 | 4062 | ||