drivers/cxl/core/hdm.c

Source file repositories/reference/linux-study-clean/drivers/cxl/core/hdm.c

File Facts

System
Linux kernel
Corpus path
drivers/cxl/core/hdm.c
Extension
.c
Size
35427 bytes
Lines
1280
Domain
Driver Families
Bucket
drivers/cxl
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (!info || !info->mem_enabled) {
			dev_err(dev, "No component registers mapped\n");
			return ERR_PTR(-ENXIO);
		}

		cxlhdm->decoder_count = info->ranges;
		return cxlhdm;
	}

	if (!reg_map->component_map.hdm_decoder.valid) {
		dev_dbg(&port->dev, "HDM decoder registers not implemented\n");
		/* unique error code to indicate no HDM decoder capability */
		return ERR_PTR(-ENODEV);
	}

	rc = cxl_map_component_regs(reg_map, &cxlhdm->regs,
				    BIT(CXL_CM_CAP_CAP_ID_HDM));
	if (rc) {
		dev_err(dev, "Failed to map HDM capability.\n");
		return ERR_PTR(rc);
	}

	parse_hdm_decoder_caps(cxlhdm);
	if (cxlhdm->decoder_count < 0) {
		dev_err(dev, "Spec violation. Caps invalid\n");
		return ERR_PTR(-ENXIO);
	}

	/*
	 * Now that the hdm capability is parsed, decide if range
	 * register emulation is needed and fixup cxlhdm accordingly.
	 */
	if (should_emulate_decoders(info)) {
		dev_dbg(dev, "Fallback map %d range register%s\n", info->ranges,
			str_plural(info->ranges));
		cxlhdm->decoder_count = info->ranges;
	}

	return cxlhdm;
}

static void __cxl_dpa_debug(struct seq_file *file, struct resource *r, int depth)
{
	unsigned long long start = r->start, end = r->end;

	seq_printf(file, "%*s%08llx-%08llx : %s\n", depth * 2, "", start, end,
		   r->name);
}

void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds)
{
	struct resource *p1, *p2;

	guard(rwsem_read)(&cxl_rwsem.dpa);
	for (p1 = cxlds->dpa_res.child; p1; p1 = p1->sibling) {
		__cxl_dpa_debug(file, p1, 0);
		for (p2 = p1->child; p2; p2 = p2->sibling)
			__cxl_dpa_debug(file, p2, 1);
	}
}
EXPORT_SYMBOL_NS_GPL(cxl_dpa_debug, "CXL");

/* See request_skip() kernel-doc */
static resource_size_t __adjust_skip(struct cxl_dev_state *cxlds,
				     const resource_size_t skip_base,
				     const resource_size_t skip_len,
				     const char *requester)
{
	const resource_size_t skip_end = skip_base + skip_len - 1;

	for (int i = 0; i < cxlds->nr_partitions; i++) {
		const struct resource *part_res = &cxlds->part[i].res;
		resource_size_t adjust_start, adjust_end, size;

		adjust_start = max(skip_base, part_res->start);
		adjust_end = min(skip_end, part_res->end);

		if (adjust_end < adjust_start)
			continue;

		size = adjust_end - adjust_start + 1;

		if (!requester)
			__release_region(&cxlds->dpa_res, adjust_start, size);
		else if (!__request_region(&cxlds->dpa_res, adjust_start, size,
					   requester, 0))
			return adjust_start - skip_base;
	}

	return skip_len;

Annotation

Implementation Notes