diff options
| -rw-r--r-- | drivers/net/phy/phy.c | 5 | ||||
| -rw-r--r-- | drivers/net/phy/phy_device.c | 2 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 4 | ||||
| -rw-r--r-- | include/linux/phy.h | 22 | ||||
| -rw-r--r-- | include/linux/skbuff.h | 31 | ||||
| -rw-r--r-- | net/Kconfig | 10 | ||||
| -rw-r--r-- | net/core/Makefile | 2 | ||||
| -rw-r--r-- | net/core/dev.c | 3 | ||||
| -rw-r--r-- | net/core/timestamping.c | 126 | ||||
| -rw-r--r-- | net/socket.c | 4 |
10 files changed, 208 insertions, 1 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index bd88d818f08..5130db8f5c4 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
| @@ -361,6 +361,11 @@ int phy_mii_ioctl(struct phy_device *phydev, | |||
| 361 | } | 361 | } |
| 362 | break; | 362 | break; |
| 363 | 363 | ||
| 364 | case SIOCSHWTSTAMP: | ||
| 365 | if (phydev->drv->hwtstamp) | ||
| 366 | return phydev->drv->hwtstamp(phydev, ifr); | ||
| 367 | /* fall through */ | ||
| 368 | |||
| 364 | default: | 369 | default: |
| 365 | return -EOPNOTSUPP; | 370 | return -EOPNOTSUPP; |
| 366 | } | 371 | } |
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 1a99bb24410..c0761197c07 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
| @@ -460,6 +460,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, | |||
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | phydev->attached_dev = dev; | 462 | phydev->attached_dev = dev; |
| 463 | dev->phydev = phydev; | ||
| 463 | 464 | ||
| 464 | phydev->dev_flags = flags; | 465 | phydev->dev_flags = flags; |
| 465 | 466 | ||
| @@ -513,6 +514,7 @@ EXPORT_SYMBOL(phy_attach); | |||
| 513 | */ | 514 | */ |
| 514 | void phy_detach(struct phy_device *phydev) | 515 | void phy_detach(struct phy_device *phydev) |
| 515 | { | 516 | { |
| 517 | phydev->attached_dev->phydev = NULL; | ||
| 516 | phydev->attached_dev = NULL; | 518 | phydev->attached_dev = NULL; |
| 517 | 519 | ||
| 518 | /* If the device had no specific driver before (i.e. - it | 520 | /* If the device had no specific driver before (i.e. - it |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c4fedf00054..fdc3f299223 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | 54 | ||
| 55 | struct vlan_group; | 55 | struct vlan_group; |
| 56 | struct netpoll_info; | 56 | struct netpoll_info; |
| 57 | struct phy_device; | ||
| 57 | /* 802.11 specific */ | 58 | /* 802.11 specific */ |
| 58 | struct wireless_dev; | 59 | struct wireless_dev; |
| 59 | /* source back-compat hooks */ | 60 | /* source back-compat hooks */ |
| @@ -1065,6 +1066,9 @@ struct net_device { | |||
| 1065 | #endif | 1066 | #endif |
| 1066 | /* n-tuple filter list attached to this device */ | 1067 | /* n-tuple filter list attached to this device */ |
| 1067 | struct ethtool_rx_ntuple_list ethtool_ntuple_list; | 1068 | struct ethtool_rx_ntuple_list ethtool_ntuple_list; |
| 1069 | |||
| 1070 | /* phy device may attach itself for hardware timestamping */ | ||
| 1071 | struct phy_device *phydev; | ||
| 1068 | }; | 1072 | }; |
| 1069 | #define to_net_dev(d) container_of(d, struct net_device, dev) | 1073 | #define to_net_dev(d) container_of(d, struct net_device, dev) |
| 1070 | 1074 | ||
diff --git a/include/linux/phy.h b/include/linux/phy.h index d63736a8400..6b0a782c622 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
| @@ -234,6 +234,8 @@ enum phy_state { | |||
| 234 | PHY_RESUMING | 234 | PHY_RESUMING |
| 235 | }; | 235 | }; |
| 236 | 236 | ||
| 237 | struct sk_buff; | ||
| 238 | |||
| 237 | /* phy_device: An instance of a PHY | 239 | /* phy_device: An instance of a PHY |
| 238 | * | 240 | * |
| 239 | * drv: Pointer to the driver for this PHY instance | 241 | * drv: Pointer to the driver for this PHY instance |
| @@ -402,6 +404,26 @@ struct phy_driver { | |||
| 402 | /* Clears up any memory if needed */ | 404 | /* Clears up any memory if needed */ |
| 403 | void (*remove)(struct phy_device *phydev); | 405 | void (*remove)(struct phy_device *phydev); |
| 404 | 406 | ||
| 407 | /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */ | ||
| 408 | int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); | ||
| 409 | |||
| 410 | /* | ||
| 411 | * Requests a Rx timestamp for 'skb'. If the skb is accepted, | ||
| 412 | * the phy driver promises to deliver it using netif_rx() as | ||
| 413 | * soon as a timestamp becomes available. One of the | ||
| 414 | * PTP_CLASS_ values is passed in 'type'. The function must | ||
| 415 | * return true if the skb is accepted for delivery. | ||
| 416 | */ | ||
| 417 | bool (*rxtstamp)(struct phy_device *dev, struct sk_buff *skb, int type); | ||
| 418 | |||
| 419 | /* | ||
| 420 | * Requests a Tx timestamp for 'skb'. The phy driver promises | ||
| 421 | * to deliver it to the socket's error queue as soon as a | ||
| 422 | * timestamp becomes available. One of the PTP_CLASS_ values | ||
| 423 | * is passed in 'type'. | ||
| 424 | */ | ||
| 425 | void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type); | ||
| 426 | |||
| 405 | struct device_driver driver; | 427 | struct device_driver driver; |
| 406 | }; | 428 | }; |
| 407 | #define to_phy_driver(d) container_of(d, struct phy_driver, driver) | 429 | #define to_phy_driver(d) container_of(d, struct phy_driver, driver) |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a1b0400c8d8..f5aa87e1e0c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
| @@ -1933,6 +1933,36 @@ static inline ktime_t net_invalid_timestamp(void) | |||
| 1933 | return ktime_set(0, 0); | 1933 | return ktime_set(0, 0); |
| 1934 | } | 1934 | } |
| 1935 | 1935 | ||
| 1936 | extern void skb_timestamping_init(void); | ||
| 1937 | |||
| 1938 | #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING | ||
| 1939 | |||
| 1940 | extern void skb_clone_tx_timestamp(struct sk_buff *skb); | ||
| 1941 | extern bool skb_defer_rx_timestamp(struct sk_buff *skb); | ||
| 1942 | |||
| 1943 | #else /* CONFIG_NETWORK_PHY_TIMESTAMPING */ | ||
| 1944 | |||
| 1945 | static inline void skb_clone_tx_timestamp(struct sk_buff *skb) | ||
| 1946 | { | ||
| 1947 | } | ||
| 1948 | |||
| 1949 | static inline bool skb_defer_rx_timestamp(struct sk_buff *skb) | ||
| 1950 | { | ||
| 1951 | return false; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | #endif /* !CONFIG_NETWORK_PHY_TIMESTAMPING */ | ||
| 1955 | |||
| 1956 | /** | ||
| 1957 | * skb_complete_tx_timestamp() - deliver cloned skb with tx timestamps | ||
| 1958 | * | ||
| 1959 | * @skb: clone of the the original outgoing packet | ||
| 1960 | * @hwtstamps: hardware time stamps | ||
| 1961 | * | ||
| 1962 | */ | ||
| 1963 | void skb_complete_tx_timestamp(struct sk_buff *skb, | ||
| 1964 | struct skb_shared_hwtstamps *hwtstamps); | ||
| 1965 | |||
| 1936 | /** | 1966 | /** |
| 1937 | * skb_tstamp_tx - queue clone of skb with send time stamps | 1967 | * skb_tstamp_tx - queue clone of skb with send time stamps |
| 1938 | * @orig_skb: the original outgoing packet | 1968 | * @orig_skb: the original outgoing packet |
| @@ -1965,6 +1995,7 @@ static inline void sw_tx_timestamp(struct sk_buff *skb) | |||
| 1965 | */ | 1995 | */ |
| 1966 | static inline void skb_tx_timestamp(struct sk_buff *skb) | 1996 | static inline void skb_tx_timestamp(struct sk_buff *skb) |
| 1967 | { | 1997 | { |
| 1998 | skb_clone_tx_timestamp(skb); | ||
| 1968 | sw_tx_timestamp(skb); | 1999 | sw_tx_timestamp(skb); |
| 1969 | } | 2000 | } |
| 1970 | 2001 | ||
diff --git a/net/Kconfig b/net/Kconfig index 0d68b40fc0e..b3250944cde 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
| @@ -86,6 +86,16 @@ config NETWORK_SECMARK | |||
| 86 | to nfmark, but designated for security purposes. | 86 | to nfmark, but designated for security purposes. |
| 87 | If you are unsure how to answer this question, answer N. | 87 | If you are unsure how to answer this question, answer N. |
| 88 | 88 | ||
| 89 | config NETWORK_PHY_TIMESTAMPING | ||
| 90 | bool "Timestamping in PHY devices" | ||
| 91 | depends on EXPERIMENTAL | ||
| 92 | help | ||
| 93 | This allows timestamping of network packets by PHYs with | ||
| 94 | hardware timestamping capabilities. This option adds some | ||
| 95 | overhead in the transmit and receive paths. | ||
| 96 | |||
| 97 | If you are unsure how to answer this question, answer N. | ||
| 98 | |||
| 89 | menuconfig NETFILTER | 99 | menuconfig NETFILTER |
| 90 | bool "Network packet filtering framework (Netfilter)" | 100 | bool "Network packet filtering framework (Netfilter)" |
| 91 | ---help--- | 101 | ---help--- |
diff --git a/net/core/Makefile b/net/core/Makefile index 51c3eec850e..8a04dd22cf7 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
| @@ -18,4 +18,4 @@ obj-$(CONFIG_NET_DMA) += user_dma.o | |||
| 18 | obj-$(CONFIG_FIB_RULES) += fib_rules.o | 18 | obj-$(CONFIG_FIB_RULES) += fib_rules.o |
| 19 | obj-$(CONFIG_TRACEPOINTS) += net-traces.o | 19 | obj-$(CONFIG_TRACEPOINTS) += net-traces.o |
| 20 | obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o | 20 | obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o |
| 21 | 21 | obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o | |
diff --git a/net/core/dev.c b/net/core/dev.c index e2b9fa2c917..1c002c7ef5d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2957,6 +2957,9 @@ int netif_receive_skb(struct sk_buff *skb) | |||
| 2957 | if (netdev_tstamp_prequeue) | 2957 | if (netdev_tstamp_prequeue) |
| 2958 | net_timestamp_check(skb); | 2958 | net_timestamp_check(skb); |
| 2959 | 2959 | ||
| 2960 | if (skb_defer_rx_timestamp(skb)) | ||
| 2961 | return NET_RX_SUCCESS; | ||
| 2962 | |||
| 2960 | #ifdef CONFIG_RPS | 2963 | #ifdef CONFIG_RPS |
| 2961 | { | 2964 | { |
| 2962 | struct rps_dev_flow voidflow, *rflow = &voidflow; | 2965 | struct rps_dev_flow voidflow, *rflow = &voidflow; |
diff --git a/net/core/timestamping.c b/net/core/timestamping.c new file mode 100644 index 00000000000..0ae6c22da85 --- /dev/null +++ b/net/core/timestamping.c | |||
| @@ -0,0 +1,126 @@ | |||
