drivers/accel/ivpu/ivpu_fw.c

Source file repositories/reference/linux-study-clean/drivers/accel/ivpu/ivpu_fw.c

File Facts

System
Linux kernel
Corpus path
drivers/accel/ivpu/ivpu_fw.c
Extension
.c
Size
24882 bytes
Lines
725
Domain
Driver Families
Bucket
drivers/accel
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) {
			vdev->fw->name = fw_names[i].name;
			return 0;
		}
	}

	ivpu_err(vdev, "Failed to request firmware: %d\n", ret);
	return ret;
}

static int
ivpu_fw_check_api(struct ivpu_device *vdev, const struct vpu_firmware_header *fw_hdr,
		  const char *str, int index, u16 expected_major, u16 expected_minor,
		  u16 min_major)
{
	u16 major = (u16)(fw_hdr->api_version[index] >> 16);
	u16 minor = (u16)(fw_hdr->api_version[index]);

	if (major < min_major) {
		ivpu_err(vdev, "Incompatible FW %s API version: %d.%d, required %d.0 or later\n",
			 str, major, minor, min_major);
		return -EINVAL;
	}
	if (major != expected_major) {
		ivpu_warn(vdev, "Major FW %s API version different: %d.%d (expected %d.%d)\n",
			  str, major, minor, expected_major, expected_minor);
	}
	ivpu_dbg(vdev, FW_BOOT, "FW %s API version: %d.%d (expected %d.%d)\n",
		 str, major, minor, expected_major, expected_minor);

	return 0;
}

static bool
ivpu_fw_check_api_ver_lt(struct ivpu_device *vdev, const struct vpu_firmware_header *fw_hdr,
			 const char *str, int index, u16 major, u16 minor)
{
	u16 fw_major = (u16)(fw_hdr->api_version[index] >> 16);
	u16 fw_minor = (u16)(fw_hdr->api_version[index]);

	if (fw_major < major || (fw_major == major && fw_minor < minor))
		return true;

	return false;
}

bool ivpu_is_within_range(u64 addr, size_t size, struct ivpu_addr_range *range)
{
	u64 addr_end;

	if (!range || check_add_overflow(addr, size, &addr_end))
		return false;

	if (addr < range->start || addr_end > range->end)
		return false;

	return true;
}

static u32
ivpu_fw_sched_mode_select(struct ivpu_device *vdev, const struct vpu_firmware_header *fw_hdr)
{
	if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_60XX &&
	    ivpu_sched_mode == VPU_SCHEDULING_MODE_OS) {
		ivpu_warn(vdev, "OS sched mode is not supported, using HW mode\n");
		return VPU_SCHEDULING_MODE_HW;
	}

	if (ivpu_sched_mode != IVPU_SCHED_MODE_AUTO)
		return ivpu_sched_mode;

	if (IVPU_FW_CHECK_API_VER_LT(vdev, fw_hdr, JSM, 3, 24))
		return VPU_SCHEDULING_MODE_OS;

	return VPU_SCHEDULING_MODE_HW;
}

static void
ivpu_preemption_config_parse(struct ivpu_device *vdev, const struct vpu_firmware_header *fw_hdr)
{
	struct ivpu_fw_info *fw = vdev->fw;
	u32 primary_preempt_buf_size, secondary_preempt_buf_size;

	if (fw_hdr->preemption_buffer_1_max_size)
		primary_preempt_buf_size = fw_hdr->preemption_buffer_1_max_size;
	else
		primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size;

	if (fw_hdr->preemption_buffer_2_max_size)
		secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_max_size;

Annotation

Implementation Notes