drivers/scsi/lpfc/lpfc_els.c

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

File Facts

System
Linux kernel
Corpus path
drivers/scsi/lpfc/lpfc_els.c
Extension
.c
Size
392414 bytes
Lines
12580
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

switch (elscmd) {
		case ELS_CMD_FLOGI:
			elsiocb->cmd_flag |=
				((LPFC_ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT)
				 & LPFC_FIP_ELS_ID_MASK);
			break;
		case ELS_CMD_FDISC:
			elsiocb->cmd_flag |=
				((LPFC_ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT)
				 & LPFC_FIP_ELS_ID_MASK);
			break;
		case ELS_CMD_LOGO:
			elsiocb->cmd_flag |=
				((LPFC_ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT)
				 & LPFC_FIP_ELS_ID_MASK);
			break;
		}
	else
		elsiocb->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK;

	/* fill in BDEs for command */
	/* Allocate buffer for command payload */
	pcmd = kmalloc_obj(*pcmd);
	if (pcmd)
		pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pcmd->phys);
	if (!pcmd || !pcmd->virt)
		goto els_iocb_free_pcmb_exit;

	INIT_LIST_HEAD(&pcmd->list);

	/* Allocate buffer for response payload */
	if (expect_rsp) {
		prsp = kmalloc_obj(*prsp);
		if (prsp)
			prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
						     &prsp->phys);
		if (!prsp || !prsp->virt)
			goto els_iocb_free_prsp_exit;
		INIT_LIST_HEAD(&prsp->list);
	} else {
		prsp = NULL;
	}

	/* Allocate buffer for Buffer ptr list */
	pbuflist = kmalloc_obj(*pbuflist);
	if (pbuflist)
		pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
						 &pbuflist->phys);
	if (!pbuflist || !pbuflist->virt)
		goto els_iocb_free_pbuf_exit;

	INIT_LIST_HEAD(&pbuflist->list);

	if (expect_rsp) {
		switch (elscmd) {
		case ELS_CMD_FLOGI:
			timeout = FF_DEF_RATOV * 2;
			break;
		case ELS_CMD_LOGO:
			timeout = phba->fc_ratov;
			break;
		default:
			timeout = phba->fc_ratov * 2;
		}

		/* Fill SGE for the num bde count */
		elsiocb->num_bdes = 2;
	}

	if (phba->sli_rev == LPFC_SLI_REV4)
		bmp = pcmd;
	else
		bmp = pbuflist;

	lpfc_sli_prep_els_req_rsp(phba, elsiocb, vport, bmp, cmd_size, did,
				  elscmd, timeout, expect_rsp);

	bpl = (struct ulp_bde64_le *)pbuflist->virt;
	bpl->addr_low = cpu_to_le32(putPaddrLow(pcmd->phys));
	bpl->addr_high = cpu_to_le32(putPaddrHigh(pcmd->phys));
	bpl->type_size = cpu_to_le32(cmd_size);
	bpl->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64);

	if (expect_rsp) {
		bpl++;
		bpl->addr_low = cpu_to_le32(putPaddrLow(prsp->phys));
		bpl->addr_high = cpu_to_le32(putPaddrHigh(prsp->phys));
		bpl->type_size = cpu_to_le32(FCELSSIZE);
		bpl->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64);
	}

Annotation

Implementation Notes