mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 10:20:17 -04:00
and-xgbe: remove the abstraction for hwptp
Remove the hwptp abstraction and associated callbacks from
the struct xgbe_hw_if {}.
The callback structure was only ever assigned a single function, without
null checks. This cleanup inlines the logic and moves all the hwtstamp
realted code a separate file, improving readability and maintainance.
Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com>
Link: https://patch.msgid.link/20250718185628.4038779-2-Raju.Rangoju@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
ff3fbcdd47
commit
7564d3247a
@@ -3,7 +3,7 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o
|
||||
|
||||
amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \
|
||||
xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \
|
||||
xgbe-ptp.o \
|
||||
xgbe-hwtstamp.o xgbe-ptp.o \
|
||||
xgbe-i2c.o xgbe-phy-v1.o xgbe-phy-v2.o \
|
||||
xgbe-platform.o
|
||||
|
||||
|
||||
@@ -1558,125 +1558,6 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel)
|
||||
DBGPR("<--rx_desc_init\n");
|
||||
}
|
||||
|
||||
static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
|
||||
unsigned int addend)
|
||||
{
|
||||
unsigned int count = 10000;
|
||||
|
||||
/* Set the addend register value and tell the device */
|
||||
XGMAC_IOWRITE(pdata, MAC_TSAR, addend);
|
||||
XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1);
|
||||
|
||||
/* Wait for addend update to complete */
|
||||
while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG))
|
||||
udelay(5);
|
||||
|
||||
if (!count)
|
||||
netdev_err(pdata->netdev,
|
||||
"timed out updating timestamp addend register\n");
|
||||
}
|
||||
|
||||
static void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec,
|
||||
unsigned int nsec)
|
||||
{
|
||||
unsigned int count = 10000;
|
||||
|
||||
/* Set the time values and tell the device */
|
||||
XGMAC_IOWRITE(pdata, MAC_STSUR, sec);
|
||||
XGMAC_IOWRITE(pdata, MAC_STNUR, nsec);
|
||||
XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1);
|
||||
|
||||
/* Wait for time update to complete */
|
||||
while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT))
|
||||
udelay(5);
|
||||
|
||||
if (!count)
|
||||
netdev_err(pdata->netdev, "timed out initializing timestamp\n");
|
||||
}
|
||||
|
||||
static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
u64 nsec;
|
||||
|
||||
nsec = XGMAC_IOREAD(pdata, MAC_STSR);
|
||||
nsec *= NSEC_PER_SEC;
|
||||
nsec += XGMAC_IOREAD(pdata, MAC_STNR);
|
||||
|
||||
return nsec;
|
||||
}
|
||||
|
||||
static u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
unsigned int tx_snr, tx_ssr;
|
||||
u64 nsec;
|
||||
|
||||
if (pdata->vdata->tx_tstamp_workaround) {
|
||||
tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
|
||||
tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR);
|
||||
} else {
|
||||
tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR);
|
||||
tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
|
||||
}
|
||||
|
||||
if (XGMAC_GET_BITS(tx_snr, MAC_TXSNR, TXTSSTSMIS))
|
||||
return 0;
|
||||
|
||||
nsec = tx_ssr;
|
||||
nsec *= NSEC_PER_SEC;
|
||||
nsec += tx_snr;
|
||||
|
||||
return nsec;
|
||||
}
|
||||
|
||||
static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
|
||||
struct xgbe_ring_desc *rdesc)
|
||||
{
|
||||
u64 nsec;
|
||||
|
||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) &&
|
||||
!XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) {
|
||||
nsec = le32_to_cpu(rdesc->desc1);
|
||||
nsec <<= 32;
|
||||
nsec |= le32_to_cpu(rdesc->desc0);
|
||||
if (nsec != 0xffffffffffffffffULL) {
|
||||
packet->rx_tstamp = nsec;
|
||||
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
||||
RX_TSTAMP, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
|
||||
unsigned int mac_tscr)
|
||||
{
|
||||
/* Set one nano-second accuracy */
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
|
||||
|
||||
/* Set fine timestamp update */
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
|
||||
|
||||
/* Overwrite earlier timestamps */
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
|
||||
|
||||
XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr);
|
||||
|
||||
/* Exit if timestamping is not enabled */
|
||||
if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
|
||||
return 0;
|
||||
|
||||
/* Initialize time registers */
|
||||
XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
|
||||
XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
|
||||
xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
|
||||
xgbe_set_tstamp_time(pdata, 0, 0);
|
||||
|
||||
/* Initialize the timecounter */
|
||||
timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
|
||||
ktime_to_ns(ktime_get_real()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
|
||||
struct xgbe_ring *ring)
|
||||
{
|
||||
@@ -3671,13 +3552,6 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
|
||||
hw_if->rx_mmc_int = xgbe_rx_mmc_int;
|
||||
hw_if->read_mmc_stats = xgbe_read_mmc_stats;
|
||||
|
||||
/* For PTP config */
|
||||
hw_if->config_tstamp = xgbe_config_tstamp;
|
||||
hw_if->update_tstamp_addend = xgbe_update_tstamp_addend;
|
||||
hw_if->set_tstamp_time = xgbe_set_tstamp_time;
|
||||
hw_if->get_tstamp_time = xgbe_get_tstamp_time;
|
||||
hw_if->get_tx_tstamp = xgbe_get_tx_tstamp;
|
||||
|
||||
/* For Data Center Bridging config */
|
||||
hw_if->config_tc = xgbe_config_tc;
|
||||
hw_if->config_dcb_tc = xgbe_config_dcb_tc;
|
||||
|
||||
@@ -448,7 +448,7 @@ static void xgbe_isr_bh_work(struct work_struct *work)
|
||||
if (XGMAC_GET_BITS(mac_tssr, MAC_TSSR, TXTSC)) {
|
||||
/* Read Tx Timestamp to clear interrupt */
|
||||
pdata->tx_tstamp =
|
||||
hw_if->get_tx_tstamp(pdata);
|
||||
xgbe_get_tx_tstamp(pdata);
|
||||
queue_work(pdata->dev_workqueue,
|
||||
&pdata->tx_tstamp_work);
|
||||
}
|
||||
@@ -1371,199 +1371,6 @@ static void xgbe_restart(struct work_struct *work)
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static void xgbe_tx_tstamp(struct work_struct *work)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = container_of(work,
|
||||
struct xgbe_prv_data,
|
||||
tx_tstamp_work);
|
||||
struct skb_shared_hwtstamps hwtstamps;
|
||||
u64 nsec;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
if (!pdata->tx_tstamp_skb)
|
||||
goto unlock;
|
||||
|
||||
if (pdata->tx_tstamp) {
|
||||
nsec = timecounter_cyc2time(&pdata->tstamp_tc,
|
||||
pdata->tx_tstamp);
|
||||
|
||||
memset(&hwtstamps, 0, sizeof(hwtstamps));
|
||||
hwtstamps.hwtstamp = ns_to_ktime(nsec);
|
||||
skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps);
|
||||
}
|
||||
|
||||
dev_kfree_skb_any(pdata->tx_tstamp_skb);
|
||||
|
||||
pdata->tx_tstamp_skb = NULL;
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
}
|
||||
|
||||
static int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata,
|
||||
struct ifreq *ifreq)
|
||||
{
|
||||
if (copy_to_user(ifreq->ifr_data, &pdata->tstamp_config,
|
||||
sizeof(pdata->tstamp_config)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata,
|
||||
struct ifreq *ifreq)
|
||||
{
|
||||
struct hwtstamp_config config;
|
||||
unsigned int mac_tscr;
|
||||
|
||||
if (copy_from_user(&config, ifreq->ifr_data, sizeof(config)))
|
||||
return -EFAULT;
|
||||
|
||||
mac_tscr = 0;
|
||||
|
||||
switch (config.tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
break;
|
||||
|
||||
case HWTSTAMP_TX_ON:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (config.rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
break;
|
||||
|
||||
case HWTSTAMP_FILTER_NTP_ALL:
|
||||
case HWTSTAMP_FILTER_ALL:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENALL, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2, UDP, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
fallthrough; /* to PTP v1, UDP, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2, UDP, Sync packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
fallthrough; /* to PTP v1, UDP, Sync packet */
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2, UDP, Delay_req packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
fallthrough; /* to PTP v1, UDP, Delay_req packet */
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* 802.AS1, Ethernet, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* 802.AS1, Ethernet, Sync packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* 802.AS1, Ethernet, Delay_req packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2/802.AS1, any layer, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2/802.AS1, any layer, Sync packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2/802.AS1, any layer, Delay_req packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
pdata->hw_if.config_tstamp(pdata, mac_tscr);
|
||||
|
||||
memcpy(&pdata->tstamp_config, &config, sizeof(config));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata,
|
||||
struct sk_buff *skb,
|
||||
struct xgbe_packet_data *packet)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) {
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
if (pdata->tx_tstamp_skb) {
|
||||
/* Another timestamp in progress, ignore this one */
|
||||
XGMAC_SET_BITS(packet->attributes,
|
||||
TX_PACKET_ATTRIBUTES, PTP, 0);
|
||||
} else {
|
||||
pdata->tx_tstamp_skb = skb_get(skb);
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
}
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
}
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
}
|
||||
|
||||
static void xgbe_prep_vlan(struct sk_buff *skb, struct xgbe_packet_data *packet)
|
||||
{
|
||||
if (skb_vlan_tag_present(skb))
|
||||
|
||||
319
drivers/net/ethernet/amd/xgbe/xgbe-hwtstamp.c
Normal file
319
drivers/net/ethernet/amd/xgbe/xgbe-hwtstamp.c
Normal file
@@ -0,0 +1,319 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
|
||||
/*
|
||||
* Copyright (c) 2014-2025, Advanced Micro Devices, Inc.
|
||||
* Copyright (c) 2014, Synopsys, Inc.
|
||||
* All rights reserved
|
||||
*
|
||||
* Author: Raju Rangoju <Raju.Rangoju@amd.com>
|
||||
*/
|
||||
|
||||
#include "xgbe.h"
|
||||
#include "xgbe-common.h"
|
||||
|
||||
void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
|
||||
unsigned int addend)
|
||||
{
|
||||
unsigned int count = 10000;
|
||||
|
||||
/* Set the addend register value and tell the device */
|
||||
XGMAC_IOWRITE(pdata, MAC_TSAR, addend);
|
||||
XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1);
|
||||
|
||||
/* Wait for addend update to complete */
|
||||
while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG))
|
||||
udelay(5);
|
||||
|
||||
if (!count)
|
||||
netdev_err(pdata->netdev,
|
||||
"timed out updating timestamp addend register\n");
|
||||
}
|
||||
|
||||
void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec,
|
||||
unsigned int nsec)
|
||||
{
|
||||
unsigned int count = 10000;
|
||||
|
||||
/* Set the time values and tell the device */
|
||||
XGMAC_IOWRITE(pdata, MAC_STSUR, sec);
|
||||
XGMAC_IOWRITE(pdata, MAC_STNUR, nsec);
|
||||
XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1);
|
||||
|
||||
/* Wait for time update to complete */
|
||||
while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT))
|
||||
udelay(5);
|
||||
|
||||
if (!count)
|
||||
netdev_err(pdata->netdev, "timed out initializing timestamp\n");
|
||||
}
|
||||
|
||||
u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
u64 nsec;
|
||||
|
||||
nsec = XGMAC_IOREAD(pdata, MAC_STSR);
|
||||
nsec *= NSEC_PER_SEC;
|
||||
nsec += XGMAC_IOREAD(pdata, MAC_STNR);
|
||||
|
||||
return nsec;
|
||||
}
|
||||
|
||||
u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
unsigned int tx_snr, tx_ssr;
|
||||
u64 nsec;
|
||||
|
||||
if (pdata->vdata->tx_tstamp_workaround) {
|
||||
tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
|
||||
tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR);
|
||||
} else {
|
||||
tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR);
|
||||
tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
|
||||
}
|
||||
|
||||
if (XGMAC_GET_BITS(tx_snr, MAC_TXSNR, TXTSSTSMIS))
|
||||
return 0;
|
||||
|
||||
nsec = tx_ssr;
|
||||
nsec *= NSEC_PER_SEC;
|
||||
nsec += tx_snr;
|
||||
|
||||
return nsec;
|
||||
}
|
||||
|
||||
void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
|
||||
struct xgbe_ring_desc *rdesc)
|
||||
{
|
||||
u64 nsec;
|
||||
|
||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) &&
|
||||
!XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) {
|
||||
nsec = le32_to_cpu(rdesc->desc1);
|
||||
nsec <<= 32;
|
||||
nsec |= le32_to_cpu(rdesc->desc0);
|
||||
if (nsec != 0xffffffffffffffffULL) {
|
||||
packet->rx_tstamp = nsec;
|
||||
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
||||
RX_TSTAMP, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int xgbe_config_tstamp(struct xgbe_prv_data *pdata, unsigned int mac_tscr)
|
||||
{
|
||||
/* Set one nano-second accuracy */
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
|
||||
|
||||
/* Set fine timestamp update */
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
|
||||
|
||||
/* Overwrite earlier timestamps */
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
|
||||
|
||||
XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr);
|
||||
|
||||
/* Exit if timestamping is not enabled */
|
||||
if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
|
||||
return 0;
|
||||
|
||||
/* Initialize time registers */
|
||||
XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
|
||||
XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
|
||||
xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
|
||||
xgbe_set_tstamp_time(pdata, 0, 0);
|
||||
|
||||
/* Initialize the timecounter */
|
||||
timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
|
||||
ktime_to_ns(ktime_get_real()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xgbe_tx_tstamp(struct work_struct *work)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = container_of(work,
|
||||
struct xgbe_prv_data,
|
||||
tx_tstamp_work);
|
||||
struct skb_shared_hwtstamps hwtstamps;
|
||||
unsigned long flags;
|
||||
u64 nsec;
|
||||
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
if (!pdata->tx_tstamp_skb)
|
||||
goto unlock;
|
||||
|
||||
if (pdata->tx_tstamp) {
|
||||
nsec = timecounter_cyc2time(&pdata->tstamp_tc,
|
||||
pdata->tx_tstamp);
|
||||
|
||||
memset(&hwtstamps, 0, sizeof(hwtstamps));
|
||||
hwtstamps.hwtstamp = ns_to_ktime(nsec);
|
||||
skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps);
|
||||
}
|
||||
|
||||
dev_kfree_skb_any(pdata->tx_tstamp_skb);
|
||||
|
||||
pdata->tx_tstamp_skb = NULL;
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
}
|
||||
|
||||
int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata, struct ifreq *ifreq)
|
||||
{
|
||||
if (copy_to_user(ifreq->ifr_data, &pdata->tstamp_config,
|
||||
sizeof(pdata->tstamp_config)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, struct ifreq *ifreq)
|
||||
{
|
||||
struct hwtstamp_config config;
|
||||
unsigned int mac_tscr;
|
||||
|
||||
if (copy_from_user(&config, ifreq->ifr_data, sizeof(config)))
|
||||
return -EFAULT;
|
||||
|
||||
mac_tscr = 0;
|
||||
|
||||
switch (config.tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
break;
|
||||
|
||||
case HWTSTAMP_TX_ON:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (config.rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
break;
|
||||
|
||||
case HWTSTAMP_FILTER_NTP_ALL:
|
||||
case HWTSTAMP_FILTER_ALL:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENALL, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2, UDP, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
fallthrough; /* to PTP v1, UDP, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
/* PTP v2, UDP, Sync packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
fallthrough; /* to PTP v1, UDP, Sync packet */
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2, UDP, Delay_req packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
fallthrough; /* to PTP v1, UDP, Delay_req packet */
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* 802.AS1, Ethernet, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* 802.AS1, Ethernet, Sync packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* 802.AS1, Ethernet, Delay_req packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2/802.AS1, any layer, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2/802.AS1, any layer, Sync packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
/* PTP v2/802.AS1, any layer, Delay_req packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
|
||||
XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
xgbe_config_tstamp(pdata, mac_tscr);
|
||||
|
||||
memcpy(&pdata->tstamp_config, &config, sizeof(config));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata,
|
||||
struct sk_buff *skb,
|
||||
struct xgbe_packet_data *packet)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) {
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
if (pdata->tx_tstamp_skb) {
|
||||
/* Another timestamp in progress, ignore this one */
|
||||
XGMAC_SET_BITS(packet->attributes,
|
||||
TX_PACKET_ATTRIBUTES, PTP, 0);
|
||||
} else {
|
||||
pdata->tx_tstamp_skb = skb_get(skb);
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
}
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
}
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
}
|
||||
@@ -20,7 +20,7 @@ static u64 xgbe_cc_read(const struct cyclecounter *cc)
|
||||
tstamp_cc);
|
||||
u64 nsec;
|
||||
|
||||
nsec = pdata->hw_if.get_tstamp_time(pdata);
|
||||
nsec = xgbe_get_tstamp_time(pdata);
|
||||
|
||||
return nsec;
|
||||
}
|
||||
@@ -37,7 +37,7 @@ static int xgbe_adjfine(struct ptp_clock_info *info, long scaled_ppm)
|
||||
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
|
||||
pdata->hw_if.update_tstamp_addend(pdata, addend);
|
||||
xgbe_update_tstamp_addend(pdata, addend);
|
||||
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
|
||||
|
||||
@@ -741,14 +741,6 @@ struct xgbe_hw_if {
|
||||
void (*tx_mmc_int)(struct xgbe_prv_data *);
|
||||
void (*read_mmc_stats)(struct xgbe_prv_data *);
|
||||
|
||||
/* For Timestamp config */
|
||||
int (*config_tstamp)(struct xgbe_prv_data *, unsigned int);
|
||||
void (*update_tstamp_addend)(struct xgbe_prv_data *, unsigned int);
|
||||
void (*set_tstamp_time)(struct xgbe_prv_data *, unsigned int sec,
|
||||
unsigned int nsec);
|
||||
u64 (*get_tstamp_time)(struct xgbe_prv_data *);
|
||||
u64 (*get_tx_tstamp)(struct xgbe_prv_data *);
|
||||
|
||||
/* For Data Center Bridging config */
|
||||
void (*config_tc)(struct xgbe_prv_data *);
|
||||
void (*config_dcb_tc)(struct xgbe_prv_data *);
|
||||
@@ -1277,6 +1269,28 @@ void xgbe_init_tx_coalesce(struct xgbe_prv_data *);
|
||||
void xgbe_restart_dev(struct xgbe_prv_data *pdata);
|
||||
void xgbe_full_restart_dev(struct xgbe_prv_data *pdata);
|
||||
|
||||
/* For Timestamp config */
|
||||
int xgbe_config_tstamp(struct xgbe_prv_data *pdata, unsigned int mac_tscr);
|
||||
u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata);
|
||||
u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata);
|
||||
void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
|
||||
struct xgbe_ring_desc *rdesc);
|
||||
void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
|
||||
struct xgbe_ring_desc *rdesc);
|
||||
void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
|
||||
unsigned int addend);
|
||||
void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec,
|
||||
unsigned int nsec);
|
||||
int xgbe_config_tstamp(struct xgbe_prv_data *pdata, unsigned int mac_tscr);
|
||||
void xgbe_tx_tstamp(struct work_struct *work);
|
||||
int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata,
|
||||
struct ifreq *ifreq);
|
||||
int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata,
|
||||
struct ifreq *ifreq);
|
||||
void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata,
|
||||
struct sk_buff *skb,
|
||||
struct xgbe_packet_data *packet);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void xgbe_debugfs_init(struct xgbe_prv_data *);
|
||||
void xgbe_debugfs_exit(struct xgbe_prv_data *);
|
||||
|
||||
Reference in New Issue
Block a user