CM5: PTP_SYS_OFFSET_EXTENDED on the macb PHC (RP1) is occasionally ~4 µs off - phc2sys inherits it
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 47/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- c, linux
- Lĩnh vực
- networking, operating-systems
Hướng nghiên cứu
Start with drivers/net/ethernet/cadence/macb_ptp.c, especially gem_tsu_get_time(), which the report identifies as bracketing only the first TN read. Compare how PTP_SYS_OFFSET_EXTENDED and PTP_SYS_OFFSET collect timestamps, then reproduce on a CM5 using the attached probe and /dev/ptp1. Done means the extended method no longer shows the reported occasional ~4.1 µs offset; the cause is still unknown, so investigation will be needed.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
On CM5, PTP_SYS_OFFSET_EXTENDED on the Ethernet MAC's PHC (macb / gem-ptp-timer, behind RP1) occasionally returns a PHC/system time pair that is off by about 4.1 µs. PTP_SYS_OFFSET (basic) on the same clock, and a plain clock_gettime(CLOCK_REALTIME) / clock_gettime(PHC) / clock_gettime(CLOCK_REALTIME) from user space, never show it.
phc2sys (linuxptp 4.2) picks the extended ioctl automatically and has no option to avoid it. As a result, every phc2sys instance on the MAC clock shows minutes with max ≈ 4100 ns in its summary statistics, in both directions: PHC → CLOCK_REALTIME (PTP slave) and CLOCK_REALTIME → PHC (grandmaster). ptp4l itself is unaffected, because it uses packet timestamps.
Steps to reproduce the behaviour
- CM5 on CM5IO, PTP hardware timestamps from the MAC (
ethtool --set-hwtimestamp-cfg eth0 index 1 qualifier precise; this is/dev/ptp1). - Optionally run ptp4l so that the PHC is disciplined. The effect also shows without any servo running on CLOCK_REALTIME.
- Build and run the attached probe. It reads PHC minus CLOCK_REALTIME ten times a second in three ways, each as the best of 5 by bracket width:
Columns:gcc -O2 -o sysoff ptp-sysoff.c ./sysoff /dev/ptp1 3000 100 > run.txtt ext_off ext_width basic_off basic_width user_off user_width(ns).
Result over 3000 samples (5 min, nothing steering CLOCK_REALTIME):
| read method | sample-to-sample steps > 2 µs | bracket width (median) |
|---|---|---|
PTP_SYS_OFFSET_EXTENDED |
140, each ±4.1 µs: one sample off, the next back | 55 ns |
PTP_SYS_OFFSET |
0 | 1148 ns |
| user space | 0 | 1500 ns |
- The extended offset differs from the basic one by a median of 527 ns, rising to 4.6 µs in about 2 % of samples.
- Basic and user space agree within 37 ns, and their largest step between samples is 458 ns.
With phc2sys forced to the basic method (an LD_PRELOAD shim making the extended ioctls return EOPNOTSUPP), the 4.1 µs maxima disappear on both sides.
phc2sys summaries over 10 minutes, after one minute of settling:
| extended (default) | basic (shim) | |
|---|---|---|
| phc2sys CLOCK_REALTIME → PHC (grandmaster) | rms ~1 µs in most minutes, max ≈ 4100 ns | rms 24–30 ns, max ≤ 73 ns |
| phc2sys PHC → CLOCK_REALTIME (slave) | 18 of 20 minutes with max ≈ 4100 ns | rms 84–117 ns, max ≤ 333 ns |
| ptp4l on the slave, 16 s windows with max ≥ 1 µs | 12 of 37 | 1 of 38 |
Device (s)
Compute Module 5
System
- Raspberry Pi Compute Module 5 Rev 1.0 on CM5IO
- Debian GNU/Linux 13 (trixie), kernel
6.18.50+rpt-rpi-2712 - linuxptp 4.2-1+b1 (Debian package)
Logs
phc2sys summary (-u 60) with the default (extended) method, one line per minute:
CLOCK_REALTIME rms 1110 max 4207 ... delay 53
CLOCK_REALTIME rms 81 max 259 ... delay 53
CLOCK_REALTIME rms 1339 max 4292 ... delay 53
Additional context
In gem_tsu_get_time() (drivers/net/ethernet/cadence/macb_ptp.c), the pre/post system timestamps bracket only the first TN read. The 55 ns bracket is much narrower than a full PHC read over PCIe takes here (about 1.1 µs, measured by the basic method). We have not found the mechanism behind the occasional 4.1 µs, so this is an observation, not a diagnosis. Happy to run further tests.
ptp-sysoff.c
// Diagnostic: PTP clock minus CLOCK_REALTIME, three ways, side by side.
// ext - PTP_SYS_OFFSET_EXTENDED (the driver brackets its own read; phc2sys uses it)
// basic - PTP_SYS_OFFSET (the kernel brackets the driver's whole gettime)
// user - clock_gettime(REALTIME), clock_gettime(PHC), clock_gettime(REALTIME)
// Each: best of 5 by bracket width. One line per sample:
// t_s ext_off ext_w basic_off basic_w user_off user_w (ns)
// Usage: sysoff /dev/ptp1 <samples> <interval_ms>
#include <fcntl.h>
#include <linux/ptp_clock.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
#define FD_TO_CLOCKID(fd) ((~(clockid_t)(fd) << 3) | 3)
static int64_t pct(const struct ptp_clock_time* t) { return (int64_t)t->sec * 1000000000LL + t->nsec; }
static int64_t tsn(const struct timespec* t) { return (int64_t)t->tv_sec * 1000000000LL + t->tv_nsec; }
int main(int argc, char** argv) {
if (argc < 4) {
fprintf(stderr, "usage: %s /dev/ptpN samples interval_ms\n", argv[0]);
return 2;
}
int fd = open(argv[1], O_RDONLY);
if (fd < 0) { perror(argv[1]); return 1; }
const int n = atoi(argv[2]);
const int ms = atoi(argv[3]);
const clockid_t phc = FD_TO_CLOCKID(fd);
struct timespec t0;
clock_gettime(CLOCK_MONOTONIC, &t0);
for (int k = 0; k < n; ++k) {
// ext
struct ptp_sys_offset_extended e = {0};
e.n_samples = 5;
int64_t extOff = 0, extW = -1;
if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED, &e) == 0) {
for (unsigned i = 0; i < e.n_samples; ++i) {
int64_t pre = pct(&e.ts[i][0]), p = pct(&e.ts[i][1]), post = pct(&e.ts[i][2]);
int64_t w = post - pre;
if (extW < 0 || w < extW) { extW = w; extOff = p - (pre + w / 2); }
}
}
// basic: sys, phc, sys, phc, ..., sys
struct ptp_sys_offset b = {0};
b.n_samples = 5;
int64_t basOff = 0, basW = -1;
if (ioctl(fd, PTP_SYS_OFFSET, &b) == 0) {
for (unsigned i = 0; i < b.n_samples; ++i) {
int64_t pre = pct(&b.ts[2 * i]), p = pct(&b.ts[2 * i + 1]), post = pct(&b.ts[2 * i + 2]);
int64_t w = post - pre;
if (basW < 0 || w < basW) { basW = w; basOff = p - (pre + w / 2); }
}
}
// user
int64_t usrOff = 0, usrW = -1;
for (int i = 0; i < 5; ++i) {
struct timespec a, p, c;
clock_gettime(CLOCK_REALTIME, &a);
clock_gettime(phc, &p);
clock_gettime(CLOCK_REALTIME, &c);
int64_t w = tsn(&c) - tsn(&a);
if (usrW < 0 || w < usrW) { usrW = w; usrOff = tsn(&p) - (tsn(&a) + w / 2); }
}
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
printf("%.3f %lld %lld %lld %lld %lld %lld\n", (tsn(&now) - tsn(&t0)) / 1e9, (long long)extOff, (long long)extW,
(long long)basOff, (long long)basW, (long long)usrOff, (long long)usrW);
fflush(stdout);
usleep(ms * 1000);
}
close(fd);
return 0;
}
- Ngôn ngữ chính
- C
- Star
- 13.3k
- Fork
- 5.5k
- Merge trung bình
- 1 ngày 4 giờ
- Pull request đã merge (30 ngày)
- 21
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của raspberrypi/linux
-
drm/vc4: hdmi: vc4_hdmi_hpd_irq_thread() checks !force_hotplug globally instead of per-connector bitmaskCó thể đã có người làm @popcornmix đã nhận 12 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
raspberrypi/linux#7724 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 63/100
raspberrypi/linux#7718 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
raspberrypi/linux#7415 · 2 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
rp1-cfe doesn't forward V4L2_EVENT_SOURCE_CHANGE event from csi-2 sensor driver to userspace appĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
raspberrypi/linux#7399 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Documentation update requiredĐang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 82/100
raspberrypi/linux#7357 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của raspberrypi/linux
Issue tương tự
-
Implement looks_size reporterĐang mởenhancement good first issue help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
-
bug multiplayer status: planned
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
ChupathingyCE/chupathingyce#851 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 73/100
HigherOrderCO/Bend#2104 ·
-
Research radar digest 2026-W46Đang mởresearch-radar
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
good first issue help wanted program
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
hffgzktbcc-blip/ounce-core#297 ·
Maintainer thường phản hồi trong vòng 1 ngày