mirror of
https://github.com/AsahiLinux/m1n1
synced 2025-03-07 08:47:20 +00:00
WIP: AFK: Support multiple endpoints with IOP initiated communication
Endpoint 0x2a (dptx-port) sees DCP initiated notify messages. Those need to be handled with the correct endpoint context and must not be rejected when other endpoints are polling for new messages.
This commit is contained in:
parent
32431d8ba1
commit
43fa9185f6
6 changed files with 122 additions and 32 deletions
124
src/afk.c
124
src/afk.c
|
@ -82,10 +82,16 @@ struct epic_cmd {
|
|||
|
||||
#define AFK_MAX_CHANNEL 16
|
||||
|
||||
struct afk_epic_ep {
|
||||
int ep;
|
||||
struct afk_epic {
|
||||
rtkit_dev_t *rtk;
|
||||
|
||||
afk_epic_ep_t *endpoint[0x10];
|
||||
};
|
||||
|
||||
struct afk_epic_ep {
|
||||
int ep;
|
||||
|
||||
afk_epic_t *afk;
|
||||
struct rtkit_buffer buf;
|
||||
u16 tag;
|
||||
|
||||
|
@ -100,6 +106,8 @@ struct afk_epic_ep {
|
|||
|
||||
const afk_epic_service_ops_t *ops;
|
||||
afk_epic_service_t services[AFK_MAX_CHANNEL];
|
||||
|
||||
void (*recv_handler)(afk_epic_ep_t *epic);
|
||||
};
|
||||
|
||||
enum RBEP_MSG {
|
||||
|
@ -148,12 +156,12 @@ bool afk_rb_init(afk_epic_ep_t *epic, struct afk_rb *rb, u64 base, u64 size)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int afk_epic_poll(afk_epic_ep_t *epic)
|
||||
static int afk_epic_poll(afk_epic_t *afk, int endpoint)
|
||||
{
|
||||
int ret;
|
||||
struct rtkit_message msg;
|
||||
|
||||
while ((ret = rtkit_recv(epic->rtk, &msg)) == 0)
|
||||
while ((ret = rtkit_recv(afk->rtk, &msg)) == 0)
|
||||
;
|
||||
|
||||
if (ret < 0) {
|
||||
|
@ -161,11 +169,17 @@ static int afk_epic_poll(afk_epic_ep_t *epic)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (msg.ep != epic->ep) {
|
||||
if (msg.ep < 0x20 || msg.ep >= 0x30 || !afk->endpoint[msg.ep - 0x20]) {
|
||||
printf("EPIC: received message for unexpected endpoint %d\n", msg.ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
afk_epic_ep_t *epic = afk->endpoint[msg.ep - 0x20];
|
||||
if (!epic) {
|
||||
printf("EPIC: received message for idle endpoint %d\n", msg.ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int type = FIELD_GET(RBEP_TYPE, msg.msg);
|
||||
u64 base, size, tag;
|
||||
switch (type) {
|
||||
|
@ -175,13 +189,13 @@ static int afk_epic_poll(afk_epic_ep_t *epic)
|
|||
case RBEP_GETBUF:
|
||||
size = FIELD_GET(GETBUF_SIZE, msg.msg) << BLOCK_SHIFT;
|
||||
epic->tag = FIELD_GET(GETBUF_TAG, msg.msg);
|
||||
if (!rtkit_alloc_buffer(epic->rtk, &epic->buf, size)) {
|
||||
if (!rtkit_alloc_buffer(epic->afk->rtk, &epic->buf, size)) {
|
||||
printf("EPIC: failed to allocate buffer\n");
|
||||
return -1;
|
||||
}
|
||||
msg.msg = (FIELD_PREP(RBEP_TYPE, RBEP_GETBUF_ACK) |
|
||||
FIELD_PREP(GETBUF_ACK_DVA, epic->buf.dva));
|
||||
if (!rtkit_send(epic->rtk, &msg)) {
|
||||
if (!rtkit_send(epic->afk->rtk, &msg)) {
|
||||
printf("EPIC: failed to send buffer address\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -208,7 +222,7 @@ static int afk_epic_poll(afk_epic_ep_t *epic)
|
|||
|
||||
if (epic->rx.ready && epic->tx.ready) {
|
||||
msg.msg = FIELD_PREP(RBEP_TYPE, RBEP_START);
|
||||
if (!rtkit_send(epic->rtk, &msg)) {
|
||||
if (!rtkit_send(epic->afk->rtk, &msg)) {
|
||||
printf("EPIC: failed to send start\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -216,7 +230,11 @@ static int afk_epic_poll(afk_epic_ep_t *epic)
|
|||
break;
|
||||
|
||||
case RBEP_RECV:
|
||||
return 1;
|
||||
if (endpoint == epic->ep)
|
||||
return 1;
|
||||
if (epic->recv_handler)
|
||||
epic->recv_handler(epic);
|
||||
break;
|
||||
|
||||
case RBEP_START_ACK:
|
||||
epic->started = true;
|
||||
|
@ -244,7 +262,7 @@ static int afk_epic_rx(afk_epic_ep_t *epic, struct afk_qe **qe)
|
|||
|
||||
while (rptr == rb->hdr->wptr) {
|
||||
do {
|
||||
ret = afk_epic_poll(epic);
|
||||
ret = afk_epic_poll(epic->afk, epic->ep);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} while (ret == 0);
|
||||
|
@ -322,7 +340,7 @@ static int afk_epic_tx(afk_epic_ep_t *epic, u32 channel, u32 type, void *data, s
|
|||
FIELD_PREP(RBEP_TYPE, RBEP_SEND) | FIELD_PREP(SEND_WPTR, wptr),
|
||||
};
|
||||
|
||||
if (!rtkit_send(epic->rtk, &msg)) {
|
||||
if (!rtkit_send(epic->afk->rtk, &msg)) {
|
||||
printf("EPIC: failed to send TX WPTR message\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -547,7 +565,34 @@ int afk_epic_command(afk_epic_ep_t *epic, int channel, u16 sub_seq, u16 code, vo
|
|||
return 0;
|
||||
}
|
||||
|
||||
afk_epic_ep_t *afk_epic_init(rtkit_dev_t *rtk, int endpoint)
|
||||
static void afk_epic_notify_handler(afk_epic_ep_t *epic)
|
||||
{
|
||||
struct afk_qe *rmsg;
|
||||
int ret = afk_epic_rx(epic, &rmsg);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
if (rmsg->type != TYPE_NOTIFY) {
|
||||
printf("EPIC: got unexpected message type %d in %s command\n", rmsg->type, __func__);
|
||||
afk_epic_rx_ack(epic);
|
||||
return;
|
||||
}
|
||||
|
||||
struct epic_hdr *hdr = (void *)(rmsg + 1);
|
||||
struct epic_sub_hdr *sub = (void *)(hdr + 1);
|
||||
|
||||
if (sub->category == CAT_NOTIFY && sub->type == CODE_STD_SERVICE) {
|
||||
void *payload = rmsg->data + sizeof(struct epic_hdr) + sizeof(struct epic_sub_hdr);
|
||||
size_t payload_size = rmsg->size - sizeof(struct epic_hdr) - sizeof(struct epic_sub_hdr);
|
||||
afk_epic_handle_std_service(epic, rmsg->channel, hdr, sub, payload, payload_size);
|
||||
} else
|
||||
printf("EPIC: %s: rx: Ch %u, Type:0x%02x sub cat:%x type:%x \n", __func__, rmsg->channel,
|
||||
rmsg->type, sub->category, sub->type);
|
||||
|
||||
afk_epic_rx_ack(epic);
|
||||
}
|
||||
|
||||
afk_epic_ep_t *afk_epic_start_ep(afk_epic_t *afk, int endpoint, bool notify)
|
||||
{
|
||||
afk_epic_ep_t *epic = malloc(sizeof(afk_epic_ep_t));
|
||||
if (!epic)
|
||||
|
@ -555,21 +600,25 @@ afk_epic_ep_t *afk_epic_init(rtkit_dev_t *rtk, int endpoint)
|
|||
|
||||
memset(epic, 0, sizeof(*epic));
|
||||
epic->ep = endpoint;
|
||||
epic->rtk = rtk;
|
||||
epic->afk = afk;
|
||||
afk->endpoint[endpoint - 0x20] = epic;
|
||||
|
||||
if (!rtkit_start_ep(rtk, endpoint)) {
|
||||
if (notify)
|
||||
epic->recv_handler = afk_epic_notify_handler;
|
||||
|
||||
if (!rtkit_start_ep(epic->afk->rtk, endpoint)) {
|
||||
printf("EPIC: failed to start endpoint %d\n", endpoint);
|
||||
goto err;
|
||||
}
|
||||
|
||||
struct rtkit_message msg = {endpoint, FIELD_PREP(RBEP_TYPE, RBEP_INIT)};
|
||||
if (!rtkit_send(rtk, &msg)) {
|
||||
if (!rtkit_send(epic->afk->rtk, &msg)) {
|
||||
printf("EPIC: failed to send init message\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (!epic->started) {
|
||||
int ret = afk_epic_poll(epic);
|
||||
int ret = afk_epic_poll(epic->afk, endpoint);
|
||||
if (ret < 0)
|
||||
break;
|
||||
else if (ret > 0)
|
||||
|
@ -579,27 +628,30 @@ afk_epic_ep_t *afk_epic_init(rtkit_dev_t *rtk, int endpoint)
|
|||
return epic;
|
||||
|
||||
err:
|
||||
afk->endpoint[endpoint - 0x20] = NULL;
|
||||
free(epic);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int afk_epic_shutdown(afk_epic_ep_t *epic)
|
||||
int afk_epic_shutdown_ep(afk_epic_ep_t *epic)
|
||||
{
|
||||
struct rtkit_message msg = {epic->ep, FIELD_PREP(RBEP_TYPE, RBEP_SHUTDOWN)};
|
||||
if (!rtkit_send(epic->rtk, &msg)) {
|
||||
if (!rtkit_send(epic->afk->rtk, &msg)) {
|
||||
printf("EPIC: failed to send shutdown message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (epic->started) {
|
||||
int ret = afk_epic_poll(epic);
|
||||
int ret = afk_epic_poll(epic->afk, epic->ep);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
rtkit_free_buffer(epic->rtk, &epic->buf);
|
||||
rtkit_free_buffer(epic->rtk, &epic->rxbuf);
|
||||
rtkit_free_buffer(epic->rtk, &epic->txbuf);
|
||||
rtkit_free_buffer(epic->afk->rtk, &epic->buf);
|
||||
rtkit_free_buffer(epic->afk->rtk, &epic->rxbuf);
|
||||
rtkit_free_buffer(epic->afk->rtk, &epic->txbuf);
|
||||
|
||||
epic->afk->endpoint[epic->ep - 0x20] = NULL;
|
||||
|
||||
free(epic);
|
||||
return 0;
|
||||
|
@ -675,12 +727,12 @@ int afk_epic_start_interface(afk_epic_ep_t *epic, const afk_epic_service_ops_t *
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!rtkit_alloc_buffer(epic->rtk, &epic->rxbuf, rxsize)) {
|
||||
if (!rtkit_alloc_buffer(epic->afk->rtk, &epic->rxbuf, rxsize)) {
|
||||
printf("EPIC: failed to allocate rx buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!rtkit_alloc_buffer(epic->rtk, &epic->txbuf, txsize)) {
|
||||
if (!rtkit_alloc_buffer(epic->afk->rtk, &epic->txbuf, txsize)) {
|
||||
printf("EPIC: failed to allocate tx buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -689,3 +741,27 @@ int afk_epic_start_interface(afk_epic_ep_t *epic, const afk_epic_service_ops_t *
|
|||
|
||||
return channel;
|
||||
}
|
||||
|
||||
afk_epic_t *afk_epic_init(rtkit_dev_t *rtkit)
|
||||
{
|
||||
afk_epic_t *afk = calloc(sizeof(*afk), 1);
|
||||
|
||||
if (!afk)
|
||||
return NULL;
|
||||
|
||||
afk->rtk = rtkit;
|
||||
|
||||
return afk;
|
||||
}
|
||||
|
||||
int afk_epic_shutdown(afk_epic_t *afk)
|
||||
{
|
||||
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
if (afk->endpoint[i])
|
||||
afk_epic_shutdown_ep(afk->endpoint[i]);
|
||||
|
||||
free(afk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#define MAX_PENDING_CMDS 8
|
||||
|
||||
typedef struct afk_epic afk_epic_t;
|
||||
typedef struct afk_epic_ep afk_epic_ep_t;
|
||||
|
||||
typedef struct afk_epic_service_ops afk_epic_service_ops_t;
|
||||
|
@ -57,8 +58,11 @@ typedef struct afk_epic_service_ops {
|
|||
void *reply, size_t reply_size);
|
||||
} afk_epic_service_ops_t;
|
||||
|
||||
afk_epic_ep_t *afk_epic_init(rtkit_dev_t *rtkit, int endpoint);
|
||||
int afk_epic_shutdown(afk_epic_ep_t *epic);
|
||||
afk_epic_t *afk_epic_init(rtkit_dev_t *rtkit);
|
||||
int afk_epic_shutdown(afk_epic_t *afk);
|
||||
|
||||
afk_epic_ep_t *afk_epic_start_ep(afk_epic_t *afk, int endpoint, bool notify);
|
||||
int afk_epic_shutdown_ep(afk_epic_ep_t *epic);
|
||||
|
||||
int afk_epic_start_channel(afk_epic_ep_t *epic, const afk_epic_service_ops_t *ops, void *intf,
|
||||
const char *name);
|
||||
|
|
|
@ -60,8 +60,15 @@ dcp_dev_t *dcp_init(const char *dcp_path, const char *dcp_dart_path, const char
|
|||
goto out_iovad;
|
||||
}
|
||||
|
||||
dcp->afk = afk_epic_init(dcp->rtkit);
|
||||
if (!dcp->afk) {
|
||||
printf("dcp: failed to initialize AFK\n");
|
||||
goto out_rtkit;
|
||||
}
|
||||
|
||||
return dcp;
|
||||
|
||||
out_rtkit:
|
||||
rtkit_quiesce(dcp->rtkit);
|
||||
rtkit_free(dcp->rtkit);
|
||||
out_iovad:
|
||||
|
@ -76,6 +83,7 @@ out_free:
|
|||
|
||||
int dcp_shutdown(dcp_dev_t *dcp, bool sleep)
|
||||
{
|
||||
afk_epic_shutdown(dcp->afk);
|
||||
if (sleep) {
|
||||
rtkit_sleep(dcp->rtkit);
|
||||
pmgr_reset(0, "DISP0_CPU0");
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#ifndef DCP_H
|
||||
#define DCP_H
|
||||
|
||||
#include "afk.h"
|
||||
#include "asc.h"
|
||||
#include "dart.h"
|
||||
#include "rtkit.h"
|
||||
|
@ -32,6 +33,7 @@ typedef struct {
|
|||
iova_domain_t *iovad_dcp;
|
||||
asc_dev_t *asc;
|
||||
rtkit_dev_t *rtkit;
|
||||
afk_epic_t *afk;
|
||||
|
||||
dptx_port_t *port;
|
||||
} dcp_dev_t;
|
||||
|
|
|
@ -500,7 +500,7 @@ dcp_dptx_if_t *dcp_dptx_init(dcp_dev_t *dcp)
|
|||
return NULL;
|
||||
|
||||
dptx->dcp = dcp;
|
||||
dptx->epic = afk_epic_init(dcp->rtkit, DCP_DPTX_ENDPOINT);
|
||||
dptx->epic = afk_epic_start_ep(dcp->afk, DCP_DPTX_ENDPOINT, true);
|
||||
if (!dptx->epic) {
|
||||
printf("dcp-dptx: failed to initialize EPIC\n");
|
||||
goto err_free;
|
||||
|
@ -531,7 +531,7 @@ dcp_dptx_if_t *dcp_dptx_init(dcp_dev_t *dcp)
|
|||
return dptx;
|
||||
|
||||
err_shutdown:
|
||||
afk_epic_shutdown(dptx->epic);
|
||||
afk_epic_shutdown_ep(dptx->epic);
|
||||
err_free:
|
||||
free(dptx);
|
||||
return NULL;
|
||||
|
@ -539,7 +539,7 @@ err_free:
|
|||
|
||||
int dcp_dptx_shutdown(dcp_dptx_if_t *dptx)
|
||||
{
|
||||
afk_epic_shutdown(dptx->epic);
|
||||
afk_epic_shutdown_ep(dptx->epic);
|
||||
|
||||
free(dptx);
|
||||
return 0;
|
||||
|
|
|
@ -92,7 +92,7 @@ dcp_iboot_if_t *dcp_ib_init(dcp_dev_t *dcp)
|
|||
return NULL;
|
||||
|
||||
iboot->dcp = dcp;
|
||||
iboot->epic = afk_epic_init(dcp->rtkit, DCP_IBOOT_ENDPOINT);
|
||||
iboot->epic = afk_epic_start_ep(dcp->afk, DCP_IBOOT_ENDPOINT, false);
|
||||
if (!iboot->epic) {
|
||||
printf("dcp-iboot: failed to initialize EPIC\n");
|
||||
goto err_free;
|
||||
|
@ -109,7 +109,7 @@ dcp_iboot_if_t *dcp_ib_init(dcp_dev_t *dcp)
|
|||
return iboot;
|
||||
|
||||
err_shutdown:
|
||||
afk_epic_shutdown(iboot->epic);
|
||||
afk_epic_shutdown_ep(iboot->epic);
|
||||
err_free:
|
||||
free(iboot);
|
||||
return NULL;
|
||||
|
@ -117,7 +117,7 @@ err_free:
|
|||
|
||||
int dcp_ib_shutdown(dcp_iboot_if_t *iboot)
|
||||
{
|
||||
afk_epic_shutdown(iboot->epic);
|
||||
afk_epic_shutdown_ep(iboot->epic);
|
||||
|
||||
free(iboot);
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue