drivers/scsi/lpfc/lpfc_hbadisc.c

Source file repositories/reference/linux-study-clean/drivers/scsi/lpfc/lpfc_hbadisc.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/lpfc/lpfc_hbadisc.c
Extension
.c
Size
215220 bytes
Lines
7226
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ndlp->fc4_xpt_flags & SCSI_XPT_REGD) {
			ndlp->fc4_xpt_flags &= ~SCSI_XPT_REGD;

			/* If NLP_XPT_REGD was cleared in lpfc_nlp_unreg_node,
			 * unregister calls were made to the scsi and nvme
			 * transports and refcnt was already decremented. Clear
			 * the NLP_XPT_REGD flag only if the NVME nrport is
			 * confirmed unregistered.
			 */
			if (ndlp->fc4_xpt_flags & NLP_XPT_REGD) {
				if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD))
					ndlp->fc4_xpt_flags &= ~NLP_XPT_REGD;
				spin_unlock_irqrestore(&ndlp->lock, iflags);

				/* Release scsi transport reference */
				lpfc_nlp_put(ndlp);
			} else {
				spin_unlock_irqrestore(&ndlp->lock, iflags);
			}
		} else {
			spin_unlock_irqrestore(&ndlp->lock, iflags);
		}

		if (drop_initial_node_ref)
			lpfc_nlp_put(ndlp);
		return;
	}

	if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
		return;

	/* Ignore callback for a mismatched (stale) rport */
	if (ndlp->rport != rport) {
		lpfc_vlog_msg(vport, KERN_WARNING, LOG_NODE,
			      "6788 fc rport mismatch: d_id x%06x ndlp x%px "
			      "fc rport x%px node rport x%px state x%x "
			      "refcnt %u\n",
			      ndlp->nlp_DID, ndlp, rport, ndlp->rport,
			      ndlp->nlp_state, kref_read(&ndlp->kref));
		return;
	}

	if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn))
		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
				 "6789 rport name %llx != node port name %llx",
				 rport->port_name,
				 wwn_to_u64(ndlp->nlp_portname.u.wwn));

	evtp = &ndlp->dev_loss_evt;

	if (!list_empty(&evtp->evt_listp)) {
		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
				 "6790 rport name %llx dev_loss_evt pending\n",
				 rport->port_name);
		return;
	}

	set_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag);

	spin_lock_irqsave(&ndlp->lock, iflags);
	/* If there is a PLOGI in progress, and we are in a
	 * NLP_NPR_2B_DISC state, don't turn off the flag.
	 */
	if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE)
		clear_bit(NLP_NPR_2B_DISC, &ndlp->nlp_flag);

	/*
	 * The backend does not expect any more calls associated with this
	 * rport. Remove the association between rport and ndlp.
	 */
	ndlp->fc4_xpt_flags &= ~SCSI_XPT_REGD;
	((struct lpfc_rport_data *)rport->dd_data)->pnode = NULL;
	ndlp->rport = NULL;
	spin_unlock_irqrestore(&ndlp->lock, iflags);

	if (phba->worker_thread) {
		/* We need to hold the node by incrementing the reference
		 * count until this queued work is done
		 */
		evtp->evt_arg1 = lpfc_nlp_get(ndlp);

		spin_lock_irqsave(&phba->hbalock, iflags);
		if (evtp->evt_arg1) {
			evtp->evt = LPFC_EVT_DEV_LOSS;
			list_add_tail(&evtp->evt_listp, &phba->work_list);
			spin_unlock_irqrestore(&phba->hbalock, iflags);
			lpfc_worker_wake_up(phba);
			return;
		}
		spin_unlock_irqrestore(&phba->hbalock, iflags);

Annotation

Implementation Notes