]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 Dec 2018 10:30:13 +0000 (11:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 Dec 2018 10:30:13 +0000 (11:30 +0100)
added patches:
exec-avoid-gcc-8-warning-for-get_task_comm.patch
selftests-move-networking-timestamping-from-documentation.patch
staging-rts5208-fix-gcc-8-logic-error-warning.patch
vme-ca91cx42-fix-lm_ctl-address-mask.patch
vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch

queue-3.18/exec-avoid-gcc-8-warning-for-get_task_comm.patch [new file with mode: 0644]
queue-3.18/selftests-move-networking-timestamping-from-documentation.patch [new file with mode: 0644]
queue-3.18/series
queue-3.18/staging-rts5208-fix-gcc-8-logic-error-warning.patch [new file with mode: 0644]
queue-3.18/vme-ca91cx42-fix-lm_ctl-address-mask.patch [new file with mode: 0644]
queue-3.18/vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch [new file with mode: 0644]

diff --git a/queue-3.18/exec-avoid-gcc-8-warning-for-get_task_comm.patch b/queue-3.18/exec-avoid-gcc-8-warning-for-get_task_comm.patch
new file mode 100644 (file)
index 0000000..f2645da
--- /dev/null
@@ -0,0 +1,85 @@
+From 3756f6401c302617c5e091081ca4d26ab604bec5 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Thu, 14 Dec 2017 15:32:41 -0800
+Subject: exec: avoid gcc-8 warning for get_task_comm
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit 3756f6401c302617c5e091081ca4d26ab604bec5 upstream.
+
+gcc-8 warns about using strncpy() with the source size as the limit:
+
+  fs/exec.c:1223:32: error: argument to 'sizeof' in 'strncpy' call is the same expression as the source; did you mean to use the size of the destination? [-Werror=sizeof-pointer-memaccess]
+
+This is indeed slightly suspicious, as it protects us from source
+arguments without NUL-termination, but does not guarantee that the
+destination is terminated.
+
+This keeps the strncpy() to ensure we have properly padded target
+buffer, but ensures that we use the correct length, by passing the
+actual length of the destination buffer as well as adding a build-time
+check to ensure it is exactly TASK_COMM_LEN.
+
+There are only 23 callsites which I all reviewed to ensure this is
+currently the case.  We could get away with doing only the check or
+passing the right length, but it doesn't hurt to do both.
+
+Link: http://lkml.kernel.org/r/20171205151724.1764896-1-arnd@arndb.de
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Suggested-by: Kees Cook <keescook@chromium.org>
+Acked-by: Kees Cook <keescook@chromium.org>
+Acked-by: Ingo Molnar <mingo@kernel.org>
+Cc: Alexander Viro <viro@zeniv.linux.org.uk>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Serge Hallyn <serge@hallyn.com>
+Cc: James Morris <james.l.morris@oracle.com>
+Cc: Aleksa Sarai <asarai@suse.de>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Frederic Weisbecker <frederic@kernel.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/exec.c             |    7 +++----
+ include/linux/sched.h |    7 ++++++-
+ 2 files changed, 9 insertions(+), 5 deletions(-)
+
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -1051,15 +1051,14 @@ killed:
+       return -EAGAIN;
+ }
+-char *get_task_comm(char *buf, struct task_struct *tsk)
++char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
+ {
+-      /* buf must be at least sizeof(tsk->comm) in size */
+       task_lock(tsk);
+-      strncpy(buf, tsk->comm, sizeof(tsk->comm));
++      strncpy(buf, tsk->comm, buf_size);
+       task_unlock(tsk);
+       return buf;
+ }
+-EXPORT_SYMBOL_GPL(get_task_comm);
++EXPORT_SYMBOL_GPL(__get_task_comm);
+ /*
+  * These functions flushes out all traces of the currently running executable
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -2466,7 +2466,12 @@ static inline void set_task_comm(struct
+ {
+       __set_task_comm(tsk, from, false);
+ }
+-extern char *get_task_comm(char *to, struct task_struct *tsk);
++
++extern char *__get_task_comm(char *to, size_t len, struct task_struct *tsk);
++#define get_task_comm(buf, tsk) ({                    \
++      BUILD_BUG_ON(sizeof(buf) != TASK_COMM_LEN);     \
++      __get_task_comm(buf, sizeof(buf), tsk);         \
++})
+ #ifdef CONFIG_SMP
+ void scheduler_ipi(void);
diff --git a/queue-3.18/selftests-move-networking-timestamping-from-documentation.patch b/queue-3.18/selftests-move-networking-timestamping-from-documentation.patch
new file mode 100644 (file)
index 0000000..fe948c1
--- /dev/null
@@ -0,0 +1,2369 @@
+From 3d2c86e3057995270e08693231039d9d942871f0 Mon Sep 17 00:00:00 2001
+From: Shuah Khan <shuahkh@osg.samsung.com>
+Date: Thu, 15 Sep 2016 08:36:07 -0600
+Subject: selftests: Move networking/timestamping from Documentation
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit 3d2c86e3057995270e08693231039d9d942871f0 upstream.
+
+Remove networking from Documentation Makefile to move the test to
+selftests. Update networking/timestamping Makefile to work under
+selftests. These tests will not be run as part of selftests suite
+and will not be included in install targets. They can be built and
+run separately for now.
+
+This is part of the effort to move runnable code from Documentation.
+
+Acked-by: Jonathan Corbet <corbet@lwn.net>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+[ added to 3.18.y stable to remove a build warning - gregkh]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ Documentation/Makefile                                            |    3 
+ Documentation/networking/Makefile                                 |    1 
+ Documentation/networking/timestamping/.gitignore                  |    3 
+ Documentation/networking/timestamping/Makefile                    |   14 
+ Documentation/networking/timestamping/hwtstamp_config.c           |  134 --
+ Documentation/networking/timestamping/timestamping.c              |  528 ----------
+ Documentation/networking/timestamping/txtimestamp.c               |  469 --------
+ tools/testing/selftests/networking/timestamping/.gitignore        |    3 
+ tools/testing/selftests/networking/timestamping/Makefile          |    8 
+ tools/testing/selftests/networking/timestamping/hwtstamp_config.c |  134 ++
+ tools/testing/selftests/networking/timestamping/timestamping.c    |  528 ++++++++++
+ tools/testing/selftests/networking/timestamping/txtimestamp.c     |  469 ++++++++
+ 12 files changed, 1143 insertions(+), 1151 deletions(-)
+
+--- a/Documentation/Makefile
++++ b/Documentation/Makefile
+@@ -1,4 +1,3 @@
+ subdir-y := accounting auxdisplay blackfin connector \
+       filesystems filesystems ia64 laptops misc-devices \
+-      networking pcmcia prctl ptp spi timers vDSO video4linux \
+-      watchdog
++      pcmcia prctl ptp spi timers vDSO video4linux watchdog
+--- a/Documentation/networking/Makefile
++++ /dev/null
+@@ -1 +0,0 @@
+-subdir-y := timestamping
+--- a/Documentation/networking/timestamping/.gitignore
++++ /dev/null
+@@ -1,3 +0,0 @@
+-timestamping
+-txtimestamp
+-hwtstamp_config
+--- a/Documentation/networking/timestamping/Makefile
++++ /dev/null
+@@ -1,14 +0,0 @@
+-# To compile, from the source root
+-#
+-#    make headers_install
+-#    make M=documentation
+-
+-# List of programs to build
+-hostprogs-y := hwtstamp_config timestamping txtimestamp
+-
+-# Tell kbuild to always build the programs
+-always := $(hostprogs-y)
+-
+-HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
+-HOSTCFLAGS_txtimestamp.o += -I$(objtree)/usr/include
+-HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include
+--- a/Documentation/networking/timestamping/hwtstamp_config.c
++++ /dev/null
+@@ -1,134 +0,0 @@
+-/* Test program for SIOC{G,S}HWTSTAMP
+- * Copyright 2013 Solarflare Communications
+- * Author: Ben Hutchings
+- */
+-
+-#include <errno.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-
+-#include <sys/socket.h>
+-#include <sys/ioctl.h>
+-
+-#include <linux/if.h>
+-#include <linux/net_tstamp.h>
+-#include <linux/sockios.h>
+-
+-static int
+-lookup_value(const char **names, int size, const char *name)
+-{
+-      int value;
+-
+-      for (value = 0; value < size; value++)
+-              if (names[value] && strcasecmp(names[value], name) == 0)
+-                      return value;
+-
+-      return -1;
+-}
+-
+-static const char *
+-lookup_name(const char **names, int size, int value)
+-{
+-      return (value >= 0 && value < size) ? names[value] : NULL;
+-}
+-
+-static void list_names(FILE *f, const char **names, int size)
+-{
+-      int value;
+-
+-      for (value = 0; value < size; value++)
+-              if (names[value])
+-                      fprintf(f, "    %s\n", names[value]);
+-}
+-
+-static const char *tx_types[] = {
+-#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
+-      TX_TYPE(OFF),
+-      TX_TYPE(ON),
+-      TX_TYPE(ONESTEP_SYNC)
+-#undef TX_TYPE
+-};
+-#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
+-
+-static const char *rx_filters[] = {
+-#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
+-      RX_FILTER(NONE),
+-      RX_FILTER(ALL),
+-      RX_FILTER(SOME),
+-      RX_FILTER(PTP_V1_L4_EVENT),
+-      RX_FILTER(PTP_V1_L4_SYNC),
+-      RX_FILTER(PTP_V1_L4_DELAY_REQ),
+-      RX_FILTER(PTP_V2_L4_EVENT),
+-      RX_FILTER(PTP_V2_L4_SYNC),
+-      RX_FILTER(PTP_V2_L4_DELAY_REQ),
+-      RX_FILTER(PTP_V2_L2_EVENT),
+-      RX_FILTER(PTP_V2_L2_SYNC),
+-      RX_FILTER(PTP_V2_L2_DELAY_REQ),
+-      RX_FILTER(PTP_V2_EVENT),
+-      RX_FILTER(PTP_V2_SYNC),
+-      RX_FILTER(PTP_V2_DELAY_REQ),
+-#undef RX_FILTER
+-};
+-#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
+-
+-static void usage(void)
+-{
+-      fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
+-            "tx_type is any of (case-insensitive):\n",
+-            stderr);
+-      list_names(stderr, tx_types, N_TX_TYPES);
+-      fputs("rx_filter is any of (case-insensitive):\n", stderr);
+-      list_names(stderr, rx_filters, N_RX_FILTERS);
+-}
+-
+-int main(int argc, char **argv)
+-{
+-      struct ifreq ifr;
+-      struct hwtstamp_config config;
+-      const char *name;
+-      int sock;
+-
+-      if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
+-              usage();
+-              return 2;
+-      }
+-
+-      if (argc == 4) {
+-              config.flags = 0;
+-              config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
+-              config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
+-              if (config.tx_type < 0 || config.rx_filter < 0) {
+-                      usage();
+-                      return 2;
+-              }
+-      }
+-
+-      sock = socket(AF_INET, SOCK_DGRAM, 0);
+-      if (sock < 0) {
+-              perror("socket");
+-              return 1;
+-      }
+-
+-      strcpy(ifr.ifr_name, argv[1]);
+-      ifr.ifr_data = (caddr_t)&config;
+-
+-      if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
+-              perror("ioctl");
+-              return 1;
+-      }
+-
+-      printf("flags = %#x\n", config.flags);
+-      name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
+-      if (name)
+-              printf("tx_type = %s\n", name);
+-      else
+-              printf("tx_type = %d\n", config.tx_type);
+-      name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
+-      if (name)
+-              printf("rx_filter = %s\n", name);
+-      else
+-              printf("rx_filter = %d\n", config.rx_filter);
+-
+-      return 0;
+-}
+--- a/Documentation/networking/timestamping/timestamping.c
++++ /dev/null
+@@ -1,528 +0,0 @@
+-/*
+- * This program demonstrates how the various time stamping features in
+- * the Linux kernel work. It emulates the behavior of a PTP
+- * implementation in stand-alone master mode by sending PTPv1 Sync
+- * multicasts once every second. It looks for similar packets, but
+- * beyond that doesn't actually implement PTP.
+- *
+- * Outgoing packets are time stamped with SO_TIMESTAMPING with or
+- * without hardware support.
+- *
+- * Incoming packets are time stamped with SO_TIMESTAMPING with or
+- * without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
+- * SO_TIMESTAMP[NS].
+- *
+- * Copyright (C) 2009 Intel Corporation.
+- * Author: Patrick Ohly <patrick.ohly@intel.com>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <errno.h>
+-#include <string.h>
+-
+-#include <sys/time.h>
+-#include <sys/socket.h>
+-#include <sys/select.h>
+-#include <sys/ioctl.h>
+-#include <arpa/inet.h>
+-#include <net/if.h>
+-
+-#include <asm/types.h>
+-#include <linux/net_tstamp.h>
+-#include <linux/errqueue.h>
+-
+-#ifndef SO_TIMESTAMPING
+-# define SO_TIMESTAMPING         37
+-# define SCM_TIMESTAMPING        SO_TIMESTAMPING
+-#endif
+-
+-#ifndef SO_TIMESTAMPNS
+-# define SO_TIMESTAMPNS 35
+-#endif
+-
+-#ifndef SIOCGSTAMPNS
+-# define SIOCGSTAMPNS 0x8907
+-#endif
+-
+-#ifndef SIOCSHWTSTAMP
+-# define SIOCSHWTSTAMP 0x89b0
+-#endif
+-
+-static void usage(const char *error)
+-{
+-      if (error)
+-              printf("invalid option: %s\n", error);
+-      printf("timestamping interface option*\n\n"
+-             "Options:\n"
+-             "  IP_MULTICAST_LOOP - looping outgoing multicasts\n"
+-             "  SO_TIMESTAMP - normal software time stamping, ms resolution\n"
+-             "  SO_TIMESTAMPNS - more accurate software time stamping\n"
+-             "  SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
+-             "  SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
+-             "  SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
+-             "  SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
+-             "  SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
+-             "  SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
+-             "  SIOCGSTAMP - check last socket time stamp\n"
+-             "  SIOCGSTAMPNS - more accurate socket time stamp\n");
+-      exit(1);
+-}
+-
+-static void bail(const char *error)
+-{
+-      printf("%s: %s\n", error, strerror(errno));
+-      exit(1);
+-}
+-
+-static const unsigned char sync[] = {
+-      0x00, 0x01, 0x00, 0x01,
+-      0x5f, 0x44, 0x46, 0x4c,
+-      0x54, 0x00, 0x00, 0x00,
+-      0x00, 0x00, 0x00, 0x00,
+-      0x00, 0x00, 0x00, 0x00,
+-      0x01, 0x01,
+-
+-      /* fake uuid */
+-      0x00, 0x01,
+-      0x02, 0x03, 0x04, 0x05,
+-
+-      0x00, 0x01, 0x00, 0x37,
+-      0x00, 0x00, 0x00, 0x08,
+-      0x00, 0x00, 0x00, 0x00,
+-      0x49, 0x05, 0xcd, 0x01,
+-      0x29, 0xb1, 0x8d, 0xb0,
+-      0x00, 0x00, 0x00, 0x00,
+-      0x00, 0x01,
+-
+-      /* fake uuid */
+-      0x00, 0x01,
+-      0x02, 0x03, 0x04, 0x05,
+-
+-      0x00, 0x00, 0x00, 0x37,
+-      0x00, 0x00, 0x00, 0x04,
+-      0x44, 0x46, 0x4c, 0x54,
+-      0x00, 0x00, 0xf0, 0x60,
+-      0x00, 0x01, 0x00, 0x00,
+-      0x00, 0x00, 0x00, 0x01,
+-      0x00, 0x00, 0xf0, 0x60,
+-      0x00, 0x00, 0x00, 0x00,
+-      0x00, 0x00, 0x00, 0x04,
+-      0x44, 0x46, 0x4c, 0x54,
+-      0x00, 0x01,
+-
+-      /* fake uuid */
+-      0x00, 0x01,
+-      0x02, 0x03, 0x04, 0x05,
+-
+-      0x00, 0x00, 0x00, 0x00,
+-      0x00, 0x00, 0x00, 0x00,
+-      0x00, 0x00, 0x00, 0x00,
+-      0x00, 0x00, 0x00, 0x00
+-};
+-
+-static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
+-{
+-      struct timeval now;
+-      int res;
+-
+-      res = sendto(sock, sync, sizeof(sync), 0,
+-              addr, addr_len);
+-      gettimeofday(&now, 0);
+-      if (res < 0)
+-              printf("%s: %s\n", "send", strerror(errno));
+-      else
+-              printf("%ld.%06ld: sent %d bytes\n",
+-                     (long)now.tv_sec, (long)now.tv_usec,
+-                     res);
+-}
+-
+-static void printpacket(struct msghdr *msg, int res,
+-                      char *data,
+-                      int sock, int recvmsg_flags,
+-                      int siocgstamp, int siocgstampns)
+-{
+-      struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
+-      struct cmsghdr *cmsg;
+-      struct timeval tv;
+-      struct timespec ts;
+-      struct timeval now;
+-
+-      gettimeofday(&now, 0);
+-
+-      printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
+-             (long)now.tv_sec, (long)now.tv_usec,
+-             (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
+-             res,
+-             inet_ntoa(from_addr->sin_addr),
+-             msg->msg_controllen);
+-      for (cmsg = CMSG_FIRSTHDR(msg);
+-           cmsg;
+-           cmsg = CMSG_NXTHDR(msg, cmsg)) {
+-              printf("   cmsg len %zu: ", cmsg->cmsg_len);
+-              switch (cmsg->cmsg_level) {
+-              case SOL_SOCKET:
+-                      printf("SOL_SOCKET ");
+-                      switch (cmsg->cmsg_type) {
+-                      case SO_TIMESTAMP: {
+-                              struct timeval *stamp =
+-                                      (struct timeval *)CMSG_DATA(cmsg);
+-                              printf("SO_TIMESTAMP %ld.%06ld",
+-                                     (long)stamp->tv_sec,
+-                                     (long)stamp->tv_usec);
+-                              break;
+-                      }
+-                      case SO_TIMESTAMPNS: {
+-                              struct timespec *stamp =
+-                                      (struct timespec *)CMSG_DATA(cmsg);
+-                              printf("SO_TIMESTAMPNS %ld.%09ld",
+-                                     (long)stamp->tv_sec,
+-                                     (long)stamp->tv_nsec);
+-                              break;
+-                      }
+-                      case SO_TIMESTAMPING: {
+-                              struct timespec *stamp =
+-                                      (struct timespec *)CMSG_DATA(cmsg);
+-                              printf("SO_TIMESTAMPING ");
+-                              printf("SW %ld.%09ld ",
+-                                     (long)stamp->tv_sec,
+-                                     (long)stamp->tv_nsec);
+-                              stamp++;
+-                              /* skip deprecated HW transformed */
+-                              stamp++;
+-                              printf("HW raw %ld.%09ld",
+-                                     (long)stamp->tv_sec,
+-                                     (long)stamp->tv_nsec);
+-                              break;
+-                      }
+-                      default:
+-                              printf("type %d", cmsg->cmsg_type);
+-                              break;
+-                      }
+-                      break;
+-              case IPPROTO_IP:
+-                      printf("IPPROTO_IP ");
+-                      switch (cmsg->cmsg_type) {
+-                      case IP_RECVERR: {
+-                              struct sock_extended_err *err =
+-                                      (struct sock_extended_err *)CMSG_DATA(cmsg);
+-                              printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
+-                                      strerror(err->ee_errno),
+-                                      err->ee_origin,
+-#ifdef SO_EE_ORIGIN_TIMESTAMPING
+-                                      err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
+-                                      "bounced packet" : "unexpected origin"
+-#else
+-                                      "probably SO_EE_ORIGIN_TIMESTAMPING"
+-#endif
+-                                      );
+-                              if (res < sizeof(sync))
+-                                      printf(" => truncated data?!");
+-                              else if (!memcmp(sync, data + res - sizeof(sync),
+-                                                      sizeof(sync)))
+-                                      printf(" => GOT OUR DATA BACK (HURRAY!)");
+-                              break;
+-                      }
+-                      case IP_PKTINFO: {
+-                              struct in_pktinfo *pktinfo =
+-                                      (struct in_pktinfo *)CMSG_DATA(cmsg);
+-                              printf("IP_PKTINFO interface index %u",
+-                                      pktinfo->ipi_ifindex);
+-                              break;
+-                      }
+-                      default:
+-                              printf("type %d", cmsg->cmsg_type);
+-                              break;
+-                      }
+-                      break;
+-              default:
+-                      printf("level %d type %d",
+-                              cmsg->cmsg_level,
+-                              cmsg->cmsg_type);
+-                      break;
+-              }
+-              printf("\n");
+-      }
+-
+-      if (siocgstamp) {
+-              if (ioctl(sock, SIOCGSTAMP, &tv))
+-                      printf("   %s: %s\n", "SIOCGSTAMP", strerror(errno));
+-              else
+-                      printf("SIOCGSTAMP %ld.%06ld\n",
+-                             (long)tv.tv_sec,
+-                             (long)tv.tv_usec);
+-      }
+-      if (siocgstampns) {
+-              if (ioctl(sock, SIOCGSTAMPNS, &ts))
+-                      printf("   %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
+-              else
+-                      printf("SIOCGSTAMPNS %ld.%09ld\n",
+-                             (long)ts.tv_sec,
+-                             (long)ts.tv_nsec);
+-      }
+-}
+-
+-static void recvpacket(int sock, int recvmsg_flags,
+-                     int siocgstamp, int siocgstampns)
+-{
+-      char data[256];
+-      struct msghdr msg;
+-      struct iovec entry;
+-      struct sockaddr_in from_addr;
+-      struct {
+-              struct cmsghdr cm;
+-              char control[512];
+-      } control;
+-      int res;
+-
+-      memset(&msg, 0, sizeof(msg));
+-      msg.msg_iov = &entry;
+-      msg.msg_iovlen = 1;
+-      entry.iov_base = data;
+-      entry.iov_len = sizeof(data);
+-      msg.msg_name = (caddr_t)&from_addr;
+-      msg.msg_namelen = sizeof(from_addr);
+-      msg.msg_control = &control;
+-      msg.msg_controllen = sizeof(control);
+-
+-      res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
+-      if (res < 0) {
+-              printf("%s %s: %s\n",
+-                     "recvmsg",
+-                     (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
+-                     strerror(errno));
+-      } else {
+-              printpacket(&msg, res, data,
+-                          sock, recvmsg_flags,
+-                          siocgstamp, siocgstampns);
+-      }
+-}
+-
+-int main(int argc, char **argv)
+-{
+-      int so_timestamping_flags = 0;
+-      int so_timestamp = 0;
+-      int so_timestampns = 0;
+-      int siocgstamp = 0;
+-      int siocgstampns = 0;
+-      int ip_multicast_loop = 0;
+-      char *interface;
+-      int i;
+-      int enabled = 1;
+-      int sock;
+-      struct ifreq device;
+-      struct ifreq hwtstamp;
+-      struct hwtstamp_config hwconfig, hwconfig_requested;
+-      struct sockaddr_in addr;
+-      struct ip_mreq imr;
+-      struct in_addr iaddr;
+-      int val;
+-      socklen_t len;
+-      struct timeval next;
+-
+-      if (argc < 2)
+-              usage(0);
+-      interface = argv[1];
+-
+-      for (i = 2; i < argc; i++) {
+-              if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
+-                      so_timestamp = 1;
+-              else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
+-                      so_timestampns = 1;
+-              else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
+-                      siocgstamp = 1;
+-              else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
+-                      siocgstampns = 1;
+-              else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
+-                      ip_multicast_loop = 1;
+-              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
+-                      so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
+-              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
+-                      so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
+-              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
+-                      so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
+-              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
+-                      so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
+-              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
+-                      so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
+-              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
+-                      so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
+-              else
+-                      usage(argv[i]);
+-      }
+-
+-      sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+-      if (sock < 0)
+-              bail("socket");
+-
+-      memset(&device, 0, sizeof(device));
+-      strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
+-      if (ioctl(sock, SIOCGIFADDR, &device) < 0)
+-              bail("getting interface IP address");
+-
+-      memset(&hwtstamp, 0, sizeof(hwtstamp));
+-      strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
+-      hwtstamp.ifr_data = (void *)&hwconfig;
+-      memset(&hwconfig, 0, sizeof(hwconfig));
+-      hwconfig.tx_type =
+-              (so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
+-              HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+-      hwconfig.rx_filter =
+-              (so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
+-              HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
+-      hwconfig_requested = hwconfig;
+-      if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
+-              if ((errno == EINVAL || errno == ENOTSUP) &&
+-                  hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
+-                  hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
+-                      printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
+-              else
+-                      bail("SIOCSHWTSTAMP");
+-      }
+-      printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
+-             hwconfig_requested.tx_type, hwconfig.tx_type,
+-             hwconfig_requested.rx_filter, hwconfig.rx_filter);
+-
+-      /* bind to PTP port */
+-      addr.sin_family = AF_INET;
+-      addr.sin_addr.s_addr = htonl(INADDR_ANY);
+-      addr.sin_port = htons(319 /* PTP event port */);
+-      if (bind(sock,
+-               (struct sockaddr *)&addr,
+-               sizeof(struct sockaddr_in)) < 0)
+-              bail("bind");
+-
+-      /* set multicast group for outgoing packets */
+-      inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
+-      addr.sin_addr = iaddr;
+-      imr.imr_multiaddr.s_addr = iaddr.s_addr;
+-      imr.imr_interface.s_addr =
+-              ((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
+-      if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
+-                     &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
+-              bail("set multicast");
+-
+-      /* join multicast group, loop our own packet */
+-      if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+-                     &imr, sizeof(struct ip_mreq)) < 0)
+-              bail("join multicast group");
+-
+-      if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
+-                     &ip_multicast_loop, sizeof(enabled)) < 0) {
+-              bail("loop multicast");
+-      }
+-
+-      /* set socket options for time stamping */
+-      if (so_timestamp &&
+-              setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
+-                         &enabled, sizeof(enabled)) < 0)
+-              bail("setsockopt SO_TIMESTAMP");
+-
+-      if (so_timestampns &&
+-              setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
+-                         &enabled, sizeof(enabled)) < 0)
+-              bail("setsockopt SO_TIMESTAMPNS");
+-
+-      if (so_timestamping_flags &&
+-              setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
+-                         &so_timestamping_flags,
+-                         sizeof(so_timestamping_flags)) < 0)
+-              bail("setsockopt SO_TIMESTAMPING");
+-
+-      /* request IP_PKTINFO for debugging purposes */
+-      if (setsockopt(sock, SOL_IP, IP_PKTINFO,
+-                     &enabled, sizeof(enabled)) < 0)
+-              printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
+-
+-      /* verify socket options */
+-      len = sizeof(val);
+-      if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
+-              printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
+-      else
+-              printf("SO_TIMESTAMP %d\n", val);
+-
+-      if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
+-              printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
+-                     strerror(errno));
+-      else
+-              printf("SO_TIMESTAMPNS %d\n", val);
+-
+-      if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
+-              printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
+-                     strerror(errno));
+-      } else {
+-              printf("SO_TIMESTAMPING %d\n", val);
+-              if (val != so_timestamping_flags)
+-                      printf("   not the expected value %d\n",
+-                             so_timestamping_flags);
+-      }
+-
+-      /* send packets forever every five seconds */
+-      gettimeofday(&next, 0);
+-      next.tv_sec = (next.tv_sec + 1) / 5 * 5;
+-      next.tv_usec = 0;
+-      while (1) {
+-              struct timeval now;
+-              struct timeval delta;
+-              long delta_us;
+-              int res;
+-              fd_set readfs, errorfs;
+-
+-              gettimeofday(&now, 0);
+-              delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
+-                      (long)(next.tv_usec - now.tv_usec);
+-              if (delta_us > 0) {
+-                      /* continue waiting for timeout or data */
+-                      delta.tv_sec = delta_us / 1000000;
+-                      delta.tv_usec = delta_us % 1000000;
+-
+-                      FD_ZERO(&readfs);
+-                      FD_ZERO(&errorfs);
+-                      FD_SET(sock, &readfs);
+-                      FD_SET(sock, &errorfs);
+-                      printf("%ld.%06ld: select %ldus\n",
+-                             (long)now.tv_sec, (long)now.tv_usec,
+-                             delta_us);
+-                      res = select(sock + 1, &readfs, 0, &errorfs, &delta);
+-                      gettimeofday(&now, 0);
+-                      printf("%ld.%06ld: select returned: %d, %s\n",
+-                             (long)now.tv_sec, (long)now.tv_usec,
+-                             res,
+-                             res < 0 ? strerror(errno) : "success");
+-                      if (res > 0) {
+-                              if (FD_ISSET(sock, &readfs))
+-                                      printf("ready for reading\n");
+-                              if (FD_ISSET(sock, &errorfs))
+-                                      printf("has error\n");
+-                              recvpacket(sock, 0,
+-                                         siocgstamp,
+-                                         siocgstampns);
+-                              recvpacket(sock, MSG_ERRQUEUE,
+-                                         siocgstamp,
+-                                         siocgstampns);
+-                      }
+-              } else {
+-                      /* write one packet */
+-                      sendpacket(sock,
+-                                 (struct sockaddr *)&addr,
+-                                 sizeof(addr));
+-                      next.tv_sec += 5;
+-                      continue;
+-              }
+-      }
+-
+-      return 0;
+-}
+--- a/Documentation/networking/timestamping/txtimestamp.c
++++ /dev/null
+@@ -1,469 +0,0 @@
+-/*
+- * Copyright 2014 Google Inc.
+- * Author: willemb@google.com (Willem de Bruijn)
+- *
+- * Test software tx timestamping, including
+- *
+- * - SCHED, SND and ACK timestamps
+- * - RAW, UDP and TCP
+- * - IPv4 and IPv6
+- * - various packet sizes (to test GSO and TSO)
+- *
+- * Consult the command line arguments for help on running
+- * the various testcases.
+- *
+- * This test requires a dummy TCP server.
+- * A simple `nc6 [-u] -l -p $DESTPORT` will do
+- *
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <arpa/inet.h>
+-#include <asm/types.h>
+-#include <error.h>
+-#include <errno.h>
+-#include <linux/errqueue.h>
+-#include <linux/if_ether.h>
+-#include <linux/net_tstamp.h>
+-#include <netdb.h>
+-#include <net/if.h>
+-#include <netinet/in.h>
+-#include <netinet/ip.h>
+-#include <netinet/udp.h>
+-#include <netinet/tcp.h>
+-#include <netpacket/packet.h>
+-#include <poll.h>
+-#include <stdarg.h>
+-#include <stdint.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <sys/ioctl.h>
+-#include <sys/select.h>
+-#include <sys/socket.h>
+-#include <sys/time.h>
+-#include <sys/types.h>
+-#include <time.h>
+-#include <unistd.h>
+-
+-/* command line parameters */
+-static int cfg_proto = SOCK_STREAM;
+-static int cfg_ipproto = IPPROTO_TCP;
+-static int cfg_num_pkts = 4;
+-static int do_ipv4 = 1;
+-static int do_ipv6 = 1;
+-static int cfg_payload_len = 10;
+-static uint16_t dest_port = 9000;
+-
+-static struct sockaddr_in daddr;
+-static struct sockaddr_in6 daddr6;
+-static struct timespec ts_prev;
+-
+-static void __print_timestamp(const char *name, struct timespec *cur,
+-                            uint32_t key, int payload_len)
+-{
+-      if (!(cur->tv_sec | cur->tv_nsec))
+-              return;
+-
+-      fprintf(stderr, "  %s: %lu s %lu us (seq=%u, len=%u)",
+-                      name, cur->tv_sec, cur->tv_nsec / 1000,
+-                      key, payload_len);
+-
+-      if ((ts_prev.tv_sec | ts_prev.tv_nsec)) {
+-              int64_t cur_ms, prev_ms;
+-
+-              cur_ms = (long) cur->tv_sec * 1000 * 1000;
+-              cur_ms += cur->tv_nsec / 1000;
+-
+-              prev_ms = (long) ts_prev.tv_sec * 1000 * 1000;
+-              prev_ms += ts_prev.tv_nsec / 1000;
+-
+-              fprintf(stderr, "  (%+ld us)", cur_ms - prev_ms);
+-      }
+-
+-      ts_prev = *cur;
+-      fprintf(stderr, "\n");
+-}
+-
+-static void print_timestamp_usr(void)
+-{
+-      struct timespec ts;
+-      struct timeval tv;      /* avoid dependency on -lrt */
+-
+-      gettimeofday(&tv, NULL);
+-      ts.tv_sec = tv.tv_sec;
+-      ts.tv_nsec = tv.tv_usec * 1000;
+-
+-      __print_timestamp("  USR", &ts, 0, 0);
+-}
+-
+-static void print_timestamp(struct scm_timestamping *tss, int tstype,
+-                          int tskey, int payload_len)
+-{
+-      const char *tsname;
+-
+-      switch (tstype) {
+-      case SCM_TSTAMP_SCHED:
+-              tsname = "  ENQ";
+-              break;
+-      case SCM_TSTAMP_SND:
+-              tsname = "  SND";
+-              break;
+-      case SCM_TSTAMP_ACK:
+-              tsname = "  ACK";
+-              break;
+-      default:
+-              error(1, 0, "unknown timestamp type: %u",
+-              tstype);
+-      }
+-      __print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
+-}
+-
+-static void __poll(int fd)
+-{
+-      struct pollfd pollfd;
+-      int ret;
+-
+-      memset(&pollfd, 0, sizeof(pollfd));
+-      pollfd.fd = fd;
+-      ret = poll(&pollfd, 1, 100);
+-      if (ret != 1)
+-              error(1, errno, "poll");
+-}
+-
+-static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
+-{
+-      struct sock_extended_err *serr = NULL;
+-      struct scm_timestamping *tss = NULL;
+-      struct cmsghdr *cm;
+-
+-      for (cm = CMSG_FIRSTHDR(msg);
+-           cm && cm->cmsg_len;
+-           cm = CMSG_NXTHDR(msg, cm)) {
+-              if (cm->cmsg_level == SOL_SOCKET &&
+-                  cm->cmsg_type == SCM_TIMESTAMPING) {
+-                      tss = (void *) CMSG_DATA(cm);
+-              } else if ((cm->cmsg_level == SOL_IP &&
+-                   cm->cmsg_type == IP_RECVERR) ||
+-                  (cm->cmsg_level == SOL_IPV6 &&
+-                   cm->cmsg_type == IPV6_RECVERR)) {
+-
+-                      serr = (void *) CMSG_DATA(cm);
+-                      if (serr->ee_errno != ENOMSG ||
+-                          serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
+-                              fprintf(stderr, "unknown ip error %d %d\n",
+-                                              serr->ee_errno,
+-                                              serr->ee_origin);
+-                              serr = NULL;
+-                      }
+-              } else
+-                      fprintf(stderr, "unknown cmsg %d,%d\n",
+-                                      cm->cmsg_level, cm->cmsg_type);
+-      }
+-
+-      if (serr && tss)
+-              print_timestamp(tss, serr->ee_info, serr->ee_data, payload_len);
+-}
+-
+-static int recv_errmsg(int fd)
+-{
+-      static char ctrl[1024 /* overprovision*/];
+-      static struct msghdr msg;
+-      struct iovec entry;
+-      static char *data;
+-      int ret = 0;
+-
+-      data = malloc(cfg_payload_len);
+-      if (!data)
+-              error(1, 0, "malloc");
+-
+-      memset(&msg, 0, sizeof(msg));
+-      memset(&entry, 0, sizeof(entry));
+-      memset(ctrl, 0, sizeof(ctrl));
+-
+-      entry.iov_base = data;
+-      entry.iov_len = cfg_payload_len;
+-      msg.msg_iov = &entry;
+-      msg.msg_iovlen = 1;
+-      msg.msg_name = NULL;
+-      msg.msg_namelen = 0;
+-      msg.msg_control = ctrl;
+-      msg.msg_controllen = sizeof(ctrl);
+-
+-      ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
+-      if (ret == -1 && errno != EAGAIN)
+-              error(1, errno, "recvmsg");
+-
+-      __recv_errmsg_cmsg(&msg, ret);
+-
+-      free(data);
+-      return ret == -1;
+-}
+-
+-static void do_test(int family, unsigned int opt)
+-{
+-      char *buf;
+-      int fd, i, val, total_len;
+-
+-      if (family == IPPROTO_IPV6 && cfg_proto != SOCK_STREAM) {
+-              /* due to lack of checksum generation code */
+-              fprintf(stderr, "test: skipping datagram over IPv6\n");
+-              return;
+-      }
+-
+-      total_len = cfg_payload_len;
+-      if (cfg_proto == SOCK_RAW) {
+-              total_len += sizeof(struct udphdr);
+-              if (cfg_ipproto == IPPROTO_RAW)
+-                      total_len += sizeof(struct iphdr);
+-      }
+-
+-      buf = malloc(total_len);
+-      if (!buf)
+-              error(1, 0, "malloc");
+-
+-      fd = socket(family, cfg_proto, cfg_ipproto);
+-      if (fd < 0)
+-              error(1, errno, "socket");
+-
+-      if (cfg_proto == SOCK_STREAM) {
+-              val = 1;
+-              if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
+-                             (char*) &val, sizeof(val)))
+-                      error(1, 0, "setsockopt no nagle");
+-
+-              if (family == PF_INET) {
+-                      if (connect(fd, (void *) &daddr, sizeof(daddr)))
+-                              error(1, errno, "connect ipv4");
+-              } else {
+-                      if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
+-                              error(1, errno, "connect ipv6");
+-              }
+-      }
+-
+-      opt |= SOF_TIMESTAMPING_SOFTWARE |
+-             SOF_TIMESTAMPING_OPT_ID;
+-      if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
+-                     (char *) &opt, sizeof(opt)))
+-              error(1, 0, "setsockopt timestamping");
+-
+-      for (i = 0; i < cfg_num_pkts; i++) {
+-              memset(&ts_prev, 0, sizeof(ts_prev));
+-              memset(buf, 'a' + i, total_len);
+-              buf[total_len - 2] = '\n';
+-              buf[total_len - 1] = '\0';
+-
+-              if (cfg_proto == SOCK_RAW) {
+-                      struct udphdr *udph;
+-                      int off = 0;
+-
+-                      if (cfg_ipproto == IPPROTO_RAW) {
+-                              struct iphdr *iph = (void *) buf;
+-
+-                              memset(iph, 0, sizeof(*iph));
+-                              iph->ihl      = 5;
+-                              iph->version  = 4;
+-                              iph->ttl      = 2;
+-                              iph->daddr    = daddr.sin_addr.s_addr;
+-                              iph->protocol = IPPROTO_UDP;
+-                              /* kernel writes saddr, csum, len */
+-
+-                              off = sizeof(*iph);
+-                      }
+-
+-                      udph = (void *) buf + off;
+-                      udph->source = ntohs(9000);     /* random spoof */
+-                      udph->dest   = ntohs(dest_port);
+-                      udph->len    = ntohs(sizeof(*udph) + cfg_payload_len);
+-                      udph->check  = 0;       /* not allowed for IPv6 */
+-              }
+-
+-              print_timestamp_usr();
+-              if (cfg_proto != SOCK_STREAM) {
+-                      if (family == PF_INET)
+-                              val = sendto(fd, buf, total_len, 0, (void *) &daddr, sizeof(daddr));
+-                      else
+-                              val = sendto(fd, buf, total_len, 0, (void *) &daddr6, sizeof(daddr6));
+-              } else {
+-                      val = send(fd, buf, cfg_payload_len, 0);
+-              }
+-              if (val != total_len)
+-                      error(1, errno, "send");
+-
+-              /* wait for all errors to be queued, else ACKs arrive OOO */
+-              usleep(50 * 1000);
+-
+-              __poll(fd);
+-
+-              while (!recv_errmsg(fd)) {}
+-      }
+-
+-      if (close(fd))
+-              error(1, errno, "close");
+-
+-      free(buf);
+-      usleep(400 * 1000);
+-}
+-
+-static void __attribute__((noreturn)) usage(const char *filepath)
+-{
+-      fprintf(stderr, "\nUsage: %s [options] hostname\n"
+-                      "\nwhere options are:\n"
+-                      "  -4:   only IPv4\n"
+-                      "  -6:   only IPv6\n"
+-                      "  -h:   show this message\n"
+-                      "  -l N: send N bytes at a time\n"
+-                      "  -r:   use raw\n"
+-                      "  -R:   use raw (IP_HDRINCL)\n"
+-                      "  -p N: connect to port N\n"
+-                      "  -u:   use udp\n",
+-                      filepath);
+-      exit(1);
+-}
+-
+-static void parse_opt(int argc, char **argv)
+-{
+-      int proto_count = 0;
+-      char c;
+-
+-      while ((c = getopt(argc, argv, "46hl:p:rRu")) != -1) {
+-              switch (c) {
+-              case '4':
+-                      do_ipv6 = 0;
+-                      break;
+-              case '6':
+-                      do_ipv4 = 0;
+-                      break;
+-              case 'r':
+-                      proto_count++;
+-                      cfg_proto = SOCK_RAW;
+-                      cfg_ipproto = IPPROTO_UDP;
+-                      break;
+-              case 'R':
+-                      proto_count++;
+-                      cfg_proto = SOCK_RAW;
+-                      cfg_ipproto = IPPROTO_RAW;
+-                      break;
+-              case 'u':
+-                      proto_count++;
+-                      cfg_proto = SOCK_DGRAM;
+-                      cfg_ipproto = IPPROTO_UDP;
+-                      break;
+-              case 'l':
+-                      cfg_payload_len = strtoul(optarg, NULL, 10);
+-                      break;
+-              case 'p':
+-                      dest_port = strtoul(optarg, NULL, 10);
+-                      break;
+-              case 'h':
+-              default:
+-                      usage(argv[0]);
+-              }
+-      }
+-
+-      if (!cfg_payload_len)
+-              error(1, 0, "payload may not be nonzero");
+-      if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
+-              error(1, 0, "udp packet might exceed expected MTU");
+-      if (!do_ipv4 && !do_ipv6)
+-              error(1, 0, "pass -4 or -6, not both");
+-      if (proto_count > 1)
+-              error(1, 0, "pass -r, -R or -u, not multiple");
+-
+-      if (optind != argc - 1)
+-              error(1, 0, "missing required hostname argument");
+-}
+-
+-static void resolve_hostname(const char *hostname)
+-{
+-      struct addrinfo *addrs, *cur;
+-      int have_ipv4 = 0, have_ipv6 = 0;
+-
+-      if (getaddrinfo(hostname, NULL, NULL, &addrs))
+-              error(1, errno, "getaddrinfo");
+-
+-      cur = addrs;
+-      while (cur && !have_ipv4 && !have_ipv6) {
+-              if (!have_ipv4 && cur->ai_family == AF_INET) {
+-                      memcpy(&daddr, cur->ai_addr, sizeof(daddr));
+-                      daddr.sin_port = htons(dest_port);
+-                      have_ipv4 = 1;
+-              }
+-              else if (!have_ipv6 && cur->ai_family == AF_INET6) {
+-                      memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
+-                      daddr6.sin6_port = htons(dest_port);
+-                      have_ipv6 = 1;
+-              }
+-              cur = cur->ai_next;
+-      }
+-      if (addrs)
+-              freeaddrinfo(addrs);
+-
+-      do_ipv4 &= have_ipv4;
+-      do_ipv6 &= have_ipv6;
+-}
+-
+-static void do_main(int family)
+-{
+-      fprintf(stderr, "family:       %s\n",
+-                      family == PF_INET ? "INET" : "INET6");
+-
+-      fprintf(stderr, "test SND\n");
+-      do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
+-
+-      fprintf(stderr, "test ENQ\n");
+-      do_test(family, SOF_TIMESTAMPING_TX_SCHED);
+-
+-      fprintf(stderr, "test ENQ + SND\n");
+-      do_test(family, SOF_TIMESTAMPING_TX_SCHED |
+-                      SOF_TIMESTAMPING_TX_SOFTWARE);
+-
+-      if (cfg_proto == SOCK_STREAM) {
+-              fprintf(stderr, "\ntest ACK\n");
+-              do_test(family, SOF_TIMESTAMPING_TX_ACK);
+-
+-              fprintf(stderr, "\ntest SND + ACK\n");
+-              do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
+-                              SOF_TIMESTAMPING_TX_ACK);
+-
+-              fprintf(stderr, "\ntest ENQ + SND + ACK\n");
+-              do_test(family, SOF_TIMESTAMPING_TX_SCHED |
+-                              SOF_TIMESTAMPING_TX_SOFTWARE |
+-                              SOF_TIMESTAMPING_TX_ACK);
+-      }
+-}
+-
+-const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
+-
+-int main(int argc, char **argv)
+-{
+-      if (argc == 1)
+-              usage(argv[0]);
+-
+-      parse_opt(argc, argv);
+-      resolve_hostname(argv[argc - 1]);
+-
+-      fprintf(stderr, "protocol:     %s\n", sock_names[cfg_proto]);
+-      fprintf(stderr, "payload:      %u\n", cfg_payload_len);
+-      fprintf(stderr, "server port:  %u\n", dest_port);
+-      fprintf(stderr, "\n");
+-
+-      if (do_ipv4)
+-              do_main(PF_INET);
+-      if (do_ipv6)
+-              do_main(PF_INET6);
+-
+-      return 0;
+-}
+--- /dev/null
++++ b/tools/testing/selftests/networking/timestamping/.gitignore
+@@ -0,0 +1,3 @@
++timestamping
++txtimestamp
++hwtstamp_config
+--- /dev/null
++++ b/tools/testing/selftests/networking/timestamping/Makefile
+@@ -0,0 +1,8 @@
++TEST_PROGS := hwtstamp_config timestamping txtimestamp
++
++all: $(TEST_PROGS)
++
++include ../../lib.mk
++
++clean:
++      rm -fr $(TEST_PROGS)
+--- /dev/null
++++ b/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
+@@ -0,0 +1,134 @@
++/* Test program for SIOC{G,S}HWTSTAMP
++ * Copyright 2013 Solarflare Communications
++ * Author: Ben Hutchings
++ */
++
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <sys/socket.h>
++#include <sys/ioctl.h>
++
++#include <linux/if.h>
++#include <linux/net_tstamp.h>
++#include <linux/sockios.h>
++
++static int
++lookup_value(const char **names, int size, const char *name)
++{
++      int value;
++
++      for (value = 0; value < size; value++)
++              if (names[value] && strcasecmp(names[value], name) == 0)
++                      return value;
++
++      return -1;
++}
++
++static const char *
++lookup_name(const char **names, int size, int value)
++{
++      return (value >= 0 && value < size) ? names[value] : NULL;
++}
++
++static void list_names(FILE *f, const char **names, int size)
++{
++      int value;
++
++      for (value = 0; value < size; value++)
++              if (names[value])
++                      fprintf(f, "    %s\n", names[value]);
++}
++
++static const char *tx_types[] = {
++#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
++      TX_TYPE(OFF),
++      TX_TYPE(ON),
++      TX_TYPE(ONESTEP_SYNC)
++#undef TX_TYPE
++};
++#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
++
++static const char *rx_filters[] = {
++#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
++      RX_FILTER(NONE),
++      RX_FILTER(ALL),
++      RX_FILTER(SOME),
++      RX_FILTER(PTP_V1_L4_EVENT),
++      RX_FILTER(PTP_V1_L4_SYNC),
++      RX_FILTER(PTP_V1_L4_DELAY_REQ),
++      RX_FILTER(PTP_V2_L4_EVENT),
++      RX_FILTER(PTP_V2_L4_SYNC),
++      RX_FILTER(PTP_V2_L4_DELAY_REQ),
++      RX_FILTER(PTP_V2_L2_EVENT),
++      RX_FILTER(PTP_V2_L2_SYNC),
++      RX_FILTER(PTP_V2_L2_DELAY_REQ),
++      RX_FILTER(PTP_V2_EVENT),
++      RX_FILTER(PTP_V2_SYNC),
++      RX_FILTER(PTP_V2_DELAY_REQ),
++#undef RX_FILTER
++};
++#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
++
++static void usage(void)
++{
++      fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
++            "tx_type is any of (case-insensitive):\n",
++            stderr);
++      list_names(stderr, tx_types, N_TX_TYPES);
++      fputs("rx_filter is any of (case-insensitive):\n", stderr);
++      list_names(stderr, rx_filters, N_RX_FILTERS);
++}
++
++int main(int argc, char **argv)
++{
++      struct ifreq ifr;
++      struct hwtstamp_config config;
++      const char *name;
++      int sock;
++
++      if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
++              usage();
++              return 2;
++      }
++
++      if (argc == 4) {
++              config.flags = 0;
++              config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
++              config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
++              if (config.tx_type < 0 || config.rx_filter < 0) {
++                      usage();
++                      return 2;
++              }
++      }
++
++      sock = socket(AF_INET, SOCK_DGRAM, 0);
++      if (sock < 0) {
++              perror("socket");
++              return 1;
++      }
++
++      strcpy(ifr.ifr_name, argv[1]);
++      ifr.ifr_data = (caddr_t)&config;
++
++      if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
++              perror("ioctl");
++              return 1;
++      }
++
++      printf("flags = %#x\n", config.flags);
++      name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
++      if (name)
++              printf("tx_type = %s\n", name);
++      else
++              printf("tx_type = %d\n", config.tx_type);
++      name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
++      if (name)
++              printf("rx_filter = %s\n", name);
++      else
++              printf("rx_filter = %d\n", config.rx_filter);
++
++      return 0;
++}
+--- /dev/null
++++ b/tools/testing/selftests/networking/timestamping/timestamping.c
+@@ -0,0 +1,528 @@
++/*
++ * This program demonstrates how the various time stamping features in
++ * the Linux kernel work. It emulates the behavior of a PTP
++ * implementation in stand-alone master mode by sending PTPv1 Sync
++ * multicasts once every second. It looks for similar packets, but
++ * beyond that doesn't actually implement PTP.
++ *
++ * Outgoing packets are time stamped with SO_TIMESTAMPING with or
++ * without hardware support.
++ *
++ * Incoming packets are time stamped with SO_TIMESTAMPING with or
++ * without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
++ * SO_TIMESTAMP[NS].
++ *
++ * Copyright (C) 2009 Intel Corporation.
++ * Author: Patrick Ohly <patrick.ohly@intel.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <string.h>
++
++#include <sys/time.h>
++#include <sys/socket.h>
++#include <sys/select.h>
++#include <sys/ioctl.h>
++#include <arpa/inet.h>
++#include <net/if.h>
++
++#include <asm/types.h>
++#include <linux/net_tstamp.h>
++#include <linux/errqueue.h>
++
++#ifndef SO_TIMESTAMPING
++# define SO_TIMESTAMPING         37
++# define SCM_TIMESTAMPING        SO_TIMESTAMPING
++#endif
++
++#ifndef SO_TIMESTAMPNS
++# define SO_TIMESTAMPNS 35
++#endif
++
++#ifndef SIOCGSTAMPNS
++# define SIOCGSTAMPNS 0x8907
++#endif
++
++#ifndef SIOCSHWTSTAMP
++# define SIOCSHWTSTAMP 0x89b0
++#endif
++
++static void usage(const char *error)
++{
++      if (error)
++              printf("invalid option: %s\n", error);
++      printf("timestamping interface option*\n\n"
++             "Options:\n"
++             "  IP_MULTICAST_LOOP - looping outgoing multicasts\n"
++             "  SO_TIMESTAMP - normal software time stamping, ms resolution\n"
++             "  SO_TIMESTAMPNS - more accurate software time stamping\n"
++             "  SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
++             "  SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
++             "  SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
++             "  SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
++             "  SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
++             "  SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
++             "  SIOCGSTAMP - check last socket time stamp\n"
++             "  SIOCGSTAMPNS - more accurate socket time stamp\n");
++      exit(1);
++}
++
++static void bail(const char *error)
++{
++      printf("%s: %s\n", error, strerror(errno));
++      exit(1);
++}
++
++static const unsigned char sync[] = {
++      0x00, 0x01, 0x00, 0x01,
++      0x5f, 0x44, 0x46, 0x4c,
++      0x54, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00,
++      0x01, 0x01,
++
++      /* fake uuid */
++      0x00, 0x01,
++      0x02, 0x03, 0x04, 0x05,
++
++      0x00, 0x01, 0x00, 0x37,
++      0x00, 0x00, 0x00, 0x08,
++      0x00, 0x00, 0x00, 0x00,
++      0x49, 0x05, 0xcd, 0x01,
++      0x29, 0xb1, 0x8d, 0xb0,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x01,
++
++      /* fake uuid */
++      0x00, 0x01,
++      0x02, 0x03, 0x04, 0x05,
++
++      0x00, 0x00, 0x00, 0x37,
++      0x00, 0x00, 0x00, 0x04,
++      0x44, 0x46, 0x4c, 0x54,
++      0x00, 0x00, 0xf0, 0x60,
++      0x00, 0x01, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x01,
++      0x00, 0x00, 0xf0, 0x60,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x04,
++      0x44, 0x46, 0x4c, 0x54,
++      0x00, 0x01,
++
++      /* fake uuid */
++      0x00, 0x01,
++      0x02, 0x03, 0x04, 0x05,
++
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00
++};
++
++static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
++{
++      struct timeval now;
++      int res;
++
++      res = sendto(sock, sync, sizeof(sync), 0,
++              addr, addr_len);
++      gettimeofday(&now, 0);
++      if (res < 0)
++              printf("%s: %s\n", "send", strerror(errno));
++      else
++              printf("%ld.%06ld: sent %d bytes\n",
++                     (long)now.tv_sec, (long)now.tv_usec,
++                     res);
++}
++
++static void printpacket(struct msghdr *msg, int res,
++                      char *data,
++                      int sock, int recvmsg_flags,
++                      int siocgstamp, int siocgstampns)
++{
++      struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
++      struct cmsghdr *cmsg;
++      struct timeval tv;
++      struct timespec ts;
++      struct timeval now;
++
++      gettimeofday(&now, 0);
++
++      printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
++             (long)now.tv_sec, (long)now.tv_usec,
++             (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
++             res,
++             inet_ntoa(from_addr->sin_addr),
++             msg->msg_controllen);
++      for (cmsg = CMSG_FIRSTHDR(msg);
++           cmsg;
++           cmsg = CMSG_NXTHDR(msg, cmsg)) {
++              printf("   cmsg len %zu: ", cmsg->cmsg_len);
++              switch (cmsg->cmsg_level) {
++              case SOL_SOCKET:
++                      printf("SOL_SOCKET ");
++                      switch (cmsg->cmsg_type) {
++                      case SO_TIMESTAMP: {
++                              struct timeval *stamp =
++                                      (struct timeval *)CMSG_DATA(cmsg);
++                              printf("SO_TIMESTAMP %ld.%06ld",
++                                     (long)stamp->tv_sec,
++                                     (long)stamp->tv_usec);
++                              break;
++                      }
++                      case SO_TIMESTAMPNS: {
++                              struct timespec *stamp =
++                                      (struct timespec *)CMSG_DATA(cmsg);
++                              printf("SO_TIMESTAMPNS %ld.%09ld",
++                                     (long)stamp->tv_sec,
++                                     (long)stamp->tv_nsec);
++                              break;
++                      }
++                      case SO_TIMESTAMPING: {
++                              struct timespec *stamp =
++                                      (struct timespec *)CMSG_DATA(cmsg);
++                              printf("SO_TIMESTAMPING ");
++                              printf("SW %ld.%09ld ",
++                                     (long)stamp->tv_sec,
++                                     (long)stamp->tv_nsec);
++                              stamp++;
++                              /* skip deprecated HW transformed */
++                              stamp++;
++                              printf("HW raw %ld.%09ld",
++                                     (long)stamp->tv_sec,
++                                     (long)stamp->tv_nsec);
++                              break;
++                      }
++                      default:
++                              printf("type %d", cmsg->cmsg_type);
++                              break;
++                      }
++                      break;
++              case IPPROTO_IP:
++                      printf("IPPROTO_IP ");
++                      switch (cmsg->cmsg_type) {
++                      case IP_RECVERR: {
++                              struct sock_extended_err *err =
++                                      (struct sock_extended_err *)CMSG_DATA(cmsg);
++                              printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
++                                      strerror(err->ee_errno),
++                                      err->ee_origin,
++#ifdef SO_EE_ORIGIN_TIMESTAMPING
++                                      err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
++                                      "bounced packet" : "unexpected origin"
++#else
++                                      "probably SO_EE_ORIGIN_TIMESTAMPING"
++#endif
++                                      );
++                              if (res < sizeof(sync))
++                                      printf(" => truncated data?!");
++                              else if (!memcmp(sync, data + res - sizeof(sync),
++                                                      sizeof(sync)))
++                                      printf(" => GOT OUR DATA BACK (HURRAY!)");
++                              break;
++                      }
++                      case IP_PKTINFO: {
++                              struct in_pktinfo *pktinfo =
++                                      (struct in_pktinfo *)CMSG_DATA(cmsg);
++                              printf("IP_PKTINFO interface index %u",
++                                      pktinfo->ipi_ifindex);
++                              break;
++                      }
++                      default:
++                              printf("type %d", cmsg->cmsg_type);
++                              break;
++                      }
++                      break;
++              default:
++                      printf("level %d type %d",
++                              cmsg->cmsg_level,
++                              cmsg->cmsg_type);
++                      break;
++              }
++              printf("\n");
++      }
++
++      if (siocgstamp) {
++              if (ioctl(sock, SIOCGSTAMP, &tv))
++                      printf("   %s: %s\n", "SIOCGSTAMP", strerror(errno));
++              else
++                      printf("SIOCGSTAMP %ld.%06ld\n",
++                             (long)tv.tv_sec,
++                             (long)tv.tv_usec);
++      }
++      if (siocgstampns) {
++              if (ioctl(sock, SIOCGSTAMPNS, &ts))
++                      printf("   %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
++              else
++                      printf("SIOCGSTAMPNS %ld.%09ld\n",
++                             (long)ts.tv_sec,
++                             (long)ts.tv_nsec);
++      }
++}
++
++static void recvpacket(int sock, int recvmsg_flags,
++                     int siocgstamp, int siocgstampns)
++{
++      char data[256];
++      struct msghdr msg;
++      struct iovec entry;
++      struct sockaddr_in from_addr;
++      struct {
++              struct cmsghdr cm;
++              char control[512];
++      } control;
++      int res;
++
++      memset(&msg, 0, sizeof(msg));
++      msg.msg_iov = &entry;
++      msg.msg_iovlen = 1;
++      entry.iov_base = data;
++      entry.iov_len = sizeof(data);
++      msg.msg_name = (caddr_t)&from_addr;
++      msg.msg_namelen = sizeof(from_addr);
++      msg.msg_control = &control;
++      msg.msg_controllen = sizeof(control);
++
++      res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
++      if (res < 0) {
++              printf("%s %s: %s\n",
++                     "recvmsg",
++                     (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
++                     strerror(errno));
++      } else {
++              printpacket(&msg, res, data,
++                          sock, recvmsg_flags,
++                          siocgstamp, siocgstampns);
++      }
++}
++
++int main(int argc, char **argv)
++{
++      int so_timestamping_flags = 0;
++      int so_timestamp = 0;
++      int so_timestampns = 0;
++      int siocgstamp = 0;
++      int siocgstampns = 0;
++      int ip_multicast_loop = 0;
++      char *interface;
++      int i;
++      int enabled = 1;
++      int sock;
++      struct ifreq device;
++      struct ifreq hwtstamp;
++      struct hwtstamp_config hwconfig, hwconfig_requested;
++      struct sockaddr_in addr;
++      struct ip_mreq imr;
++      struct in_addr iaddr;
++      int val;
++      socklen_t len;
++      struct timeval next;
++
++      if (argc < 2)
++              usage(0);
++      interface = argv[1];
++
++      for (i = 2; i < argc; i++) {
++              if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
++                      so_timestamp = 1;
++              else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
++                      so_timestampns = 1;
++              else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
++                      siocgstamp = 1;
++              else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
++                      siocgstampns = 1;
++              else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
++                      ip_multicast_loop = 1;
++              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
++                      so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
++              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
++                      so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
++              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
++                      so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
++              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
++                      so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
++              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
++                      so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
++              else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
++                      so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
++              else
++                      usage(argv[i]);
++      }
++
++      sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
++      if (sock < 0)
++              bail("socket");
++
++      memset(&device, 0, sizeof(device));
++      strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
++      if (ioctl(sock, SIOCGIFADDR, &device) < 0)
++              bail("getting interface IP address");
++
++      memset(&hwtstamp, 0, sizeof(hwtstamp));
++      strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
++      hwtstamp.ifr_data = (void *)&hwconfig;
++      memset(&hwconfig, 0, sizeof(hwconfig));
++      hwconfig.tx_type =
++              (so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
++              HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
++      hwconfig.rx_filter =
++              (so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
++              HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
++      hwconfig_requested = hwconfig;
++      if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
++              if ((errno == EINVAL || errno == ENOTSUP) &&
++                  hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
++                  hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
++                      printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
++              else
++                      bail("SIOCSHWTSTAMP");
++      }
++      printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
++             hwconfig_requested.tx_type, hwconfig.tx_type,
++             hwconfig_requested.rx_filter, hwconfig.rx_filter);
++
++      /* bind to PTP port */
++      addr.sin_family = AF_INET;
++      addr.sin_addr.s_addr = htonl(INADDR_ANY);
++      addr.sin_port = htons(319 /* PTP event port */);
++      if (bind(sock,
++               (struct sockaddr *)&addr,
++               sizeof(struct sockaddr_in)) < 0)
++              bail("bind");
++
++      /* set multicast group for outgoing packets */
++      inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
++      addr.sin_addr = iaddr;
++      imr.imr_multiaddr.s_addr = iaddr.s_addr;
++      imr.imr_interface.s_addr =
++              ((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
++      if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
++                     &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
++              bail("set multicast");
++
++      /* join multicast group, loop our own packet */
++      if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
++                     &imr, sizeof(struct ip_mreq)) < 0)
++              bail("join multicast group");
++
++      if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
++                     &ip_multicast_loop, sizeof(enabled)) < 0) {
++              bail("loop multicast");
++      }
++
++      /* set socket options for time stamping */
++      if (so_timestamp &&
++              setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
++                         &enabled, sizeof(enabled)) < 0)
++              bail("setsockopt SO_TIMESTAMP");
++
++      if (so_timestampns &&
++              setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
++                         &enabled, sizeof(enabled)) < 0)
++              bail("setsockopt SO_TIMESTAMPNS");
++
++      if (so_timestamping_flags &&
++              setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
++                         &so_timestamping_flags,
++                         sizeof(so_timestamping_flags)) < 0)
++              bail("setsockopt SO_TIMESTAMPING");
++
++      /* request IP_PKTINFO for debugging purposes */
++      if (setsockopt(sock, SOL_IP, IP_PKTINFO,
++                     &enabled, sizeof(enabled)) < 0)
++              printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
++
++      /* verify socket options */
++      len = sizeof(val);
++      if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
++              printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
++      else
++              printf("SO_TIMESTAMP %d\n", val);
++
++      if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
++              printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
++                     strerror(errno));
++      else
++              printf("SO_TIMESTAMPNS %d\n", val);
++
++      if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
++              printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
++                     strerror(errno));
++      } else {
++              printf("SO_TIMESTAMPING %d\n", val);
++              if (val != so_timestamping_flags)
++                      printf("   not the expected value %d\n",
++                             so_timestamping_flags);
++      }
++
++      /* send packets forever every five seconds */
++      gettimeofday(&next, 0);
++      next.tv_sec = (next.tv_sec + 1) / 5 * 5;
++      next.tv_usec = 0;
++      while (1) {
++              struct timeval now;
++              struct timeval delta;
++              long delta_us;
++              int res;
++              fd_set readfs, errorfs;
++
++              gettimeofday(&now, 0);
++              delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
++                      (long)(next.tv_usec - now.tv_usec);
++              if (delta_us > 0) {
++                      /* continue waiting for timeout or data */
++                      delta.tv_sec = delta_us / 1000000;
++                      delta.tv_usec = delta_us % 1000000;
++
++                      FD_ZERO(&readfs);
++                      FD_ZERO(&errorfs);
++                      FD_SET(sock, &readfs);
++                      FD_SET(sock, &errorfs);
++                      printf("%ld.%06ld: select %ldus\n",
++                             (long)now.tv_sec, (long)now.tv_usec,
++                             delta_us);
++                      res = select(sock + 1, &readfs, 0, &errorfs, &delta);
++                      gettimeofday(&now, 0);
++                      printf("%ld.%06ld: select returned: %d, %s\n",
++                             (long)now.tv_sec, (long)now.tv_usec,
++                             res,
++                             res < 0 ? strerror(errno) : "success");
++                      if (res > 0) {
++                              if (FD_ISSET(sock, &readfs))
++                                      printf("ready for reading\n");
++                              if (FD_ISSET(sock, &errorfs))
++                                      printf("has error\n");
++                              recvpacket(sock, 0,
++                                         siocgstamp,
++                                         siocgstampns);
++                              recvpacket(sock, MSG_ERRQUEUE,
++                                         siocgstamp,
++                                         siocgstampns);
++                      }
++              } else {
++                      /* write one packet */
++                      sendpacket(sock,
++                                 (struct sockaddr *)&addr,
++                                 sizeof(addr));
++                      next.tv_sec += 5;
++                      continue;
++              }
++      }
++
++      return 0;
++}
+--- /dev/null
++++ b/tools/testing/selftests/networking/timestamping/txtimestamp.c
+@@ -0,0 +1,469 @@
++/*
++ * Copyright 2014 Google Inc.
++ * Author: willemb@google.com (Willem de Bruijn)
++ *
++ * Test software tx timestamping, including
++ *
++ * - SCHED, SND and ACK timestamps
++ * - RAW, UDP and TCP
++ * - IPv4 and IPv6
++ * - various packet sizes (to test GSO and TSO)
++ *
++ * Consult the command line arguments for help on running
++ * the various testcases.
++ *
++ * This test requires a dummy TCP server.
++ * A simple `nc6 [-u] -l -p $DESTPORT` will do
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <arpa/inet.h>
++#include <asm/types.h>
++#include <error.h>
++#include <errno.h>
++#include <linux/errqueue.h>
++#include <linux/if_ether.h>
++#include <linux/net_tstamp.h>
++#include <netdb.h>
++#include <net/if.h>
++#include <netinet/in.h>
++#include <netinet/ip.h>
++#include <netinet/udp.h>
++#include <netinet/tcp.h>
++#include <netpacket/packet.h>
++#include <poll.h>
++#include <stdarg.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/ioctl.h>
++#include <sys/select.h>
++#include <sys/socket.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#include <time.h>
++#include <unistd.h>
++
++/* command line parameters */
++static int cfg_proto = SOCK_STREAM;
++static int cfg_ipproto = IPPROTO_TCP;
++static int cfg_num_pkts = 4;
++static int do_ipv4 = 1;
++static int do_ipv6 = 1;
++static int cfg_payload_len = 10;
++static uint16_t dest_port = 9000;
++
++static struct sockaddr_in daddr;
++static struct sockaddr_in6 daddr6;
++static struct timespec ts_prev;
++
++static void __print_timestamp(const char *name, struct timespec *cur,
++                            uint32_t key, int payload_len)
++{
++      if (!(cur->tv_sec | cur->tv_nsec))
++              return;
++
++      fprintf(stderr, "  %s: %lu s %lu us (seq=%u, len=%u)",
++                      name, cur->tv_sec, cur->tv_nsec / 1000,
++                      key, payload_len);
++
++      if ((ts_prev.tv_sec | ts_prev.tv_nsec)) {
++              int64_t cur_ms, prev_ms;
++
++              cur_ms = (long) cur->tv_sec * 1000 * 1000;
++              cur_ms += cur->tv_nsec / 1000;
++
++              prev_ms = (long) ts_prev.tv_sec * 1000 * 1000;
++              prev_ms += ts_prev.tv_nsec / 1000;
++
++              fprintf(stderr, "  (%+ld us)", cur_ms - prev_ms);
++      }
++
++      ts_prev = *cur;
++      fprintf(stderr, "\n");
++}
++
++static void print_timestamp_usr(void)
++{
++      struct timespec ts;
++      struct timeval tv;      /* avoid dependency on -lrt */
++
++      gettimeofday(&tv, NULL);
++      ts.tv_sec = tv.tv_sec;
++      ts.tv_nsec = tv.tv_usec * 1000;
++
++      __print_timestamp("  USR", &ts, 0, 0);
++}
++
++static void print_timestamp(struct scm_timestamping *tss, int tstype,
++                          int tskey, int payload_len)
++{
++      const char *tsname;
++
++      switch (tstype) {
++      case SCM_TSTAMP_SCHED:
++              tsname = "  ENQ";
++              break;
++      case SCM_TSTAMP_SND:
++              tsname = "  SND";
++              break;
++      case SCM_TSTAMP_ACK:
++              tsname = "  ACK";
++              break;
++      default:
++              error(1, 0, "unknown timestamp type: %u",
++              tstype);
++      }
++      __print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
++}
++
++static void __poll(int fd)
++{
++      struct pollfd pollfd;
++      int ret;
++
++      memset(&pollfd, 0, sizeof(pollfd));
++      pollfd.fd = fd;
++      ret = poll(&pollfd, 1, 100);
++      if (ret != 1)
++              error(1, errno, "poll");
++}
++
++static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
++{
++      struct sock_extended_err *serr = NULL;
++      struct scm_timestamping *tss = NULL;
++      struct cmsghdr *cm;
++
++      for (cm = CMSG_FIRSTHDR(msg);
++           cm && cm->cmsg_len;
++           cm = CMSG_NXTHDR(msg, cm)) {
++              if (cm->cmsg_level == SOL_SOCKET &&
++                  cm->cmsg_type == SCM_TIMESTAMPING) {
++                      tss = (void *) CMSG_DATA(cm);
++              } else if ((cm->cmsg_level == SOL_IP &&
++                   cm->cmsg_type == IP_RECVERR) ||
++                  (cm->cmsg_level == SOL_IPV6 &&
++                   cm->cmsg_type == IPV6_RECVERR)) {
++
++                      serr = (void *) CMSG_DATA(cm);
++                      if (serr->ee_errno != ENOMSG ||
++                          serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
++                              fprintf(stderr, "unknown ip error %d %d\n",
++                                              serr->ee_errno,
++                                              serr->ee_origin);
++                              serr = NULL;
++                      }
++              } else
++                      fprintf(stderr, "unknown cmsg %d,%d\n",
++                                      cm->cmsg_level, cm->cmsg_type);
++      }
++
++      if (serr && tss)
++              print_timestamp(tss, serr->ee_info, serr->ee_data, payload_len);
++}
++
++static int recv_errmsg(int fd)
++{
++      static char ctrl[1024 /* overprovision*/];
++      static struct msghdr msg;
++      struct iovec entry;
++      static char *data;
++      int ret = 0;
++
++      data = malloc(cfg_payload_len);
++      if (!data)
++              error(1, 0, "malloc");
++
++      memset(&msg, 0, sizeof(msg));
++      memset(&entry, 0, sizeof(entry));
++      memset(ctrl, 0, sizeof(ctrl));
++
++      entry.iov_base = data;
++      entry.iov_len = cfg_payload_len;
++      msg.msg_iov = &entry;
++      msg.msg_iovlen = 1;
++      msg.msg_name = NULL;
++      msg.msg_namelen = 0;
++      msg.msg_control = ctrl;
++      msg.msg_controllen = sizeof(ctrl);
++
++      ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
++      if (ret == -1 && errno != EAGAIN)
++              error(1, errno, "recvmsg");
++
++      __recv_errmsg_cmsg(&msg, ret);
++
++      free(data);
++      return ret == -1;
++}
++
++static void do_test(int family, unsigned int opt)
++{
++      char *buf;
++      int fd, i, val, total_len;
++
++      if (family == IPPROTO_IPV6 && cfg_proto != SOCK_STREAM) {
++              /* due to lack of checksum generation code */
++              fprintf(stderr, "test: skipping datagram over IPv6\n");
++              return;
++      }
++
++      total_len = cfg_payload_len;
++      if (cfg_proto == SOCK_RAW) {
++              total_len += sizeof(struct udphdr);
++              if (cfg_ipproto == IPPROTO_RAW)
++                      total_len += sizeof(struct iphdr);
++      }
++
++      buf = malloc(total_len);
++      if (!buf)
++              error(1, 0, "malloc");
++
++      fd = socket(family, cfg_proto, cfg_ipproto);
++      if (fd < 0)
++              error(1, errno, "socket");
++
++      if (cfg_proto == SOCK_STREAM) {
++              val = 1;
++              if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
++                             (char*) &val, sizeof(val)))
++                      error(1, 0, "setsockopt no nagle");
++
++              if (family == PF_INET) {
++                      if (connect(fd, (void *) &daddr, sizeof(daddr)))
++                              error(1, errno, "connect ipv4");
++              } else {
++                      if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
++                              error(1, errno, "connect ipv6");
++              }
++      }
++
++      opt |= SOF_TIMESTAMPING_SOFTWARE |
++             SOF_TIMESTAMPING_OPT_ID;
++      if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
++                     (char *) &opt, sizeof(opt)))
++              error(1, 0, "setsockopt timestamping");
++
++      for (i = 0; i < cfg_num_pkts; i++) {
++              memset(&ts_prev, 0, sizeof(ts_prev));
++              memset(buf, 'a' + i, total_len);
++              buf[total_len - 2] = '\n';
++              buf[total_len - 1] = '\0';
++
++              if (cfg_proto == SOCK_RAW) {
++                      struct udphdr *udph;
++                      int off = 0;
++
++                      if (cfg_ipproto == IPPROTO_RAW) {
++                              struct iphdr *iph = (void *) buf;
++
++                              memset(iph, 0, sizeof(*iph));
++                              iph->ihl      = 5;
++                              iph->version  = 4;
++                              iph->ttl      = 2;
++                              iph->daddr    = daddr.sin_addr.s_addr;
++                              iph->protocol = IPPROTO_UDP;
++                              /* kernel writes saddr, csum, len */
++
++                              off = sizeof(*iph);
++                      }
++
++                      udph = (void *) buf + off;
++                      udph->source = ntohs(9000);     /* random spoof */
++                      udph->dest   = ntohs(dest_port);
++                      udph->len    = ntohs(sizeof(*udph) + cfg_payload_len);
++                      udph->check  = 0;       /* not allowed for IPv6 */
++              }
++
++              print_timestamp_usr();
++              if (cfg_proto != SOCK_STREAM) {
++                      if (family == PF_INET)
++                              val = sendto(fd, buf, total_len, 0, (void *) &daddr, sizeof(daddr));
++                      else
++                              val = sendto(fd, buf, total_len, 0, (void *) &daddr6, sizeof(daddr6));
++              } else {
++                      val = send(fd, buf, cfg_payload_len, 0);
++              }
++              if (val != total_len)
++                      error(1, errno, "send");
++
++              /* wait for all errors to be queued, else ACKs arrive OOO */
++              usleep(50 * 1000);
++
++              __poll(fd);
++
++              while (!recv_errmsg(fd)) {}
++      }
++
++      if (close(fd))
++              error(1, errno, "close");
++
++      free(buf);
++      usleep(400 * 1000);
++}
++
++static void __attribute__((noreturn)) usage(const char *filepath)
++{
++      fprintf(stderr, "\nUsage: %s [options] hostname\n"
++                      "\nwhere options are:\n"
++                      "  -4:   only IPv4\n"
++                      "  -6:   only IPv6\n"
++                      "  -h:   show this message\n"
++                      "  -l N: send N bytes at a time\n"
++                      "  -r:   use raw\n"
++                      "  -R:   use raw (IP_HDRINCL)\n"
++                      "  -p N: connect to port N\n"
++                      "  -u:   use udp\n",
++                      filepath);
++      exit(1);
++}
++
++static void parse_opt(int argc, char **argv)
++{
++      int proto_count = 0;
++      char c;
++
++      while ((c = getopt(argc, argv, "46hl:p:rRu")) != -1) {
++              switch (c) {
++              case '4':
++                      do_ipv6 = 0;
++                      break;
++              case '6':
++                      do_ipv4 = 0;
++                      break;
++              case 'r':
++                      proto_count++;
++                      cfg_proto = SOCK_RAW;
++                      cfg_ipproto = IPPROTO_UDP;
++                      break;
++              case 'R':
++                      proto_count++;
++                      cfg_proto = SOCK_RAW;
++                      cfg_ipproto = IPPROTO_RAW;
++                      break;
++              case 'u':
++                      proto_count++;
++                      cfg_proto = SOCK_DGRAM;
++                      cfg_ipproto = IPPROTO_UDP;
++                      break;
++              case 'l':
++                      cfg_payload_len = strtoul(optarg, NULL, 10);
++                      break;
++              case 'p':
++                      dest_port = strtoul(optarg, NULL, 10);
++                      break;
++              case 'h':
++              default:
++                      usage(argv[0]);
++              }
++      }
++
++      if (!cfg_payload_len)
++              error(1, 0, "payload may not be nonzero");
++      if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
++              error(1, 0, "udp packet might exceed expected MTU");
++      if (!do_ipv4 && !do_ipv6)
++              error(1, 0, "pass -4 or -6, not both");
++      if (proto_count > 1)
++              error(1, 0, "pass -r, -R or -u, not multiple");
++
++      if (optind != argc - 1)
++              error(1, 0, "missing required hostname argument");
++}
++
++static void resolve_hostname(const char *hostname)
++{
++      struct addrinfo *addrs, *cur;
++      int have_ipv4 = 0, have_ipv6 = 0;
++
++      if (getaddrinfo(hostname, NULL, NULL, &addrs))
++              error(1, errno, "getaddrinfo");
++
++      cur = addrs;
++      while (cur && !have_ipv4 && !have_ipv6) {
++              if (!have_ipv4 && cur->ai_family == AF_INET) {
++                      memcpy(&daddr, cur->ai_addr, sizeof(daddr));
++                      daddr.sin_port = htons(dest_port);
++                      have_ipv4 = 1;
++              }
++              else if (!have_ipv6 && cur->ai_family == AF_INET6) {
++                      memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
++                      daddr6.sin6_port = htons(dest_port);
++                      have_ipv6 = 1;
++              }
++              cur = cur->ai_next;
++      }
++      if (addrs)
++              freeaddrinfo(addrs);
++
++      do_ipv4 &= have_ipv4;
++      do_ipv6 &= have_ipv6;
++}
++
++static void do_main(int family)
++{
++      fprintf(stderr, "family:       %s\n",
++                      family == PF_INET ? "INET" : "INET6");
++
++      fprintf(stderr, "test SND\n");
++      do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
++
++      fprintf(stderr, "test ENQ\n");
++      do_test(family, SOF_TIMESTAMPING_TX_SCHED);
++
++      fprintf(stderr, "test ENQ + SND\n");
++      do_test(family, SOF_TIMESTAMPING_TX_SCHED |
++                      SOF_TIMESTAMPING_TX_SOFTWARE);
++
++      if (cfg_proto == SOCK_STREAM) {
++              fprintf(stderr, "\ntest ACK\n");
++              do_test(family, SOF_TIMESTAMPING_TX_ACK);
++
++              fprintf(stderr, "\ntest SND + ACK\n");
++              do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
++                              SOF_TIMESTAMPING_TX_ACK);
++
++              fprintf(stderr, "\ntest ENQ + SND + ACK\n");
++              do_test(family, SOF_TIMESTAMPING_TX_SCHED |
++                              SOF_TIMESTAMPING_TX_SOFTWARE |
++                              SOF_TIMESTAMPING_TX_ACK);
++      }
++}
++
++const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
++
++int main(int argc, char **argv)
++{
++      if (argc == 1)
++              usage(argv[0]);
++
++      parse_opt(argc, argv);
++      resolve_hostname(argv[argc - 1]);
++
++      fprintf(stderr, "protocol:     %s\n", sock_names[cfg_proto]);
++      fprintf(stderr, "payload:      %u\n", cfg_payload_len);
++      fprintf(stderr, "server port:  %u\n", dest_port);
++      fprintf(stderr, "\n");
++
++      if (do_ipv4)
++              do_main(PF_INET);
++      if (do_ipv6)
++              do_main(PF_INET6);
++
++      return 0;
++}
index c821e1c5f7c2dcc11bd138d43a661496d6fbdeb6..4d8d4bc0e96f068bfbeee226b611ece9ada9937d 100644 (file)
@@ -31,3 +31,8 @@ pstore-convert-console-write-to-use-write_buf.patch
 matroxfb-fix-size-of-memcpy.patch
 staging-speakup-replace-strncpy-with-memcpy.patch
 kconfig-avoid-format-overflow-warning-from-gcc-8.1.patch
+exec-avoid-gcc-8-warning-for-get_task_comm.patch
+vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch
+vme-ca91cx42-fix-lm_ctl-address-mask.patch
+staging-rts5208-fix-gcc-8-logic-error-warning.patch
+selftests-move-networking-timestamping-from-documentation.patch
diff --git a/queue-3.18/staging-rts5208-fix-gcc-8-logic-error-warning.patch b/queue-3.18/staging-rts5208-fix-gcc-8-logic-error-warning.patch
new file mode 100644 (file)
index 0000000..d859618
--- /dev/null
@@ -0,0 +1,43 @@
+From 58930cced012adb01bc78b3687049b17ef44d0a3 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Tue, 5 Sep 2017 09:33:32 +0200
+Subject: staging: rts5208: fix gcc-8 logic error warning
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit 58930cced012adb01bc78b3687049b17ef44d0a3 upstream.
+
+As gcc-8 points out, the bit mask check makes no sense here:
+
+drivers/staging/rts5208/sd.c: In function 'ext_sd_send_cmd_get_rsp':
+drivers/staging/rts5208/sd.c:4130:25: error: bitwise comparison always evaluates to true [-Werror=tautological-compare]
+
+However, the code is even more bogus, as we have already
+checked for the SD_RSP_TYPE_R0 case earlier in the function
+and returned success. As seen in the mmc/sd driver core,
+SD_RSP_TYPE_R0 means "no response" anyway, so checking for
+a particular response would not help either.
+
+This just removes the nonsensical code to get rid of the
+warning.
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/rts5208/sd.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/staging/rts5208/sd.c
++++ b/drivers/staging/rts5208/sd.c
+@@ -3531,9 +3531,6 @@ RTY_SEND_CMD:
+                               if ((ptr[3] & 0x1E) != 0x04)
+                                       TRACE_RET(chip, STATUS_FAIL);
+-                      } else if (rsp_type == SD_RSP_TYPE_R0) {
+-                              if ((ptr[3] & 0x1E) != 0x03)
+-                                      TRACE_RET(chip, STATUS_FAIL);
+                       }
+               }
+       }
diff --git a/queue-3.18/vme-ca91cx42-fix-lm_ctl-address-mask.patch b/queue-3.18/vme-ca91cx42-fix-lm_ctl-address-mask.patch
new file mode 100644 (file)
index 0000000..12d8dbf
--- /dev/null
@@ -0,0 +1,42 @@
+From 5a2f8831243337dd05df42174b4d7b1e01daacda Mon Sep 17 00:00:00 2001
+From: Dmitry Kalinkin <dmitry.kalinkin@gmail.com>
+Date: Thu, 28 May 2015 15:07:07 +0300
+Subject: vme: ca91cx42: fix LM_CTL address mask
+
+From: Dmitry Kalinkin <dmitry.kalinkin@gmail.com>
+
+commit 5a2f8831243337dd05df42174b4d7b1e01daacda upstream.
+
+Universe II datasheet defines following address space values
+for LM_CTL[16:18]
+
+000=A16
+001=A24
+010=A32
+011,100,101=Reserved
+110=User1
+111=User2
+
+Mask 5<<16 is not the right one for matching [16:18], instead we should
+use 7<<16.
+
+Signed-off-by: Dmitry Kalinkin <dmitry.kalinkin@gmail.com>
+Cc: Igor Alekseev <igor.alekseev@itep.ru>
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/vme/bridges/vme_ca91cx42.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/vme/bridges/vme_ca91cx42.h
++++ b/drivers/vme/bridges/vme_ca91cx42.h
+@@ -547,7 +547,7 @@ static const int CA91CX42_LINT_LM[] = {
+ #define CA91CX42_LM_CTL_DATA          (1<<22)
+ #define CA91CX42_LM_CTL_SUPR          (1<<21)
+ #define CA91CX42_LM_CTL_NPRIV         (1<<20)
+-#define CA91CX42_LM_CTL_AS_M          (5<<16)
++#define CA91CX42_LM_CTL_AS_M          (7<<16)
+ #define CA91CX42_LM_CTL_AS_A16                0
+ #define CA91CX42_LM_CTL_AS_A24                (1<<16)
+ #define CA91CX42_LM_CTL_AS_A32                (1<<17)
diff --git a/queue-3.18/vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch b/queue-3.18/vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch
new file mode 100644 (file)
index 0000000..d4f8e85
--- /dev/null
@@ -0,0 +1,47 @@
+From c8a6a09c1c617402cc9254b2bc8da359a0347d75 Mon Sep 17 00:00:00 2001
+From: Augusto Mecking Caringi <augustocaringi@gmail.com>
+Date: Tue, 10 Jan 2017 10:45:00 +0000
+Subject: vme: Fix wrong pointer utilization in ca91cx42_slave_get
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Augusto Mecking Caringi <augustocaringi@gmail.com>
+
+commit c8a6a09c1c617402cc9254b2bc8da359a0347d75 upstream.
+
+In ca91cx42_slave_get function, the value pointed by vme_base pointer is
+set through:
+
+*vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]);
+
+So it must be dereferenced to be used in calculation of pci_base:
+
+*pci_base = (dma_addr_t)*vme_base + pci_offset;
+
+This bug was caught thanks to the following gcc warning:
+
+drivers/vme/bridges/vme_ca91cx42.c: In function ‘ca91cx42_slave_get’:
+drivers/vme/bridges/vme_ca91cx42.c:467:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
+*pci_base = (dma_addr_t)vme_base + pci_offset;
+
+Signed-off-by: Augusto Mecking Caringi <augustocaringi@gmail.com>
+Acked-By: Martyn Welch <martyn@welchs.me.uk>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/vme/bridges/vme_ca91cx42.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/vme/bridges/vme_ca91cx42.c
++++ b/drivers/vme/bridges/vme_ca91cx42.c
+@@ -468,7 +468,7 @@ static int ca91cx42_slave_get(struct vme
+       vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]);
+       pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]);
+-      *pci_base = (dma_addr_t)vme_base + pci_offset;
++      *pci_base = (dma_addr_t)*vme_base + pci_offset;
+       *size = (unsigned long long)((vme_bound - *vme_base) + granularity);
+       *enabled = 0;