Received: by 2002:ad5:4acb:0:0:0:0:0 with SMTP id n11csp3979352imw; Mon, 11 Jul 2022 21:51:41 -0700 (PDT) X-Google-Smtp-Source: AGRyM1uBYp0SuOc40YyVkLl0IZagjLCeNwZ+7g+I1d93YgZslLfHD83Q5ZD9auTVTmk/nGIZE2bz X-Received: by 2002:a05:6402:34c3:b0:43a:c323:274f with SMTP id w3-20020a05640234c300b0043ac323274fmr20689236edc.67.1657601500767; Mon, 11 Jul 2022 21:51:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1657601500; cv=none; d=google.com; s=arc-20160816; b=ygAYa4LtLrXciz2FpqxDqBQ3y4c9Y2jN83f6e1UGLoLxlAHl1bqy2FbliKcM5eFPmU wXkfQkdA7llChfS4FKdVqHCFYAKWQQ2cp65fd+oh7mbf3aWwr9tocVgUB0qDrxLqwFoV CknFkvjLpWZSGaaaarZ1bLIUzOuk1yhPIB5hBIK/AO/82Sctp0MbqsDo9kTK2k7HZ35S DJie149QqZua3Wo24WLu26WvlTwCL704J6HsS4e5gftUXFPdACkHbymHhiMzWht4ohq2 bdCVZLWkaO0YZjvSe18O79dvQwnsTXS2r6oIPlrR24mnK+lfzTtO5TnYjWTUpw+OQTGa eALg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:from:subject :references:mime-version:message-id:in-reply-to:date:dkim-signature; bh=4htvJMwk9Uq3+H7F7oT1uH3l+HozdkoS/P4WOYTuXyA=; b=Ft+olKyebrA75Tmm0IYbjwzwF+c2za/lVX7UX012Lf5dkN6l3dGcPh7rPJr+bk9qP4 ANw5mquCrg8dkg7juB6qcMKgyzL2g3oByM3bOOJ+sAPG0krk37dTBv+Aur+1aNG8Xs6Y LQ1BziGuIK6+CZPuCq8fUOfP9sUrdkYFSqEAVsZAwFN0P0ZUuDv+r/pAnSBpPsW6RR0A NqNgXa+HOfnnMmWW1TX5G/KP/LoL8wGElZ+tFsVMCl6OMuySxbFfcDgnU087tDrQ8qKr 1iNozlrCZDUXh7VMKTPSvwZDO9dPYxmKlrFmyUFE+3Gf6Lm1OALGtyqd6Cu2sNX3ngUl bpCg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=Gn4PWW33; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id mp11-20020a1709071b0b00b007296e194403si14236681ejc.273.2022.07.11.21.51.16; Mon, 11 Jul 2022 21:51:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=Gn4PWW33; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231159AbiGLEXW (ORCPT + 99 others); Tue, 12 Jul 2022 00:23:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42840 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229735AbiGLEXP (ORCPT ); Tue, 12 Jul 2022 00:23:15 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C8FCA25C50 for ; Mon, 11 Jul 2022 21:23:12 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id f13-20020a056a001acd00b0052ab9ae76fbso1742187pfv.20 for ; Mon, 11 Jul 2022 21:23:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=4htvJMwk9Uq3+H7F7oT1uH3l+HozdkoS/P4WOYTuXyA=; b=Gn4PWW33xaYPLR1oWicT6XyTa/Ua0WKtB4gfnmNOEdWNwe4iE8ZncGu6ZHaJtebdKb 9IhkYU0FIUh7IOAvfk/YqAI4iguG3td7S5738WODO0cG40sL4Or8GHPNzsjg8bwNBlaB MSFmirwqwVd5Hw7eyr6/YVKXbq+wGAO6Z3NTHQil2xhUFrSwx1wjjjQ2sK64ZswAItL1 Y/Px8MqzjtyeTuXOcCeUqEwOJ04iRjx1lLmbG3eNOj3SilURf8mue+MdlbuCEvE5D2W5 cBgySFI4TN6LfIImg1JGn4NRCdKecXHYjMmLtJrZRJ4bgWvSSuiCu0KH0r/NllCDOAZS zmlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=4htvJMwk9Uq3+H7F7oT1uH3l+HozdkoS/P4WOYTuXyA=; b=OnuYuVgBgpHLJRzRhfPdeW6niNFYTU/iPGj8+SrqXdkoVRKmHqzaSUhNiw9O4v/Fst ZTM7XFoLCneh531/nYjH0snHm8h+pM2J8170ESi+qRaCW9+ioZ+G4J1QtQf9rtBmMYWX Xi3CSC8Lx1uroR0aPTUGRfz54YzRRDsZc46qMpfUh8YUP8WRkP1Ix/E6cg+o6BnpgAyf u/Ay9MjYobwU+4qA6mIV8xlDvNiJSTtT6AUW9j/sQ5aTy+1GSo7TEBNgR2wPeNnEDfxp wOAsh+yaNKYwCLshJ7UzphkNynAS32V2rzHfGSOlpv8INS5U2khDXfI+X7J2Tb0ngC+2 1KZw== X-Gm-Message-State: AJIora9+BuYOWd7xOezIWfQ45aBElEo0CMQKRY7M+YacNXUOWhafs7p8 W8X720NrA8Rp7v7tRMm+iyLcJzhQkYVWqgnkaqYU0Lqm74jcSqfm9ioZZm5gBRoeG4r04pfsYSe VYvslaCmSiNyh9xqJbIRzhHBxAGhgHLJqCqHSJPGw0oNo4muY+03mEQiWjxoXLWkq5T2r/R0= X-Received: from jstultz-noogler2.c.googlers.com ([fda3:e722:ac3:cc00:24:72f4:c0a8:600]) (user=jstultz job=sendgmr) by 2002:aa7:9afa:0:b0:528:bbf7:e444 with SMTP id y26-20020aa79afa000000b00528bbf7e444mr22532953pfp.71.1657599791895; Mon, 11 Jul 2022 21:23:11 -0700 (PDT) Date: Tue, 12 Jul 2022 04:22:58 +0000 In-Reply-To: <20220712042258.293010-1-jstultz@google.com> Message-Id: <20220712042258.293010-3-jstultz@google.com> Mime-Version: 1.0 References: <20220712042258.293010-1-jstultz@google.com> X-Mailer: git-send-email 2.37.0.144.g8ac04bfd2-goog Subject: [RFC][PATCH 3/3] kselftest: Add drm_syncobj API test tool From: John Stultz To: LKML Cc: John Stultz , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Jason Ekstrand , "=?UTF-8?q?Christian=20K=C3=B6nig?=" , Lionel Landwerlin , Chunming Zhou , David Airlie , Daniel Vetter , Shuah Khan , dri-devel@lists.freedesktop.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org An initial pass at a drm_syncobj API test. Currently covers trivial use of: DRM_IOCTL_SYNCOBJ_CREATE DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOCTL_SYNCOBJ_WAIT DRM_IOCTL_SYNCOBJ_RESET DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL And demonstrates how the userspace API can be used, along with some fairly simple bad parameter checking. The patch includes a few helpers taken from libdrm, as at least on the VM I was testing with, I didn't have a new enough libdrm to support the *_TIMELINE_* ioctls. Ideally the ioctl-helper bits can be dropped at a later time. Feedback would be appreciated! Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: Jason Ekstrand Cc: Christian K=C3=B6nig Cc: Lionel Landwerlin Cc: Chunming Zhou Cc: David Airlie Cc: Daniel Vetter Cc: Shuah Khan Cc: dri-devel@lists.freedesktop.org Signed-off-by: John Stultz --- .../drivers/gpu/drm_syncobj/Makefile | 11 + .../drivers/gpu/drm_syncobj/ioctl-helper.c | 85 ++++ .../drivers/gpu/drm_syncobj/ioctl-helper.h | 74 ++++ .../drivers/gpu/drm_syncobj/syncobj-test.c | 410 ++++++++++++++++++ 4 files changed, 580 insertions(+) create mode 100644 tools/testing/selftests/drivers/gpu/drm_syncobj/Makefil= e create mode 100644 tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-h= elper.c create mode 100644 tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-h= elper.h create mode 100644 tools/testing/selftests/drivers/gpu/drm_syncobj/syncobj= -test.c diff --git a/tools/testing/selftests/drivers/gpu/drm_syncobj/Makefile b/too= ls/testing/selftests/drivers/gpu/drm_syncobj/Makefile new file mode 100644 index 000000000000..6576d9b2006c --- /dev/null +++ b/tools/testing/selftests/drivers/gpu/drm_syncobj/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +CFLAGS +=3D -I/usr/include/libdrm/ +LDFLAGS +=3D -pthread -ldrm + +TEST_GEN_FILES=3D syncobj-test + +include ../../../lib.mk + +$(OUTPUT)/syncobj-test: syncobj-test.c ioctl-helper.c +EXTRA_CLEAN =3D $(OUTPUT)/ioctl-helper.o + diff --git a/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.c= b/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.c new file mode 100644 index 000000000000..e5c59c9bed36 --- /dev/null +++ b/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ioctl-helper.h" + +#ifndef DRM_CAP_SYNCOBJ_TIMELINE +/* + * The following is nabbed from libdrm's xf86drm.c as the + * installed libdrm doesn't yet include these definitions + * + * + * \author Rickard E. (Rik) Faith + * \author Kevin E. Martin + */ +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software= "), + * to deal in the Software without restriction, including without limitati= on + * the rights to use, copy, modify, merge, publish, distribute, sublicense= , + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the ne= xt + * paragraph) shall be included in all copies or substantial portions of t= he + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY= , + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHAL= L + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES= OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR O= THER + * DEALINGS IN THE SOFTWARE. + */ +int drmSyncobjTimelineSignal(int fd, const uint32_t *handles, + uint64_t *points, uint32_t handle_count) +{ + struct drm_syncobj_timeline_array args; + int ret; + + memset(&args, 0, sizeof(args)); + args.handles =3D (uintptr_t)handles; + args.points =3D (uintptr_t)points; + args.count_handles =3D handle_count; + + ret =3D drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args); + return ret; +} + +int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points, + unsigned int num_handles, + int64_t timeout_nsec, unsigned int flags, + uint32_t *first_signaled) +{ + struct drm_syncobj_timeline_wait args; + int ret; + + memset(&args, 0, sizeof(args)); + args.handles =3D (uintptr_t)handles; + args.points =3D (uintptr_t)points; + args.timeout_nsec =3D timeout_nsec; + args.count_handles =3D num_handles; + args.flags =3D flags; + + ret =3D drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &args); + if (ret < 0) + return -errno; + + if (first_signaled) + *first_signaled =3D args.first_signaled; + return ret; +} + +#endif diff --git a/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.h= b/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.h new file mode 100644 index 000000000000..b0c1025034b5 --- /dev/null +++ b/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __IOCTL_HELPER_H__ +#define __IOCTL_HELPER_H__ + +/* Bits pulled from libdrm's include/drm/drm.h */ +#ifndef DRM_CAP_SYNCOBJ_TIMELINE +/* + * Header for the Direct Rendering Manager + * + * Author: Rickard E. (Rik) Faith + * + * Acknowledgments: + * Dec 1999, Richard Henderson , move to generic cmpxchg. + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software= "), + * to deal in the Software without restriction, including without limitati= on + * the rights to use, copy, modify, merge, publish, distribute, sublicense= , + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the ne= xt + * paragraph) shall be included in all copies or substantial portions of t= he + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY= , + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHAL= L + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES = OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +struct drm_syncobj_timeline_wait { + __u64 handles; + /* wait on specific timeline point for every handles*/ + __u64 points; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + + +#define DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED (1 << 0) +struct drm_syncobj_timeline_array { + __u64 handles; + __u64 points; + __u32 count_handles; + __u32 flags; +}; + +#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_= timeline_wait) +#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_= timeline_array) +#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_= transfer) +#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_= syncobj_timeline_array) + +int drmSyncobjTimelineSignal(int fd, const uint32_t *handles, + uint64_t *points, uint32_t handle_count); +int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points, + unsigned int num_handles, + int64_t timeout_nsec, unsigned int flags, + uint32_t *first_signaled); +#endif +#endif /*__IOCTL_HELPER_H__*/ + diff --git a/tools/testing/selftests/drivers/gpu/drm_syncobj/syncobj-test.c= b/tools/testing/selftests/drivers/gpu/drm_syncobj/syncobj-test.c new file mode 100644 index 000000000000..21474b0d3b9e --- /dev/null +++ b/tools/testing/selftests/drivers/gpu/drm_syncobj/syncobj-test.c @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This test exercises basic syncobj ioctl interfaces from + * userland via the libdrm helpers. + * + * Copyright (C) 2022, Google LLC. + * + * Currently covers trivial use of: + * DRM_IOCTL_SYNCOBJ_CREATE + * DRM_IOCTL_SYNCOBJ_DESTROY + * DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD + * DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE + * DRM_IOCTL_SYNCOBJ_WAIT + * DRM_IOCTL_SYNCOBJ_RESET + * DRM_IOCTL_SYNCOBJ_SIGNAL + * DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT + * DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL + * + * TODO: Need coverage for the following ioctls: + * DRM_IOCTL_SYNCOBJ_QUERY + * DRM_IOCTL_SYNCOBJ_TRANSFER + * As well as more complicated use of interface (like + * signal/wait with multiple handles, etc), and sync_file + * import/export. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ioctl-helper.h" + + +#define NSEC_PER_SEC 1000000000ULL +static uint64_t get_abs_timeout(uint64_t rel_nsec) +{ + struct timespec ts; + uint64_t ns; + + clock_gettime(CLOCK_MONOTONIC, &ts); + ns =3D ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec; + ns +=3D rel_nsec; + return ns; +} + +struct test_arg { + int dev_fd; + uint32_t handle; + int handle_fd; +}; +#define TEST_TIMES 5 + +void *syncobj_signal_reset(void *arg) +{ + struct test_arg *d =3D (struct test_arg *)arg; + int ret; + int i; + + for (i =3D 0; i < TEST_TIMES; i++) { + sleep(3); + printf("%s: sending signal!\n", __func__); + ret =3D drmSyncobjSignal(d->dev_fd, &d->handle, 1); + if (ret) + printf("Signal failed %i\n", ret); + } + return NULL; +} + +static int syncobj_wait_reset(struct test_arg *d) +{ + uint64_t abs_timeout; + int ret; + int i; + + for (i =3D 0; i < TEST_TIMES; i++) { + abs_timeout =3D get_abs_timeout(10*NSEC_PER_SEC); + printf("%s calling drmSyncobjWait\n", __func__); + ret =3D drmSyncobjWait(d->dev_fd, &d->handle, 1, abs_timeout, + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, + NULL); + if (ret) { + printf("Error: syncobjwait failed %i\n", ret); + break; + } + printf("%s: drmSyncobjWait returned!\n", __func__); + + ret =3D drmSyncobjReset(d->dev_fd, &d->handle, 1); + if (ret) { + printf("Error: syncobjreset failed\n"); + break; + } + } + return ret; +} + +void *syncobj_signal_timeline(void *arg) +{ + struct test_arg *d =3D (struct test_arg *)arg; + uint64_t point =3D 0; + int ret; + + for (point =3D 0; point <=3D (TEST_TIMES-1)*5; point++) { + sleep(1); + printf("%s: sending signal %lld!\n", __func__, point); + ret =3D drmSyncobjTimelineSignal(d->dev_fd, &d->handle, &point, 1); + if (ret) + printf("Signal failed %i\n", ret); + } + return NULL; +} + + +int syncobj_timeline_wait(struct test_arg *d) +{ + uint64_t abs_timeout; + uint64_t point; + int ret; + int i; + + for (i =3D 0; i < TEST_TIMES; i++) { + abs_timeout =3D get_abs_timeout(10*NSEC_PER_SEC); + + point =3D i * 5; + printf("%s: drmSyncobjTimelineWait waiting on %lld!\n", __func__, point)= ; + ret =3D drmSyncobjTimelineWait(d->dev_fd, &d->handle, &point, 1, + abs_timeout, + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, + NULL); + if (ret) { + printf("Error: syncobjwait failed %i\n", ret); + return ret; + } + printf("%s: drmSyncobjTimelineWait got %lld!\n", __func__, point); + } + return 0; +} + + +static int test_thread_signal_wait(int devfd, void *(*signal_fn)(void *), + int (*wait_fn)(struct test_arg *)) +{ + uint32_t handle; + struct test_arg d; + pthread_t pth; + int ret; + + ret =3D drmSyncobjCreate(devfd, 0, &handle); + if (ret) { + printf("Error: Couldn't create syncobj\n"); + return ret; + } + + d.dev_fd =3D devfd; + d.handle =3D handle; + + pthread_create(&pth, 0, signal_fn, &d); + ret =3D wait_fn(&d); + pthread_join(pth, NULL); + drmSyncobjDestroy(devfd, handle); + + return ret; +} + +static int test_fork_signal_wait(int devfd, void *(*signal_fn)(void *), + int (*wait_fn)(struct test_arg *)) +{ + uint32_t handle; + struct test_arg p, c; + pid_t id; + int ret; + + ret =3D drmSyncobjCreate(devfd, 0, &handle); + if (ret) { + printf("Error: Couldn't create syncobj\n"); + return ret; + } + + p.dev_fd =3D devfd; + p.handle =3D 0; + p.handle_fd =3D 0; + c =3D p; + p.handle =3D handle; + + ret =3D drmSyncobjHandleToFD(devfd, handle, &c.handle_fd); + if (ret) { + printf("Error: Couldn't convert handle to fd\n"); + goto out; + } + + id =3D fork(); + if (id =3D=3D 0) { + ret =3D drmSyncobjFDToHandle(c.dev_fd, c.handle_fd, &c.handle); + if (ret) { + printf("Error: Couldn't convert fd to handle\n"); + exit(-1); + } + close(c.handle_fd); + signal_fn((void *)&c); + exit(0); + } else { + ret =3D wait_fn(&p); + waitpid(id, 0, 0); + } + +out: + if (c.handle_fd) + close(c.handle_fd); + drmSyncobjDestroy(devfd, handle); + + return ret; +} + + +static int test_badparameters(int devfd) +{ + uint32_t handle1, handle2; + int ret, fail =3D 0; + + /* create bad fd */ + ret =3D drmSyncobjCreate(-1, 0, &handle1); + if (!ret || errno !=3D EBADF) { + printf("drmSyncobjCreate - bad fd fails! (%i !=3D EBADF)\n", errno); + fail =3D 1; + } + /* destroy bad fd */ + ret =3D drmSyncobjDestroy(-1, handle1); + if (!ret || errno !=3D EBADF) { + printf("drmSyncobjDestroy - bad fd fails! (%i !=3D EBADF)\n", errno); + fail =3D 1; + } + + /* TODO: Bad flags */ + + ret =3D drmSyncobjCreate(devfd, 0, &handle1); + if (ret) { + printf("drmSyncobjCreate - unexpected failure!\n"); + fail =3D 1; + } + + /* Destroy zeroed handle */ + handle2 =3D 0; + ret =3D drmSyncobjDestroy(devfd, handle2); + if (!ret || errno !=3D EINVAL) { + printf("drmSyncobjDestroy - zero'ed handle! (%i !=3D EINVAL)\n", errno); + fail =3D 1; + } + /* Destroy invalid handle */ + handle2 =3D -1; + ret =3D drmSyncobjDestroy(devfd, handle2); + if (!ret || errno !=3D EINVAL) { + printf("drmSyncobjDestroy - invalid handle! (%i !=3D EINVAL)\n", errno); + fail =3D 1; + } + + /* invalid timeouts */ + ret =3D drmSyncobjWait(devfd, &handle1, 1, 1000, + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, + NULL); + if (!ret || errno !=3D ETIME) { + printf("drmSyncobjWait - invalid timeout (relative)! (%i !=3D ETIME)\n",= errno); + fail =3D 1; + } + + ret =3D drmSyncobjWait(devfd, &handle1, 1, -1, + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, + NULL); + if (!ret || errno !=3D ETIME) { + printf("drmSyncobjWait - invalid timeout (-1)! (%i !=3D ETIME)\n", errno= ); + fail =3D 1; + } + + ret =3D drmSyncobjDestroy(devfd, handle1); + if (ret) { + printf("drmSyncobjDestroy - unexpected failure!\n"); + fail =3D 1; + } + + + return fail; +} + + +#define NAME_LEN 16 +static int check_device(int fd) +{ + drm_version_t version =3D { 0 }; + char name[NAME_LEN]; + uint32_t handle; + int ret; + + memset(name, 0, NAME_LEN); + version.name_len =3D NAME_LEN; + version.name =3D name; + + ret =3D ioctl(fd, DRM_IOCTL_VERSION, &version); + if (ret) + return -1; + + printf("%s name: %s\n", __func__, name); + + ret =3D drmSyncobjCreate(fd, 0, &handle); + if (!ret) { + drmSyncobjDestroy(fd, handle); + printf("%s selected: %s\n", __func__, name); + } + return ret; +} + +static int find_device(void) +{ + int i, fd; + const char *drmstr =3D "/dev/dri/card"; + + fd =3D -1; + for (i =3D 0; i < 16; i++) { + char name[80]; + + snprintf(name, 80, "%s%u", drmstr, i); + + fd =3D open(name, O_RDWR); + if (fd < 0) + continue; + + if (check_device(fd)) { + close(fd); + fd =3D -1; + continue; + } else { + break; + } + } + return fd; +} + +int main(int argc, char **argv) +{ + int devfd =3D find_device(); + char *testname; + int ret; + + if (devfd < 0) { + printf("Error: Couldn't find supported drm device\n"); + return devfd; + } + + testname =3D "Bad parameters test"; + printf("\n%s\n", testname); + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"); + ret =3D test_badparameters(devfd); + if (ret) + printf("%s: FAILED\n", testname); + else + printf("%s: PASSED\n", testname); + + + testname =3D "Threaded reset test"; + printf("\n%s\n", testname); + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"); + ret =3D test_thread_signal_wait(devfd, &syncobj_signal_reset, &syncobj_wa= it_reset); + if (ret) + printf("%s: FAILED\n", testname); + else + printf("%s: PASSED\n", testname); + + testname =3D "Threaded timeline test"; + printf("\n%s\n", testname); + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"); + ret =3D test_thread_signal_wait(devfd, &syncobj_signal_timeline, &syncobj= _timeline_wait); + if (ret) + printf("%s: FAILED\n", testname); + else + printf("%s: PASSED\n", testname); + + + testname =3D "Forked reset test"; + printf("\n%s\n", testname); + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"); + ret =3D test_fork_signal_wait(devfd, &syncobj_signal_reset, &syncobj_wait= _reset); + if (ret) + printf("\n%s: FAILED\n", testname); + else + printf("\n%s: PASSED\n", testname); + + testname =3D "Forked timeline test"; + printf("\n%s\n", testname); + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"); + ret =3D test_fork_signal_wait(devfd, &syncobj_signal_timeline, &syncobj_t= imeline_wait); + if (ret) + printf("\n%s: FAILED\n", testname); + else + printf("\n%s: PASSED\n", testname); + + + close(devfd); + return 0; +} --=20 2.37.0.144.g8ac04bfd2-goog