net: ptp: clock: Add usermode support to ptp_clock_get()
It is useful that the ptp_clock_get() function can be called from
the userspace. Create also unit test for calling that function
from userspace.
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt
index aa770c1..57acca6 100644
--- a/drivers/CMakeLists.txt
+++ b/drivers/CMakeLists.txt
@@ -43,3 +43,4 @@
add_subdirectory_ifdef(CONFIG_ENTROPY_HAS_DRIVER entropy)
add_subdirectory_ifdef(CONFIG_SYS_CLOCK_EXISTS timer)
add_subdirectory_ifdef(CONFIG_NEURAL_NET_ACCEL neural_net)
+add_subdirectory_ifdef(CONFIG_PTP_CLOCK ptp_clock)
diff --git a/drivers/ptp_clock/CMakeLists.txt b/drivers/ptp_clock/CMakeLists.txt
new file mode 100644
index 0000000..6ece304
--- /dev/null
+++ b/drivers/ptp_clock/CMakeLists.txt
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_sources_ifdef(CONFIG_PTP_CLOCK ptp_clock.c)
diff --git a/drivers/ptp_clock/ptp_clock.c b/drivers/ptp_clock/ptp_clock.c
new file mode 100644
index 0000000..ce9ce02
--- /dev/null
+++ b/drivers/ptp_clock/ptp_clock.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <syscall_handler.h>
+#include <ptp_clock.h>
+
+#ifdef CONFIG_USERSPACE
+Z_SYSCALL_HANDLER(ptp_clock_get, dev, tm)
+{
+ struct net_ptp_time ptp_time;
+ int ret;
+
+ Z_OOPS(Z_SYSCALL_DRIVER_PTP_CLOCK(dev, get));
+ Z_OOPS(Z_SYSCALL_MEMORY_WRITE(tm, sizeof(struct net_ptp_time)));
+
+ ret = z_impl_ptp_clock_get((struct device *)dev, &ptp_time);
+ if (ret != 0) {
+ return 0;
+ }
+
+ if (z_user_to_copy((void *)tm, &ptp_time, sizeof(ptp_time)) != 0) {
+ return 0;
+ }
+
+ return (u32_t)ret;
+}
+#endif /* CONFIG_USERSPACE */
diff --git a/include/ptp_clock.h b/include/ptp_clock.h
index 68120b9..edb9084 100644
--- a/include/ptp_clock.h
+++ b/include/ptp_clock.h
@@ -7,6 +7,7 @@
#ifndef ZEPHYR_INCLUDE_PTP_CLOCK_H_
#define ZEPHYR_INCLUDE_PTP_CLOCK_H_
+#include <kernel.h>
#include <stdint.h>
#include <device.h>
#include <misc/util.h>
@@ -51,7 +52,10 @@
*
* @return 0 if ok, <0 if error
*/
-static inline int ptp_clock_get(struct device *dev, struct net_ptp_time *tm)
+__syscall int ptp_clock_get(struct device *dev, struct net_ptp_time *tm);
+
+static inline int z_impl_ptp_clock_get(struct device *dev,
+ struct net_ptp_time *tm)
{
const struct ptp_clock_driver_api *api = dev->driver_api;
@@ -88,6 +92,8 @@
return api->rate_adjust(dev, rate);
}
+#include <syscalls/ptp_clock.h>
+
#ifdef __cplusplus
}
#endif
diff --git a/scripts/gen_kobject_list.py b/scripts/gen_kobject_list.py
index d4aa54d..8cf04ab 100755
--- a/scripts/gen_kobject_list.py
+++ b/scripts/gen_kobject_list.py
@@ -112,6 +112,7 @@
"spi_driver_api",
"uart_driver_api",
"can_driver_api",
+ "ptp_clock_driver_api",
]
diff --git a/tests/net/ptp/clock/src/main.c b/tests/net/ptp/clock/src/main.c
index 1ca2d06..88e45d3 100644
--- a/tests/net/ptp/clock/src/main.c
+++ b/tests/net/ptp/clock/src/main.c
@@ -394,6 +394,7 @@
static void test_ptp_clock_interfaces(void)
{
+ struct device *clk_by_index;
struct device *clk;
int idx;
@@ -410,6 +411,11 @@
clk = net_eth_get_ptp_clock(eth_interfaces[non_ptp_interface]);
zassert_is_null(clk, "Clock found for interface %p\n",
eth_interfaces[non_ptp_interface]);
+
+ clk_by_index = net_eth_get_ptp_clock_by_index(ptp_clocks[0]);
+ zassert_not_null(clk_by_index,
+ "Clock not found for interface index %d\n",
+ ptp_clocks[0]);
}
static void test_ptp_clock_iface(int idx)
@@ -504,8 +510,51 @@
zassert_equal(clk1, clk_by_index, "Invalid PTP clock 1");
}
+static ZTEST_BMEM struct net_ptp_time tm;
+static ZTEST_BMEM struct net_ptp_time empty;
+
+static void test_ptp_clock_get_by_xxx(const char *who)
+{
+ struct device *clk_by_index;
+ int ret;
+
+ clk_by_index = net_eth_get_ptp_clock_by_index(ptp_clocks[0]);
+ zassert_not_null(clk_by_index, "PTP 0 not found (%s)", who);
+ zassert_equal(clk0, clk_by_index, "Invalid PTP clock 0 (%s)", who);
+
+ (void)memset(&tm, 0, sizeof(tm));
+ ptp_clock_get(clk_by_index, &tm);
+
+ ret = memcmp(&tm, &empty, sizeof(tm));
+ zassert_not_equal(ret, 0, "ptp_clock_get() failed in %s mode", who);
+}
+
+static void test_ptp_clock_get_kernel(void)
+{
+ struct device *clk;
+
+ /* Make sure that this function is really run in kernel mode by
+ * calling a function that will not work in user mode.
+ */
+ clk = net_eth_get_ptp_clock(eth_interfaces[0]);
+
+ test_ptp_clock_get_by_xxx("kernel");
+}
+
+static void test_ptp_clock_get_user(void)
+{
+ test_ptp_clock_get_by_xxx("user");
+}
+
void test_main(void)
{
+ struct device *clk;
+
+ clk = device_get_binding(PTP_CLOCK_NAME);
+ if (clk != NULL) {
+ k_object_access_grant(clk, k_current_get());
+ }
+
ztest_test_suite(ptp_clock_test,
ztest_unit_test(check_interfaces),
ztest_unit_test(address_setup),
@@ -513,7 +562,9 @@
ztest_unit_test(test_ptp_clock_iface_1),
ztest_unit_test(test_ptp_clock_iface_2),
ztest_unit_test(test_ptp_clock_get_by_index),
- ztest_user_unit_test(test_ptp_clock_get_by_index_user)
+ ztest_user_unit_test(test_ptp_clock_get_by_index_user),
+ ztest_unit_test(test_ptp_clock_get_kernel),
+ ztest_user_unit_test(test_ptp_clock_get_user)
);
ztest_run_test_suite(ptp_clock_test);
diff --git a/tests/net/ptp/clock/testcase.yaml b/tests/net/ptp/clock/testcase.yaml
index fa33ec5..c0eb38c 100644
--- a/tests/net/ptp/clock/testcase.yaml
+++ b/tests/net/ptp/clock/testcase.yaml
@@ -1,6 +1,5 @@
common:
depends_on: netif
- platform_whitelist: native_posix qemu_x86 qemu_cortex_m3
tests:
net.ptp.clock:
min_ram: 32