aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_hbadisc.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_hbadisc.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_hbadisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c157
1 files changed, 70 insertions, 87 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index ea27bbb81552..556d55fc9456 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -349,7 +349,8 @@ lpfc_work_done(struct lpfc_hba *phba)
349{ 349{
350 struct lpfc_sli_ring *pring; 350 struct lpfc_sli_ring *pring;
351 uint32_t ha_copy, status, control, work_port_events; 351 uint32_t ha_copy, status, control, work_port_events;
352 struct lpfc_vport *vport; 352 struct lpfc_vport **vports;
353 int i;
353 354
354 spin_lock_irq(&phba->hbalock); 355 spin_lock_irq(&phba->hbalock);
355 ha_copy = phba->work_ha; 356 ha_copy = phba->work_ha;
@@ -364,48 +365,31 @@ lpfc_work_done(struct lpfc_hba *phba)
364 365
365 if (ha_copy & HA_LATT) 366 if (ha_copy & HA_LATT)
366 lpfc_handle_latt(phba); 367 lpfc_handle_latt(phba);
367 368 vports = lpfc_create_vport_work_array(phba);
368 spin_lock_irq(&phba->hbalock); 369 if (vports != NULL)
369 list_for_each_entry(vport, &phba->port_list, listentry) { 370 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
370 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 371 work_port_events = vports[i]->work_port_events;
371 372 if (work_port_events & WORKER_DISC_TMO)
372 if (!scsi_host_get(shost)) { 373 lpfc_disc_timeout_handler(vports[i]);
373 continue; 374 if (work_port_events & WORKER_ELS_TMO)
375 lpfc_els_timeout_handler(vports[i]);
376 if (work_port_events & WORKER_HB_TMO)
377 lpfc_hb_timeout_handler(phba);
378 if (work_port_events & WORKER_MBOX_TMO)
379 lpfc_mbox_timeout_handler(phba);
380 if (work_port_events & WORKER_FABRIC_BLOCK_TMO)
381 lpfc_unblock_fabric_iocbs(phba);
382 if (work_port_events & WORKER_FDMI_TMO)
383 lpfc_fdmi_timeout_handler(vports[i]);
384 if (work_port_events & WORKER_RAMP_DOWN_QUEUE)
385 lpfc_ramp_down_queue_handler(phba);
386 if (work_port_events & WORKER_RAMP_UP_QUEUE)
387 lpfc_ramp_up_queue_handler(phba);
388 spin_lock_irq(&vports[i]->work_port_lock);
389 vports[i]->work_port_events &= ~work_port_events;
390 spin_unlock_irq(&vports[i]->work_port_lock);
374 } 391 }
375 spin_unlock_irq(&phba->hbalock); 392 lpfc_destroy_vport_work_array(vports);
376 work_port_events = vport->work_port_events;
377
378 if (work_port_events & WORKER_DISC_TMO)
379 lpfc_disc_timeout_handler(vport);
380
381 if (work_port_events & WORKER_ELS_TMO)
382 lpfc_els_timeout_handler(vport);
383
384 if (work_port_events & WORKER_HB_TMO)
385 lpfc_hb_timeout_handler(phba);
386
387 if (work_port_events & WORKER_MBOX_TMO)
388 lpfc_mbox_timeout_handler(phba);
389
390 if (work_port_events & WORKER_FABRIC_BLOCK_TMO)
391 lpfc_unblock_fabric_iocbs(phba);
392
393 if (work_port_events & WORKER_FDMI_TMO)
394 lpfc_fdmi_timeout_handler(vport);
395
396 if (work_port_events & WORKER_RAMP_DOWN_QUEUE)
397 lpfc_ramp_down_queue_handler(phba);
398
399 if (work_port_events & WORKER_RAMP_UP_QUEUE)
400 lpfc_ramp_up_queue_handler(phba);
401
402 spin_lock_irq(&vport->work_port_lock);
403 vport->work_port_events &= ~work_port_events;
404 spin_unlock_irq(&vport->work_port_lock);
405 scsi_host_put(shost);
406 spin_lock_irq(&phba->hbalock);
407 }
408 spin_unlock_irq(&phba->hbalock);
409 393
410 pring = &phba->sli.ring[LPFC_ELS_RING]; 394 pring = &phba->sli.ring[LPFC_ELS_RING];
411 status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING))); 395 status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING)));
@@ -448,32 +432,22 @@ static int
448check_work_wait_done(struct lpfc_hba *phba) 432check_work_wait_done(struct lpfc_hba *phba)
449{ 433{
450 struct lpfc_vport *vport; 434 struct lpfc_vport *vport;
451 struct lpfc_sli_ring *pring; 435 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
452 int rc = 0; 436 int rc = 0;
453 437
454 spin_lock_irq(&phba->hbalock); 438 spin_lock_irq(&phba->hbalock);
455 list_for_each_entry(vport, &phba->port_list, listentry) { 439 list_for_each_entry(vport, &phba->port_list, listentry) {
456 if (vport->work_port_events) { 440 if (vport->work_port_events) {
457 rc = 1; 441 rc = 1;
458 goto exit; 442 break;
459 } 443 }
460 } 444 }
461 445 if (rc || phba->work_ha || (!list_empty(&phba->work_list)) ||
462 if (phba->work_ha || (!list_empty(&phba->work_list)) || 446 kthread_should_stop() || pring->flag & LPFC_DEFERRED_RING_EVENT) {
463 kthread_should_stop()) {
464 rc = 1;
465 goto exit;
466 }
467
468 pring = &phba->sli.ring[LPFC_ELS_RING];
469 if (pring->flag & LPFC_DEFERRED_RING_EVENT)
470 rc = 1; 447 rc = 1;
471exit:
472 if (rc)
473 phba->work_found++; 448 phba->work_found++;
474 else 449 } else
475 phba->work_found = 0; 450 phba->work_found = 0;
476
477 spin_unlock_irq(&phba->hbalock); 451 spin_unlock_irq(&phba->hbalock);
478 return rc; 452 return rc;
479} 453}
@@ -601,7 +575,6 @@ lpfc_linkdown_port(struct lpfc_vport *vport)
601 575
602 /* free any ndlp's on unused list */ 576 /* free any ndlp's on unused list */
603 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) 577 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
604 /* free any ndlp's in unused state */
605 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) 578 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
606 lpfc_drop_node(vport, ndlp); 579 lpfc_drop_node(vport, ndlp);
607 580
@@ -614,8 +587,9 @@ lpfc_linkdown(struct lpfc_hba *phba)
614{ 587{
615 struct lpfc_vport *vport = phba->pport; 588 struct lpfc_vport *vport = phba->pport;
616 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 589 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
617 struct lpfc_vport *port_iterator; 590 struct lpfc_vport **vports;
618 LPFC_MBOXQ_t *mb; 591 LPFC_MBOXQ_t *mb;
592 int i;
619 593
620 if (phba->link_state == LPFC_LINK_DOWN) { 594 if (phba->link_state == LPFC_LINK_DOWN) {
621 return 0; 595 return 0;
@@ -626,13 +600,13 @@ lpfc_linkdown(struct lpfc_hba *phba)
626 phba->pport->fc_flag &= ~FC_LBIT; 600 phba->pport->fc_flag &= ~FC_LBIT;
627 } 601 }
628 spin_unlock_irq(&phba->hbalock); 602 spin_unlock_irq(&phba->hbalock);
629 603 vports = lpfc_create_vport_work_array(phba);
630 list_for_each_entry(port_iterator, &phba->port_list, listentry) { 604 if (vports != NULL)
631 605 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
632 /* Issue a LINK DOWN event to all nodes */ 606 /* Issue a LINK DOWN event to all nodes */
633 lpfc_linkdown_port(port_iterator); 607 lpfc_linkdown_port(vports[i]);
634 } 608 }
635 609 lpfc_destroy_vport_work_array(vports);
636 /* Clean up any firmware default rpi's */ 610 /* Clean up any firmware default rpi's */
637 mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 611 mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
638 if (mb) { 612 if (mb) {
@@ -733,7 +707,8 @@ lpfc_linkup_port(struct lpfc_vport *vport)
733static int 707static int
734lpfc_linkup(struct lpfc_hba *phba) 708lpfc_linkup(struct lpfc_hba *phba)
735{ 709{
736 struct lpfc_vport *vport; 710 struct lpfc_vport **vports;
711 int i;
737 712
738 phba->link_state = LPFC_LINK_UP; 713 phba->link_state = LPFC_LINK_UP;
739 714
@@ -741,9 +716,11 @@ lpfc_linkup(struct lpfc_hba *phba)
741 clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); 716 clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
742 del_timer_sync(&phba->fabric_block_timer); 717 del_timer_sync(&phba->fabric_block_timer);
743 718
744 list_for_each_entry(vport, &phba->port_list, listentry) { 719 vports = lpfc_create_vport_work_array(phba);
745 lpfc_linkup_port(vport); 720 if (vports != NULL)
746 } 721 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++)
722 lpfc_linkup_port(vports[i]);
723 lpfc_destroy_vport_work_array(vports);
747 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) 724 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
748 lpfc_issue_clear_la(phba, phba->pport); 725 lpfc_issue_clear_la(phba, phba->pport);
749 726
@@ -1298,15 +1275,15 @@ void
1298lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) 1275lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1299{ 1276{
1300 struct lpfc_vport *vport = pmb->vport; 1277 struct lpfc_vport *vport = pmb->vport;
1301 struct lpfc_vport *next_vport;
1302 MAILBOX_t *mb = &pmb->mb; 1278 MAILBOX_t *mb = &pmb->mb;
1303 struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); 1279 struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
1304 struct lpfc_nodelist *ndlp; 1280 struct lpfc_nodelist *ndlp;
1305 ndlp = (struct lpfc_nodelist *) pmb->context2; 1281 struct lpfc_vport **vports;
1282 int i;
1306 1283
1284 ndlp = (struct lpfc_nodelist *) pmb->context2;
1307 pmb->context1 = NULL; 1285 pmb->context1 = NULL;
1308 pmb->context2 = NULL; 1286 pmb->context2 = NULL;
1309
1310 if (mb->mbxStatus) { 1287 if (mb->mbxStatus) {
1311 lpfc_mbuf_free(phba, mp->virt, mp->phys); 1288 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1312 kfree(mp); 1289 kfree(mp);
@@ -1337,21 +1314,27 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1337 lpfc_nlp_put(ndlp); /* Drop the reference from the mbox */ 1314 lpfc_nlp_put(ndlp); /* Drop the reference from the mbox */
1338 1315
1339 if (vport->port_state == LPFC_FABRIC_CFG_LINK) { 1316 if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
1340 list_for_each_entry(next_vport, &phba->port_list, listentry) { 1317 vports = lpfc_create_vport_work_array(phba);
1341 if (next_vport->port_type == LPFC_PHYSICAL_PORT) 1318 if (vports != NULL)
1342 continue; 1319 for(i = 0;
1343 1320 i < LPFC_MAX_VPORTS && vports[i] != NULL;
1344 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) 1321 i++) {
1345 lpfc_initial_fdisc(next_vport); 1322 if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
1346 else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { 1323 continue;
1347 lpfc_vport_set_state(vport, 1324 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
1348 FC_VPORT_NO_FABRIC_SUPP); 1325 lpfc_initial_fdisc(vports[i]);
1349 lpfc_printf_log(phba, KERN_ERR, LOG_ELS, 1326 else if (phba->sli3_options &
1350 "%d (%d):0259 No NPIV Fabric " 1327 LPFC_SLI3_NPIV_ENABLED) {
1351 "support\n", 1328 lpfc_vport_set_state(vports[i],
1352 phba->brd_no, vport->vpi); 1329 FC_VPORT_NO_FABRIC_SUPP);
1330 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
1331 "%d (%d):0259 No NPIV "
1332 "Fabric support\n",
1333 phba->brd_no,
1334 vports[i]->vpi);
1335 }
1353 } 1336 }
1354 } 1337 lpfc_destroy_vport_work_array(vports);
1355 lpfc_do_scr_ns_plogi(phba, vport); 1338 lpfc_do_scr_ns_plogi(phba, vport);
1356 } 1339 }
1357 1340