Module Name:    src
Committed By:   riastradh
Date:           Sun Dec 19 11:23:52 UTC 2021

Modified Files:
        src/sys/external/bsd/drm2/include/linux: hrtimer.h
        src/sys/external/bsd/drm2/linux: files.drmkms_linux
Added Files:
        src/sys/external/bsd/drm2/linux: linux_hrtimer.c

Log Message:
linux compat: Draft hrtimer shims.

(not actually high-resolution, just a wrapper around callout(9))


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/drm2/include/linux/hrtimer.h
cvs rdiff -u -r1.30 -r1.31 src/sys/external/bsd/drm2/linux/files.drmkms_linux
cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/linux/linux_hrtimer.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/include/linux/hrtimer.h
diff -u src/sys/external/bsd/drm2/include/linux/hrtimer.h:1.3 src/sys/external/bsd/drm2/include/linux/hrtimer.h:1.4
--- src/sys/external/bsd/drm2/include/linux/hrtimer.h:1.3	Sun Dec 19 10:38:05 2021
+++ src/sys/external/bsd/drm2/include/linux/hrtimer.h	Sun Dec 19 11:23:51 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: hrtimer.h,v 1.3 2021/12/19 10:38:05 riastradh Exp $	*/
+/*	$NetBSD: hrtimer.h,v 1.4 2021/12/19 11:23:51 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -32,9 +32,48 @@
 #ifndef _LINUX_HRTIMER_H_
 #define _LINUX_HRTIMER_H_
 
+#include <sys/types.h>
+
+#include <sys/callout.h>
+
+#include <linux/ktime.h>
 #include <linux/timer.h>
 
 struct hrtimer {
+	enum hrtimer_restart (*function)(struct hrtimer *);
+
+	struct hrtimer_private	*hrt_private;
+};
+
+enum hrtimer_mode {
+	HRTIMER_MODE_ABS,
+	HRTIMER_MODE_REL,
 };
 
+enum hrtimer_restart {
+	HRTIMER_NORESTART,
+	HRTIMER_RESTART,
+};
+
+#define	hrtimer_active		linux_hrtimer_active
+#define	hrtimer_add_expires_ns	linux_hrtimer_add_expires_ns
+#define	hrtimer_cancel		linux_hrtimer_cancel
+#define	hrtimer_forward		linux_hrtimer_forward
+#define	hrtimer_forward_now	linux_hrtimer_forward_now
+#define	hrtimer_init		linux_hrtimer_init
+#define	hrtimer_set_expires	linux_hrtimer_set_expiresp
+#define	hrtimer_start		linux_hrtimer_start
+#define	hrtimer_start_range_ns	linux_hrtimer_start_range_ns
+
+void hrtimer_init(struct hrtimer *, clockid_t, enum hrtimer_mode);
+void hrtimer_set_expires(struct hrtimer *, ktime_t);
+void hrtimer_add_expires_ns(struct hrtimer *, uint64_t);
+void hrtimer_start(struct hrtimer *, ktime_t, enum hrtimer_mode);
+void hrtimer_start_range_ns(struct hrtimer *, ktime_t, uint64_t,
+    enum hrtimer_mode);
+int hrtimer_cancel(struct hrtimer *);
+bool hrtimer_active(struct hrtimer *);
+uint64_t hrtimer_forward(struct hrtimer *, ktime_t, ktime_t);
+uint64_t hrtimer_forward_now(struct hrtimer *, ktime_t);
+
 #endif  /* _LINUX_HRTIMER_H_ */

Index: src/sys/external/bsd/drm2/linux/files.drmkms_linux
diff -u src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.30 src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.31
--- src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.30	Sun Dec 19 11:21:30 2021
+++ src/sys/external/bsd/drm2/linux/files.drmkms_linux	Sun Dec 19 11:23:52 2021
@@ -1,4 +1,4 @@
-#       $NetBSD: files.drmkms_linux,v 1.30 2021/12/19 11:21:30 riastradh Exp $
+#       $NetBSD: files.drmkms_linux,v 1.31 2021/12/19 11:23:52 riastradh Exp $
 
 define	drmkms_linux: i2cexec, i2c_bitbang
 
@@ -13,6 +13,7 @@ file	external/bsd/drm2/linux/linux_dma_f
 file	external/bsd/drm2/linux/linux_dma_resv.c	drmkms_linux
 file	external/bsd/drm2/linux/linux_dmi.c		drmkms_linux
 file	external/bsd/drm2/linux/linux_firmware.c	drmkms_linux
+file	external/bsd/drm2/linux/linux_hrtimer.c		drmkms_linux
 file	external/bsd/drm2/linux/linux_i2c.c		drmkms_linux
 file	external/bsd/drm2/linux/linux_idr.c		drmkms_linux
 file	external/bsd/drm2/linux/linux_kmap.c		drmkms_linux

Added files:

Index: src/sys/external/bsd/drm2/linux/linux_hrtimer.c
diff -u /dev/null src/sys/external/bsd/drm2/linux/linux_hrtimer.c:1.1
--- /dev/null	Sun Dec 19 11:23:52 2021
+++ src/sys/external/bsd/drm2/linux/linux_hrtimer.c	Sun Dec 19 11:23:52 2021
@@ -0,0 +1,212 @@
+/*	$NetBSD: linux_hrtimer.c,v 1.1 2021/12/19 11:23:52 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2021 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: linux_hrtimer.c,v 1.1 2021/12/19 11:23:52 riastradh Exp $");
+
+#include <sys/types.h>
+#include <sys/callout.h>
+#include <sys/kmem.h>
+
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+
+struct hrtimer_private {
+	struct callout		ch;
+	enum hrtimer_mode	mode;
+	ktime_t			expires;
+};
+
+static void hrtimer_fire(void *);
+
+void
+hrtimer_init(struct hrtimer *hrt, clockid_t clkid, enum hrtimer_mode mode)
+{
+	struct hrtimer_private *H;
+
+	KASSERTMSG(clkid == CLOCK_MONOTONIC, "clkid %d", clkid);
+
+	H = hrt->hrt_private = kmem_zalloc(sizeof(*H), KM_SLEEP);
+
+	callout_init(&H->ch, CALLOUT_MPSAFE);
+	callout_setfunc(&H->ch, hrtimer_fire, H);
+	H->mode = mode;
+}
+
+static void
+_hrtimer_schedule(struct hrtimer *hrt)
+{
+	struct hrtimer_private *H = hrt->hrt_private;
+	int delta;
+
+	switch (H->mode) {
+	case HRTIMER_MODE_ABS:
+		panic("absolute hrtimer NYI");
+		break;
+	case HRTIMER_MODE_REL:
+		delta = ktime_to_ms(H->expires);
+		break;
+	default:
+		panic("invalid hrtimer mode %d", H->mode);
+	}
+	callout_schedule(&H->ch, delta);
+}
+
+static void
+hrtimer_fire(void *cookie)
+{
+	struct hrtimer *hrt = cookie;
+	struct hrtimer_private *H = hrt->hrt_private;
+
+	switch ((*hrt->function)(hrt)) {
+	case HRTIMER_RESTART:
+		_hrtimer_schedule(hrt);
+		break;
+	case HRTIMER_NORESTART:
+		break;
+	}
+
+	callout_ack(&H->ch);
+}
+
+void
+hrtimer_set_expires(struct hrtimer *hrt, ktime_t expires)
+{
+	struct hrtimer_private *H = hrt->hrt_private;
+
+	H->expires = expires;
+}
+
+void
+hrtimer_add_expires_ns(struct hrtimer *hrt, uint64_t ns)
+{
+	struct hrtimer_private *H = hrt->hrt_private;
+
+	H->expires = ktime_add_ns(H->expires, ns);
+}
+
+void
+hrtimer_start(struct hrtimer *hrt, ktime_t expires, enum hrtimer_mode mode)
+{
+
+	hrtimer_start_range_ns(hrt, expires, 0, mode);
+}
+
+void
+hrtimer_start_range_ns(struct hrtimer *hrt, ktime_t expires, uint64_t range_ns,
+    enum hrtimer_mode mode)
+{
+	struct hrtimer_private *H = hrt->hrt_private;
+
+	H->expires = expires;
+	(void)range_ns;
+	H->mode = mode;
+	_hrtimer_schedule(hrt);
+}
+
+int
+hrtimer_cancel(struct hrtimer *hrt)
+{
+	struct hrtimer_private *H = hrt->hrt_private;
+	bool active;
+
+	/*
+	 * Halt the callout and ascertain whether the hrtimer was
+	 * active when we invoked hrtimer_cancel.
+	 */
+	if (callout_halt(&H->ch, NULL)) {
+		/* Callout expired, meaning it was active.  */
+		active = true;
+	} else {
+		/*
+		 * Callout had not yet expired.  It will not expire
+		 * now, so callout_pending is now stable and
+		 * corresponds with whether the hrtimer was active or
+		 * not.
+		 */
+		active = callout_pending(&H->ch);
+	}
+
+	callout_destroy(&H->ch);
+	kmem_free(H, sizeof(*H));
+
+	explicit_memset(hrt, 0, sizeof(*hrt)); /* paranoia */
+
+	return active;
+}
+
+bool
+hrtimer_active(struct hrtimer *hrt)
+{
+	struct hrtimer_private *H = hrt->hrt_private;
+
+	/*
+	 * If the callout has been scheduled, but has not yet fired,
+	 * then it is pending.
+	 *
+	 * If the callout has fired, but has not yet reached
+	 * callout_ack, then it is invoking.
+	 */
+	return callout_pending(&H->ch) || callout_invoking(&H->ch);
+}
+
+uint64_t
+hrtimer_forward(struct hrtimer *hrt, ktime_t now, ktime_t period)
+{
+	struct hrtimer_private *H = hrt->hrt_private;
+	uint64_t now_ms, period_ms, expires_ms, nperiods;
+
+	KASSERT(!callout_pending(&H->ch));
+
+	/*
+	 * Can't get better than 10ms precision (or ~1ms if you set
+	 * HZ=1000) so not much point in doing this arithmetic at finer
+	 * resolution than ms.
+	 */
+	now_ms = ktime_to_ms(now);
+	period_ms = ktime_to_ms(period);
+	expires_ms = ktime_to_ms(H->expires);
+
+	/* If it hasn't yet expired, no overruns.  */
+	if (now_ms < expires_ms)
+		return 0;
+
+	/* Advance it by as many periods as it should have fired.  */
+	/* XXX fenceposts */
+	nperiods = howmany(now_ms - expires_ms, period_ms);
+	H->expires = ktime_add_ns(H->expires, 1000000*nperiods*period_ms);
+
+	return nperiods;
+}
+
+uint64_t
+hrtimer_forward_now(struct hrtimer *hrt, ktime_t period)
+{
+
+	return hrtimer_forward(hrt, ktime_get(), period);
+}

Reply via email to