drivers/scsi/lpfc/lpfc_ct.c

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

File Facts

System
Linux kernel
Corpus path
drivers/scsi/lpfc/lpfc_ct.c
Extension
.c
Size
110281 bytes
Lines
3835
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

list_for_each_entry(iocb, &head, list) {
			if (phba->sli_rev == LPFC_SLI_REV4)
				bde_count = iocb->wcqe_cmpl.word3;
			else
				bde_count = iocb->iocb.ulpBdeCount;

			if (!bde_count)
				continue;
			bdeBuf1 = iocb->cmd_dmabuf;
			iocb->cmd_dmabuf = NULL;
			if (phba->sli_rev == LPFC_SLI_REV4)
				size = iocb->wqe.gen_req.bde.tus.f.bdeSize;
			else
				size  = iocb->iocb.un.cont64[0].tus.f.bdeSize;
			lpfc_ct_unsol_buffer(phba, ctiocbq, bdeBuf1, size);
			lpfc_in_buf_free(phba, bdeBuf1);
			if (bde_count == 2) {
				bdeBuf2 = iocb->bpl_dmabuf;
				iocb->bpl_dmabuf = NULL;
				if (phba->sli_rev == LPFC_SLI_REV4)
					size = iocb->unsol_rcv_len;
				else
					size = iocb->iocb.unsli3.rcvsli3.bde2.tus.f.bdeSize;
				lpfc_ct_unsol_buffer(phba, ctiocbq, bdeBuf2,
						     size);
				lpfc_in_buf_free(phba, bdeBuf2);
			}
		}
		list_del(&head);
	} else {
		INIT_LIST_HEAD(&head);
		list_add_tail(&head, &ctiocbq->list);
		list_for_each_entry(iocbq, &head, list) {
			icmd = &iocbq->iocb;
			if (icmd->ulpBdeCount == 0)
				lpfc_ct_unsol_buffer(phba, iocbq, NULL, 0);
			for (i = 0; i < icmd->ulpBdeCount; i++) {
				dma_addr = getPaddr(icmd->un.cont64[i].addrHigh,
						    icmd->un.cont64[i].addrLow);
				mp = lpfc_sli_ringpostbuf_get(phba, pring,
							      dma_addr);
				size = icmd->un.cont64[i].tus.f.bdeSize;
				lpfc_ct_unsol_buffer(phba, iocbq, mp, size);
				lpfc_in_buf_free(phba, mp);
			}
			lpfc_sli3_post_buffer(phba, pring, i);
		}
		list_del(&head);
	}
}

/**
 * lpfc_ct_handle_unsol_abort - ct upper level protocol abort handler
 * @phba: Pointer to HBA context object.
 * @dmabuf: pointer to a dmabuf that describes the FC sequence
 *
 * This function serves as the upper level protocol abort handler for CT
 * protocol.
 *
 * Return 1 if abort has been handled, 0 otherwise.
 **/
int
lpfc_ct_handle_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
{
	int handled;

	/* CT upper level goes through BSG */
	handled = lpfc_bsg_ct_unsol_abort(phba, dmabuf);

	return handled;
}

static void
lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
{
	struct lpfc_dmabuf *mlast, *next_mlast;

	list_for_each_entry_safe(mlast, next_mlast, &mlist->list, list) {
		list_del(&mlast->list);
		lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
		kfree(mlast);
	}
	lpfc_mbuf_free(phba, mlist->virt, mlist->phys);
	kfree(mlist);
	return;
}

static struct lpfc_dmabuf *
lpfc_alloc_ct_rsp(struct lpfc_hba *phba, __be16 cmdcode, struct ulp_bde64 *bpl,
		  uint32_t size, int *entries)

Annotation

Implementation Notes