drivers/gpu/drm/msm/adreno/a6xx_hfi.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/msm/adreno/a6xx_hfi.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/msm/adreno/a6xx_hfi.c
Extension
.c
Size
29471 bytes
Lines
1103
Domain
Driver Families
Bucket
drivers/gpu
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 (!ret) {
			ret = a6xx_hfi_wait_for_msg_interrupt(gmu, id, seqnum);
			if (ret) {
				DRM_DEV_ERROR(gmu->dev,
					"The HFI response queue is unexpectedly empty\n");
				return ret;
			}
			continue;
		}

		if (HFI_HEADER_ID(resp.header) == HFI_F2H_MSG_ERROR) {
			struct a6xx_hfi_msg_error *error =
				(struct a6xx_hfi_msg_error *) &resp;

			DRM_DEV_ERROR(gmu->dev, "GMU firmware error %d\n",
				error->code);
			continue;
		}

		if (seqnum != HFI_HEADER_SEQNUM(resp.ret_header)) {
			DRM_DEV_ERROR(gmu->dev,
				"Unexpected message id %d on the response queue\n",
				HFI_HEADER_SEQNUM(resp.ret_header));
			continue;
		}

		if (resp.error) {
			DRM_DEV_ERROR(gmu->dev,
				"Message %s id %d returned error %d\n",
				a6xx_hfi_msg_id[id], seqnum, resp.error);
			return -EINVAL;
		}

		/* All is well, copy over the buffer */
		if (payload && payload_size)
			memcpy(payload, resp.payload,
				min_t(u32, payload_size, sizeof(resp.payload)));

		return 0;
	}
}

static int a6xx_hfi_send_msg(struct a6xx_gmu *gmu, int id,
		void *data, u32 size, u32 *payload, u32 payload_size)
{
	struct a6xx_hfi_queue *queue = &gmu->queues[HFI_COMMAND_QUEUE];
	int ret, dwords = size >> 2;
	u32 seqnum;

	seqnum = atomic_inc_return(&queue->seqnum) % 0xfff;

	/* First dword of the message is the message header - fill it in */
	*((u32 *) data) = (seqnum << 20) | (HFI_MSG_CMD << 16) |
		(dwords << 8) | id;

	ret = a6xx_hfi_queue_write(gmu, queue, data, dwords);
	if (ret) {
		DRM_DEV_ERROR(gmu->dev, "Unable to send message %s id %d\n",
			a6xx_hfi_msg_id[id], seqnum);
		return ret;
	}

	return a6xx_hfi_wait_for_ack(gmu, id, seqnum, payload, payload_size);
}

static int a6xx_hfi_send_gmu_init(struct a6xx_gmu *gmu, int boot_state)
{
	struct a6xx_hfi_msg_gmu_init_cmd msg = { 0 };

	msg.dbg_buffer_addr = (u32) gmu->debug.iova;
	msg.dbg_buffer_size = (u32) gmu->debug.size;
	msg.boot_state = boot_state;

	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_INIT, &msg, sizeof(msg),
		NULL, 0);
}

static int a6xx_hfi_get_fw_version(struct a6xx_gmu *gmu, u32 *version)
{
	struct a6xx_hfi_msg_fw_version msg = { 0 };

	/* Currently supporting version 1.10 */
	msg.supported_version = (1 << 28) | (1 << 19) | (1 << 17);

	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_FW_VERSION, &msg, sizeof(msg),
		version, sizeof(*version));
}

static int a6xx_hfi_send_perf_table_v1(struct a6xx_gmu *gmu)
{

Annotation

Implementation Notes