Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 426e1fa3 authored by David S. Miller's avatar David S. Miller
Browse files


Ben Hutchings says:

====================
SIOCGHWTSTAMP ioctl

1. Add the SIOCGHWTSTAMP ioctl and update the timestamping
documentation.
2. Implement SIOCGHWTSTAMP in most drivers that support SIOCSHWTSTAMP.
3. Add a test program to exercise SIOC{G,S}HWTSTAMP.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e1ca87bb a4bcc795
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support
by the network device and will be empty without that support.


SIOCSHWTSTAMP:
SIOCSHWTSTAMP, SIOCGHWTSTAMP:

Hardware time stamping must also be initialized for each device driver
that is expected to do hardware time stamping. The parameter is defined in
@@ -115,6 +115,10 @@ Only a processes with admin rights may change the configuration. User
space is responsible to ensure that multiple processes don't interfere
with each other and that the settings are reset.

Any process can read the actual configuration by passing this
structure to ioctl(SIOCGHWTSTAMP) in the same way.  However, this has
not been implemented in all drivers.

/* possible values for hwtstamp_config->tx_type */
enum {
	/*
@@ -157,7 +161,8 @@ DEVICE IMPLEMENTATION

A driver which supports hardware time stamping must support the
SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
the actual values as described in the section on SIOCSHWTSTAMP.
the actual values as described in the section on SIOCSHWTSTAMP.  It
should also support SIOCGHWTSTAMP.

Time stamps for received packets must be stored in the skb. To get a pointer
to the shared time stamp structure of the skb call skb_hwtstamps(). Then
+1 −0
Original line number Diff line number Diff line
timestamping
hwtstamp_config
+3 −2
Original line number Diff line number Diff line
@@ -2,12 +2,13 @@
obj- := dummy.o

# List of programs to build
hostprogs-y := timestamping
hostprogs-y := timestamping hwtstamp_config

# Tell kbuild to always build the programs
always := $(hostprogs-y)

HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include

clean:
	rm -f timestamping
	rm -f timestamping hwtstamp_config
+134 −0
Original line number Diff line number Diff line
/* 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;
}
+17 −4
Original line number Diff line number Diff line
@@ -667,8 +667,8 @@ static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result)
	return 1000000000UL / ppn;
}

static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
		struct ifreq *ifr, int cmd)
static int bfin_mac_hwtstamp_set(struct net_device *netdev,
				 struct ifreq *ifr)
{
	struct hwtstamp_config config;
	struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -824,6 +824,16 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
		-EFAULT : 0;
}

static int bfin_mac_hwtstamp_get(struct net_device *netdev,
				 struct ifreq *ifr)
{
	struct bfin_mac_local *lp = netdev_priv(netdev);

	return copy_to_user(ifr->ifr_data, &lp->stamp_cfg,
			    sizeof(lp->stamp_cfg)) ?
		-EFAULT : 0;
}

static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
{
	struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -1062,7 +1072,8 @@ static void bfin_phc_release(struct bfin_mac_local *lp)
#else
# define bfin_mac_hwtstamp_is_none(cfg) 0
# define bfin_mac_hwtstamp_init(dev)
# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP)
# define bfin_mac_hwtstamp_set(dev, ifr) (-EOPNOTSUPP)
# define bfin_mac_hwtstamp_get(dev, ifr) (-EOPNOTSUPP)
# define bfin_rx_hwtstamp(dev, skb)
# define bfin_tx_hwtstamp(dev, skb)
# define bfin_phc_init(netdev, dev) 0
@@ -1496,7 +1507,9 @@ static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)

	switch (cmd) {
	case SIOCSHWTSTAMP:
		return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
		return bfin_mac_hwtstamp_set(netdev, ifr);
	case SIOCGHWTSTAMP:
		return bfin_mac_hwtstamp_get(netdev, ifr);
	default:
		if (lp->phydev)
			return phy_mii_ioctl(lp->phydev, ifr, cmd);
Loading