aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_els.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_els.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_els.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c61
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
3737void
3738lpfc_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
3743static void 3781static void
3744lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 3782lpfc_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 *
4009lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) 4047lpfc_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