diff options
author | David S. Miller <davem@davemloft.net> | 2013-12-05 19:45:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-12-05 19:45:14 -0500 |
commit | 426e1fa31e0d8e982891e801c80b84b74f209f10 (patch) | |
tree | bc53409418ffa918fb3f175639bc5c9245c4219f | |
parent | e1ca87bb1b64b044163e686ff3bb71405156c561 (diff) | |
parent | a4bcc795e9cc84902b86edbfbb755ecb38d11f91 (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>
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 | |||
85 | by the network device and will be empty without that support. | 85 | by the network device and will be empty without that support. |
86 | 86 | ||
87 | 87 | ||
88 | SIOCSHWTSTAMP: | 88 | SIOCSHWTSTAMP, SIOCGHWTSTAMP: |
89 | 89 | ||
90 | Hardware time stamping must also be initialized for each device driver | 90 | Hardware time stamping must also be initialized for each device driver |
91 | that is expected to do hardware time stamping. The parameter is defined in | 91 | 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 | |||
115 | space is responsible to ensure that multiple processes don't interfere | 115 | space is responsible to ensure that multiple processes don't interfere |
116 | with each other and that the settings are reset. | 116 | with each other and that the settings are reset. |
117 | 117 | ||
118 | Any process can read the actual configuration by passing this | ||
119 | structure to ioctl(SIOCGHWTSTAMP) in the same way. However, this has | ||
120 | not been implemented in all drivers. | ||
121 | |||
118 | /* possible values for hwtstamp_config->tx_type */ | 122 | /* possible values for hwtstamp_config->tx_type */ |
119 | enum { | 123 | enum { |
120 | /* | 124 | /* |
@@ -157,7 +161,8 @@ DEVICE IMPLEMENTATION | |||
157 | 161 | ||
158 | A driver which supports hardware time stamping must support the | 162 | A driver which supports hardware time stamping must support the |
159 | SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with | 163 | SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with |
160 | the actual values as described in the section on SIOCSHWTSTAMP. | 164 | the actual values as described in the section on SIOCSHWTSTAMP. It |
165 | should also support SIOCGHWTSTAMP. | ||
161 | 166 | ||
162 | Time stamps for received packets must be stored in the skb. To get a pointer | 167 | Time stamps for received packets must be stored in the skb. To get a pointer |
163 | to the shared time stamp structure of the skb call skb_hwtstamps(). Then | 168 | to 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 @@ | |||
1 | timestamping | 1 | timestamping |
2 | hwtstamp_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 @@ | |||
2 | obj- := dummy.o | 2 | obj- := dummy.o |
3 | 3 | ||
4 | # List of programs to build | 4 | # List of programs to build |
5 | hostprogs-y := timestamping | 5 | hostprogs-y := timestamping hwtstamp_config |
6 | 6 | ||
7 | # Tell kbuild to always build the programs | 7 | # Tell kbuild to always build the programs |
8 | always := $(hostprogs-y) | 8 | always := $(hostprogs-y) |
9 | 9 | ||
10 | HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include | 10 | HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include |
11 | HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include | ||
11 | 12 | ||
12 | clean: | 13 | clean: |
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 | |||
18 | static int | ||
19 | lookup_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 | |||
30 | static const char * | ||
31 | lookup_name(const char **names, int size, int value) | ||
32 | { | ||
33 | return (value >= 0 && value < size) ? names[value] : NULL; | ||
34 | } | ||
35 | |||
36 | static 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 | |||
45 | static 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 | |||
54 | static 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 | |||
75 | static 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 | |||
85 | int 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 | ||
670 | static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, | 670 | static 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 | ||
827 | static 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 | |||
827 | static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) | 837 | static 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 | ||
13597 | static int tg3_hwtstamp_ioctl(struct net_device *dev, | 13597 | static 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 | ||
13684 | static 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 | |||
13685 | static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 13745 | static 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 | ||
340 | void fec_ptp_init(struct platform_device *pdev); | 340 | void fec_ptp_init(struct platform_device *pdev); |
341 | void fec_ptp_start_cyclecounter(struct net_device *ndev); | 341 | void fec_ptp_start_cyclecounter(struct net_device *ndev); |
342 | int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd); | 342 | int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); |
343 | int 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 | */ |
277 | int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) | 277 | int 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 | ||
324 | int 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 | ||
798 | static int gfar_hwtstamp_ioctl(struct net_device *netdev, | 798 | static 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 */ | 847 | static 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 | |||
849 | static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 861 | static 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 | **/ |
5793 | static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) | 5793 | static 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 | ||
5828 | static 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 | |||
5828 | static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | 5836 | static 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 | ||
2028 | static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) | 2028 | static 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 | ||
2087 | static 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 | |||
2087 | static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 2095 | static 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 | ||
3192 | static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) | 3192 | static 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 | ||
3253 | static 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) | |||
3263 | static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 3278 | static 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 | ||
556 | struct ethtool_ts_info; | 556 | struct ethtool_ts_info; |
557 | void efx_ptp_probe(struct efx_nic *efx); | 557 | void efx_ptp_probe(struct efx_nic *efx); |
558 | int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd); | 558 | int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); |
559 | int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); | ||
559 | void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); | 560 | void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); |
560 | bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); | 561 | bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); |
561 | int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); | 562 | int 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 | ||
1234 | int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd) | 1234 | int 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 | ||
1254 | int 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 | |||
1254 | static void ptp_event_failure(struct efx_nic *efx, int expected_frag_len) | 1263 | static 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 | ||
1325 | static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) | 1325 | static 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 | ||
1386 | static 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 | ||
1388 | static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | 1406 | static 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. */ |
484 | static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq, | 484 | static 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 | ||
537 | static 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 | |||
538 | static inline bool filter_packet(struct net_device *dev, void *buf) | 552 | static 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) | |||
2098 | static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 2112 | static 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, ®s->channel[ch].ch_event); | 373 | __raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); |
374 | } | 374 | } |
375 | 375 | ||
376 | static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | 376 | static 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 | ||
420 | static 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 | |||
420 | static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, | 446 | static 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 | */ |
41 | struct hwtstamp_config { | 41 | struct 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 | ||
3011 | static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, | 2994 | /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ |
2995 | static 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 | ||
3114 | static 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 | |||
3135 | struct rtentry32 { | 3095 | struct 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: |