mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-20 02:34:23 +08:00
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: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
e5ffa727e5
commit
598a8148e7
@ -41,7 +41,6 @@ int nvkm_msgqueue_reinit(struct nvkm_msgqueue *);
|
||||
void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *);
|
||||
|
||||
/* interface to ACR unit running on falcon (NVIDIA signed firmware) */
|
||||
int nvkm_msgqueue_acr_boot_falcon(struct nvkm_msgqueue *,
|
||||
enum nvkm_secboot_falcon);
|
||||
int nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *, unsigned long);
|
||||
|
||||
#endif
|
||||
|
@ -55,7 +55,7 @@ struct nvkm_secboot {
|
||||
#define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev)
|
||||
|
||||
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 gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **);
|
||||
|
@ -1463,25 +1463,27 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
|
||||
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
|
||||
struct nvkm_device *device = subdev->device;
|
||||
struct nvkm_secboot *sb = device->secboot;
|
||||
int ret = 0;
|
||||
u32 secboot_mask = 0;
|
||||
|
||||
/* load fuc microcode */
|
||||
nvkm_mc_unk260(device, 0);
|
||||
|
||||
/* securely-managed falcons must be reset using secure boot */
|
||||
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
|
||||
gf100_gr_init_fw(gr->fecs, &gr->fuc409c, &gr->fuc409d);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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
|
||||
gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (secboot_mask != 0) {
|
||||
int ret = nvkm_secboot_reset(sb, secboot_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nvkm_mc_unk260(device, 1);
|
||||
|
||||
|
@ -463,12 +463,31 @@ nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, void *buf)
|
||||
}
|
||||
|
||||
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 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
|
||||
|
@ -101,9 +101,11 @@ struct nvkm_msgqueue_init_func {
|
||||
* struct nvkm_msgqueue_acr_func - msgqueue functions related to ACR
|
||||
*
|
||||
* @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 {
|
||||
int (*boot_falcon)(struct nvkm_msgqueue *, enum nvkm_secboot_falcon);
|
||||
int (*boot_multiple_falcons)(struct nvkm_msgqueue *, unsigned long);
|
||||
};
|
||||
|
||||
struct nvkm_msgqueue_func {
|
||||
|
@ -39,8 +39,7 @@ struct nvkm_acr_func {
|
||||
int (*fini)(struct nvkm_acr *, struct nvkm_secboot *, bool);
|
||||
int (*load)(struct nvkm_acr *, struct nvkm_falcon *,
|
||||
struct nvkm_gpuobj *, u64);
|
||||
int (*reset)(struct nvkm_acr *, struct nvkm_secboot *,
|
||||
enum nvkm_secboot_falcon);
|
||||
int (*reset)(struct nvkm_acr *, struct nvkm_secboot *, unsigned long);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -976,15 +976,16 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb)
|
||||
*/
|
||||
static int
|
||||
acr_r352_reset_nopmu(struct acr_r352 *acr, struct nvkm_secboot *sb,
|
||||
enum nvkm_secboot_falcon falcon)
|
||||
unsigned long falcon_mask)
|
||||
{
|
||||
int falcon;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Perform secure boot each time we are called on FECS. Since only FECS
|
||||
* and GPCCS are managed and started together, this ought to be safe.
|
||||
*/
|
||||
if (falcon != NVKM_SECBOOT_FALCON_FECS)
|
||||
if (!(falcon_mask & BIT(NVKM_SECBOOT_FALCON_FECS)))
|
||||
goto end;
|
||||
|
||||
ret = acr_r352_shutdown(acr, sb);
|
||||
@ -996,7 +997,9 @@ acr_r352_reset_nopmu(struct acr_r352 *acr, struct nvkm_secboot *sb,
|
||||
return ret;
|
||||
|
||||
end:
|
||||
acr->falcon_state[falcon] = RESET;
|
||||
for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END) {
|
||||
acr->falcon_state[falcon] = RESET;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1009,11 +1012,11 @@ end:
|
||||
*/
|
||||
static int
|
||||
acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
|
||||
enum nvkm_secboot_falcon falcon)
|
||||
unsigned long falcon_mask)
|
||||
{
|
||||
struct acr_r352 *acr = acr_r352(_acr);
|
||||
struct nvkm_msgqueue *queue;
|
||||
const char *fname = nvkm_secboot_falcon_name[falcon];
|
||||
int falcon;
|
||||
bool wpr_already_set = sb->wpr_set;
|
||||
int ret;
|
||||
|
||||
@ -1026,7 +1029,7 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
|
||||
if (!nvkm_secboot_is_managed(sb, _acr->boot_falcon)) {
|
||||
/* Redo secure boot entirely if it was already done */
|
||||
if (wpr_already_set)
|
||||
return acr_r352_reset_nopmu(acr, sb, falcon);
|
||||
return acr_r352_reset_nopmu(acr, sb, falcon_mask);
|
||||
/* Else return the result of the initial invokation */
|
||||
else
|
||||
return ret;
|
||||
@ -1044,13 +1047,15 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
|
||||
}
|
||||
|
||||
/* Otherwise just ask the LS firmware to reset the falcon */
|
||||
nvkm_debug(&sb->subdev, "resetting %s falcon\n", fname);
|
||||
ret = nvkm_msgqueue_acr_boot_falcon(queue, falcon);
|
||||
for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END)
|
||||
nvkm_debug(&sb->subdev, "resetting %s falcon\n",
|
||||
nvkm_secboot_falcon_name[falcon]);
|
||||
ret = nvkm_msgqueue_acr_boot_falcons(queue, falcon_mask);
|
||||
if (ret) {
|
||||
nvkm_error(&sb->subdev, "cannot boot %s falcon\n", fname);
|
||||
nvkm_error(&sb->subdev, "error during falcon reset: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
nvkm_debug(&sb->subdev, "falcon %s reset\n", fname);
|
||||
nvkm_debug(&sb->subdev, "falcon reset done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -102,15 +102,15 @@ nvkm_secboot_falcon_name[] = {
|
||||
* nvkm_secboot_reset() - reset specified falcon
|
||||
*/
|
||||
int
|
||||
nvkm_secboot_reset(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon)
|
||||
nvkm_secboot_reset(struct nvkm_secboot *sb, unsigned long falcon_mask)
|
||||
{
|
||||
/* Unmanaged falcon? */
|
||||
if (!(BIT(falcon) & sb->acr->managed_falcons)) {
|
||||
if ((falcon_mask | sb->acr->managed_falcons) != sb->acr->managed_falcons) {
|
||||
nvkm_error(&sb->subdev, "cannot reset unmanaged falcon!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return sb->acr->func->reset(sb->acr, sb, falcon);
|
||||
return sb->acr->func->reset(sb->acr, sb, falcon_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user