Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73360d86 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Remove support for legacy GPMU firmware"

parents fd0cb5c7 5e5f4c3f
Loading
Loading
Loading
Loading
+13 −206
Original line number Diff line number Diff line
@@ -728,187 +728,17 @@ static int _gpmu_create_load_cmds(struct adreno_device *adreno_dev,
	return 0;
}

static int _gpmu_verify_header(struct adreno_device *adreno_dev,
	uint32_t *header, uint32_t fw_size)
{
	unsigned int i;
	const struct adreno_gpu_core *gpucore = adreno_dev->gpucore;
	unsigned int gpmu_major_offset = 0, gpmu_minor_offset = 0;
	unsigned int gpmu_major, gpmu_minor;
	uint32_t header_size;

	header_size = header[0];

	/*
	 * The minimum firmware binary size is eight dwords, one for each of
	 * the following fields: GPMU header block length, header block ID,
	 * major tag, major vlaue, minor tag, minor value, ucode block length,
	 * and ucode block ID.
	 */
	if (fw_size < 8) {
		KGSL_CORE_ERR("GPMU firmware size is less than 8 dwords, actual size %d\n",
			fw_size);
		return -EIO;
	}

	/*
	 * The minimum firmware header size is five dwords, one for each of
	 * the following fields: GPMU header block ID, major tag, major value,
	 * minor tag, minor value.
	 */
	if (header_size < 5) {
		KGSL_CORE_ERR("GPMU firmware header size is less than 5 dwords, actual size %d\n",
			header_size);
		return -EIO;
	}

	if (header_size >= fw_size) {
		KGSL_CORE_ERR("GPMU firmware header size (%d) is larger than firmware size (%d)\n",
				header_size, fw_size);
		return -EIO;
	}

	if (header[1] != GPMU_HEADER_ID) {
		KGSL_CORE_ERR("GPMU firmware header ID mis-match: expected 0x%X, actual 0x%X\n",
				GPMU_HEADER_ID, header[1]);
		return -EIO;
	}

	if ((header_size - 1) % 2 != 0) {
		KGSL_CORE_ERR("GPMU firmware header contains incompete (tag, value) pair\n");
		return -EIO;
	}

	for (i = 2; i < header_size; i += 2) {
		switch (header[i]) {
		case HEADER_MAJOR:
			gpmu_major_offset = i;
			gpmu_major = header[i + 1];
			break;
		case HEADER_MINOR:
			gpmu_minor_offset = i;
			gpmu_minor = header[i + 1];
			break;
		case HEADER_DATE:
		case HEADER_TIME:
			break;
		default:
			KGSL_CORE_ERR("GPMU unknown header ID %d\n",
					header[i]);
			break;
		}
	}

	if (gpmu_major_offset == 0) {
		KGSL_CORE_ERR("GPMU major version number is missing\n");
		return -EIO;
	}

	if (gpmu_minor_offset == 0) {
		KGSL_CORE_ERR("GPMU minor version number is missing\n");
		return -EIO;
	}

	/*
	 * A value of 0 for both the Major and Minor version fields indicates
	 * the code is un-versioned, and should be allowed to pass all
	 * versioning checks.
	 */
	if ((gpmu_major != 0) || (gpmu_minor != 0)) {
		if (gpucore->gpmu_major != gpmu_major) {
			KGSL_CORE_ERR(
				"GPMU major version mis-match: expected %d, actual %d\n",
				gpucore->gpmu_major, gpmu_major);
			return -EIO;
		}

		/*
		 * Driver should be compatible for firmware with
		 * smaller minor version number.
		 */
		if (gpucore->gpmu_minor < gpmu_minor) {
			KGSL_CORE_ERR(
				"GPMU minor version mis-match: expected %d, actual %d\n",
				gpucore->gpmu_minor, gpmu_minor);
			return -EIO;
		}
	}

	return 0;
}

static int _gpmu_verify_ucode(struct adreno_device *adreno_dev,
	uint32_t *data, uint32_t fw_size)
{
	uint32_t header_size = data[0];
	uint32_t *block = &data[header_size + 1];
	uint32_t block_size = block[0];
	uint32_t block_id = block[1];

	if (block_size == 0) {
		KGSL_CORE_ERR("GPMU firmware block size is zero\n");
		return -EIO;
	}

	/*
	 * Deduct one (block length field) from the firmware block size to
	 * get the microcode size.
	 */
	block_size -= 1;

	if (block_size > GPMU_INST_RAM_SIZE) {
		KGSL_CORE_ERR(
		"GPMU firmware block size is larger than RAM size\n");
		return -EIO;
	}

	/*
	 * The actual microcode size is fw_size - header_size - 2, with
	 * the two block length dword fields deducted.
	 */
	if (block_size > fw_size - header_size - 2) {
		KGSL_CORE_ERR("GPMU firmware microcode size (%d) larger than actual (%d)\n",
				block_size, fw_size - header_size - 2);
		return -EIO;
	}

	if (block_id != GPMU_FIRMWARE_ID) {
		KGSL_CORE_ERR("GPMU firmware id not mis-match: expected 0x%X, actual 0x%X\n",
			GPMU_FIRMWARE_ID,  block_id);
		return -EIO;
	}

	return 0;
}

/*
 * _load_gpmu_firmware() - Load the ucode into the GPMU RAM
 * @adreno_dev: Pointer to adreno device

 * GPMU firmare format (one dword per field):
 *	Header block length (length dword field not inclusive)
 *	Header block ID
 *	Header Field 1 tag
 *	Header Field 1 data
 *	Header Field 2 tag
 *	Header Field 2 data (two tag/data pairs minimum for major and minor)
 *	. . .
 *	Header Field M tag
 *	Header Field M data
 *	Microcode block length (length dword field not inclusive)
 *	Microcode block ID
 *	Microcode data Dword 1
 *	Microcode data Dword 2
 *	. . .
 *	Microcode data Dword N
 */
static int _load_gpmu_firmware(struct adreno_device *adreno_dev)
{
	uint32_t *data, *header;
	uint32_t *data;
	const struct firmware *fw = NULL;
	struct kgsl_device *device = &adreno_dev->dev;
	const struct adreno_gpu_core *gpucore = adreno_dev->gpucore;
	uint32_t fw_size, header_size;
	uint32_t *cmds, cmd_size;
	int ret =  -EINVAL;

@@ -930,30 +760,8 @@ static int _load_gpmu_firmware(struct adreno_device *adreno_dev)
	}

	data = (uint32_t *)fw->data;
	fw_size = fw->size / sizeof(uint32_t);

	if (data[0] == 9) {
		/* Legacy file header */

		/* Read header block and verify versioning first */
		ret = _gpmu_verify_header(adreno_dev, data, fw_size);
		if (ret)
			goto err;

		/* Now verify the block data */
		ret = _gpmu_verify_ucode(adreno_dev, data, fw_size);
		if (ret)
			goto err;

		header = &data[0];
		header_size = header[0];

		cmds = data + header_size + 1 + 2;
		cmd_size = data[header_size + 1] - 1;
	} else {
		/* New file header */

		if (data[0] >= fw_size || data[0] < 2)
	if (data[0] >= (fw->size / sizeof(uint32_t)) || data[0] < 2)
		goto err;

	if (data[1] != GPMU_FIRMWARE_ID)
@@ -967,7 +775,6 @@ static int _load_gpmu_firmware(struct adreno_device *adreno_dev)

	cmds = data + data[2] + 3;
	cmd_size = data[0] - data[2] - 2;
	}

	if (cmd_size > GPMU_INST_RAM_SIZE) {
		KGSL_CORE_ERR(