drivers/thunderbolt/dma_port.c

Source file repositories/reference/linux-study-clean/drivers/thunderbolt/dma_port.c

File Facts

System
Linux kernel
Corpus path
drivers/thunderbolt/dma_port.c
Extension
.c
Size
11589 bytes
Lines
461
Domain
Driver Families
Bucket
drivers/thunderbolt
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

struct tb_dma_port {
	struct tb_switch *sw;
	u8 port;
	u32 base;
	u8 buf[];
};

/*
 * When the switch is in safe mode it supports very little functionality
 * so we don't validate that much here.
 */
static bool dma_port_match(const struct tb_cfg_request *req,
			   const struct ctl_pkg *pkg)
{
	u64 route = tb_cfg_get_route(pkg->buffer) & ~BIT_ULL(63);

	if (pkg->frame.eof == TB_CFG_PKG_ERROR)
		return true;
	if (pkg->frame.eof != req->response_type)
		return false;
	if (route != tb_cfg_get_route(req->request))
		return false;
	if (pkg->frame.size != req->response_size)
		return false;

	return true;
}

static bool dma_port_copy(struct tb_cfg_request *req, const struct ctl_pkg *pkg)
{
	memcpy(req->response, pkg->buffer, req->response_size);
	return true;
}

static int dma_port_read(struct tb_ctl *ctl, void *buffer, u64 route,
			 u32 port, u32 offset, u32 length, int timeout_msec)
{
	struct cfg_read_pkg request = {
		.header = tb_cfg_make_header(route),
		.addr = {
			.seq = 1,
			.port = port,
			.space = TB_CFG_PORT,
			.offset = offset,
			.length = length,
		},
	};
	struct tb_cfg_request *req;
	struct cfg_write_pkg reply;
	struct tb_cfg_result res;

	req = tb_cfg_request_alloc();
	if (!req)
		return -ENOMEM;

	req->match = dma_port_match;
	req->copy = dma_port_copy;
	req->request = &request;
	req->request_size = sizeof(request);
	req->request_type = TB_CFG_PKG_READ;
	req->response = &reply;
	req->response_size = 12 + 4 * length;
	req->response_type = TB_CFG_PKG_READ;

	res = tb_cfg_request_sync(ctl, req, timeout_msec);

	tb_cfg_request_put(req);

	if (res.err)
		return res.err;

	memcpy(buffer, &reply.data, 4 * length);
	return 0;
}

static int dma_port_write(struct tb_ctl *ctl, const void *buffer, u64 route,
			  u32 port, u32 offset, u32 length, int timeout_msec)
{
	struct cfg_write_pkg request = {
		.header = tb_cfg_make_header(route),
		.addr = {
			.seq = 1,
			.port = port,
			.space = TB_CFG_PORT,
			.offset = offset,
			.length = length,
		},
	};
	struct tb_cfg_request *req;
	struct cfg_read_pkg reply;

Annotation

Implementation Notes