mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
net: allow simultaneous SW and HW transmit timestamping
Add SOF_TIMESTAMPING_OPT_TX_SWHW option to allow an outgoing packet to be looped to the socket's error queue with a software timestamp even when a hardware transmit timestamp is expected to be provided by the driver. Applications using this option will receive two separate messages from the error queue, one with a software timestamp and the other with a hardware timestamp. As the hardware timestamp is saved to the shared skb info, which may happen before the first message with software timestamp is received by the application, the hardware timestamp is copied to the SCM_TIMESTAMPING control message only when the skb has no software timestamp or it is an incoming packet. While changing sw_tx_timestamp(), inline it in skb_tx_timestamp() as there are no other users. CC: Richard Cochran <richardcochran@gmail.com> CC: Willem de Bruijn <willemb@google.com> Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
67953d47bb
commit
b50a5c70ff
20
net/socket.c
20
net/socket.c
@@ -662,6 +662,19 @@ static bool skb_is_err_queue(const struct sk_buff *skb)
|
||||
return skb->pkt_type == PACKET_OUTGOING;
|
||||
}
|
||||
|
||||
/* On transmit, software and hardware timestamps are returned independently.
|
||||
* As the two skb clones share the hardware timestamp, which may be updated
|
||||
* before the software timestamp is received, a hardware TX timestamp may be
|
||||
* returned only if there is no software TX timestamp. Ignore false software
|
||||
* timestamps, which may be made in the __sock_recv_timestamp() call when the
|
||||
* option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a
|
||||
* hardware timestamp.
|
||||
*/
|
||||
static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
|
||||
{
|
||||
return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
|
||||
}
|
||||
|
||||
static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
|
||||
{
|
||||
struct scm_ts_pktinfo ts_pktinfo;
|
||||
@@ -691,14 +704,16 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
|
||||
{
|
||||
int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
|
||||
struct scm_timestamping tss;
|
||||
int empty = 1;
|
||||
int empty = 1, false_tstamp = 0;
|
||||
struct skb_shared_hwtstamps *shhwtstamps =
|
||||
skb_hwtstamps(skb);
|
||||
|
||||
/* Race occurred between timestamp enabling and packet
|
||||
receiving. Fill in the current time for now. */
|
||||
if (need_software_tstamp && skb->tstamp == 0)
|
||||
if (need_software_tstamp && skb->tstamp == 0) {
|
||||
__net_timestamp(skb);
|
||||
false_tstamp = 1;
|
||||
}
|
||||
|
||||
if (need_software_tstamp) {
|
||||
if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
|
||||
@@ -720,6 +735,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
|
||||
empty = 0;
|
||||
if (shhwtstamps &&
|
||||
(sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
|
||||
!skb_is_swtx_tstamp(skb, false_tstamp) &&
|
||||
ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
|
||||
empty = 0;
|
||||
if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
|
||||
|
Reference in New Issue
Block a user