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

Commit 671e2ee5 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'linux-5.2' of git://github.com/skeggsb/linux into drm-fixes



" This is a bit more than I'd like to be pushing at this point in a
cycle, but it's a fairly important issue.  There's been numerous
reports of more recent GP10[2467] boards failing to load, and I've
worked with NVIDIA FW engineers and tracked this down to the FW we've
been using not properly supporting the boards in question.

I've pushed an update to linux-firmware with the new FW version, which
unfortunately contains API changes vs the older firmware.

This series teaches the ACR subsystem inside nouveau enough to be able
to deal with supporting multiple incompatible FW revisions, and adds
support to the relevant chipsets for loading the newer FW revision, if
it's available."

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Ben Skeggs <skeggsb@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv7pG+vur0Kn_TyU3ainnkvJVw07upnnaQNOToF+kzQtDQ@mail.gmail.com
parents e659b412 ab4bec16
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NVKM_FIRMWARE_H__
#define __NVKM_FIRMWARE_H__

#include <core/device.h>

int nvkm_firmware_get(struct nvkm_device *device, const char *fwname,
		      const struct firmware **fw);

void nvkm_firmware_put(const struct firmware *fw);

#include <core/subdev.h>

int nvkm_firmware_get_version(const struct nvkm_subdev *, const char *fwname,
			      int min_version, int max_version,
			      const struct firmware **);
int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname,
		      const struct firmware **);
void nvkm_firmware_put(const struct firmware *);
#endif
+28 −5
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@

/**
 * nvkm_firmware_get - load firmware from the official nvidia/chip/ directory
 * @device	device that will use that firmware
 * @subdev	subdevice that will use that firmware
 * @fwname	name of firmware file to load
 * @fw		firmware structure to load to
 *
@@ -32,9 +32,11 @@
 * Firmware files released by NVIDIA will always follow this format.
 */
int
nvkm_firmware_get(struct nvkm_device *device, const char *fwname,
nvkm_firmware_get_version(const struct nvkm_subdev *subdev, const char *fwname,
			  int min_version, int max_version,
			  const struct firmware **fw)
{
	struct nvkm_device *device = subdev->device;
	char f[64];
	char cname[16];
	int i;
@@ -48,8 +50,29 @@ nvkm_firmware_get(struct nvkm_device *device, const char *fwname,
		cname[i] = tolower(cname[i]);
	}

	for (i = max_version; i >= min_version; i--) {
		if (i != 0)
			snprintf(f, sizeof(f), "nvidia/%s/%s-%d.bin", cname, fwname, i);
		else
			snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname);
	return request_firmware(fw, f, device->dev);

		if (!firmware_request_nowarn(fw, f, device->dev)) {
			nvkm_debug(subdev, "firmware \"%s\" loaded\n", f);
			return i;
		}

		nvkm_debug(subdev, "firmware \"%s\" unavailable\n", f);
	}

	nvkm_error(subdev, "failed to load firmware \"%s\"", fwname);
	return -ENOENT;
}

int
nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname,
		  const struct firmware **fw)
{
	return nvkm_firmware_get_version(subdev, fwname, 0, 0, fw);
}

/**
+1 −3
Original line number Diff line number Diff line
@@ -2115,12 +2115,10 @@ int
gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
		 struct gf100_gr_fuc *fuc)
{
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
	const struct firmware *fw;
	int ret;

	ret = nvkm_firmware_get(device, fwname, &fw);
	ret = nvkm_firmware_get(&gr->base.engine.subdev, fwname, &fw);
	if (ret) {
		ret = gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret);
		if (ret)
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ nvkm_acr_load_firmware(const struct nvkm_subdev *subdev, const char *name,
	void *blob;
	int ret;

	ret = nvkm_firmware_get(subdev->device, name, &fw);
	ret = nvkm_firmware_get(subdev, name, &fw);
	if (ret)
		return ERR_PTR(ret);
	if (fw->size < min_size) {
+41 −15
Original line number Diff line number Diff line
@@ -229,6 +229,8 @@ struct acr_r352_lsf_wpr_header {
struct ls_ucode_img_r352 {
	struct ls_ucode_img base;

	const struct acr_r352_lsf_func *func;

	struct acr_r352_lsf_wpr_header wpr_header;
	struct acr_r352_lsf_lsb_header lsb_header;
};
@@ -243,6 +245,7 @@ acr_r352_ls_ucode_img_load(const struct acr_r352 *acr,
			   enum nvkm_secboot_falcon falcon_id)
{
	const struct nvkm_subdev *subdev = acr->base.subdev;
	const struct acr_r352_ls_func *func = acr->func->ls_func[falcon_id];
	struct ls_ucode_img_r352 *img;
	int ret;

@@ -252,15 +255,16 @@ acr_r352_ls_ucode_img_load(const struct acr_r352 *acr,

	img->base.falcon_id = falcon_id;

	ret = acr->func->ls_func[falcon_id]->load(sb, &img->base);

	if (ret) {
	ret = func->load(sb, func->version_max, &img->base);
	if (ret < 0) {
		kfree(img->base.ucode_data);
		kfree(img->base.sig);
		kfree(img);
		return ERR_PTR(ret);
	}

	img->func = func->version[ret];

	/* Check that the signature size matches our expectations... */
	if (img->base.sig_size != sizeof(img->lsb_header.signature)) {
		nvkm_error(subdev, "invalid signature size for %s falcon!\n",
@@ -302,8 +306,7 @@ acr_r352_ls_img_fill_headers(struct acr_r352 *acr,
	struct acr_r352_lsf_wpr_header *whdr = &img->wpr_header;
	struct acr_r352_lsf_lsb_header *lhdr = &img->lsb_header;
	struct ls_ucode_img_desc *desc = &_img->ucode_desc;
	const struct acr_r352_ls_func *func =
					    acr->func->ls_func[_img->falcon_id];
	const struct acr_r352_lsf_func *func = img->func;

	/* Fill WPR header */
	whdr->falcon_id = _img->falcon_id;
@@ -419,8 +422,8 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,

	/* Figure out how large we need gdesc to be. */
	list_for_each_entry(_img, imgs, node) {
		const struct acr_r352_ls_func *ls_func =
					    acr->func->ls_func[_img->falcon_id];
		struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
		const struct acr_r352_lsf_func *ls_func = img->func;

		max_desc_size = max(max_desc_size, ls_func->bl_desc_size);
	}
@@ -433,8 +436,7 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,

	list_for_each_entry(_img, imgs, node) {
		struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
		const struct acr_r352_ls_func *ls_func =
					    acr->func->ls_func[_img->falcon_id];
		const struct acr_r352_lsf_func *ls_func = img->func;

		nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
				      sizeof(img->wpr_header));
@@ -1063,20 +1065,36 @@ acr_r352_dtor(struct nvkm_acr *_acr)
	kfree(acr);
}

static const struct acr_r352_lsf_func
acr_r352_ls_fecs_func_0 = {
	.generate_bl_desc = acr_r352_generate_flcn_bl_desc,
	.bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
};

const struct acr_r352_ls_func
acr_r352_ls_fecs_func = {
	.load = acr_ls_ucode_load_fecs,
	.version_max = 0,
	.version = {
		&acr_r352_ls_fecs_func_0,
	}
};

static const struct acr_r352_lsf_func
acr_r352_ls_gpccs_func_0 = {
	.generate_bl_desc = acr_r352_generate_flcn_bl_desc,
	.bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
	/* GPCCS will be loaded using PRI */
	.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD,
};

const struct acr_r352_ls_func
acr_r352_ls_gpccs_func = {
	.load = acr_ls_ucode_load_gpccs,
	.generate_bl_desc = acr_r352_generate_flcn_bl_desc,
	.bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
	/* GPCCS will be loaded using PRI */
	.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD,
	.version_max = 0,
	.version = {
		&acr_r352_ls_gpccs_func_0,
	}
};


@@ -1150,12 +1168,20 @@ acr_r352_generate_pmu_bl_desc(const struct nvkm_acr *acr,
	desc->argv = addr_args;
}

static const struct acr_r352_lsf_func
acr_r352_ls_pmu_func_0 = {
	.generate_bl_desc = acr_r352_generate_pmu_bl_desc,
	.bl_desc_size = sizeof(struct acr_r352_pmu_bl_desc),
};

static const struct acr_r352_ls_func
acr_r352_ls_pmu_func = {
	.load = acr_ls_ucode_load_pmu,
	.generate_bl_desc = acr_r352_generate_pmu_bl_desc,
	.bl_desc_size = sizeof(struct acr_r352_pmu_bl_desc),
	.post_run = acr_ls_pmu_post_run,
	.version_max = 0,
	.version = {
		&acr_r352_ls_pmu_func_0,
	}
};

const struct acr_r352_func
Loading