void nvkm_falcon_cmdq_init(struct nvkm_falcon_cmdq *,
u32 index, u32 offset, u32 size);
void nvkm_falcon_cmdq_fini(struct nvkm_falcon_cmdq *);
+
+struct nvkm_falcon_msgq;
+int nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *, const char *name,
+ struct nvkm_falcon_msgq **);
+void nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **);
+void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *,
+ u32 index, u32 offset, u32 size);
#endif
#include <core/device.h>
#define nvkm_falcon_cmdq nvkm_msgqueue_queue
+#define nvkm_falcon_msgq nvkm_msgqueue_queue
struct nvkm_subdev {
const struct nvkm_subdev_func *func;
struct nvkm_falcon_qmgr *qmgr;
struct nvkm_falcon_cmdq *cmdq;
+ struct nvkm_falcon_msgq *msgq;
struct nvkm_msgqueue *queue;
struct work_struct work;
};
struct nvkm_falcon_qmgr *qmgr;
struct nvkm_falcon_cmdq *hpq;
struct nvkm_falcon_cmdq *lpq;
+ struct nvkm_falcon_msgq *msgq;
struct nvkm_msgqueue *queue;
struct {
{
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
nvkm_msgqueue_del(&sec2->queue);
+ nvkm_falcon_msgq_del(&sec2->msgq);
nvkm_falcon_cmdq_del(&sec2->cmdq);
nvkm_falcon_qmgr_del(&sec2->qmgr);
nvkm_falcon_dtor(&sec2->falcon);
return ret;
if ((ret = nvkm_falcon_qmgr_new(&sec2->falcon, &sec2->qmgr)) ||
- (ret = nvkm_falcon_cmdq_new(sec2->qmgr, "cmdq", &sec2->cmdq)))
+ (ret = nvkm_falcon_cmdq_new(sec2->qmgr, "cmdq", &sec2->cmdq)) ||
+ (ret = nvkm_falcon_msgq_new(sec2->qmgr, "msgq", &sec2->msgq)))
return ret;
INIT_WORK(&sec2->work, nvkm_sec2_recv);
msgqueue_msg_handle(priv, hdr);
}
}
+
+void
+nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *msgq,
+ u32 index, u32 offset, u32 size)
+{
+ const struct nvkm_falcon_func *func = msgq->qmgr->falcon->func;
+
+ msgq->head_reg = func->msgq.head + index * func->msgq.stride;
+ msgq->tail_reg = func->msgq.tail + index * func->msgq.stride;
+ msgq->offset = offset;
+
+ FLCNQ_DBG(msgq, "initialised @ index %d offset 0x%08x size 0x%08x",
+ index, msgq->offset, size);
+}
+
+void
+nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **pmsgq)
+{
+ struct nvkm_falcon_msgq *msgq = *pmsgq;
+ if (msgq) {
+ kfree(*pmsgq);
+ *pmsgq = NULL;
+ }
+}
+
+int
+nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *qmgr, const char *name,
+ struct nvkm_falcon_msgq **pmsgq)
+{
+ struct nvkm_falcon_msgq *msgq = *pmsgq;
+
+ if (!(msgq = *pmsgq = kzalloc(sizeof(*msgq), GFP_KERNEL)))
+ return -ENOMEM;
+
+ msgq->qmgr = qmgr;
+ msgq->name = name;
+ mutex_init(&msgq->mutex);
+ return 0;
+}
/* Queues identifiers */
enum {
- /* Message queue for PMU -> Host communication */
- MSGQUEUE_0137C63D_MESSAGE_QUEUE = 4,
MSGQUEUE_0137C63D_NUM_QUEUES = 5,
};
struct msgqueue_0137c63d {
struct nvkm_msgqueue base;
-
- struct nvkm_msgqueue_queue queue[MSGQUEUE_0137C63D_NUM_QUEUES];
};
#define msgqueue_0137c63d(q) \
container_of(q, struct msgqueue_0137c63d, base)
static void
msgqueue_0137c63d_process_msgs(struct nvkm_msgqueue *queue)
{
- struct msgqueue_0137c63d *priv = msgqueue_0137c63d(queue);
- struct nvkm_msgqueue_queue *q_queue =
- &priv->queue[MSGQUEUE_0137C63D_MESSAGE_QUEUE];
-
- nvkm_msgqueue_process_msgs(&priv->base, q_queue);
+ nvkm_msgqueue_process_msgs(queue, queue->falcon->owner->device->pmu->msgq);
}
/* Init unit */
u16 sw_managed_area_offset;
u16 sw_managed_area_size;
} *init = (void *)hdr;
- const struct nvkm_falcon_func *func = _queue->falcon->func;
const struct nvkm_subdev *subdev = _queue->falcon->owner;
struct nvkm_pmu *pmu = subdev->device->pmu;
- int i;
if (init->base.hdr.unit_id != MSGQUEUE_0137C63D_UNIT_INIT) {
nvkm_error(subdev, "expected message from init unit\n");
return -EINVAL;
}
- for (i = 0; i < MSGQUEUE_0137C63D_NUM_QUEUES; i++) {
- struct nvkm_msgqueue_queue *queue = &priv->queue[i];
-
- mutex_init(&queue->mutex);
-
- queue->index = init->queue_info[i].index;
- queue->offset = init->queue_info[i].offset;
- queue->size = init->queue_info[i].size;
-
- if (i == MSGQUEUE_0137C63D_MESSAGE_QUEUE) {
- queue->head_reg = func->msgq.head;
- queue->tail_reg = func->msgq.tail;
- }
-
- nvkm_debug(subdev,
- "queue %d: index %d, offset 0x%08x, size 0x%08x\n",
- i, queue->index, queue->offset, queue->size);
- }
-
nvkm_falcon_cmdq_init(pmu->hpq, init->queue_info[0].index,
init->queue_info[0].offset,
init->queue_info[0].size);
nvkm_falcon_cmdq_init(pmu->lpq, init->queue_info[1].index,
init->queue_info[1].offset,
init->queue_info[1].size);
+ nvkm_falcon_msgq_init(pmu->msgq, init->queue_info[4].index,
+ init->queue_info[4].offset,
+ init->queue_info[4].size);
/* Complete initialization by initializing WPR region */
return acr_init_wpr(&priv->base);
struct msgqueue_0148cdec {
struct nvkm_msgqueue base;
-
- struct nvkm_msgqueue_queue queue[MSGQUEUE_0148CDEC_NUM_QUEUES];
};
#define msgqueue_0148cdec(q) \
container_of(q, struct msgqueue_0148cdec, base)
static void
msgqueue_0148cdec_process_msgs(struct nvkm_msgqueue *queue)
{
- struct msgqueue_0148cdec *priv = msgqueue_0148cdec(queue);
- struct nvkm_msgqueue_queue *q_queue =
- &priv->queue[MSGQUEUE_0148CDEC_MESSAGE_QUEUE];
-
- nvkm_msgqueue_process_msgs(&priv->base, q_queue);
+ nvkm_msgqueue_process_msgs(queue, queue->falcon->owner->device->sec2->msgq);
}
static int
init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr)
{
- struct msgqueue_0148cdec *priv = msgqueue_0148cdec(_queue);
struct {
struct nvkm_msgqueue_msg base;
u16 sw_managed_area_offset;
u16 sw_managed_area_size;
} *init = (void *)hdr;
- const struct nvkm_falcon_func *func = _queue->falcon->func;
const struct nvkm_subdev *subdev = _queue->falcon->owner;
struct nvkm_sec2 *sec2 = subdev->device->sec2;
int i;
for (i = 0; i < MSGQUEUE_0148CDEC_NUM_QUEUES; i++) {
u8 id = init->queue_info[i].id;
- struct nvkm_msgqueue_queue *queue = &priv->queue[id];
-
- mutex_init(&queue->mutex);
-
- queue->index = init->queue_info[i].index;
- queue->offset = init->queue_info[i].offset;
- queue->size = init->queue_info[i].size;
if (id == MSGQUEUE_0148CDEC_MESSAGE_QUEUE) {
- queue->head_reg = func->msgq.head + queue->index *
- func->msgq.stride;
- queue->tail_reg = func->msgq.tail + queue->index *
- func->msgq.stride;
+ nvkm_falcon_msgq_init(sec2->msgq,
+ init->queue_info[i].index,
+ init->queue_info[i].offset,
+ init->queue_info[i].size);
} else {
nvkm_falcon_cmdq_init(sec2->cmdq,
init->queue_info[i].index,
init->queue_info[i].offset,
init->queue_info[i].size);
}
-
- nvkm_debug(subdev,
- "queue %d: index %d, offset 0x%08x, size 0x%08x\n",
- id, queue->index, queue->offset, queue->size);
}
complete_all(&_queue->init_done);
{
struct nvkm_pmu *pmu = nvkm_pmu(subdev);
nvkm_msgqueue_del(&pmu->queue);
+ nvkm_falcon_msgq_del(&pmu->msgq);
nvkm_falcon_cmdq_del(&pmu->lpq);
nvkm_falcon_cmdq_del(&pmu->hpq);
nvkm_falcon_qmgr_del(&pmu->qmgr);
if ((ret = nvkm_falcon_qmgr_new(&pmu->falcon, &pmu->qmgr)) ||
(ret = nvkm_falcon_cmdq_new(pmu->qmgr, "hpq", &pmu->hpq)) ||
- (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "lpq", &pmu->lpq)))
+ (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "lpq", &pmu->lpq)) ||
+ (ret = nvkm_falcon_msgq_new(pmu->qmgr, "msgq", &pmu->msgq)))
return ret;
return 0;