Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: lpfc: Fix NPIV port deletion crash

The driver is calling schedule_timeout after the DA_ID nameserver request
and LOGO commands are issued to the fabric by the initiator virtual
endport. These fixed delay functions are causing long delays in the
driver's worker thread when processing discovery I/Os in a serialized
fashion, which is then triggering mailbox timeout errors artificially.

To fix this, don't wait on the DA_ID request to complete and call
wait_event_timeout to allow the vport delete thread to make progress on an
event driven basis rather than fixing the wait time.

Link: https://lore.kernel.org/r/20211204002644.116455-5-jsmart2021@gmail.com
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

James Smart and committed by
Martin K. Petersen
8ed190a9 7576d48c

+73 -25
-2
drivers/scsi/lpfc/lpfc.h
··· 669 669 struct timer_list els_tmofunc; 670 670 struct timer_list delayed_disc_tmo; 671 671 672 - int unreg_vpi_cmpl; 673 - 674 672 uint8_t load_flag; 675 673 #define FC_LOADING 0x1 /* HBA in process of loading drvr */ 676 674 #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */
+10 -1
drivers/scsi/lpfc/lpfc_els.c
··· 10978 10978 lpfc_can_disctmo(vport); 10979 10979 } 10980 10980 10981 + if (ndlp->save_flags & NLP_WAIT_FOR_LOGO) { 10982 + /* Wake up lpfc_vport_delete if waiting...*/ 10983 + if (ndlp->logo_waitq) 10984 + wake_up(ndlp->logo_waitq); 10985 + spin_lock_irq(&ndlp->lock); 10986 + ndlp->nlp_flag &= ~(NLP_ISSUE_LOGO | NLP_LOGO_SND); 10987 + ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO; 10988 + spin_unlock_irq(&ndlp->lock); 10989 + } 10990 + 10981 10991 /* Safe to release resources now. */ 10982 10992 lpfc_els_free_iocb(phba, cmdiocb); 10983 10993 lpfc_nlp_put(ndlp); 10984 - vport->unreg_vpi_cmpl = VPORT_ERROR; 10985 10994 } 10986 10995 10987 10996 /**
-2
drivers/scsi/lpfc/lpfc_hbadisc.c
··· 3928 3928 vport->vpi_state &= ~LPFC_VPI_REGISTERED; 3929 3929 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; 3930 3930 spin_unlock_irq(shost->host_lock); 3931 - vport->unreg_vpi_cmpl = VPORT_OK; 3932 3931 mempool_free(pmb, phba->mbox_mem_pool); 3933 3932 lpfc_cleanup_vports_rrqs(vport, NULL); 3934 3933 /* ··· 3957 3958 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, 3958 3959 "1800 Could not issue unreg_vpi\n"); 3959 3960 mempool_free(mbox, phba->mbox_mem_pool); 3960 - vport->unreg_vpi_cmpl = VPORT_ERROR; 3961 3961 return rc; 3962 3962 } 3963 3963 return 0;
+63 -20
drivers/scsi/lpfc/lpfc_vport.c
··· 486 486 } 487 487 488 488 static int 489 + lpfc_send_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) 490 + { 491 + int rc; 492 + struct lpfc_hba *phba = vport->phba; 493 + 494 + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); 495 + 496 + spin_lock_irq(&ndlp->lock); 497 + if (!(ndlp->save_flags & NLP_WAIT_FOR_LOGO) && 498 + !ndlp->logo_waitq) { 499 + ndlp->logo_waitq = &waitq; 500 + ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; 501 + ndlp->nlp_flag |= NLP_ISSUE_LOGO; 502 + ndlp->save_flags |= NLP_WAIT_FOR_LOGO; 503 + } 504 + spin_unlock_irq(&ndlp->lock); 505 + rc = lpfc_issue_els_npiv_logo(vport, ndlp); 506 + if (!rc) { 507 + wait_event_timeout(waitq, 508 + (!(ndlp->save_flags & NLP_WAIT_FOR_LOGO)), 509 + msecs_to_jiffies(phba->fc_ratov * 2000)); 510 + 511 + if (!(ndlp->save_flags & NLP_WAIT_FOR_LOGO)) 512 + goto logo_cmpl; 513 + /* LOGO wait failed. Correct status. */ 514 + rc = -EINTR; 515 + } else { 516 + rc = -EIO; 517 + } 518 + 519 + /* Error - clean up node flags. */ 520 + spin_lock_irq(&ndlp->lock); 521 + ndlp->nlp_flag &= ~NLP_ISSUE_LOGO; 522 + ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO; 523 + spin_unlock_irq(&ndlp->lock); 524 + 525 + logo_cmpl: 526 + lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT, 527 + "1824 Issue LOGO completes with status %d\n", 528 + rc); 529 + spin_lock_irq(&ndlp->lock); 530 + ndlp->logo_waitq = NULL; 531 + spin_unlock_irq(&ndlp->lock); 532 + return rc; 533 + } 534 + 535 + static int 489 536 disable_vport(struct fc_vport *fc_vport) 490 537 { 491 538 struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; 492 539 struct lpfc_hba *phba = vport->phba; 493 540 struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL; 494 - long timeout; 495 541 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 496 542 543 + /* Can't disable during an outstanding delete. */ 544 + if (vport->load_flag & FC_UNLOADING) 545 + return 0; 546 + 497 547 ndlp = lpfc_findnode_did(vport, Fabric_DID); 498 - if (ndlp && phba->link_state >= LPFC_LINK_UP) { 499 - vport->unreg_vpi_cmpl = VPORT_INVAL; 500 - timeout = msecs_to_jiffies(phba->fc_ratov * 2000); 501 - if (!lpfc_issue_els_npiv_logo(vport, ndlp)) 502 - while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout) 503 - timeout = schedule_timeout(timeout); 504 - } 548 + if (ndlp && phba->link_state >= LPFC_LINK_UP) 549 + (void)lpfc_send_npiv_logo(vport, ndlp); 505 550 506 551 lpfc_sli_host_down(vport); 507 552 ··· 645 600 struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; 646 601 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 647 602 struct lpfc_hba *phba = vport->phba; 648 - long timeout; 603 + int rc; 649 604 650 605 if (vport->port_type == LPFC_PHYSICAL_PORT) { 651 606 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, ··· 710 665 phba->fc_topology != LPFC_TOPOLOGY_LOOP) { 711 666 if (vport->cfg_enable_da_id) { 712 667 /* Send DA_ID and wait for a completion. */ 713 - timeout = msecs_to_jiffies(phba->fc_ratov * 2000); 714 - if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0)) 715 - while (vport->ct_flags && timeout) 716 - timeout = schedule_timeout(timeout); 717 - else 668 + rc = lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0); 669 + if (rc) { 718 670 lpfc_printf_log(vport->phba, KERN_WARNING, 719 671 LOG_VPORT, 720 672 "1829 CT command failed to " 721 - "delete objects on fabric\n"); 673 + "delete objects on fabric, " 674 + "rc %d\n", rc); 675 + } 722 676 } 723 677 724 678 /* ··· 732 688 ndlp = lpfc_findnode_did(vport, Fabric_DID); 733 689 if (!ndlp) 734 690 goto skip_logo; 735 - vport->unreg_vpi_cmpl = VPORT_INVAL; 736 - timeout = msecs_to_jiffies(phba->fc_ratov * 2000); 737 - if (!lpfc_issue_els_npiv_logo(vport, ndlp)) 738 - while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout) 739 - timeout = schedule_timeout(timeout); 691 + 692 + rc = lpfc_send_npiv_logo(vport, ndlp); 693 + if (rc) 694 + goto skip_logo; 740 695 } 741 696 742 697 if (!(phba->pport->load_flag & FC_UNLOADING))