|
@@ -43,6 +43,15 @@ struct msgqueue_0137c63d {
|
|
#define msgqueue_0137c63d(q) \
|
|
#define msgqueue_0137c63d(q) \
|
|
container_of(q, struct msgqueue_0137c63d, base)
|
|
container_of(q, struct msgqueue_0137c63d, base)
|
|
|
|
|
|
|
|
+struct msgqueue_0137bca5 {
|
|
|
|
+ struct msgqueue_0137c63d base;
|
|
|
|
+
|
|
|
|
+ u64 wpr_addr;
|
|
|
|
+};
|
|
|
|
+#define msgqueue_0137bca5(q) \
|
|
|
|
+ container_of(container_of(q, struct msgqueue_0137c63d, base), \
|
|
|
|
+ struct msgqueue_0137bca5, base);
|
|
|
|
+
|
|
static struct nvkm_msgqueue_queue *
|
|
static struct nvkm_msgqueue_queue *
|
|
msgqueue_0137c63d_cmd_queue(struct nvkm_msgqueue *queue,
|
|
msgqueue_0137c63d_cmd_queue(struct nvkm_msgqueue *queue,
|
|
enum msgqueue_msg_priority priority)
|
|
enum msgqueue_msg_priority priority)
|
|
@@ -180,6 +189,7 @@ msgqueue_0137c63d_init_func = {
|
|
enum {
|
|
enum {
|
|
ACR_CMD_INIT_WPR_REGION = 0x00,
|
|
ACR_CMD_INIT_WPR_REGION = 0x00,
|
|
ACR_CMD_BOOTSTRAP_FALCON = 0x01,
|
|
ACR_CMD_BOOTSTRAP_FALCON = 0x01,
|
|
|
|
+ ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS = 0x03,
|
|
};
|
|
};
|
|
|
|
|
|
static void
|
|
static void
|
|
@@ -286,11 +296,81 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+acr_boot_multiple_falcons_callback(struct nvkm_msgqueue *priv,
|
|
|
|
+ struct nvkm_msgqueue_hdr *hdr)
|
|
|
|
+{
|
|
|
|
+ struct acr_bootstrap_falcon_msg {
|
|
|
|
+ struct nvkm_msgqueue_msg base;
|
|
|
|
+
|
|
|
|
+ u32 falcon_mask;
|
|
|
|
+ } *msg = (void *)hdr;
|
|
|
|
+ const struct nvkm_subdev *subdev = priv->falcon->owner;
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask)
|
|
|
|
+{
|
|
|
|
+ DECLARE_COMPLETION_ONSTACK(completed);
|
|
|
|
+ /*
|
|
|
|
+ * flags - Flag specifying RESET or no RESET.
|
|
|
|
+ * falcon id - Falcon id specifying falcon to bootstrap.
|
|
|
|
+ */
|
|
|
|
+ struct {
|
|
|
|
+ struct nvkm_msgqueue_hdr 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);
|
|
|
|
+
|
|
|
|
+ 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);
|
|
|
|
+ nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr,
|
|
|
|
+ acr_boot_multiple_falcons_callback, &completed, true);
|
|
|
|
+
|
|
|
|
+ if (!wait_for_completion_timeout(&completed, msecs_to_jiffies(1000)))
|
|
|
|
+ return -ETIMEDOUT;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct nvkm_msgqueue_acr_func
|
|
static const struct nvkm_msgqueue_acr_func
|
|
msgqueue_0137c63d_acr_func = {
|
|
msgqueue_0137c63d_acr_func = {
|
|
.boot_falcon = acr_boot_falcon,
|
|
.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
|
|
static void
|
|
msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
|
|
msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
|
|
{
|
|
{
|
|
@@ -322,3 +402,35 @@ msgqueue_0137c63d_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+static const struct nvkm_msgqueue_func
|
|
|
|
+msgqueue_0137bca5_func = {
|
|
|
|
+ .init_func = &msgqueue_0137c63d_init_func,
|
|
|
|
+ .acr_func = &msgqueue_0137bca5_acr_func,
|
|
|
|
+ .cmd_queue = msgqueue_0137c63d_cmd_queue,
|
|
|
|
+ .recv = msgqueue_0137c63d_process_msgs,
|
|
|
|
+ .dtor = msgqueue_0137c63d_dtor,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+msgqueue_0137bca5_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
|
|
|
|
+ struct nvkm_msgqueue **queue)
|
|
|
|
+{
|
|
|
|
+ struct msgqueue_0137bca5 *ret;
|
|
|
|
+
|
|
|
|
+ ret = kzalloc(sizeof(*ret), GFP_KERNEL);
|
|
|
|
+ if (!ret)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ *queue = &ret->base.base;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * FIXME this must be set to the address of a *GPU* mapping within the
|
|
|
|
+ * ACR address space!
|
|
|
|
+ */
|
|
|
|
+ /* ret->wpr_addr = sb->wpr_addr; */
|
|
|
|
+
|
|
|
|
+ nvkm_msgqueue_ctor(&msgqueue_0137bca5_func, falcon, &ret->base.base);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|