Add pool to allocate individual rtkit task arguments instead of passing a
authortobhe <tobhe@openbsd.org>
Fri, 12 Jul 2024 10:01:28 +0000 (10:01 +0000)
committertobhe <tobhe@openbsd.org>
Fri, 12 Jul 2024 10:01:28 +0000 (10:01 +0000)
shared argument.  This fixes a race condition where a message could overwrite
rtkep->msg of a previously scheduled task resulting in a refcounting error later
on causing the screen to stay dark after waking up from suspend.

ok kettenis@

sys/dev/pci/drm/apple/apldcp.c

index c27bcd7..6ab379c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: apldcp.c,v 1.1 2024/01/22 18:54:01 kettenis Exp $     */
+/*     $OpenBSD: apldcp.c,v 1.2 2024/07/12 10:01:28 tobhe Exp $        */
 /*
  * Copyright (c) 2023 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -18,6 +18,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <sys/pool.h>
 
 #include <machine/intr.h>
 #include <machine/bus.h>
@@ -103,14 +104,19 @@ apldcp_activate(struct device *self, int act)
 
 #include <arm64/dev/rtkit.h>
 
+struct apple_rtkit_task {
+       struct apple_rtkit_ep *rtkep;
+       struct task task;
+       uint64_t msg;
+};
+
 struct apple_rtkit_ep {
        struct apple_rtkit *rtk;
        uint8_t ep;
-
-       struct task task;
-       uint64_t msg;
 };
 
+static struct pool rtktask_pool;
+
 struct apple_rtkit {
        struct rtkit_state *state;
        struct apple_rtkit_ep ep[64];
@@ -170,10 +176,12 @@ apple_rtkit_logmap(void *cookie, bus_addr_t addr)
 void
 apple_rtkit_do_recv(void *arg)
 {
-       struct apple_rtkit_ep *rtkep = arg;
+       struct apple_rtkit_task *rtktask = arg;
+       struct apple_rtkit_ep *rtkep = rtktask->rtkep;
        struct apple_rtkit *rtk = rtkep->rtk;
 
-       rtk->ops->recv_message(rtk->cookie, rtkep->ep, rtkep->msg);
+       rtk->ops->recv_message(rtk->cookie, rtkep->ep, rtktask->msg);
+       pool_put(&rtktask_pool, rtktask);
 }
 
 void
@@ -181,9 +189,15 @@ apple_rtkit_recv(void *cookie, uint64_t msg)
 {
        struct apple_rtkit_ep *rtkep = cookie;
        struct apple_rtkit *rtk = rtkep->rtk;
+       struct apple_rtkit_task *rtktask;
 
-       rtkep->msg = msg;
-       task_add(rtk->tq, &rtkep->task);
+       rtktask = pool_get(&rtktask_pool, PR_NOWAIT | PR_ZERO);
+       KASSERT(rtktask != NULL);
+
+       rtktask->rtkep = rtkep;
+       rtktask->msg = msg;
+       task_set(&rtktask->task, apple_rtkit_do_recv, rtktask);
+       task_add(rtk->tq, &rtktask->task);
 }
 
 int
@@ -195,8 +209,6 @@ apple_rtkit_start_ep(struct apple_rtkit *rtk, uint8_t ep)
        rtkep = &rtk->ep[ep];
        rtkep->rtk = rtk;
        rtkep->ep = ep;
-       task_set(&rtkep->task, apple_rtkit_do_recv, rtkep);
-
        error = rtkit_start_endpoint(rtk->state, ep, apple_rtkit_recv, rtkep);
        return -error;
 }
@@ -239,6 +251,9 @@ devm_apple_rtkit_init(struct device *dev, void *cookie,
                return ERR_PTR(ENOMEM);
        }
 
+       pool_init(&rtktask_pool, sizeof(struct apple_rtkit_task), 0, IPL_TTY,
+           0, "apldcp_rtkit", NULL);
+
        rk = malloc(sizeof(*rk), M_DEVBUF, M_WAITOK | M_ZERO);
        rk->rk_cookie = rtk;
        rk->rk_dmat = pdev->dmat;