aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-12-05 19:45:14 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-05 19:45:14 -0500
commit426e1fa31e0d8e982891e801c80b84b74f209f10 (patch)
treebc53409418ffa918fb3f175639bc5c9245c4219f
parente1ca87bb1b64b044163e686ff3bb71405156c561 (diff)
parenta4bcc795e9cc84902b86edbfbb755ecb38d11f91 (diff)
Merge branch 'siocghwtstamp' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next
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: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/timestamping.txt9
-rw-r--r--Documentation/networking/timestamping/.gitignore1
-rw-r--r--Documentation/networking/timestamping/Makefile5
-rw-r--r--Documentation/networking/timestamping/hwtstamp_config.c134
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.c21
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c71
-rw-r--r--drivers/net/ethernet/freescale/fec.h3
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c8
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c16
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c22
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c14
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c27
-rw-r--r--drivers/net/ethernet/sfc/efx.c4
-rw-r--r--drivers/net/ethernet/sfc/nic.h3
-rw-r--r--drivers/net/ethernet/sfc/ptp.c11
-rw-r--r--drivers/net/ethernet/ti/cpsw.c24
-rw-r--r--drivers/net/ethernet/tile/tilegx.c22
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c36
-rw-r--r--include/uapi/linux/net_tstamp.h16
-rw-r--r--include/uapi/linux/sockios.h3
-rw-r--r--net/core/dev_ioctl.c2
-rw-r--r--net/socket.c57
23 files changed, 423 insertions, 100 deletions
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt
index 98097d8cb910..661d3c316a17 100644
--- a/Documentation/networking/timestamping.txt
+++ b/Documentation/networking/timestamping.txt
@@ -85,7 +85,7 @@ Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support
85by the network device and will be empty without that support. 85by the network device and will be empty without that support.
86 86
87 87
88SIOCSHWTSTAMP: 88SIOCSHWTSTAMP, SIOCGHWTSTAMP:
89 89
90Hardware time stamping must also be initialized for each device driver 90Hardware time stamping must also be initialized for each device driver
91that is expected to do hardware time stamping. The parameter is defined in 91that 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
115space is responsible to ensure that multiple processes don't interfere 115space is responsible to ensure that multiple processes don't interfere
116with each other and that the settings are reset. 116with each other and that the settings are reset.
117 117
118Any process can read the actual configuration by passing this
119structure to ioctl(SIOCGHWTSTAMP) in the same way. However, this has
120not been implemented in all drivers.
121
118/* possible values for hwtstamp_config->tx_type */ 122/* possible values for hwtstamp_config->tx_type */
119enum { 123enum {
120 /* 124 /*
@@ -157,7 +161,8 @@ DEVICE IMPLEMENTATION
157 161
158A driver which supports hardware time stamping must support the 162A driver which supports hardware time stamping must support the
159SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with 163SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
160the actual values as described in the section on SIOCSHWTSTAMP. 164the actual values as described in the section on SIOCSHWTSTAMP. It
165should also support SIOCGHWTSTAMP.
161 166
162Time stamps for received packets must be stored in the skb. To get a pointer 167Time stamps for received packets must be stored in the skb. To get a pointer
163to the shared time stamp structure of the skb call skb_hwtstamps(). Then 168to the shared time stamp structure of the skb call skb_hwtstamps(). Then
diff --git a/Documentation/networking/timestamping/.gitignore b/Documentation/networking/timestamping/.gitignore
index 71e81eb2e22f..a380159765ce 100644
--- a/Documentation/networking/timestamping/.gitignore
+++ b/Documentation/networking/timestamping/.gitignore
@@ -1 +1,2 @@
1timestamping 1timestamping
2hwtstamp_config
diff --git a/Documentation/networking/timestamping/Makefile b/Documentation/networking/timestamping/Makefile
index e79973443e9f..d934afc8306a 100644
--- a/Documentation/networking/timestamping/Makefile
+++ b/Documentation/networking/timestamping/Makefile
@@ -2,12 +2,13 @@
2obj- := dummy.o 2obj- := dummy.o
3 3
4# List of programs to build 4# List of programs to build
5hostprogs-y := timestamping 5hostprogs-y := timestamping hwtstamp_config
6 6
7# Tell kbuild to always build the programs 7# Tell kbuild to always build the programs
8always := $(hostprogs-y) 8always := $(hostprogs-y)
9 9
10HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include 10HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
11HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include
11 12
12clean: 13clean:
13 rm -f timestamping 14 rm -f timestamping hwtstamp_config
diff --git a/Documentation/networking/timestamping/hwtstamp_config.c b/Documentation/networking/timestamping/hwtstamp_config.c
new file mode 100644
index 000000000000..e8b685a7f15f
--- /dev/null
+++ b/Documentation/networking/timestamping/hwtstamp_config.c
@@ -0,0 +1,134 @@
1/* Test program for SIOC{G,S}HWTSTAMP
2 * Copyright 2013 Solarflare Communications
3 * Author: Ben Hutchings
4 */
5
6#include <errno.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <sys/socket.h>
12#include <sys/ioctl.h>
13
14#include <linux/if.h>
15#include <linux/net_tstamp.h>
16#include <linux/sockios.h>
17
18static int
19lookup_value(const char **names, int size, const char *name)
20{
21 int value;
22
23 for (value = 0; value < size; value++)
24 if (names[value] && strcasecmp(names[value], name) == 0)
25 return value;
26
27 return -1;
28}
29
30static const char *
31lookup_name(const char **names, int size, int value)
32{
33 return (value >= 0 && value < size) ? names[value] : NULL;
34}
35
36static void list_names(FILE *f, const char **names, int size)
37{
38 int value;
39
40 for (value = 0; value < size; value++)
41 if (names[value])
42 fprintf(f, " %s\n", names[value]);
43}
44
45static const char *tx_types[] = {
46#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
47 TX_TYPE(OFF),
48 TX_TYPE(ON),
49 TX_TYPE(ONESTEP_SYNC)
50#undef TX_TYPE
51};
52#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
53
54static const char *rx_filters[] = {
55#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
56 RX_FILTER(NONE),
57 RX_FILTER(ALL),
58 RX_FILTER(SOME),
59 RX_FILTER(PTP_V1_L4_EVENT),
60 RX_FILTER(PTP_V1_L4_SYNC),
61 RX_FILTER(PTP_V1_L4_DELAY_REQ),
62 RX_FILTER(PTP_V2_L4_EVENT),
63 RX_FILTER(PTP_V2_L4_SYNC),
64 RX_FILTER(PTP_V2_L4_DELAY_REQ),
65 RX_FILTER(PTP_V2_L2_EVENT),
66 RX_FILTER(PTP_V2_L2_SYNC),
67 RX_FILTER(PTP_V2_L2_DELAY_REQ),
68 RX_FILTER(PTP_V2_EVENT),
69 RX_FILTER(PTP_V2_SYNC),
70 RX_FILTER(PTP_V2_DELAY_REQ),
71#undef RX_FILTER
72};
73#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
74
75static void usage(void)
76{
77 fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
78 "tx_type is any of (case-insensitive):\n",
79 stderr);
80 list_names(stderr, tx_types, N_TX_TYPES);
81 fputs("rx_filter is any of (case-insensitive):\n", stderr);
82 list_names(stderr, rx_filters, N_RX_FILTERS);
83}
84
85int main(int argc, char **argv)
86{
87 struct ifreq ifr;
88 struct hwtstamp_config config;
89 const char *name;
90 int sock;
91
92 if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
93 usage();
94 return 2;
95 }
96
97 if (argc == 4) {
98 config.flags = 0;
99 config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
100 config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
101 if (config.tx_type < 0 || config.rx_filter < 0) {
102 usage();
103 return 2;
104 }
105 }
106
107 sock = socket(AF_INET, SOCK_DGRAM, 0);
108 if (sock < 0) {
109 perror("socket");
110 return 1;
111 }
112
113 strcpy(ifr.ifr_name, argv[1]);
114 ifr.ifr_data = (caddr_t)&config;
115
116 if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
117 perror("ioctl");
118 return 1;
119 }
120
121 printf("flags = %#x\n", config.flags);
122 name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
123 if (name)
124 printf("tx_type = %s\n", name);
125 else
126 printf("tx_type = %d\n", config.tx_type);
127 name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
128 if (name)
129 printf("rx_filter = %s\n", name);
130 else
131 printf("rx_filter = %d\n", config.rx_filter);
132
133 return 0;
134}
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index 75fb1d20d6fd..0d4f29579879 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -667,8 +667,8 @@ static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result)
667 return 1000000000UL / ppn; 667 return 1000000000UL / ppn;
668} 668}
669 669
670static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, 670static int bfin_mac_hwtstamp_set(struct net_device *netdev,
671 struct ifreq *ifr, int cmd) 671 struct ifreq *ifr)
672{ 672{
673 struct hwtstamp_config config; 673 struct hwtstamp_config config;
674 struct bfin_mac_local *lp = netdev_priv(netdev); 674 struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -824,6 +824,16 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
824 -EFAULT : 0; 824 -EFAULT : 0;
825} 825}
826 826
827static int bfin_mac_hwtstamp_get(struct net_device *netdev,
828 struct ifreq *ifr)
829{
830 struct bfin_mac_local *lp = netdev_priv(netdev);
831
832 return copy_to_user(ifr->ifr_data, &lp->stamp_cfg,
833 sizeof(lp->stamp_cfg)) ?
834 -EFAULT : 0;
835}
836
827static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) 837static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
828{ 838{
829 struct bfin_mac_local *lp = netdev_priv(netdev); 839 struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -1062,7 +1072,8 @@ static void bfin_phc_release(struct bfin_mac_local *lp)
1062#else 1072#else
1063# define bfin_mac_hwtstamp_is_none(cfg) 0 1073# define bfin_mac_hwtstamp_is_none(cfg) 0
1064# define bfin_mac_hwtstamp_init(dev) 1074# define bfin_mac_hwtstamp_init(dev)
1065# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP) 1075# define bfin_mac_hwtstamp_set(dev, ifr) (-EOPNOTSUPP)
1076# define bfin_mac_hwtstamp_get(dev, ifr) (-EOPNOTSUPP)
1066# define bfin_rx_hwtstamp(dev, skb) 1077# define bfin_rx_hwtstamp(dev, skb)
1067# define bfin_tx_hwtstamp(dev, skb) 1078# define bfin_tx_hwtstamp(dev, skb)
1068# define bfin_phc_init(netdev, dev) 0 1079# 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)
1496 1507
1497 switch (cmd) { 1508 switch (cmd) {
1498 case SIOCSHWTSTAMP: 1509 case SIOCSHWTSTAMP:
1499 return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd); 1510 return bfin_mac_hwtstamp_set(netdev, ifr);
1511 case SIOCGHWTSTAMP:
1512 return bfin_mac_hwtstamp_get(netdev, ifr);
1500 default: 1513 default:
1501 if (lp->phydev) 1514 if (lp->phydev)
1502 return phy_mii_ioctl(lp->phydev, ifr, cmd); 1515 return phy_mii_ioctl(lp->phydev, ifr, cmd);
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 472305cdff4f..e35a1c5fc9b1 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -13594,14 +13594,13 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
13594 13594
13595} 13595}
13596 13596
13597static int tg3_hwtstamp_ioctl(struct net_device *dev, 13597static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
13598 struct ifreq *ifr, int cmd)
13599{ 13598{
13600 struct tg3 *tp = netdev_priv(dev); 13599 struct tg3 *tp = netdev_priv(dev);
13601 struct hwtstamp_config stmpconf; 13600 struct hwtstamp_config stmpconf;
13602 13601
13603 if (!tg3_flag(tp, PTP_CAPABLE)) 13602 if (!tg3_flag(tp, PTP_CAPABLE))
13604 return -EINVAL; 13603 return -EOPNOTSUPP;
13605 13604
13606 if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) 13605 if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf)))
13607 return -EFAULT; 13606 return -EFAULT;
@@ -13682,6 +13681,67 @@ static int tg3_hwtstamp_ioctl(struct net_device *dev,
13682 -EFAULT : 0; 13681 -EFAULT : 0;
13683} 13682}
13684 13683
13684static int tg3_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
13685{
13686 struct tg3 *tp = netdev_priv(dev);
13687 struct hwtstamp_config stmpconf;
13688
13689 if (!tg3_flag(tp, PTP_CAPABLE))
13690 return -EOPNOTSUPP;
13691
13692 stmpconf.flags = 0;
13693 stmpconf.tx_type = (tg3_flag(tp, TX_TSTAMP_EN) ?
13694 HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF);
13695
13696 switch (tp->rxptpctl) {
13697 case 0:
13698 stmpconf.rx_filter = HWTSTAMP_FILTER_NONE;
13699 break;
13700 case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_ALL_V1_EVENTS:
13701 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
13702 break;
13703 case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
13704 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
13705 break;
13706 case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_DELAY_REQ:
13707 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
13708 break;
13709 case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
13710 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
13711 break;
13712 case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
13713 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
13714 break;
13715 case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
13716 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
13717 break;
13718 case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
13719 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
13720 break;
13721 case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
13722 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC;
13723 break;
13724 case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
13725 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
13726 break;
13727 case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_DELAY_REQ:
13728 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
13729 break;
13730 case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_DELAY_REQ:
13731 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ;
13732 break;
13733 case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_DELAY_REQ:
13734 stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
13735 break;
13736 default:
13737 WARN_ON_ONCE(1);
13738 return -ERANGE;
13739 }
13740
13741 return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ?
13742 -EFAULT : 0;
13743}
13744
13685static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 13745static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
13686{ 13746{
13687 struct mii_ioctl_data *data = if_mii(ifr); 13747 struct mii_ioctl_data *data = if_mii(ifr);
@@ -13735,7 +13795,10 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
13735 return err; 13795 return err;
13736 13796
13737 case SIOCSHWTSTAMP: 13797 case SIOCSHWTSTAMP:
13738 return tg3_hwtstamp_ioctl(dev, ifr, cmd); 13798 return tg3_hwtstamp_set(dev, ifr);
13799
13800 case SIOCGHWTSTAMP:
13801 return tg3_hwtstamp_get(dev, ifr);
13739 13802
13740 default: 13803 default:
13741 /* do nothing */ 13804 /* do nothing */
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 0120217a16dd..3b8d6d19ff05 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -339,7 +339,8 @@ struct fec_enet_private {
339 339
340void fec_ptp_init(struct platform_device *pdev); 340void fec_ptp_init(struct platform_device *pdev);
341void fec_ptp_start_cyclecounter(struct net_device *ndev); 341void fec_ptp_start_cyclecounter(struct net_device *ndev);
342int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd); 342int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
343int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
343 344
344/****************************************************************************/ 345/****************************************************************************/
345#endif /* FEC_H */ 346#endif /* FEC_H */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 73b000df8a08..92ef4e5eddf7 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1683,8 +1683,12 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
1683 if (!phydev) 1683 if (!phydev)
1684 return -ENODEV; 1684 return -ENODEV;
1685 1685
1686 if (cmd == SIOCSHWTSTAMP && fep->bufdesc_ex) 1686 if (fep->bufdesc_ex) {
1687 return fec_ptp_ioctl(ndev, rq, cmd); 1687 if (cmd == SIOCSHWTSTAMP)
1688 return fec_ptp_set(ndev, rq);
1689 if (cmd == SIOCGHWTSTAMP)
1690 return fec_ptp_get(ndev, rq);
1691 }
1688 1692
1689 return phy_mii_ioctl(phydev, rq, cmd); 1693 return phy_mii_ioctl(phydev, rq, cmd);
1690} 1694}
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 5007e4f9fff9..3a74ea48fd40 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -274,7 +274,7 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
274 * @ifreq: ioctl data 274 * @ifreq: ioctl data
275 * @cmd: particular ioctl requested 275 * @cmd: particular ioctl requested
276 */ 276 */
277int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) 277int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr)
278{ 278{
279 struct fec_enet_private *fep = netdev_priv(ndev); 279 struct fec_enet_private *fep = netdev_priv(ndev);
280 280
@@ -321,6 +321,20 @@ int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
321 -EFAULT : 0; 321 -EFAULT : 0;
322} 322}
323 323
324int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr)
325{
326 struct fec_enet_private *fep = netdev_priv(ndev);
327 struct hwtstamp_config config;
328
329 config.flags = 0;
330 config.tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
331 config.rx_filter = (fep->hwts_rx_en ?
332 HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
333
334 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
335 -EFAULT : 0;
336}
337
324/** 338/**
325 * fec_time_keep - call timecounter_read every second to avoid timer overrun 339 * fec_time_keep - call timecounter_read every second to avoid timer overrun
326 * because ENET just support 32bit counter, will timeout in 4s 340 * because ENET just support 32bit counter, will timeout in 4s
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index b14d7904a075..365342d293e8 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -795,8 +795,7 @@ err_grp_init:
795 return err; 795 return err;
796} 796}
797 797
798static int gfar_hwtstamp_ioctl(struct net_device *netdev, 798static int gfar_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)
799 struct ifreq *ifr, int cmd)
800{ 799{
801 struct hwtstamp_config config; 800 struct hwtstamp_config config;
802 struct gfar_private *priv = netdev_priv(netdev); 801 struct gfar_private *priv = netdev_priv(netdev);
@@ -845,7 +844,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,
845 -EFAULT : 0; 844 -EFAULT : 0;
846} 845}
847 846
848/* Ioctl MII Interface */ 847static int gfar_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr)
848{
849 struct hwtstamp_config config;
850 struct gfar_private *priv = netdev_priv(netdev);
851
852 config.flags = 0;
853 config.tx_type = priv->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
854 config.rx_filter = (priv->hwts_rx_en ?
855 HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
856
857 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
858 -EFAULT : 0;
859}
860
849static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 861static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
850{ 862{
851 struct gfar_private *priv = netdev_priv(dev); 863 struct gfar_private *priv = netdev_priv(dev);
@@ -854,7 +866,9 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
854 return -EINVAL; 866 return -EINVAL;
855 867
856 if (cmd == SIOCSHWTSTAMP) 868 if (cmd == SIOCSHWTSTAMP)
857 return gfar_hwtstamp_ioctl(dev, rq, cmd); 869 return gfar_hwtstamp_set(dev, rq);
870 if (cmd == SIOCGHWTSTAMP)
871 return gfar_hwtstamp_get(dev, rq);
858 872
859 if (!priv->phydev) 873 if (!priv->phydev)
860 return -ENODEV; 874 return -ENODEV;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 8d3945ab7334..051d1583e211 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -5790,7 +5790,7 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
5790 * specified. Matching the kind of event packet is not supported, with the 5790 * specified. Matching the kind of event packet is not supported, with the
5791 * exception of "all V2 events regardless of level 2 or 4". 5791 * exception of "all V2 events regardless of level 2 or 4".
5792 **/ 5792 **/
5793static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) 5793static int e1000e_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)
5794{ 5794{
5795 struct e1000_adapter *adapter = netdev_priv(netdev); 5795 struct e1000_adapter *adapter = netdev_priv(netdev);
5796 struct hwtstamp_config config; 5796 struct hwtstamp_config config;
@@ -5825,6 +5825,14 @@ static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)
5825 sizeof(config)) ? -EFAULT : 0; 5825 sizeof(config)) ? -EFAULT : 0;
5826} 5826}
5827 5827
5828static int e1000e_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr)
5829{
5830 struct e1000_adapter *adapter = netdev_priv(netdev);
5831
5832 return copy_to_user(ifr->ifr_data, &adapter->hwtstamp_config,
5833 sizeof(adapter->hwtstamp_config)) ? -EFAULT : 0;
5834}
5835
5828static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 5836static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
5829{ 5837{
5830 switch (cmd) { 5838 switch (cmd) {
@@ -5833,7 +5841,9 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
5833 case SIOCSMIIREG: 5841 case SIOCSMIIREG:
5834 return e1000_mii_ioctl(netdev, ifr, cmd); 5842 return e1000_mii_ioctl(netdev, ifr, cmd);
5835 case SIOCSHWTSTAMP: 5843 case SIOCSHWTSTAMP:
5836 return e1000e_hwtstamp_ioctl(netdev, ifr); 5844 return e1000e_hwtstamp_set(netdev, ifr);
5845 case SIOCGHWTSTAMP:
5846 return e1000e_hwtstamp_get(netdev, ifr);
5837 default: 5847 default:
5838 return -EOPNOTSUPP; 5848 return -EOPNOTSUPP;
5839 } 5849 }
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index e72d8a112a6b..709e5ec5ce14 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2025,7 +2025,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
2025 return 0; 2025 return 0;
2026} 2026}
2027 2027
2028static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) 2028static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
2029{ 2029{
2030 struct mlx4_en_priv *priv = netdev_priv(dev); 2030 struct mlx4_en_priv *priv = netdev_priv(dev);
2031 struct mlx4_en_dev *mdev = priv->mdev; 2031 struct mlx4_en_dev *mdev = priv->mdev;
@@ -2084,11 +2084,21 @@ static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
2084 sizeof(config)) ? -EFAULT : 0; 2084 sizeof(config)) ? -EFAULT : 0;
2085} 2085}
2086 2086
2087static int mlx4_en_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
2088{
2089 struct mlx4_en_priv *priv = netdev_priv(dev);
2090
2091 return copy_to_user(ifr->ifr_data, &priv->hwtstamp_config,
2092 sizeof(priv->hwtstamp_config)) ? -EFAULT : 0;
2093}
2094
2087static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 2095static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2088{ 2096{
2089 switch (cmd) { 2097 switch (cmd) {
2090 case SIOCSHWTSTAMP: 2098 case SIOCSHWTSTAMP:
2091 return mlx4_en_hwtstamp_ioctl(dev, ifr); 2099 return mlx4_en_hwtstamp_set(dev, ifr);
2100 case SIOCGHWTSTAMP:
2101 return mlx4_en_hwtstamp_get(dev, ifr);
2092 default: 2102 default:
2093 return -EOPNOTSUPP; 2103 return -EOPNOTSUPP;
2094 } 2104 }
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index f9876ea8c8bf..5d4ad589ebf3 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -3189,7 +3189,7 @@ static enum vxge_hw_status vxge_timestamp_config(struct __vxge_hw_device *devh)
3189 return status; 3189 return status;
3190} 3190}
3191 3191
3192static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) 3192static int vxge_hwtstamp_set(struct vxgedev *vdev, void __user *data)
3193{ 3193{
3194 struct hwtstamp_config config; 3194 struct hwtstamp_config config;
3195 int i; 3195 int i;
@@ -3250,6 +3250,21 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data)
3250 return 0; 3250 return 0;
3251} 3251}
3252 3252
3253static int vxge_hwtstamp_get(struct vxgedev *vdev, void __user *data)
3254{
3255 struct hwtstamp_config config;
3256
3257 config.flags = 0;
3258 config.tx_type = HWTSTAMP_TX_OFF;
3259 config.rx_filter = (vdev->rx_hwts ?
3260 HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
3261
3262 if (copy_to_user(data, &config, sizeof(config)))
3263 return -EFAULT;
3264
3265 return 0;
3266}
3267
3253/** 3268/**
3254 * vxge_ioctl 3269 * vxge_ioctl
3255 * @dev: Device pointer. 3270 * @dev: Device pointer.
@@ -3263,19 +3278,15 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data)
3263static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 3278static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3264{ 3279{
3265 struct vxgedev *vdev = netdev_priv(dev); 3280 struct vxgedev *vdev = netdev_priv(dev);
3266 int ret;
3267 3281
3268 switch (cmd) { 3282 switch (cmd) {
3269 case SIOCSHWTSTAMP: 3283 case SIOCSHWTSTAMP:
3270 ret = vxge_hwtstamp_ioctl(vdev, rq->ifr_data); 3284 return vxge_hwtstamp_set(vdev, rq->ifr_data);
3271 if (ret) 3285 case SIOCGHWTSTAMP:
3272 return ret; 3286 return vxge_hwtstamp_get(vdev, rq->ifr_data);
3273 break;
3274 default: 3287 default:
3275 return -EOPNOTSUPP; 3288 return -EOPNOTSUPP;
3276 } 3289 }
3277
3278 return 0;
3279} 3290}
3280 3291
3281/** 3292/**
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 2e27837ce6a2..958d8c7fa02f 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1847,7 +1847,9 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
1847 struct mii_ioctl_data *data = if_mii(ifr); 1847 struct mii_ioctl_data *data = if_mii(ifr);
1848 1848
1849 if (cmd == SIOCSHWTSTAMP) 1849 if (cmd == SIOCSHWTSTAMP)
1850 return efx_ptp_ioctl(efx, ifr, cmd); 1850 return efx_ptp_set_ts_config(efx, ifr);
1851 if (cmd == SIOCGHWTSTAMP)
1852 return efx_ptp_get_ts_config(efx, ifr);
1851 1853
1852 /* Convert phy_id from older PRTAD/DEVAD format */ 1854 /* Convert phy_id from older PRTAD/DEVAD format */
1853 if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) && 1855 if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) &&
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 11b6112d9249..33852e824f12 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -555,7 +555,8 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
555 555
556struct ethtool_ts_info; 556struct ethtool_ts_info;
557void efx_ptp_probe(struct efx_nic *efx); 557void efx_ptp_probe(struct efx_nic *efx);
558int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd); 558int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr);
559int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr);
559void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); 560void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info);
560bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); 561bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
561int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); 562int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 03acf57df045..afd4d3a50460 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -1231,7 +1231,7 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info)
1231 1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); 1231 1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);
1232} 1232}
1233 1233
1234int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd) 1234int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr)
1235{ 1235{
1236 struct hwtstamp_config config; 1236 struct hwtstamp_config config;
1237 int rc; 1237 int rc;
@@ -1251,6 +1251,15 @@ int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd)
1251 ? -EFAULT : 0; 1251 ? -EFAULT : 0;
1252} 1252}
1253 1253
1254int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr)
1255{
1256 if (!efx->ptp_data)
1257 return -EOPNOTSUPP;
1258
1259 return copy_to_user(ifr->ifr_data, &efx->ptp_data->config,
1260 sizeof(efx->ptp_data->config)) ? -EFAULT : 0;
1261}
1262
1254static void ptp_event_failure(struct efx_nic *efx, int expected_frag_len) 1263static void ptp_event_failure(struct efx_nic *efx, int expected_frag_len)
1255{ 1264{
1256 struct efx_ptp_data *ptp = efx->ptp_data; 1265 struct efx_ptp_data *ptp = efx->ptp_data;
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a91f0c9d4511..c8a54f96cf5d 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1322,7 +1322,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
1322 __raw_writel(ETH_P_1588, &priv->regs->ts_ltype); 1322 __raw_writel(ETH_P_1588, &priv->regs->ts_ltype);
1323} 1323}
1324 1324
1325static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) 1325static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
1326{ 1326{
1327 struct cpsw_priv *priv = netdev_priv(dev); 1327 struct cpsw_priv *priv = netdev_priv(dev);
1328 struct cpts *cpts = priv->cpts; 1328 struct cpts *cpts = priv->cpts;
@@ -1383,6 +1383,24 @@ static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
1383 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 1383 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
1384} 1384}
1385 1385
1386static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
1387{
1388 struct cpsw_priv *priv = netdev_priv(dev);
1389 struct cpts *cpts = priv->cpts;
1390 struct hwtstamp_config cfg;
1391
1392 if (priv->version != CPSW_VERSION_1 &&
1393 priv->version != CPSW_VERSION_2)
1394 return -EOPNOTSUPP;
1395
1396 cfg.flags = 0;
1397 cfg.tx_type = cpts->tx_enable ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
1398 cfg.rx_filter = (cpts->rx_enable ?
1399 HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE);
1400
1401 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
1402}
1403
1386#endif /*CONFIG_TI_CPTS*/ 1404#endif /*CONFIG_TI_CPTS*/
1387 1405
1388static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) 1406static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
@@ -1397,7 +1415,9 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
1397 switch (cmd) { 1415 switch (cmd) {
1398#ifdef CONFIG_TI_CPTS 1416#ifdef CONFIG_TI_CPTS
1399 case SIOCSHWTSTAMP: 1417 case SIOCSHWTSTAMP:
1400 return cpsw_hwtstamp_ioctl(dev, req); 1418 return cpsw_hwtstamp_set(dev, req);
1419 case SIOCGHWTSTAMP:
1420 return cpsw_hwtstamp_get(dev, req);
1401#endif 1421#endif
1402 case SIOCGMIIPHY: 1422 case SIOCGMIIPHY:
1403 data->phy_id = priv->slaves[slave_no].phy->addr; 1423 data->phy_id = priv->slaves[slave_no].phy->addr;
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index 628b736e5ae7..858f9a786b8c 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -481,8 +481,7 @@ static void tile_tx_timestamp(struct sk_buff *skb, int instance)
481} 481}
482 482
483/* Use ioctl() to enable or disable TX or RX timestamping. */ 483/* Use ioctl() to enable or disable TX or RX timestamping. */
484static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq, 484static int tile_hwtstamp_set(struct net_device *dev, struct ifreq *rq)
485 int cmd)
486{ 485{
487#ifdef CONFIG_PTP_1588_CLOCK_TILEGX 486#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
488 struct hwtstamp_config config; 487 struct hwtstamp_config config;
@@ -535,6 +534,21 @@ static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq,
535#endif 534#endif
536} 535}
537 536
537static int tile_hwtstamp_get(struct net_device *dev, struct ifreq *rq)
538{
539#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
540 struct tile_net_priv *priv = netdev_priv(dev);
541
542 if (copy_to_user(rq->ifr_data, &priv->stamp_cfg,
543 sizeof(priv->stamp_cfg)))
544 return -EFAULT;
545
546 return 0;
547#else
548 return -EOPNOTSUPP;
549#endif
550}
551
538static inline bool filter_packet(struct net_device *dev, void *buf) 552static inline bool filter_packet(struct net_device *dev, void *buf)
539{ 553{
540 /* Filter packets received before we're up. */ 554 /* Filter packets received before we're up. */
@@ -2098,7 +2112,9 @@ static void tile_net_tx_timeout(struct net_device *dev)
2098static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 2112static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2099{ 2113{
2100 if (cmd == SIOCSHWTSTAMP) 2114 if (cmd == SIOCSHWTSTAMP)
2101 return tile_hwtstamp_ioctl(dev, rq, cmd); 2115 return tile_hwtstamp_set(dev, rq);
2116 if (cmd == SIOCGHWTSTAMP)
2117 return tile_hwtstamp_get(dev, rq);
2102 2118
2103 return -EOPNOTSUPP; 2119 return -EOPNOTSUPP;
2104} 2120}
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index bcc224a83734..25283f17d82f 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -373,7 +373,7 @@ static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb)
373 __raw_writel(TX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event); 373 __raw_writel(TX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
374} 374}
375 375
376static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 376static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)
377{ 377{
378 struct hwtstamp_config cfg; 378 struct hwtstamp_config cfg;
379 struct ixp46x_ts_regs *regs; 379 struct ixp46x_ts_regs *regs;
@@ -417,6 +417,32 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
417 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 417 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
418} 418}
419 419
420static int hwtstamp_get(struct net_device *netdev, struct ifreq *ifr)
421{
422 struct hwtstamp_config cfg;
423 struct port *port = netdev_priv(netdev);
424
425 cfg.flags = 0;
426 cfg.tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
427
428 switch (port->hwts_rx_en) {
429 case 0:
430 cfg.rx_filter = HWTSTAMP_FILTER_NONE;
431 break;
432 case PTP_SLAVE_MODE:
433 cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
434 break;
435 case PTP_MASTER_MODE:
436 cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
437 break;
438 default:
439 WARN_ON_ONCE(1);
440 return -ERANGE;
441 }
442
443 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
444}
445
420static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, 446static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location,
421 int write, u16 cmd) 447 int write, u16 cmd)
422{ 448{
@@ -959,8 +985,12 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
959 if (!netif_running(dev)) 985 if (!netif_running(dev))
960 return -EINVAL; 986 return -EINVAL;
961 987
962 if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP) 988 if (cpu_is_ixp46x()) {
963 return hwtstamp_ioctl(dev, req, cmd); 989 if (cmd == SIOCSHWTSTAMP)
990 return hwtstamp_set(dev, req);
991 if (cmd == SIOCGHWTSTAMP)
992 return hwtstamp_get(dev, req);
993 }
964 994
965 return phy_mii_ioctl(port->phydev, req, cmd); 995 return phy_mii_ioctl(port->phydev, req, cmd);
966} 996}
diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h
index ae5df122e42f..f53879c0f590 100644
--- a/include/uapi/linux/net_tstamp.h
+++ b/include/uapi/linux/net_tstamp.h
@@ -26,17 +26,17 @@ enum {
26}; 26};
27 27
28/** 28/**
29 * struct hwtstamp_config - %SIOCSHWTSTAMP parameter 29 * struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter
30 * 30 *
31 * @flags: no flags defined right now, must be zero 31 * @flags: no flags defined right now, must be zero for %SIOCSHWTSTAMP
32 * @tx_type: one of HWTSTAMP_TX_* 32 * @tx_type: one of HWTSTAMP_TX_*
33 * @rx_type: one of one of HWTSTAMP_FILTER_* 33 * @rx_filter: one of HWTSTAMP_FILTER_*
34 * 34 *
35 * %SIOCSHWTSTAMP expects a &struct ifreq with a ifr_data pointer to 35 * %SIOCGHWTSTAMP and %SIOCSHWTSTAMP expect a &struct ifreq with a
36 * this structure. dev_ifsioc() in the kernel takes care of the 36 * ifr_data pointer to this structure. For %SIOCSHWTSTAMP, if the
37 * translation between 32 bit userspace and 64 bit kernel. The 37 * driver or hardware does not support the requested @rx_filter value,
38 * structure is intentionally chosen so that it has the same layout on 38 * the driver may use a more general filter mode. In this case
39 * 32 and 64 bit systems, don't break this! 39 * @rx_filter will indicate the actual mode on return.
40 */ 40 */
41struct hwtstamp_config { 41struct hwtstamp_config {
42 int flags; 42 int flags;
diff --git a/include/uapi/linux/sockios.h b/include/uapi/linux/sockios.h
index 7997a506ad41..e888b1aed69f 100644
--- a/include/uapi/linux/sockios.h
+++ b/include/uapi/linux/sockios.h
@@ -125,7 +125,8 @@
125#define SIOCBRDELIF 0x89a3 /* remove interface from bridge */ 125#define SIOCBRDELIF 0x89a3 /* remove interface from bridge */
126 126
127/* hardware time stamping: parameters in linux/net_tstamp.h */ 127/* hardware time stamping: parameters in linux/net_tstamp.h */
128#define SIOCSHWTSTAMP 0x89b0 128#define SIOCSHWTSTAMP 0x89b0 /* set and get config */
129#define SIOCGHWTSTAMP 0x89b1 /* get config */
129 130
130/* Device private ioctl calls */ 131/* Device private ioctl calls */
131 132
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 5b7d0e1d0664..cf999e09bcd2 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -327,6 +327,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
327 cmd == SIOCBRADDIF || 327 cmd == SIOCBRADDIF ||
328 cmd == SIOCBRDELIF || 328 cmd == SIOCBRDELIF ||
329 cmd == SIOCSHWTSTAMP || 329 cmd == SIOCSHWTSTAMP ||
330 cmd == SIOCGHWTSTAMP ||
330 cmd == SIOCWANDEV) { 331 cmd == SIOCWANDEV) {
331 err = -EOPNOTSUPP; 332 err = -EOPNOTSUPP;
332 if (ops->ndo_do_ioctl) { 333 if (ops->ndo_do_ioctl) {
@@ -546,6 +547,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
546 */ 547 */
547 default: 548 default:
548 if (cmd == SIOCWANDEV || 549 if (cmd == SIOCWANDEV ||
550 cmd == SIOCGHWTSTAMP ||
549 (cmd >= SIOCDEVPRIVATE && 551 (cmd >= SIOCDEVPRIVATE &&
550 cmd <= SIOCDEVPRIVATE + 15)) { 552 cmd <= SIOCDEVPRIVATE + 15)) {
551 dev_load(net, ifr.ifr_name); 553 dev_load(net, ifr.ifr_name);
diff --git a/net/socket.c b/net/socket.c
index e83c416708af..cd38a785f7d2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2968,11 +2968,8 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
2968 struct compat_ifreq __user *ifr32) 2968 struct compat_ifreq __user *ifr32)
2969{ 2969{
2970 struct ifreq kifr; 2970 struct ifreq kifr;
2971 struct ifreq __user *uifr;
2972 mm_segment_t old_fs; 2971 mm_segment_t old_fs;
2973 int err; 2972 int err;
2974 u32 data;
2975 void __user *datap;
2976 2973
2977 switch (cmd) { 2974 switch (cmd) {
2978 case SIOCBONDENSLAVE: 2975 case SIOCBONDENSLAVE:
@@ -2989,26 +2986,13 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
2989 set_fs(old_fs); 2986 set_fs(old_fs);
2990 2987
2991 return err; 2988 return err;
2992 case SIOCBONDSLAVEINFOQUERY:
2993 case SIOCBONDINFOQUERY:
2994 uifr = compat_alloc_user_space(sizeof(*uifr));
2995 if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
2996 return -EFAULT;
2997
2998 if (get_user(data, &ifr32->ifr_ifru.ifru_data))
2999 return -EFAULT;
3000
3001 datap = compat_ptr(data);
3002 if (put_user(datap, &uifr->ifr_ifru.ifru_data))
3003 return -EFAULT;
3004
3005 return dev_ioctl(net, cmd, uifr);
3006 default: 2989 default:
3007 return -ENOIOCTLCMD; 2990 return -ENOIOCTLCMD;
3008 } 2991 }
3009} 2992}
3010 2993
3011static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, 2994/* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2995static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
3012 struct compat_ifreq __user *u_ifreq32) 2996 struct compat_ifreq __user *u_ifreq32)
3013{ 2997{
3014 struct ifreq __user *u_ifreq64; 2998 struct ifreq __user *u_ifreq64;
@@ -3019,19 +3003,16 @@ static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
3019 if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), 3003 if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
3020 IFNAMSIZ)) 3004 IFNAMSIZ))
3021 return -EFAULT; 3005 return -EFAULT;
3022 if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) 3006 if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
3023 return -EFAULT; 3007 return -EFAULT;
3024 data64 = compat_ptr(data32); 3008 data64 = compat_ptr(data32);
3025 3009
3026 u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); 3010 u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
3027 3011
3028 /* Don't check these user accesses, just let that get trapped
3029 * in the ioctl handler instead.
3030 */
3031 if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], 3012 if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
3032 IFNAMSIZ)) 3013 IFNAMSIZ))
3033 return -EFAULT; 3014 return -EFAULT;
3034 if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) 3015 if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
3035 return -EFAULT; 3016 return -EFAULT;
3036 3017
3037 return dev_ioctl(net, cmd, u_ifreq64); 3018 return dev_ioctl(net, cmd, u_ifreq64);
@@ -3111,27 +3092,6 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3111 return err; 3092 return err;
3112} 3093}
3113 3094
3114static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3115{
3116 void __user *uptr;
3117 compat_uptr_t uptr32;
3118 struct ifreq __user *uifr;
3119
3120 uifr = compat_alloc_user_space(sizeof(*uifr));
3121 if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3122 return -EFAULT;
3123
3124 if (get_user(uptr32, &uifr32->ifr_data))
3125 return -EFAULT;
3126
3127 uptr = compat_ptr(uptr32);
3128
3129 if (put_user(uptr, &uifr->ifr_data))
3130 return -EFAULT;
3131
3132 return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3133}
3134
3135struct rtentry32 { 3095struct rtentry32 {
3136 u32 rt_pad1; 3096 u32 rt_pad1;
3137 struct sockaddr rt_dst; /* target address */ 3097 struct sockaddr rt_dst; /* target address */
@@ -3243,7 +3203,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
3243 struct net *net = sock_net(sk); 3203 struct net *net = sock_net(sk);
3244 3204
3245 if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 3205 if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3246 return siocdevprivate_ioctl(net, cmd, argp); 3206 return compat_ifr_data_ioctl(net, cmd, argp);
3247 3207
3248 switch (cmd) { 3208 switch (cmd) {
3249 case SIOCSIFBR: 3209 case SIOCSIFBR:
@@ -3263,8 +3223,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
3263 case SIOCBONDENSLAVE: 3223 case SIOCBONDENSLAVE:
3264 case SIOCBONDRELEASE: 3224 case SIOCBONDRELEASE:
3265 case SIOCBONDSETHWADDR: 3225 case SIOCBONDSETHWADDR:
3266 case SIOCBONDSLAVEINFOQUERY:
3267 case SIOCBONDINFOQUERY:
3268 case SIOCBONDCHANGEACTIVE: 3226 case SIOCBONDCHANGEACTIVE:
3269 return bond_ioctl(net, cmd, argp); 3227 return bond_ioctl(net, cmd, argp);
3270 case SIOCADDRT: 3228 case SIOCADDRT:
@@ -3274,8 +3232,11 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
3274 return do_siocgstamp(net, sock, cmd, argp); 3232 return do_siocgstamp(net, sock, cmd, argp);
3275 case SIOCGSTAMPNS: 3233 case SIOCGSTAMPNS:
3276 return do_siocgstampns(net, sock, cmd, argp); 3234 return do_siocgstampns(net, sock, cmd, argp);
3235 case SIOCBONDSLAVEINFOQUERY:
3236 case SIOCBONDINFOQUERY:
3277 case SIOCSHWTSTAMP: 3237 case SIOCSHWTSTAMP:
3278 return compat_siocshwtstamp(net, argp); 3238 case SIOCGHWTSTAMP:
3239 return compat_ifr_data_ioctl(net, cmd, argp);
3279 3240
3280 case FIOSETOWN: 3241 case FIOSETOWN:
3281 case SIOCSPGRP: 3242 case SIOCSPGRP: