@@ -389,6 +389,13 @@ AC_ARG_ENABLE(testing, AS_HELP_STRING([--enable-testing],
[enable_testing=${enableval}])
AM_CONDITIONAL(TESTING, test "${enable_testing}" = "yes")
+if (test "${enable_testing}" = "yes"); then
+ AC_CHECK_DECLS([SOF_TIMESTAMPING_TX_COMPLETION, SCM_TSTAMP_COMPLETION],
+ [], [], [[#include <time.h>
+ #include <linux/errqueue.h>
+ #include <linux/net_tstamp.h>]])
+fi
+
AC_ARG_ENABLE(experimental, AS_HELP_STRING([--enable-experimental],
[enable experimental tools]),
[enable_experimental=${enableval}])
@@ -1066,20 +1066,10 @@ static const struct iso_client_data connect_send_tx_timestamping = {
.send = &send_16_2_1,
.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_OPT_ID |
- SOF_TIMESTAMPING_TX_SOFTWARE),
- .repeat_send = 1,
- .repeat_send_pre_ts = 2,
-};
-
-static const struct iso_client_data connect_send_tx_sched_timestamping = {
- .qos = QOS_16_2_1,
- .expect_err = 0,
- .send = &send_16_2_1,
- .so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_TX_SOFTWARE |
- SOF_TIMESTAMPING_OPT_TSONLY |
- SOF_TIMESTAMPING_TX_SCHED),
+ SOF_TIMESTAMPING_TX_COMPLETION),
.repeat_send = 1,
+ .repeat_send_pre_ts = 2,
};
static const struct iso_client_data connect_send_tx_cmsg_timestamping = {
@@ -1087,7 +1077,8 @@ static const struct iso_client_data connect_send_tx_cmsg_timestamping = {
.expect_err = 0,
.send = &send_16_2_1,
.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
- SOF_TIMESTAMPING_TX_SOFTWARE),
+ SOF_TIMESTAMPING_OPT_TSONLY |
+ SOF_TIMESTAMPING_TX_COMPLETION),
.repeat_send = 1,
.cmsg_timestamping = true,
};
@@ -1097,7 +1088,7 @@ static const struct iso_client_data connect_send_tx_no_poll_timestamping = {
.expect_err = 0,
.send = &send_16_2_1,
.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
- SOF_TIMESTAMPING_TX_SOFTWARE),
+ SOF_TIMESTAMPING_TX_COMPLETION),
.repeat_send = 1,
.no_poll_errqueue = true,
};
@@ -2241,10 +2232,10 @@ static gboolean iso_recv_errqueue(GIOChannel *io, GIOCondition cond,
err = tx_tstamp_recv(&data->tx_ts, sk, isodata->send->iov_len);
if (err > 0)
return TRUE;
- else if (!err && !data->step)
- tester_test_passed();
- else
+ else if (err)
tester_test_failed();
+ else if (!data->step)
+ tester_test_passed();
data->io_id[2] = 0;
return FALSE;
@@ -2289,7 +2280,7 @@ static void iso_tx_timestamping(struct test_data *data, GIOChannel *io)
int err;
unsigned int count;
- if (!(isodata->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK))
+ if (!(isodata->so_timestamping & TS_TX_RECORD_MASK))
return;
tester_print("Enabling TX timestamping");
@@ -2336,7 +2327,7 @@ static void iso_tx_timestamping(struct test_data *data, GIOChannel *io)
}
if (isodata->cmsg_timestamping)
- so &= ~SOF_TIMESTAMPING_TX_RECORD_MASK;
+ so &= ~TS_TX_RECORD_MASK;
err = setsockopt(sk, SOL_SOCKET, SO_TIMESTAMPING, &so, sizeof(so));
if (err < 0) {
@@ -2374,7 +2365,7 @@ static void iso_send_data(struct test_data *data, GIOChannel *io)
cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
*((uint32_t *)CMSG_DATA(cmsg)) = (isodata->so_timestamping &
- SOF_TIMESTAMPING_TX_RECORD_MASK);
+ TS_TX_RECORD_MASK);
}
ret = sendmsg(sk, &msg, 0);
@@ -3645,11 +3636,6 @@ int main(int argc, char *argv[])
test_iso("ISO Send - TX Timestamping", &connect_send_tx_timestamping,
setup_powered, test_connect);
- /* Test schedule-time TX timestamps are emitted */
- test_iso("ISO Send - TX Sched Timestamping",
- &connect_send_tx_sched_timestamping, setup_powered,
- test_connect);
-
/* Test TX timestamping with flags set via per-packet CMSG */
test_iso("ISO Send - TX CMSG Timestamping",
&connect_send_tx_cmsg_timestamping, setup_powered,
@@ -381,7 +381,8 @@ static const struct l2cap_data client_connect_tx_timestamping_test = {
.data_len = sizeof(l2_data),
.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_OPT_ID |
- SOF_TIMESTAMPING_TX_SOFTWARE),
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_TX_COMPLETION),
.repeat_send = 2,
};
@@ -594,7 +595,8 @@ static const struct l2cap_data le_client_connect_tx_timestamping_test = {
.data_len = sizeof(l2_data),
.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_OPT_ID |
- SOF_TIMESTAMPING_TX_SOFTWARE),
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_TX_COMPLETION),
};
static const struct l2cap_data le_client_connect_adv_success_test_1 = {
@@ -1345,10 +1347,10 @@ static gboolean recv_errqueue(GIOChannel *io, GIOCondition cond,
err = tx_tstamp_recv(&data->tx_ts, sk, l2data->data_len);
if (err > 0)
return TRUE;
- else if (!err && !data->step)
- tester_test_passed();
- else
+ else if (err)
tester_test_failed();
+ else if (!data->step)
+ tester_test_passed();
data->err_io_id = 0;
return FALSE;
@@ -1362,7 +1364,7 @@ static void l2cap_tx_timestamping(struct test_data *data, GIOChannel *io)
int err;
unsigned int count;
- if (!(l2data->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK))
+ if (!(l2data->so_timestamping & TS_TX_RECORD_MASK))
return;
sk = g_io_channel_unix_get_fd(io);
@@ -665,10 +665,10 @@ static gboolean recv_errqueue(GIOChannel *io, GIOCondition cond,
err = tx_tstamp_recv(&data->tx_ts, sk, scodata->data_len);
if (err > 0)
return TRUE;
- else if (!err && !data->step)
- tester_test_passed();
- else
+ else if (err)
tester_test_failed();
+ else if (!data->step)
+ tester_test_passed();
data->err_io_id = 0;
return FALSE;
@@ -682,7 +682,7 @@ static void sco_tx_timestamping(struct test_data *data, GIOChannel *io)
int err;
unsigned int count;
- if (!(scodata->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK))
+ if (!(scodata->so_timestamping & TS_TX_RECORD_MASK))
return;
sk = g_io_channel_unix_get_fd(io);
@@ -20,6 +20,15 @@
#define SEC_NSEC(_t) ((_t) * 1000000000LL)
#define TS_NSEC(_ts) (SEC_NSEC((_ts)->tv_sec) + (_ts)->tv_nsec)
+#if !HAVE_DECL_SOF_TIMESTAMPING_TX_COMPLETION
+#define SOF_TIMESTAMPING_TX_COMPLETION (SOF_TIMESTAMPING_LAST << 1)
+#endif
+#if !HAVE_DECL_SCM_TSTAMP_COMPLETION
+#define SCM_TSTAMP_COMPLETION (SCM_TSTAMP_ACK + 1)
+#endif
+#define TS_TX_RECORD_MASK (SOF_TIMESTAMPING_TX_RECORD_MASK | \
+ SOF_TIMESTAMPING_TX_COMPLETION)
+
struct tx_tstamp_data {
struct {
uint32_t id;
@@ -59,6 +68,13 @@ static inline int tx_tstamp_expect(struct tx_tstamp_data *data)
pos++;
}
+ if (data->so_timestamping & SOF_TIMESTAMPING_TX_COMPLETION) {
+ g_assert(pos < ARRAY_SIZE(data->expect));
+ data->expect[pos].type = SCM_TSTAMP_COMPLETION;
+ data->expect[pos].id = data->sent;
+ pos++;
+ }
+
data->sent++;
steps = pos - data->count;
@@ -77,6 +93,7 @@ static inline int tx_tstamp_recv(struct tx_tstamp_data *data, int sk, int len)
struct scm_timestamping *tss = NULL;
struct sock_extended_err *serr = NULL;
struct timespec now;
+ unsigned int i;
iov.iov_base = buf;
iov.iov_len = sizeof(buf);
@@ -89,7 +106,7 @@ static inline int tx_tstamp_recv(struct tx_tstamp_data *data, int sk, int len)
ret = recvmsg(sk, &msg, MSG_ERRQUEUE);
if (ret < 0) {
- if (ret == EAGAIN || ret == EWOULDBLOCK)
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
return data->count - data->pos;
tester_warn("Failed to read from errqueue: %s (%d)",
@@ -147,18 +164,29 @@ static inline int tx_tstamp_recv(struct tx_tstamp_data *data, int sk, int len)
return -EINVAL;
}
- if ((data->so_timestamping & SOF_TIMESTAMPING_OPT_ID) &&
- serr->ee_data != data->expect[data->pos].id) {
- tester_warn("Bad timestamp id %u", serr->ee_data);
+ /* Find first unreceived timestamp of the right type */
+ for (i = 0; i < data->count; ++i) {
+ if (data->expect[i].type >= 0xffff)
+ continue;
+
+ if (serr->ee_info == data->expect[i].type) {
+ data->expect[i].type = 0xffff;
+ break;
+ }
+ }
+ if (i == data->count) {
+ tester_warn("Bad timestamp type %u", serr->ee_info);
return -EINVAL;
}
- if (serr->ee_info != data->expect[data->pos].type) {
- tester_warn("Bad timestamp type %u", serr->ee_info);
+ if ((data->so_timestamping & SOF_TIMESTAMPING_OPT_ID) &&
+ serr->ee_data != data->expect[i].id) {
+ tester_warn("Bad timestamp id %u", serr->ee_data);
return -EINVAL;
}
- tester_print("Got valid TX timestamp %u", data->pos);
+ tester_print("Got valid TX timestamp %u (type %u, id %u)", i,
+ serr->ee_info, serr->ee_data);
++data->pos;