drm/nouveau/flcn/cmdq: move command generation to subdevs
This moves the code to generate commands for the ACR unit of the PMU/SEC2 LS firmwares to those subdevs. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
25fd061cc7
commit
86ce2a7153
|
@ -0,0 +1,47 @@
|
|||
#ifndef __NVFW_PMU_H__
|
||||
#define __NVFW_PMU_H__
|
||||
|
||||
#define NV_PMU_UNIT_ACR 0x0a
|
||||
|
||||
struct nv_pmu_acr_cmd {
|
||||
struct nv_falcon_cmd hdr;
|
||||
#define NV_PMU_ACR_CMD_INIT_WPR_REGION 0x00
|
||||
#define NV_PMU_ACR_CMD_BOOTSTRAP_FALCON 0x01
|
||||
#define NV_PMU_ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS 0x03
|
||||
u8 cmd_type;
|
||||
};
|
||||
|
||||
struct nv_pmu_acr_msg {
|
||||
struct nv_falcon_cmd hdr;
|
||||
u8 msg_type;
|
||||
};
|
||||
|
||||
struct nv_pmu_acr_bootstrap_falcon_cmd {
|
||||
struct nv_pmu_acr_cmd cmd;
|
||||
#define NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000
|
||||
#define NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO 0x00000001
|
||||
u32 flags;
|
||||
u32 falcon_id;
|
||||
};
|
||||
|
||||
struct nv_pmu_acr_bootstrap_falcon_msg {
|
||||
struct nv_pmu_acr_msg msg;
|
||||
u32 falcon_id;
|
||||
};
|
||||
|
||||
struct nv_pmu_acr_bootstrap_multiple_falcons_cmd {
|
||||
struct nv_pmu_acr_cmd cmd;
|
||||
#define NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_YES 0x00000000
|
||||
#define NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_NO 0x00000001
|
||||
u32 flags;
|
||||
u32 falcon_mask;
|
||||
u32 use_va_mask;
|
||||
u32 wpr_lo;
|
||||
u32 wpr_hi;
|
||||
};
|
||||
|
||||
struct nv_pmu_acr_bootstrap_multiple_falcons_msg {
|
||||
struct nv_pmu_acr_msg msg;
|
||||
u32 falcon_mask;
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef __NVFW_SEC2_H__
|
||||
#define __NVFW_SEC2_H__
|
||||
|
||||
#define NV_SEC2_UNIT_ACR 0x08
|
||||
|
||||
struct nv_sec2_acr_cmd {
|
||||
struct nv_falcon_cmd hdr;
|
||||
#define NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON 0x00
|
||||
u8 cmd_type;
|
||||
};
|
||||
|
||||
struct nv_sec2_acr_msg {
|
||||
struct nv_falcon_cmd hdr;
|
||||
u8 msg_type;
|
||||
};
|
||||
|
||||
struct nv_sec2_acr_bootstrap_falcon_cmd {
|
||||
struct nv_sec2_acr_cmd cmd;
|
||||
#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000
|
||||
#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO 0x00000001
|
||||
u32 flags;
|
||||
u32 falcon_id;
|
||||
};
|
||||
|
||||
struct nv_sec2_acr_bootstrap_falcon_msg {
|
||||
struct nv_sec2_acr_msg msg;
|
||||
u32 error_code;
|
||||
u32 falcon_id;
|
||||
};
|
||||
#endif
|
|
@ -37,7 +37,4 @@ int nvkm_msgqueue_reinit(struct nvkm_msgqueue *);
|
|||
/* useful if we run a NVIDIA-signed firmware */
|
||||
void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *);
|
||||
|
||||
/* interface to ACR unit running on falcon (NVIDIA signed firmware) */
|
||||
int nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *, unsigned long);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,15 +13,34 @@ enum nvkm_acr_lsf_id {
|
|||
NVKM_ACR_LSF_NVDEC = 4,
|
||||
NVKM_ACR_LSF_SEC2 = 7,
|
||||
NVKM_ACR_LSF_MINION = 10,
|
||||
NVKM_ACR_LSF_NUM
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
nvkm_acr_lsf_id(enum nvkm_acr_lsf_id id)
|
||||
{
|
||||
switch (id) {
|
||||
case NVKM_ACR_LSF_PMU : return "pmu";
|
||||
case NVKM_ACR_LSF_GSPLITE: return "gsplite";
|
||||
case NVKM_ACR_LSF_FECS : return "fecs";
|
||||
case NVKM_ACR_LSF_GPCCS : return "gpccs";
|
||||
case NVKM_ACR_LSF_NVDEC : return "nvdec";
|
||||
case NVKM_ACR_LSF_SEC2 : return "sec2";
|
||||
case NVKM_ACR_LSF_MINION : return "minion";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
struct nvkm_acr {
|
||||
const struct nvkm_acr_func *func;
|
||||
struct nvkm_subdev subdev;
|
||||
|
||||
struct list_head lsfw;
|
||||
struct list_head lsfw, lsf;
|
||||
};
|
||||
|
||||
int nvkm_acr_bootstrap_falcons(struct nvkm_device *, unsigned long mask);
|
||||
|
||||
int gm200_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
|
||||
int gm20b_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
|
||||
int gp102_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
|
||||
|
@ -55,6 +74,8 @@ struct nvkm_acr_lsfw {
|
|||
};
|
||||
|
||||
struct nvkm_acr_lsf_func {
|
||||
int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
|
||||
int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask);
|
||||
};
|
||||
|
||||
int
|
||||
|
|
|
@ -20,11 +20,53 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "priv.h"
|
||||
|
||||
#include <subdev/acr.h>
|
||||
#include <subdev/timer.h>
|
||||
|
||||
#include <nvfw/sec2.h>
|
||||
|
||||
static int
|
||||
gp102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nv_falcon_msg *hdr)
|
||||
{
|
||||
struct nv_sec2_acr_bootstrap_falcon_msg *msg =
|
||||
container_of(hdr, typeof(*msg), msg.hdr);
|
||||
struct nvkm_subdev *subdev = priv;
|
||||
const char *name = nvkm_acr_lsf_id(msg->falcon_id);
|
||||
|
||||
if (msg->error_code) {
|
||||
nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for "
|
||||
"falcon %d [%s]: %08x\n",
|
||||
msg->falcon_id, name, msg->error_code);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nvkm_debug(subdev, "%s booted\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
|
||||
enum nvkm_acr_lsf_id id)
|
||||
{
|
||||
struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon);
|
||||
struct nv_sec2_acr_bootstrap_falcon_cmd cmd = {
|
||||
.cmd.hdr.unit_id = sec2->func->unit_acr,
|
||||
.cmd.hdr.size = sizeof(cmd),
|
||||
.cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON,
|
||||
.flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES,
|
||||
.falcon_id = id,
|
||||
};
|
||||
|
||||
return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr,
|
||||
gp102_sec2_acr_bootstrap_falcon_callback,
|
||||
&sec2->engine.subdev,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static const struct nvkm_acr_lsf_func
|
||||
gp102_sec2_acr_0 = {
|
||||
.bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -117,6 +159,7 @@ gp102_sec2_flcn = {
|
|||
const struct nvkm_sec2_func
|
||||
gp102_sec2 = {
|
||||
.flcn = &gp102_sec2_flcn,
|
||||
.unit_acr = NV_SEC2_UNIT_ACR,
|
||||
.intr = gp102_sec2_intr,
|
||||
};
|
||||
|
||||
|
@ -135,6 +178,7 @@ MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
|
|||
|
||||
const struct nvkm_acr_lsf_func
|
||||
gp102_sec2_acr_1 = {
|
||||
.bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
|
||||
};
|
||||
|
||||
int
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
struct nvkm_sec2_func {
|
||||
const struct nvkm_falcon_func *flcn;
|
||||
u8 unit_acr;
|
||||
void (*intr)(struct nvkm_sec2 *);
|
||||
};
|
||||
|
||||
|
|
|
@ -35,34 +35,6 @@ nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, void *buf)
|
|||
queue->func->init_func->gen_cmdline(queue, buf);
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *queue,
|
||||
unsigned long falcon_mask)
|
||||
{
|
||||
unsigned long falcon;
|
||||
|
||||
if (!queue || !queue->func->acr_func)
|
||||
return -ENODEV;
|
||||
|
||||
/* 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
|
||||
nvkm_msgqueue_new(u32 version, struct nvkm_falcon *falcon,
|
||||
const struct nvkm_secboot *sb, struct nvkm_msgqueue **queue)
|
||||
|
|
|
@ -90,20 +90,8 @@ struct nvkm_msgqueue_init_func {
|
|||
int (*init_callback)(struct nvkm_msgqueue *, struct nvkm_msgqueue_hdr *);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
const struct nvkm_msgqueue_init_func *init_func;
|
||||
const struct nvkm_msgqueue_acr_func *acr_func;
|
||||
void (*dtor)(struct nvkm_msgqueue *);
|
||||
void (*recv)(struct nvkm_msgqueue *queue);
|
||||
};
|
||||
|
|
|
@ -147,8 +147,6 @@ msgqueue_0137c63d_init_func = {
|
|||
|
||||
enum {
|
||||
ACR_CMD_INIT_WPR_REGION = 0x00,
|
||||
ACR_CMD_BOOTSTRAP_FALCON = 0x01,
|
||||
ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS = 0x03,
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -198,144 +196,6 @@ acr_init_wpr(struct nvkm_msgqueue *queue)
|
|||
pmu, 0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
acr_boot_falcon_callback(void *priv, struct nv_falcon_msg *hdr)
|
||||
{
|
||||
struct acr_bootstrap_falcon_msg {
|
||||
struct nv_falcon_msg base;
|
||||
u8 msg_type;
|
||||
u32 falcon_id;
|
||||
} *msg = (void *)hdr;
|
||||
struct nvkm_subdev *subdev = priv;
|
||||
u32 falcon_id = msg->falcon_id;
|
||||
|
||||
if (falcon_id >= NVKM_SECBOOT_FALCON_END) {
|
||||
nvkm_error(subdev, "in bootstrap falcon callback:\n");
|
||||
nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES = 0,
|
||||
ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_NO = 1,
|
||||
};
|
||||
|
||||
static int
|
||||
acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon)
|
||||
{
|
||||
struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu;
|
||||
/*
|
||||
* flags - Flag specifying RESET or no RESET.
|
||||
* falcon id - Falcon id specifying falcon to bootstrap.
|
||||
*/
|
||||
struct {
|
||||
struct nv_falcon_cmd hdr;
|
||||
u8 cmd_type;
|
||||
u32 flags;
|
||||
u32 falcon_id;
|
||||
} cmd;
|
||||
|
||||
if (!wait_for_completion_timeout(&pmu->wpr_ready,
|
||||
msecs_to_jiffies(1000))) {
|
||||
nvkm_error(&pmu->subdev, "timeout waiting for WPR init\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR;
|
||||
cmd.hdr.size = sizeof(cmd);
|
||||
cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON;
|
||||
cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
|
||||
cmd.falcon_id = falcon;
|
||||
return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr,
|
||||
acr_boot_falcon_callback, &pmu->subdev,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static int
|
||||
acr_boot_multiple_falcons_callback(void *priv, struct nv_falcon_msg *hdr)
|
||||
{
|
||||
struct acr_bootstrap_falcon_msg {
|
||||
struct nv_falcon_msg base;
|
||||
u8 msg_type;
|
||||
u32 falcon_mask;
|
||||
} *msg = (void *)hdr;
|
||||
const struct nvkm_subdev *subdev = priv;
|
||||
unsigned long falcon_mask = msg->falcon_mask;
|
||||
u32 falcon_id, falcon_treated = 0;
|
||||
|
||||
for_each_set_bit(falcon_id, &falcon_mask, NVKM_SECBOOT_FALCON_END) {
|
||||
nvkm_debug(subdev, "%s booted\n",
|
||||
nvkm_secboot_falcon_name[falcon_id]);
|
||||
falcon_treated |= BIT(falcon_id);
|
||||
}
|
||||
|
||||
if (falcon_treated != msg->falcon_mask) {
|
||||
nvkm_error(subdev, "in bootstrap falcon callback:\n");
|
||||
nvkm_error(subdev, "invalid falcon mask 0x%x\n",
|
||||
msg->falcon_mask);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask)
|
||||
{
|
||||
struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu;
|
||||
/*
|
||||
* flags - Flag specifying RESET or no RESET.
|
||||
* falcon id - Falcon id specifying falcon to bootstrap.
|
||||
*/
|
||||
struct {
|
||||
struct nv_falcon_cmd hdr;
|
||||
u8 cmd_type;
|
||||
u32 flags;
|
||||
u32 falcon_mask;
|
||||
u32 use_va_mask;
|
||||
u32 wpr_lo;
|
||||
u32 wpr_hi;
|
||||
} cmd;
|
||||
struct msgqueue_0137bca5 *queue = msgqueue_0137bca5(priv);
|
||||
|
||||
if (!wait_for_completion_timeout(&pmu->wpr_ready,
|
||||
msecs_to_jiffies(1000))) {
|
||||
nvkm_error(&pmu->subdev, "timeout waiting for WPR init\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR;
|
||||
cmd.hdr.size = sizeof(cmd);
|
||||
cmd.cmd_type = ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS;
|
||||
cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
|
||||
cmd.falcon_mask = falcon_mask;
|
||||
cmd.wpr_lo = lower_32_bits(queue->wpr_addr);
|
||||
cmd.wpr_hi = upper_32_bits(queue->wpr_addr);
|
||||
return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr,
|
||||
acr_boot_multiple_falcons_callback,
|
||||
&pmu->subdev, msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static const struct nvkm_msgqueue_acr_func
|
||||
msgqueue_0137c63d_acr_func = {
|
||||
.boot_falcon = acr_boot_falcon,
|
||||
};
|
||||
|
||||
static const struct nvkm_msgqueue_acr_func
|
||||
msgqueue_0137bca5_acr_func = {
|
||||
.boot_falcon = acr_boot_falcon,
|
||||
.boot_multiple_falcons = acr_boot_multiple_falcons,
|
||||
};
|
||||
|
||||
static void
|
||||
msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
|
||||
{
|
||||
|
@ -345,7 +205,6 @@ msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
|
|||
static const struct nvkm_msgqueue_func
|
||||
msgqueue_0137c63d_func = {
|
||||
.init_func = &msgqueue_0137c63d_init_func,
|
||||
.acr_func = &msgqueue_0137c63d_acr_func,
|
||||
.recv = msgqueue_0137c63d_process_msgs,
|
||||
.dtor = msgqueue_0137c63d_dtor,
|
||||
};
|
||||
|
@ -370,7 +229,6 @@ msgqueue_0137c63d_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
|
|||
static const struct nvkm_msgqueue_func
|
||||
msgqueue_0137bca5_func = {
|
||||
.init_func = &msgqueue_0137c63d_init_func,
|
||||
.acr_func = &msgqueue_0137bca5_acr_func,
|
||||
.recv = msgqueue_0137c63d_process_msgs,
|
||||
.dtor = msgqueue_0137c63d_dtor,
|
||||
};
|
||||
|
|
|
@ -130,81 +130,6 @@ msgqueue_0148cdec_init_func = {
|
|||
};
|
||||
|
||||
|
||||
|
||||
/* ACR unit */
|
||||
#define MSGQUEUE_0148CDEC_UNIT_ACR 0x08
|
||||
|
||||
enum {
|
||||
ACR_CMD_BOOTSTRAP_FALCON = 0x00,
|
||||
};
|
||||
|
||||
static int
|
||||
acr_boot_falcon_callback(void *priv, struct nv_falcon_msg *hdr)
|
||||
{
|
||||
struct acr_bootstrap_falcon_msg {
|
||||
struct nv_falcon_msg base;
|
||||
u8 msg_type;
|
||||
u32 error_code;
|
||||
u32 falcon_id;
|
||||
} *msg = (void *)hdr;
|
||||
const struct nvkm_subdev *subdev = priv;
|
||||
u32 falcon_id = msg->falcon_id;
|
||||
|
||||
if (msg->error_code) {
|
||||
nvkm_error(subdev, "in bootstrap falcon callback:\n");
|
||||
nvkm_error(subdev, "expected error code 0x%x\n",
|
||||
msg->error_code);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (falcon_id >= NVKM_SECBOOT_FALCON_END) {
|
||||
nvkm_error(subdev, "in bootstrap falcon callback:\n");
|
||||
nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES = 0,
|
||||
ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_NO = 1,
|
||||
};
|
||||
|
||||
static int
|
||||
acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon)
|
||||
{
|
||||
struct nvkm_sec2 *sec2 = priv->falcon->owner->device->sec2;
|
||||
/*
|
||||
* flags - Flag specifying RESET or no RESET.
|
||||
* falcon id - Falcon id specifying falcon to bootstrap.
|
||||
*/
|
||||
struct {
|
||||
struct nv_falcon_cmd hdr;
|
||||
u8 cmd_type;
|
||||
u32 flags;
|
||||
u32 falcon_id;
|
||||
} cmd;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.hdr.unit_id = MSGQUEUE_0148CDEC_UNIT_ACR;
|
||||
cmd.hdr.size = sizeof(cmd);
|
||||
cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON;
|
||||
cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
|
||||
cmd.falcon_id = falcon;
|
||||
return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.hdr,
|
||||
acr_boot_falcon_callback,
|
||||
&sec2->engine.subdev,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
const struct nvkm_msgqueue_acr_func
|
||||
msgqueue_0148cdec_acr_func = {
|
||||
.boot_falcon = acr_boot_falcon,
|
||||
};
|
||||
|
||||
static void
|
||||
msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue)
|
||||
{
|
||||
|
@ -214,7 +139,6 @@ msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue)
|
|||
const struct nvkm_msgqueue_func
|
||||
msgqueue_0148cdec_func = {
|
||||
.init_func = &msgqueue_0148cdec_init_func,
|
||||
.acr_func = &msgqueue_0148cdec_acr_func,
|
||||
.recv = msgqueue_0148cdec_process_msgs,
|
||||
.dtor = msgqueue_0148cdec_dtor,
|
||||
};
|
||||
|
|
|
@ -23,19 +23,90 @@
|
|||
|
||||
#include <core/firmware.h>
|
||||
|
||||
static struct nvkm_acr_lsf *
|
||||
nvkm_acr_falcon(struct nvkm_device *device)
|
||||
{
|
||||
struct nvkm_acr *acr = device->acr;
|
||||
struct nvkm_acr_lsf *lsf;
|
||||
|
||||
if (acr) {
|
||||
list_for_each_entry(lsf, &acr->lsf, head) {
|
||||
if (lsf->func->bootstrap_falcon)
|
||||
return lsf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask)
|
||||
{
|
||||
struct nvkm_acr_lsf *acrflcn = nvkm_acr_falcon(device);
|
||||
unsigned long id;
|
||||
|
||||
if (!acrflcn)
|
||||
return -ENOSYS;
|
||||
|
||||
if (acrflcn->func->bootstrap_multiple_falcons) {
|
||||
return acrflcn->func->
|
||||
bootstrap_multiple_falcons(acrflcn->falcon, mask);
|
||||
}
|
||||
|
||||
for_each_set_bit(id, &mask, NVKM_ACR_LSF_NUM) {
|
||||
int ret = acrflcn->func->bootstrap_falcon(acrflcn->falcon, id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvkm_acr_cleanup(struct nvkm_acr *acr)
|
||||
{
|
||||
nvkm_acr_lsfw_del_all(acr);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_acr_oneinit(struct nvkm_subdev *subdev)
|
||||
{
|
||||
struct nvkm_acr *acr = nvkm_acr(subdev);
|
||||
struct nvkm_acr_lsfw *lsfw;
|
||||
struct nvkm_acr_lsf *lsf;
|
||||
|
||||
list_for_each_entry(lsfw, &acr->lsfw, head) {
|
||||
if (!(lsf = kmalloc(sizeof(*lsf), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
lsf->func = lsfw->func;
|
||||
lsf->falcon = lsfw->falcon;
|
||||
lsf->id = lsfw->id;
|
||||
list_add_tail(&lsf->head, &acr->lsf);
|
||||
}
|
||||
|
||||
nvkm_acr_cleanup(acr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
nvkm_acr_dtor(struct nvkm_subdev *subdev)
|
||||
{
|
||||
struct nvkm_acr *acr = nvkm_acr(subdev);
|
||||
struct nvkm_acr_lsf *lsf, *lst;
|
||||
|
||||
nvkm_acr_lsfw_del_all(acr);
|
||||
list_for_each_entry_safe(lsf, lst, &acr->lsf, head) {
|
||||
list_del(&lsf->head);
|
||||
kfree(lsf);
|
||||
}
|
||||
|
||||
nvkm_acr_cleanup(acr);
|
||||
return acr;
|
||||
}
|
||||
|
||||
static const struct nvkm_subdev_func
|
||||
nvkm_acr = {
|
||||
.dtor = nvkm_acr_dtor,
|
||||
.oneinit = nvkm_acr_oneinit,
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -48,6 +119,7 @@ nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device,
|
|||
return -ENOMEM;
|
||||
nvkm_subdev_ctor(&nvkm_acr, device, index, &acr->subdev);
|
||||
INIT_LIST_HEAD(&acr->lsfw);
|
||||
INIT_LIST_HEAD(&acr->lsf);
|
||||
|
||||
fwif = nvkm_firmware_load(&acr->subdev, fwif, "Acr", acr);
|
||||
if (IS_ERR(fwif))
|
||||
|
|
|
@ -18,6 +18,13 @@ struct nvkm_acr_func {
|
|||
int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, int,
|
||||
struct nvkm_acr **);
|
||||
|
||||
struct nvkm_acr_lsf {
|
||||
const struct nvkm_acr_lsf_func *func;
|
||||
struct nvkm_falcon *falcon;
|
||||
enum nvkm_acr_lsf_id id;
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
struct nvkm_acr_lsfw *nvkm_acr_lsfw_add(const struct nvkm_acr_lsf_func *,
|
||||
struct nvkm_acr *, struct nvkm_falcon *,
|
||||
enum nvkm_acr_lsf_id);
|
||||
|
|
|
@ -20,11 +20,45 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "priv.h"
|
||||
|
||||
#include <core/msgqueue.h>
|
||||
#include <subdev/acr.h>
|
||||
|
||||
#include <nvfw/pmu.h>
|
||||
|
||||
static int
|
||||
gm20b_pmu_acr_bootstrap_falcon_cb(void *priv, struct nv_falcon_msg *hdr)
|
||||
{
|
||||
struct nv_pmu_acr_bootstrap_falcon_msg *msg =
|
||||
container_of(hdr, typeof(*msg), msg.hdr);
|
||||
return msg->falcon_id;
|
||||
}
|
||||
|
||||
int
|
||||
gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
|
||||
enum nvkm_acr_lsf_id id)
|
||||
{
|
||||
struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon);
|
||||
struct nv_pmu_acr_bootstrap_falcon_cmd cmd = {
|
||||
.cmd.hdr.unit_id = NV_PMU_UNIT_ACR,
|
||||
.cmd.hdr.size = sizeof(cmd),
|
||||
.cmd.cmd_type = NV_PMU_ACR_CMD_BOOTSTRAP_FALCON,
|
||||
.flags = NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES,
|
||||
.falcon_id = id,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr,
|
||||
gm20b_pmu_acr_bootstrap_falcon_cb,
|
||||
&pmu->subdev, msecs_to_jiffies(1000));
|
||||
if (ret >= 0 && ret != cmd.falcon_id)
|
||||
ret = -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct nvkm_acr_lsf_func
|
||||
gm20b_pmu_acr = {
|
||||
.bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
@ -20,10 +20,46 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "priv.h"
|
||||
|
||||
#include <subdev/acr.h>
|
||||
|
||||
#include <nvfw/pmu.h>
|
||||
|
||||
static int
|
||||
gp10b_pmu_acr_bootstrap_multiple_falcons_cb(void *priv,
|
||||
struct nv_falcon_msg *hdr)
|
||||
{
|
||||
struct nv_pmu_acr_bootstrap_multiple_falcons_msg *msg =
|
||||
container_of(hdr, typeof(*msg), msg.hdr);
|
||||
return msg->falcon_mask;
|
||||
}
|
||||
static int
|
||||
gp10b_pmu_acr_bootstrap_multiple_falcons(struct nvkm_falcon *falcon, u32 mask)
|
||||
{
|
||||
struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon);
|
||||
struct nv_pmu_acr_bootstrap_multiple_falcons_cmd cmd = {
|
||||
.cmd.hdr.unit_id = NV_PMU_UNIT_ACR,
|
||||
.cmd.hdr.size = sizeof(cmd),
|
||||
.cmd.cmd_type = NV_PMU_ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS,
|
||||
.flags = NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_YES,
|
||||
.falcon_mask = mask,
|
||||
.wpr_lo = 0, /*XXX*/
|
||||
.wpr_hi = 0, /*XXX*/
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr,
|
||||
gp10b_pmu_acr_bootstrap_multiple_falcons_cb,
|
||||
&pmu->subdev, msecs_to_jiffies(1000));
|
||||
if (ret >= 0 && ret != cmd.falcon_mask)
|
||||
ret = -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct nvkm_acr_lsf_func
|
||||
gp10b_pmu_acr = {
|
||||
.bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
|
||||
.bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons,
|
||||
};
|
||||
|
||||
static const struct nvkm_pmu_func
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define nvkm_pmu(p) container_of((p), struct nvkm_pmu, subdev)
|
||||
#include <subdev/pmu.h>
|
||||
#include <subdev/pmu/fuc/os.h>
|
||||
enum nvkm_acr_lsf_id;
|
||||
|
||||
struct nvkm_pmu_func {
|
||||
const struct nvkm_falcon_func *flcn;
|
||||
|
@ -41,6 +42,7 @@ void gf100_pmu_reset(struct nvkm_pmu *);
|
|||
|
||||
void gk110_pmu_pgob(struct nvkm_pmu *, bool);
|
||||
|
||||
int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
|
||||
void gm20b_pmu_recv(struct nvkm_pmu *);
|
||||
|
||||
struct nvkm_pmu_fwif {
|
||||
|
|
|
@ -991,12 +991,13 @@ end:
|
|||
* load the HS firmware and run it, so once the falcon stops all the managed
|
||||
* falcons should have their LS firmware loaded and be ready to run.
|
||||
*/
|
||||
int nvkm_acr_bootstrap_falcons(struct nvkm_device *, unsigned long);
|
||||
|
||||
static int
|
||||
acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
|
||||
unsigned long falcon_mask)
|
||||
{
|
||||
struct acr_r352 *acr = acr_r352(_acr);
|
||||
struct nvkm_msgqueue *queue;
|
||||
int falcon;
|
||||
bool wpr_already_set = sb->wpr_set;
|
||||
int ret;
|
||||
|
@ -1016,22 +1017,12 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
|
|||
return ret;
|
||||
}
|
||||
|
||||
switch (_acr->boot_falcon) {
|
||||
case NVKM_SECBOOT_FALCON_PMU:
|
||||
queue = sb->subdev.device->pmu->queue;
|
||||
break;
|
||||
case NVKM_SECBOOT_FALCON_SEC2:
|
||||
queue = sb->subdev.device->sec2->queue;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Otherwise just ask the LS firmware to reset the 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);
|
||||
|
||||
ret = nvkm_acr_bootstrap_falcons(sb->subdev.device, falcon_mask);
|
||||
if (ret) {
|
||||
nvkm_error(&sb->subdev, "error during falcon reset: %d\n", ret);
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue