Skip to content

Commit

Permalink
[SCSI] lpfc 8.2.2 : Fix locking around HBA's port_list
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
James Smart authored and James Bottomley committed Aug 1, 2007
1 parent a58cbd5 commit 549e55c
Show file tree
Hide file tree
Showing 10 changed files with 308 additions and 223 deletions.
9 changes: 5 additions & 4 deletions drivers/scsi/lpfc/lpfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,10 +528,11 @@ struct lpfc_hba {
struct fc_host_statistics link_stats;

struct list_head port_list;
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
uint16_t max_vpi; /* Maximum virtual nports */
#define LPFC_MAX_VPI 100 /* Max number of VPorts supported */
unsigned long *vpi_bmask; /* vpi allocation table */
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
uint16_t max_vpi; /* Maximum virtual nports */
#define LPFC_MAX_VPI 100 /* Max number of VPI supported */
#define LPFC_MAX_VPORTS (LPFC_MAX_VPI+1)/* Max number of VPorts supported */
unsigned long *vpi_bmask; /* vpi allocation table */

/* Data structure used by fabric iocb scheduler */
struct list_head fabric_iocb_list;
Expand Down
21 changes: 13 additions & 8 deletions drivers/scsi/lpfc/lpfc_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1060,19 +1060,24 @@ lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val)
static void
lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
{
struct lpfc_vport *vport;
struct lpfc_vport **vports;
struct Scsi_Host *shost;
struct lpfc_nodelist *ndlp;
int i;

list_for_each_entry(vport, &phba->port_list, listentry) {
shost = lpfc_shost_from_vport(vport);
spin_lock_irq(shost->host_lock);
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irq(shost->host_lock);
list_for_each_entry(ndlp, &vports[i]->fc_nodes,
nlp_listp)
if (ndlp->rport)
ndlp->rport->dev_loss_tmo =
phba->cfg_devloss_tmo;
spin_unlock_irq(shost->host_lock);
}
phba->cfg_devloss_tmo;
spin_unlock_irq(shost->host_lock);
}
lpfc_destroy_vport_work_array(vports);
}

static int
Expand Down
2 changes: 2 additions & 0 deletions drivers/scsi/lpfc/lpfc_crtn.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ void lpfc_reg_vpi(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);

struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove);
int lpfc_linkdown(struct lpfc_hba *);
void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
Expand Down Expand Up @@ -117,6 +118,7 @@ void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
int lpfc_els_handle_rscn(struct lpfc_vport *);
void lpfc_els_flush_rscn(struct lpfc_vport *);
int lpfc_rscn_payload_check(struct lpfc_vport *, uint32_t);
void lpfc_els_flush_all_cmd(struct lpfc_hba *);
void lpfc_els_flush_cmd(struct lpfc_vport *);
int lpfc_els_disc_adisc(struct lpfc_vport *);
int lpfc_els_disc_plogi(struct lpfc_vport *);
Expand Down
12 changes: 7 additions & 5 deletions drivers/scsi/lpfc/lpfc_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,17 +390,19 @@ lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
return 0;
}

static struct lpfc_vport *
struct lpfc_vport *
lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) {

struct lpfc_vport *vport_curr;
unsigned long flags;

spin_lock_irqsave(&phba->hbalock, flags);
list_for_each_entry(vport_curr, &phba->port_list, listentry) {
if ((vport_curr->fc_myDID) &&
(vport_curr->fc_myDID == did))
if ((vport_curr->fc_myDID) && (vport_curr->fc_myDID == did)) {
spin_unlock_irqrestore(&phba->hbalock, flags);
return vport_curr;
}
}

spin_unlock_irqrestore(&phba->hbalock, flags);
return NULL;
}

Expand Down
61 changes: 52 additions & 9 deletions drivers/scsi/lpfc/lpfc_els.c
Original file line number Diff line number Diff line change
Expand Up @@ -2800,7 +2800,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_dmabuf *pcmd;
struct lpfc_vport *next_vport;
uint32_t *lp, *datap;
IOCB_t *icmd;
uint32_t payload_len, length, nportid, *cmd;
Expand Down Expand Up @@ -2850,13 +2849,8 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
nportid = ((be32_to_cpu(nportid)) & Mask_DID);
i -= sizeof(uint32_t);
rscn_id++;
list_for_each_entry(next_vport, &phba->port_list,
listentry) {
if (nportid == next_vport->fc_myDID) {
hba_id++;
break;
}
}
if (lpfc_find_vport_by_did(phba, nportid))
hba_id++;
}
if (rscn_id == hba_id) {
/* ALL NPortIDs in RSCN are on HBA */
Expand Down Expand Up @@ -3740,6 +3734,50 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
return;
}

void
lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
{
LIST_HEAD(completions);
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
struct lpfc_iocbq *tmp_iocb, *piocb;
IOCB_t *cmd = NULL;

lpfc_fabric_abort_hba(phba);
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
cmd = &piocb->iocb;
if (piocb->iocb_flag & LPFC_IO_LIBDFC)
continue;
/* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
cmd->ulpCommand == CMD_ABORT_XRI_CN)
continue;
list_move_tail(&piocb->list, &completions);
pring->txq_cnt--;
}
list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
if (piocb->iocb_flag & LPFC_IO_LIBDFC)
continue;
lpfc_sli_issue_abort_iotag(phba, pring, piocb);
}
spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) {
piocb = list_get_first(&completions, struct lpfc_iocbq, list);
cmd = &piocb->iocb;
list_del_init(&piocb->list);
if (!piocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, piocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(piocb->iocb_cmpl) (phba, piocb, piocb);
}
}
return;
}

static void
lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
Expand Down Expand Up @@ -4009,11 +4047,16 @@ static struct lpfc_vport *
lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
{
struct lpfc_vport *vport;
unsigned long flags;

spin_lock_irqsave(&phba->hbalock, flags);
list_for_each_entry(vport, &phba->port_list, listentry) {
if (vport->vpi == vpi)
if (vport->vpi == vpi) {
spin_unlock_irqrestore(&phba->hbalock, flags);
return vport;
}
}
spin_unlock_irqrestore(&phba->hbalock, flags);
return NULL;
}

Expand Down
Loading

0 comments on commit 549e55c

Please sign in to comment.