diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 157 |
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 | |||
448 | check_work_wait_done(struct lpfc_hba *phba) | 432 | check_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; |
471 | exit: | ||
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) | |||
733 | static int | 707 | static int |
734 | lpfc_linkup(struct lpfc_hba *phba) | 708 | lpfc_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 | |||
1298 | lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | 1275 | lpfc_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 | ||