r8126: Add r8126 driver version 10.013.00-NAPI-PTP

Add support for r8126 ethernet driverversion 10.013.00-NAPI-PTP
which adds support for PTP and supports till K6.9

Bug 4478230

Change-Id: I381d3689a188e5d365ff89092a98023eeaa2a095
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3158780
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
This commit is contained in:
Revanth Kumar Uppala
2024-06-05 12:10:04 +00:00
committed by mobile promotions
parent 36b50b7f27
commit cb5d91e562
11 changed files with 1891 additions and 661 deletions

View File

@@ -29,14 +29,6 @@
# This product is covered by one or more of the following patents: # This product is covered by one or more of the following patents:
# US6,570,884, US6,115,776, and US6,327,625. # US6,570,884, US6,115,776, and US6,327,625.
################################################################################ ################################################################################
LINUX_VERSION := $(shell expr $(VERSION) \* 256 + $(PATCHLEVEL))
LINUX_VERSION_6_9 := $(shell expr 6 \* 256 + 9)
# Use dummy R8126 driver for K69 and later
ifeq ($(shell test $(LINUX_VERSION) -ge $(LINUX_VERSION_6_9); echo $$?),0)
obj-m := r8126.o
r8126-objs := r8126_dummy.o
else
CONFIG_SOC_LAN = n CONFIG_SOC_LAN = n
ENABLE_REALWOW_SUPPORT = n ENABLE_REALWOW_SUPPORT = n
@@ -50,7 +42,7 @@ ENABLE_EEE = y
ENABLE_S0_MAGIC_PACKET = n ENABLE_S0_MAGIC_PACKET = n
ENABLE_TX_NO_CLOSE = y ENABLE_TX_NO_CLOSE = y
ENABLE_MULTIPLE_TX_QUEUE = y ENABLE_MULTIPLE_TX_QUEUE = y
ENABLE_PTP_SUPPORT = n ENABLE_PTP_SUPPORT = y
ENABLE_PTP_MASTER_MODE = n ENABLE_PTP_MASTER_MODE = n
ENABLE_RSS_SUPPORT = n ENABLE_RSS_SUPPORT = n
ENABLE_LIB_SUPPORT = n ENABLE_LIB_SUPPORT = n
@@ -63,7 +55,6 @@ ENABLE_RX_PACKET_FRAGMENT = n
obj-m := r8126.o obj-m := r8126.o
r8126-objs := r8126_n.o rtl_eeprom.o rtltool.o r8126-objs := r8126_n.o rtl_eeprom.o rtltool.o
ifeq ($(CONFIG_SOC_LAN), y) ifeq ($(CONFIG_SOC_LAN), y)
EXTRA_CFLAGS += -DCONFIG_SOC_LAN EXTRA_CFLAGS += -DCONFIG_SOC_LAN
endif endif
@@ -139,5 +130,3 @@ endif
ifeq ($(ENABLE_RX_PACKET_FRAGMENT), y) ifeq ($(ENABLE_RX_PACKET_FRAGMENT), y)
EXTRA_CFLAGS += -DENABLE_RX_PACKET_FRAGMENT EXTRA_CFLAGS += -DENABLE_RX_PACKET_FRAGMENT
endif endif
endif

View File

@@ -41,7 +41,9 @@
#include <linux/version.h> #include <linux/version.h>
#include "r8126_dash.h" #include "r8126_dash.h"
#include "r8126_realwow.h" #include "r8126_realwow.h"
#ifdef ENABLE_PTP_SUPPORT
#include "r8126_ptp.h" #include "r8126_ptp.h"
#endif
#include "r8126_rss.h" #include "r8126_rss.h"
#ifdef ENABLE_LIB_SUPPORT #ifdef ENABLE_LIB_SUPPORT
#include "r8126_lib.h" #include "r8126_lib.h"
@@ -51,8 +53,105 @@
#define fallthrough #define fallthrough
#endif #endif
int rtl8126_enable_msix(struct rtl8126_private *tp);
void netdev_sw_irq_coalesce_default_on(struct net_device *dev); void netdev_sw_irq_coalesce_default_on(struct net_device *dev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
#define netif_xmit_stopped netif_tx_queue_stopped
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
#ifndef MDIO_AN_EEE_ADV_100TX
#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */
#endif
#ifndef MDIO_AN_EEE_ADV_1000T
#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
#define MDIO_EEE_100TX MDIO_AN_EEE_ADV_100TX /* 100TX EEE cap */
#define MDIO_EEE_1000T MDIO_AN_EEE_ADV_1000T /* 1000T EEE cap */
#define MDIO_EEE_10GT 0x0008 /* 10GT EEE cap */
#define MDIO_EEE_1000KX 0x0010 /* 1000KX EEE cap */
#define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */
#define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */
static inline u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv)
{
u32 adv = 0;
if (eee_adv & MDIO_EEE_100TX)
adv |= ADVERTISED_100baseT_Full;
if (eee_adv & MDIO_EEE_1000T)
adv |= ADVERTISED_1000baseT_Full;
if (eee_adv & MDIO_EEE_10GT)
adv |= ADVERTISED_10000baseT_Full;
if (eee_adv & MDIO_EEE_1000KX)
adv |= ADVERTISED_1000baseKX_Full;
if (eee_adv & MDIO_EEE_10GKX4)
adv |= ADVERTISED_10000baseKX4_Full;
if (eee_adv & MDIO_EEE_10GKR)
adv |= ADVERTISED_10000baseKR_Full;
return adv;
}
static inline u16 ethtool_adv_to_mmd_eee_adv_t(u32 adv)
{
u16 reg = 0;
if (adv & ADVERTISED_100baseT_Full)
reg |= MDIO_EEE_100TX;
if (adv & ADVERTISED_1000baseT_Full)
reg |= MDIO_EEE_1000T;
if (adv & ADVERTISED_10000baseT_Full)
reg |= MDIO_EEE_10GT;
if (adv & ADVERTISED_1000baseKX_Full)
reg |= MDIO_EEE_1000KX;
if (adv & ADVERTISED_10000baseKX4_Full)
reg |= MDIO_EEE_10GKX4;
if (adv & ADVERTISED_10000baseKR_Full)
reg |= MDIO_EEE_10GKR;
return reg;
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
{
return skb->transport_header != ~0U;
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
static inline void linkmode_set_bit(int nr, volatile unsigned long *addr)
{
__set_bit(nr, addr);
}
static inline void linkmode_clear_bit(int nr, volatile unsigned long *addr)
{
__clear_bit(nr, addr);
}
static inline int linkmode_test_bit(int nr, volatile unsigned long *addr)
{
return test_bit(nr, addr);
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
static inline void linkmode_mod_bit(int nr, volatile unsigned long *addr,
int set)
{
if (set)
linkmode_set_bit(nr, addr);
else
linkmode_clear_bit(nr, addr);
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)
static inline static inline
ssize_t strscpy(char *dest, const char *src, size_t count) ssize_t strscpy(char *dest, const char *src, size_t count)
@@ -117,6 +216,16 @@ typedef int netdev_tx_t;
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,9)
static inline bool page_is_pfmemalloc(struct page *page)
{
/*
* Page index cannot be this large so this must be
* a pfmemalloc page.
*/
return page->index == -1UL;
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,1,9) */
static inline bool dev_page_is_reusable(struct page *page) static inline bool dev_page_is_reusable(struct page *page)
{ {
return likely(page_to_nid(page) == numa_mem_id() && return likely(page_to_nid(page) == numa_mem_id() &&
@@ -275,7 +384,7 @@ do { \
#define ENABLE_R8126_PROCFS #define ENABLE_R8126_PROCFS
#endif #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
#define ENABLE_R8126_SYSFS #define ENABLE_R8126_SYSFS
#endif #endif
@@ -394,6 +503,23 @@ do { \
#define MDIO_EEE_5GT 0x0002 #define MDIO_EEE_5GT 0x0002
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,9,0)
#define ethtool_keee ethtool_eee
#define rtl8126_ethtool_adv_to_mmd_eee_adv_cap1_t ethtool_adv_to_mmd_eee_adv_t
static inline u32 rtl8126_ethtool_adv_to_mmd_eee_adv_cap2_t(u32 adv)
{
u32 result = 0;
if (adv & SUPPORTED_2500baseX_Full)
result |= MDIO_EEE_2_5GT;
return result;
}
#else
#define rtl8126_ethtool_adv_to_mmd_eee_adv_cap1_t linkmode_to_mii_eee_cap1_t
#define rtl8126_ethtool_adv_to_mmd_eee_adv_cap2_t linkmode_to_mii_eee_cap2_t
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,9,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8126_netpoll #define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8126_netpoll
@@ -490,7 +616,7 @@ This is free software, and you are welcome to redistribute it under certain cond
#ifdef RTL8126_DEBUG #ifdef RTL8126_DEBUG
#define assert(expr) \ #define assert(expr) \
if(!(expr)) { \ if(!(expr)) { \
printk( "Assertion failed! %s,%s,%s,line=%d\n", \ printk("Assertion failed! %s,%s,%s,line=%d\n", \
#expr,__FILE__,__FUNCTION__,__LINE__); \ #expr,__FILE__,__FUNCTION__,__LINE__); \
} }
#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) #define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0)
@@ -677,10 +803,15 @@ This is free software, and you are welcome to redistribute it under certain cond
#define ADVERTISE_1000HALF 0x100 #define ADVERTISE_1000HALF 0x100
#endif #endif
#ifndef BIT_ULL
#define BIT_ULL(nr) (1ULL << (nr))
#endif
#ifndef ADVERTISED_2500baseX_Full #ifndef ADVERTISED_2500baseX_Full
#define ADVERTISED_2500baseX_Full 0x8000 #define ADVERTISED_2500baseX_Full 0x8000
#endif #endif
#define RTK_ADVERTISED_5000baseX_Full BIT(48) #define RTK_ADVERTISED_5000baseX_Full BIT_ULL(48)
#define RTK_SUPPORTED_5000baseX_Full BIT_ULL(48)
#define RTK_ADVERTISE_2500FULL 0x80 #define RTK_ADVERTISE_2500FULL 0x80
#define RTK_ADVERTISE_5000FULL 0x100 #define RTK_ADVERTISE_5000FULL 0x100
@@ -728,9 +859,9 @@ This is free software, and you are welcome to redistribute it under certain cond
/*****************************************************************************/ /*****************************************************************************/
//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) //#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ #if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27)) || \
(( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && \
( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3))))
/* copied from linux kernel 2.6.20 include/linux/netdev.h */ /* copied from linux kernel 2.6.20 include/linux/netdev.h */
#define NETDEV_ALIGN 32 #define NETDEV_ALIGN 32
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) #define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)
@@ -866,7 +997,7 @@ extern void __chk_io_ptr(void __iomem *);
/*****************************************************************************/ /*****************************************************************************/
/* 2.5.28 => 2.4.23 */ /* 2.5.28 => 2.4.23 */
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28))
static inline void _kc_synchronize_irq(void) static inline void _kc_synchronize_irq(void)
{ {
@@ -887,12 +1018,12 @@ static inline void _kc_synchronize_irq(void)
/*****************************************************************************/ /*****************************************************************************/
/* 2.6.4 => 2.6.0 */ /* 2.6.4 => 2.6.0 */
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4))
#define MODULE_VERSION(_version) MODULE_INFO(version, _version) #define MODULE_VERSION(_version) MODULE_INFO(version, _version)
#endif /* 2.6.4 => 2.6.0 */ #endif /* 2.6.4 => 2.6.0 */
/*****************************************************************************/ /*****************************************************************************/
/* 2.6.0 => 2.5.28 */ /* 2.6.0 => 2.5.28 */
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
#define MODULE_INFO(version, _version) #define MODULE_INFO(version, _version)
#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 #define CONFIG_E1000_DISABLE_PACKET_SPLIT 1
@@ -923,13 +1054,13 @@ static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr)
/*****************************************************************************/ /*****************************************************************************/
/* 2.4.22 => 2.4.17 */ /* 2.4.22 => 2.4.17 */
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22))
#define pci_name(x) ((x)->slot_name) #define pci_name(x) ((x)->slot_name)
#endif /* 2.4.22 => 2.4.17 */ #endif /* 2.4.22 => 2.4.17 */
/*****************************************************************************/ /*****************************************************************************/
/* 2.6.5 => 2.6.0 */ /* 2.6.5 => 2.6.0 */
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5))
#define pci_dma_sync_single_for_cpu pci_dma_sync_single #define pci_dma_sync_single_for_cpu pci_dma_sync_single
#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu #define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu
#endif /* 2.6.5 => 2.6.0 */ #endif /* 2.6.5 => 2.6.0 */
@@ -1413,6 +1544,26 @@ enum RTL8126_registers {
PPS_RISE_TIME_S_8125 = 0x68A4, PPS_RISE_TIME_S_8125 = 0x68A4,
PTP_EGRESS_TIME_BASE_NS_8125 = 0XCF20, PTP_EGRESS_TIME_BASE_NS_8125 = 0XCF20,
PTP_EGRESS_TIME_BASE_S_8125 = 0XCF24, PTP_EGRESS_TIME_BASE_S_8125 = 0XCF24,
PTP_CTL = 0xE400,
PTP_INER = 0xE402,
PTP_INSR = 0xE404,
PTP_SYNCE_CTL = 0xE406,
PTP_GEN_CFG = 0xE408,
PTP_CLK_CFG_8126 = 0xE410,
PTP_CFG_NS_LO_8126 = 0xE412,
PTP_CFG_NS_HI_8126 = 0xE414,
PTP_CFG_S_LO_8126 = 0xE416,
PTP_CFG_S_MI_8126 = 0xE418,
PTP_CFG_S_HI_8126 = 0xE41A,
PTP_TAI_CFG = 0xE420,
PTP_TAI_TS_S_LO = 0xE42A,
PTP_TAI_TS_S_HI = 0xE42C,
PTP_TRX_TS_STA = 0xE430,
PTP_TRX_TS_NS_LO = 0xE446,
PTP_TRX_TS_NS_HI = 0xE448,
PTP_TRX_TS_S_LO = 0xE44A,
PTP_TRX_TS_S_MI = 0xE44C,
PTP_TRX_TS_S_HI = 0xE44E,
//TCAM //TCAM
TCAM_NOTVALID_ADDR = 0xA000, TCAM_NOTVALID_ADDR = 0xA000,
@@ -1453,6 +1604,10 @@ enum RTL8126_register_content {
RxRUNT_V3 = (1 << 19), RxRUNT_V3 = (1 << 19),
RxCRC_V3 = (1 << 17), RxCRC_V3 = (1 << 17),
RxRES_V4 = (1 << 22),
RxRUNT_V4 = (1 << 21),
RxCRC_V4 = (1 << 20),
/* ChipCmdBits */ /* ChipCmdBits */
StopReq = 0x80, StopReq = 0x80,
CmdReset = 0x10, CmdReset = 0x10,
@@ -1487,6 +1642,7 @@ enum RTL8126_register_content {
Reserved2_shift = 13, Reserved2_shift = 13,
RxCfgDMAShift = 8, RxCfgDMAShift = 8,
EnableRxDescV3 = (1 << 24), EnableRxDescV3 = (1 << 24),
EnableRxDescV4_1 = (1 << 24),
EnableOuterVlan = (1 << 23), EnableOuterVlan = (1 << 23),
EnableInnerVlan = (1 << 22), EnableInnerVlan = (1 << 22),
RxCfg_128_int_en = (1 << 15), RxCfg_128_int_en = (1 << 15),
@@ -1692,6 +1848,11 @@ enum _DescStatusBit {
FirstFrag_V3 = (1 << 25), /* First segment of a packet */ FirstFrag_V3 = (1 << 25), /* First segment of a packet */
LastFrag_V3 = (1 << 24), /* Final segment of a packet */ LastFrag_V3 = (1 << 24), /* Final segment of a packet */
DescOwn_V4 = (DescOwn), /* Descriptor is owned by NIC */
RingEnd_V4 = (RingEnd), /* End of descriptor ring */
FirstFrag_V4 = (FirstFrag), /* First segment of a packet */
LastFrag_V4 = (LastFrag), /* Final segment of a packet */
/* Tx private */ /* Tx private */
/*------ offset 0 of tx descriptor ------*/ /*------ offset 0 of tx descriptor ------*/
LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
@@ -1750,7 +1911,7 @@ enum _DescStatusBit {
RxIPF_v3 = (1 << 26), /* IP checksum failed */ RxIPF_v3 = (1 << 26), /* IP checksum failed */
RxUDPF_v3 = (1 << 25), /* UDP/IP checksum failed */ RxUDPF_v3 = (1 << 25), /* UDP/IP checksum failed */
RxTCPF_v3 = (1 << 24), /* TCP/IP checksum failed */ RxTCPF_v3 = (1 << 24), /* TCP/IP checksum failed */
RxSCTPF_v3 = (1 << 23), /* TCP/IP checksum failed */ RxSCTPF_v3 = (1 << 23), /* SCTP checksum failed */
RxVlanTag_v3 = (RxVlanTag), /* VLAN tag available */ RxVlanTag_v3 = (RxVlanTag), /* VLAN tag available */
/*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/
@@ -1763,6 +1924,23 @@ enum _DescStatusBit {
RxV6F_v3 = (RxV6F), RxV6F_v3 = (RxV6F),
RxV4F_v3 = (RxV4F), RxV4F_v3 = (RxV4F),
/*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/
RxIPF_v4 = (1 << 17), /* IP checksum failed */
RxUDPF_v4 = (1 << 16), /* UDP/IP checksum failed */
RxTCPF_v4 = (1 << 15), /* TCP/IP checksum failed */
RxSCTPF_v4 = (1 << 19), /* SCTP checksum failed */
RxVlanTag_v4 = (RxVlanTag), /* VLAN tag available */
/*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/
RxUDPT_v4 = (1 << 19),
RxTCPT_v4 = (1 << 18),
RxSCTP_v4 = (1 << 19),
/*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/
/*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/
RxV6F_v4 = (RxV6F),
RxV4F_v4 = (RxV4F),
/*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/
}; };
enum features { enum features {
@@ -1831,6 +2009,7 @@ enum efuse {
}; };
#define RsvdMask 0x3fffc000 #define RsvdMask 0x3fffc000
#define RsvdMaskV3 0x3fff8000 #define RsvdMaskV3 0x3fff8000
#define RsvdMaskV4 RsvdMaskV3
struct TxDesc { struct TxDesc {
u32 opts1; u32 opts1;
@@ -1897,6 +2076,22 @@ struct RxDescV3 {
}; };
}; };
struct RxDescV4 {
union {
u64 addr;
struct {
u32 RSSInfo;
u32 RSSResult;
} RxDescNormalDDWord1;
};
struct {
u32 opts2;
u32 opts1;
} RxDescNormalDDWord2;
};
enum rxdesc_type { enum rxdesc_type {
RXDESC_TYPE_NORMAL=0, RXDESC_TYPE_NORMAL=0,
RXDESC_TYPE_NEXT, RXDESC_TYPE_NEXT,
@@ -1916,7 +2111,8 @@ enum rx_desc_ring_type {
enum rx_desc_len { enum rx_desc_len {
RX_DESC_LEN_TYPE_1 = (sizeof(struct RxDesc)), RX_DESC_LEN_TYPE_1 = (sizeof(struct RxDesc)),
RX_DESC_LEN_TYPE_3 = (sizeof(struct RxDescV3)) RX_DESC_LEN_TYPE_3 = (sizeof(struct RxDescV3)),
RX_DESC_LEN_TYPE_4 = (sizeof(struct RxDescV4))
}; };
struct ring_info { struct ring_info {
@@ -2247,6 +2443,22 @@ enum rtl8126_state_t {
__RTL8126_PTP_TX_IN_PROGRESS, __RTL8126_PTP_TX_IN_PROGRESS,
}; };
#define RTL_FLAG_RX_HWTSTAMP_ENABLED BIT_0
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
struct ethtool_eee {
__u32 cmd;
__u32 supported;
__u32 advertised;
__u32 lp_advertised;
__u32 eee_active;
__u32 eee_enabled;
__u32 tx_lpi_enabled;
__u32 tx_lpi_timer;
__u32 reserved[2];
};
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */
struct rtl8126_private { struct rtl8126_private {
void __iomem *mmio_addr; /* memory map physical address */ void __iomem *mmio_addr; /* memory map physical address */
struct pci_dev *pci_dev; /* Index of PCI device */ struct pci_dev *pci_dev; /* Index of PCI device */
@@ -2260,6 +2472,7 @@ struct rtl8126_private {
//struct msix_entry msix_entries[R8126_MAX_MSIX_VEC]; //struct msix_entry msix_entries[R8126_MAX_MSIX_VEC];
struct net_device_stats stats; /* statistics of net device */ struct net_device_stats stats; /* statistics of net device */
unsigned long state; unsigned long state;
u32 flags;
u32 msg_enable; u32 msg_enable;
u32 tx_tcp_csum_cmd; u32 tx_tcp_csum_cmd;
@@ -2523,7 +2736,7 @@ struct rtl8126_private {
//Realwow-------------- //Realwow--------------
#endif //ENABLE_REALWOW_SUPPORT #endif //ENABLE_REALWOW_SUPPORT
struct ethtool_eee eee; struct ethtool_keee eee;
#ifdef ENABLE_R8126_PROCFS #ifdef ENABLE_R8126_PROCFS
//Procfs support //Procfs support
@@ -2536,9 +2749,12 @@ struct rtl8126_private {
DECLARE_BITMAP(sysfs_flag, R8126_SYSFS_FLAG_MAX); DECLARE_BITMAP(sysfs_flag, R8126_SYSFS_FLAG_MAX);
u32 testmode; u32 testmode;
#endif #endif
u8 HwSuppRxDescType;
u8 InitRxDescType; u8 InitRxDescType;
u16 RxDescLength; //V1 16 Byte V2 32 Bytes u16 RxDescLength; //V1 16 Byte V2 32 Bytes
spinlock_t phy_lock;
u8 HwSuppPtpVer; u8 HwSuppPtpVer;
u8 EnablePtp; u8 EnablePtp;
u8 ptp_master_mode; u8 ptp_master_mode;
@@ -2551,6 +2767,9 @@ struct rtl8126_private {
unsigned long ptp_tx_start; unsigned long ptp_tx_start;
struct ptp_clock_info ptp_clock_info; struct ptp_clock_info ptp_clock_info;
struct ptp_clock *ptp_clock; struct ptp_clock *ptp_clock;
u8 syncE_en;
u8 pps_enable;
struct hrtimer pps_timer;
#endif #endif
u8 HwSuppRssVer; u8 HwSuppRssVer;
@@ -2674,7 +2893,7 @@ enum mcfg {
//Ram Code Version //Ram Code Version
#define NIC_RAMCODE_VERSION_CFG_METHOD_1 (0x0023) #define NIC_RAMCODE_VERSION_CFG_METHOD_1 (0x0023)
#define NIC_RAMCODE_VERSION_CFG_METHOD_2 (0x0033) #define NIC_RAMCODE_VERSION_CFG_METHOD_2 (0x0033)
#define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0048) #define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0051)
//hwoptimize //hwoptimize
#define HW_PATCH_SOC_LAN (BIT_0) #define HW_PATCH_SOC_LAN (BIT_0)
@@ -2715,17 +2934,25 @@ void rtl8126_dash2_disable_rx(struct rtl8126_private *tp);
void rtl8126_dash2_enable_rx(struct rtl8126_private *tp); void rtl8126_dash2_enable_rx(struct rtl8126_private *tp);
void rtl8126_hw_disable_mac_mcu_bps(struct net_device *dev); void rtl8126_hw_disable_mac_mcu_bps(struct net_device *dev);
void rtl8126_mark_to_asic(struct rtl8126_private *tp, struct RxDesc *desc, u32 rx_buf_sz); void rtl8126_mark_to_asic(struct rtl8126_private *tp, struct RxDesc *desc, u32 rx_buf_sz);
void rtl8126_mark_as_last_descriptor(struct rtl8126_private *tp, struct RxDesc *desc);
static inline void static inline void
rtl8126_make_unusable_by_asic(struct rtl8126_private *tp, rtl8126_make_unusable_by_asic(struct rtl8126_private *tp,
struct RxDesc *desc) struct RxDesc *desc)
{ {
if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { switch (tp->InitRxDescType) {
case RX_DESC_RING_TYPE_3:
((struct RxDescV3 *)desc)->addr = RTL8126_MAGIC_NUMBER; ((struct RxDescV3 *)desc)->addr = RTL8126_MAGIC_NUMBER;
((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1 &= ~cpu_to_le32(DescOwn | RsvdMaskV3); ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1 &= ~cpu_to_le32(DescOwn | RsvdMaskV3);
} else { break;
case RX_DESC_RING_TYPE_4:
((struct RxDescV4 *)desc)->addr = RTL8126_MAGIC_NUMBER;
((struct RxDescV4 *)desc)->RxDescNormalDDWord2.opts1 &= ~cpu_to_le32(DescOwn | RsvdMaskV4);
break;
default:
desc->addr = RTL8126_MAGIC_NUMBER; desc->addr = RTL8126_MAGIC_NUMBER;
desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
break;
} }
} }
@@ -2766,12 +2993,20 @@ int rtl8126_dump_tally_counter(struct rtl8126_private *tp, dma_addr_t paddr);
void rtl8126_enable_napi(struct rtl8126_private *tp); void rtl8126_enable_napi(struct rtl8126_private *tp);
void _rtl8126_wait_for_quiescence(struct net_device *dev); void _rtl8126_wait_for_quiescence(struct net_device *dev);
void rtl8126_mdio_direct_write_phy_ocp(struct rtl8126_private *tp, u16 RegAddr,u16 value);
u32 rtl8126_mdio_direct_read_phy_ocp(struct rtl8126_private *tp, u16 RegAddr);
void rtl8126_clear_and_set_eth_phy_ocp_bit(struct rtl8126_private *tp, u16 addr, u16 clearmask, u16 setmask);
void rtl8126_clear_eth_phy_ocp_bit(struct rtl8126_private *tp, u16 addr, u16 mask);
void rtl8126_set_eth_phy_ocp_bit(struct rtl8126_private *tp, u16 addr, u16 mask);
void rtl8126_clear_mac_ocp_bit(struct rtl8126_private *tp, u16 addr, u16 mask);
#ifndef ENABLE_LIB_SUPPORT #ifndef ENABLE_LIB_SUPPORT
static inline void rtl8126_lib_reset_prepare(struct rtl8126_private *tp) { } static inline void rtl8126_lib_reset_prepare(struct rtl8126_private *tp) { }
static inline void rtl8126_lib_reset_complete(struct rtl8126_private *tp) { } static inline void rtl8126_lib_reset_complete(struct rtl8126_private *tp) { }
#endif #endif
#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 ) #define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0)
#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0) #define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0)
#define HW_SUPPORT_D0_SPEED_UP(_M) ((_M)->HwSuppD0SpeedUpVer > 0) #define HW_SUPPORT_D0_SPEED_UP(_M) ((_M)->HwSuppD0SpeedUpVer > 0)
#define HW_SUPPORT_MAC_MCU(_M) ((_M)->HwSuppMacMcuVer > 0) #define HW_SUPPORT_MAC_MCU(_M) ((_M)->HwSuppMacMcuVer > 0)

View File

@@ -175,10 +175,10 @@ RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2;
#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8 #define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8
#define OCP_REG_CONFIG0_TLSEN BIT_7 #define OCP_REG_CONFIG0_TLSEN BIT_7
#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0 ) #define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0)
#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1 ) #define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1)
#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2 ) #define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2)
#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3 ) #define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3)
#define RECV_FROM_FW_BUF_SIZE (1520) #define RECV_FROM_FW_BUF_SIZE (1520)
#define SEND_TO_FW_BUF_SIZE (1520) #define SEND_TO_FW_BUF_SIZE (1520)

View File

@@ -1,15 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/module.h>
/* Dummy implementation for module */
static int __init r8126_dummy_dummy_init(void)
{
return 0;
}
device_initcall(r8126_dummy_dummy_init);
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
MODULE_DESCRIPTION("Dummy R8126 dummy driver");
MODULE_LICENSE("GPL");

View File

File diff suppressed because it is too large Load Diff

View File

@@ -45,57 +45,90 @@
#include "r8126.h" #include "r8126.h"
#include "r8126_ptp.h" #include "r8126_ptp.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) static void rtl8126_wait_clkadj_ready(struct rtl8126_private *tp)
static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
{ {
return *(const struct timespec *)&ts64; int i;
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++)
if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CLK_CFG_8126) & CLKADJ_MODE_SET))
break;
} }
static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) static void rtl8126_set_clkadj_mode(struct rtl8126_private *tp, u16 cmd)
{ {
return *(const struct timespec64 *)&ts; rtl8126_clear_and_set_eth_phy_ocp_bit(tp,
PTP_CLK_CFG_8126,
BIT_3 | BIT_2 | BIT_1,
CLKADJ_MODE_SET | cmd);
rtl8126_wait_clkadj_ready(tp);
} }
#endif
static int _rtl8126_phc_gettime(struct rtl8126_private *tp, struct timespec64 *ts64) static int _rtl8126_phc_gettime(struct rtl8126_private *tp, struct timespec64 *ts64)
{ {
//get local time unsigned long flags;
RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_LATCHED_LOCAL_TIME | PTP_EXEC_CMD));
spin_lock_irqsave(&tp->phy_lock, flags);
//Direct Read
rtl8126_set_clkadj_mode(tp, DIRECT_READ);
/* nanoseconds */ /* nanoseconds */
//0x6808[29:0] //Ns[29:16] E414[13:0]
ts64->tv_nsec = (RTL_R32(tp, PTP_SOFT_CONFIG_Time_NS_8125) & 0x3fffffff); ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_NS_HI_8126) & 0x3fff;
ts64->tv_nsec <<= 16;
//Ns[15:0] E412[15:0]
ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_NS_LO_8126);
/* seconds */ /* seconds */
//0x680C[47:0] //S[47:32] E41A[15:0]
ts64->tv_sec = RTL_R16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4); ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_HI_8126);
ts64->tv_sec <<= 32; ts64->tv_sec <<= 16;
ts64->tv_sec |= RTL_R32(tp, PTP_SOFT_CONFIG_Time_S_8125); //S[31:16] E418[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_MI_8126);
ts64->tv_sec <<= 16;
//S[15:0] E416[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_LO_8126);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0; return 0;
} }
static int _rtl8126_phc_settime(struct rtl8126_private *tp, const struct timespec64 *ts64) static int _rtl8126_phc_settime(struct rtl8126_private *tp, const struct timespec64 *ts64)
{ {
unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags);
/* nanoseconds */ /* nanoseconds */
//0x6808[29:0] //Ns[15:0] E412[15:0]
RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, (ts64->tv_nsec & 0x3fffffff)); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, ts64->tv_nsec);
//Ns[29:16] E414[13:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (ts64->tv_nsec & 0x3fff0000) >> 16);
/* seconds */ /* seconds */
//0x680C[47:0] //S[15:0] E416[15:0]
RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, ts64->tv_sec); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_LO_8126, ts64->tv_sec);
RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (ts64->tv_sec >> 32)); //S[31:16] E418[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_MI_8126, (ts64->tv_sec >> 16));
//S[47:32] E41A[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_HI_8126, (ts64->tv_sec >> 32));
//set local time //Direct Write
RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); rtl8126_set_clkadj_mode(tp, DIRECT_WRITE);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0; return 0;
} }
static int _rtl8126_phc_adjtime(struct rtl8126_private *tp, s64 delta) static int _rtl8126_phc_adjtime(struct rtl8126_private *tp, s64 delta)
{ {
unsigned long flags;
struct timespec64 d; struct timespec64 d;
bool negative = false; bool negative;
u64 tohw; u64 tohw;
u32 nsec; u32 nsec;
u64 sec; u64 sec;
@@ -104,6 +137,7 @@ static int _rtl8126_phc_adjtime(struct rtl8126_private *tp, s64 delta)
negative = true; negative = true;
tohw = -delta; tohw = -delta;
} else { } else {
negative = false;
tohw = delta; tohw = delta;
} }
@@ -112,31 +146,31 @@ static int _rtl8126_phc_adjtime(struct rtl8126_private *tp, s64 delta)
nsec = d.tv_nsec; nsec = d.tv_nsec;
sec = d.tv_sec; sec = d.tv_sec;
if (negative) {
nsec = -nsec;
sec = -sec;
}
nsec &= 0x3fffffff; nsec &= 0x3fffffff;
sec &= 0x0000ffffffffffff; sec &= 0x0000ffffffffffff;
if (negative) { spin_lock_irqsave(&tp->phy_lock, flags);
nsec |= PTP_SOFT_CONFIG_TIME_NS_NEGATIVE;
sec |= PTP_SOFT_CONFIG_TIME_S_NEGATIVE;
}
/* nanoseconds */ /* nanoseconds */
//0x6808[29:0] //Ns[15:0] E412[15:0]
RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, nsec); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, nsec);
//Ns[29:16] E414[13:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (nsec >> 16));
/* seconds */ /* seconds */
//0x680C[47:0] //S[15:0] E416[15:0]
RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, sec); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_LO_8126, sec);
RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (sec >> 32)); //S[31:16] E418[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_MI_8126, (sec >> 16));
//S[47:32] E41A[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_HI_8126, (sec >> 32));
//adjust local time if (negative)
//RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); rtl8126_set_clkadj_mode(tp, DECREMENT_STEP);
RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); else
rtl8126_set_clkadj_mode(tp, INCREMENT_STEP);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0; return 0;
} }
@@ -148,57 +182,60 @@ static int rtl8126_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
//netif_info(tp, drv, tp->dev, "phc adjust time\n"); //netif_info(tp, drv, tp->dev, "phc adjust time\n");
rtnl_lock();
ret = _rtl8126_phc_adjtime(tp, delta); ret = _rtl8126_phc_adjtime(tp, delta);
rtnl_unlock();
return ret; return ret;
} }
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,2,0)
/* /*
1ppm means every 125MHz plus 125Hz. It also means every 8ns minus 8ns*10^(-6) * delta = delta * 10^6 ppm = delta * 10^9 ppb (in this equation ppm and ppb are not variable)
*
1ns=2^30 sub_ns * in adjfreq ppb is a variable
* ppb = delta * 10^9
8ns*10^(-6) = 8 * 2^30 sub_ns * 10^(-6) = 2^33 sub_ns * 10^(-6) = 8590 = 0x218E sub_ns * delta = ppb / 10^9
* rate_value = |delta| * 2^32 = |ppb| / 10^9 * 2^32 = (|ppb| << 32) / 10^9
1ppb means every 125MHz plus 0.125Hz. It also means every 8ns minus 8ns*10^(-9) */
1ns=2^30 sub_ns
8ns*10^(-9) = 8 * 2^30 sub_ns * 10^(-9) = 2^33 sub_ns * 10^(-9) = 8.59 sub_ns = 9 sub_ns
*/
static int _rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb) static int _rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
{ {
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info); struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
bool negative = false; unsigned long flags;
u32 sub_ns; u32 rate_value;
if (ppb < 0) { if (ppb < 0) {
negative = true; rate_value = ((u64)-ppb << 32) / 1000000000;
ppb = -ppb; rate_value = ~rate_value + 1;
}
sub_ns = ppb * 9;
if (negative) {
sub_ns = -sub_ns;
sub_ns &= 0x3fffffff;
sub_ns |= PTP_ADJUST_TIME_NS_NEGATIVE;
} else } else
sub_ns &= 0x3fffffff; rate_value = ((u64)ppb << 32) / 1000000000;
spin_lock_irqsave(&tp->phy_lock, flags);
/* nanoseconds */ /* nanoseconds */
//0x6808[29:0] //Ns[15:0] E412[15:0]
RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, sub_ns); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, rate_value);
//Ns[22:16] E414[13:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (rate_value & 0x003f0000) >> 16);
//adjust local time rtl8126_set_clkadj_mode(tp, RATE_WRITE);
RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD));
//RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0; return 0;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
static int rtl8126_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
if (ppb > ptp->max_adj || ppb < -ptp->max_adj)
return -EINVAL;
_rtl8126_phc_adjfreq(ptp, ppb);
return 0;
}
#else
static int rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) static int rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
{ {
//struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info); //struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
@@ -212,8 +249,24 @@ static int rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
return 0; return 0;
} }
#endif //LINUX_VERSION_CODE < KERNEL_VERSION(6,2,0) #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
static int rtl8126_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64,
struct ptp_system_timestamp *sts)
{
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
int ret;
//netif_info(tp, drv, tp->dev, "phc get ts\n");
ptp_read_system_prets(sts);
ret = _rtl8126_phc_gettime(tp, ts64);
ptp_read_system_postts(sts);
return ret;
}
#else
static int rtl8126_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64) static int rtl8126_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64)
{ {
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info); struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
@@ -221,12 +274,11 @@ static int rtl8126_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts
//netif_info(tp, drv, tp->dev, "phc get ts\n"); //netif_info(tp, drv, tp->dev, "phc get ts\n");
rtnl_lock();
ret = _rtl8126_phc_gettime(tp, ts64); ret = _rtl8126_phc_gettime(tp, ts64);
rtnl_unlock();
return ret; return ret;
} }
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) */
static int rtl8126_phc_settime(struct ptp_clock_info *ptp, static int rtl8126_phc_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts64) const struct timespec64 *ts64)
@@ -236,38 +288,77 @@ static int rtl8126_phc_settime(struct ptp_clock_info *ptp,
//netif_info(tp, drv, tp->dev, "phc set ts\n"); //netif_info(tp, drv, tp->dev, "phc set ts\n");
rtnl_lock();
ret = _rtl8126_phc_settime(tp, ts64); ret = _rtl8126_phc_settime(tp, ts64);
rtnl_unlock();
return ret; return ret;
} }
static void _rtl8126_phc_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
unsigned long flags;
u16 phy_ocp_data;
if (on) {
tp->pps_enable = 1;
rtl8126_clear_mac_ocp_bit(tp, 0xDC00, BIT_6);
rtl8126_clear_mac_ocp_bit(tp, 0xDC20, BIT_1);
spin_lock_irqsave(&tp->phy_lock, flags);
/* Set periodic pulse 1pps */
/* E432[8:0] = 0x017d */
phy_ocp_data = rtl8126_mdio_direct_read_phy_ocp(tp, 0xE432);
phy_ocp_data &= 0xFE00;
phy_ocp_data |= 0x017d;
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE432, phy_ocp_data);
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE434, 0x7840);
/* E436[8:0] = 0xbe */
phy_ocp_data = rtl8126_mdio_direct_read_phy_ocp(tp, 0xE436);
phy_ocp_data &= 0xFE00;
phy_ocp_data |= 0xbe;
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE436, phy_ocp_data);
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE438, 0xbc20);
spin_unlock_irqrestore(&tp->phy_lock, flags);
/* start hrtimer */
hrtimer_start(&tp->pps_timer, 1000000000, HRTIMER_MODE_REL);
} else
tp->pps_enable = 0;
}
static int rtl8126_phc_enable(struct ptp_clock_info *ptp, static int rtl8126_phc_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on) struct ptp_clock_request *rq, int on)
{ {
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
u16 ptp_ctrl;
//netif_info(tp, drv, tp->dev, "phc enable type %x on %d\n", rq->type, on);
switch (rq->type) { switch (rq->type) {
case PTP_CLK_REQ_PPS: case PTP_CLK_REQ_PPS:
rtnl_lock(); _rtl8126_phc_enable(ptp, rq, on);
ptp_ctrl = RTL_R16(tp, PTP_CTRL_8125);
ptp_ctrl &= ~BIT_15;
if (on)
ptp_ctrl |= BIT_14;
else
ptp_ctrl &= ~BIT_14;
RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl);
rtnl_unlock();
return 0; return 0;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
} }
static void rtl8126_ptp_enable_config(struct rtl8126_private *tp)
{
u16 ptp_ctrl;
if (tp->syncE_en)
rtl8126_set_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
else
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
ptp_ctrl = BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 | BIT_12;
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CTL, ptp_ctrl);
rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15);
}
int rtl8126_get_ts_info(struct net_device *netdev, int rtl8126_get_ts_info(struct net_device *netdev,
struct ethtool_ts_info *info) struct ethtool_ts_info *info)
{ {
@@ -311,53 +402,154 @@ static const struct ptp_clock_info rtl_ptp_clock_info = {
.n_per_out = 0, .n_per_out = 0,
.n_pins = 0, .n_pins = 0,
.pps = 1, .pps = 1,
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,2,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
.adjfine = rtl8126_ptp_adjfine,
#else
.adjfreq = rtl8126_phc_adjfreq, .adjfreq = rtl8126_phc_adjfreq,
#endif //LINUX_VERSION_CODE < KERNEL_VERSION(6,2,0) #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0) */
.adjtime = rtl8126_phc_adjtime, .adjtime = rtl8126_phc_adjtime,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
.gettimex64 = rtl8126_phc_gettime,
#else
.gettime64 = rtl8126_phc_gettime, .gettime64 = rtl8126_phc_gettime,
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) */
.settime64 = rtl8126_phc_settime, .settime64 = rtl8126_phc_settime,
.enable = rtl8126_phc_enable, .enable = rtl8126_phc_enable,
}; };
static int rtl8126_ptp_egresstime(struct rtl8126_private *tp, struct timespec64 *ts64, u32 regnum) static u16 rtl8126_ptp_get_tx_msgtype(struct rtl8126_private *tp)
{ {
u16 tx_ts_ready = 0;
int i;
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++) {
tx_ts_ready = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & 0xF000;
if (tx_ts_ready)
break;
}
switch (tx_ts_ready) {
case TX_TS_PDLYRSP_RDY:
return 3;
case TX_TS_PDLYREQ_RDY:
return 2;
case TX_TS_DLYREQ_RDY:
return 1;
case TX_TS_SYNC_RDY:
default:
return 0;
}
}
static u16 rtl8126_ptp_get_rx_msgtype(struct rtl8126_private *tp)
{
u16 rx_ts_ready = 0;
int i;
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++) {
rx_ts_ready = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & 0x0F00;
if (rx_ts_ready)
break;
}
switch (rx_ts_ready) {
case RX_TS_PDLYRSP_RDY:
return 3;
case RX_TS_PDLYREQ_RDY:
return 2;
case RX_TS_DLYREQ_RDY:
return 1;
case RX_TS_SYNC_RDY:
default:
return 0;
}
}
static void rtl8126_wait_trx_ts_ready(struct rtl8126_private *tp)
{
int i;
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++)
if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & TRX_TS_RD))
break;
}
static void rtl8126_set_trx_ts_cmd(struct rtl8126_private *tp, u16 cmd)
{
rtl8126_clear_and_set_eth_phy_ocp_bit(tp,
PTP_TRX_TS_STA,
TRXTS_SEL | BIT_3 | BIT_2,
TRX_TS_RD | cmd);
rtl8126_wait_trx_ts_ready(tp);
}
static void rtl8126_ptp_egresstime(struct rtl8126_private *tp, struct timespec64 *ts64)
{
u16 msgtype;
msgtype = rtl8126_ptp_get_tx_msgtype(tp);
msgtype <<= 2;
rtl8126_set_trx_ts_cmd(tp, (msgtype | BIT_4));
/* nanoseconds */ /* nanoseconds */
//[29:0] //Ns[29:16] E448[13:0]
ts64->tv_nsec = rtl8126_mac_ocp_read(tp, PTP_EGRESS_TIME_BASE_NS_8125 + regnum * 16 + 2); ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_HI) & 0x3fff;
ts64->tv_nsec <<= 16; ts64->tv_nsec <<= 16;
ts64->tv_nsec |= rtl8126_mac_ocp_read(tp, PTP_EGRESS_TIME_BASE_NS_8125 + regnum * 16); //Ns[15:0] E446[15:0]
ts64->tv_nsec &= 0x3fffffff; ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_LO);
/* seconds */ /* seconds */
//[47:0] //S[47:32] E44E[15:0]
ts64->tv_sec = rtl8126_mac_ocp_read(tp, PTP_EGRESS_TIME_BASE_S_8125 + regnum * 16 + 4); ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_HI);
ts64->tv_sec <<= 16; ts64->tv_sec <<= 16;
ts64->tv_sec |= rtl8126_mac_ocp_read(tp, PTP_EGRESS_TIME_BASE_S_8125 + regnum * 16 + 2); //S[31:16] E44C[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_MI);
ts64->tv_sec <<= 16; ts64->tv_sec <<= 16;
ts64->tv_sec |= rtl8126_mac_ocp_read(tp, PTP_EGRESS_TIME_BASE_S_8125 + regnum * 16); //S[15:0] E44A[15:0]
ts64->tv_sec &= 0x0000ffffffffffff; ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_LO);
}
return 0; static void rtl8126_ptp_ingresstime(struct rtl8126_private *tp, struct timespec64 *ts64)
{
u16 msgtype;
msgtype = rtl8126_ptp_get_rx_msgtype(tp);
msgtype <<= 2;
rtl8126_set_trx_ts_cmd(tp, (TRXTS_SEL | msgtype | BIT_4));
/* nanoseconds */
//Ns[29:16] E448[13:0]
ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_HI) & 0x3fff;
ts64->tv_nsec <<= 16;
//Ns[15:0] E446[15:0]
ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_LO);
/* seconds */
//S[47:32] E44E[15:0]
ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_HI);
ts64->tv_sec <<= 16;
//S[31:16] E44C[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_MI);
ts64->tv_sec <<= 16;
//S[15:0] E44A[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_LO);
} }
static void rtl8126_ptp_tx_hwtstamp(struct rtl8126_private *tp) static void rtl8126_ptp_tx_hwtstamp(struct rtl8126_private *tp)
{ {
struct sk_buff *skb = tp->ptp_tx_skb; struct sk_buff *skb = tp->ptp_tx_skb;
struct skb_shared_hwtstamps shhwtstamps = {0}; struct skb_shared_hwtstamps shhwtstamps = { 0 };
struct timespec64 ts64; struct timespec64 ts64;
u32 regnum;
RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, TX_TX_INTR);
//IO 0x2302 bit 10~11 WR_PTR rtl8126_ptp_egresstime(tp, &ts64);
regnum = RTL_R16(tp, 0x2032) & 0x0C00;
regnum >>= 10;
regnum = (regnum + 3) % 4;
rtnl_lock();
rtl8126_ptp_egresstime(tp, &ts64, regnum);
rtnl_unlock();
/* Upper 32 bits contain s, lower 32 bits contain ns. */ /* Upper 32 bits contain s, lower 32 bits contain ns. */
shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec, shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec,
@@ -381,6 +573,7 @@ static void rtl8126_ptp_tx_work(struct work_struct *work)
{ {
struct rtl8126_private *tp = container_of(work, struct rtl8126_private, struct rtl8126_private *tp = container_of(work, struct rtl8126_private,
ptp_tx_work); ptp_tx_work);
unsigned long flags;
if (!tp->ptp_tx_skb) if (!tp->ptp_tx_skb)
return; return;
@@ -394,47 +587,66 @@ static void rtl8126_ptp_tx_work(struct work_struct *work)
/* Clear the tx valid bit in TSYNCTXCTL register to enable /* Clear the tx valid bit in TSYNCTXCTL register to enable
* interrupt * interrupt
*/ */
RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); spin_lock_irqsave(&tp->phy_lock, flags);
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, TX_TX_INTR);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return; return;
} }
if (RTL_R8(tp, PTP_ISR_8125) & (PTP_ISR_TOK)) spin_lock_irqsave(&tp->phy_lock, flags);
if (rtl8126_mdio_direct_read_phy_ocp(tp, PTP_INSR) & TX_TX_INTR) {
rtl8126_ptp_tx_hwtstamp(tp); rtl8126_ptp_tx_hwtstamp(tp);
else spin_unlock_irqrestore(&tp->phy_lock, flags);
} else {
spin_unlock_irqrestore(&tp->phy_lock, flags);
/* reschedule to check later */ /* reschedule to check later */
schedule_work(&tp->ptp_tx_work); schedule_work(&tp->ptp_tx_work);
}
} }
static int rtl8126_hwtstamp_enable(struct rtl8126_private *tp, bool enable) static int rtl8126_hwtstamp_enable(struct rtl8126_private *tp, bool enable)
{ {
RTL_W16(tp, PTP_CTRL_8125, 0); unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags);
if (enable) { if (enable) {
u16 ptp_ctrl; //trx timestamp interrupt enable
struct timespec64 ts64; rtl8126_set_eth_phy_ocp_bit(tp, PTP_INER, BIT_2 | BIT_3);
//set isr clear mode
rtl8126_set_eth_phy_ocp_bit(tp, PTP_GEN_CFG, BIT_0);
//clear ptp isr //clear ptp isr
RTL_W8(tp, PTP_ISR_8125, 0xff); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, 0xFFFF);
//ptp source 0:gphy 1:mac
rtl8126_mac_ocp_write(tp, 0xDC00, rtl8126_mac_ocp_read(tp, 0xDC00) | BIT_6);
//enable ptp
ptp_ctrl = (BIT_0 | BIT_3 | BIT_4 | BIT_6 | BIT_10 | BIT_12);
if (tp->ptp_master_mode)
ptp_ctrl |= BIT_1;
RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl);
//set system time //enable ptp
/* rtl8126_ptp_enable_config(tp);
if (ktime_to_timespec64_cond(ktime_get_real(), &ts64))
_rtl8126_phc_settime(tp, timespec64_to_timespec(ts64)); //rtl8126_set_local_time(tp);
*/ } else {
ktime_get_real_ts64(&ts64); /* trx timestamp interrupt disable */
_rtl8126_phc_settime(tp, &ts64); rtl8126_clear_eth_phy_ocp_bit(tp, PTP_INER, BIT_2 | BIT_3);
/* disable ptp */
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_CTL, BIT_0);
rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15);
} }
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0; return 0;
} }
void rtl8126_set_local_time(struct rtl8126_private *tp)
{
struct timespec64 ts64;
//set system time
ktime_get_real_ts64(&ts64);
_rtl8126_phc_settime(tp, &ts64);
}
static long rtl8126_ptp_create_clock(struct rtl8126_private *tp) static long rtl8126_ptp_create_clock(struct rtl8126_private *tp)
{ {
struct net_device *netdev = tp->dev; struct net_device *netdev = tp->dev;
@@ -449,9 +661,10 @@ static long rtl8126_ptp_create_clock(struct rtl8126_private *tp)
} }
tp->ptp_clock_info = rtl_ptp_clock_info; tp->ptp_clock_info = rtl_ptp_clock_info;
tp->ptp_clock_info.max_adj = 488281;//0x1FFFFF * 10^9 / 2^32
snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name), snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name),
"%pm", tp->dev->dev_addr); "%pm", tp->dev->dev_addr);
tp->ptp_clock_info.max_adj = 119304647;
tp->ptp_clock = ptp_clock_register(&tp->ptp_clock_info, &tp->pci_dev->dev); tp->ptp_clock = ptp_clock_register(&tp->ptp_clock_info, &tp->pci_dev->dev);
if (IS_ERR(tp->ptp_clock)) { if (IS_ERR(tp->ptp_clock)) {
err = PTR_ERR(tp->ptp_clock); err = PTR_ERR(tp->ptp_clock);
@@ -464,6 +677,43 @@ static long rtl8126_ptp_create_clock(struct rtl8126_private *tp)
return 0; return 0;
} }
static enum hrtimer_restart
rtl8126_hrtimer_for_pps(struct hrtimer *timer) {
struct rtl8126_private *tp = container_of(timer, struct rtl8126_private, pps_timer);
u16 tai_cfg = BIT_8 | BIT_3 | BIT_1 | BIT_0;
s64 pps_sec;
if (tp->pps_enable)
{
unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags);
//Direct Read
rtl8126_set_clkadj_mode(tp, DIRECT_READ);
pps_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_HI_8126);
pps_sec <<= 16;
pps_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_MI_8126);
pps_sec <<= 16;
pps_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_LO_8126);
pps_sec++;
//E42A[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_TS_S_LO, pps_sec & 0xffff);
//E42C[31:16]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_TS_S_HI, (pps_sec & 0xffff0000) >> 16);
//Periodic Tai start
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_CFG, tai_cfg);
spin_unlock_irqrestore(&tp->phy_lock, flags);
hrtimer_forward_now(&tp->pps_timer, 1000000000); //rekick
return HRTIMER_RESTART;
} else
return HRTIMER_NORESTART;
}
void rtl8126_ptp_reset(struct rtl8126_private *tp) void rtl8126_ptp_reset(struct rtl8126_private *tp)
{ {
if (!tp->ptp_clock) if (!tp->ptp_clock)
@@ -483,6 +733,11 @@ void rtl8126_ptp_init(struct rtl8126_private *tp)
/* we have a clock so we can initialize work now */ /* we have a clock so we can initialize work now */
INIT_WORK(&tp->ptp_tx_work, rtl8126_ptp_tx_work); INIT_WORK(&tp->ptp_tx_work, rtl8126_ptp_tx_work);
/* init a hrtimer for pps */
tp->pps_enable = 0;
hrtimer_init(&tp->pps_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
tp->pps_timer.function = rtl8126_hrtimer_for_pps;
/* reset the PTP related hardware bits */ /* reset the PTP related hardware bits */
rtl8126_ptp_reset(tp); rtl8126_ptp_reset(tp);
@@ -500,6 +755,8 @@ void rtl8126_ptp_suspend(struct rtl8126_private *tp)
/* ensure that we cancel any pending PTP Tx work item in progress */ /* ensure that we cancel any pending PTP Tx work item in progress */
cancel_work_sync(&tp->ptp_tx_work); cancel_work_sync(&tp->ptp_tx_work);
hrtimer_cancel(&tp->pps_timer);
} }
void rtl8126_ptp_stop(struct rtl8126_private *tp) void rtl8126_ptp_stop(struct rtl8126_private *tp)
@@ -537,6 +794,7 @@ static int rtl8126_set_tstamp(struct net_device *netdev, struct ifreq *ifr)
switch (config.tx_type) { switch (config.tx_type) {
case HWTSTAMP_TX_ON: case HWTSTAMP_TX_ON:
hwtstamp = 1; hwtstamp = 1;
break;
case HWTSTAMP_TX_OFF: case HWTSTAMP_TX_OFF:
break; break;
case HWTSTAMP_TX_ONESTEP_SYNC: case HWTSTAMP_TX_ONESTEP_SYNC:
@@ -556,15 +814,20 @@ static int rtl8126_set_tstamp(struct net_device *netdev, struct ifreq *ifr)
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
hwtstamp = 1; hwtstamp = 1;
tp->flags |= RTL_FLAG_RX_HWTSTAMP_ENABLED;
break;
case HWTSTAMP_FILTER_NONE: case HWTSTAMP_FILTER_NONE:
tp->flags &= ~RTL_FLAG_RX_HWTSTAMP_ENABLED;
break; break;
default: default:
tp->flags &= ~RTL_FLAG_RX_HWTSTAMP_ENABLED;
return -ERANGE; return -ERANGE;
} }
if (tp->hwtstamp_config.tx_type != config.tx_type || if (tp->hwtstamp_config.tx_type != config.tx_type ||
tp->hwtstamp_config.rx_filter != config.rx_filter) { tp->hwtstamp_config.rx_filter != config.rx_filter) {
tp->hwtstamp_config = config; tp->hwtstamp_config = config;
rtl8126_hwtstamp_enable(tp, hwtstamp); rtl8126_hwtstamp_enable(tp, hwtstamp);
} }
@@ -605,15 +868,25 @@ int rtl8126_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
return ret; return ret;
} }
void rtl8126_rx_ptp_pktstamp(struct rtl8126_private *tp, struct sk_buff *skb, void rtl8126_rx_ptp_pktstamp(struct rtl8126_private *tp, struct sk_buff *skb)
struct RxDescV3 *descv3)
{ {
time64_t tv_sec; struct timespec64 ts64;
long tv_nsec; unsigned long flags;
tv_sec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampHigh) + spin_lock_irqsave(&tp->phy_lock, flags);
((u64)le32_to_cpu(descv3->RxDescPTPDDWord4.TimeStampHHigh) << 32);
tv_nsec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampLow);
skb_hwtstamps(skb)->hwtstamp = ktime_set(tv_sec, tv_nsec); if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_INSR) & RX_TS_INTR)) {
spin_unlock_irqrestore(&tp->phy_lock, flags);
return;
}
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, RX_TS_INTR);
rtl8126_ptp_ingresstime(tp, &ts64);
spin_unlock_irqrestore(&tp->phy_lock, flags);
skb_hwtstamps(skb)->hwtstamp = ktime_set(ts64.tv_sec, ts64.tv_nsec);
return;
} }

View File

@@ -61,6 +61,37 @@ enum PTP_CMD_TYPE {
PTP_CMD_LATCHED_LOCAL_TIME, PTP_CMD_LATCHED_LOCAL_TIME,
}; };
enum PTP_CLKADJ_MOD_TYPE {
NO_FUNCTION = 0,
CLKADJ_MODE_SET = 1,
RESERVED = 2,
DIRECT_READ = 4,
DIRECT_WRITE = 6,
INCREMENT_STEP = 8,
DECREMENT_STEP = 10,
RATE_READ = 12,
RATE_WRITE = 14,
};
enum PTP_INSR_TYPE {
EVENT_CAP_INTR = (1 << 0),
TRIG_GEN_INTR = (1 << 1),
RX_TS_INTR = (1 << 2),
TX_TX_INTR = (1 << 3),
};
enum PTP_TRX_TS_STA_REG {
TRX_TS_RD = (1 << 0),
TRXTS_SEL = (1 << 1),
RX_TS_PDLYRSP_RDY = (1 << 8),
RX_TS_PDLYREQ_RDY = (1 << 9),
RX_TS_DLYREQ_RDY = (1 << 10),
RX_TS_SYNC_RDY = (1 << 11),
TX_TS_PDLYRSP_RDY = (1 << 12),
TX_TS_PDLYREQ_RDY = (1 << 13),
TX_TS_DLYREQ_RDY = (1 << 14),
TX_TS_SYNC_RDY = (1 << 15),
};
struct rtl8126_private; struct rtl8126_private;
struct RxDescV3; struct RxDescV3;
@@ -75,7 +106,8 @@ void rtl8126_ptp_stop(struct rtl8126_private *tp);
int rtl8126_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); int rtl8126_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
void rtl8126_rx_ptp_pktstamp(struct rtl8126_private *tp, struct sk_buff *skb, void rtl8126_rx_ptp_pktstamp(struct rtl8126_private *tp, struct sk_buff *skb);
struct RxDescV3 *descv3);
void rtl8126_set_local_time(struct rtl8126_private *tp);
#endif /* _LINUX_R8126_PTP_H */ #endif /* _LINUX_R8126_PTP_H */

View File

@@ -324,28 +324,6 @@ static void rtl8126_get_reta(struct rtl8126_private *tp, u32 *indir)
indir[i] = tp->rss_indir_tbl[i]; indir[i] = tp->rss_indir_tbl[i];
} }
int rtl8126_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP;
if (hfunc)
*hfunc = ETH_RSS_HASH_TOP;
if (indir)
rtl8126_get_reta(tp, indir);
if (key)
memcpy(key, tp->rss_key, RTL8126_RSS_KEY_SIZE);
return 0;
}
static u32 rtl8126_rss_key_reg(struct rtl8126_private *tp) static u32 rtl8126_rss_key_reg(struct rtl8126_private *tp)
{ {
return RSS_KEY_8125; return RSS_KEY_8125;
@@ -386,6 +364,88 @@ static void rtl8126_store_rss_key(struct rtl8126_private *tp)
RTL_W32(tp, rss_key_reg + i, *rss_key++); RTL_W32(tp, rss_key_reg + i, *rss_key++);
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
int rtl8126_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
{
struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP;
rxfh->hfunc = ETH_RSS_HASH_TOP;
if (rxfh->indir)
rtl8126_get_reta(tp, rxfh->indir);
if (rxfh->key)
memcpy(rxfh->key, tp->rss_key, RTL8126_RSS_KEY_SIZE);
return 0;
}
int rtl8126_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
struct rtl8126_private *tp = netdev_priv(dev);
int i;
u32 reta_entries = rtl8126_rss_indir_tbl_entries(tp);
netif_info(tp, drv, tp->dev, "rss set rxfh\n");
/* We require at least one supported parameter to be changed and no
* change in any of the unsupported parameters
*/
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
/* Fill out the redirection table */
if (rxfh->indir) {
int max_queues = tp->num_rx_rings;
/* Verify user input. */
for (i = 0; i < reta_entries; i++)
if (rxfh->indir[i] >= max_queues)
return -EINVAL;
for (i = 0; i < reta_entries; i++)
tp->rss_indir_tbl[i] = rxfh->indir[i];
}
/* Fill out the rss hash key */
if (rxfh->key)
memcpy(tp->rss_key, rxfh->key, RTL8126_RSS_KEY_SIZE);
rtl8126_store_reta(tp);
rtl8126_store_rss_key(tp);
return 0;
}
#else
int rtl8126_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP;
if (hfunc)
*hfunc = ETH_RSS_HASH_TOP;
if (indir)
rtl8126_get_reta(tp, indir);
if (key)
memcpy(key, tp->rss_key, RTL8126_RSS_KEY_SIZE);
return 0;
}
int rtl8126_set_rxfh(struct net_device *dev, const u32 *indir, int rtl8126_set_rxfh(struct net_device *dev, const u32 *indir,
const u8 *key, const u8 hfunc) const u8 *key, const u8 hfunc)
{ {
@@ -424,11 +484,19 @@ int rtl8126_set_rxfh(struct net_device *dev, const u32 *indir,
return 0; return 0;
} }
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
static u32 rtl8126_get_rx_desc_hash(struct rtl8126_private *tp, static u32 rtl8126_get_rx_desc_hash(struct rtl8126_private *tp,
struct RxDescV3 *descv3) struct RxDesc *desc)
{ {
return le32_to_cpu(descv3->RxDescNormalDDWord2.RSSResult); switch (tp->InitRxDescType) {
case RX_DESC_RING_TYPE_3:
return le32_to_cpu(((struct RxDescV3 *)desc)->RxDescNormalDDWord2.RSSResult);
case RX_DESC_RING_TYPE_4:
return le32_to_cpu(((struct RxDescV4 *)desc)->RxDescNormalDDWord1.RSSResult);
default:
return 0;
}
} }
#define RXS_8125B_RSS_UDP BIT(9) #define RXS_8125B_RSS_UDP BIT(9)
@@ -437,7 +505,14 @@ static u32 rtl8126_get_rx_desc_hash(struct rtl8126_private *tp,
#define RXS_8125_RSS_TCP BIT(13) #define RXS_8125_RSS_TCP BIT(13)
#define RTL8126_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6) #define RTL8126_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6)
#define RTL8126_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP) #define RTL8126_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP)
void rtl8126_rx_hash(struct rtl8126_private *tp,
#define RXS_8125B_RSS_UDP_V4 BIT(27)
#define RXS_8125_RSS_IPV4_V4 BIT(28)
#define RXS_8125_RSS_IPV6_V4 BIT(29)
#define RXS_8125_RSS_TCP_V4 BIT(30)
#define RTL8126_RXS_RSS_L3_TYPE_MASK_V4 (RXS_8125_RSS_IPV4_V4 | RXS_8125_RSS_IPV6_V4)
#define RTL8126_RXS_RSS_L4_TYPE_MASK_V4 (RXS_8125_RSS_TCP_V4 | RXS_8125B_RSS_UDP_V4)
static void rtl8126_rx_hash_v3(struct rtl8126_private *tp,
struct RxDescV3 *descv3, struct RxDescV3 *descv3,
struct sk_buff *skb) struct sk_buff *skb)
{ {
@@ -451,11 +526,46 @@ void rtl8126_rx_hash(struct rtl8126_private *tp,
if (!(rss_header_info & RTL8126_RXS_RSS_L3_TYPE_MASK)) if (!(rss_header_info & RTL8126_RXS_RSS_L3_TYPE_MASK))
return; return;
skb_set_hash(skb, rtl8126_get_rx_desc_hash(tp, descv3), skb_set_hash(skb, rtl8126_get_rx_desc_hash(tp, (struct RxDesc *)descv3),
(RTL8126_RXS_RSS_L4_TYPE_MASK & rss_header_info) ? (RTL8126_RXS_RSS_L4_TYPE_MASK & rss_header_info) ?
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
} }
static void rtl8126_rx_hash_v4(struct rtl8126_private *tp,
struct RxDescV4 *descv4,
struct sk_buff *skb)
{
u32 rss_header_info;
if (!(tp->dev->features & NETIF_F_RXHASH))
return;
rss_header_info = le32_to_cpu(descv4->RxDescNormalDDWord1.RSSInfo);
if (!(rss_header_info & RTL8126_RXS_RSS_L3_TYPE_MASK_V4))
return;
skb_set_hash(skb, rtl8126_get_rx_desc_hash(tp, (struct RxDesc *)descv4),
(RTL8126_RXS_RSS_L4_TYPE_MASK_V4 & rss_header_info) ?
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
}
void rtl8126_rx_hash(struct rtl8126_private *tp,
struct RxDesc *desc,
struct sk_buff *skb)
{
switch (tp->InitRxDescType) {
case RX_DESC_RING_TYPE_3:
rtl8126_rx_hash_v3(tp, (struct RxDescV3 *)desc, skb);
break;
case RX_DESC_RING_TYPE_4:
rtl8126_rx_hash_v4(tp, (struct RxDescV4 *)desc, skb);
break;
default:
return;
}
}
void rtl8126_disable_rss(struct rtl8126_private *tp) void rtl8126_disable_rss(struct rtl8126_private *tp)
{ {
RTL_W32(tp, RSS_CTRL_8125, 0x00); RTL_W32(tp, RSS_CTRL_8125, 0x00);

View File

@@ -47,18 +47,25 @@ enum rtl8126_rss_flag {
}; };
struct rtl8126_private; struct rtl8126_private;
struct RxDesc;
int rtl8126_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, int rtl8126_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs); u32 *rule_locs);
int rtl8126_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); int rtl8126_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd);
u32 rtl8126_get_rxfh_key_size(struct net_device *netdev); u32 rtl8126_get_rxfh_key_size(struct net_device *netdev);
u32 rtl8126_rss_indir_size(struct net_device *netdev); u32 rtl8126_rss_indir_size(struct net_device *netdev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
int rtl8126_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh);
int rtl8126_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack);
#else
int rtl8126_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, int rtl8126_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc); u8 *hfunc);
int rtl8126_set_rxfh(struct net_device *netdev, const u32 *indir, int rtl8126_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *key, const u8 hfunc); const u8 *key, const u8 hfunc);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
void rtl8126_rx_hash(struct rtl8126_private *tp, void rtl8126_rx_hash(struct rtl8126_private *tp,
struct RxDescV3 *descv3, struct RxDesc *desc,
struct sk_buff *skb); struct sk_buff *skb);
void _rtl8126_config_rss(struct rtl8126_private *tp); void _rtl8126_config_rss(struct rtl8126_private *tp);
void rtl8126_config_rss(struct rtl8126_private *tp); void rtl8126_config_rss(struct rtl8126_private *tp);

View File

@@ -93,7 +93,7 @@ void rtl8126_eeprom_cleanup(struct rtl8126_private *tp)
rtl8126_lower_clock(tp, &x); rtl8126_lower_clock(tp, &x);
} }
int rtl8126_eeprom_cmd_done(struct rtl8126_private *tp) static int rtl8126_eeprom_cmd_done(struct rtl8126_private *tp)
{ {
u8 x; u8 x;
int i; int i;
@@ -123,9 +123,8 @@ u16 rtl8126_eeprom_read_sc(struct rtl8126_private *tp, u16 reg)
u8 x; u8 x;
u16 data; u16 data;
if(tp->eeprom_type == EEPROM_TYPE_NONE) { if(tp->eeprom_type == EEPROM_TYPE_NONE)
return -1; return -1;
}
if (tp->eeprom_type==EEPROM_TYPE_93C46) if (tp->eeprom_type==EEPROM_TYPE_93C46)
addr_sz = 6; addr_sz = 6;
@@ -157,9 +156,8 @@ void rtl8126_eeprom_write_sc(struct rtl8126_private *tp, u16 reg, u16 data)
int addr_sz = 6; int addr_sz = 6;
int w_dummy_addr = 4; int w_dummy_addr = 4;
if(tp->eeprom_type == EEPROM_TYPE_NONE) { if(tp->eeprom_type == EEPROM_TYPE_NONE)
return ; return;
}
if (tp->eeprom_type==EEPROM_TYPE_93C46) { if (tp->eeprom_type==EEPROM_TYPE_93C46) {
addr_sz = 6; addr_sz = 6;
@@ -178,17 +176,15 @@ void rtl8126_eeprom_write_sc(struct rtl8126_private *tp, u16 reg, u16 data)
rtl8126_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); rtl8126_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3);
rtl8126_shift_out_bits(tp, reg, addr_sz); rtl8126_shift_out_bits(tp, reg, addr_sz);
if (rtl8126_eeprom_cmd_done(tp) < 0) { if (rtl8126_eeprom_cmd_done(tp) < 0)
return; return;
}
rtl8126_stand_by(tp); rtl8126_stand_by(tp);
rtl8126_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); rtl8126_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3);
rtl8126_shift_out_bits(tp, reg, addr_sz); rtl8126_shift_out_bits(tp, reg, addr_sz);
rtl8126_shift_out_bits(tp, data, 16); rtl8126_shift_out_bits(tp, data, 16);
if (rtl8126_eeprom_cmd_done(tp) < 0) { if (rtl8126_eeprom_cmd_done(tp) < 0)
return; return;
}
rtl8126_stand_by(tp); rtl8126_stand_by(tp);
rtl8126_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); rtl8126_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5);

View File

@@ -54,6 +54,5 @@ void rtl8126_raise_clock(struct rtl8126_private *tp, u8 *x);
void rtl8126_lower_clock(struct rtl8126_private *tp, u8 *x); void rtl8126_lower_clock(struct rtl8126_private *tp, u8 *x);
void rtl8126_stand_by(struct rtl8126_private *tp); void rtl8126_stand_by(struct rtl8126_private *tp);
void rtl8126_set_eeprom_sel_low(struct rtl8126_private *tp); void rtl8126_set_eeprom_sel_low(struct rtl8126_private *tp);
int rtl8126_eeprom_cmd_done(struct rtl8126_private *tp);
#endif /* _LINUX_RTLEEPROM_H */ #endif /* _LINUX_RTLEEPROM_H */