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.
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/completion.hlinux/circ_buf.hlinux/list.hsoc/qcom/cmd-db.hsoc/qcom/tcs.ha6xx_gmu.ha6xx_gmu.xml.ha6xx_gpu.h
Detected Declarations
function a6xx_hfi_queue_readfunction a6xx_hfi_queue_writefunction a6xx_hfi_wait_for_msg_interruptfunction a6xx_hfi_wait_for_ackfunction a6xx_hfi_send_msgfunction a6xx_hfi_send_gmu_initfunction a6xx_hfi_get_fw_versionfunction a6xx_hfi_send_perf_table_v1function a8xx_hfi_send_perf_tablefunction a6xx_hfi_send_perf_tablefunction a6xx_generate_bw_tablefunction a618_build_bw_tablefunction a619_build_bw_tablefunction a640_build_bw_tablefunction a650_build_bw_tablefunction a690_build_bw_tablefunction a660_build_bw_tablefunction a663_build_bw_tablefunction adreno_7c3_build_bw_tablefunction a730_build_bw_tablefunction a740_build_bw_tablefunction a6xx_build_bw_tablefunction a6xx_hfi_send_bw_tablefunction a6xx_hfi_feature_ctrl_msgfunction a6xx_hfi_enable_ifpcfunction a6xx_hfi_enable_acdfunction a6xx_hfi_send_testfunction a6xx_hfi_send_startfunction a6xx_hfi_send_core_fw_startfunction a6xx_hfi_set_freqfunction a6xx_hfi_send_prep_slumberfunction a6xx_hfi_start_v1function a6xx_hfi_startfunction a6xx_hfi_stopfunction a6xx_hfi_queue_initfunction a6xx_hfi_init
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
- Immediate include surface: `linux/completion.h`, `linux/circ_buf.h`, `linux/list.h`, `soc/qcom/cmd-db.h`, `soc/qcom/tcs.h`, `a6xx_gmu.h`, `a6xx_gmu.xml.h`, `a6xx_gpu.h`.
- Detected declarations: `function a6xx_hfi_queue_read`, `function a6xx_hfi_queue_write`, `function a6xx_hfi_wait_for_msg_interrupt`, `function a6xx_hfi_wait_for_ack`, `function a6xx_hfi_send_msg`, `function a6xx_hfi_send_gmu_init`, `function a6xx_hfi_get_fw_version`, `function a6xx_hfi_send_perf_table_v1`, `function a8xx_hfi_send_perf_table`, `function a6xx_hfi_send_perf_table`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.