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

Commit 2c41ef1b authored by Rob Clark's avatar Rob Clark
Browse files

drm/msm/adreno: deal with linux-firmware fw paths



When firmware was added to linux-firmware, it was put in a qcom sub-
directory, unlike what we'd been using before.  For a300_pfp.fw and
a300_pm4.fw symlinks were created, but we'd prefer not to have to do
this in the future.  So add support to look in both places when
loading firmware.

Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent e8f3de96
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -76,9 +76,26 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname)
		goto out;
	}

	/* Load the rest of the MDT */
	ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID, mem_region, mem_phys,
		mem_size);
	/*
	 * Load the rest of the MDT
	 *
	 * Note that we could be dealing with two different paths, since
	 * with upstream linux-firmware it would be in a qcom/ subdir..
	 * adreno_request_fw() handles this, but qcom_mdt_load() does
	 * not.  But since we've already gotten thru adreno_request_fw()
	 * we know which of the two cases it is:
	 */
	if (to_adreno_gpu(gpu)->fwloc == FW_LOCATION_LEGACY) {
		ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID,
				mem_region, mem_phys, mem_size);
	} else {
		char newname[strlen("qcom/") + strlen(fwname) + 1];

		sprintf(newname, "qcom/%s", fwname);

		ret = qcom_mdt_load(dev, fw, newname, GPU_PAS_ID,
				mem_region, mem_phys, mem_size);
	}
	if (ret)
		goto out;

+62 −5
Original line number Diff line number Diff line
@@ -69,15 +69,72 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname)
{
	struct drm_device *drm = adreno_gpu->base.dev;
	const struct firmware *fw = NULL;
	char newname[strlen("qcom/") + strlen(fwname) + 1];
	int ret;

	ret = request_firmware(&fw, fwname, drm->dev);
	if (ret) {
		dev_err(drm->dev, "failed to load %s: %d\n", fwname, ret);
	sprintf(newname, "qcom/%s", fwname);

	/*
	 * Try first to load from qcom/$fwfile using a direct load (to avoid
	 * a potential timeout waiting for usermode helper)
	 */
	if ((adreno_gpu->fwloc == FW_LOCATION_UNKNOWN) ||
	    (adreno_gpu->fwloc == FW_LOCATION_NEW)) {

		ret = request_firmware_direct(&fw, newname, drm->dev);
		if (!ret) {
			dev_info(drm->dev, "loaded %s from new location\n",
				newname);
			adreno_gpu->fwloc = FW_LOCATION_NEW;
			return fw;
		} else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) {
			dev_err(drm->dev, "failed to load %s: %d\n",
				newname, ret);
			return ERR_PTR(ret);
		}
	}

	/*
	 * Then try the legacy location without qcom/ prefix
	 */
	if ((adreno_gpu->fwloc == FW_LOCATION_UNKNOWN) ||
	    (adreno_gpu->fwloc == FW_LOCATION_LEGACY)) {

		ret = request_firmware_direct(&fw, fwname, drm->dev);
		if (!ret) {
			dev_info(drm->dev, "loaded %s from legacy location\n",
				newname);
			adreno_gpu->fwloc = FW_LOCATION_LEGACY;
			return fw;
		} else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) {
			dev_err(drm->dev, "failed to load %s: %d\n",
				fwname, ret);
			return ERR_PTR(ret);
		}
	}

	/*
	 * Finally fall back to request_firmware() for cases where the
	 * usermode helper is needed (I think mainly android)
	 */
	if ((adreno_gpu->fwloc == FW_LOCATION_UNKNOWN) ||
	    (adreno_gpu->fwloc == FW_LOCATION_HELPER)) {

		ret = request_firmware(&fw, newname, drm->dev);
		if (!ret) {
			dev_info(drm->dev, "loaded %s with helper\n",
				newname);
			adreno_gpu->fwloc = FW_LOCATION_HELPER;
			return fw;
		} else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) {
			dev_err(drm->dev, "failed to load %s: %d\n",
				newname, ret);
			return ERR_PTR(ret);
		}
	}

	dev_err(drm->dev, "failed to load %s\n", fwname);
	return ERR_PTR(-ENOENT);
}

static int adreno_load_fw(struct adreno_gpu *adreno_gpu)
+21 −0
Original line number Diff line number Diff line
@@ -101,6 +101,27 @@ struct adreno_gpu {
	/* interesting register offsets to dump: */
	const unsigned int *registers;

	/*
	 * Are we loading fw from legacy path?  Prior to addition
	 * of gpu firmware to linux-firmware, the fw files were
	 * placed in toplevel firmware directory, following qcom's
	 * android kernel.  But linux-firmware preferred they be
	 * placed in a 'qcom' subdirectory.
	 *
	 * For backwards compatibility, we try first to load from
	 * the new path, using request_firmware_direct() to avoid
	 * any potential timeout waiting for usermode helper, then
	 * fall back to the old path (with direct load).  And
	 * finally fall back to request_firmware() with the new
	 * path to allow the usermode helper.
	 */
	enum {
		FW_LOCATION_UNKNOWN = 0,
		FW_LOCATION_NEW,       /* /lib/firmware/qcom/$fwfile */
		FW_LOCATION_LEGACY,    /* /lib/firmware/$fwfile */
		FW_LOCATION_HELPER,
	} fwloc;

	/* firmware: */
	const struct firmware *pm4, *pfp;