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

Commit 598a8148 authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Ben Skeggs
Browse files

drm/nouveau/secboot: allow to boot multiple falcons



Change the secboot and msgqueue interfaces to take a mask of falcons to
reset instead of a single falcon. The GP10B firmware interface requires
FECS and GPCCS to be booted in a single firmware command.

For firmwares that only support single falcon boot, it is trivial to
loop over the mask and boot each falcons individually.

Signed-off-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent e5ffa727
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -41,7 +41,6 @@ int nvkm_msgqueue_reinit(struct nvkm_msgqueue *);
void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *);
void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *);


/* interface to ACR unit running on falcon (NVIDIA signed firmware) */
/* interface to ACR unit running on falcon (NVIDIA signed firmware) */
int nvkm_msgqueue_acr_boot_falcon(struct nvkm_msgqueue *,
int nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *, unsigned long);
				  enum nvkm_secboot_falcon);


#endif
#endif
+1 −1
Original line number Original line Diff line number Diff line
@@ -55,7 +55,7 @@ struct nvkm_secboot {
#define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev)
#define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev)


bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_secboot_falcon);
bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_secboot_falcon);
int nvkm_secboot_reset(struct nvkm_secboot *, enum nvkm_secboot_falcon);
int nvkm_secboot_reset(struct nvkm_secboot *, unsigned long);


int gm200_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **);
int gm200_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **);
int gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **);
int gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **);
+9 −7
Original line number Original line Diff line number Diff line
@@ -1463,25 +1463,27 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_device *device = subdev->device;
	struct nvkm_secboot *sb = device->secboot;
	struct nvkm_secboot *sb = device->secboot;
	int ret = 0;
	u32 secboot_mask = 0;


	/* load fuc microcode */
	/* load fuc microcode */
	nvkm_mc_unk260(device, 0);
	nvkm_mc_unk260(device, 0);


	/* securely-managed falcons must be reset using secure boot */
	/* securely-managed falcons must be reset using secure boot */
	if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
	if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
		ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS);
		secboot_mask |= BIT(NVKM_SECBOOT_FALCON_FECS);
	else
	else
		gf100_gr_init_fw(gr->fecs, &gr->fuc409c, &gr->fuc409d);
		gf100_gr_init_fw(gr->fecs, &gr->fuc409c, &gr->fuc409d);
	if (ret)
		return ret;


	if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS))
	if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS))
		ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS);
		secboot_mask |= BIT(NVKM_SECBOOT_FALCON_GPCCS);
	else
	else
		gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad);
		gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad);

	if (secboot_mask != 0) {
		int ret = nvkm_secboot_reset(sb, secboot_mask);
		if (ret)
		if (ret)
			return ret;
			return ret;
	}


	nvkm_mc_unk260(device, 1);
	nvkm_mc_unk260(device, 1);


+22 −3
Original line number Original line Diff line number Diff line
@@ -463,12 +463,31 @@ nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, void *buf)
}
}


int
int
nvkm_msgqueue_acr_boot_falcon(struct nvkm_msgqueue *queue, enum nvkm_secboot_falcon falcon)
nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *queue,
			       unsigned long falcon_mask)
{
{
	if (!queue || !queue->func->acr_func || !queue->func->acr_func->boot_falcon)
	unsigned long falcon;

	if (!queue || !queue->func->acr_func)
		return -ENODEV;
		return -ENODEV;


	return queue->func->acr_func->boot_falcon(queue, falcon);
	/* Does the firmware support booting multiple falcons? */
	if (queue->func->acr_func->boot_multiple_falcons)
		return queue->func->acr_func->boot_multiple_falcons(queue,
								   falcon_mask);

	/* Else boot all requested falcons individually */
	if (!queue->func->acr_func->boot_falcon)
		return -ENODEV;

	for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END) {
		int ret = queue->func->acr_func->boot_falcon(queue, falcon);

		if (ret)
			return ret;
	}

	return 0;
}
}


int
int
+2 −0
Original line number Original line Diff line number Diff line
@@ -101,9 +101,11 @@ struct nvkm_msgqueue_init_func {
 * struct nvkm_msgqueue_acr_func - msgqueue functions related to ACR
 * struct nvkm_msgqueue_acr_func - msgqueue functions related to ACR
 *
 *
 * @boot_falcon:	build and send the command to reset a given falcon
 * @boot_falcon:	build and send the command to reset a given falcon
 * @boot_multiple_falcons: build and send the command to reset several falcons
 */
 */
struct nvkm_msgqueue_acr_func {
struct nvkm_msgqueue_acr_func {
	int (*boot_falcon)(struct nvkm_msgqueue *, enum nvkm_secboot_falcon);
	int (*boot_falcon)(struct nvkm_msgqueue *, enum nvkm_secboot_falcon);
	int (*boot_multiple_falcons)(struct nvkm_msgqueue *, unsigned long);
};
};


struct nvkm_msgqueue_func {
struct nvkm_msgqueue_func {
Loading