drivers/scsi/lpfc/lpfc_nvmet.c

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

File Facts

System
Linux kernel
Corpus path
drivers/scsi/lpfc/lpfc_nvmet.c
Extension
.c
Size
110064 bytes
Lines
3628
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 (status) {
			atomic_inc(&tgtp->xmt_ls_rsp_error);
			if (result == IOERR_ABORT_REQUESTED)
				atomic_inc(&tgtp->xmt_ls_rsp_aborted);
			if (bf_get(lpfc_wcqe_c_xb, wcqe))
				atomic_inc(&tgtp->xmt_ls_rsp_xb_set);
		} else {
			atomic_inc(&tgtp->xmt_ls_rsp_cmpl);
		}
	}

finish:
	__lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, rspwqe);
}

/**
 * lpfc_nvmet_ctxbuf_post - Repost a NVMET RQ DMA buffer and clean up context
 * @phba: HBA buffer is associated with
 * @ctx_buf: ctx buffer context
 *
 * Description: Frees the given DMA buffer in the appropriate way given by
 * reposting it to its associated RQ so it can be reused.
 *
 * Notes: Takes phba->hbalock.  Can be called with or without other locks held.
 *
 * Returns: None
 **/
void
lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
{
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
	struct lpfc_async_xchg_ctx *ctxp = ctx_buf->context;
	struct lpfc_nvmet_tgtport *tgtp;
	struct fc_frame_header *fc_hdr;
	struct rqb_dmabuf *nvmebuf;
	struct lpfc_nvmet_ctx_info *infop;
	uint32_t size, oxid, sid;
	int cpu;
	unsigned long iflag;

	if (ctxp->state == LPFC_NVME_STE_FREE) {
		lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
				"6411 NVMET free, already free IO x%x: %d %d\n",
				ctxp->oxid, ctxp->state, ctxp->entry_cnt);
	}

	if (ctxp->rqb_buffer) {
		spin_lock_irqsave(&ctxp->ctxlock, iflag);
		nvmebuf = ctxp->rqb_buffer;
		/* check if freed in another path whilst acquiring lock */
		if (nvmebuf) {
			ctxp->rqb_buffer = NULL;
			if (ctxp->flag & LPFC_NVME_CTX_REUSE_WQ) {
				ctxp->flag &= ~LPFC_NVME_CTX_REUSE_WQ;
				spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
				nvmebuf->hrq->rqbp->rqb_free_buffer(phba,
								    nvmebuf);
			} else {
				spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
				/* repost */
				lpfc_rq_buf_free(phba, &nvmebuf->hbuf);
			}
		} else {
			spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
		}
	}
	ctxp->state = LPFC_NVME_STE_FREE;

	spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
	if (phba->sli4_hba.nvmet_io_wait_cnt) {
		list_remove_head(&phba->sli4_hba.lpfc_nvmet_io_wait_list,
				 nvmebuf, struct rqb_dmabuf,
				 hbuf.list);
		phba->sli4_hba.nvmet_io_wait_cnt--;
		spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock,
				       iflag);

		fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
		oxid = be16_to_cpu(fc_hdr->fh_ox_id);
		tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
		size = nvmebuf->bytes_recv;
		sid = sli4_sid_from_fc_hdr(fc_hdr);

		ctxp = (struct lpfc_async_xchg_ctx *)ctx_buf->context;
		ctxp->wqeq = NULL;
		ctxp->offset = 0;
		ctxp->phba = phba;
		ctxp->size = size;
		ctxp->oxid = oxid;
		ctxp->sid = sid;

Annotation

Implementation Notes