r8126: Add r8126 driver version 10.016.00

Add support for r8126 ethernet driverversion 10.016.00
which adds support till K6.15

Bug 5312842

Change-Id: I5987fd9a885fef7be6e1448674fc2e5c61820d1a
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3415199
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
This commit is contained in:
Revanth Kumar Uppala
2025-07-23 04:28:31 +00:00
committed by mobile promotions
parent 4a68689610
commit 914b98c3ac
18 changed files with 2460 additions and 3473 deletions

View File

@@ -4,7 +4,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free
@@ -30,23 +30,9 @@
# 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)) CONFIG_SOC_LAN = y
LINUX_VERSION_6_9 := $(shell expr 6 \* 256 + 9) ENABLE_FIBER_SUPPORT = n
LINUX_VERSION_5_14 := $(shell expr 5 \* 256 + 14)
# Use dummy R8126 driver for Kernel versions greater that K69
ifeq ($(shell test $(LINUX_VERSION) -gt $(LINUX_VERSION_6_9); echo $$?),0)
obj-m := r8126.o
r8126-objs := r8126_dummy.o
else ifeq ($(shell test $(LINUX_VERSION) -eq $(LINUX_VERSION_5_14); echo $$?),0)
obj-m := r8126.o
r8126-objs := r8126_dummy.o
else
CONFIG_SOC_LAN = n
ENABLE_REALWOW_SUPPORT = n ENABLE_REALWOW_SUPPORT = n
ENABLE_DASH_SUPPORT = n
ENABLE_DASH_PRINTER_SUPPORT = n
CONFIG_DOWN_SPEED_100 = n CONFIG_DOWN_SPEED_100 = n
CONFIG_ASPM = y CONFIG_ASPM = y
ENABLE_S5WOL = y ENABLE_S5WOL = y
@@ -54,10 +40,9 @@ ENABLE_S5_KEEP_CURR_MAC = n
ENABLE_EEE = y 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 = n
ENABLE_PTP_SUPPORT = y ENABLE_PTP_SUPPORT = n
ENABLE_PTP_MASTER_MODE = n ENABLE_RSS_SUPPORT = n
ENABLE_RSS_SUPPORT = y
ENABLE_LIB_SUPPORT = n ENABLE_LIB_SUPPORT = n
ENABLE_USE_FIRMWARE_FILE = n ENABLE_USE_FIRMWARE_FILE = n
DISABLE_WOL_SUPPORT = n DISABLE_WOL_SUPPORT = n
@@ -65,12 +50,17 @@ DISABLE_MULTI_MSIX_VECTOR = n
ENABLE_DOUBLE_VLAN = n ENABLE_DOUBLE_VLAN = n
ENABLE_PAGE_REUSE = n ENABLE_PAGE_REUSE = n
ENABLE_RX_PACKET_FRAGMENT = n ENABLE_RX_PACKET_FRAGMENT = n
ENABLE_GIGA_LITE = y
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
ifeq ($(ENABLE_FIBER_SUPPORT), y)
r8126-objs += r8126_fiber.o
EXTRA_CFLAGS += -DENABLE_FIBER_SUPPORT
endif
ifeq ($(ENABLE_REALWOW_SUPPORT), y) ifeq ($(ENABLE_REALWOW_SUPPORT), y)
r8126-objs += r8126_realwow.o r8126-objs += r8126_realwow.o
EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT
@@ -113,9 +103,6 @@ ifeq ($(ENABLE_PTP_SUPPORT), y)
r8126-objs += r8126_ptp.o r8126-objs += r8126_ptp.o
EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT
endif endif
ifeq ($(ENABLE_PTP_MASTER_MODE), y)
EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE
endif
ifeq ($(ENABLE_RSS_SUPPORT), y) ifeq ($(ENABLE_RSS_SUPPORT), y)
r8126-objs += r8126_rss.o r8126-objs += r8126_rss.o
EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT
@@ -143,5 +130,9 @@ 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
ifeq ($(ENABLE_GIGA_LITE), y)
EXTRA_CFLAGS += -DENABLE_GIGA_LITE
endif endif
# Backward compatibility
ccflags-y += $(EXTRA_CFLAGS)

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free
@@ -39,8 +39,10 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/version.h> #include <linux/version.h>
#include "r8126_dash.h"
#include "r8126_realwow.h" #include "r8126_realwow.h"
#ifdef ENABLE_FIBER_SUPPORT
#include "r8126_fiber.h"
#endif /* ENABLE_FIBER_SUPPORT */
#ifdef ENABLE_PTP_SUPPORT #ifdef ENABLE_PTP_SUPPORT
#include "r8126_ptp.h" #include "r8126_ptp.h"
#endif #endif
@@ -53,8 +55,6 @@
#define fallthrough #define fallthrough
#endif #endif
void netdev_sw_irq_coalesce_default_on(struct net_device *dev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
#define netif_xmit_stopped netif_tx_queue_stopped #define netif_xmit_stopped netif_tx_queue_stopped
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) */ #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) */
@@ -202,6 +202,32 @@ static inline void netdev_tx_completed_queue(struct netdev_queue *dev_queue,
static inline void netdev_tx_reset_queue(struct netdev_queue *q) {} static inline void netdev_tx_reset_queue(struct netdev_queue *q) {}
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)
static inline void fsleep(unsigned long usecs)
{
if (usecs <= 10)
udelay(usecs);
else if (usecs <= 20000)
usleep_range(usecs, 2 * usecs);
else
msleep(DIV_ROUND_UP(usecs, 1000));
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,92)
/* Iterate through singly-linked GSO fragments of an skb. */
#define skb_list_walk_safe(first, skb, next_skb) \
for ((skb) = (first), (next_skb) = (skb) ? (skb)->next : NULL; (skb); \
(skb) = (next_skb), (next_skb) = (skb) ? (skb)->next : NULL)
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,4,92) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,217)
static inline void skb_mark_not_on_list(struct sk_buff *skb)
{
skb->next = NULL;
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,14,217) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0)
#define netdev_xmit_more() (0) #define netdev_xmit_more() (0)
#endif #endif
@@ -211,6 +237,10 @@ static inline void netdev_tx_reset_queue(struct netdev_queue *q) {}
#define netif_testing_off(dev) #define netif_testing_off(dev)
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,2,0)
#define netdev_sw_irq_coalesce_default_on(dev)
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,2,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
typedef int netdev_tx_t; typedef int netdev_tx_t;
#endif #endif
@@ -362,6 +392,14 @@ do { \
#endif #endif
#endif #endif
#ifdef CONFIG_R8126_NAPI
#define r8126_spin_lock(lock, flags) (void)flags;spin_lock_bh(lock)
#define r8126_spin_unlock(lock, flags) (void)flags;spin_unlock_bh(lock)
#else
#define r8126_spin_lock(lock, flags) spin_lock_irqsave(lock, flags)
#define r8126_spin_unlock(lock, flags) spin_unlock_irqrestore(lock, flags)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
#define eth_random_addr(addr) random_ether_addr(addr) #define eth_random_addr(addr) random_ether_addr(addr)
#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) #endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
@@ -578,12 +616,10 @@ static inline u32 rtl8126_ethtool_adv_to_mmd_eee_adv_cap2_t(u32 adv)
#else #else
#define NAPI_SUFFIX "" #define NAPI_SUFFIX ""
#endif #endif
#if defined(ENABLE_DASH_PRINTER_SUPPORT) #ifdef ENABLE_REALWOW_SUPPORT
#define DASH_SUFFIX "-PRINTER" #define REALWOW_SUFFIX "-REALWOW"
#elif defined(ENABLE_DASH_SUPPORT)
#define DASH_SUFFIX "-DASH"
#else #else
#define DASH_SUFFIX "" #define REALWOW_SUFFIX ""
#endif #endif
#if defined(ENABLE_REALWOW_SUPPORT) #if defined(ENABLE_REALWOW_SUPPORT)
@@ -604,12 +640,12 @@ static inline u32 rtl8126_ethtool_adv_to_mmd_eee_adv_cap2_t(u32 adv)
#define RSS_SUFFIX "" #define RSS_SUFFIX ""
#endif #endif
#define RTL8126_VERSION "10.013.00" NAPI_SUFFIX DASH_SUFFIX REALWOW_SUFFIX PTP_SUFFIX RSS_SUFFIX #define RTL8126_VERSION "10.016.00" NAPI_SUFFIX REALWOW_SUFFIX PTP_SUFFIX RSS_SUFFIX
#define MODULENAME "r8126" #define MODULENAME "r8126"
#define PFX MODULENAME ": " #define PFX MODULENAME ": "
#define GPL_CLAIM "\ #define GPL_CLAIM "\
r8126 Copyright (C) 2024 Realtek NIC software team <nicfae@realtek.com> \n \ r8126 Copyright (C) 2025 Realtek NIC software team <nicfae@realtek.com> \n \
This program comes with ABSOLUTELY NO WARRANTY; for details, please see <http://www.gnu.org/licenses/>. \n \ This program comes with ABSOLUTELY NO WARRANTY; for details, please see <http://www.gnu.org/licenses/>. \n \
This is free software, and you are welcome to redistribute it under certain conditions; see <http://www.gnu.org/licenses/>. \n" This is free software, and you are welcome to redistribute it under certain conditions; see <http://www.gnu.org/licenses/>. \n"
@@ -725,7 +761,9 @@ This is free software, and you are welcome to redistribute it under certain cond
#endif #endif
#define R8126_MAX_TX_QUEUES (2) #define R8126_MAX_TX_QUEUES (2)
#define R8126_MAX_RX_QUEUES (4) #define R8126_MAX_RX_QUEUES_V2 (4)
#define R8126_MAX_RX_QUEUES_V3 (16)
#define R8126_MAX_RX_QUEUES R8126_MAX_RX_QUEUES_V3
#define R8126_MAX_QUEUES R8126_MAX_RX_QUEUES #define R8126_MAX_QUEUES R8126_MAX_RX_QUEUES
#define OCP_STD_PHY_BASE 0xa400 #define OCP_STD_PHY_BASE 0xa400
@@ -856,6 +894,10 @@ This is free software, and you are welcome to redistribute it under certain cond
#define SPEED_5000 5000 #define SPEED_5000 5000
#endif #endif
#define R8126_LINK_STATE_OFF 0
#define R8126_LINK_STATE_ON 1
#define R8126_LINK_STATE_UNKNOWN 2
/*****************************************************************************/ /*****************************************************************************/
//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) //#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
@@ -1616,6 +1658,7 @@ enum RTL8126_register_content {
RxBufEmpty = 0x01, RxBufEmpty = 0x01,
/* Cfg9346Bits */ /* Cfg9346Bits */
Cfg9346_EEM_MASK = 0xC0,
Cfg9346_Lock = 0x00, Cfg9346_Lock = 0x00,
Cfg9346_Unlock = 0xC0, Cfg9346_Unlock = 0xC0,
Cfg9346_EEDO = (1 << 0), Cfg9346_EEDO = (1 << 0),
@@ -1632,6 +1675,7 @@ enum RTL8126_register_content {
AcceptMulticast = 0x04, AcceptMulticast = 0x04,
AcceptMyPhys = 0x02, AcceptMyPhys = 0x02,
AcceptAllPhys = 0x01, AcceptAllPhys = 0x01,
AcceppVlanPhys = 0x8000,
/* Transmit Priority Polling*/ /* Transmit Priority Polling*/
HPQ = 0x80, HPQ = 0x80,
@@ -1709,8 +1753,11 @@ enum RTL8126_register_content {
/* rtl8126_PHYstatus */ /* rtl8126_PHYstatus */
PowerSaveStatus = 0x80, PowerSaveStatus = 0x80,
_1000bpsL = 0x80000,
_5000bpsF = 0x1000, _5000bpsF = 0x1000,
_5000bpsL = 0x800,
_2500bpsF = 0x400, _2500bpsF = 0x400,
_2500bpsL = 0x200,
TxFlowCtrl = 0x40, TxFlowCtrl = 0x40,
RxFlowCtrl = 0x20, RxFlowCtrl = 0x20,
_1000bpsF = 0x10, _1000bpsF = 0x10,
@@ -1858,6 +1905,10 @@ enum _DescStatusBit {
LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */ GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */
GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */ GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */
GiantSendEn_V3 = (1 << 16), /* Giant Send Offload Enable V3 */
GiantSendv4_V3 = (1 << 29), /* IPv4 Giant Send Offload V3 */
GiantSendv6_V3 = (0), /* IPv6 Giant Send Offload V3 */
GiantSendTCP_V3 = (1 << 30), /* TCP Giant Send Offload V3 */
LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */ LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */
MSSShift = 16, /* MSS value position */ MSSShift = 16, /* MSS value position */
MSSMask = 0x7FFU, /* MSS value 11 bits */ MSSMask = 0x7FFU, /* MSS value 11 bits */
@@ -2011,14 +2062,11 @@ enum efuse {
#define RsvdMaskV3 0x3fff8000 #define RsvdMaskV3 0x3fff8000
#define RsvdMaskV4 RsvdMaskV3 #define RsvdMaskV4 RsvdMaskV3
/* Tx desc V3 */
struct TxDesc { struct TxDesc {
u32 opts1; u32 opts1;
u32 opts2; u32 opts2;
u64 addr; u64 addr;
u32 reserved0;
u32 reserved1;
u32 reserved2;
u32 reserved3;
}; };
struct RxDesc { struct RxDesc {
@@ -2148,6 +2196,7 @@ enum r8126_flag {
R8126_FLAG_TASK_RESET_PENDING, R8126_FLAG_TASK_RESET_PENDING,
R8126_FLAG_TASK_ESD_CHECK_PENDING, R8126_FLAG_TASK_ESD_CHECK_PENDING,
R8126_FLAG_TASK_LINKCHG_CHECK_PENDING, R8126_FLAG_TASK_LINKCHG_CHECK_PENDING,
R8126_FLAG_TASK_LINK_CHECK_PENDING,
R8126_FLAG_MAX R8126_FLAG_MAX
}; };
@@ -2519,8 +2568,8 @@ struct rtl8126_private {
u16 cp_cmd; u16 cp_cmd;
u32 intr_mask; u32 intr_mask;
u32 timer_intr_mask; u32 timer_intr_mask;
u16 isr_reg[R8126_MAX_QUEUES]; u16 isr_reg[R8126_MAX_MSIX_VEC];
u16 imr_reg[R8126_MAX_QUEUES]; u16 imr_reg[R8126_MAX_MSIX_VEC];
int phy_auto_nego_reg; int phy_auto_nego_reg;
int phy_1000_ctrl_reg; int phy_1000_ctrl_reg;
int phy_2500_ctrl_reg; int phy_2500_ctrl_reg;
@@ -2558,10 +2607,12 @@ struct rtl8126_private {
struct work_struct reset_task; struct work_struct reset_task;
struct work_struct esd_task; struct work_struct esd_task;
struct work_struct linkchg_task; struct work_struct linkchg_task;
struct work_struct link_task;
#else #else
struct delayed_work reset_task; struct delayed_work reset_task;
struct delayed_work esd_task; struct delayed_work esd_task;
struct delayed_work linkchg_task; struct delayed_work linkchg_task;
struct delayed_work link_task;
#endif #endif
DECLARE_BITMAP(task_flags, R8126_FLAG_MAX); DECLARE_BITMAP(task_flags, R8126_FLAG_MAX);
unsigned features; unsigned features;
@@ -2604,7 +2655,6 @@ struct rtl8126_private {
u32 HwFiberModeVer; u32 HwFiberModeVer;
u32 HwFiberStat; u32 HwFiberStat;
u8 HwSwitchMdiToFiber;
u16 NicCustLedValue; u16 NicCustLedValue;
@@ -2646,83 +2696,7 @@ struct rtl8126_private {
struct rtl8126_fw *rtl_fw; struct rtl8126_fw *rtl_fw;
u32 ocp_base; u32 ocp_base;
//Dash+++++++++++++++++
u8 HwSuppDashVer;
u8 DASH;
u8 dash_printer_enabled;
u8 HwPkgDet; u8 HwPkgDet;
u8 AllowAccessDashOcp;
void __iomem *mapped_cmac_ioaddr; /* mapped cmac memory map physical address */
void __iomem *cmac_ioaddr; /* cmac memory map physical address */
#ifdef ENABLE_DASH_SUPPORT
u16 AfterRecvFromFwBufLen;
u8 AfterRecvFromFwBuf[RECV_FROM_FW_BUF_SIZE];
u16 AfterSendToFwBufLen;
u8 AfterSendToFwBuf[SEND_TO_FW_BUF_SIZE];
u16 SendToFwBufferLen;
u32 SizeOfSendToFwBuffer;
u32 SizeOfSendToFwBufferMemAlloc;
u32 NumOfSendToFwBuffer;
u8 OobReq;
u8 OobAck;
u32 OobReqComplete;
u32 OobAckComplete;
u8 RcvFwReqSysOkEvt;
u8 RcvFwDashOkEvt;
u8 SendFwHostOkEvt;
u8 DashFwDisableRx;
void *UnalignedSendToFwBufferVa;
void *SendToFwBuffer;
u64 SendToFwBufferPhy;
u8 SendingToFw;
dma_addr_t UnalignedSendToFwBufferPa;
PTX_DASH_SEND_FW_DESC TxDashSendFwDesc;
u64 TxDashSendFwDescPhy;
u8 *UnalignedTxDashSendFwDescVa;
u32 SizeOfTxDashSendFwDescMemAlloc;
u32 SizeOfTxDashSendFwDesc;
u32 NumTxDashSendFwDesc;
u32 CurrNumTxDashSendFwDesc;
u32 LastSendNumTxDashSendFwDesc;
dma_addr_t UnalignedTxDashSendFwDescPa;
u32 NumRecvFromFwBuffer;
u32 SizeOfRecvFromFwBuffer;
u32 SizeOfRecvFromFwBufferMemAlloc;
void *RecvFromFwBuffer;
u64 RecvFromFwBufferPhy;
void *UnalignedRecvFromFwBufferVa;
dma_addr_t UnalignedRecvFromFwBufferPa;
PRX_DASH_FROM_FW_DESC RxDashRecvFwDesc;
u64 RxDashRecvFwDescPhy;
u8 *UnalignedRxDashRecvFwDescVa;
u32 SizeOfRxDashRecvFwDescMemAlloc;
u32 SizeOfRxDashRecvFwDesc;
u32 NumRxDashRecvFwDesc;
u32 CurrNumRxDashRecvFwDesc;
dma_addr_t UnalignedRxDashRecvFwDescPa;
u8 DashReqRegValue;
u16 HostReqValue;
u32 CmacResetIsrCounter;
u8 CmacResetIntr;
u8 CmacResetting;
u8 CmacOobIssueCmacReset;
u32 CmacResetbyFwCnt;
#if defined(ENABLE_DASH_PRINTER_SUPPORT)
struct completion fw_ack;
struct completion fw_req;
struct completion fw_host_ok;
#endif
//Dash-----------------
#endif //ENABLE_DASH_SUPPORT
//Realwow++++++++++++++ //Realwow++++++++++++++
u8 HwSuppKCPOffloadVer; u8 HwSuppKCPOffloadVer;
@@ -2757,7 +2731,6 @@ struct rtl8126_private {
u8 HwSuppPtpVer; u8 HwSuppPtpVer;
u8 EnablePtp; u8 EnablePtp;
u8 ptp_master_mode;
#ifdef ENABLE_PTP_SUPPORT #ifdef ENABLE_PTP_SUPPORT
u32 tx_hwtstamp_timeouts; u32 tx_hwtstamp_timeouts;
u32 tx_hwtstamp_skipped; u32 tx_hwtstamp_skipped;
@@ -2785,6 +2758,8 @@ struct rtl8126_private {
u8 HwSuppMacMcuVer; u8 HwSuppMacMcuVer;
u16 MacMcuPageSize; u16 MacMcuPageSize;
u64 hw_mcu_patch_code_ver;
u64 bin_mcu_patch_code_ver;
u8 HwSuppTcamVer; u8 HwSuppTcamVer;
@@ -2858,8 +2833,7 @@ enum eetype {
}; };
enum mcfg { enum mcfg {
CFG_METHOD_1=1, CFG_METHOD_2=2,
CFG_METHOD_2,
CFG_METHOD_3, CFG_METHOD_3,
CFG_METHOD_DEFAULT, CFG_METHOD_DEFAULT,
CFG_METHOD_MAX CFG_METHOD_MAX
@@ -2893,7 +2867,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 (0x0051) #define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0060)
//hwoptimize //hwoptimize
#define HW_PATCH_SOC_LAN (BIT_0) #define HW_PATCH_SOC_LAN (BIT_0)
@@ -2912,13 +2886,7 @@ void rtl8126_mac_ocp_write(struct rtl8126_private *tp, u16 reg_addr, u16 value);
u16 rtl8126_mac_ocp_read(struct rtl8126_private *tp, u16 reg_addr); u16 rtl8126_mac_ocp_read(struct rtl8126_private *tp, u16 reg_addr);
void rtl8126_clear_eth_phy_bit(struct rtl8126_private *tp, u8 addr, u16 mask); void rtl8126_clear_eth_phy_bit(struct rtl8126_private *tp, u8 addr, u16 mask);
void rtl8126_set_eth_phy_bit(struct rtl8126_private *tp, u8 addr, u16 mask); void rtl8126_set_eth_phy_bit(struct rtl8126_private *tp, u8 addr, u16 mask);
void rtl8126_ocp_write(struct rtl8126_private *tp, u16 addr, u8 len, u32 data);
void rtl8126_oob_notify(struct rtl8126_private *tp, u8 cmd);
void rtl8126_init_ring_indexes(struct rtl8126_private *tp); void rtl8126_init_ring_indexes(struct rtl8126_private *tp);
void rtl8126_oob_mutex_lock(struct rtl8126_private *tp);
u32 rtl8126_ocp_read(struct rtl8126_private *tp, u16 addr, u8 len);
u32 rtl8126_ocp_read_with_oob_base_address(struct rtl8126_private *tp, u16 addr, u8 len, u32 base_address);
u32 rtl8126_ocp_write_with_oob_base_address(struct rtl8126_private *tp, u16 addr, u8 len, u32 value, u32 base_address);
u32 rtl8126_eri_read(struct rtl8126_private *tp, int addr, int len, int type); u32 rtl8126_eri_read(struct rtl8126_private *tp, int addr, int len, int type);
u32 rtl8126_eri_read_with_oob_base_address(struct rtl8126_private *tp, int addr, int len, int type, u32 base_address); u32 rtl8126_eri_read_with_oob_base_address(struct rtl8126_private *tp, int addr, int len, int type, u32 base_address);
int rtl8126_eri_write(struct rtl8126_private *tp, int addr, int len, u32 value, int type); int rtl8126_eri_write(struct rtl8126_private *tp, int addr, int len, u32 value, int type);
@@ -2927,11 +2895,6 @@ u16 rtl8126_ephy_read(struct rtl8126_private *tp, int RegAddr);
void rtl8126_wait_txrx_fifo_empty(struct net_device *dev); void rtl8126_wait_txrx_fifo_empty(struct net_device *dev);
void rtl8126_enable_now_is_oob(struct rtl8126_private *tp); void rtl8126_enable_now_is_oob(struct rtl8126_private *tp);
void rtl8126_disable_now_is_oob(struct rtl8126_private *tp); void rtl8126_disable_now_is_oob(struct rtl8126_private *tp);
void rtl8126_oob_mutex_unlock(struct rtl8126_private *tp);
void rtl8126_dash2_disable_tx(struct rtl8126_private *tp);
void rtl8126_dash2_enable_tx(struct rtl8126_private *tp);
void rtl8126_dash2_disable_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); void rtl8126_mark_as_last_descriptor(struct rtl8126_private *tp, struct RxDesc *desc);
@@ -2978,7 +2941,7 @@ rtl8126_enable_hw_interrupt_v2(struct rtl8126_private *tp, u32 message_id)
int rtl8126_open(struct net_device *dev); int rtl8126_open(struct net_device *dev);
int rtl8126_close(struct net_device *dev); int rtl8126_close(struct net_device *dev);
void rtl8126_hw_config(struct net_device *dev); void rtl8126_hw_config(struct net_device *dev);
void rtl8126_hw_set_timer_int_8125(struct rtl8126_private *tp, u32 message_id, u8 timer_intmiti_val); void rtl8126_hw_set_timer_int(struct rtl8126_private *tp, u32 message_id, u8 timer_intmiti_val);
void rtl8126_set_rx_q_num(struct rtl8126_private *tp, unsigned int num_rx_queues); void rtl8126_set_rx_q_num(struct rtl8126_private *tp, unsigned int num_rx_queues);
void rtl8126_set_tx_q_num(struct rtl8126_private *tp, unsigned int num_tx_queues); void rtl8126_set_tx_q_num(struct rtl8126_private *tp, unsigned int num_tx_queues);
void rtl8126_enable_mcu(struct rtl8126_private *tp, bool enable); void rtl8126_enable_mcu(struct rtl8126_private *tp, bool enable);
@@ -2997,9 +2960,10 @@ void rtl8126_mdio_direct_write_phy_ocp(struct rtl8126_private *tp, u16 RegAddr,u
u32 rtl8126_mdio_direct_read_phy_ocp(struct rtl8126_private *tp, u16 RegAddr); 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_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_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_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); void rtl8126_clear_mac_ocp_bit(struct rtl8126_private *tp, u16 addr, u16 mask);
void rtl8126_set_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) { }

View File

@@ -1,261 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# 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, see <http://www.gnu.org/licenses/>.
#
# Author:
# Realtek NIC software team <nicfae@realtek.com>
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
#
################################################################################
*/
/************************************************************************************
* This product is covered by one or more of the following patents:
* US6,570,884, US6,115,776, and US6,327,625.
***********************************************************************************/
#ifndef _LINUX_R8126_DASH_H
#define _LINUX_R8126_DASH_H
#include <linux/if.h>
#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2
enum rtl_dash_cmd {
RTL_DASH_ARP_NS_OFFLOAD = 0,
RTL_DASH_SET_OOB_IPMAC,
RTL_DASH_NOTIFY_OOB,
RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW,
RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE,
RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA,
RTL_DASH_OOB_REQ,
RTL_DASH_OOB_ACK,
RTL_DASH_DETACH_OOB_REQ,
RTL_DASH_DETACH_OOB_ACK,
RTL_FW_SET_IPV4 = 0x10,
RTL_FW_GET_IPV4,
RTL_FW_SET_IPV6,
RTL_FW_GET_IPV6,
RTL_FW_SET_EXT_SNMP,
RTL_FW_GET_EXT_SNMP,
RTL_FW_SET_WAKEUP_PATTERN,
RTL_FW_GET_WAKEUP_PATTERN,
RTL_FW_DEL_WAKEUP_PATTERN,
RTLT_DASH_COMMAND_INVALID,
};
struct rtl_dash_ip_mac {
struct sockaddr ifru_addr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
};
struct rtl_dash_ioctl_struct {
__u32 cmd;
__u32 offset;
__u32 len;
union {
__u32 data;
void *data_buffer;
};
};
struct settings_ipv4 {
__u32 IPv4addr;
__u32 IPv4mask;
__u32 IPv4Gateway;
};
struct settings_ipv6 {
__u32 reserved;
__u32 prefixLen;
__u16 IPv6addr[8];
__u16 IPv6Gateway[8];
};
struct settings_ext_snmp {
__u16 index;
__u16 oid_get_len;
__u8 oid_for_get[24];
__u8 reserved0[26];
__u16 value_len;
__u8 value[256];
__u8 supported;
__u8 reserved1[27];
};
struct wakeup_pattern {
__u8 index;
__u8 valid;
__u8 start;
__u8 length;
__u8 name[36];
__u8 mask[16];
__u8 pattern[128];
__u32 reserved[2];
};
typedef struct _RX_DASH_FROM_FW_DESC {
u16 length;
u8 statusLowByte;
u8 statusHighByte;
u32 resv;
u64 BufferAddress;
}
RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC;
typedef struct _TX_DASH_SEND_FW_DESC {
u16 length;
u8 statusLowByte;
u8 statusHighByte;
u32 resv;
u64 BufferAddress;
}
TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC;
typedef struct _OSOOBHdr {
u32 len;
u8 type;
u8 flag;
u8 hostReqV;
u8 res;
}
OSOOBHdr, *POSOOBHdr;
typedef struct _RX_DASH_BUFFER_TYPE_2 {
OSOOBHdr oobhdr;
u8 RxDataBuffer[0];
}
RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2;
#define ALIGN_8 (0x7)
#define ALIGN_16 (0xf)
#define ALIGN_32 (0x1f)
#define ALIGN_64 (0x3f)
#define ALIGN_256 (0xff)
#define ALIGN_4096 (0xfff)
#define OCP_REG_CONFIG0 (0x10)
#define OCP_REG_CONFIG0_REV_F (0xB8)
#define OCP_REG_DASH_POLL (0x30)
#define OCP_REG_HOST_REQ (0x34)
#define OCP_REG_DASH_REQ (0x35)
#define OCP_REG_CR (0x36)
#define OCP_REG_DMEMSTA (0x38)
#define OCP_REG_GPHYAR (0x60)
#define OCP_REG_CONFIG0_DASHEN BIT_15
#define OCP_REG_CONFIG0_OOBRESET BIT_14
#define OCP_REG_CONFIG0_APRDY BIT_13
#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12
#define OCP_REG_CONFIG0_DRIVERRDY BIT_11
#define OCP_REG_CONFIG0_OOB_WDT BIT_9
#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8
#define OCP_REG_CONFIG0_TLSEN BIT_7
#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0)
#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_3(_M) ((_M)->HwSuppDashVer == 3)
#define RECV_FROM_FW_BUF_SIZE (1520)
#define SEND_TO_FW_BUF_SIZE (1520)
#define RX_DASH_FROM_FW_OWN BIT_15
#define TX_DASH_SEND_FW_OWN BIT_15
#define TX_DASH_SEND_FW_OWN_HIGHBYTE BIT_7
#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3)
#define TXS_EXC BIT_4
#define TXS_LNKF BIT_5
#define TXS_OWC BIT_6
#define TXS_TES BIT_7
#define TXS_UNF BIT_9
#define TXS_LGSEN BIT_11
#define TXS_LS BIT_12
#define TXS_FS BIT_13
#define TXS_EOR BIT_14
#define TXS_OWN BIT_15
#define TPPool_HRDY 0x20
#define HostReqReg (0xC0)
#define SystemMasterDescStartAddrLow (0xF0)
#define SystemMasterDescStartAddrHigh (0xF4)
#define SystemSlaveDescStartAddrLow (0xF8)
#define SystemSlaveDescStartAddrHigh (0xFC)
//DASH Request Type
#define WSMANREG 0x01
#define OSPUSHDATA 0x02
#define RXS_OWN BIT_15
#define RXS_EOR BIT_14
#define RXS_FS BIT_13
#define RXS_LS BIT_12
#define ISRIMR_DP_DASH_OK BIT_15
#define ISRIMR_DP_HOST_OK BIT_13
#define ISRIMR_DP_REQSYS_OK BIT_11
#define ISRIMR_DASH_INTR_EN BIT_12
#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15
#define ISRIMR_DASH_TYPE2_ROK BIT_0
#define ISRIMR_DASH_TYPE2_RDU BIT_1
#define ISRIMR_DASH_TYPE2_TOK BIT_2
#define ISRIMR_DASH_TYPE2_TDU BIT_3
#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4
#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5
#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6
#define CMAC_OOB_STOP 0x25
#define CMAC_OOB_INIT 0x26
#define CMAC_OOB_RESET 0x2a
#define NO_BASE_ADDRESS 0x00000000
#define RTL8168FP_OOBMAC_BASE 0xBAF70000
#define RTL8168FP_CMAC_IOBASE 0xBAF20000
#define RTL8168FP_KVM_BASE 0xBAF80400
#define CMAC_SYNC_REG 0x20
#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98
#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F
/* cmac write/read MMIO register */
#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg)))
int rtl8126_dash_ioctl(struct net_device *dev, struct ifreq *ifr);
void HandleDashInterrupt(struct net_device *dev);
int AllocateDashShareMemory(struct net_device *dev);
void FreeAllocatedDashShareMemory(struct net_device *dev);
void DashHwInit(struct net_device *dev);
#endif /* _LINUX_R8126_DASH_H */

View File

@@ -1,16 +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("Revanth Kumar Uppala <ruppala@nvidia.com>");
MODULE_DESCRIPTION("Dummy R8126 dummy driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,466 @@
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
#
# 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, see <http://www.gnu.org/licenses/>.
#
# Author:
# Realtek NIC software team <nicfae@realtek.com>
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
#
################################################################################
*/
/************************************************************************************
* This product is covered by one or more of the following patents:
* US6,570,884, US6,115,776, and US6,327,625.
***********************************************************************************/
#include <linux/version.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include "r8126.h"
#include "r8126_fiber.h"
static void
rtl8126_fiber_set_mdc_gpio_c45(struct rtl8126_private *tp, bool pu)
{
if (pu)
rtl8126_set_mac_ocp_bit(tp, 0xDC52, BIT_7);
else
rtl8126_clear_mac_ocp_bit(tp, 0xDC52, BIT_7);
//RtPciCommittp);
}
static void
rtl8126_fiber_set_mdc(struct rtl8126_private *tp, bool pu)
{
rtl8126_fiber_set_mdc_gpio_c45(tp, pu);
}
static void
rtl8126_fiber_set_mdcDownUp(struct rtl8126_private *tp)
{
udelay(1);
rtl8126_fiber_set_mdc(tp, 0);
udelay(1);
rtl8126_fiber_set_mdc(tp, 1);
}
static void
rtl8126_fiber_set_mdio_bit_gpio_c45(struct rtl8126_private *tp, bool pu)
{
if (pu)
rtl8126_set_mac_ocp_bit(tp, 0xDC52, BIT_2);
else
rtl8126_clear_mac_ocp_bit(tp, 0xDC52, BIT_2);
//RtPciCommittp);
rtl8126_fiber_set_mdcDownUp(tp);
}
static void
rtl8126_fiber_set_mdio_bit(struct rtl8126_private *tp, bool pu)
{
rtl8126_fiber_set_mdio_bit_gpio_c45(tp, pu);
}
static u16
rtl8126_fiber_get_mdio_bit_gpio_c45(struct rtl8126_private *tp)
{
rtl8126_fiber_set_mdcDownUp(tp);
return !!(rtl8126_mac_ocp_read(tp, 0xDC58) & BIT(2));
}
static u16
rtl8126_fiber_get_mdio_bit(struct rtl8126_private *tp)
{
return rtl8126_fiber_get_mdio_bit_gpio_c45(tp);
}
static void
rtl8126_fiber_shift_bit_in(struct rtl8126_private *tp, u32 val, int count)
{
int i;
for (i = (count - 1); i >= 0; i--)
rtl8126_fiber_set_mdio_bit(tp, !!(val & BIT(i)));
}
static u16
rtl8126_fiber_shift_bit_out(struct rtl8126_private *tp)
{
u16 data = 0;
int i;
for (i = 15; i >= 0; i--)
data += (rtl8126_fiber_get_mdio_bit(tp) << i);
return data;
}
static void
rtl8126_fiber_dir_gpio_c45(struct rtl8126_private *tp, bool output_mode)
{
if (output_mode)
rtl8126_set_mac_ocp_bit(tp, 0xDC4C, BIT_2);
else
rtl8126_clear_mac_ocp_bit(tp, 0xDC4C, BIT_2);
}
static void
rtl8126_fiber_dir(struct rtl8126_private *tp, bool output_mode)
{
rtl8126_fiber_dir_gpio_c45(tp, output_mode);
}
//fiber
#define R8126_FIBER_C22 (0)
#define R8126_FIBER_C45 (1)
// sfp opcodes
#define R8126_FIBER_ST (1)
#define R8126_FIBER_OP_W (1)
#define R8126_FIBER_OP_R (2)
#define R8126_FIBER_TA (2)
// sfp C45 opcodes
#define R8126_FIBER_MDIO_C45 (BIT(15))
#define R8126_FIBER_C45_ST (R8126_FIBER_MDIO_C45 | 0)
#define R8126_FIBER_C45_OP_ADDR (R8126_FIBER_MDIO_C45 | 0)
#define R8126_FIBER_C45_OP_W (R8126_FIBER_MDIO_C45 | 1)
#define R8126_FIBER_C45_OP_R (R8126_FIBER_MDIO_C45 | 3)
static void
rtl8126_fiber_cmd(struct rtl8126_private *tp, u32 cmd, u8 phy_addr,
u32 reg)
{
/* change to output mode */
rtl8126_fiber_dir(tp, 1);
/* preamble 32bit of 1 */
rtl8126_fiber_shift_bit_in(tp, UINT_MAX, 32);
/* start bit */
if (cmd & R8126_FIBER_MDIO_C45)
rtl8126_fiber_shift_bit_in(tp, R8126_FIBER_C45_ST, 2);
else
rtl8126_fiber_shift_bit_in(tp, R8126_FIBER_ST, 2);
/* opcode */
rtl8126_fiber_shift_bit_in(tp, cmd, 2);
/* phy address */
rtl8126_fiber_shift_bit_in(tp, phy_addr, 5);
/* phy reg */
rtl8126_fiber_shift_bit_in(tp, reg, 5);
}
static u8
rtl8126_fiber_cmdAddr(struct rtl8126_private *tp, u8 phy_addr, u32 reg)
{
u8 dev_addr = (reg >> 16) & 0x1F;
u16 addr = (u16)reg;
rtl8126_fiber_cmd(tp, R8126_FIBER_C45_OP_ADDR, phy_addr, dev_addr);
/* turn-around(TA) */
rtl8126_fiber_shift_bit_in(tp, R8126_FIBER_TA, 2);
rtl8126_fiber_shift_bit_in(tp, addr, 16);
rtl8126_fiber_dir(tp, 0);
rtl8126_fiber_get_mdio_bit(tp);
return dev_addr;
}
static void
rtl8126_fiber_reset_gpio_c45(struct rtl8126_private *tp)
{
rtl8126_set_mac_ocp_bit(tp, 0xDC4C, (BIT_7 | BIT_2));
/* init sfp interface */
rtl8126_clear_mac_ocp_bit(tp, 0xDC52, BIT_7);
rtl8126_set_mac_ocp_bit(tp, 0xDC52, BIT_2);
}
static void
rtl8126_fiber_write_common(struct rtl8126_private *tp, u16 val)
{
/* turn-around(TA) */
rtl8126_fiber_shift_bit_in(tp, R8126_FIBER_TA, 2);
/* write phy data */
rtl8126_fiber_shift_bit_in(tp, val, 16);
/* change to input mode */
rtl8126_fiber_dir(tp, 0);
rtl8126_fiber_get_mdio_bit(tp);
}
static void
rtl8126_fiber_mdio_write_gpio_c45(
struct rtl8126_private *tp,
u32 reg,
u16 val,
u8 phy_addr)
{
/* opcode write */
reg = rtl8126_fiber_cmdAddr(tp, phy_addr, reg);
rtl8126_fiber_cmd(tp, R8126_FIBER_C45_OP_W, phy_addr, reg);
rtl8126_fiber_write_common(tp, val);
}
static u16
rtl8126_fiber_read_common(struct rtl8126_private *tp)
{
u16 data = 0;
/* change to input mode */
rtl8126_fiber_dir(tp, 0);
/* TA 0 */
rtl8126_fiber_get_mdio_bit(tp);
/* read phy data */
data = rtl8126_fiber_shift_bit_out(tp);
rtl8126_fiber_get_mdio_bit(tp);
return data;
}
static u16
rtl8126_fiber_mdio_read_gpio_c45(
struct rtl8126_private *tp,
u32 reg,
u8 phy_addr)
{
reg = rtl8126_fiber_cmdAddr(tp, phy_addr, reg);
rtl8126_fiber_cmd(tp, R8126_FIBER_C45_OP_R, phy_addr, reg);
return rtl8126_fiber_read_common(tp);
}
void
rtl8126_fiber_mdio_write(
struct rtl8126_private *tp,
u32 reg,
u16 val)
{
switch(tp->HwFiberStat) {
case FIBER_STAT_CONNECT_GPO_C45:
return rtl8126_fiber_mdio_write_gpio_c45(tp, reg, val, 0);
default:
return;
}
}
u16
rtl8126_fiber_mdio_read(
struct rtl8126_private *tp,
u32 reg)
{
switch(tp->HwFiberStat) {
case FIBER_STAT_CONNECT_GPO_C45:
return rtl8126_fiber_mdio_read_gpio_c45(tp, reg, 0);
default:
return 0xffff;
}
}
static void
rtl8126_fiber_clear_and_set_phy_bit(struct rtl8126_private *tp, u32 addr, u16 clearmask, u16 setmask)
{
u16 PhyRegValue;
PhyRegValue = rtl8126_fiber_mdio_read(tp, addr);
PhyRegValue &= ~clearmask;
PhyRegValue |= setmask;
rtl8126_fiber_mdio_write(tp, addr, PhyRegValue);
}
static void
rtl8126_fiber_clear_phy_bit(struct rtl8126_private *tp, u32 addr, u16 mask)
{
rtl8126_fiber_clear_and_set_phy_bit(tp, addr, mask, 0);
}
static void
rtl8126_fiber_set_phy_bit(struct rtl8126_private *tp, u32 addr, u16 mask)
{
rtl8126_fiber_clear_and_set_phy_bit(tp, addr, 0, mask);
}
#define R8126_MAKE_C45_ADDR(_mmd, _addr) (_mmd << 16 | _addr)
static void
rtl8126_fiber_set_ra_8251b(struct rtl8126_private *tp)
{
struct pci_dev *pdev = tp->pci_dev;
u16 const svid = pdev->subsystem_vendor;
rtl8126_fiber_clear_and_set_phy_bit(tp,
R8126_MAKE_C45_ADDR(30, 0x6973),
0x00FF,
(svid == PCI_VENDOR_ID_DELL) ?
0x03 : 0x12);
rtl8126_fiber_clear_and_set_phy_bit(tp,
R8126_MAKE_C45_ADDR(30, 0x6974),
0x00FF,
0x0005);
rtl8126_fiber_clear_and_set_phy_bit(tp,
R8126_MAKE_C45_ADDR(30, 0x6975),
0x00FF,
0x0008);
}
static void
rtl8126_fiber_set_ra(struct rtl8126_private *tp)
{
switch (tp->HwFiberModeVer) {
case FIBER_MODE_RTL8126_RTL8251B:
rtl8126_fiber_set_ra_8251b(tp);
break;
}
}
static void
rtl8126_fiber_phy_reset_8251b(struct rtl8126_private *tp)
{
u16 PhyRegValue;
u32 Timeout;
rtl8126_fiber_set_phy_bit(tp, R8126_MAKE_C45_ADDR(0x01, 0x00), BIT_15);
Timeout = 0;
do {
udelay(1000);
PhyRegValue = rtl8126_fiber_mdio_read(tp, R8126_MAKE_C45_ADDR(0x01, 0x00));
Timeout++;
} while ((PhyRegValue & BIT_15) && (Timeout < 20));
}
static void
rtl8126_fiber_phy_reset(struct rtl8126_private *tp)
{
switch (tp->HwFiberModeVer) {
case FIBER_MODE_RTL8126_RTL8251B:
rtl8126_fiber_phy_reset_8251b(tp);
break;
}
}
static void
rtl8126_hw_rtl8251b_phy_config(struct rtl8126_private *tp)
{
rtl8126_fiber_reset_gpio_c45(tp);
rtl8126_fiber_set_ra(tp);
rtl8126_fiber_clear_phy_bit(tp, R8126_MAKE_C45_ADDR(0x07, 0x3C), (BIT_2 | BIT_1));
rtl8126_fiber_clear_phy_bit(tp, R8126_MAKE_C45_ADDR(0x07, 0x3E), (BIT_1 | BIT_0));
rtl8126_fiber_phy_reset(tp);
}
void
rtl8126_hw_fiber_phy_config(struct rtl8126_private *tp)
{
switch (tp->HwFiberModeVer) {
case FIBER_MODE_RTL8126_RTL8251B:
rtl8126_hw_rtl8251b_phy_config(tp);
break;
}
}
#define RTL8251B_PHY_ID_1 0x001C
#define RTL8251B_PHY_ID_2 0xC868
static u32
rtl8126_fiber_get_connect_status_8251b(struct rtl8126_private *tp)
{
int i;
int const checkcnt = 4;
rtl8126_fiber_reset_gpio_c45(tp);
for (i = 0; i < checkcnt; i++) {
if (RTL8251B_PHY_ID_1 != rtl8126_fiber_mdio_read_gpio_c45(tp, R8126_MAKE_C45_ADDR(0x01, 0x02), 0) ||
RTL8251B_PHY_ID_2 != rtl8126_fiber_mdio_read_gpio_c45(tp, R8126_MAKE_C45_ADDR(0x01, 0x03), 0))
return FIBER_STAT_DISCONNECT;
}
return FIBER_STAT_CONNECT_GPO_C45;
}
static u32
rtl8126_fiber_get_connect_status(struct rtl8126_private *tp)
{
switch (tp->HwFiberModeVer) {
case FIBER_MODE_RTL8126_RTL8251B:
return rtl8126_fiber_get_connect_status_8251b(tp);
default:
return FIBER_STAT_NOT_CHECKED;
}
}
void
rtl8126_check_fiber_mode_support(struct rtl8126_private *tp)
{
switch(tp->mcfg) {
case CFG_METHOD_3: {
u8 tmp = (u8)rtl8126_mac_ocp_read(tp, 0xD006);
if (tmp == 0x03)
tp->HwFiberModeVer = FIBER_MODE_RTL8126_RTL8251B;
}
break;
}
if (HW_FIBER_MODE_ENABLED(tp))
tp->HwFiberStat = rtl8126_fiber_get_connect_status(tp);
}
unsigned int
rtl8126_fiber_link_ok(struct net_device *dev)
{
struct rtl8126_private *tp = netdev_priv(dev);
u16 status;
switch (tp->HwFiberStat) {
case FIBER_STAT_CONNECT_GPO_C45:
status = rtl8126_fiber_mdio_read(tp, R8126_MAKE_C45_ADDR(30, 0x758D));
if (status != USHRT_MAX && status & BIT_1)
return 1;
else
return 0;
break;
default:
return 0;
}
}

View File

@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
#
# 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, see <http://www.gnu.org/licenses/>.
#
# Author:
# Realtek NIC software team <nicfae@realtek.com>
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
#
################################################################################
*/
/************************************************************************************
* This product is covered by one or more of the following patents:
* US6,570,884, US6,115,776, and US6,327,625.
***********************************************************************************/
#ifndef _LINUX_R8126_FIBER_H
#define _LINUX_R8126_FIBER_H
enum {
FIBER_MODE_NIC_ONLY = 0,
FIBER_MODE_RTL8126_RTL8251B,
FIBER_MODE_MAX
};
enum {
FIBER_STAT_NOT_CHECKED = 0,
FIBER_STAT_DISCONNECT,
FIBER_STAT_CONNECT_GPO_C45,
FIBER_STAT_MAX
};
#define HW_FIBER_MODE_ENABLED(_M) ((_M)->HwFiberModeVer > 0)
#define HW_FIBER_STATUS_CONNECTED(_M) (((_M)->HwFiberStat == FIBER_STAT_CONNECT_GPO_C45))
#define HW_FIBER_STATUS_DISCONNECTED(_M) ((_M)->HwFiberStat == FIBER_STAT_DISCONNECT)
struct rtl8126_private;
void rtl8126_hw_fiber_phy_config(struct rtl8126_private *tp);
void rtl8126_check_fiber_mode_support(struct rtl8126_private *tp);
void rtl8126_fiber_mdio_write( struct rtl8126_private *tp, u32 reg, u16 val);
u16 rtl8126_fiber_mdio_read(struct rtl8126_private *tp, u32 reg);
unsigned int rtl8126_fiber_link_ok(struct net_device *dev);
#endif /* _LINUX_R8126_FIBER_H */

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free

View File

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free
@@ -68,7 +68,7 @@ static int _rtl8126_phc_gettime(struct rtl8126_private *tp, struct timespec64 *t
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
//Direct Read //Direct Read
rtl8126_set_clkadj_mode(tp, DIRECT_READ); rtl8126_set_clkadj_mode(tp, DIRECT_READ);
@@ -91,7 +91,7 @@ static int _rtl8126_phc_gettime(struct rtl8126_private *tp, struct timespec64 *t
//S[15:0] E416[15:0] //S[15:0] E416[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_LO_8126); ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_LO_8126);
spin_unlock_irqrestore(&tp->phy_lock, flags); r8126_spin_unlock(&tp->phy_lock, flags);
return 0; return 0;
} }
@@ -100,7 +100,7 @@ static int _rtl8126_phc_settime(struct rtl8126_private *tp, const struct timespe
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
/* nanoseconds */ /* nanoseconds */
//Ns[15:0] E412[15:0] //Ns[15:0] E412[15:0]
@@ -119,7 +119,7 @@ static int _rtl8126_phc_settime(struct rtl8126_private *tp, const struct timespe
//Direct Write //Direct Write
rtl8126_set_clkadj_mode(tp, DIRECT_WRITE); rtl8126_set_clkadj_mode(tp, DIRECT_WRITE);
spin_unlock_irqrestore(&tp->phy_lock, flags); r8126_spin_unlock(&tp->phy_lock, flags);
return 0; return 0;
} }
@@ -149,7 +149,7 @@ static int _rtl8126_phc_adjtime(struct rtl8126_private *tp, s64 delta)
nsec &= 0x3fffffff; nsec &= 0x3fffffff;
sec &= 0x0000ffffffffffff; sec &= 0x0000ffffffffffff;
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
/* nanoseconds */ /* nanoseconds */
//Ns[15:0] E412[15:0] //Ns[15:0] E412[15:0]
@@ -170,7 +170,7 @@ static int _rtl8126_phc_adjtime(struct rtl8126_private *tp, s64 delta)
else else
rtl8126_set_clkadj_mode(tp, INCREMENT_STEP); rtl8126_set_clkadj_mode(tp, INCREMENT_STEP);
spin_unlock_irqrestore(&tp->phy_lock, flags); r8126_spin_unlock(&tp->phy_lock, flags);
return 0; return 0;
} }
@@ -207,7 +207,7 @@ static int _rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
} else } else
rate_value = ((u64)ppb << 32) / 1000000000; rate_value = ((u64)ppb << 32) / 1000000000;
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
/* nanoseconds */ /* nanoseconds */
//Ns[15:0] E412[15:0] //Ns[15:0] E412[15:0]
@@ -217,7 +217,7 @@ static int _rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
rtl8126_set_clkadj_mode(tp, RATE_WRITE); rtl8126_set_clkadj_mode(tp, RATE_WRITE);
spin_unlock_irqrestore(&tp->phy_lock, flags); r8126_spin_unlock(&tp->phy_lock, flags);
return 0; return 0;
} }
@@ -305,7 +305,7 @@ static void _rtl8126_phc_enable(struct ptp_clock_info *ptp,
rtl8126_clear_mac_ocp_bit(tp, 0xDC00, BIT_6); rtl8126_clear_mac_ocp_bit(tp, 0xDC00, BIT_6);
rtl8126_clear_mac_ocp_bit(tp, 0xDC20, BIT_1); rtl8126_clear_mac_ocp_bit(tp, 0xDC20, BIT_1);
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
/* Set periodic pulse 1pps */ /* Set periodic pulse 1pps */
/* E432[8:0] = 0x017d */ /* E432[8:0] = 0x017d */
@@ -324,7 +324,7 @@ static void _rtl8126_phc_enable(struct ptp_clock_info *ptp,
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE438, 0xbc20); rtl8126_mdio_direct_write_phy_ocp(tp, 0xE438, 0xbc20);
spin_unlock_irqrestore(&tp->phy_lock, flags); r8126_spin_unlock(&tp->phy_lock, flags);
/* start hrtimer */ /* start hrtimer */
hrtimer_start(&tp->pps_timer, 1000000000, HRTIMER_MODE_REL); hrtimer_start(&tp->pps_timer, 1000000000, HRTIMER_MODE_REL);
@@ -346,21 +346,23 @@ static int rtl8126_phc_enable(struct ptp_clock_info *ptp,
static void rtl8126_ptp_enable_config(struct rtl8126_private *tp) static void rtl8126_ptp_enable_config(struct rtl8126_private *tp)
{ {
u16 ptp_ctrl;
if (tp->syncE_en) if (tp->syncE_en)
rtl8126_set_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0); rtl8126_set_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
else else
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0); 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_CTL_TYPE_3 | BIT_12);
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CTL, ptp_ctrl);
rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15); rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15);
} }
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,11,0)
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)
#else
int rtl8126_get_ts_info(struct net_device *netdev,
struct kernel_ethtool_ts_info *info)
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,11,0) */
{ {
struct rtl8126_private *tp = netdev_priv(netdev); struct rtl8126_private *tp = netdev_priv(netdev);
@@ -431,17 +433,18 @@ static u16 rtl8126_ptp_get_tx_msgtype(struct rtl8126_private *tp)
switch (tx_ts_ready) { switch (tx_ts_ready) {
case TX_TS_PDLYRSP_RDY: case TX_TS_PDLYRSP_RDY:
return 3; return PTP_MSGTYPE_PDELAY_RESP;
case TX_TS_PDLYREQ_RDY: case TX_TS_PDLYREQ_RDY:
return 2; return PTP_MSGTYPE_PDELAY_REQ;
case TX_TS_DLYREQ_RDY: case TX_TS_DLYREQ_RDY:
return 1; return PTP_MSGTYPE_DELAY_REQ;
case TX_TS_SYNC_RDY: case TX_TS_SYNC_RDY:
default: default:
return 0; return PTP_MSGTYPE_SYNC;
} }
} }
/*
static u16 rtl8126_ptp_get_rx_msgtype(struct rtl8126_private *tp) static u16 rtl8126_ptp_get_rx_msgtype(struct rtl8126_private *tp)
{ {
u16 rx_ts_ready = 0; u16 rx_ts_ready = 0;
@@ -455,16 +458,17 @@ static u16 rtl8126_ptp_get_rx_msgtype(struct rtl8126_private *tp)
switch (rx_ts_ready) { switch (rx_ts_ready) {
case RX_TS_PDLYRSP_RDY: case RX_TS_PDLYRSP_RDY:
return 3; return PTP_MSGTYPE_PDELAY_RESP;
case RX_TS_PDLYREQ_RDY: case RX_TS_PDLYREQ_RDY:
return 2; return PTP_MSGTYPE_PDELAY_REQ;
case RX_TS_DLYREQ_RDY: case RX_TS_DLYREQ_RDY:
return 1; return PTP_MSGTYPE_DELAY_REQ;
case RX_TS_SYNC_RDY: case RX_TS_SYNC_RDY:
default: default:
return 0; return PTP_MSGTYPE_SYNC;
} }
} }
*/
static void rtl8126_wait_trx_ts_ready(struct rtl8126_private *tp) static void rtl8126_wait_trx_ts_ready(struct rtl8126_private *tp)
{ {
@@ -513,13 +517,20 @@ static void rtl8126_ptp_egresstime(struct rtl8126_private *tp, struct timespec64
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_LO); ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_LO);
} }
static void rtl8126_ptp_ingresstime(struct rtl8126_private *tp, struct timespec64 *ts64) static void rtl8126_ptp_ingresstime(struct rtl8126_private *tp, struct timespec64 *ts64, u8 type)
{ {
u16 msgtype; u16 msgtype;
msgtype = rtl8126_ptp_get_rx_msgtype(tp); switch (type) {
case PTP_MSGTYPE_PDELAY_RESP:
msgtype <<= 2; case PTP_MSGTYPE_PDELAY_REQ:
case PTP_MSGTYPE_DELAY_REQ:
case PTP_MSGTYPE_SYNC:
msgtype = type << 2;
break;
default:
return;
}
rtl8126_set_trx_ts_cmd(tp, (TRXTS_SEL | msgtype | BIT_4)); rtl8126_set_trx_ts_cmd(tp, (TRXTS_SEL | msgtype | BIT_4));
@@ -574,6 +585,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; unsigned long flags;
bool tx_intr;
if (!tp->ptp_tx_skb) if (!tp->ptp_tx_skb)
return; return;
@@ -587,18 +599,22 @@ 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
*/ */
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, TX_TX_INTR); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, TX_TX_INTR);
spin_unlock_irqrestore(&tp->phy_lock, flags); r8126_spin_unlock(&tp->phy_lock, flags);
return; return;
} }
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
if (rtl8126_mdio_direct_read_phy_ocp(tp, PTP_INSR) & TX_TX_INTR) { if (rtl8126_mdio_direct_read_phy_ocp(tp, PTP_INSR) & TX_TX_INTR) {
tx_intr = true;
rtl8126_ptp_tx_hwtstamp(tp); rtl8126_ptp_tx_hwtstamp(tp);
spin_unlock_irqrestore(&tp->phy_lock, flags);
} else { } else {
spin_unlock_irqrestore(&tp->phy_lock, flags); tx_intr = false;
}
r8126_spin_unlock(&tp->phy_lock, flags);
if (!tx_intr) {
/* reschedule to check later */ /* reschedule to check later */
schedule_work(&tp->ptp_tx_work); schedule_work(&tp->ptp_tx_work);
} }
@@ -608,7 +624,7 @@ static int rtl8126_hwtstamp_enable(struct rtl8126_private *tp, bool enable)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
if (enable) { if (enable) {
//trx timestamp interrupt enable //trx timestamp interrupt enable
@@ -634,7 +650,7 @@ static int rtl8126_hwtstamp_enable(struct rtl8126_private *tp, bool enable)
rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15); rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15);
} }
spin_unlock_irqrestore(&tp->phy_lock, flags); r8126_spin_unlock(&tp->phy_lock, flags);
return 0; return 0;
} }
@@ -687,7 +703,7 @@ rtl8126_hrtimer_for_pps(struct hrtimer *timer) {
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
//Direct Read //Direct Read
rtl8126_set_clkadj_mode(tp, DIRECT_READ); rtl8126_set_clkadj_mode(tp, DIRECT_READ);
@@ -706,7 +722,7 @@ rtl8126_hrtimer_for_pps(struct hrtimer *timer) {
//Periodic Tai start //Periodic Tai start
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_CFG, tai_cfg); rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_CFG, tai_cfg);
spin_unlock_irqrestore(&tp->phy_lock, flags); r8126_spin_unlock(&tp->phy_lock, flags);
hrtimer_forward_now(&tp->pps_timer, 1000000000); //rekick hrtimer_forward_now(&tp->pps_timer, 1000000000); //rekick
return HRTIMER_RESTART; return HRTIMER_RESTART;
@@ -868,25 +884,71 @@ 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) static void rtl8126_rx_ptp_pktstamp(struct rtl8126_private *tp, struct sk_buff *skb, u8 type)
{ {
struct timespec64 ts64; struct timespec64 ts64;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags); r8126_spin_lock(&tp->phy_lock, flags);
if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_INSR) & RX_TS_INTR)) { rtl8126_ptp_ingresstime(tp, &ts64, type);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return;
}
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, RX_TS_INTR); r8126_spin_unlock(&tp->phy_lock, flags);
rtl8126_ptp_ingresstime(tp, &ts64);
spin_unlock_irqrestore(&tp->phy_lock, flags);
skb_hwtstamps(skb)->hwtstamp = ktime_set(ts64.tv_sec, ts64.tv_nsec); skb_hwtstamps(skb)->hwtstamp = ktime_set(ts64.tv_sec, ts64.tv_nsec);
return; return;
} }
void rtl8126_rx_ptp_timestamp(struct rtl8126_private *tp, struct sk_buff *skb)
{
unsigned int ptp_class;
struct ptp_header *hdr;
u8 msgtype;
ptp_class = ptp_classify_raw(skb);
if (ptp_class == PTP_CLASS_NONE)
return;
skb_reset_mac_header(skb);
hdr = ptp_parse_header(skb, ptp_class);
if (unlikely(!hdr))
return;
msgtype = ptp_get_msgtype(hdr, ptp_class);
rtl8126_rx_ptp_pktstamp(tp, skb, msgtype);
return;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
struct ptp_header *ptp_parse_header(struct sk_buff *skb, unsigned int type)
{
u8 *ptr = skb_mac_header(skb);
if (type & PTP_CLASS_VLAN)
//ptr += VLAN_HLEN;
ptr += 4;
switch (type & PTP_CLASS_PMASK) {
case PTP_CLASS_IPV4:
ptr += IPV4_HLEN(ptr) + UDP_HLEN;
break;
case PTP_CLASS_IPV6:
ptr += IP6_HLEN + UDP_HLEN;
break;
case PTP_CLASS_L2:
break;
default:
return NULL;
}
ptr += ETH_HLEN;
/* Ensure that the entire header is present in this packet. */
if (ptr + sizeof(struct ptp_header) > skb->data + skb->len)
return NULL;
return (struct ptp_header *)ptr;
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) */

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free
@@ -41,6 +41,23 @@
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
#include <linux/ptp_classify.h> #include <linux/ptp_classify.h>
#ifndef PTP_CLASS_NONE
#define PTP_CLASS_NONE 0x00
#endif
#ifndef PTP_MSGTYPE_SYNC
#define PTP_MSGTYPE_SYNC 0x0
#endif
#ifndef PTP_MSGTYPE_DELAY_REQ
#define PTP_MSGTYPE_DELAY_REQ 0x1
#endif
#ifndef PTP_MSGTYPE_PDELAY_REQ
#define PTP_MSGTYPE_PDELAY_REQ 0x2
#endif
#ifndef PTP_MSGTYPE_PDELAY_RESP
#define PTP_MSGTYPE_PDELAY_RESP 0x3
#endif
struct rtl8126_ptp_info { struct rtl8126_ptp_info {
s64 time_sec; s64 time_sec;
u32 time_ns; u32 time_ns;
@@ -93,11 +110,88 @@ enum PTP_TRX_TS_STA_REG {
TX_TS_SYNC_RDY = (1 << 15), TX_TS_SYNC_RDY = (1 << 15),
}; };
#define PTP_CTL_TYPE_0 (0xF3F)
#define PTP_CTL_TYPE_1 (0x2FF)
#define PTP_CTL_TYPE_2 (0x0FF)
#define PTP_CTL_TYPE_3 (0x03F)
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
struct clock_identity {
u8 id[8];
} __packed;
struct port_identity {
struct clock_identity clock_identity;
__be16 port_number;
} __packed;
struct ptp_header {
u8 tsmt; /* transportSpecific | messageType */
u8 ver; /* reserved | versionPTP */
__be16 message_length;
u8 domain_number;
u8 reserved1;
u8 flag_field[2];
__be64 correction;
__be32 reserved2;
struct port_identity source_port_identity;
__be16 sequence_id;
u8 control;
u8 log_message_interval;
} __packed;
/**
* ptp_parse_header - Get pointer to the PTP v2 header
* @skb: packet buffer
* @type: type of the packet (see ptp_classify_raw())
*
* This function takes care of the VLAN, UDP, IPv4 and IPv6 headers. The length
* is checked.
*
* Note, internally skb_mac_header() is used. Make sure that the @skb is
* initialized accordingly.
*
* Return: Pointer to the ptp v2 header or NULL if not found
*/
struct ptp_header *ptp_parse_header(struct sk_buff *skb, unsigned int type);
/**
* ptp_get_msgtype - Extract ptp message type from given header
* @hdr: ptp header
* @type: type of the packet (see ptp_classify_raw())
*
* This function returns the message type for a given ptp header. It takes care
* of the different ptp header versions (v1 or v2).
*
* Return: The message type
*/
static inline u8 ptp_get_msgtype(const struct ptp_header *hdr,
unsigned int type)
{
u8 msgtype;
if (unlikely(type & PTP_CLASS_V1)) {
/* msg type is located at the control field for ptp v1 */
msgtype = hdr->control;
} else {
msgtype = hdr->tsmt & 0x0f;
}
return msgtype;
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) */
struct rtl8126_private; struct rtl8126_private;
struct RxDescV3; struct RxDescV3;
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,11,0)
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);
#else
int rtl8126_get_ts_info(struct net_device *netdev,
struct kernel_ethtool_ts_info *info);
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,11,0) */
void rtl8126_ptp_reset(struct rtl8126_private *tp); void rtl8126_ptp_reset(struct rtl8126_private *tp);
void rtl8126_ptp_init(struct rtl8126_private *tp); void rtl8126_ptp_init(struct rtl8126_private *tp);
@@ -106,7 +200,7 @@ 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_timestamp(struct rtl8126_private *tp, struct sk_buff *skb);
void rtl8126_set_local_time(struct rtl8126_private *tp); void rtl8126_set_local_time(struct rtl8126_private *tp);

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free
@@ -91,8 +91,6 @@ int rtl8126_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
struct rtl8126_private *tp = netdev_priv(dev); struct rtl8126_private *tp = netdev_priv(dev);
int ret = -EOPNOTSUPP; int ret = -EOPNOTSUPP;
netif_info(tp, drv, tp->dev, "rss get rxnfc\n");
if (!(dev->features & NETIF_F_RXHASH)) if (!(dev->features & NETIF_F_RXHASH))
return ret; return ret;
@@ -159,8 +157,6 @@ static int rtl8126_set_rss_hash_opt(struct rtl8126_private *tp,
{ {
u32 rss_flags = tp->rss_flags; u32 rss_flags = tp->rss_flags;
netif_info(tp, drv, tp->dev, "rss set hash\n");
/* /*
* RSS does not support anything other than hashing * RSS does not support anything other than hashing
* to queues on src and dst IPs and ports * to queues on src and dst IPs and ports
@@ -271,8 +267,6 @@ int rtl8126_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
struct rtl8126_private *tp = netdev_priv(dev); struct rtl8126_private *tp = netdev_priv(dev);
int ret = -EOPNOTSUPP; int ret = -EOPNOTSUPP;
netif_info(tp, drv, tp->dev, "rss set rxnfc\n");
if (!(dev->features & NETIF_F_RXHASH)) if (!(dev->features & NETIF_F_RXHASH))
return ret; return ret;
@@ -296,8 +290,6 @@ u32 rtl8126_get_rxfh_key_size(struct net_device *dev)
{ {
struct rtl8126_private *tp = netdev_priv(dev); struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get key size\n");
if (!(dev->features & NETIF_F_RXHASH)) if (!(dev->features & NETIF_F_RXHASH))
return 0; return 0;
@@ -308,8 +300,6 @@ u32 rtl8126_rss_indir_size(struct net_device *dev)
{ {
struct rtl8126_private *tp = netdev_priv(dev); struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get indir tbl size\n");
if (!(dev->features & NETIF_F_RXHASH)) if (!(dev->features & NETIF_F_RXHASH))
return 0; return 0;
@@ -369,8 +359,6 @@ int rtl8126_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
{ {
struct rtl8126_private *tp = netdev_priv(dev); struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
if (!(dev->features & NETIF_F_RXHASH)) if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP; return -EOPNOTSUPP;
@@ -392,8 +380,6 @@ int rtl8126_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
int i; int i;
u32 reta_entries = rtl8126_rss_indir_tbl_entries(tp); 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 /* We require at least one supported parameter to be changed and no
* change in any of the unsupported parameters * change in any of the unsupported parameters
*/ */
@@ -429,8 +415,6 @@ int rtl8126_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
{ {
struct rtl8126_private *tp = netdev_priv(dev); struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
if (!(dev->features & NETIF_F_RXHASH)) if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP; return -EOPNOTSUPP;
@@ -453,8 +437,6 @@ int rtl8126_set_rxfh(struct net_device *dev, const u32 *indir,
int i; int i;
u32 reta_entries = rtl8126_rss_indir_tbl_entries(tp); 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 /* We require at least one supported parameter to be changed and no
* change in any of the unsupported parameters * change in any of the unsupported parameters
*/ */

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free
@@ -47,6 +47,7 @@
int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr) int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
{ {
struct rtltool_cmd my_cmd; struct rtltool_cmd my_cmd;
unsigned long flags;
int ret; int ret;
if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd)))
@@ -55,6 +56,11 @@ int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
ret = 0; ret = 0;
switch (my_cmd.cmd) { switch (my_cmd.cmd) {
case RTLTOOL_READ_MAC: case RTLTOOL_READ_MAC:
if ((my_cmd.offset + my_cmd.len) > pci_resource_len(tp->pci_dev, 2)) {
ret = -EINVAL;
break;
}
if (my_cmd.len==1) if (my_cmd.len==1)
my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); my_cmd.data = readb(tp->mmio_addr+my_cmd.offset);
else if (my_cmd.len==2) else if (my_cmd.len==2)
@@ -73,6 +79,11 @@ int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
break; break;
case RTLTOOL_WRITE_MAC: case RTLTOOL_WRITE_MAC:
if ((my_cmd.offset + my_cmd.len) > pci_resource_len(tp->pci_dev, 2)) {
ret = -EINVAL;
break;
}
if (my_cmd.len==1) if (my_cmd.len==1)
writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset);
else if (my_cmd.len==2) else if (my_cmd.len==2)
@@ -87,7 +98,9 @@ int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
break; break;
case RTLTOOL_READ_PHY: case RTLTOOL_READ_PHY:
r8126_spin_lock(&tp->phy_lock, flags);
my_cmd.data = rtl8126_mdio_prot_read(tp, my_cmd.offset); my_cmd.data = rtl8126_mdio_prot_read(tp, my_cmd.offset);
r8126_spin_unlock(&tp->phy_lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT; ret = -EFAULT;
break; break;
@@ -96,7 +109,9 @@ int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
break; break;
case RTLTOOL_WRITE_PHY: case RTLTOOL_WRITE_PHY:
r8126_spin_lock(&tp->phy_lock, flags);
rtl8126_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); rtl8126_mdio_prot_write(tp, my_cmd.offset, my_cmd.data);
r8126_spin_unlock(&tp->phy_lock, flags);
break; break;
case RTLTOOL_READ_EPHY: case RTLTOOL_READ_EPHY:
@@ -189,33 +204,18 @@ int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
rtl8126_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); rtl8126_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data);
break; break;
case RTL_READ_OOB_MAC:
rtl8126_oob_mutex_lock(tp);
my_cmd.data = rtl8126_ocp_read(tp, my_cmd.offset, 4);
rtl8126_oob_mutex_unlock(tp);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTL_WRITE_OOB_MAC:
if (my_cmd.len == 0 || my_cmd.len > 4)
return -EOPNOTSUPP;
rtl8126_oob_mutex_lock(tp);
rtl8126_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data);
rtl8126_oob_mutex_unlock(tp);
break;
case RTL_ENABLE_PCI_DIAG: case RTL_ENABLE_PCI_DIAG:
r8126_spin_lock(&tp->phy_lock, flags);
tp->rtk_enable_diag = 1; tp->rtk_enable_diag = 1;
r8126_spin_unlock(&tp->phy_lock, flags);
dprintk("enable rtk diag\n"); dprintk("enable rtk diag\n");
break; break;
case RTL_DISABLE_PCI_DIAG: case RTL_DISABLE_PCI_DIAG:
r8126_spin_lock(&tp->phy_lock, flags);
tp->rtk_enable_diag = 0; tp->rtk_enable_diag = 0;
r8126_spin_unlock(&tp->phy_lock, flags);
dprintk("disable rtk diag\n"); dprintk("disable rtk diag\n");
break; break;
@@ -239,7 +239,9 @@ int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
break; break;
case RTL_DIRECT_READ_PHY_OCP: case RTL_DIRECT_READ_PHY_OCP:
r8126_spin_lock(&tp->phy_lock, flags);
my_cmd.data = rtl8126_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); my_cmd.data = rtl8126_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset);
r8126_spin_unlock(&tp->phy_lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT; ret = -EFAULT;
break; break;
@@ -248,9 +250,40 @@ int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
break; break;
case RTL_DIRECT_WRITE_PHY_OCP: case RTL_DIRECT_WRITE_PHY_OCP:
r8126_spin_lock(&tp->phy_lock, flags);
rtl8126_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); rtl8126_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data);
r8126_spin_unlock(&tp->phy_lock, flags);
break; break;
#ifdef ENABLE_FIBER_SUPPORT
case RTL_READ_FIBER_PHY:
if (!HW_FIBER_STATUS_CONNECTED(tp)) {
ret = -EOPNOTSUPP;
break;
}
r8126_spin_lock(&tp->phy_lock, flags);
my_cmd.data = rtl8126_fiber_mdio_read(tp, my_cmd.offset);
r8126_spin_unlock(&tp->phy_lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTL_WRITE_FIBER_PHY:
if (!HW_FIBER_STATUS_CONNECTED(tp)) {
ret = -EOPNOTSUPP;
break;
}
r8126_spin_lock(&tp->phy_lock, flags);
rtl8126_fiber_mdio_write(tp, my_cmd.offset, my_cmd.data);
r8126_spin_unlock(&tp->phy_lock, flags);
break;
#endif /* ENABLE_FIBER_SUPPORT */
default: default:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
break; break;

View File

@@ -5,7 +5,7 @@
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet # r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
# controllers with PCI-Express interface. # controllers with PCI-Express interface.
# #
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved. # Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License as published by the Free
@@ -63,6 +63,9 @@ enum rtl_cmd {
RTL_DIRECT_READ_PHY_OCP, RTL_DIRECT_READ_PHY_OCP,
RTL_DIRECT_WRITE_PHY_OCP, RTL_DIRECT_WRITE_PHY_OCP,
RTL_READ_FIBER_PHY,
RTL_WRITE_FIBER_PHY,
RTLTOOL_INVALID RTLTOOL_INVALID
}; };