drivers/scsi/mpt3sas/mpt3sas_base.c

Source file repositories/reference/linux-study-clean/drivers/scsi/mpt3sas/mpt3sas_base.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/mpt3sas/mpt3sas_base.c
Extension
.c
Size
260699 bytes
Lines
9043
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 (scmd == NULL) {
			ioc_err(ioc, "scmd is NULL\n");
			return;
		}

		/* Get sg_scmd from scmd provided */
		sg_scmd = scsi_sglist(scmd);
	}

	/*
	 * 0 - 255	System register
	 * 256 - 4352	MPI Frame. (This is based on maxCredit 32)
	 * 4352 - 4864	Reply_free pool (512 byte is reserved
	 *		considering maxCredit 32. Reply need extra
	 *		room, for mCPU case kept four times of
	 *		maxCredit).
	 * 4864 - 17152	SGE chain element. (32cmd * 3 chain of
	 *		128 byte size = 12288)
	 * 17152 - x	Host buffer mapped with smid.
	 *		(Each smid can have 64K Max IO.)
	 * BAR0+Last 1K MSIX Addr and Data
	 * Total size in use 2113664 bytes of 4MB BAR0
	 */

	buffer_iomem = _base_get_buffer_bar0(ioc, smid);
	buffer_iomem_phys = _base_get_buffer_phys_bar0(ioc, smid);

	buff_ptr = buffer_iomem;
	buff_ptr_phys = buffer_iomem_phys;
	WARN_ON(buff_ptr_phys > U32_MAX);

	if (le32_to_cpu(sgel->FlagsLength) &
			(MPI2_SGE_FLAGS_HOST_TO_IOC << MPI2_SGE_FLAGS_SHIFT))
		is_write = true;

	for (i = 0; i < MPT_MIN_PHYS_SEGMENTS + ioc->facts.MaxChainDepth; i++) {

		sgl_flags =
		    (le32_to_cpu(sgel->FlagsLength) >> MPI2_SGE_FLAGS_SHIFT);

		switch (sgl_flags & MPI2_SGE_FLAGS_ELEMENT_MASK) {
		case MPI2_SGE_FLAGS_CHAIN_ELEMENT:
			/*
			 * Helper function which on passing
			 * chain_buffer_dma returns chain_buffer. Get
			 * the virtual address for sgel->Address
			 */
			sgel_next =
				_base_get_chain_buffer_dma_to_chain_buffer(ioc,
						le32_to_cpu(sgel->Address));
			if (sgel_next == NULL)
				return;
			/*
			 * This is coping 128 byte chain
			 * frame (not a host buffer)
			 */
			dst_chain_addr[sge_chain_count] =
				_base_get_chain(ioc,
					smid, sge_chain_count);
			src_chain_addr[sge_chain_count] =
						(void *) sgel_next;
			dst_addr_phys = _base_get_chain_phys(ioc,
						smid, sge_chain_count);
			WARN_ON(dst_addr_phys > U32_MAX);
			sgel->Address =
				cpu_to_le32(lower_32_bits(dst_addr_phys));
			sgel = sgel_next;
			sge_chain_count++;
			break;
		case MPI2_SGE_FLAGS_SIMPLE_ELEMENT:
			if (is_write) {
				if (is_scsiio_req) {
					_base_clone_to_sys_mem(buff_ptr,
					    sg_virt(sg_scmd),
					    (le32_to_cpu(sgel->FlagsLength) &
					    0x00ffffff));
					/*
					 * FIXME: this relies on a a zero
					 * PCI mem_offset.
					 */
					sgel->Address =
					    cpu_to_le32((u32)buff_ptr_phys);
				} else {
					_base_clone_to_sys_mem(buff_ptr,
					    ioc->config_vaddr,
					    (le32_to_cpu(sgel->FlagsLength) &
					    0x00ffffff));
					sgel->Address =
					    cpu_to_le32((u32)buff_ptr_phys);
				}

Annotation

Implementation Notes