2010-07-17 12:49:36 +04:00
/*
* PTP 1588 clock support - support for timestamping in PHY devices
*
* Copyright ( C ) 2010 OMICRON electronics GmbH
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/errqueue.h>
# include <linux/phy.h>
# include <linux/ptp_classify.h>
# include <linux/skbuff.h>
2011-07-15 19:47:34 +04:00
# include <linux/export.h>
2010-07-17 12:49:36 +04:00
2010-12-06 23:50:09 +03:00
static unsigned int classify ( const struct sk_buff * skb )
2010-07-17 12:49:36 +04:00
{
2014-03-28 21:58:21 +04:00
if ( likely ( skb - > dev & & skb - > dev - > phydev & &
2010-07-17 12:49:36 +04:00
skb - > dev - > phydev - > drv ) )
2014-03-28 21:58:22 +04:00
return ptp_classify_raw ( skb ) ;
2010-07-17 12:49:36 +04:00
else
return PTP_CLASS_NONE ;
}
void skb_clone_tx_timestamp ( struct sk_buff * skb )
{
struct phy_device * phydev ;
struct sk_buff * clone ;
unsigned int type ;
2014-09-04 21:31:35 +04:00
if ( ! skb - > sk )
2010-07-17 12:49:36 +04:00
return ;
type = classify ( skb ) ;
2014-06-27 13:59:09 +04:00
if ( type = = PTP_CLASS_NONE )
return ;
phydev = skb - > dev - > phydev ;
if ( likely ( phydev - > drv - > txtstamp ) ) {
2014-09-04 21:31:35 +04:00
clone = skb_clone_sk ( skb ) ;
if ( ! clone )
2014-06-27 13:59:09 +04:00
return ;
phydev - > drv - > txtstamp ( phydev , clone , type ) ;
2010-07-17 12:49:36 +04:00
}
}
2011-06-12 06:18:58 +04:00
EXPORT_SYMBOL_GPL ( skb_clone_tx_timestamp ) ;
2010-07-17 12:49:36 +04:00
bool skb_defer_rx_timestamp ( struct sk_buff * skb )
{
struct phy_device * phydev ;
unsigned int type ;
2015-07-09 21:02:52 +03:00
if ( ! skb - > dev | | ! skb - > dev - > phydev | | ! skb - > dev - > phydev - > drv )
return false ;
2010-12-05 21:50:32 +03:00
if ( skb_headroom ( skb ) < ETH_HLEN )
return false ;
2015-07-09 21:02:52 +03:00
2010-12-05 21:50:32 +03:00
__skb_push ( skb , ETH_HLEN ) ;
2010-07-17 12:49:36 +04:00
2015-07-09 21:02:52 +03:00
type = ptp_classify_raw ( skb ) ;
2010-07-17 12:49:36 +04:00
2010-12-05 21:50:32 +03:00
__skb_pull ( skb , ETH_HLEN ) ;
2010-07-17 12:49:36 +04:00
2014-06-27 13:59:09 +04:00
if ( type = = PTP_CLASS_NONE )
return false ;
phydev = skb - > dev - > phydev ;
if ( likely ( phydev - > drv - > rxtstamp ) )
return phydev - > drv - > rxtstamp ( phydev , skb , type ) ;
2010-07-17 12:49:36 +04:00
return false ;
}
2011-06-20 01:51:23 +04:00
EXPORT_SYMBOL_GPL ( skb_defer_rx_timestamp ) ;