From 58da1ffb2b1234e9c6c75013a649c659cc38ebd4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 7 Apr 2008 10:15:56 -0400 Subject: [SCSI] lpfc 8.2.6 : Multiple discovery fixes Multiple Discovery Fixes: - Fix race on discovery due to link events coinciding with vport_delete. - Use NLP_FABRIC state to filter out switch-based pseudo initiators that reuse the same WWNs. - Correct erroneous setting of DID=0 in lpfc_matchdid() - Correct extra reference count that was in the lookup path for the remoteid from an unsolicited ELS. - Correct double-free bug in els abort path. - Correct FDMI server discovery logic for switch that return a WWN of 0. - Fix bugs in ndlp mgmt when a node changes address - Correct bug that did not delete RSCNs for vports upon link transitions - Fix "0216 Link event during NS query" error which pops up when vports are swapped to different switch ports. - Add sanity checks on ndlp structures - Fix devloss log message to dump WWN correctly - Hold off mgmt commands that were interferring with discovery mailbox cmds - Remove unnecessary FC_ESTABLISH_LINK logic. - Correct some race conditions in the worker thread, resulting in devloss: - Clear the work_port_events field before handling the work port events - Clear the deferred ring event before handling a deferred ring event - Hold the hba lock when waking up the work thread - Send an acc for the rscn even when we aren't going to handle it - Fix locking behavior that was not properly protecting the ACTIVE flag, thus allowing mailbox command order to shift. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hbadisc.c | 41 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c') diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 976653440fba..7c8c3e6f399d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -69,7 +69,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport) rdata = rport->dd_data; ndlp = rdata->pnode; - if (!ndlp) { + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) printk(KERN_ERR "Cannot find remote node" " to terminate I/O Data x%x\n", @@ -114,7 +114,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) rdata = rport->dd_data; ndlp = rdata->pnode; - if (!ndlp) + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) return; vport = ndlp->vport; @@ -243,8 +243,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) if (warn_on) { lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, "0203 Devloss timeout on " - "WWPN %x:%x:%x:%x:%x:%x:%x:%x " - "NPort x%x Data: x%x x%x x%x\n", + "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " + "NPort x%06x Data: x%x x%x x%x\n", *name, *(name+1), *(name+2), *(name+3), *(name+4), *(name+5), *(name+6), *(name+7), ndlp->nlp_DID, ndlp->nlp_flag, @@ -252,8 +252,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) } else { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0204 Devloss timeout on " - "WWPN %x:%x:%x:%x:%x:%x:%x:%x " - "NPort x%x Data: x%x x%x x%x\n", + "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " + "NPort x%06x Data: x%x x%x x%x\n", *name, *(name+1), *(name+2), *(name+3), *(name+4), *(name+5), *(name+6), *(name+7), ndlp->nlp_DID, ndlp->nlp_flag, @@ -399,7 +399,10 @@ lpfc_work_done(struct lpfc_hba *phba) vport = vports[i]; if (vport == NULL) break; + spin_lock_irq(&vport->work_port_lock); work_port_events = vport->work_port_events; + vport->work_port_events &= ~work_port_events; + spin_unlock_irq(&vport->work_port_lock); if (work_port_events & WORKER_DISC_TMO) lpfc_disc_timeout_handler(vport); if (work_port_events & WORKER_ELS_TMO) @@ -416,9 +419,6 @@ lpfc_work_done(struct lpfc_hba *phba) lpfc_ramp_down_queue_handler(phba); if (work_port_events & WORKER_RAMP_UP_QUEUE) lpfc_ramp_up_queue_handler(phba); - spin_lock_irq(&vport->work_port_lock); - vport->work_port_events &= ~work_port_events; - spin_unlock_irq(&vport->work_port_lock); } lpfc_destroy_vport_work_array(phba, vports); @@ -430,10 +430,10 @@ lpfc_work_done(struct lpfc_hba *phba) if (pring->flag & LPFC_STOP_IOCB_EVENT) { pring->flag |= LPFC_DEFERRED_RING_EVENT; } else { + pring->flag &= ~LPFC_DEFERRED_RING_EVENT; lpfc_sli_handle_slow_ring_event(phba, pring, (status & HA_RXMASK)); - pring->flag &= ~LPFC_DEFERRED_RING_EVENT; } /* * Turn on Ring interrupts @@ -519,7 +519,9 @@ lpfc_do_work(void *p) schedule(); } } + spin_lock_irq(&phba->hbalock); phba->work_wait = NULL; + spin_unlock_irq(&phba->hbalock); return 0; } @@ -809,11 +811,9 @@ out: mempool_free(pmb, phba->mbox_mem_pool); spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK); + vport->fc_flag &= ~FC_ABORT_DISCOVERY; spin_unlock_irq(shost->host_lock); - del_timer_sync(&phba->fc_estabtmo); - lpfc_can_disctmo(vport); /* turn on Link Attention interrupts */ @@ -1340,10 +1340,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) i++) { if (vports[i]->port_type == LPFC_PHYSICAL_PORT) continue; + if (phba->fc_topology == TOPOLOGY_LOOP) { + lpfc_vport_set_state(vports[i], + FC_VPORT_LINKDOWN); + continue; + } if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) lpfc_initial_fdisc(vports[i]); - else if (phba->sli3_options & - LPFC_SLI3_NPIV_ENABLED) { + else { lpfc_vport_set_state(vports[i], FC_VPORT_NO_FABRIC_SUPP); lpfc_printf_vlog(vport, KERN_ERR, @@ -2190,10 +2194,6 @@ lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (did == Bcast_DID) return 0; - if (ndlp->nlp_DID == 0) { - return 0; - } - /* First check for Direct match */ if (ndlp->nlp_DID == did) return 1; @@ -2301,7 +2301,8 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) return ndlp; } - if (vport->fc_flag & FC_RSCN_MODE) { + if ((vport->fc_flag & FC_RSCN_MODE) && + !(vport->fc_flag & FC_NDISC_ACTIVE)) { if (lpfc_rscn_payload_check(vport, did)) { /* If we've already recieved a PLOGI from this NPort * we don't need to try to discover it again. -- cgit v1.2.2 From 97eab63490452f0a5242fa94ddaa9b727d69cb25 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 7 Apr 2008 10:16:05 -0400 Subject: [SCSI] lpfc 8.2.6 : Miscellaneous Fixes Miscellaneous Fixes - Allow WRITE_VPARAM command when the virtual port is in a stopped state - Fixed handling of our queue depth max that was unconditionally raising the depth on all vports, rather than just the vport affected. - Fix race in interrupt handler for mailbox processing that did not take out the host lock. - Removed unused functions: find_node, findnode_rpi, and fabric_abort_flogi - Correct misspelled word unsolicited in message 0146 - Correct HW-error 5 handling - it should not reset the adapter - Correct handling of IOCBs, which did not null out our pCmd field before invoking the midlayer io done function. - Changed our maximum supported target id to 4096 Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hbadisc.c | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c') diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7c8c3e6f399d..7cb68feb04fd 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -2948,24 +2948,6 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param) return NULL; } -#if 0 -/* - * Search node lists for a remote port matching filter criteria - * Caller needs to hold host_lock before calling this routine. - */ -struct lpfc_nodelist * -lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param) -{ - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_nodelist *ndlp; - - spin_lock_irq(shost->host_lock); - ndlp = __lpfc_find_node(vport, filter, param); - spin_unlock_irq(shost->host_lock); - return ndlp; -} -#endif /* 0 */ - /* * This routine looks up the ndlp lists for the given RPI. If rpi found it * returns the node list element pointer else return NULL. @@ -2976,20 +2958,6 @@ __lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi) return __lpfc_find_node(vport, lpfc_filter_by_rpi, &rpi); } -#if 0 -struct lpfc_nodelist * -lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi) -{ - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_nodelist *ndlp; - - spin_lock_irq(shost->host_lock); - ndlp = __lpfc_findnode_rpi(vport, rpi); - spin_unlock_irq(shost->host_lock); - return ndlp; -} -#endif /* 0 */ - /* * This routine looks up the ndlp lists for the given WWPN. If WWPN found it * returns the node element list pointer else return NULL. -- cgit v1.2.2