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 | 17 | #include <linux/linkmode.h> |
| 18 | 18 | #include <linux/mdio.h> |
| 19 | 19 | #include <linux/mii.h> |
| 20 | +#include <linux/mii_timestamper.h> | |
| 20 | 21 | #include <linux/module.h> |
| 21 | 22 | #include <linux/timer.h> |
| 22 | 23 | #include <linux/workqueue.h> |
| @@ -441,6 +442,7 @@ struct phy_device { · 418 unmodified lines | ||
| 441 | 442 | struct sfp_bus *sfp_bus; |
| 442 | 443 | struct phylink *phylink; |
| 443 | 444 | struct net_device *attached_dev; |
| 445 | + struct mii_timestamper *mii_ts; | |
| 444 | 446 | |
| 445 | 447 | u8 mdix; |
| 446 | 448 | u8 mdix_ctrl; |
| @@ -546,29 +548,6 @@ struct phy_driver { · 99 unmodified lines | ||
| 546 | 548 | */ |
| 547 | 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 | 551 | /* Some devices (e.g. qnap TS-119P II) require PHY register changes to |
| 573 | 552 | * enable Wake on LAN, so set_wol is provided to be called in the |
| 574 | 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 | 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 | 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 | 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 | 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 | 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 | 960 | static inline bool phy_rxtstamp(struct phy_device *phydev, struct sk_buff *skb, |
| 982 | 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 | 966 | static inline int phy_ts_info(struct phy_device *phydev, |
| 988 | 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 | 972 | static inline void phy_txtstamp(struct phy_device *phydev, struct sk_buff *skb, |
| 994 | 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 | /** |