Currently the stack supports time stamping in PHY devices. However, there are newer, non-PHY devices that can snoop an MII bus and provide time stamps. In order to support such devices, this patch introduces a new interface to be used by both PHY and non-PHY devices. In addition, the one and only user of the old PHY time stamping API is converted to the new interface.
Showing the changes to include/linux (2 of 6 files). Show all
Unified · Split
| @@ -0,0 +1,58 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Support for generic time stamping devices on MII buses. | ||
| 4 | * Copyright (C) 2018 Richard Cochran <richardcochran@gmail.com> | ||
| 5 | */ | ||
| 6 | #ifndef _LINUX_MII_TIMESTAMPER_H | ||
| 7 | #define _LINUX_MII_TIMESTAMPER_H | ||
| 8 | |||
| 9 | #include <linux/device.h> | ||
| 10 | #include <linux/ethtool.h> | ||
| 11 | #include <linux/skbuff.h> | ||
| 12 | |||
| 13 | struct phy_device; | ||
| 14 | |||
| 15 | /** | ||
| 16 | * struct mii_timestamper - Callback interface to MII time stamping devices. | ||
| 17 | * | ||
| 18 | * @rxtstamp: Requests a Rx timestamp for 'skb'. If the skb is accepted, | ||
| 19 | * the MII time stamping device promises to deliver it using | ||
| 20 | * netif_rx() as soon as a timestamp becomes available. One of | ||
| 21 | * the PTP_CLASS_ values is passed in 'type'. The function | ||
| 22 | * must return true if the skb is accepted for delivery. | ||
| 23 | * | ||
| 24 | * @txtstamp: Requests a Tx timestamp for 'skb'. The MII time stamping | ||
| 25 | * device promises to deliver it using skb_complete_tx_timestamp() | ||
| 26 | * as soon as a timestamp becomes available. One of the PTP_CLASS_ | ||
| 27 | * values is passed in 'type'. | ||
| 28 | * | ||
| 29 | * @hwtstamp: Handles SIOCSHWTSTAMP ioctl for hardware time stamping. | ||
| 30 | * | ||
| 31 | * @link_state: Allows the device to respond to changes in the link | ||
| 32 | * state. The caller invokes this function while holding | ||
| 33 | * the phy_device mutex. | ||
| 34 | * | ||
| 35 | * @ts_info: Handles ethtool queries for hardware time stamping. | ||
| 36 | * | ||
| 37 | * Drivers for PHY time stamping devices should embed their | ||
| 38 | * mii_timestamper within a private structure, obtaining a reference | ||
| 39 | * to it using container_of(). | ||
| 40 | */ | ||
| 41 | struct mii_timestamper { | ||
| 42 | bool (*rxtstamp)(struct mii_timestamper *mii_ts, | ||
| 43 | struct sk_buff *skb, int type); | ||
| 44 | |||
| 45 | void (*txtstamp)(struct mii_timestamper *mii_ts, | ||
| 46 | struct sk_buff *skb, int type); | ||
| 47 | |||
| 48 | int (*hwtstamp)(struct mii_timestamper *mii_ts, | ||
| 49 | struct ifreq *ifreq); | ||
| 50 | |||
| 51 | void (*link_state)(struct mii_timestamper *mii_ts, | ||
| 52 | struct phy_device *phydev); | ||
| 53 | |||
| 54 | int (*ts_info)(struct mii_timestamper *mii_ts, | ||
| 55 | struct ethtool_ts_info *ts_info); | ||
| 56 | }; | ||
| 57 | |||
| 58 | #endif | ||
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #include <linux/linkmode.h> | 17 | #include <linux/linkmode.h> |
| 18 | #include <linux/mdio.h> | 18 | #include <linux/mdio.h> |
| 19 | #include <linux/mii.h> | 19 | #include <linux/mii.h> |
| 20 | #include <linux/mii_timestamper.h> | ||
| 20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 21 | #include <linux/timer.h> | 22 | #include <linux/timer.h> |
| 22 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
| @@ -441,6 +442,7 @@ struct phy_device { · 418 unmodified lines | |||
| 441 | struct sfp_bus *sfp_bus; | 442 | struct sfp_bus *sfp_bus; |
| 442 | struct phylink *phylink; | 443 | struct phylink *phylink; |
| 443 | struct net_device *attached_dev; | 444 | struct net_device *attached_dev; |
| 445 | struct mii_timestamper *mii_ts; | ||
| 444 | 446 | ||
| 445 | u8 mdix; | 447 | u8 mdix; |
| 446 | u8 mdix_ctrl; | 448 | u8 mdix_ctrl; |
| @@ -546,29 +548,6 @@ struct phy_driver { · 99 unmodified lines | |||
| 546 | */ | 548 | */ |
| 547 | int (*match_phy_device)(struct phy_device *phydev); | 549 | int (*match_phy_device)(struct phy_device *phydev); |
| 548 | 550 | ||
| 549 | /* Handles ethtool queries for hardware time stamping. */ | ||
| 550 | int (*ts_info)(struct phy_device *phydev, struct ethtool_ts_info *ti); | ||
| 551 | |||
| 552 | /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */ | ||
| 553 | int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); | ||
| 554 | |||
| 555 | /* | ||
| 556 | * Requests a Rx timestamp for 'skb'. If the skb is accepted, | ||
| 557 | * the phy driver promises to deliver it using netif_rx() as | ||
| 558 | * soon as a timestamp becomes available. One of the | ||
| 559 | * PTP_CLASS_ values is passed in 'type'. The function must | ||
| 560 | * return true if the skb is accepted for delivery. | ||
| 561 | */ | ||
| 562 | bool (*rxtstamp)(struct phy_device *dev, struct sk_buff *skb, int type); | ||
| 563 | |||
| 564 | /* | ||
| 565 | * Requests a Tx timestamp for 'skb'. The phy driver promises | ||
| 566 | * to deliver it using skb_complete_tx_timestamp() as soon as a | ||
| 567 | * timestamp becomes available. One of the PTP_CLASS_ values | ||
| 568 | * is passed in 'type'. | ||
| 569 | */ | ||
| 570 | void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type); | ||
| 571 | |||
| 572 | /* Some devices (e.g. qnap TS-119P II) require PHY register changes to | 551 | /* Some devices (e.g. qnap TS-119P II) require PHY register changes to |
| 573 | * enable Wake on LAN, so set_wol is provided to be called in the | 552 | * enable Wake on LAN, so set_wol is provided to be called in the |
| 574 | * ethernet driver's set_wol function. */ | 553 | * ethernet driver's set_wol function. */ |
| @@ -942,7 +921,7 @@ static inline bool phy_polling_mode(struct phy_device *phydev) · 367 unmodified lines | |||
| 942 | */ | 921 | */ |
| 943 | static inline bool phy_has_hwtstamp(struct phy_device *phydev) | 922 | static inline bool phy_has_hwtstamp(struct phy_device *phydev) |
| 944 | { | 923 | { |
| 945 | return phydev && phydev->drv && phydev->drv->hwtstamp; | 924 | return phydev && phydev->mii_ts && phydev->mii_ts->hwtstamp; |
| 946 | } | 925 | } |
| 947 | 926 | ||
| 948 | /** | 927 | /** |
| @@ -951,7 +930,7 @@ static inline bool phy_has_hwtstamp(struct phy_device *phydev) · 2 unmodified lines | |||
| 951 | */ | 930 | */ |
| 952 | static inline bool phy_has_rxtstamp(struct phy_device *phydev) | 931 | static inline bool phy_has_rxtstamp(struct phy_device *phydev) |
| 953 | { | 932 | { |
| 954 | return phydev && phydev->drv && phydev->drv->rxtstamp; | 933 | return phydev && phydev->mii_ts && phydev->mii_ts->rxtstamp; |
| 955 | } | 934 | } |
| 956 | 935 | ||
| 957 | /** | 936 | /** |
| @@ -961,7 +940,7 @@ static inline bool phy_has_rxtstamp(struct phy_device *phydev) · 3 unmodified lines | |||
| 961 | */ | 940 | */ |
| 962 | static inline bool phy_has_tsinfo(struct phy_device *phydev) | 941 | static inline bool phy_has_tsinfo(struct phy_device *phydev) |
| 963 | { | 942 | { |
| 964 | return phydev && phydev->drv && phydev->drv->ts_info; | 943 | return phydev && phydev->mii_ts && phydev->mii_ts->ts_info; |
| 965 | } | 944 | } |
| 966 | 945 | ||
| 967 | /** | 946 | /** |
| @@ -970,30 +949,30 @@ static inline bool phy_has_tsinfo(struct phy_device *phydev) · 2 unmodified lines | |||
| 970 | */ | 949 | */ |
| 971 | static inline bool phy_has_txtstamp(struct phy_device *phydev) | 950 | static inline bool phy_has_txtstamp(struct phy_device *phydev) |
| 972 | { | 951 | { |
| 973 | return phydev && phydev->drv && phydev->drv->txtstamp; | 952 | return phydev && phydev->mii_ts && phydev->mii_ts->txtstamp; |
| 974 | } | 953 | } |
| 975 | 954 | ||
| 976 | static inline int phy_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) | 955 | static inline int phy_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) |
| 977 | { | 956 | { |
| 978 | return phydev->drv->hwtstamp(phydev, ifr); | 957 | return phydev->mii_ts->hwtstamp(phydev->mii_ts, ifr); |
| 979 | } | 958 | } |
| 980 | 959 | ||
| 981 | static inline bool phy_rxtstamp(struct phy_device *phydev, struct sk_buff *skb, | 960 | static inline bool phy_rxtstamp(struct phy_device *phydev, struct sk_buff *skb, |
| 982 | int type) | 961 | int type) |
| 983 | { | 962 | { |
| 984 | return phydev->drv->rxtstamp(phydev, skb, type); | 963 | return phydev->mii_ts->rxtstamp(phydev->mii_ts, skb, type); |
| 985 | } | 964 | } |
| 986 | 965 | ||
| 987 | static inline int phy_ts_info(struct phy_device *phydev, | 966 | static inline int phy_ts_info(struct phy_device *phydev, |
| 988 | struct ethtool_ts_info *tsinfo) | 967 | struct ethtool_ts_info *tsinfo) |
| 989 | { | 968 | { |
| 990 | return phydev->drv->ts_info(phydev, tsinfo); | 969 | return phydev->mii_ts->ts_info(phydev->mii_ts, tsinfo); |
| 991 | } | 970 | } |
| 992 | 971 | ||
| 993 | static inline void phy_txtstamp(struct phy_device *phydev, struct sk_buff *skb, | 972 | static inline void phy_txtstamp(struct phy_device *phydev, struct sk_buff *skb, |
| 994 | int type) | 973 | int type) |
| 995 | { | 974 | { |
| 996 | phydev->drv->txtstamp(phydev, skb, type); | 975 | phydev->mii_ts->txtstamp(phydev->mii_ts, skb, type); |
| 997 | } | 976 | } |
| 998 | 977 | ||
| 999 | /** | 978 | /** |