mirror of
				https://github.com/Ysurac/openmptcprouter-feeds.git
				synced 2025-03-09 15:40:03 +00:00 
			
		
		
		
	Add r8125 driver
This commit is contained in:
		
							parent
							
								
									d9b5b9991c
								
							
						
					
					
						commit
						4a33826a28
					
				
					 17 changed files with 20659 additions and 0 deletions
				
			
		
							
								
								
									
										45
									
								
								r8125/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								r8125/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| # Attribution: https://gist.github.com/lenew/9b41ba901c3393047ede0766760f9d55
 | ||||
| 
 | ||||
| #Put this source to 'package/lean/r8125' folder of OpenWRT/LEDE SDK
 | ||||
| #Build(make menuconfig, make defconfig, make)
 | ||||
| 
 | ||||
| include $(TOPDIR)/rules.mk | ||||
| include $(INCLUDE_DIR)/kernel.mk | ||||
| 
 | ||||
| PKG_NAME:=r8125 | ||||
| PKG_VERSION:=9.006.04 | ||||
| PKG_RELEASE:=$(AUTORELEASE) | ||||
| 
 | ||||
| PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) | ||||
| 
 | ||||
| include $(INCLUDE_DIR)/package.mk | ||||
| 
 | ||||
| define KernelPackage/r8125 | ||||
|   TITLE:=Driver for Realtek r8125 chipsets | ||||
|   SUBMENU:=Network Devices | ||||
|   VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) | ||||
|   FILES:= $(PKG_BUILD_DIR)/r8125.ko | ||||
|   AUTOLOAD:=$(call AutoProbe,r8125) | ||||
| endef | ||||
| 
 | ||||
| define Package/r8125/description | ||||
|   This package contains a driver for Realtek r8125 chipsets. | ||||
| endef | ||||
| 
 | ||||
| R8125_MAKEOPTS= -C $(PKG_BUILD_DIR) \
 | ||||
| 	PATH="$(TARGET_PATH)" \
 | ||||
| 	ARCH="$(LINUX_KARCH)" \
 | ||||
| 	CROSS_COMPILE="$(TARGET_CROSS)" \
 | ||||
| 	TARGET="$(HAL_TARGET)" \
 | ||||
| 	TOOLPREFIX="$(KERNEL_CROSS)" \
 | ||||
| 	TOOLPATH="$(KERNEL_CROSS)" \
 | ||||
| 	KERNELPATH="$(LINUX_DIR)" \
 | ||||
| 	KERNELDIR="$(LINUX_DIR)" \
 | ||||
| 	LDOPTS=" " \
 | ||||
| 	DOMULTI=1 | ||||
| 
 | ||||
| define Build/Compile | ||||
| 	$(MAKE) $(R8125_MAKEOPTS) modules | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call KernelPackage,r8125)) | ||||
							
								
								
									
										197
									
								
								r8125/src/Makefile
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										197
									
								
								r8125/src/Makefile
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,197 @@ | |||
| # SPDX-License-Identifier: GPL-2.0-only
 | ||||
| ################################################################################
 | ||||
| #
 | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
 | ||||
| # controllers with PCI-Express interface.
 | ||||
| #
 | ||||
| # Copyright(c) 2021 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.
 | ||||
| ################################################################################
 | ||||
| 
 | ||||
| CONFIG_SOC_LAN = n | ||||
| ENABLE_REALWOW_SUPPORT = n | ||||
| ENABLE_DASH_SUPPORT = n | ||||
| ENABLE_DASH_PRINTER_SUPPORT = n | ||||
| CONFIG_DOWN_SPEED_100 = n | ||||
| CONFIG_ASPM = y | ||||
| ENABLE_S5WOL = y | ||||
| ENABLE_S5_KEEP_CURR_MAC = n | ||||
| ENABLE_EEE = y | ||||
| ENABLE_S0_MAGIC_PACKET = n | ||||
| ENABLE_TX_NO_CLOSE = y | ||||
| ENABLE_MULTIPLE_TX_QUEUE = n | ||||
| ENABLE_PTP_SUPPORT = n | ||||
| ENABLE_PTP_MASTER_MODE = n | ||||
| ENABLE_RSS_SUPPORT = y | ||||
| ENABLE_LIB_SUPPORT = n | ||||
| ENABLE_USE_FIRMWARE_FILE = n | ||||
| DISABLE_PM_SUPPORT = n | ||||
| DISABLE_MULTI_MSIX_VECTOR = n | ||||
| 
 | ||||
| ifneq ($(KERNELRELEASE),) | ||||
| 	obj-m := r8125.o | ||||
| 	r8125-objs := r8125_n.o rtl_eeprom.o rtltool.o | ||||
| 	ifeq ($(CONFIG_SOC_LAN), y) | ||||
| 		EXTRA_CFLAGS += -DCONFIG_SOC_LAN | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_REALWOW_SUPPORT), y) | ||||
| 		r8125-objs += r8125_realwow.o | ||||
| 		EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_DASH_SUPPORT), y) | ||||
| 		r8125-objs += r8125_dash.o | ||||
| 		EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y) | ||||
| 		r8125-objs += r8125_dash.o | ||||
| 		EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT | ||||
| 	endif | ||||
| 	EXTRA_CFLAGS += -DCONFIG_R8125_NAPI | ||||
| 	EXTRA_CFLAGS += -DCONFIG_R8125_VLAN | ||||
| 	ifeq ($(CONFIG_DOWN_SPEED_100), y) | ||||
| 		EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100 | ||||
| 	endif | ||||
| 	ifeq ($(CONFIG_ASPM), y) | ||||
| 		EXTRA_CFLAGS += -DCONFIG_ASPM | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_S5WOL), y) | ||||
| 		EXTRA_CFLAGS += -DENABLE_S5WOL | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y) | ||||
| 		EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_EEE), y) | ||||
| 		EXTRA_CFLAGS += -DENABLE_EEE | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_S0_MAGIC_PACKET), y) | ||||
| 		EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_TX_NO_CLOSE), y) | ||||
| 		EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_MULTIPLE_TX_QUEUE), y) | ||||
| 		EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_PTP_SUPPORT), y) | ||||
| 		r8125-objs += r8125_ptp.o | ||||
| 		EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_PTP_MASTER_MODE), y) | ||||
| 		EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_RSS_SUPPORT), y) | ||||
| 		r8125-objs += r8125_rss.o | ||||
| 		EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_LIB_SUPPORT), y) | ||||
| 		r8125-objs += r8125_lib.o | ||||
| 		EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT | ||||
| 	endif | ||||
| 	ifeq ($(ENABLE_USE_FIRMWARE_FILE), y) | ||||
| 		r8125-objs += r8125_firmware.o | ||||
| 		EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE | ||||
| 	endif | ||||
| 	ifeq ($(DISABLE_PM_SUPPORT), y) | ||||
| 		EXTRA_CFLAGS += -DDISABLE_PM_SUPPORT | ||||
| 	endif | ||||
| 	ifeq ($(DISABLE_MULTI_MSIX_VECTOR), y) | ||||
| 		EXTRA_CFLAGS += -DDISABLE_MULTI_MSIX_VECTOR | ||||
| 	endif | ||||
| else | ||||
| 	BASEDIR := /lib/modules/$(shell uname -r) | ||||
| 	KERNELDIR ?= $(BASEDIR)/build | ||||
| 	PWD :=$(shell pwd) | ||||
| 	DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net/ethernet -name realtek -type d) | ||||
| 	ifeq ($(DRIVERDIR),) | ||||
| 		DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net -name realtek -type d) | ||||
| 	endif | ||||
| 	ifeq ($(DRIVERDIR),) | ||||
| 		DRIVERDIR := $(BASEDIR)/kernel/drivers/net | ||||
| 	endif | ||||
| 	RTKDIR := $(subst $(BASEDIR)/,,$(DRIVERDIR)) | ||||
| 
 | ||||
| 	KERNEL_GCC_VERSION := $(shell cat /proc/version | sed -n 's/.*gcc version \([[:digit:]]\.[[:digit:]]\.[[:digit:]]\).*/\1/p') | ||||
| 	CCVERSION = $(shell $(CC) -dumpversion) | ||||
| 
 | ||||
| 	KVER = $(shell uname -r) | ||||
| 	KMAJ = $(shell echo $(KVER) | \
 | ||||
| 	sed -e 's/^\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*.*/\1/') | ||||
| 	KMIN = $(shell echo $(KVER) | \
 | ||||
| 	sed -e 's/^[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*.*/\1/') | ||||
| 	KREV = $(shell echo $(KVER) | \
 | ||||
| 	sed -e 's/^[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/') | ||||
| 
 | ||||
| 	kver_ge = $(shell \
 | ||||
| 	echo test | awk '{if($(KMAJ) < $(1)) {print 0} else { \
 | ||||
| 	if($(KMAJ) > $(1)) {print 1} else { \
 | ||||
| 	if($(KMIN) < $(2)) {print 0} else { \
 | ||||
| 	if($(KMIN) > $(2)) {print 1} else { \
 | ||||
| 	if($(KREV) < $(3)) {print 0} else { print 1 } \
 | ||||
| 	}}}}}' \
 | ||||
| 	) | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: print_vars clean modules install | ||||
| 
 | ||||
| print_vars: | ||||
| 	@echo | ||||
| 	@echo "CC: " $(CC) | ||||
| 	@echo "CCVERSION: " $(CCVERSION) | ||||
| 	@echo "KERNEL_GCC_VERSION: " $(KERNEL_GCC_VERSION) | ||||
| 	@echo "KVER: " $(KVER) | ||||
| 	@echo "KMAJ: " $(KMAJ) | ||||
| 	@echo "KMIN: " $(KMIN) | ||||
| 	@echo "KREV: " $(KREV) | ||||
| 	@echo "BASEDIR: " $(BASEDIR) | ||||
| 	@echo "DRIVERDIR: " $(DRIVERDIR) | ||||
| 	@echo "PWD: " $(PWD) | ||||
| 	@echo "RTKDIR: " $(RTKDIR) | ||||
| 	@echo | ||||
| 
 | ||||
| .PHONY:modules | ||||
| modules: | ||||
| #ifeq ($(call kver_ge,5,0,0),1)
 | ||||
| 	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules | ||||
| #else
 | ||||
| #	$(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
 | ||||
| #endif
 | ||||
| 
 | ||||
| .PHONY:clean | ||||
| clean: | ||||
| #ifeq ($(call kver_ge,5,0,0),1)
 | ||||
| 	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean | ||||
| #else
 | ||||
| #	$(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) clean
 | ||||
| #endif
 | ||||
| 
 | ||||
| .PHONY:install | ||||
| install: | ||||
| #ifeq ($(call kver_ge,5,0,0),1)
 | ||||
| 	$(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install | ||||
| #else
 | ||||
| #	$(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install
 | ||||
| #endif
 | ||||
| 
 | ||||
| endif | ||||
							
								
								
									
										75
									
								
								r8125/src/Makefile_linux24x
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										75
									
								
								r8125/src/Makefile_linux24x
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| # SPDX-License-Identifier: GPL-2.0-only | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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. | ||||
| ################################################################################ | ||||
| 
 | ||||
| CC		:= gcc | ||||
| LD		:= ld | ||||
| ARCH		:= $(shell uname -m | sed 's/i.86/i386/') | ||||
| KSRC		:= /lib/modules/$(shell uname -r)/build | ||||
| CONFIG_FILE	:= $(KSRC)/include/linux/autoconf.h | ||||
| KMISC		:= /lib/modules/$(shell uname -r)/kernel/drivers/net/ | ||||
| 
 | ||||
| 
 | ||||
| ifeq ($(ARCH),x86_64) | ||||
|    MODCFLAGS	+= -mcmodel=kernel -mno-red-zone | ||||
| endif | ||||
| 
 | ||||
| #standard flags for module builds | ||||
| MODCFLAGS	+= -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall | ||||
| MODCFLAGS	+= -I$(KSRC)/include -I. | ||||
| MODCFLAGS	+= -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h | ||||
| SOURCE		:= r8125_n.c rtl_eeprom.c rtltool.c | ||||
| OBJS		:= $(SOURCE:.c=.o) | ||||
| 
 | ||||
| 
 | ||||
| SMP		:= $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \ | ||||
|    grep CONFIG_SMP | awk '{print $$3}') | ||||
| 
 | ||||
| ifneq ($(SMP),1) | ||||
|    SMP		:= 0 | ||||
| endif | ||||
| 
 | ||||
| ifeq ($(SMP),1) | ||||
|    MODCFLAGS	+= -D__SMP__ | ||||
| endif | ||||
| 
 | ||||
| modules: $(OBJS) | ||||
| 	$(LD) -r $^ -o r8125.o | ||||
| 	strip --strip-debug r8125.o | ||||
| 
 | ||||
| %.o: %.c | ||||
| 	$(CC) $(MODCFLAGS) -c $< -o $@ | ||||
| 
 | ||||
| clean: | ||||
| 	rm *.o -f | ||||
| 
 | ||||
| install: | ||||
| 	install -m 744 -c r8125.o $(KMISC) | ||||
							
								
								
									
										2508
									
								
								r8125/src/r8125.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										2508
									
								
								r8125/src/r8125.h
									
										
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										261
									
								
								r8125/src/r8125_dash.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										261
									
								
								r8125/src/r8125_dash.h
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,261 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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_R8125_DASH_H | ||||
| #define _LINUX_R8125_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 rtl8125_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_R8125_DASH_H */ | ||||
							
								
								
									
										264
									
								
								r8125/src/r8125_firmware.c
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										264
									
								
								r8125/src/r8125_firmware.c
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,264 @@ | |||
| // SPDX-License-Identifier: GPL-2.0-only
 | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8168 is the Linux device driver released for Realtek Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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/delay.h> | ||||
| #include <linux/firmware.h> | ||||
| 
 | ||||
| #include "r8125_firmware.h" | ||||
| 
 | ||||
| enum rtl_fw_opcode { | ||||
|         PHY_READ		= 0x0, | ||||
|         PHY_DATA_OR		= 0x1, | ||||
|         PHY_DATA_AND		= 0x2, | ||||
|         PHY_BJMPN		= 0x3, | ||||
|         PHY_MDIO_CHG		= 0x4, | ||||
|         PHY_CLEAR_READCOUNT	= 0x7, | ||||
|         PHY_WRITE		= 0x8, | ||||
|         PHY_READCOUNT_EQ_SKIP	= 0x9, | ||||
|         PHY_COMP_EQ_SKIPN	= 0xa, | ||||
|         PHY_COMP_NEQ_SKIPN	= 0xb, | ||||
|         PHY_WRITE_PREVIOUS	= 0xc, | ||||
|         PHY_SKIPN		= 0xd, | ||||
|         PHY_DELAY_MS		= 0xe, | ||||
| }; | ||||
| 
 | ||||
| struct fw_info { | ||||
|         u32	magic; | ||||
|         char	version[RTL8125_VER_SIZE]; | ||||
|         __le32	fw_start; | ||||
|         __le32	fw_len; | ||||
|         u8	chksum; | ||||
| } __packed; | ||||
| 
 | ||||
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) | ||||
| #define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) | ||||
| #endif | ||||
| #define FW_OPCODE_SIZE sizeof_field(struct rtl8125_fw_phy_action, code[0]) | ||||
| 
 | ||||
| static bool rtl8125_fw_format_ok(struct rtl8125_fw *rtl_fw) | ||||
| { | ||||
|         const struct firmware *fw = rtl_fw->fw; | ||||
|         struct fw_info *fw_info = (struct fw_info *)fw->data; | ||||
|         struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; | ||||
| 
 | ||||
|         if (fw->size < FW_OPCODE_SIZE) | ||||
|                 return false; | ||||
| 
 | ||||
|         if (!fw_info->magic) { | ||||
|                 size_t i, size, start; | ||||
|                 u8 checksum = 0; | ||||
| 
 | ||||
|                 if (fw->size < sizeof(*fw_info)) | ||||
|                         return false; | ||||
| 
 | ||||
|                 for (i = 0; i < fw->size; i++) | ||||
|                         checksum += fw->data[i]; | ||||
|                 if (checksum != 0) | ||||
|                         return false; | ||||
| 
 | ||||
|                 start = le32_to_cpu(fw_info->fw_start); | ||||
|                 if (start > fw->size) | ||||
|                         return false; | ||||
| 
 | ||||
|                 size = le32_to_cpu(fw_info->fw_len); | ||||
|                 if (size > (fw->size - start) / FW_OPCODE_SIZE) | ||||
|                         return false; | ||||
| 
 | ||||
|                 strscpy(rtl_fw->version, fw_info->version, RTL8125_VER_SIZE); | ||||
| 
 | ||||
|                 pa->code = (__le32 *)(fw->data + start); | ||||
|                 pa->size = size; | ||||
|         } else { | ||||
|                 if (fw->size % FW_OPCODE_SIZE) | ||||
|                         return false; | ||||
| 
 | ||||
|                 strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8125_VER_SIZE); | ||||
| 
 | ||||
|                 pa->code = (__le32 *)fw->data; | ||||
|                 pa->size = fw->size / FW_OPCODE_SIZE; | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
| } | ||||
| 
 | ||||
| static bool rtl8125_fw_data_ok(struct rtl8125_fw *rtl_fw) | ||||
| { | ||||
|         struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; | ||||
|         size_t index; | ||||
| 
 | ||||
|         for (index = 0; index < pa->size; index++) { | ||||
|                 u32 action = le32_to_cpu(pa->code[index]); | ||||
|                 u32 val = action & 0x0000ffff; | ||||
|                 u32 regno = (action & 0x0fff0000) >> 16; | ||||
| 
 | ||||
|                 switch (action >> 28) { | ||||
|                 case PHY_READ: | ||||
|                 case PHY_DATA_OR: | ||||
|                 case PHY_DATA_AND: | ||||
|                 case PHY_CLEAR_READCOUNT: | ||||
|                 case PHY_WRITE: | ||||
|                 case PHY_WRITE_PREVIOUS: | ||||
|                 case PHY_DELAY_MS: | ||||
|                         break; | ||||
| 
 | ||||
|                 case PHY_MDIO_CHG: | ||||
|                         if (val > 1) | ||||
|                                 goto out; | ||||
|                         break; | ||||
| 
 | ||||
|                 case PHY_BJMPN: | ||||
|                         if (regno > index) | ||||
|                                 goto out; | ||||
|                         break; | ||||
|                 case PHY_READCOUNT_EQ_SKIP: | ||||
|                         if (index + 2 >= pa->size) | ||||
|                                 goto out; | ||||
|                         break; | ||||
|                 case PHY_COMP_EQ_SKIPN: | ||||
|                 case PHY_COMP_NEQ_SKIPN: | ||||
|                 case PHY_SKIPN: | ||||
|                         if (index + 1 + regno >= pa->size) | ||||
|                                 goto out; | ||||
|                         break; | ||||
| 
 | ||||
|                 default: | ||||
|                         dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); | ||||
|                         return false; | ||||
|                 } | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
| out: | ||||
|         dev_err(rtl_fw->dev, "Out of range of firmware\n"); | ||||
|         return false; | ||||
| } | ||||
| 
 | ||||
| void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw) | ||||
| { | ||||
|         struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; | ||||
|         rtl8125_fw_write_t fw_write = rtl_fw->phy_write; | ||||
|         rtl8125_fw_read_t fw_read = rtl_fw->phy_read; | ||||
|         int predata = 0, count = 0; | ||||
|         size_t index; | ||||
| 
 | ||||
|         for (index = 0; index < pa->size; index++) { | ||||
|                 u32 action = le32_to_cpu(pa->code[index]); | ||||
|                 u32 data = action & 0x0000ffff; | ||||
|                 u32 regno = (action & 0x0fff0000) >> 16; | ||||
|                 enum rtl_fw_opcode opcode = action >> 28; | ||||
| 
 | ||||
|                 if (!action) | ||||
|                         break; | ||||
| 
 | ||||
|                 switch (opcode) { | ||||
|                 case PHY_READ: | ||||
|                         predata = fw_read(tp, regno); | ||||
|                         count++; | ||||
|                         break; | ||||
|                 case PHY_DATA_OR: | ||||
|                         predata |= data; | ||||
|                         break; | ||||
|                 case PHY_DATA_AND: | ||||
|                         predata &= data; | ||||
|                         break; | ||||
|                 case PHY_BJMPN: | ||||
|                         index -= (regno + 1); | ||||
|                         break; | ||||
|                 case PHY_MDIO_CHG: | ||||
|                         if (data) { | ||||
|                                 fw_write = rtl_fw->mac_mcu_write; | ||||
|                                 fw_read = rtl_fw->mac_mcu_read; | ||||
|                         } else { | ||||
|                                 fw_write = rtl_fw->phy_write; | ||||
|                                 fw_read = rtl_fw->phy_read; | ||||
|                         } | ||||
| 
 | ||||
|                         break; | ||||
|                 case PHY_CLEAR_READCOUNT: | ||||
|                         count = 0; | ||||
|                         break; | ||||
|                 case PHY_WRITE: | ||||
|                         fw_write(tp, regno, data); | ||||
|                         break; | ||||
|                 case PHY_READCOUNT_EQ_SKIP: | ||||
|                         if (count == data) | ||||
|                                 index++; | ||||
|                         break; | ||||
|                 case PHY_COMP_EQ_SKIPN: | ||||
|                         if (predata == data) | ||||
|                                 index += regno; | ||||
|                         break; | ||||
|                 case PHY_COMP_NEQ_SKIPN: | ||||
|                         if (predata != data) | ||||
|                                 index += regno; | ||||
|                         break; | ||||
|                 case PHY_WRITE_PREVIOUS: | ||||
|                         fw_write(tp, regno, predata); | ||||
|                         break; | ||||
|                 case PHY_SKIPN: | ||||
|                         index += regno; | ||||
|                         break; | ||||
|                 case PHY_DELAY_MS: | ||||
|                         mdelay(data); | ||||
|                         break; | ||||
|                 } | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw) | ||||
| { | ||||
|         release_firmware(rtl_fw->fw); | ||||
| } | ||||
| 
 | ||||
| int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw) | ||||
| { | ||||
|         int rc; | ||||
| 
 | ||||
|         rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); | ||||
|         if (rc < 0) | ||||
|                 goto out; | ||||
| 
 | ||||
|         if (!rtl8125_fw_format_ok(rtl_fw) || !rtl8125_fw_data_ok(rtl_fw)) { | ||||
|                 release_firmware(rtl_fw->fw); | ||||
|                 rc = -EINVAL; | ||||
|                 goto out; | ||||
|         } | ||||
| 
 | ||||
|         return 0; | ||||
| out: | ||||
|         dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", | ||||
|                 rtl_fw->fw_name, rc); | ||||
|         return rc; | ||||
| } | ||||
							
								
								
									
										68
									
								
								r8125/src/r8125_firmware.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										68
									
								
								r8125/src/r8125_firmware.h
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,68 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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_rtl8125_FIRMWARE_H | ||||
| #define _LINUX_rtl8125_FIRMWARE_H | ||||
| 
 | ||||
| #include <linux/device.h> | ||||
| #include <linux/firmware.h> | ||||
| 
 | ||||
| struct rtl8125_private; | ||||
| typedef void (*rtl8125_fw_write_t)(struct rtl8125_private *tp, u16 reg, u16 val); | ||||
| typedef u32 (*rtl8125_fw_read_t)(struct rtl8125_private *tp, u16 reg); | ||||
| 
 | ||||
| #define RTL8125_VER_SIZE		32 | ||||
| 
 | ||||
| struct rtl8125_fw { | ||||
|         rtl8125_fw_write_t phy_write; | ||||
|         rtl8125_fw_read_t phy_read; | ||||
|         rtl8125_fw_write_t mac_mcu_write; | ||||
|         rtl8125_fw_read_t mac_mcu_read; | ||||
|         const struct firmware *fw; | ||||
|         const char *fw_name; | ||||
|         struct device *dev; | ||||
| 
 | ||||
|         char version[RTL8125_VER_SIZE]; | ||||
| 
 | ||||
|         struct rtl8125_fw_phy_action { | ||||
|                 __le32 *code; | ||||
|                 size_t size; | ||||
|         } phy_action; | ||||
| }; | ||||
| 
 | ||||
| int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw); | ||||
| void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw); | ||||
| void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw); | ||||
| 
 | ||||
| #endif /* _LINUX_rtl8125_FIRMWARE_H */ | ||||
							
								
								
									
										15150
									
								
								r8125/src/r8125_n.c
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										15150
									
								
								r8125/src/r8125_n.c
									
										
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										594
									
								
								r8125/src/r8125_ptp.c
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										594
									
								
								r8125/src/r8125_ptp.c
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,594 @@ | |||
| // SPDX-License-Identifier: GPL-2.0-only
 | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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/module.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/mii.h> | ||||
| #include <linux/in.h> | ||||
| #include <linux/ethtool.h> | ||||
| 
 | ||||
| #include "r8125.h" | ||||
| #include "r8125_ptp.h" | ||||
| 
 | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) | ||||
| static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) | ||||
| { | ||||
|         return *(const struct timespec *)&ts64; | ||||
| } | ||||
| 
 | ||||
| static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) | ||||
| { | ||||
|         return *(const struct timespec64 *)&ts; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static int _rtl8125_phc_gettime(struct rtl8125_private *tp, struct timespec64 *ts64) | ||||
| { | ||||
|         //get local time
 | ||||
|         RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_LATCHED_LOCAL_TIME | PTP_EXEC_CMD)); | ||||
| 
 | ||||
|         /* nanoseconds */ | ||||
|         //0x6808[29:0]
 | ||||
|         ts64->tv_nsec = (RTL_R32(tp, PTP_SOFT_CONFIG_Time_NS_8125) & 0x3fffffff) + | ||||
|                         tp->ptp_adjust; | ||||
| 
 | ||||
|         /* seconds */ | ||||
|         //0x680C[47:0]
 | ||||
|         ts64->tv_sec = RTL_R16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4); | ||||
|         ts64->tv_sec <<= 32; | ||||
|         ts64->tv_sec |= RTL_R32(tp, PTP_SOFT_CONFIG_Time_S_8125); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static int _rtl8125_phc_settime(struct rtl8125_private *tp, const struct timespec64 *ts64) | ||||
| { | ||||
|         /* nanoseconds */ | ||||
|         //0x6808[29:0]
 | ||||
|         RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, (ts64->tv_nsec & 0x3fffffff)); | ||||
| 
 | ||||
|         /* seconds */ | ||||
|         //0x680C[47:0]
 | ||||
|         RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, ts64->tv_sec); | ||||
|         RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (ts64->tv_sec >> 32)); | ||||
| 
 | ||||
|         //set local time
 | ||||
|         RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| static int _rtl8125_phc_adjtime(struct rtl8125_private *tp, s64 delta) | ||||
| { | ||||
|         struct timespec64 now, then = ns_to_timespec64(delta); | ||||
|         u32 nsec; | ||||
|         u64 sec; | ||||
| 
 | ||||
|         _rtl8125_phc_gettime(tp, &now); | ||||
|         now = timespec64_add(now, then); | ||||
| 
 | ||||
|         nsec = now.tv_nsec & 0x3fffffff; | ||||
|         sec = now.tv_sec & 0x0000ffffffffffff; | ||||
| 
 | ||||
|         /* nanoseconds */ | ||||
|         //0x6808[29:0]
 | ||||
|         RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, nsec); | ||||
| 
 | ||||
|         /* seconds */ | ||||
|         //0x680C[47:0]
 | ||||
|         RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, sec); | ||||
|         RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (sec >> 32)); | ||||
| 
 | ||||
|         //adjust local time
 | ||||
|         //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)); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static int rtl8125_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) | ||||
| { | ||||
|         struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); | ||||
|         unsigned long flags; | ||||
|         //int ret = 0;
 | ||||
| 
 | ||||
|         //netif_info(tp, drv, tp->dev, "phc adjust time\n");
 | ||||
| 
 | ||||
|         spin_lock_irqsave(&tp->lock, flags); | ||||
|         //ret = _rtl8125_phc_adjtime(tp, delta);
 | ||||
|         tp->ptp_adjust += delta; | ||||
|         spin_unlock_irqrestore(&tp->lock, flags); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| 1ppm means every 125MHz plus 125Hz. It also means every 8ns minus 8ns*10^(-6) | ||||
| 
 | ||||
| 1ns=2^30 sub_ns | ||||
| 
 | ||||
| 8ns*10^(-6) = 8 * 2^30 sub_ns * 10^(-6) = 2^33 sub_ns * 10^(-6) = 8590 = 0x218E sub_ns | ||||
| 
 | ||||
| 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 _rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb) | ||||
| { | ||||
|         struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); | ||||
|         bool negative = false; | ||||
|         u32 sub_ns; | ||||
| 
 | ||||
|         if (ppb < 0) { | ||||
|                 negative = true; | ||||
|                 ppb = -ppb; | ||||
|         } | ||||
| 
 | ||||
|         sub_ns = ppb * 9; | ||||
|         if (negative) { | ||||
|                 sub_ns = -sub_ns; | ||||
|                 sub_ns &= 0x3fffffff; | ||||
|                 sub_ns |= PTP_ADJUST_TIME_NS_NEGATIVE; | ||||
|         } else | ||||
|                 sub_ns &= 0x3fffffff; | ||||
| 
 | ||||
|         /* nanoseconds */ | ||||
|         //0x6808[29:0]
 | ||||
|         RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, sub_ns); | ||||
| 
 | ||||
|         //adjust local time
 | ||||
|         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));
 | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static int rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) | ||||
| { | ||||
|         //struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info);
 | ||||
| 
 | ||||
|         //netif_info(tp, drv, tp->dev, "phc adjust freq\n");
 | ||||
| 
 | ||||
|         if (delta > ptp->max_adj || delta < -ptp->max_adj) | ||||
|                 return -EINVAL; | ||||
| 
 | ||||
|         _rtl8125_phc_adjfreq(ptp, delta); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static int rtl8125_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64) | ||||
| { | ||||
|         struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); | ||||
|         unsigned long flags; | ||||
|         int ret; | ||||
| 
 | ||||
|         //netif_info(tp, drv, tp->dev, "phc get ts\n");
 | ||||
| 
 | ||||
|         spin_lock_irqsave(&tp->lock, flags); | ||||
|         ret = _rtl8125_phc_gettime(tp, ts64); | ||||
|         spin_unlock_irqrestore(&tp->lock, flags); | ||||
| 
 | ||||
|         return ret; | ||||
| } | ||||
| 
 | ||||
| static int rtl8125_phc_settime(struct ptp_clock_info *ptp, | ||||
|                                const struct timespec64 *ts64) | ||||
| { | ||||
|         struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); | ||||
|         unsigned long flags; | ||||
|         int ret; | ||||
| 
 | ||||
|         //netif_info(tp, drv, tp->dev, "phc set ts\n");
 | ||||
| 
 | ||||
|         spin_lock_irqsave(&tp->lock, flags); | ||||
|         ret = _rtl8125_phc_settime(tp, ts64); | ||||
|         tp->ptp_adjust = 0; | ||||
|         spin_unlock_irqrestore(&tp->lock, flags); | ||||
| 
 | ||||
|         return ret; | ||||
| } | ||||
| 
 | ||||
| static int rtl8125_phc_enable(struct ptp_clock_info *ptp, | ||||
|                               struct ptp_clock_request *rq, int on) | ||||
| { | ||||
|         struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); | ||||
|         unsigned long flags; | ||||
|         u16 ptp_ctrl; | ||||
| 
 | ||||
|         //netif_info(tp, drv, tp->dev, "phc enable type %x on %d\n", rq->type, on);
 | ||||
| 
 | ||||
|         switch (rq->type) { | ||||
|         case PTP_CLK_REQ_PPS: | ||||
|                 spin_lock_irqsave(&tp->lock, flags); | ||||
|                 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); | ||||
|                 spin_unlock_irqrestore(&tp->lock, flags); | ||||
|                 return 0; | ||||
|         default: | ||||
|                 return -EOPNOTSUPP; | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| int rtl8125_get_ts_info(struct net_device *netdev, | ||||
|                         struct ethtool_ts_info *info) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(netdev); | ||||
| 
 | ||||
|         /* we always support timestamping disabled */ | ||||
|         info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); | ||||
| 
 | ||||
|         if (tp->HwSuppPtpVer == 0) | ||||
|                 return ethtool_op_get_ts_info(netdev, info); | ||||
| 
 | ||||
|         info->so_timestamping =  SOF_TIMESTAMPING_TX_SOFTWARE | | ||||
|                                  SOF_TIMESTAMPING_RX_SOFTWARE | | ||||
|                                  SOF_TIMESTAMPING_SOFTWARE | | ||||
|                                  SOF_TIMESTAMPING_TX_HARDWARE | | ||||
|                                  SOF_TIMESTAMPING_RX_HARDWARE | | ||||
|                                  SOF_TIMESTAMPING_RAW_HARDWARE; | ||||
| 
 | ||||
|         if (tp->ptp_clock) | ||||
|                 info->phc_index = ptp_clock_index(tp->ptp_clock); | ||||
|         else | ||||
|                 info->phc_index = -1; | ||||
| 
 | ||||
|         info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); | ||||
| 
 | ||||
|         info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | | ||||
|                            BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | | ||||
|                            BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | | ||||
|                            BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | | ||||
|                            BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | | ||||
|                            BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | | ||||
|                            BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct ptp_clock_info rtl_ptp_clock_info = { | ||||
|         .owner      = THIS_MODULE, | ||||
|         .n_alarm    = 0, | ||||
|         .n_ext_ts   = 0, | ||||
|         .n_per_out  = 0, | ||||
|         .n_pins     = 0, | ||||
|         .pps        = 1, | ||||
|         .adjfreq    = rtl8125_phc_adjfreq, | ||||
|         .adjtime    = rtl8125_phc_adjtime, | ||||
|         .gettime64  = rtl8125_phc_gettime, | ||||
|         .settime64  = rtl8125_phc_settime, | ||||
|         .enable     = rtl8125_phc_enable, | ||||
| }; | ||||
| 
 | ||||
| static int rtl8125_get_tx_ptp_pkt_tstamp(struct rtl8125_private *tp, struct timespec64 *ts64) | ||||
| { | ||||
|         return _rtl8125_phc_gettime(tp, ts64); | ||||
| } | ||||
| 
 | ||||
| static void rtl8125_ptp_tx_hwtstamp(struct rtl8125_private *tp) | ||||
| { | ||||
|         struct sk_buff *skb = tp->ptp_tx_skb; | ||||
|         struct skb_shared_hwtstamps shhwtstamps = {0}; | ||||
|         struct timespec64 ts64; | ||||
| 
 | ||||
|         RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); | ||||
| 
 | ||||
|         rtl8125_get_tx_ptp_pkt_tstamp(tp, &ts64); | ||||
| 
 | ||||
|         /* Upper 32 bits contain s, lower 32 bits contain ns. */ | ||||
|         shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec, | ||||
|                                          ts64.tv_nsec); | ||||
| 
 | ||||
|         /* Clear the lock early before calling skb_tstamp_tx so that
 | ||||
|          * applications are not woken up before the lock bit is clear. We use | ||||
|          * a copy of the skb pointer to ensure other threads can't change it | ||||
|          * while we're notifying the stack. | ||||
|          */ | ||||
|         tp->ptp_tx_skb = NULL; | ||||
| 
 | ||||
|         /* Notify the stack and free the skb after we've unlocked */ | ||||
|         skb_tstamp_tx(skb, &shhwtstamps); | ||||
|         dev_kfree_skb_any(skb); | ||||
| } | ||||
| 
 | ||||
| #define RTL8125_PTP_TX_TIMEOUT      (HZ * 15) | ||||
| static void rtl8125_ptp_tx_work(struct work_struct *work) | ||||
| { | ||||
|         struct rtl8125_private *tp = container_of(work, struct rtl8125_private, | ||||
|                                      ptp_tx_work); | ||||
|         unsigned long flags; | ||||
| 
 | ||||
|         spin_lock_irqsave(&tp->lock, flags); | ||||
| 
 | ||||
|         if (!tp->ptp_tx_skb) | ||||
|                 goto Exit; | ||||
| 
 | ||||
|         if (time_is_before_jiffies(tp->ptp_tx_start + | ||||
|                                    RTL8125_PTP_TX_TIMEOUT)) { | ||||
|                 dev_kfree_skb_any(tp->ptp_tx_skb); | ||||
|                 tp->ptp_tx_skb = NULL; | ||||
|                 tp->tx_hwtstamp_timeouts++; | ||||
|                 /* Clear the tx valid bit in TSYNCTXCTL register to enable
 | ||||
|                  * interrupt | ||||
|                  */ | ||||
|                 RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); | ||||
|                 goto Exit; | ||||
|         } | ||||
| 
 | ||||
|         if (RTL_R8(tp, PTP_ISR_8125) & (PTP_ISR_TOK)) | ||||
|                 rtl8125_ptp_tx_hwtstamp(tp); | ||||
|         else | ||||
|                 /* reschedule to check later */ | ||||
|                 schedule_work(&tp->ptp_tx_work); | ||||
| 
 | ||||
| Exit: | ||||
|         spin_unlock_irqrestore(&tp->lock, flags); | ||||
| } | ||||
| 
 | ||||
| static int rtl8125_hwtstamp_enable(struct rtl8125_private *tp, bool enable) | ||||
| { | ||||
|         RTL_W16(tp, PTP_CTRL_8125, 0); | ||||
|         if (enable) { | ||||
|                 u16 ptp_ctrl; | ||||
|                 struct timespec64 ts64; | ||||
| 
 | ||||
|                 //clear ptp isr
 | ||||
|                 RTL_W8(tp, PTP_ISR_8125, 0xff); | ||||
|                 //ptp source 0:gphy 1:mac
 | ||||
|                 rtl8125_mac_ocp_write(tp, 0xDC00, rtl8125_mac_ocp_read(tp, 0xDC00) | BIT_6); | ||||
|                 //enable ptp
 | ||||
|                 ptp_ctrl = (BIT_0 | BIT_3 | BIT_4 | BIT_6 | BIT_10 | BIT_12 | BIT_13); | ||||
|                 if (tp->ptp_master_mode) { | ||||
|                         ptp_ctrl &= ~BIT_13; | ||||
|                         ptp_ctrl |= BIT_1; | ||||
|                 } | ||||
|                 RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); | ||||
| 
 | ||||
|                 //set system time
 | ||||
|                 /*
 | ||||
|                 if (ktime_to_timespec64_cond(ktime_get_real(), &ts64)) | ||||
|                 _rtl8125_phc_settime(tp, timespec64_to_timespec(ts64)); | ||||
|                 */ | ||||
|                 ktime_get_real_ts64(&ts64); | ||||
|                 ts64.tv_nsec += tp->ptp_adjust; | ||||
|                 _rtl8125_phc_settime(tp, &ts64); | ||||
|                 tp->ptp_adjust = 0; | ||||
|         } | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static long rtl8125_ptp_create_clock(struct rtl8125_private *tp) | ||||
| { | ||||
|         struct net_device *netdev = tp->dev; | ||||
|         long err; | ||||
| 
 | ||||
|         if (!IS_ERR_OR_NULL(tp->ptp_clock)) | ||||
|                 return 0; | ||||
| 
 | ||||
|         if (tp->HwSuppPtpVer == 0) { | ||||
|                 tp->ptp_clock = NULL; | ||||
|                 return -EOPNOTSUPP; | ||||
|         } | ||||
| 
 | ||||
|         tp->ptp_clock_info = rtl_ptp_clock_info; | ||||
|         snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name), | ||||
|                  "%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); | ||||
|         if (IS_ERR(tp->ptp_clock)) { | ||||
|                 err = PTR_ERR(tp->ptp_clock); | ||||
|                 tp->ptp_clock = NULL; | ||||
|                 netif_err(tp, drv, tp->dev, "ptp_clock_register failed\n"); | ||||
|                 return err; | ||||
|         } else | ||||
|                 netif_info(tp, drv, tp->dev, "registered PHC device on %s\n", netdev->name); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| void rtl8125_ptp_reset(struct rtl8125_private *tp) | ||||
| { | ||||
|         if (!tp->ptp_clock) | ||||
|                 return; | ||||
| 
 | ||||
|         netif_info(tp, drv, tp->dev, "reset PHC clock\n"); | ||||
| 
 | ||||
|         rtl8125_hwtstamp_enable(tp, false); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_ptp_init(struct rtl8125_private *tp) | ||||
| { | ||||
|         /* obtain a PTP device, or re-use an existing device */ | ||||
|         if (rtl8125_ptp_create_clock(tp)) | ||||
|                 return; | ||||
| 
 | ||||
|         /* we have a clock so we can initialize work now */ | ||||
|         INIT_WORK(&tp->ptp_tx_work, rtl8125_ptp_tx_work); | ||||
| 
 | ||||
|         tp->ptp_adjust = 0; | ||||
| 
 | ||||
|         /* reset the PTP related hardware bits */ | ||||
|         rtl8125_ptp_reset(tp); | ||||
| 
 | ||||
|         return; | ||||
| } | ||||
| 
 | ||||
| void rtl8125_ptp_suspend(struct rtl8125_private *tp) | ||||
| { | ||||
|         if (!tp->ptp_clock) | ||||
|                 return; | ||||
| 
 | ||||
|         netif_info(tp, drv, tp->dev, "suspend PHC clock\n"); | ||||
| 
 | ||||
|         rtl8125_hwtstamp_enable(tp, false); | ||||
| 
 | ||||
|         /* ensure that we cancel any pending PTP Tx work item in progress */ | ||||
|         cancel_work_sync(&tp->ptp_tx_work); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_ptp_stop(struct rtl8125_private *tp) | ||||
| { | ||||
|         struct net_device *netdev = tp->dev; | ||||
| 
 | ||||
|         netif_info(tp, drv, tp->dev, "stop PHC clock\n"); | ||||
| 
 | ||||
|         /* first, suspend PTP activity */ | ||||
|         rtl8125_ptp_suspend(tp); | ||||
| 
 | ||||
|         /* disable the PTP clock device */ | ||||
|         if (tp->ptp_clock) { | ||||
|                 ptp_clock_unregister(tp->ptp_clock); | ||||
|                 tp->ptp_clock = NULL; | ||||
|                 netif_info(tp, drv, tp->dev, "removed PHC on %s\n", | ||||
|                            netdev->name); | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| static int rtl8125_set_tstamp(struct net_device *netdev, struct ifreq *ifr) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(netdev); | ||||
|         struct hwtstamp_config config; | ||||
|         bool hwtstamp = 0; | ||||
| 
 | ||||
|         //netif_info(tp, drv, tp->dev, "ptp set ts\n");
 | ||||
| 
 | ||||
|         if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) | ||||
|                 return -EFAULT; | ||||
| 
 | ||||
|         if (config.flags) | ||||
|                 return -EINVAL; | ||||
| 
 | ||||
|         switch (config.tx_type) { | ||||
|         case HWTSTAMP_TX_ON: | ||||
|                 hwtstamp = 1; | ||||
|         case HWTSTAMP_TX_OFF: | ||||
|                 break; | ||||
|         case HWTSTAMP_TX_ONESTEP_SYNC: | ||||
|         default: | ||||
|                 return -ERANGE; | ||||
|         } | ||||
| 
 | ||||
|         switch (config.rx_filter) { | ||||
|         case HWTSTAMP_FILTER_PTP_V2_EVENT: | ||||
|         case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: | ||||
|         case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: | ||||
|         case HWTSTAMP_FILTER_PTP_V2_SYNC: | ||||
|         case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: | ||||
|         case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: | ||||
|         case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: | ||||
|         case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: | ||||
|         case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: | ||||
|                 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; | ||||
|                 hwtstamp = 1; | ||||
|         case HWTSTAMP_FILTER_NONE: | ||||
|                 break; | ||||
|         default: | ||||
|                 return -ERANGE; | ||||
|         } | ||||
| 
 | ||||
|         if (tp->hwtstamp_config.tx_type != config.tx_type || | ||||
|             tp->hwtstamp_config.rx_filter != config.rx_filter) { | ||||
|                 tp->hwtstamp_config = config; | ||||
|                 rtl8125_hwtstamp_enable(tp, hwtstamp); | ||||
|         } | ||||
| 
 | ||||
|         return copy_to_user(ifr->ifr_data, &config, | ||||
|                             sizeof(config)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int rtl8125_get_tstamp(struct net_device *netdev, struct ifreq *ifr) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(netdev); | ||||
| 
 | ||||
|         //netif_info(tp, drv, tp->dev, "ptp get ts\n");
 | ||||
| 
 | ||||
|         return copy_to_user(ifr->ifr_data, &tp->hwtstamp_config, | ||||
|                             sizeof(tp->hwtstamp_config)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(netdev); | ||||
|         int ret; | ||||
|         unsigned long flags; | ||||
| 
 | ||||
|         //netif_info(tp, drv, tp->dev, "ptp ioctl\n");
 | ||||
| 
 | ||||
|         ret = 0; | ||||
|         switch (cmd) { | ||||
| #ifdef ENABLE_PTP_SUPPORT | ||||
|         case SIOCSHWTSTAMP: | ||||
|                 spin_lock_irqsave(&tp->lock, flags); | ||||
|                 ret = rtl8125_set_tstamp(netdev, ifr); | ||||
|                 spin_unlock_irqrestore(&tp->lock, flags); | ||||
|                 break; | ||||
|         case SIOCGHWTSTAMP: | ||||
|                 spin_lock_irqsave(&tp->lock, flags); | ||||
|                 ret = rtl8125_get_tstamp(netdev, ifr); | ||||
|                 spin_unlock_irqrestore(&tp->lock, flags); | ||||
|                 break; | ||||
| #endif | ||||
|         default: | ||||
|                 ret = -EOPNOTSUPP; | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         return ret; | ||||
| } | ||||
| 
 | ||||
| void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, | ||||
|                              struct RxDescV3 *descv3) | ||||
| { | ||||
|         time64_t tv_sec; | ||||
|         long tv_nsec; | ||||
| 
 | ||||
|         tv_sec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampHigh) + | ||||
|                  ((u64)le32_to_cpu(descv3->RxDescPTPDDWord4.TimeStampHHigh) << 32); | ||||
|         tv_nsec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampLow) + tp->ptp_adjust; | ||||
| 
 | ||||
|         skb_hwtstamps(skb)->hwtstamp = ktime_set(tv_sec, tv_nsec); | ||||
| } | ||||
							
								
								
									
										81
									
								
								r8125/src/r8125_ptp.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										81
									
								
								r8125/src/r8125_ptp.h
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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_rtl8125_PTP_H | ||||
| #define _LINUX_rtl8125_PTP_H | ||||
| 
 | ||||
| #include <linux/ktime.h> | ||||
| #include <linux/timecounter.h> | ||||
| #include <linux/net_tstamp.h> | ||||
| #include <linux/ptp_clock_kernel.h> | ||||
| #include <linux/ptp_classify.h> | ||||
| 
 | ||||
| struct rtl8125_ptp_info { | ||||
|         s64 time_sec; | ||||
|         u32 time_ns; | ||||
|         u16 ts_info; | ||||
| }; | ||||
| 
 | ||||
| #ifndef _STRUCT_TIMESPEC | ||||
| #define _STRUCT_TIMESPEC | ||||
| struct timespec { | ||||
|         __kernel_old_time_t tv_sec;     /* seconds */ | ||||
|         long            tv_nsec;    /* nanoseconds */ | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| enum PTP_CMD_TYPE { | ||||
|         PTP_CMD_SET_LOCAL_TIME = 0, | ||||
|         PTP_CMD_DRIFT_LOCAL_TIME, | ||||
|         PTP_CMD_LATCHED_LOCAL_TIME, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| struct rtl8125_private; | ||||
| struct RxDescV3; | ||||
| 
 | ||||
| int rtl8125_get_ts_info(struct net_device *netdev, | ||||
|                         struct ethtool_ts_info *info); | ||||
| 
 | ||||
| void rtl8125_ptp_reset(struct rtl8125_private *tp); | ||||
| void rtl8125_ptp_init(struct rtl8125_private *tp); | ||||
| void rtl8125_ptp_suspend(struct rtl8125_private *tp); | ||||
| void rtl8125_ptp_stop(struct rtl8125_private *tp); | ||||
| 
 | ||||
| int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); | ||||
| 
 | ||||
| void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, | ||||
|                              struct RxDescV3 *descv3); | ||||
| 
 | ||||
| #endif /* _LINUX_rtl8125_PTP_H */ | ||||
							
								
								
									
										118
									
								
								r8125/src/r8125_realwow.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										118
									
								
								r8125/src/r8125_realwow.h
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,118 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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_R8125_REALWOW_H | ||||
| #define _LINUX_R8125_REALWOW_H | ||||
| 
 | ||||
| #define SIOCDEVPRIVATE_RTLREALWOW   SIOCDEVPRIVATE+3 | ||||
| 
 | ||||
| #define MAX_RealWoW_KCP_SIZE (100) | ||||
| #define MAX_RealWoW_Payload (64) | ||||
| 
 | ||||
| #define KA_TX_PACKET_SIZE (100) | ||||
| #define KA_WAKEUP_PATTERN_SIZE (120) | ||||
| 
 | ||||
| //HwSuppKeepAliveOffloadVer
 | ||||
| #define HW_SUPPORT_KCP_OFFLOAD(_M)        ((_M)->HwSuppKCPOffloadVer > 0) | ||||
| 
 | ||||
| enum rtl_realwow_cmd { | ||||
| 
 | ||||
|         RTL_REALWOW_SET_KCP_DISABLE=0, | ||||
|         RTL_REALWOW_SET_KCP_INFO, | ||||
|         RTL_REALWOW_SET_KCP_CONTENT, | ||||
| 
 | ||||
|         RTL_REALWOW_SET_KCP_ACKPKTINFO, | ||||
|         RTL_REALWOW_SET_KCP_WPINFO, | ||||
|         RTL_REALWOW_SET_KCPDHCP_TIMEOUT, | ||||
| 
 | ||||
|         RTLT_REALWOW_COMMAND_INVALID | ||||
| }; | ||||
| 
 | ||||
| struct rtl_realwow_ioctl_struct { | ||||
|         __u32	cmd; | ||||
|         __u32	offset; | ||||
|         __u32	len; | ||||
|         union { | ||||
|                 __u32	data; | ||||
|                 void *data_buffer; | ||||
|         }; | ||||
| }; | ||||
| 
 | ||||
| typedef struct _MP_KCPInfo { | ||||
|         u8 DIPv4[4]; | ||||
|         u8 MacID[6]; | ||||
|         u16 UdpPort[2]; | ||||
|         u8 PKTLEN[2]; | ||||
| 
 | ||||
|         u16 ackLostCnt; | ||||
|         u8 KCP_WakePattern[MAX_RealWoW_Payload]; | ||||
|         u8 KCP_AckPacket[MAX_RealWoW_Payload]; | ||||
|         u32 KCP_interval; | ||||
|         u8 KCP_WakePattern_Len; | ||||
|         u8 KCP_AckPacket_Len; | ||||
|         u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE]; | ||||
| } MP_KCP_INFO, *PMP_KCP_INFO; | ||||
| 
 | ||||
| typedef struct _KCPInfo { | ||||
|         u32 nId; // = id
 | ||||
|         u8 DIPv4[4]; | ||||
|         u8 MacID[6]; | ||||
|         u16 UdpPort; | ||||
|         u16 PKTLEN; | ||||
| } KCPInfo, *PKCPInfo; | ||||
| 
 | ||||
| typedef struct _KCPContent { | ||||
|         u32 id; // = id
 | ||||
|         u32 mSec; // = msec
 | ||||
|         u32 size; // =size
 | ||||
|         u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here
 | ||||
| } KCPContent, *PKCPContent; | ||||
| 
 | ||||
| typedef struct _RealWoWAckPktInfo { | ||||
|         u16 ackLostCnt; | ||||
|         u16 patterntSize; | ||||
|         u8 pattern[MAX_RealWoW_Payload]; | ||||
| } RealWoWAckPktInfo,*PRealWoWAckPktInfo; | ||||
| 
 | ||||
| typedef struct _RealWoWWPInfo { | ||||
|         u16 patterntSize; | ||||
|         u8 pattern[MAX_RealWoW_Payload]; | ||||
| } RealWoWWPInfo,*PRealWoWWPInfo; | ||||
| 
 | ||||
| int rtl8125_realwow_ioctl(struct net_device *dev, struct ifreq *ifr); | ||||
| void rtl8125_realwow_hw_init(struct net_device *dev); | ||||
| void rtl8125_get_realwow_hw_version(struct net_device *dev); | ||||
| void rtl8125_set_realwow_d3_para(struct net_device *dev); | ||||
| 
 | ||||
| #endif /* _LINUX_R8125_REALWOW_H */ | ||||
							
								
								
									
										481
									
								
								r8125/src/r8125_rss.c
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										481
									
								
								r8125/src/r8125_rss.c
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,481 @@ | |||
| // SPDX-License-Identifier: GPL-2.0-only
 | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8168 is the Linux device driver released for Realtek Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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 "r8125.h" | ||||
| 
 | ||||
| enum rtl8125_rss_register_content { | ||||
|         /* RSS */ | ||||
|         RSS_CTRL_TCP_IPV4_SUPP = (1 << 0), | ||||
|         RSS_CTRL_IPV4_SUPP  = (1 << 1), | ||||
|         RSS_CTRL_TCP_IPV6_SUPP  = (1 << 2), | ||||
|         RSS_CTRL_IPV6_SUPP  = (1 << 3), | ||||
|         RSS_HALF_SUPP  = (1 << 7), | ||||
|         RSS_CTRL_UDP_IPV4_SUPP  = (1 << 11), | ||||
|         RSS_CTRL_UDP_IPV6_SUPP  = (1 << 12), | ||||
|         RSS_QUAD_CPU_EN  = (1 << 16), | ||||
|         RSS_HQ_Q_SUP_R  = (1 << 31), | ||||
| }; | ||||
| 
 | ||||
| static int rtl8125_get_rss_hash_opts(struct rtl8125_private *tp, | ||||
|                                      struct ethtool_rxnfc *cmd) | ||||
| { | ||||
|         cmd->data = 0; | ||||
| 
 | ||||
|         /* Report default options for RSS */ | ||||
|         switch (cmd->flow_type) { | ||||
|         case TCP_V4_FLOW: | ||||
|                 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||||
|         /* fallthrough */ | ||||
|         case UDP_V4_FLOW: | ||||
|                 if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) | ||||
|                         cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||||
|         /* fallthrough */ | ||||
|         case IPV4_FLOW: | ||||
|                 cmd->data |= RXH_IP_SRC | RXH_IP_DST; | ||||
|                 break; | ||||
|         case TCP_V6_FLOW: | ||||
|                 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||||
|         /* fallthrough */ | ||||
|         case UDP_V6_FLOW: | ||||
|                 if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) | ||||
|                         cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||||
|         /* fallthrough */ | ||||
|         case IPV6_FLOW: | ||||
|                 cmd->data |= RXH_IP_SRC | RXH_IP_DST; | ||||
|                 break; | ||||
|         default: | ||||
|                 return -EINVAL; | ||||
|         } | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, | ||||
|                       u32 *rule_locs) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(dev); | ||||
|         int ret = -EOPNOTSUPP; | ||||
| 
 | ||||
|         netif_info(tp, drv, tp->dev, "rss get rxnfc\n"); | ||||
| 
 | ||||
|         if (!(dev->features & NETIF_F_RXHASH)) | ||||
|                 return ret; | ||||
| 
 | ||||
|         switch (cmd->cmd) { | ||||
|         case ETHTOOL_GRXRINGS: | ||||
|                 cmd->data = rtl8125_tot_rx_rings(tp); | ||||
|                 ret = 0; | ||||
|                 break; | ||||
|         case ETHTOOL_GRXFH: | ||||
|                 ret = rtl8125_get_rss_hash_opts(tp, cmd); | ||||
|                 break; | ||||
|         default: | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         return ret; | ||||
| } | ||||
| 
 | ||||
| u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp) | ||||
| { | ||||
|         return tp->HwSuppIndirTblEntries; | ||||
| } | ||||
| 
 | ||||
| #define RSS_MASK_BITS_OFFSET (8) | ||||
| #define RSS_CPU_NUM_OFFSET (16) | ||||
| #define RTL8125_UDP_RSS_FLAGS (RTL_8125_RSS_FLAG_HASH_UDP_IPV4 | \ | ||||
| 		       RTL_8125_RSS_FLAG_HASH_UDP_IPV6) | ||||
| static int _rtl8125_set_rss_hash_opt(struct rtl8125_private *tp) | ||||
| { | ||||
|         u32 rss_flags = tp->rss_flags; | ||||
|         u32 hash_mask_len; | ||||
|         u32 rss_ctrl; | ||||
| 
 | ||||
|         rss_ctrl = ilog2(rtl8125_tot_rx_rings(tp)); | ||||
|         rss_ctrl &= (BIT_0 | BIT_1 | BIT_2); | ||||
|         rss_ctrl <<= RSS_CPU_NUM_OFFSET; | ||||
| 
 | ||||
|         /* Perform hash on these packet types */ | ||||
|         rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP | ||||
|                     | RSS_CTRL_IPV4_SUPP | ||||
|                     | RSS_CTRL_IPV6_SUPP | ||||
|                     | RSS_CTRL_TCP_IPV6_SUPP; | ||||
| 
 | ||||
|         if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) | ||||
|                 rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; | ||||
| 
 | ||||
|         if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) | ||||
|                 rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; | ||||
| 
 | ||||
|         hash_mask_len = ilog2(rtl8125_rss_indir_tbl_entries(tp)); | ||||
|         hash_mask_len &= (BIT_0 | BIT_1 | BIT_2); | ||||
|         rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET; | ||||
| 
 | ||||
|         RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static int rtl8125_set_rss_hash_opt(struct rtl8125_private *tp, | ||||
|                                     struct ethtool_rxnfc *nfc) | ||||
| { | ||||
|         u32 rss_flags = tp->rss_flags; | ||||
| 
 | ||||
|         netif_info(tp, drv, tp->dev, "rss set hash\n"); | ||||
| 
 | ||||
|         /*
 | ||||
|          * RSS does not support anything other than hashing | ||||
|          * to queues on src and dst IPs and ports | ||||
|          */ | ||||
|         if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | | ||||
|                           RXH_L4_B_0_1 | RXH_L4_B_2_3)) | ||||
|                 return -EINVAL; | ||||
| 
 | ||||
|         switch (nfc->flow_type) { | ||||
|         case TCP_V4_FLOW: | ||||
|         case TCP_V6_FLOW: | ||||
|                 if (!(nfc->data & RXH_IP_SRC) || | ||||
|                     !(nfc->data & RXH_IP_DST) || | ||||
|                     !(nfc->data & RXH_L4_B_0_1) || | ||||
|                     !(nfc->data & RXH_L4_B_2_3)) | ||||
|                         return -EINVAL; | ||||
|                 break; | ||||
|         case UDP_V4_FLOW: | ||||
|                 if (!(nfc->data & RXH_IP_SRC) || | ||||
|                     !(nfc->data & RXH_IP_DST)) | ||||
|                         return -EINVAL; | ||||
|                 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { | ||||
|                 case 0: | ||||
|                         rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV4; | ||||
|                         break; | ||||
|                 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): | ||||
|                         rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV4; | ||||
|                         break; | ||||
|                 default: | ||||
|                         return -EINVAL; | ||||
|                 } | ||||
|                 break; | ||||
|         case UDP_V6_FLOW: | ||||
|                 if (!(nfc->data & RXH_IP_SRC) || | ||||
|                     !(nfc->data & RXH_IP_DST)) | ||||
|                         return -EINVAL; | ||||
|                 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { | ||||
|                 case 0: | ||||
|                         rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV6; | ||||
|                         break; | ||||
|                 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): | ||||
|                         rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV6; | ||||
|                         break; | ||||
|                 default: | ||||
|                         return -EINVAL; | ||||
|                 } | ||||
|                 break; | ||||
|         case SCTP_V4_FLOW: | ||||
|         case AH_ESP_V4_FLOW: | ||||
|         case AH_V4_FLOW: | ||||
|         case ESP_V4_FLOW: | ||||
|         case SCTP_V6_FLOW: | ||||
|         case AH_ESP_V6_FLOW: | ||||
|         case AH_V6_FLOW: | ||||
|         case ESP_V6_FLOW: | ||||
|         case IP_USER_FLOW: | ||||
|         case ETHER_FLOW: | ||||
|                 /* RSS is not supported for these protocols */ | ||||
|                 if (nfc->data) { | ||||
|                         netif_err(tp, drv, tp->dev, "Command parameters not supported\n"); | ||||
|                         return -EINVAL; | ||||
|                 } | ||||
|                 return 0; | ||||
|                 break; | ||||
|         default: | ||||
|                 return -EINVAL; | ||||
|         } | ||||
| 
 | ||||
|         /* if we changed something we need to update flags */ | ||||
|         if (rss_flags != tp->rss_flags) { | ||||
|                 u32 rss_ctrl = RTL_R32(tp, RSS_CTRL_8125); | ||||
| 
 | ||||
|                 if ((rss_flags & RTL8125_UDP_RSS_FLAGS) && | ||||
|                     !(tp->rss_flags & RTL8125_UDP_RSS_FLAGS)) | ||||
|                         netdev_warn(tp->dev, | ||||
|                                     "enabling UDP RSS: fragmented packets may " | ||||
|                                     "arrive out of order to the stack above\n"); | ||||
| 
 | ||||
|                 tp->rss_flags = rss_flags; | ||||
| 
 | ||||
|                 /* Perform hash on these packet types */ | ||||
|                 rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP | ||||
|                             | RSS_CTRL_IPV4_SUPP | ||||
|                             | RSS_CTRL_IPV6_SUPP | ||||
|                             | RSS_CTRL_TCP_IPV6_SUPP; | ||||
| 
 | ||||
|                 rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP | | ||||
|                               RSS_CTRL_UDP_IPV6_SUPP); | ||||
| 
 | ||||
|                 if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) | ||||
|                         rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; | ||||
| 
 | ||||
|                 if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) | ||||
|                         rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; | ||||
| 
 | ||||
|                 RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); | ||||
|         } | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(dev); | ||||
|         int ret = -EOPNOTSUPP; | ||||
| 
 | ||||
|         netif_info(tp, drv, tp->dev, "rss set rxnfc\n"); | ||||
| 
 | ||||
|         if (!(dev->features & NETIF_F_RXHASH)) | ||||
|                 return ret; | ||||
| 
 | ||||
|         switch (cmd->cmd) { | ||||
|         case ETHTOOL_SRXFH: | ||||
|                 ret = rtl8125_set_rss_hash_opt(tp, cmd); | ||||
|                 break; | ||||
|         default: | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         return ret; | ||||
| } | ||||
| 
 | ||||
| static u32 _rtl8125_get_rxfh_key_size(struct rtl8125_private *tp) | ||||
| { | ||||
|         return sizeof(tp->rss_key); | ||||
| } | ||||
| 
 | ||||
| u32 rtl8125_get_rxfh_key_size(struct net_device *dev) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(dev); | ||||
| 
 | ||||
|         netif_info(tp, drv, tp->dev, "rss get key size\n"); | ||||
| 
 | ||||
|         if (!(dev->features & NETIF_F_RXHASH)) | ||||
|                 return 0; | ||||
| 
 | ||||
|         return _rtl8125_get_rxfh_key_size(tp); | ||||
| } | ||||
| 
 | ||||
| u32 rtl8125_rss_indir_size(struct net_device *dev) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(dev); | ||||
| 
 | ||||
|         netif_info(tp, drv, tp->dev, "rss get indir tbl size\n"); | ||||
| 
 | ||||
|         if (!(dev->features & NETIF_F_RXHASH)) | ||||
|                 return 0; | ||||
| 
 | ||||
|         return rtl8125_rss_indir_tbl_entries(tp); | ||||
| } | ||||
| 
 | ||||
| static void rtl8125_get_reta(struct rtl8125_private *tp, u32 *indir) | ||||
| { | ||||
|         int i, reta_size = rtl8125_rss_indir_tbl_entries(tp); | ||||
| 
 | ||||
|         for (i = 0; i < reta_size; i++) | ||||
|                 indir[i] = tp->rss_indir_tbl[i]; | ||||
| } | ||||
| 
 | ||||
| int rtl8125_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, | ||||
|                      u8 *hfunc) | ||||
| { | ||||
|         struct rtl8125_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) | ||||
|                 rtl8125_get_reta(tp, indir); | ||||
| 
 | ||||
|         if (key) | ||||
|                 memcpy(key, tp->rss_key, rtl8125_get_rxfh_key_size(dev)); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static u32 rtl8125_rss_key_reg(struct rtl8125_private *tp) | ||||
| { | ||||
|         return RSS_KEY_8125; | ||||
| } | ||||
| 
 | ||||
| static u32 rtl8125_rss_indir_tbl_reg(struct rtl8125_private *tp) | ||||
| { | ||||
|         return RSS_INDIRECTION_TBL_8125_V2; | ||||
| } | ||||
| 
 | ||||
| static void rtl8125_store_reta(struct rtl8125_private *tp) | ||||
| { | ||||
|         u16 indir_tbl_reg = rtl8125_rss_indir_tbl_reg(tp); | ||||
|         u32 i, reta_entries = rtl8125_rss_indir_tbl_entries(tp); | ||||
|         u32 reta = 0; | ||||
|         u8 *indir_tbl = tp->rss_indir_tbl; | ||||
| 
 | ||||
|         /* Write redirection table to HW */ | ||||
|         for (i = 0; i < reta_entries; i++) { | ||||
|                 reta |= indir_tbl[i] << (i & 0x3) * 8; | ||||
|                 if ((i & 3) == 3) { | ||||
|                         RTL_W32(tp, indir_tbl_reg, reta); | ||||
| 
 | ||||
|                         indir_tbl_reg += 4; | ||||
|                         reta = 0; | ||||
|                 } | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| static void rtl8125_store_rss_key(struct rtl8125_private *tp) | ||||
| { | ||||
|         const u16 rss_key_reg = rtl8125_rss_key_reg(tp); | ||||
|         u32 i, rss_key_size = _rtl8125_get_rxfh_key_size(tp); | ||||
|         u32 *rss_key = (u32*)tp->rss_key; | ||||
| 
 | ||||
|         /* Write redirection table to HW */ | ||||
|         for (i = 0; i < rss_key_size; i+=4) | ||||
|                 RTL_W32(tp, rss_key_reg + i, *rss_key++); | ||||
| } | ||||
| 
 | ||||
| int rtl8125_set_rxfh(struct net_device *dev, const u32 *indir, | ||||
|                      const u8 *key, const u8 hfunc) | ||||
| { | ||||
|         struct rtl8125_private *tp = netdev_priv(dev); | ||||
|         int i; | ||||
|         u32 reta_entries = rtl8125_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 (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) | ||||
|                 return -EOPNOTSUPP; | ||||
| 
 | ||||
|         /* Fill out the redirection table */ | ||||
|         if (indir) { | ||||
|                 int max_queues = tp->num_rx_rings; | ||||
| 
 | ||||
|                 /* Verify user input. */ | ||||
|                 for (i = 0; i < reta_entries; i++) | ||||
|                         if (indir[i] >= max_queues) | ||||
|                                 return -EINVAL; | ||||
| 
 | ||||
|                 for (i = 0; i < reta_entries; i++) | ||||
|                         tp->rss_indir_tbl[i] = indir[i]; | ||||
|         } | ||||
| 
 | ||||
|         /* Fill out the rss hash key */ | ||||
|         if (key) | ||||
|                 memcpy(tp->rss_key, key, rtl8125_get_rxfh_key_size(dev)); | ||||
| 
 | ||||
|         rtl8125_store_reta(tp); | ||||
| 
 | ||||
|         rtl8125_store_rss_key(tp); | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static u32 rtl8125_get_rx_desc_hash(struct rtl8125_private *tp, | ||||
|                                     struct RxDescV3 *descv3) | ||||
| { | ||||
|         return le32_to_cpu(descv3->RxDescNormalDDWord2.RSSResult); | ||||
| } | ||||
| 
 | ||||
| #define RXS_8125B_RSS_UDP BIT(9) | ||||
| #define RXS_8125_RSS_IPV4 BIT(10) | ||||
| #define RXS_8125_RSS_IPV6 BIT(12) | ||||
| #define RXS_8125_RSS_TCP BIT(13) | ||||
| #define RTL8125_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6) | ||||
| #define RTL8125_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP) | ||||
| void rtl8125_rx_hash(struct rtl8125_private *tp, | ||||
|                      struct RxDescV3 *descv3, | ||||
|                      struct sk_buff *skb) | ||||
| { | ||||
|         u16 rss_header_info; | ||||
| 
 | ||||
|         if (!(tp->dev->features & NETIF_F_RXHASH)) | ||||
|                 return; | ||||
| 
 | ||||
|         rss_header_info = le16_to_cpu(descv3->RxDescNormalDDWord2.HeaderInfo); | ||||
| 
 | ||||
|         if (!(rss_header_info & RTL8125_RXS_RSS_L3_TYPE_MASK)) | ||||
|                 return; | ||||
| 
 | ||||
|         skb_set_hash(skb, rtl8125_get_rx_desc_hash(tp, descv3), | ||||
|                      (RTL8125_RXS_RSS_L4_TYPE_MASK & rss_header_info) ? | ||||
|                      PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_disable_rss(struct rtl8125_private *tp) | ||||
| { | ||||
|         RTL_W32(tp, RSS_CTRL_8125, 0x00); | ||||
| } | ||||
| 
 | ||||
| void _rtl8125_config_rss(struct rtl8125_private *tp) | ||||
| { | ||||
|         _rtl8125_set_rss_hash_opt(tp); | ||||
| 
 | ||||
|         rtl8125_store_reta(tp); | ||||
| 
 | ||||
|         rtl8125_store_rss_key(tp); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_config_rss(struct rtl8125_private *tp) | ||||
| { | ||||
|         if (!tp->EnableRss) { | ||||
|                 rtl8125_disable_rss(tp); | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
|         _rtl8125_config_rss(tp); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_init_rss(struct rtl8125_private *tp) | ||||
| { | ||||
|         int i; | ||||
| 
 | ||||
|         for (i = 0; i < rtl8125_rss_indir_tbl_entries(tp); i++) | ||||
|                 tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings); | ||||
| 
 | ||||
|         netdev_rss_key_fill(tp->rss_key, RTL8125_RSS_KEY_SIZE); | ||||
| } | ||||
							
								
								
									
										69
									
								
								r8125/src/r8125_rss.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										69
									
								
								r8125/src/r8125_rss.h
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,69 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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_rtl8125_RSS_H | ||||
| #define _LINUX_rtl8125_RSS_H | ||||
| 
 | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| #define RTL8125_RSS_KEY_SIZE     40  /* size of RSS Hash Key in bytes */ | ||||
| #define RTL8125_MAX_INDIRECTION_TABLE_ENTRIES 128 | ||||
| 
 | ||||
| enum rtl8125_rss_flag { | ||||
|         RTL_8125_RSS_FLAG_HASH_UDP_IPV4  = (1 << 0), | ||||
|         RTL_8125_RSS_FLAG_HASH_UDP_IPV6  = (1 << 1), | ||||
| }; | ||||
| 
 | ||||
| struct rtl8125_private; | ||||
| 
 | ||||
| int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, | ||||
|                       u32 *rule_locs); | ||||
| int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); | ||||
| u32 rtl8125_get_rxfh_key_size(struct net_device *netdev); | ||||
| u32 rtl8125_rss_indir_size(struct net_device *netdev); | ||||
| int rtl8125_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, | ||||
|                      u8 *hfunc); | ||||
| int rtl8125_set_rxfh(struct net_device *netdev, const u32 *indir, | ||||
|                      const u8 *key, const u8 hfunc); | ||||
| void rtl8125_rx_hash(struct rtl8125_private *tp, | ||||
|                      struct RxDescV3 *descv3, | ||||
|                      struct sk_buff *skb); | ||||
| void _rtl8125_config_rss(struct rtl8125_private *tp); | ||||
| void rtl8125_config_rss(struct rtl8125_private *tp); | ||||
| void rtl8125_init_rss(struct rtl8125_private *tp); | ||||
| u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp); | ||||
| void rtl8125_disable_rss(struct rtl8125_private *tp); | ||||
| 
 | ||||
| #endif /* _LINUX_rtl8125_RSS_H */ | ||||
							
								
								
									
										289
									
								
								r8125/src/rtl_eeprom.c
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										289
									
								
								r8125/src/rtl_eeprom.c
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,289 @@ | |||
| // SPDX-License-Identifier: GPL-2.0-only
 | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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/init.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/delay.h> | ||||
| 
 | ||||
| #include <asm/io.h> | ||||
| 
 | ||||
| #include "r8125.h" | ||||
| #include "rtl_eeprom.h" | ||||
| 
 | ||||
| //-------------------------------------------------------------------
 | ||||
| //rtl8125_eeprom_type():
 | ||||
| //  tell the eeprom type
 | ||||
| //return value:
 | ||||
| //  0: the eeprom type is 93C46
 | ||||
| //  1: the eeprom type is 93C56 or 93C66
 | ||||
| //-------------------------------------------------------------------
 | ||||
| void rtl8125_eeprom_type(struct rtl8125_private *tp) | ||||
| { | ||||
|         u16 magic = 0; | ||||
| 
 | ||||
|         if (tp->mcfg == CFG_METHOD_DEFAULT) | ||||
|                 goto out_no_eeprom; | ||||
| 
 | ||||
|         if(RTL_R8(tp, 0xD2)&0x04) { | ||||
|                 //not support
 | ||||
|                 //tp->eeprom_type = EEPROM_TWSI;
 | ||||
|                 //tp->eeprom_len = 256;
 | ||||
|                 goto out_no_eeprom; | ||||
|         } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) { | ||||
|                 tp->eeprom_type = EEPROM_TYPE_93C56; | ||||
|                 tp->eeprom_len = 256; | ||||
|         } else { | ||||
|                 tp->eeprom_type = EEPROM_TYPE_93C46; | ||||
|                 tp->eeprom_len = 128; | ||||
|         } | ||||
| 
 | ||||
|         magic = rtl8125_eeprom_read_sc(tp, 0); | ||||
| 
 | ||||
| out_no_eeprom: | ||||
|         if ((magic != 0x8129) && (magic != 0x8128)) { | ||||
|                 tp->eeprom_type = EEPROM_TYPE_NONE; | ||||
|                 tp->eeprom_len = 0; | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| void rtl8125_eeprom_cleanup(struct rtl8125_private *tp) | ||||
| { | ||||
|         u8 x; | ||||
| 
 | ||||
|         x = RTL_R8(tp, Cfg9346); | ||||
|         x &= ~(Cfg9346_EEDI | Cfg9346_EECS); | ||||
| 
 | ||||
|         RTL_W8(tp, Cfg9346, x); | ||||
| 
 | ||||
|         rtl8125_raise_clock(tp, &x); | ||||
|         rtl8125_lower_clock(tp, &x); | ||||
| } | ||||
| 
 | ||||
| int rtl8125_eeprom_cmd_done(struct rtl8125_private *tp) | ||||
| { | ||||
|         u8 x; | ||||
|         int i; | ||||
| 
 | ||||
|         rtl8125_stand_by(tp); | ||||
| 
 | ||||
|         for (i = 0; i < 50000; i++) { | ||||
|                 x = RTL_R8(tp, Cfg9346); | ||||
| 
 | ||||
|                 if (x & Cfg9346_EEDO) { | ||||
|                         udelay(RTL_CLOCK_RATE * 2 * 3); | ||||
|                         return 0; | ||||
|                 } | ||||
|                 udelay(1); | ||||
|         } | ||||
| 
 | ||||
|         return -1; | ||||
| } | ||||
| 
 | ||||
| //-------------------------------------------------------------------
 | ||||
| //rtl8125_eeprom_read_sc():
 | ||||
| //  read one word from eeprom
 | ||||
| //-------------------------------------------------------------------
 | ||||
| u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg) | ||||
| { | ||||
|         int addr_sz = 6; | ||||
|         u8 x; | ||||
|         u16 data; | ||||
| 
 | ||||
|         if(tp->eeprom_type == EEPROM_TYPE_NONE) { | ||||
|                 return -1; | ||||
|         } | ||||
| 
 | ||||
|         if (tp->eeprom_type==EEPROM_TYPE_93C46) | ||||
|                 addr_sz = 6; | ||||
|         else if (tp->eeprom_type==EEPROM_TYPE_93C56) | ||||
|                 addr_sz = 8; | ||||
| 
 | ||||
|         x = Cfg9346_EEM1 | Cfg9346_EECS; | ||||
|         RTL_W8(tp, Cfg9346, x); | ||||
| 
 | ||||
|         rtl8125_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3); | ||||
|         rtl8125_shift_out_bits(tp, reg, addr_sz); | ||||
| 
 | ||||
|         data = rtl8125_shift_in_bits(tp); | ||||
| 
 | ||||
|         rtl8125_eeprom_cleanup(tp); | ||||
| 
 | ||||
|         RTL_W8(tp, Cfg9346, 0); | ||||
| 
 | ||||
|         return data; | ||||
| } | ||||
| 
 | ||||
| //-------------------------------------------------------------------
 | ||||
| //rtl8125_eeprom_write_sc():
 | ||||
| //  write one word to a specific address in the eeprom
 | ||||
| //-------------------------------------------------------------------
 | ||||
| void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data) | ||||
| { | ||||
|         u8 x; | ||||
|         int addr_sz = 6; | ||||
|         int w_dummy_addr = 4; | ||||
| 
 | ||||
|         if(tp->eeprom_type == EEPROM_TYPE_NONE) { | ||||
|                 return ; | ||||
|         } | ||||
| 
 | ||||
|         if (tp->eeprom_type==EEPROM_TYPE_93C46) { | ||||
|                 addr_sz = 6; | ||||
|                 w_dummy_addr = 4; | ||||
|         } else if (tp->eeprom_type==EEPROM_TYPE_93C56) { | ||||
|                 addr_sz = 8; | ||||
|                 w_dummy_addr = 6; | ||||
|         } | ||||
| 
 | ||||
|         x = Cfg9346_EEM1 | Cfg9346_EECS; | ||||
|         RTL_W8(tp, Cfg9346, x); | ||||
| 
 | ||||
|         rtl8125_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5); | ||||
|         rtl8125_shift_out_bits(tp, reg, w_dummy_addr); | ||||
|         rtl8125_stand_by(tp); | ||||
| 
 | ||||
|         rtl8125_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); | ||||
|         rtl8125_shift_out_bits(tp, reg, addr_sz); | ||||
|         if (rtl8125_eeprom_cmd_done(tp) < 0) { | ||||
|                 return; | ||||
|         } | ||||
|         rtl8125_stand_by(tp); | ||||
| 
 | ||||
|         rtl8125_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); | ||||
|         rtl8125_shift_out_bits(tp, reg, addr_sz); | ||||
|         rtl8125_shift_out_bits(tp, data, 16); | ||||
|         if (rtl8125_eeprom_cmd_done(tp) < 0) { | ||||
|                 return; | ||||
|         } | ||||
|         rtl8125_stand_by(tp); | ||||
| 
 | ||||
|         rtl8125_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); | ||||
|         rtl8125_shift_out_bits(tp, reg, w_dummy_addr); | ||||
| 
 | ||||
|         rtl8125_eeprom_cleanup(tp); | ||||
|         RTL_W8(tp, Cfg9346, 0); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x) | ||||
| { | ||||
|         *x = *x | Cfg9346_EESK; | ||||
|         RTL_W8(tp, Cfg9346, *x); | ||||
|         udelay(RTL_CLOCK_RATE); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x) | ||||
| { | ||||
| 
 | ||||
|         *x = *x & ~Cfg9346_EESK; | ||||
|         RTL_W8(tp, Cfg9346, *x); | ||||
|         udelay(RTL_CLOCK_RATE); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count) | ||||
| { | ||||
|         u8 x; | ||||
|         int  mask; | ||||
| 
 | ||||
|         mask = 0x01 << (count - 1); | ||||
|         x = RTL_R8(tp, Cfg9346); | ||||
|         x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); | ||||
| 
 | ||||
|         do { | ||||
|                 if (data & mask) | ||||
|                         x |= Cfg9346_EEDI; | ||||
|                 else | ||||
|                         x &= ~Cfg9346_EEDI; | ||||
| 
 | ||||
|                 RTL_W8(tp, Cfg9346, x); | ||||
|                 udelay(RTL_CLOCK_RATE); | ||||
|                 rtl8125_raise_clock(tp, &x); | ||||
|                 rtl8125_lower_clock(tp, &x); | ||||
|                 mask = mask >> 1; | ||||
|         } while(mask); | ||||
| 
 | ||||
|         x &= ~Cfg9346_EEDI; | ||||
|         RTL_W8(tp, Cfg9346, x); | ||||
| } | ||||
| 
 | ||||
| u16 rtl8125_shift_in_bits(struct rtl8125_private *tp) | ||||
| { | ||||
|         u8 x; | ||||
|         u16 d, i; | ||||
| 
 | ||||
|         x = RTL_R8(tp, Cfg9346); | ||||
|         x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); | ||||
| 
 | ||||
|         d = 0; | ||||
| 
 | ||||
|         for (i = 0; i < 16; i++) { | ||||
|                 d = d << 1; | ||||
|                 rtl8125_raise_clock(tp, &x); | ||||
| 
 | ||||
|                 x = RTL_R8(tp, Cfg9346); | ||||
|                 x &= ~Cfg9346_EEDI; | ||||
| 
 | ||||
|                 if (x & Cfg9346_EEDO) | ||||
|                         d |= 1; | ||||
| 
 | ||||
|                 rtl8125_lower_clock(tp, &x); | ||||
|         } | ||||
| 
 | ||||
|         return d; | ||||
| } | ||||
| 
 | ||||
| void rtl8125_stand_by(struct rtl8125_private *tp) | ||||
| { | ||||
|         u8 x; | ||||
| 
 | ||||
|         x = RTL_R8(tp, Cfg9346); | ||||
|         x &= ~(Cfg9346_EECS | Cfg9346_EESK); | ||||
|         RTL_W8(tp, Cfg9346, x); | ||||
|         udelay(RTL_CLOCK_RATE); | ||||
| 
 | ||||
|         x |= Cfg9346_EECS; | ||||
|         RTL_W8(tp, Cfg9346, x); | ||||
| } | ||||
| 
 | ||||
| void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp) | ||||
| { | ||||
|         RTL_W8(tp, Cfg9346, Cfg9346_EEM1); | ||||
|         RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK); | ||||
| 
 | ||||
|         udelay(20); | ||||
| 
 | ||||
|         RTL_W8(tp, Cfg9346, Cfg9346_EEM1); | ||||
| } | ||||
							
								
								
									
										53
									
								
								r8125/src/rtl_eeprom.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										53
									
								
								r8125/src/rtl_eeprom.h
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,53 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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. | ||||
|  ***********************************************************************************/ | ||||
| 
 | ||||
| //EEPROM opcodes
 | ||||
| #define RTL_EEPROM_READ_OPCODE      06 | ||||
| #define RTL_EEPROM_WRITE_OPCODE     05 | ||||
| #define RTL_EEPROM_ERASE_OPCODE     07 | ||||
| #define RTL_EEPROM_EWEN_OPCODE      19 | ||||
| #define RTL_EEPROM_EWDS_OPCODE      16 | ||||
| 
 | ||||
| #define RTL_CLOCK_RATE  3 | ||||
| 
 | ||||
| void rtl8125_eeprom_type(struct rtl8125_private *tp); | ||||
| void rtl8125_eeprom_cleanup(struct rtl8125_private *tp); | ||||
| u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg); | ||||
| void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data); | ||||
| void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count); | ||||
| u16 rtl8125_shift_in_bits(struct rtl8125_private *tp); | ||||
| void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x); | ||||
| void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x); | ||||
| void rtl8125_stand_by(struct rtl8125_private *tp); | ||||
| void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp); | ||||
							
								
								
									
										320
									
								
								r8125/src/rtltool.c
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										320
									
								
								r8125/src/rtltool.c
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,320 @@ | |||
| // SPDX-License-Identifier: GPL-2.0-only
 | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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/module.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/in.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include "r8125.h" | ||||
| #include "rtl_eeprom.h" | ||||
| #include "rtltool.h" | ||||
| 
 | ||||
| int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr) | ||||
| { | ||||
|         struct rtltool_cmd my_cmd; | ||||
|         int ret; | ||||
| 
 | ||||
|         if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) | ||||
|                 return -EFAULT; | ||||
| 
 | ||||
|         ret = 0; | ||||
|         switch (my_cmd.cmd) { | ||||
|         case RTLTOOL_READ_MAC: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 if (my_cmd.len==1) | ||||
|                         my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); | ||||
|                 else if (my_cmd.len==2) | ||||
|                         my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1)); | ||||
|                 else if (my_cmd.len==4) | ||||
|                         my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3)); | ||||
|                 else { | ||||
|                         ret = -EOPNOTSUPP; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { | ||||
|                         ret = -EFAULT; | ||||
|                         break; | ||||
|                 } | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_WRITE_MAC: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 if (my_cmd.len==1) | ||||
|                         writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); | ||||
|                 else if (my_cmd.len==2) | ||||
|                         writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1)); | ||||
|                 else if (my_cmd.len==4) | ||||
|                         writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3)); | ||||
|                 else { | ||||
|                         ret = -EOPNOTSUPP; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_READ_PHY: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 my_cmd.data = rtl8125_mdio_prot_read(tp, my_cmd.offset); | ||||
|                 if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { | ||||
|                         ret = -EFAULT; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_WRITE_PHY: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 rtl8125_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_READ_EPHY: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 my_cmd.data = rtl8125_ephy_read(tp, my_cmd.offset); | ||||
|                 if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { | ||||
|                         ret = -EFAULT; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_WRITE_EPHY: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 rtl8125_ephy_write(tp, my_cmd.offset, my_cmd.data); | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_READ_ERI: | ||||
|                 my_cmd.data = 0; | ||||
|                 if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { | ||||
|                         my_cmd.data = rtl8125_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC); | ||||
|                 } else { | ||||
|                         ret = -EOPNOTSUPP; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { | ||||
|                         ret = -EFAULT; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_WRITE_ERI: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { | ||||
|                         rtl8125_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC); | ||||
|                 } else { | ||||
|                         ret = -EOPNOTSUPP; | ||||
|                         break; | ||||
|                 } | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_READ_PCI: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 my_cmd.data = 0; | ||||
|                 if (my_cmd.len==1) | ||||
|                         pci_read_config_byte(tp->pci_dev, my_cmd.offset, | ||||
|                                              (u8 *)&my_cmd.data); | ||||
|                 else if (my_cmd.len==2) | ||||
|                         pci_read_config_word(tp->pci_dev, my_cmd.offset, | ||||
|                                              (u16 *)&my_cmd.data); | ||||
|                 else if (my_cmd.len==4) | ||||
|                         pci_read_config_dword(tp->pci_dev, my_cmd.offset, | ||||
|                                               &my_cmd.data); | ||||
|                 else { | ||||
|                         ret = -EOPNOTSUPP; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { | ||||
|                         ret = -EFAULT; | ||||
|                         break; | ||||
|                 } | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_WRITE_PCI: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 if (my_cmd.len==1) | ||||
|                         pci_write_config_byte(tp->pci_dev, my_cmd.offset, | ||||
|                                               my_cmd.data); | ||||
|                 else if (my_cmd.len==2) | ||||
|                         pci_write_config_word(tp->pci_dev, my_cmd.offset, | ||||
|                                               my_cmd.data); | ||||
|                 else if (my_cmd.len==4) | ||||
|                         pci_write_config_dword(tp->pci_dev, my_cmd.offset, | ||||
|                                                my_cmd.data); | ||||
|                 else { | ||||
|                         ret = -EOPNOTSUPP; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_READ_EEPROM: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 my_cmd.data = rtl8125_eeprom_read_sc(tp, my_cmd.offset); | ||||
|                 if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { | ||||
|                         ret = -EFAULT; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|         case RTLTOOL_WRITE_EEPROM: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 rtl8125_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); | ||||
|                 break; | ||||
| 
 | ||||
|         case RTL_READ_OOB_MAC: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 rtl8125_oob_mutex_lock(tp); | ||||
|                 my_cmd.data = rtl8125_ocp_read(tp, my_cmd.offset, 4); | ||||
|                 rtl8125_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 (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 if (my_cmd.len == 0 || my_cmd.len > 4) | ||||
|                         return -EOPNOTSUPP; | ||||
| 
 | ||||
|                 rtl8125_oob_mutex_lock(tp); | ||||
|                 rtl8125_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data); | ||||
|                 rtl8125_oob_mutex_unlock(tp); | ||||
|                 break; | ||||
| 
 | ||||
|         case RTL_ENABLE_PCI_DIAG: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 tp->rtk_enable_diag = 1; | ||||
| 
 | ||||
|                 dprintk("enable rtk diag\n"); | ||||
|                 break; | ||||
| 
 | ||||
|         case RTL_DISABLE_PCI_DIAG: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 tp->rtk_enable_diag = 0; | ||||
| 
 | ||||
|                 dprintk("disable rtk diag\n"); | ||||
|                 break; | ||||
| 
 | ||||
|         case RTL_READ_MAC_OCP: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 if (my_cmd.offset % 2) | ||||
|                         return -EOPNOTSUPP; | ||||
| 
 | ||||
|                 my_cmd.data = rtl8125_mac_ocp_read(tp, my_cmd.offset); | ||||
|                 if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { | ||||
|                         ret = -EFAULT; | ||||
|                         break; | ||||
|                 } | ||||
|                 break; | ||||
| 
 | ||||
|         case RTL_WRITE_MAC_OCP: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 if ((my_cmd.offset % 2) || (my_cmd.len != 2)) | ||||
|                         return -EOPNOTSUPP; | ||||
| 
 | ||||
|                 rtl8125_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data); | ||||
|                 break; | ||||
| 
 | ||||
|         case RTL_DIRECT_READ_PHY_OCP: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 my_cmd.data = rtl8125_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); | ||||
|                 if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { | ||||
|                         ret = -EFAULT; | ||||
|                         break; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|         case RTL_DIRECT_WRITE_PHY_OCP: | ||||
|                 if (!capable(CAP_NET_ADMIN)) | ||||
|                         return -EPERM; | ||||
| 
 | ||||
|                 rtl8125_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); | ||||
|                 break; | ||||
| 
 | ||||
|         default: | ||||
|                 ret = -EOPNOTSUPP; | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         return ret; | ||||
| } | ||||
							
								
								
									
										86
									
								
								r8125/src/rtltool.h
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										86
									
								
								r8125/src/rtltool.h
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,86 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
| /*
 | ||||
| ################################################################################ | ||||
| # | ||||
| # r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet | ||||
| # controllers with PCI-Express interface. | ||||
| # | ||||
| # Copyright(c) 2021 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_RTLTOOL_H | ||||
| #define _LINUX_RTLTOOL_H | ||||
| 
 | ||||
| #define SIOCRTLTOOL		SIOCDEVPRIVATE+1 | ||||
| 
 | ||||
| enum rtl_cmd { | ||||
|         RTLTOOL_READ_MAC=0, | ||||
|         RTLTOOL_WRITE_MAC, | ||||
|         RTLTOOL_READ_PHY, | ||||
|         RTLTOOL_WRITE_PHY, | ||||
|         RTLTOOL_READ_EPHY, | ||||
|         RTLTOOL_WRITE_EPHY, | ||||
|         RTLTOOL_READ_ERI, | ||||
|         RTLTOOL_WRITE_ERI, | ||||
|         RTLTOOL_READ_PCI, | ||||
|         RTLTOOL_WRITE_PCI, | ||||
|         RTLTOOL_READ_EEPROM, | ||||
|         RTLTOOL_WRITE_EEPROM, | ||||
| 
 | ||||
|         RTL_READ_OOB_MAC, | ||||
|         RTL_WRITE_OOB_MAC, | ||||
| 
 | ||||
|         RTL_ENABLE_PCI_DIAG, | ||||
|         RTL_DISABLE_PCI_DIAG, | ||||
| 
 | ||||
|         RTL_READ_MAC_OCP, | ||||
|         RTL_WRITE_MAC_OCP, | ||||
| 
 | ||||
|         RTL_DIRECT_READ_PHY_OCP, | ||||
|         RTL_DIRECT_WRITE_PHY_OCP, | ||||
| 
 | ||||
|         RTLTOOL_INVALID | ||||
| }; | ||||
| 
 | ||||
| struct rtltool_cmd { | ||||
|         __u32	cmd; | ||||
|         __u32	offset; | ||||
|         __u32	len; | ||||
|         __u32	data; | ||||
| }; | ||||
| 
 | ||||
| enum mode_access { | ||||
|         MODE_NONE=0, | ||||
|         MODE_READ, | ||||
|         MODE_WRITE | ||||
| }; | ||||
| 
 | ||||
| #ifdef __KERNEL__ | ||||
| int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr); | ||||
| #endif | ||||
| 
 | ||||
| #endif /* _LINUX_RTLTOOL_H */ | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue