mirror of
https://github.com/FOGProject/fos.git
synced 2026-02-04 12:35:05 -06:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43e7edf786 | ||
|
|
8893d32bfb | ||
|
|
7a8264cf25 | ||
|
|
3f44c60ec2 | ||
|
|
dda9e28bc8 | ||
|
|
2e501640e7 | ||
|
|
ad837a6bd9 | ||
|
|
28cfe9eb4f | ||
|
|
710c27c4ed | ||
|
|
b3e34926b3 | ||
|
|
89b9608371 | ||
|
|
c69a804e3a | ||
|
|
61ed22b001 | ||
|
|
274999bcec | ||
|
|
4f434321ae | ||
|
|
cfa3187c79 | ||
|
|
1c99536c1e | ||
|
|
e5345d2800 | ||
|
|
2643db35bc | ||
|
|
0ceb4edc3e | ||
|
|
a6e712395e | ||
|
|
887ec3abff | ||
|
|
d50ae1de7b | ||
|
|
24d86d310e | ||
|
|
84036c68e6 | ||
|
|
f87f58758b | ||
|
|
d316ba2f97 | ||
|
|
2fe1159027 | ||
|
|
23f9f4fe60 | ||
|
|
b05c8e5e6a | ||
|
|
f3532b55c4 |
@ -1476,67 +1476,162 @@ getPartitions() {
|
||||
[[ -z $disk ]] && handleError "No disk found (${FUNCNAME[0]})\n Args Passed: $*"
|
||||
parts=$(lsblk -I 3,8,9,179,202,253,259 -lpno KNAME,TYPE $disk | awk '{if ($2 ~ /part/ || $2 ~ /md/) print $1}' | sort -V | uniq)
|
||||
}
|
||||
normalize() {
|
||||
local input="$*"
|
||||
|
||||
# If no arguments, read from stdin
|
||||
if [[ -z "$input" ]]; then
|
||||
input=$(cat)
|
||||
fi
|
||||
|
||||
echo $(trim "$input" | xargs | tr '[:upper:]' '[:lower:]')
|
||||
}
|
||||
resolve_path() {
|
||||
local input="$*"
|
||||
|
||||
# If no arguments, read from stdin
|
||||
if [[ -z "$input" ]]; then
|
||||
input=$(cat)
|
||||
fi
|
||||
|
||||
echo $(readlink -f "$input" 2>/dev/null || echo "$input")
|
||||
}
|
||||
# Gets the hard drive on the host
|
||||
# Note: This function makes a best guess
|
||||
getHardDisk() {
|
||||
hd=""
|
||||
disks=""
|
||||
local devs=$(lsblk -dpno KNAME -I 3,8,9,179,202,253,259 | uniq | sort -V)
|
||||
|
||||
# Get valid devices (filter out 0B disks) once, keeping lsblk enumeration order
|
||||
local devs
|
||||
devs=$(lsblk -dpno KNAME,SIZE -I 3,8,9,179,202,253,259 | awk '$2 != "0B" && !seen[$1]++ { print $1 }')
|
||||
|
||||
if [[ -n $fdrive ]]; then
|
||||
for spec in $(echo $fdrive | tr "," "\n"); do
|
||||
local found_match=0
|
||||
for spec in ${fdrive//,/ }; do
|
||||
local spec_resolved spec_norm spec_normalized matched
|
||||
spec_resolved=$(resolve_path "$spec")
|
||||
spec_normalized=$(normalize "$spec")
|
||||
matched=0
|
||||
|
||||
for dev in $devs; do
|
||||
if [[ "x$spec" = "x$dev" ||
|
||||
"x$spec" = "x$(trim $(blockdev --getsize64 $dev))" ||
|
||||
"x$spec" = "x$(trim $(lsblk -pdno SERIAL $dev))" ||
|
||||
"x$spec" = "x$(trim $(lsblk -pdno WWN $dev))" ]]; then
|
||||
disks=$(echo "$disks $dev")
|
||||
escaped_dev=$(echo $dev | sed -e 's/[]"\/$&*.^|[]/\\&/g')
|
||||
devs=$(echo ${devs} | sed "s/[[:space:]]*${escaped_dev}[[:space:]]*/ /")
|
||||
local size uuid serial wwn
|
||||
size=$(blockdev --getsize64 "$dev" | normalize)
|
||||
uuid=$(blkid -s UUID -o value "$dev" 2>/dev/null | normalize)
|
||||
# Grab SERIAL and WWN safely (handles blanks and spacing)
|
||||
local kv serial_raw wwn_raw
|
||||
kv="$(lsblk -pdPno SERIAL,WWN "$dev" 2>/dev/null)" || kv=""
|
||||
serial_raw="$(sed -n 's/.*SERIAL="\([^"]*\)".*/\1/p' <<<"$kv")"
|
||||
wwn_raw="$(sed -n 's/.*WWN="\([^"]*\)".*/\1/p' <<<"$kv")"
|
||||
|
||||
serial="$(normalize "$serial_raw")"
|
||||
wwn="$(normalize "$wwn_raw")"
|
||||
|
||||
[[ -n $isdebug ]] && {
|
||||
echo "Comparing spec='$spec' (resolved: '$spec_resolved') with dev=$dev"
|
||||
echo " size=$size serial=$serial wwn=$wwn uuid=$uuid"
|
||||
}
|
||||
if [[ "x$spec_resolved" == "x$dev" || \
|
||||
"x$spec_normalized" == "x$size" || \
|
||||
"x$spec_normalized" == "x$wwn" || \
|
||||
"x$spec_normalized" == "x$serial" || \
|
||||
"x$spec_normalized" == "x$uuid" ]]; then
|
||||
[[ -n $isdebug ]] && echo "Matched spec '$spec' to device '$dev' (size=$size, serial=$serial, wwn=$wwn, uuid=$uuid)"
|
||||
matched=1
|
||||
found_match=1
|
||||
disks="$disks $dev"
|
||||
# remove matched dev from the pool
|
||||
devs="$(echo " $devs " | sed "s# $dev # #g; s/^ *//; s/ *$//")"
|
||||
break
|
||||
else
|
||||
p1="$(trim $(blockdev --getsize64 $dev))"
|
||||
p2="$(trim $(lsblk -pdno SERIAL $dev))"
|
||||
p3="$(trim $(lsblk -pdno WWN $dev))"
|
||||
fi
|
||||
done
|
||||
|
||||
[[ $matched -eq 0 ]] && echo "WARNING: Drive spec '$spec' does not match any available device." >&2
|
||||
done
|
||||
disks=$( echo "${disks} ${devs}" | xargs)
|
||||
elif [[ -r ${imagePath}/d1.size && -r ${imagePath}/d2.size ]]; then
|
||||
disks=$(echo ${devs})
|
||||
disk_count=$(echo "$disks" | wc -w)
|
||||
disk_array=()
|
||||
size_information=$(cat ${imagePath}/*.size 2>/dev/null)
|
||||
for disk_number in $(seq 1 $disk_count); do
|
||||
disk=$(echo $disks | cut -d' ' -f $disk_number)
|
||||
if [[ -n "${size_information}" ]]; then
|
||||
disk_size=$(blockdev --getsize64 $disk)
|
||||
image_matching_size=$(echo ${size_information} | grep -o "[0-9][0-9]*:${disk_size}" | head -1 | cut -d':' -f1)
|
||||
if [[ -n $image_matching_size && $image_matching_size -gt 0 && $image_matching_size -le 32 ]]; then
|
||||
disk_number=$image_matching_size
|
||||
else
|
||||
closest_sized_image=$(echo -e "${size_information}\nx:${disk_size}" | sort -t':' -k2 -n | grep -B1 "${disk_size}" | head -1 | cut -d':' -f1 )
|
||||
if [[ -n $closest_sized_image && $closest_sized_image -gt 0 && $closest_sized_image -le 32 ]]; then
|
||||
disk_number=$closest_sized_image
|
||||
|
||||
[[ $found_match -eq 0 ]] && handleError "Fatal: No valid drives found for 'Host Primary Disk'='$fdrive'."
|
||||
|
||||
disks=$(echo "$disks $devs" | xargs) # add unmatched devices for completeness
|
||||
|
||||
elif [[ "x$imgType" == "xmpa" ]]; then
|
||||
# Multi-disk image: keep enumeration order
|
||||
disks="$devs"
|
||||
if [[ "x$type" == "xdown" ]]; then
|
||||
# Expected disk sizes from image (d1.size, d2.size, ...)
|
||||
local sizefiles expected_sizes=()
|
||||
sizefiles=$(ls -1 "${imagePath}"/d*.size 2>/dev/null | sort -V)
|
||||
|
||||
if [[ -n "$sizefiles" ]]; then
|
||||
local f exp
|
||||
for f in $sizefiles; do
|
||||
# file format: d1: 123456789
|
||||
exp="$(awk -F: '{gsub(/[[:space:]]/,"",$2); print $2}' "$f")"
|
||||
[[ -n "$exp" ]] && expected_sizes+=("$exp")
|
||||
done
|
||||
|
||||
# Actual disks (keep lsblk order)
|
||||
local actual_disks=()
|
||||
for d in $devs; do actual_disks+=("$d"); done
|
||||
|
||||
# Build mapping in d1,d2,... order
|
||||
local mapped=() used=" "
|
||||
local i match candidates
|
||||
|
||||
for i in "${!expected_sizes[@]}"; do
|
||||
exp="${expected_sizes[$i]}"
|
||||
match=""
|
||||
candidates=0
|
||||
|
||||
# Exact match pass
|
||||
for d in "${actual_disks[@]}"; do
|
||||
[[ "$used" == *" $d "* ]] && continue
|
||||
if [[ "$(blockdev --getsize64 "$d" 2>/dev/null)" == "$exp" ]]; then
|
||||
match="$d"
|
||||
candidates=$((candidates+1))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $candidates -eq 1 ]]; then
|
||||
mapped+=("$match")
|
||||
used+=" $match "
|
||||
continue
|
||||
fi
|
||||
|
||||
# Ambiguous or missing -> warn and fall back
|
||||
echo "WARNING: Could not uniquely match disk for expected size $exp (found $candidates exact matches). Falling back to enumeration order." >&2
|
||||
mapped=()
|
||||
break
|
||||
done
|
||||
|
||||
if [[ ${#mapped[@]} -gt 0 ]]; then
|
||||
disks="${mapped[*]}"
|
||||
hd="${mapped[0]}"
|
||||
return 0
|
||||
fi
|
||||
size_information=$(echo ${size_information} | sed "s/[[:space:]]*[0-9][0-9]*:${disk_size}[[:space:]]*//")
|
||||
fi
|
||||
echo "${disk_array[@]}" | grep -q "$disk"
|
||||
if [[ $? -eq 0 ]]; then
|
||||
handleError "Fatal Error: Disk size information would lead to overwrite the already cloned disk $disk. ($0)"
|
||||
fi
|
||||
disk_array[$disk_number]=$disk
|
||||
done
|
||||
disks=${disk_array[@]}
|
||||
fi
|
||||
else
|
||||
disks=$(echo ${devs})
|
||||
if [[ -n $largesize ]]; then
|
||||
# Auto-select largest available drive
|
||||
hd=$(
|
||||
for d in $devs; do
|
||||
echo "$(blockdev --getsize64 "$d") $d"
|
||||
done | sort -k1,1nr -k2,2 | head -1 | cut -d' ' -f2
|
||||
)
|
||||
else
|
||||
for d in $devs; do
|
||||
hd="$d"
|
||||
break
|
||||
done
|
||||
fi
|
||||
[[ -z $hd ]] && handleError "Could not determine a suitable disk automatically."
|
||||
disks="$hd"
|
||||
fi
|
||||
|
||||
for hd in $disks; do
|
||||
break
|
||||
done
|
||||
[[ -z $hd || -z $disks ]] && handleError "Cannot find hard disk(s) (${FUNCNAME[0]})\n Args Passed: $*"
|
||||
# Set primary hard disk
|
||||
hd=$(awk '{print $1}' <<< "$disks")
|
||||
}
|
||||
|
||||
# Finds the hard drive info and set's up the type
|
||||
findHDDInfo() {
|
||||
dots "Looking for Hard Disk(s)"
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
Binary files chntpw-140201/chntpw.static and chntpw-140201_new/chntpw.static differ
|
||||
diff -rupN chntpw-140201/Makefile chntpw-140201_new/Makefile
|
||||
--- chntpw-140201/Makefile 2014-02-01 11:54:37.000000000 -0500
|
||||
+++ chntpw-140201_new/Makefile 2014-03-06 21:17:44.603673531 -0500
|
||||
@@ -7,13 +7,8 @@
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 6b4531e..9be0b0e 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -7,13 +7,9 @@
|
||||
#
|
||||
|
||||
#SSLPATH=/usr/local/ssl
|
||||
-OSSLPATH=/usr
|
||||
+OSSLPATH=../../.././output/target/usr
|
||||
OSSLINC=$(OSSLPATH)/include
|
||||
-
|
||||
|
||||
-CC=gcc
|
||||
-
|
||||
-# Force 32 bit
|
||||
@ -17,13 +17,13 @@ diff -rupN chntpw-140201/Makefile chntpw-140201_new/Makefile
|
||||
OSSLLIB=$(OSSLPATH)/lib
|
||||
|
||||
# 64 bit if default for compiler setup
|
||||
@@ -26,37 +21,22 @@ OSSLLIB=$(OSSLPATH)/lib
|
||||
@@ -26,36 +22,23 @@ OSSLLIB=$(OSSLPATH)/lib
|
||||
LIBS=-L$(OSSLLIB)
|
||||
|
||||
|
||||
-all: chntpw chntpw.static cpnt reged reged.static samusrgrp samusrgrp.static sampasswd sampasswd.static
|
||||
-
|
||||
+all: chntpw cpnt reged samusrgrp sampasswd
|
||||
|
||||
chntpw: chntpw.o ntreg.o edlib.o libsam.o
|
||||
$(CC) $(CFLAGS) -o chntpw chntpw.o ntreg.o edlib.o libsam.o $(LIBS)
|
||||
|
||||
@ -52,10 +52,50 @@ diff -rupN chntpw-140201/Makefile chntpw-140201_new/Makefile
|
||||
- $(CC) -static $(CFLAGS) -o sampasswd.static sampasswd.o ntreg.o libsam.o
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
#ts: ts.o ntreg.o
|
||||
# $(CC) $(CFLAGS) -nostdlib -o ts ts.o ntreg.o $(LIBS)
|
||||
diff --git a/chntpw-presplit.c b/chntpw-presplit.c
|
||||
index 824fed5..a8203b9 100644
|
||||
--- a/chntpw-presplit.c
|
||||
+++ b/chntpw-presplit.c
|
||||
@@ -582,7 +582,7 @@ int put_grp_members_sid(int grp, struct sid_array *sarray)
|
||||
|
||||
Binary files chntpw-140201/reged.static and chntpw-140201_new/reged.static differ
|
||||
Binary files chntpw-140201/sampasswd.static and chntpw-140201_new/sampasswd.static differ
|
||||
Binary files chntpw-140201/samusrgrp.static and chntpw-140201_new/samusrgrp.static differ
|
||||
if (gverbose) printf("put_grp_members_sid: ajusted: mofs = %x, mlen = %x (%d)\n", mofs + 0x34 ,mlen,mlen);
|
||||
|
||||
- if (gverbose) hexdump(&c->data, 0, c->len, 1);
|
||||
+ if (gverbose) hexdump((char *)&c->data, 0, c->len, 1);
|
||||
|
||||
/* Get total size of new SID data */
|
||||
|
||||
@@ -610,7 +610,7 @@ int put_grp_members_sid(int grp, struct sid_array *sarray)
|
||||
cd->members_len = sidlen; /* Update member count in C struct */
|
||||
cd->grp_members = i;
|
||||
|
||||
- if (gverbose) hexdump(&c->data, 0, c->len, 1);
|
||||
+ if (gverbose) hexdump((char *)&c->data, 0, c->len, 1);
|
||||
|
||||
if (!put_buf2val(hive[H_SAM], c, 0, g, 0, TPF_VK_EXACT)) {
|
||||
fprintf(stderr,"put_grp_members_sid: could not write back group info in value %s\n",g);
|
||||
diff --git a/libsam.c b/libsam.c
|
||||
index 2c06c11..0932db7 100644
|
||||
--- a/libsam.c
|
||||
+++ b/libsam.c
|
||||
@@ -511,7 +511,7 @@ int sam_put_grp_members_sid(struct hive *hdesc, int grp, struct sid_array *sarra
|
||||
|
||||
if (gverbose) printf("put_grp_members_sid: ajusted: mofs = %x, mlen = %x (%d)\n", mofs + 0x34 ,mlen,mlen);
|
||||
|
||||
- if (gverbose) hexdump(&c->data, 0, c->len, 1);
|
||||
+ if (gverbose) hexdump((char *)&c->data, 0, c->len, 1);
|
||||
|
||||
/* Get total size of new SID data */
|
||||
|
||||
@@ -539,7 +539,7 @@ int sam_put_grp_members_sid(struct hive *hdesc, int grp, struct sid_array *sarra
|
||||
cd->members_len = sidlen; /* Update member count in C struct */
|
||||
cd->grp_members = i;
|
||||
|
||||
- if (gverbose) hexdump(&c->data, 0, c->len, 1);
|
||||
+ if (gverbose) hexdump((char *)&c->data, 0, c->len, 1);
|
||||
|
||||
if (!put_buf2val(hdesc, c, 0, g, 0, TPF_VK_EXACT)) {
|
||||
fprintf(stderr,"put_grp_members_sid: could not write back group info in value %s\n",g);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# testdisk
|
||||
#
|
||||
#############################################################
|
||||
TESTDISK_VERSION:=7.1
|
||||
TESTDISK_VERSION:=7.2
|
||||
TESTDISK_SOURCE:=testdisk-$(TESTDISK_VERSION).tar.bz2
|
||||
TESTDISK_SITE:=http://www.cgsecurity.org
|
||||
TESTDISK_INSTALL_STAGING=YES
|
||||
|
||||
5
KernelPackages/drivers/net/ethernet/realtek/Kconfig
Normal file
5
KernelPackages/drivers/net/ethernet/realtek/Kconfig
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
source "drivers/net/ethernet/realtek/r8125/Kconfig"
|
||||
source "drivers/net/ethernet/realtek/r8126/Kconfig"
|
||||
source "drivers/net/ethernet/realtek/r8168/Kconfig"
|
||||
|
||||
4
KernelPackages/drivers/net/ethernet/realtek/Makefile
Normal file
4
KernelPackages/drivers/net/ethernet/realtek/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
obj-$(CONFIG_R8125) += r8125/
|
||||
obj-$(CONFIG_R8126) += r8126/
|
||||
obj-$(CONFIG_R8168) += r8168/
|
||||
@ -0,0 +1 @@
|
||||
savedcmd_drivers/net/ethernet/realtek/r8125/built-in.a := rm -f drivers/net/ethernet/realtek/r8125/built-in.a; printf "drivers/net/ethernet/realtek/r8125/%s " r8125_n.o rtl_eeprom.o rtltool.o r8125_fiber.o | xargs ar cDPrST drivers/net/ethernet/realtek/r8125/built-in.a
|
||||
1566
KernelPackages/drivers/net/ethernet/realtek/r8125/.r8125_fiber.o.cmd
Normal file
1566
KernelPackages/drivers/net/ethernet/realtek/r8125/.r8125_fiber.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1665
KernelPackages/drivers/net/ethernet/realtek/r8125/.r8125_n.o.cmd
Normal file
1665
KernelPackages/drivers/net/ethernet/realtek/r8125/.r8125_n.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1533
KernelPackages/drivers/net/ethernet/realtek/r8125/.rtl_eeprom.o.cmd
Normal file
1533
KernelPackages/drivers/net/ethernet/realtek/r8125/.rtl_eeprom.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1567
KernelPackages/drivers/net/ethernet/realtek/r8125/.rtltool.o.cmd
Normal file
1567
KernelPackages/drivers/net/ethernet/realtek/r8125/.rtltool.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
config R8125
|
||||
tristate "Realtek 2.5G Ethernet driver (r8125)"
|
||||
depends on PCI && MII
|
||||
help
|
||||
This is the official Realtek 2.5G Ethernet driver.
|
||||
|
||||
76
KernelPackages/drivers/net/ethernet/realtek/r8125/Makefile
Normal file
76
KernelPackages/drivers/net/ethernet/realtek/r8125/Makefile
Normal file
@ -0,0 +1,76 @@
|
||||
obj-$(CONFIG_R8125) += r8125.o
|
||||
r8125-objs += r8125_n.o rtl_eeprom.o rtltool.o r8125_fiber.o
|
||||
|
||||
EXTRA_CFLAGS += -DCONFIG_SOC_LAN
|
||||
EXTRA_CFLAGS += -DENABLE_FIBER_SUPPORT
|
||||
EXTRA_CFLAGS += -DCONFIG_ASPM
|
||||
EXTRA_CFLAGS += -DENABLE_S5WOL
|
||||
EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE
|
||||
EXTRA_CFLAGS += -DENABLE_GIGA_LITE
|
||||
# EXTRA_CFLAGS += -DCONFIG_R8125_NAPI # Need to check if needed
|
||||
# EXTRA_CFLAGS += -DCONFIG_R8125_VLAN # Need to check if needed
|
||||
|
||||
#
|
||||
# Other options that can be enabled if needed.
|
||||
#
|
||||
# ENABLE_REALWOW_SUPPORT:
|
||||
# r8125-objs += r8125_realwow.o
|
||||
# EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT
|
||||
#
|
||||
# ENABLE_DASH_SUPPORT:
|
||||
# r8125-objs += r8125_dash.o
|
||||
# EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT
|
||||
#
|
||||
# ENABLE_DASH_PRINTER_SUPPORT:
|
||||
# r8125-objs += r8125_dash.o
|
||||
# EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT
|
||||
#
|
||||
# CONFIG_DOWN_SPEED_100:
|
||||
# EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100
|
||||
#
|
||||
# ENABLE_S5_KEEP_CURR_MAC:
|
||||
# EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC
|
||||
#
|
||||
# ENABLE_EEE:
|
||||
# EXTRA_CFLAGS += -DENABLE_EEE
|
||||
#
|
||||
# ENABLE_S0_MAGIC_PACKET:
|
||||
# EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET
|
||||
#
|
||||
# ENABLE_MULTIPLE_TX_QUEUE:
|
||||
# EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE
|
||||
#
|
||||
# ENABLE_PTP_SUPPORT:
|
||||
# r8125-objs += r8125_ptp.o
|
||||
# EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT
|
||||
#
|
||||
# ENABLE_PTP_MASTER_MODE:
|
||||
# EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE
|
||||
#
|
||||
# ENABLE_RSS_SUPPORT:
|
||||
# r8125-objs += r8125_rss.o
|
||||
# EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT
|
||||
#
|
||||
# ENABLE_LIB_SUPPORT:
|
||||
# r8125-objs += r8125_lib.o
|
||||
# EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT
|
||||
#
|
||||
# ENABLE_USE_FIRMWARE_FILE:
|
||||
# r8125-objs += r8125_firmware.o
|
||||
# EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE
|
||||
#
|
||||
# DISABLE_WOL_SUPPORT:
|
||||
# EXTRA_CFLAGS += -DDISABLE_WOL_SUPPORT
|
||||
#
|
||||
# DISABLE_MULTI_MSIX_VECTOR:
|
||||
# EXTRA_CFLAGS += -DDISABLE_MULTI_MSIX_VECTOR
|
||||
#
|
||||
# ENABLE_DOUBLE_VLAN:
|
||||
# EXTRA_CFLAGS += -DENABLE_DOUBLE_VLAN
|
||||
#
|
||||
# ENABLE_PAGE_REUSE:
|
||||
# EXTRA_CFLAGS += -DENABLE_PAGE_REUSE
|
||||
#
|
||||
# ENABLE_RX_PACKET_FRAGMENT:
|
||||
# EXTRA_CFLAGS += -DENABLE_RX_PACKET_FRAGMENT
|
||||
|
||||
11
KernelPackages/drivers/net/ethernet/realtek/r8125/built-in.a
Normal file
11
KernelPackages/drivers/net/ethernet/realtek/r8125/built-in.a
Normal file
@ -0,0 +1,11 @@
|
||||
!<thin>
|
||||
// 52 `
|
||||
r8125_n.o/
|
||||
rtl_eeprom.o/
|
||||
rtltool.o/
|
||||
r8125_fiber.o/
|
||||
|
||||
/0 0 0 0 644 455568 `
|
||||
/11 0 0 0 644 10016 `
|
||||
/25 0 0 0 644 6712 `
|
||||
/36 0 0 0 644 10992 `
|
||||
3058
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125.h
Normal file
3058
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125.h
Normal file
File diff suppressed because it is too large
Load Diff
196
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_dash.h
Normal file
196
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_dash.h
Normal file
@ -0,0 +1,196 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_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;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct _OSOOBHdr {
|
||||
__le32 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_FIRMWARE_MAJOR_VERSION (0x120)
|
||||
|
||||
#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 HW_DASH_SUPPORT_TYPE_4(_M) ((_M)->HwSuppDashVer == 4)
|
||||
#define HW_DASH_SUPPORT_CMAC(_M) (HW_DASH_SUPPORT_TYPE_2(_M) || HW_DASH_SUPPORT_TYPE_3(_M))
|
||||
#define HW_DASH_SUPPORT_IPC2(_M) (HW_DASH_SUPPORT_TYPE_4(_M))
|
||||
#define HW_DASH_SUPPORT_GET_FIRMWARE_VERSION(_M) (HW_DASH_SUPPORT_TYPE_2(_M) || \
|
||||
HW_DASH_SUPPORT_TYPE_3(_M) || \
|
||||
HW_DASH_SUPPORT_TYPE_4(_M))
|
||||
|
||||
#define RECV_FROM_FW_BUF_SIZE (1520)
|
||||
#define SEND_TO_FW_BUF_SIZE (1520)
|
||||
|
||||
#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 RXS_OWN BIT_15
|
||||
#define RXS_EOR BIT_14
|
||||
#define RXS_FS BIT_13
|
||||
#define RXS_LS BIT_12
|
||||
|
||||
#define ISRIMR_DASH_INTR_EN BIT_12
|
||||
|
||||
#define NO_BASE_ADDRESS 0x00000000
|
||||
|
||||
/* IB2SOC registers */
|
||||
#define IPC2_SWISR_DRIVER_READY 0x05
|
||||
#define IPC2_SWISR_DRIVER_EXIT 0x06
|
||||
#define IPC2_SWISR_CLIENTTOOL_SYNC_HOSTNAME 0x20
|
||||
#define IPC2_SWISR_DIS_DASH 0x55
|
||||
#define IPC2_SWISR_EN_DASH 0x56
|
||||
|
||||
#define IPC2_IB2SOC_SET 0x10
|
||||
#define IPC2_IB2SOC_DATA 0x14
|
||||
#define IPC2_IB2SOC_CMD 0x18
|
||||
#define IPC2_IB2SOC_IMR 0x1C
|
||||
|
||||
/* IPC2 registers */
|
||||
#define IPC2_PCIE_BASE 0xC100
|
||||
#define IPC2_TX_SET_REG IPC2_PCIE_BASE
|
||||
#define IPC2_TX_STATUS_REG (IPC2_PCIE_BASE+0x04)
|
||||
#define IPC2_RX_STATUS_REG (IPC2_PCIE_BASE+0x08)
|
||||
#define IPC2_RX_CLEAR_REG (IPC2_PCIE_BASE+0x0C)
|
||||
#define IPC2_DATA_BASE 0x32000
|
||||
#define IPC2_BUFFER_LENGTH 0x1000
|
||||
#define IPC2_DATA_MASTER IPC2_DATA_BASE //dash tx buffer base
|
||||
#define IPC2_DATA_SLAVE (IPC2_DATA_BASE+IPC2_BUFFER_LENGTH) //dash rx buffer base
|
||||
#define IPC2_TX_BUFFER IPC2_DATA_MASTER
|
||||
#define IPC2_RX_BUFFER IPC2_DATA_SLAVE
|
||||
|
||||
#define IPC2_TX_SEND_BIT BIT_0
|
||||
#define IPC2_TX_ACK_BIT BIT_8
|
||||
#define IPC2_RX_ROK_BIT BIT_0
|
||||
#define IPC2_RX_ACK_BIT BIT_8
|
||||
|
||||
/* IPC2 write/read MMIO register */
|
||||
#define RTL_DASH_IPC2_W8(tp, reg, val8) RTL_W8(tp, reg, val8)
|
||||
#define RTL_DASH_IPC2_W16(tp, reg, val16) RTL_W16(tp, reg, val16)
|
||||
#define RTL_DASH_IPC2_W32(tp, reg, val32) RTL_W32(tp, reg, val32)
|
||||
#define RTL_DASH_IPC2_R8(tp, reg) RTL_R8(tp, reg)
|
||||
#define RTL_DASH_IPC2_R16(tp, reg) RTL_R16(tp, reg)
|
||||
#define RTL_DASH_IPC2_R32(tp, reg) RTL_R32(tp, reg)
|
||||
|
||||
/* DASH OOB Header Type */
|
||||
#define DASH_OOB_HDR_TYPE_REQ 0x91
|
||||
#define DASH_OOB_HDR_TYPE_ACK 0x92
|
||||
|
||||
struct rtl8125_private;
|
||||
|
||||
int rtl8125_dash_ioctl(struct net_device *dev, struct ifreq *ifr);
|
||||
bool rtl8125_check_dash_interrupt(struct rtl8125_private *tp);
|
||||
void rtl8125_handle_dash_interrupt(struct net_device *dev);
|
||||
void rtl8125_clear_ipc2_isr(struct rtl8125_private *tp);
|
||||
void rtl8125_set_ipc2_soc_imr_bit(struct rtl8125_private *tp, u16 mask);
|
||||
void rtl8125_clear_ipc2_soc_imr_bit(struct rtl8125_private *tp, u16 mask);
|
||||
|
||||
#endif /* _LINUX_R8125_DASH_H */
|
||||
464
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_fiber.c
Normal file
464
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_fiber.c
Normal file
@ -0,0 +1,464 @@
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "r8125.h"
|
||||
#include "r8125_fiber.h"
|
||||
|
||||
static void
|
||||
rtl8125_fiber_set_mdc_gpio_c45(struct rtl8125_private *tp, bool pu)
|
||||
{
|
||||
if (pu)
|
||||
rtl8125_set_mac_ocp_bit(tp, 0xDC52, BIT_7);
|
||||
else
|
||||
rtl8125_clear_mac_ocp_bit(tp, 0xDC52, BIT_7);
|
||||
|
||||
//RtPciCommittp);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_set_mdc(struct rtl8125_private *tp, bool pu)
|
||||
{
|
||||
rtl8125_fiber_set_mdc_gpio_c45(tp, pu);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_set_mdcDownUp(struct rtl8125_private *tp)
|
||||
{
|
||||
udelay(1);
|
||||
rtl8125_fiber_set_mdc(tp, 0);
|
||||
udelay(1);
|
||||
rtl8125_fiber_set_mdc(tp, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_set_mdio_bit_gpio_c45(struct rtl8125_private *tp, bool pu)
|
||||
{
|
||||
if (pu)
|
||||
rtl8125_set_mac_ocp_bit(tp, 0xDC52, BIT_2);
|
||||
else
|
||||
rtl8125_clear_mac_ocp_bit(tp, 0xDC52, BIT_2);
|
||||
|
||||
//RtPciCommittp);
|
||||
|
||||
rtl8125_fiber_set_mdcDownUp(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_set_mdio_bit(struct rtl8125_private *tp, bool pu)
|
||||
{
|
||||
rtl8125_fiber_set_mdio_bit_gpio_c45(tp, pu);
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8125_fiber_get_mdio_bit_gpio_c45(struct rtl8125_private *tp)
|
||||
{
|
||||
rtl8125_fiber_set_mdcDownUp(tp);
|
||||
|
||||
return !!(rtl8125_mac_ocp_read(tp, 0xDC58) & BIT(2));
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8125_fiber_get_mdio_bit(struct rtl8125_private *tp)
|
||||
{
|
||||
return rtl8125_fiber_get_mdio_bit_gpio_c45(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_shift_bit_in(struct rtl8125_private *tp, u32 val, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = (count - 1); i >= 0; i--)
|
||||
rtl8125_fiber_set_mdio_bit(tp, !!(val & BIT(i)));
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8125_fiber_shift_bit_out(struct rtl8125_private *tp)
|
||||
{
|
||||
u16 data = 0;
|
||||
int i;
|
||||
|
||||
for (i = 15; i >= 0; i--)
|
||||
data += (rtl8125_fiber_get_mdio_bit(tp) << i);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_dir_gpio_c45(struct rtl8125_private *tp, bool output_mode)
|
||||
{
|
||||
if (output_mode)
|
||||
rtl8125_set_mac_ocp_bit(tp, 0xDC4C, BIT_2);
|
||||
else
|
||||
rtl8125_clear_mac_ocp_bit(tp, 0xDC4C, BIT_2);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_dir(struct rtl8125_private *tp, bool output_mode)
|
||||
{
|
||||
rtl8125_fiber_dir_gpio_c45(tp, output_mode);
|
||||
}
|
||||
|
||||
//fiber
|
||||
#define R8125_FIBER_C22 (0)
|
||||
#define R8125_FIBER_C45 (1)
|
||||
|
||||
// sfp opcodes
|
||||
#define R8125_FIBER_ST (1)
|
||||
#define R8125_FIBER_OP_W (1)
|
||||
#define R8125_FIBER_OP_R (2)
|
||||
#define R8125_FIBER_TA (2)
|
||||
|
||||
// sfp C45 opcodes
|
||||
#define R8125_FIBER_MDIO_C45 (BIT(15))
|
||||
#define R8125_FIBER_C45_ST (R8125_FIBER_MDIO_C45 | 0)
|
||||
#define R8125_FIBER_C45_OP_ADDR (R8125_FIBER_MDIO_C45 | 0)
|
||||
#define R8125_FIBER_C45_OP_W (R8125_FIBER_MDIO_C45 | 1)
|
||||
#define R8125_FIBER_C45_OP_R (R8125_FIBER_MDIO_C45 | 3)
|
||||
|
||||
static void
|
||||
rtl8125_fiber_cmd(struct rtl8125_private *tp, u32 cmd, u8 phy_addr,
|
||||
u32 reg)
|
||||
{
|
||||
/* change to output mode */
|
||||
rtl8125_fiber_dir(tp, 1);
|
||||
|
||||
/* preamble 32bit of 1 */
|
||||
rtl8125_fiber_shift_bit_in(tp, UINT_MAX, 32);
|
||||
|
||||
/* start bit */
|
||||
if (cmd & R8125_FIBER_MDIO_C45)
|
||||
rtl8125_fiber_shift_bit_in(tp, R8125_FIBER_C45_ST, 2);
|
||||
else
|
||||
rtl8125_fiber_shift_bit_in(tp, R8125_FIBER_ST, 2);
|
||||
|
||||
/* opcode */
|
||||
rtl8125_fiber_shift_bit_in(tp, cmd, 2);
|
||||
|
||||
/* phy address */
|
||||
rtl8125_fiber_shift_bit_in(tp, phy_addr, 5);
|
||||
|
||||
/* phy reg */
|
||||
rtl8125_fiber_shift_bit_in(tp, reg, 5);
|
||||
}
|
||||
|
||||
static u8
|
||||
rtl8125_fiber_cmdAddr(struct rtl8125_private *tp, u8 phy_addr, u32 reg)
|
||||
{
|
||||
u8 dev_addr = (reg >> 16) & 0x1F;
|
||||
u16 addr = (u16)reg;
|
||||
|
||||
rtl8125_fiber_cmd(tp, R8125_FIBER_C45_OP_ADDR, phy_addr, dev_addr);
|
||||
|
||||
/* turn-around(TA) */
|
||||
rtl8125_fiber_shift_bit_in(tp, R8125_FIBER_TA, 2);
|
||||
|
||||
rtl8125_fiber_shift_bit_in(tp, addr, 16);
|
||||
|
||||
rtl8125_fiber_dir(tp, 0);
|
||||
|
||||
rtl8125_fiber_get_mdio_bit(tp);
|
||||
|
||||
return dev_addr;
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_reset_gpio_c45(struct rtl8125_private *tp)
|
||||
{
|
||||
rtl8125_set_mac_ocp_bit(tp, 0xDC4C, (BIT_7 | BIT_2));
|
||||
|
||||
/* init sfp interface */
|
||||
rtl8125_clear_mac_ocp_bit(tp, 0xDC52, BIT_7);
|
||||
rtl8125_set_mac_ocp_bit(tp, 0xDC52, BIT_2);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_write_common(struct rtl8125_private *tp, u16 val)
|
||||
{
|
||||
/* turn-around(TA) */
|
||||
rtl8125_fiber_shift_bit_in(tp, R8125_FIBER_TA, 2);
|
||||
|
||||
/* write phy data */
|
||||
rtl8125_fiber_shift_bit_in(tp, val, 16);
|
||||
|
||||
/* change to input mode */
|
||||
rtl8125_fiber_dir(tp, 0);
|
||||
|
||||
rtl8125_fiber_get_mdio_bit(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_mdio_write_gpio_c45(
|
||||
struct rtl8125_private *tp,
|
||||
u32 reg,
|
||||
u16 val,
|
||||
u8 phy_addr)
|
||||
{
|
||||
/* opcode write */
|
||||
reg = rtl8125_fiber_cmdAddr(tp, phy_addr, reg);
|
||||
rtl8125_fiber_cmd(tp, R8125_FIBER_C45_OP_W, phy_addr, reg);
|
||||
|
||||
rtl8125_fiber_write_common(tp, val);
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8125_fiber_read_common(struct rtl8125_private *tp)
|
||||
{
|
||||
u16 data = 0;
|
||||
|
||||
/* change to input mode */
|
||||
rtl8125_fiber_dir(tp, 0);
|
||||
|
||||
/* TA 0 */
|
||||
rtl8125_fiber_get_mdio_bit(tp);
|
||||
|
||||
/* read phy data */
|
||||
data = rtl8125_fiber_shift_bit_out(tp);
|
||||
|
||||
rtl8125_fiber_get_mdio_bit(tp);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8125_fiber_mdio_read_gpio_c45(
|
||||
struct rtl8125_private *tp,
|
||||
u32 reg,
|
||||
u8 phy_addr)
|
||||
{
|
||||
reg = rtl8125_fiber_cmdAddr(tp, phy_addr, reg);
|
||||
rtl8125_fiber_cmd(tp, R8125_FIBER_C45_OP_R, phy_addr, reg);
|
||||
|
||||
return rtl8125_fiber_read_common(tp);
|
||||
}
|
||||
|
||||
void
|
||||
rtl8125_fiber_mdio_write(
|
||||
struct rtl8125_private *tp,
|
||||
u32 reg,
|
||||
u16 val)
|
||||
{
|
||||
switch(tp->HwFiberStat) {
|
||||
case FIBER_STAT_CONNECT_GPO_C45:
|
||||
return rtl8125_fiber_mdio_write_gpio_c45(tp, reg, val, 0);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u16
|
||||
rtl8125_fiber_mdio_read(
|
||||
struct rtl8125_private *tp,
|
||||
u32 reg)
|
||||
{
|
||||
switch(tp->HwFiberStat) {
|
||||
case FIBER_STAT_CONNECT_GPO_C45:
|
||||
return rtl8125_fiber_mdio_read_gpio_c45(tp, reg, 0);
|
||||
default:
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_clear_and_set_phy_bit(struct rtl8125_private *tp, u32 addr, u16 clearmask, u16 setmask)
|
||||
{
|
||||
u16 PhyRegValue;
|
||||
|
||||
PhyRegValue = rtl8125_fiber_mdio_read(tp, addr);
|
||||
PhyRegValue &= ~clearmask;
|
||||
PhyRegValue |= setmask;
|
||||
rtl8125_fiber_mdio_write(tp, addr, PhyRegValue);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_clear_phy_bit(struct rtl8125_private *tp, u32 addr, u16 mask)
|
||||
{
|
||||
rtl8125_fiber_clear_and_set_phy_bit(tp, addr, mask, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_set_phy_bit(struct rtl8125_private *tp, u32 addr, u16 mask)
|
||||
{
|
||||
rtl8125_fiber_clear_and_set_phy_bit(tp, addr, 0, mask);
|
||||
}
|
||||
|
||||
#define R8125_MAKE_C45_ADDR(_mmd, _addr) (_mmd << 16 | _addr)
|
||||
|
||||
static void
|
||||
rtl8125_fiber_phy_reset_8221d(struct rtl8125_private *tp)
|
||||
{
|
||||
u16 PhyRegValue;
|
||||
u32 Timeout;
|
||||
|
||||
rtl8125_fiber_set_phy_bit(tp, R8125_MAKE_C45_ADDR(0x01, 0x00), BIT_15);
|
||||
|
||||
Timeout = 0;
|
||||
do {
|
||||
udelay(1000);
|
||||
|
||||
PhyRegValue = rtl8125_fiber_mdio_read(tp, R8125_MAKE_C45_ADDR(0x01, 0x00));
|
||||
|
||||
Timeout++;
|
||||
} while ((PhyRegValue & BIT_15) && (Timeout < 20));
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_phy_reset(struct rtl8125_private *tp)
|
||||
{
|
||||
switch (tp->HwFiberModeVer) {
|
||||
case FIBER_MODE_RTL8125D_RTL8221D:
|
||||
rtl8125_fiber_phy_reset_8221d(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_set_rtl8221d_phy_mode(struct rtl8125_private *tp, u16 mode)
|
||||
{
|
||||
mode &= 0x3f;
|
||||
|
||||
rtl8125_fiber_clear_phy_bit(tp, R8125_MAKE_C45_ADDR(30, 0x75F3), BIT_0);
|
||||
rtl8125_fiber_clear_and_set_phy_bit(tp,
|
||||
R8125_MAKE_C45_ADDR(30, 0x697A),
|
||||
0x003F,
|
||||
mode);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_fiber_set_phy_mode(struct rtl8125_private *tp, u16 mode)
|
||||
{
|
||||
switch (tp->HwFiberModeVer) {
|
||||
case FIBER_MODE_RTL8125D_RTL8221D:
|
||||
rtl8125_fiber_set_rtl8221d_phy_mode(tp, mode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8125_hw_rtl8221d_phy_config(struct rtl8125_private *tp)
|
||||
{
|
||||
rtl8125_fiber_reset_gpio_c45(tp);
|
||||
|
||||
rtl8125_fiber_set_phy_mode(tp, (tp->speed == SPEED_2500) ? 0x02 : 0x04);
|
||||
|
||||
|
||||
rtl8125_fiber_clear_phy_bit(tp, R8125_MAKE_C45_ADDR(0x07, 0x3C), (BIT_2 | BIT_1));
|
||||
rtl8125_fiber_clear_phy_bit(tp, R8125_MAKE_C45_ADDR(0x07, 0x3E), (BIT_1 | BIT_0));
|
||||
|
||||
|
||||
rtl8125_fiber_phy_reset(tp);
|
||||
}
|
||||
|
||||
void
|
||||
rtl8125_hw_fiber_phy_config(struct rtl8125_private *tp)
|
||||
{
|
||||
switch (tp->HwFiberModeVer) {
|
||||
case FIBER_MODE_RTL8125D_RTL8221D:
|
||||
rtl8125_hw_rtl8221d_phy_config(tp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define RTL8221D_PHY_ID_1 0x001C
|
||||
#define RTL8221D_PHY_ID_2 0xC849
|
||||
static u32
|
||||
rtl8125_fiber_get_connect_status_8221d(struct rtl8125_private *tp)
|
||||
{
|
||||
int i;
|
||||
int const checkcnt = 4;
|
||||
|
||||
rtl8125_fiber_reset_gpio_c45(tp);
|
||||
|
||||
for (i = 0; i < checkcnt; i++) {
|
||||
if (RTL8221D_PHY_ID_1 != rtl8125_fiber_mdio_read_gpio_c45(tp, R8125_MAKE_C45_ADDR(0x01, 0x02), 0) ||
|
||||
RTL8221D_PHY_ID_2 != rtl8125_fiber_mdio_read_gpio_c45(tp, R8125_MAKE_C45_ADDR(0x01, 0x03), 0))
|
||||
return FIBER_STAT_DISCONNECT;
|
||||
}
|
||||
|
||||
return FIBER_STAT_CONNECT_GPO_C45;
|
||||
}
|
||||
|
||||
static u32
|
||||
rtl8125_fiber_get_connect_status(struct rtl8125_private *tp)
|
||||
{
|
||||
switch (tp->HwFiberModeVer) {
|
||||
case FIBER_MODE_RTL8125D_RTL8221D:
|
||||
return rtl8125_fiber_get_connect_status_8221d(tp);
|
||||
default:
|
||||
return FIBER_STAT_NOT_CHECKED;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtl8125_check_fiber_mode_support(struct rtl8125_private *tp)
|
||||
{
|
||||
switch(tp->mcfg) {
|
||||
case CFG_METHOD_10:
|
||||
case CFG_METHOD_11: {
|
||||
u8 tmp = (u8)rtl8125_mac_ocp_read(tp, 0xD006);
|
||||
if (tmp == 0x03)
|
||||
tp->HwFiberModeVer = FIBER_MODE_RTL8125D_RTL8221D;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (HW_FIBER_MODE_ENABLED(tp))
|
||||
tp->HwFiberStat = rtl8125_fiber_get_connect_status(tp);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
rtl8125_fiber_link_ok(struct net_device *dev)
|
||||
{
|
||||
struct rtl8125_private *tp = netdev_priv(dev);
|
||||
u16 status;
|
||||
|
||||
switch (tp->HwFiberStat) {
|
||||
case FIBER_STAT_CONNECT_GPO_C45:
|
||||
status = rtl8125_fiber_mdio_read(tp, R8125_MAKE_C45_ADDR(30, 0x758D));
|
||||
if (status != USHRT_MAX && status & BIT_1)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8125_FIBER_H
|
||||
#define _LINUX_R8125_FIBER_H
|
||||
|
||||
enum {
|
||||
FIBER_MODE_NIC_ONLY = 0,
|
||||
FIBER_MODE_RTL8125D_RTL8221D,
|
||||
FIBER_MODE_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
FIBER_STAT_NOT_CHECKED = 0,
|
||||
FIBER_STAT_DISCONNECT,
|
||||
FIBER_STAT_CONNECT_GPO_C45,
|
||||
FIBER_STAT_MAX
|
||||
};
|
||||
|
||||
#define HW_FIBER_MODE_ENABLED(_M) ((_M)->HwFiberModeVer > 0)
|
||||
#define HW_FIBER_STATUS_CONNECTED(_M) (((_M)->HwFiberStat == FIBER_STAT_CONNECT_GPO_C45))
|
||||
#define HW_FIBER_STATUS_DISCONNECTED(_M) ((_M)->HwFiberStat == FIBER_STAT_DISCONNECT)
|
||||
|
||||
struct rtl8125_private;
|
||||
|
||||
void rtl8125_hw_fiber_phy_config(struct rtl8125_private *tp);
|
||||
void rtl8125_check_fiber_mode_support(struct rtl8125_private *tp);
|
||||
void rtl8125_fiber_mdio_write( struct rtl8125_private *tp, u32 reg, u16 val);
|
||||
u16 rtl8125_fiber_mdio_read(struct rtl8125_private *tp, u32 reg);
|
||||
unsigned int rtl8125_fiber_link_ok(struct net_device *dev);
|
||||
|
||||
#endif /* _LINUX_R8125_FIBER_H */
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_fiber.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_fiber.o
Normal file
Binary file not shown.
@ -0,0 +1,264 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/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(1 * 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;
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_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 */
|
||||
21299
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_n.c
Normal file
21299
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_n.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_n.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_n.o
Normal file
Binary file not shown.
1472
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_ptp.c
Normal file
1472
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_ptp.c
Normal file
File diff suppressed because it is too large
Load Diff
159
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_ptp.h
Normal file
159
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_ptp.h
Normal file
@ -0,0 +1,159 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_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>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0)
|
||||
#define PTP_MSGTYPE_SYNC 0x0
|
||||
#define PTP_MSGTYPE_DELAY_REQ 0x1
|
||||
#define PTP_MSGTYPE_PDELAY_REQ 0x2
|
||||
#define PTP_MSGTYPE_PDELAY_RESP 0x3
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
|
||||
struct clock_identity {
|
||||
u8 id[8];
|
||||
} __packed;
|
||||
|
||||
struct port_identity {
|
||||
struct clock_identity clock_identity;
|
||||
__be16 port_number;
|
||||
} __packed;
|
||||
|
||||
struct ptp_header {
|
||||
u8 tsmt; /* transportSpecific | messageType */
|
||||
u8 ver; /* reserved | versionPTP */
|
||||
__be16 message_length;
|
||||
u8 domain_number;
|
||||
u8 reserved1;
|
||||
u8 flag_field[2];
|
||||
__be64 correction;
|
||||
__be32 reserved2;
|
||||
struct port_identity source_port_identity;
|
||||
__be16 sequence_id;
|
||||
u8 control;
|
||||
u8 log_message_interval;
|
||||
} __packed;
|
||||
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) */
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
#define PTP_CLKADJ_MODE_SET BIT_0
|
||||
|
||||
enum PTP_CLKADJ_MOD_TYPE {
|
||||
NO_FUNCTION = 0,
|
||||
CLKADJ_MODE_SET = 1,
|
||||
RESERVED = 2,
|
||||
DIRECT_READ = 4,
|
||||
DIRECT_WRITE = 6,
|
||||
INCREMENT_STEP = 8,
|
||||
DECREMENT_STEP = 10,
|
||||
RATE_READ = 12,
|
||||
RATE_WRITE = 14,
|
||||
};
|
||||
|
||||
enum PTP_INSR_TYPE {
|
||||
EVENT_CAP_INTR = (1 << 0),
|
||||
TRIG_GEN_INTR = (1 << 1),
|
||||
RX_TS_INTR = (1 << 2),
|
||||
TX_TX_INTR = (1 << 3),
|
||||
};
|
||||
|
||||
enum PTP_TRX_TS_STA_REG {
|
||||
TRX_TS_RD = (1 << 0),
|
||||
TRXTS_SEL = (1 << 1),
|
||||
RX_TS_PDLYRSP_RDY = (1 << 8),
|
||||
RX_TS_PDLYREQ_RDY = (1 << 9),
|
||||
RX_TS_DLYREQ_RDY = (1 << 10),
|
||||
RX_TS_SYNC_RDY = (1 << 11),
|
||||
TX_TS_PDLYRSP_RDY = (1 << 12),
|
||||
TX_TS_PDLYREQ_RDY = (1 << 13),
|
||||
TX_TS_DLYREQ_RDY = (1 << 14),
|
||||
TX_TS_SYNC_RDY = (1 << 15),
|
||||
};
|
||||
|
||||
#define RTL_FLAG_RX_HWTSTAMP_ENABLED BIT_0
|
||||
|
||||
struct rtl8125_private;
|
||||
struct RxDescV3;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,11,0)
|
||||
int rtl8125_get_ts_info(struct net_device *netdev,
|
||||
struct ethtool_ts_info *info);
|
||||
#else
|
||||
int rtl8125_get_ts_info(struct net_device *netdev,
|
||||
struct kernel_ethtool_ts_info *info);
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,11,0) */
|
||||
|
||||
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_mac_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb,
|
||||
struct RxDescV3 *descv3);
|
||||
|
||||
void rtl8125_set_phy_local_time(struct rtl8125_private *tp);
|
||||
|
||||
void rtl8125_rx_phy_ptp_timestamp(struct rtl8125_private *tp, struct sk_buff *skb);
|
||||
|
||||
#endif /* _LINUX_rtl8125_PTP_H */
|
||||
@ -0,0 +1,118 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_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 */
|
||||
583
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_rss.c
Normal file
583
KernelPackages/drivers/net/ethernet/realtek/r8125/r8125_rss.c
Normal file
@ -0,0 +1,583 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "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_CTRL_IPV6_EXT_SUPP = (1 << 4),
|
||||
RSS_CTRL_TCP_IPV6_EXT_SUPP = (1 << 5),
|
||||
RSS_HALF_SUPP = (1 << 7),
|
||||
RSS_CTRL_UDP_IPV4_SUPP = (1 << 11),
|
||||
RSS_CTRL_UDP_IPV6_SUPP = (1 << 12),
|
||||
RSS_CTRL_UDP_IPV6_EXT_SUPP = (1 << 13),
|
||||
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;
|
||||
|
||||
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_IPV6_EXT_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_EXT_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 |
|
||||
RSS_CTRL_UDP_IPV6_EXT_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;
|
||||
|
||||
/*
|
||||
* 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_IPV6_EXT_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_EXT_SUPP;
|
||||
|
||||
rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP |
|
||||
RSS_CTRL_UDP_IPV6_SUPP |
|
||||
RSS_CTRL_UDP_IPV6_EXT_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 |
|
||||
RSS_CTRL_UDP_IPV6_EXT_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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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++);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
|
||||
int rtl8125_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
|
||||
{
|
||||
struct rtl8125_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rxfh->hfunc = ETH_RSS_HASH_TOP;
|
||||
|
||||
if (rxfh->indir)
|
||||
rtl8125_get_reta(tp, rxfh->indir);
|
||||
|
||||
if (rxfh->key)
|
||||
memcpy(rxfh->key, tp->rss_key, RTL8125_RSS_KEY_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8125_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rtl8125_private *tp = netdev_priv(dev);
|
||||
int i;
|
||||
u32 reta_entries = rtl8125_rss_indir_tbl_entries(tp);
|
||||
|
||||
/* We require at least one supported parameter to be changed and no
|
||||
* change in any of the unsupported parameters
|
||||
*/
|
||||
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && rxfh->hfunc != ETH_RSS_HASH_TOP)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Fill out the redirection table */
|
||||
if (rxfh->indir) {
|
||||
int max_queues = tp->num_rx_rings;
|
||||
|
||||
/* Verify user input. */
|
||||
for (i = 0; i < reta_entries; i++)
|
||||
if (rxfh->indir[i] >= max_queues)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < reta_entries; i++)
|
||||
tp->rss_indir_tbl[i] = rxfh->indir[i];
|
||||
}
|
||||
|
||||
/* Fill out the rss hash key */
|
||||
if (rxfh->key)
|
||||
memcpy(tp->rss_key, rxfh->key, RTL8125_RSS_KEY_SIZE);
|
||||
|
||||
rtl8125_store_reta(tp);
|
||||
|
||||
rtl8125_store_rss_key(tp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int rtl8125_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
|
||||
u8 *hfunc)
|
||||
{
|
||||
struct rtl8125_private *tp = netdev_priv(dev);
|
||||
|
||||
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_RSS_KEY_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* 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_RSS_KEY_SIZE);
|
||||
|
||||
rtl8125_store_reta(tp);
|
||||
|
||||
rtl8125_store_rss_key(tp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
|
||||
|
||||
static u32 rtl8125_get_rx_desc_hash(struct rtl8125_private *tp,
|
||||
struct RxDesc *desc)
|
||||
{
|
||||
switch (tp->InitRxDescType) {
|
||||
case RX_DESC_RING_TYPE_3:
|
||||
return le32_to_cpu(((struct RxDescV3 *)desc)->RxDescNormalDDWord2.RSSResult);
|
||||
case RX_DESC_RING_TYPE_4:
|
||||
return le32_to_cpu(((struct RxDescV4 *)desc)->RxDescNormalDDWord1.RSSResult);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define RXS_8125B_RSS_UDP BIT(9)
|
||||
#define RXS_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)
|
||||
|
||||
#define RXS_8125B_RSS_UDP_V4 BIT(27)
|
||||
#define RXS_8125_RSS_IPV4_V4 BIT(28)
|
||||
#define RXS_8125_RSS_IPV6_V4 BIT(29)
|
||||
#define RXS_8125_RSS_TCP_V4 BIT(30)
|
||||
#define RTL8125_RXS_RSS_L3_TYPE_MASK_V4 (RXS_8125_RSS_IPV4_V4 | RXS_8125_RSS_IPV6_V4)
|
||||
#define RTL8125_RXS_RSS_L4_TYPE_MASK_V4 (RXS_8125_RSS_TCP_V4 | RXS_8125B_RSS_UDP_V4)
|
||||
static void rtl8125_rx_hash_v3(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, (struct RxDesc *)descv3),
|
||||
(RTL8125_RXS_RSS_L4_TYPE_MASK & rss_header_info) ?
|
||||
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
|
||||
}
|
||||
|
||||
static void rtl8125_rx_hash_v4(struct rtl8125_private *tp,
|
||||
struct RxDescV4 *descv4,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u32 rss_header_info;
|
||||
|
||||
if (!(tp->dev->features & NETIF_F_RXHASH))
|
||||
return;
|
||||
|
||||
rss_header_info = le32_to_cpu(descv4->RxDescNormalDDWord1.RSSInfo);
|
||||
|
||||
if (!(rss_header_info & RTL8125_RXS_RSS_L3_TYPE_MASK_V4))
|
||||
return;
|
||||
|
||||
skb_set_hash(skb, rtl8125_get_rx_desc_hash(tp, (struct RxDesc *)descv4),
|
||||
(RTL8125_RXS_RSS_L4_TYPE_MASK_V4 & rss_header_info) ?
|
||||
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
|
||||
}
|
||||
|
||||
void rtl8125_rx_hash(struct rtl8125_private *tp,
|
||||
struct RxDesc *desc,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
switch (tp->InitRxDescType) {
|
||||
case RX_DESC_RING_TYPE_3:
|
||||
rtl8125_rx_hash_v3(tp, (struct RxDescV3 *)desc, skb);
|
||||
break;
|
||||
case RX_DESC_RING_TYPE_4:
|
||||
rtl8125_rx_hash_v4(tp, (struct RxDescV4 *)desc, skb);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_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;
|
||||
struct RxDesc;
|
||||
|
||||
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);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
|
||||
int rtl8125_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh);
|
||||
int rtl8125_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack);
|
||||
#else
|
||||
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);
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
|
||||
void rtl8125_rx_hash(struct rtl8125_private *tp,
|
||||
struct RxDesc *desc,
|
||||
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 */
|
||||
284
KernelPackages/drivers/net/ethernet/realtek/r8125/rtl_eeprom.c
Normal file
284
KernelPackages/drivers/net/ethernet/realtek/r8125/rtl_eeprom.c
Normal file
@ -0,0 +1,284 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/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);
|
||||
}
|
||||
|
||||
static 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);
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
//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);
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8125/rtl_eeprom.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8125/rtl_eeprom.o
Normal file
Binary file not shown.
312
KernelPackages/drivers/net/ethernet/realtek/r8125/rtltool.c
Normal file
312
KernelPackages/drivers/net/ethernet/realtek/r8125/rtltool.c
Normal file
@ -0,0 +1,312 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/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;
|
||||
unsigned long flags;
|
||||
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 ((my_cmd.offset + my_cmd.len) > pci_resource_len(tp->pci_dev, 2)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
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 ((my_cmd.offset + my_cmd.len) > pci_resource_len(tp->pci_dev, 2)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
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:
|
||||
r8125_spin_lock(&tp->phy_lock, flags);
|
||||
my_cmd.data = rtl8125_mdio_prot_read(tp, my_cmd.offset);
|
||||
r8125_spin_unlock(&tp->phy_lock, flags);
|
||||
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RTLTOOL_WRITE_PHY:
|
||||
r8125_spin_lock(&tp->phy_lock, flags);
|
||||
rtl8125_mdio_prot_write(tp, my_cmd.offset, my_cmd.data);
|
||||
r8125_spin_unlock(&tp->phy_lock, flags);
|
||||
break;
|
||||
|
||||
case RTLTOOL_READ_EPHY:
|
||||
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:
|
||||
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 (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:
|
||||
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 (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:
|
||||
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:
|
||||
rtl8125_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data);
|
||||
break;
|
||||
|
||||
case RTL_READ_OOB_MAC:
|
||||
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 (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:
|
||||
r8125_spin_lock(&tp->phy_lock, flags);
|
||||
tp->rtk_enable_diag = 1;
|
||||
r8125_spin_unlock(&tp->phy_lock, flags);
|
||||
|
||||
dprintk("enable rtk diag\n");
|
||||
break;
|
||||
|
||||
case RTL_DISABLE_PCI_DIAG:
|
||||
r8125_spin_lock(&tp->phy_lock, flags);
|
||||
tp->rtk_enable_diag = 0;
|
||||
r8125_spin_unlock(&tp->phy_lock, flags);
|
||||
|
||||
dprintk("disable rtk diag\n");
|
||||
break;
|
||||
|
||||
case RTL_READ_MAC_OCP:
|
||||
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 ((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:
|
||||
r8125_spin_lock(&tp->phy_lock, flags);
|
||||
my_cmd.data = rtl8125_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset);
|
||||
r8125_spin_unlock(&tp->phy_lock, flags);
|
||||
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RTL_DIRECT_WRITE_PHY_OCP:
|
||||
r8125_spin_lock(&tp->phy_lock, flags);
|
||||
rtl8125_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data);
|
||||
r8125_spin_unlock(&tp->phy_lock, flags);
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_FIBER_SUPPORT
|
||||
case RTL_READ_FIBER_PHY:
|
||||
if (!HW_FIBER_STATUS_CONNECTED(tp)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
r8125_spin_lock(&tp->phy_lock, flags);
|
||||
my_cmd.data = rtl8125_fiber_mdio_read(tp, my_cmd.offset);
|
||||
r8125_spin_unlock(&tp->phy_lock, flags);
|
||||
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RTL_WRITE_FIBER_PHY:
|
||||
if (!HW_FIBER_STATUS_CONNECTED(tp)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
r8125_spin_lock(&tp->phy_lock, flags);
|
||||
rtl8125_fiber_mdio_write(tp, my_cmd.offset, my_cmd.data);
|
||||
r8125_spin_unlock(&tp->phy_lock, flags);
|
||||
break;
|
||||
#endif /* ENABLE_FIBER_SUPPORT */
|
||||
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
89
KernelPackages/drivers/net/ethernet/realtek/r8125/rtltool.h
Normal file
89
KernelPackages/drivers/net/ethernet/realtek/r8125/rtltool.h
Normal file
@ -0,0 +1,89 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8125 is the Linux device driver released for Realtek 2.5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2025 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_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,
|
||||
|
||||
RTL_READ_FIBER_PHY,
|
||||
RTL_WRITE_FIBER_PHY,
|
||||
|
||||
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 */
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8125/rtltool.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8125/rtltool.o
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
||||
savedcmd_drivers/net/ethernet/realtek/r8126/built-in.a := rm -f drivers/net/ethernet/realtek/r8126/built-in.a; printf "drivers/net/ethernet/realtek/r8126/%s " r8126_n.o rtl_eeprom.o rtltool.o r8126_fiber.o | xargs ar cDPrST drivers/net/ethernet/realtek/r8126/built-in.a
|
||||
1566
KernelPackages/drivers/net/ethernet/realtek/r8126/.r8126_fiber.o.cmd
Normal file
1566
KernelPackages/drivers/net/ethernet/realtek/r8126/.r8126_fiber.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1665
KernelPackages/drivers/net/ethernet/realtek/r8126/.r8126_n.o.cmd
Normal file
1665
KernelPackages/drivers/net/ethernet/realtek/r8126/.r8126_n.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1533
KernelPackages/drivers/net/ethernet/realtek/r8126/.rtl_eeprom.o.cmd
Normal file
1533
KernelPackages/drivers/net/ethernet/realtek/r8126/.rtl_eeprom.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1567
KernelPackages/drivers/net/ethernet/realtek/r8126/.rtltool.o.cmd
Normal file
1567
KernelPackages/drivers/net/ethernet/realtek/r8126/.rtltool.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
config R8126
|
||||
tristate "Realtek 5G Ethernet driver (r8126)"
|
||||
depends on PCI && MII
|
||||
help
|
||||
This is the official Realtek 5G Ethernet driver.
|
||||
|
||||
73
KernelPackages/drivers/net/ethernet/realtek/r8126/Makefile
Normal file
73
KernelPackages/drivers/net/ethernet/realtek/r8126/Makefile
Normal file
@ -0,0 +1,73 @@
|
||||
obj-$(CONFIG_R8126) += r8126.o
|
||||
r8126-objs += r8126_n.o rtl_eeprom.o rtltool.o r8126_fiber.o
|
||||
|
||||
EXTRA_CFLAGS += -DCONFIG_SOC_LAN
|
||||
EXTRA_CFLAGS += -DENABLE_FIBER_SUPPORT
|
||||
EXTRA_CFLAGS += -DCONFIG_ASPM
|
||||
EXTRA_CFLAGS += -DENABLE_S5WOL
|
||||
EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE
|
||||
EXTRA_CFLAGS += -DENABLE_GIGA_LITE
|
||||
# EXTRA_CFLAGS += -DCONFIG_R8126_NAPI # Need to check if needed
|
||||
# EXTRA_CFLAGS += -DCONFIG_R8126_VLAN # Need to check if needed
|
||||
|
||||
#
|
||||
# Other options that can be enabled if needed.
|
||||
#
|
||||
# ENABLE_REALWOW_SUPPORT:
|
||||
# r8126-objs += r8126_realwow.o
|
||||
# EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT
|
||||
#
|
||||
# ENABLE_DASH_SUPPORT:
|
||||
# r8126-objs += r8126_dash.o
|
||||
# EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT
|
||||
#
|
||||
# ENABLE_DASH_PRINTER_SUPPORT:
|
||||
# r8126-objs += r8126_dash.o
|
||||
# EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT
|
||||
#
|
||||
# CONFIG_DOWN_SPEED_100:
|
||||
# EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100
|
||||
#
|
||||
# ENABLE_S5_KEEP_CURR_MAC:
|
||||
# EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC
|
||||
#
|
||||
# ENABLE_EEE:
|
||||
# EXTRA_CFLAGS += -DENABLE_EEE
|
||||
#
|
||||
# ENABLE_S0_MAGIC_PACKET:
|
||||
# EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET
|
||||
#
|
||||
# ENABLE_MULTIPLE_TX_QUEUE:
|
||||
# EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE
|
||||
#
|
||||
# ENABLE_PTP_SUPPORT:
|
||||
# r8126-objs += r8126_ptp.o
|
||||
# EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT
|
||||
#
|
||||
# ENABLE_RSS_SUPPORT:
|
||||
# r8126-objs += r8126_rss.o
|
||||
# EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT
|
||||
#
|
||||
# ENABLE_LIB_SUPPORT:
|
||||
# r8126-objs += r8126_lib.o
|
||||
# EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT
|
||||
#
|
||||
# ENABLE_USE_FIRMWARE_FILE:
|
||||
# r8126-objs += r8126_firmware.o
|
||||
# EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE
|
||||
#
|
||||
# DISABLE_WOL_SUPPORT:
|
||||
# EXTRA_CFLAGS += -DDISABLE_WOL_SUPPORT
|
||||
#
|
||||
# DISABLE_MULTI_MSIX_VECTOR:
|
||||
# EXTRA_CFLAGS += -DDISABLE_MULTI_MSIX_VECTOR
|
||||
#
|
||||
# ENABLE_DOUBLE_VLAN:
|
||||
# EXTRA_CFLAGS += -DENABLE_DOUBLE_VLAN
|
||||
#
|
||||
# ENABLE_PAGE_REUSE:
|
||||
# EXTRA_CFLAGS += -DENABLE_PAGE_REUSE
|
||||
#
|
||||
# ENABLE_RX_PACKET_FRAGMENT:
|
||||
# EXTRA_CFLAGS += -DENABLE_RX_PACKET_FRAGMENT
|
||||
|
||||
11
KernelPackages/drivers/net/ethernet/realtek/r8126/built-in.a
Normal file
11
KernelPackages/drivers/net/ethernet/realtek/r8126/built-in.a
Normal file
@ -0,0 +1,11 @@
|
||||
!<thin>
|
||||
// 52 `
|
||||
r8126_n.o/
|
||||
rtl_eeprom.o/
|
||||
rtltool.o/
|
||||
r8126_fiber.o/
|
||||
|
||||
/0 0 0 0 644 308368 `
|
||||
/11 0 0 0 644 10088 `
|
||||
/25 0 0 0 644 5872 `
|
||||
/36 0 0 0 644 11032 `
|
||||
3067
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126.h
Normal file
3067
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126.h
Normal file
File diff suppressed because it is too large
Load Diff
261
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_dash.h
Normal file
261
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_dash.h
Normal file
@ -0,0 +1,261 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8126_DASH_H
|
||||
#define _LINUX_R8126_DASH_H
|
||||
|
||||
#include <linux/if.h>
|
||||
|
||||
#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2
|
||||
|
||||
enum rtl_dash_cmd {
|
||||
RTL_DASH_ARP_NS_OFFLOAD = 0,
|
||||
RTL_DASH_SET_OOB_IPMAC,
|
||||
RTL_DASH_NOTIFY_OOB,
|
||||
|
||||
RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW,
|
||||
RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE,
|
||||
RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA,
|
||||
RTL_DASH_OOB_REQ,
|
||||
RTL_DASH_OOB_ACK,
|
||||
RTL_DASH_DETACH_OOB_REQ,
|
||||
RTL_DASH_DETACH_OOB_ACK,
|
||||
|
||||
RTL_FW_SET_IPV4 = 0x10,
|
||||
RTL_FW_GET_IPV4,
|
||||
RTL_FW_SET_IPV6,
|
||||
RTL_FW_GET_IPV6,
|
||||
RTL_FW_SET_EXT_SNMP,
|
||||
RTL_FW_GET_EXT_SNMP,
|
||||
RTL_FW_SET_WAKEUP_PATTERN,
|
||||
RTL_FW_GET_WAKEUP_PATTERN,
|
||||
RTL_FW_DEL_WAKEUP_PATTERN,
|
||||
|
||||
RTLT_DASH_COMMAND_INVALID,
|
||||
};
|
||||
|
||||
struct rtl_dash_ip_mac {
|
||||
struct sockaddr ifru_addr;
|
||||
struct sockaddr ifru_netmask;
|
||||
struct sockaddr ifru_hwaddr;
|
||||
};
|
||||
|
||||
struct rtl_dash_ioctl_struct {
|
||||
__u32 cmd;
|
||||
__u32 offset;
|
||||
__u32 len;
|
||||
union {
|
||||
__u32 data;
|
||||
void *data_buffer;
|
||||
};
|
||||
};
|
||||
|
||||
struct settings_ipv4 {
|
||||
__u32 IPv4addr;
|
||||
__u32 IPv4mask;
|
||||
__u32 IPv4Gateway;
|
||||
};
|
||||
|
||||
struct settings_ipv6 {
|
||||
__u32 reserved;
|
||||
__u32 prefixLen;
|
||||
__u16 IPv6addr[8];
|
||||
__u16 IPv6Gateway[8];
|
||||
};
|
||||
|
||||
struct settings_ext_snmp {
|
||||
__u16 index;
|
||||
__u16 oid_get_len;
|
||||
__u8 oid_for_get[24];
|
||||
__u8 reserved0[26];
|
||||
__u16 value_len;
|
||||
__u8 value[256];
|
||||
__u8 supported;
|
||||
__u8 reserved1[27];
|
||||
};
|
||||
|
||||
struct wakeup_pattern {
|
||||
__u8 index;
|
||||
__u8 valid;
|
||||
__u8 start;
|
||||
__u8 length;
|
||||
__u8 name[36];
|
||||
__u8 mask[16];
|
||||
__u8 pattern[128];
|
||||
__u32 reserved[2];
|
||||
};
|
||||
|
||||
typedef struct _RX_DASH_FROM_FW_DESC {
|
||||
u16 length;
|
||||
u8 statusLowByte;
|
||||
u8 statusHighByte;
|
||||
u32 resv;
|
||||
u64 BufferAddress;
|
||||
}
|
||||
RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC;
|
||||
|
||||
typedef struct _TX_DASH_SEND_FW_DESC {
|
||||
u16 length;
|
||||
u8 statusLowByte;
|
||||
u8 statusHighByte;
|
||||
u32 resv;
|
||||
u64 BufferAddress;
|
||||
}
|
||||
TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC;
|
||||
|
||||
typedef struct _OSOOBHdr {
|
||||
u32 len;
|
||||
u8 type;
|
||||
u8 flag;
|
||||
u8 hostReqV;
|
||||
u8 res;
|
||||
}
|
||||
OSOOBHdr, *POSOOBHdr;
|
||||
|
||||
typedef struct _RX_DASH_BUFFER_TYPE_2 {
|
||||
OSOOBHdr oobhdr;
|
||||
u8 RxDataBuffer[0];
|
||||
}
|
||||
RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2;
|
||||
|
||||
#define ALIGN_8 (0x7)
|
||||
#define ALIGN_16 (0xf)
|
||||
#define ALIGN_32 (0x1f)
|
||||
#define ALIGN_64 (0x3f)
|
||||
#define ALIGN_256 (0xff)
|
||||
#define ALIGN_4096 (0xfff)
|
||||
|
||||
#define OCP_REG_CONFIG0 (0x10)
|
||||
#define OCP_REG_CONFIG0_REV_F (0xB8)
|
||||
#define OCP_REG_DASH_POLL (0x30)
|
||||
#define OCP_REG_HOST_REQ (0x34)
|
||||
#define OCP_REG_DASH_REQ (0x35)
|
||||
#define OCP_REG_CR (0x36)
|
||||
#define OCP_REG_DMEMSTA (0x38)
|
||||
#define OCP_REG_GPHYAR (0x60)
|
||||
|
||||
|
||||
#define OCP_REG_CONFIG0_DASHEN BIT_15
|
||||
#define OCP_REG_CONFIG0_OOBRESET BIT_14
|
||||
#define OCP_REG_CONFIG0_APRDY BIT_13
|
||||
#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12
|
||||
#define OCP_REG_CONFIG0_DRIVERRDY BIT_11
|
||||
#define OCP_REG_CONFIG0_OOB_WDT BIT_9
|
||||
#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8
|
||||
#define OCP_REG_CONFIG0_TLSEN BIT_7
|
||||
|
||||
#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0)
|
||||
#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1)
|
||||
#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2)
|
||||
#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3)
|
||||
|
||||
#define RECV_FROM_FW_BUF_SIZE (1520)
|
||||
#define SEND_TO_FW_BUF_SIZE (1520)
|
||||
|
||||
#define RX_DASH_FROM_FW_OWN BIT_15
|
||||
#define TX_DASH_SEND_FW_OWN BIT_15
|
||||
#define TX_DASH_SEND_FW_OWN_HIGHBYTE BIT_7
|
||||
|
||||
#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3)
|
||||
#define TXS_EXC BIT_4
|
||||
#define TXS_LNKF BIT_5
|
||||
#define TXS_OWC BIT_6
|
||||
#define TXS_TES BIT_7
|
||||
#define TXS_UNF BIT_9
|
||||
#define TXS_LGSEN BIT_11
|
||||
#define TXS_LS BIT_12
|
||||
#define TXS_FS BIT_13
|
||||
#define TXS_EOR BIT_14
|
||||
#define TXS_OWN BIT_15
|
||||
|
||||
#define TPPool_HRDY 0x20
|
||||
|
||||
#define HostReqReg (0xC0)
|
||||
#define SystemMasterDescStartAddrLow (0xF0)
|
||||
#define SystemMasterDescStartAddrHigh (0xF4)
|
||||
#define SystemSlaveDescStartAddrLow (0xF8)
|
||||
#define SystemSlaveDescStartAddrHigh (0xFC)
|
||||
|
||||
//DASH Request Type
|
||||
#define WSMANREG 0x01
|
||||
#define OSPUSHDATA 0x02
|
||||
|
||||
#define RXS_OWN BIT_15
|
||||
#define RXS_EOR BIT_14
|
||||
#define RXS_FS BIT_13
|
||||
#define RXS_LS BIT_12
|
||||
|
||||
#define ISRIMR_DP_DASH_OK BIT_15
|
||||
#define ISRIMR_DP_HOST_OK BIT_13
|
||||
#define ISRIMR_DP_REQSYS_OK BIT_11
|
||||
|
||||
#define ISRIMR_DASH_INTR_EN BIT_12
|
||||
#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15
|
||||
|
||||
#define ISRIMR_DASH_TYPE2_ROK BIT_0
|
||||
#define ISRIMR_DASH_TYPE2_RDU BIT_1
|
||||
#define ISRIMR_DASH_TYPE2_TOK BIT_2
|
||||
#define ISRIMR_DASH_TYPE2_TDU BIT_3
|
||||
#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4
|
||||
#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5
|
||||
#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6
|
||||
|
||||
#define CMAC_OOB_STOP 0x25
|
||||
#define CMAC_OOB_INIT 0x26
|
||||
#define CMAC_OOB_RESET 0x2a
|
||||
|
||||
#define NO_BASE_ADDRESS 0x00000000
|
||||
#define RTL8168FP_OOBMAC_BASE 0xBAF70000
|
||||
#define RTL8168FP_CMAC_IOBASE 0xBAF20000
|
||||
#define RTL8168FP_KVM_BASE 0xBAF80400
|
||||
#define CMAC_SYNC_REG 0x20
|
||||
#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98
|
||||
#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F
|
||||
|
||||
/* cmac write/read MMIO register */
|
||||
#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg))
|
||||
#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg))
|
||||
#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg))
|
||||
#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg))
|
||||
#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg))
|
||||
#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg)))
|
||||
|
||||
int rtl8126_dash_ioctl(struct net_device *dev, struct ifreq *ifr);
|
||||
void HandleDashInterrupt(struct net_device *dev);
|
||||
int AllocateDashShareMemory(struct net_device *dev);
|
||||
void FreeAllocatedDashShareMemory(struct net_device *dev);
|
||||
void DashHwInit(struct net_device *dev);
|
||||
|
||||
|
||||
#endif /* _LINUX_R8126_DASH_H */
|
||||
466
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_fiber.c
Normal file
466
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_fiber.c
Normal file
@ -0,0 +1,466 @@
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "r8126.h"
|
||||
#include "r8126_fiber.h"
|
||||
|
||||
static void
|
||||
rtl8126_fiber_set_mdc_gpio_c45(struct rtl8126_private *tp, bool pu)
|
||||
{
|
||||
if (pu)
|
||||
rtl8126_set_mac_ocp_bit(tp, 0xDC52, BIT_7);
|
||||
else
|
||||
rtl8126_clear_mac_ocp_bit(tp, 0xDC52, BIT_7);
|
||||
|
||||
//RtPciCommittp);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_set_mdc(struct rtl8126_private *tp, bool pu)
|
||||
{
|
||||
rtl8126_fiber_set_mdc_gpio_c45(tp, pu);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_set_mdcDownUp(struct rtl8126_private *tp)
|
||||
{
|
||||
udelay(1);
|
||||
rtl8126_fiber_set_mdc(tp, 0);
|
||||
udelay(1);
|
||||
rtl8126_fiber_set_mdc(tp, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_set_mdio_bit_gpio_c45(struct rtl8126_private *tp, bool pu)
|
||||
{
|
||||
if (pu)
|
||||
rtl8126_set_mac_ocp_bit(tp, 0xDC52, BIT_2);
|
||||
else
|
||||
rtl8126_clear_mac_ocp_bit(tp, 0xDC52, BIT_2);
|
||||
|
||||
//RtPciCommittp);
|
||||
|
||||
rtl8126_fiber_set_mdcDownUp(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_set_mdio_bit(struct rtl8126_private *tp, bool pu)
|
||||
{
|
||||
rtl8126_fiber_set_mdio_bit_gpio_c45(tp, pu);
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8126_fiber_get_mdio_bit_gpio_c45(struct rtl8126_private *tp)
|
||||
{
|
||||
rtl8126_fiber_set_mdcDownUp(tp);
|
||||
|
||||
return !!(rtl8126_mac_ocp_read(tp, 0xDC58) & BIT(2));
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8126_fiber_get_mdio_bit(struct rtl8126_private *tp)
|
||||
{
|
||||
return rtl8126_fiber_get_mdio_bit_gpio_c45(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_shift_bit_in(struct rtl8126_private *tp, u32 val, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = (count - 1); i >= 0; i--)
|
||||
rtl8126_fiber_set_mdio_bit(tp, !!(val & BIT(i)));
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8126_fiber_shift_bit_out(struct rtl8126_private *tp)
|
||||
{
|
||||
u16 data = 0;
|
||||
int i;
|
||||
|
||||
for (i = 15; i >= 0; i--)
|
||||
data += (rtl8126_fiber_get_mdio_bit(tp) << i);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_dir_gpio_c45(struct rtl8126_private *tp, bool output_mode)
|
||||
{
|
||||
if (output_mode)
|
||||
rtl8126_set_mac_ocp_bit(tp, 0xDC4C, BIT_2);
|
||||
else
|
||||
rtl8126_clear_mac_ocp_bit(tp, 0xDC4C, BIT_2);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_dir(struct rtl8126_private *tp, bool output_mode)
|
||||
{
|
||||
rtl8126_fiber_dir_gpio_c45(tp, output_mode);
|
||||
}
|
||||
|
||||
//fiber
|
||||
#define R8126_FIBER_C22 (0)
|
||||
#define R8126_FIBER_C45 (1)
|
||||
|
||||
// sfp opcodes
|
||||
#define R8126_FIBER_ST (1)
|
||||
#define R8126_FIBER_OP_W (1)
|
||||
#define R8126_FIBER_OP_R (2)
|
||||
#define R8126_FIBER_TA (2)
|
||||
|
||||
// sfp C45 opcodes
|
||||
#define R8126_FIBER_MDIO_C45 (BIT(15))
|
||||
#define R8126_FIBER_C45_ST (R8126_FIBER_MDIO_C45 | 0)
|
||||
#define R8126_FIBER_C45_OP_ADDR (R8126_FIBER_MDIO_C45 | 0)
|
||||
#define R8126_FIBER_C45_OP_W (R8126_FIBER_MDIO_C45 | 1)
|
||||
#define R8126_FIBER_C45_OP_R (R8126_FIBER_MDIO_C45 | 3)
|
||||
|
||||
static void
|
||||
rtl8126_fiber_cmd(struct rtl8126_private *tp, u32 cmd, u8 phy_addr,
|
||||
u32 reg)
|
||||
{
|
||||
/* change to output mode */
|
||||
rtl8126_fiber_dir(tp, 1);
|
||||
|
||||
/* preamble 32bit of 1 */
|
||||
rtl8126_fiber_shift_bit_in(tp, UINT_MAX, 32);
|
||||
|
||||
/* start bit */
|
||||
if (cmd & R8126_FIBER_MDIO_C45)
|
||||
rtl8126_fiber_shift_bit_in(tp, R8126_FIBER_C45_ST, 2);
|
||||
else
|
||||
rtl8126_fiber_shift_bit_in(tp, R8126_FIBER_ST, 2);
|
||||
|
||||
/* opcode */
|
||||
rtl8126_fiber_shift_bit_in(tp, cmd, 2);
|
||||
|
||||
/* phy address */
|
||||
rtl8126_fiber_shift_bit_in(tp, phy_addr, 5);
|
||||
|
||||
/* phy reg */
|
||||
rtl8126_fiber_shift_bit_in(tp, reg, 5);
|
||||
}
|
||||
|
||||
static u8
|
||||
rtl8126_fiber_cmdAddr(struct rtl8126_private *tp, u8 phy_addr, u32 reg)
|
||||
{
|
||||
u8 dev_addr = (reg >> 16) & 0x1F;
|
||||
u16 addr = (u16)reg;
|
||||
|
||||
rtl8126_fiber_cmd(tp, R8126_FIBER_C45_OP_ADDR, phy_addr, dev_addr);
|
||||
|
||||
/* turn-around(TA) */
|
||||
rtl8126_fiber_shift_bit_in(tp, R8126_FIBER_TA, 2);
|
||||
|
||||
rtl8126_fiber_shift_bit_in(tp, addr, 16);
|
||||
|
||||
rtl8126_fiber_dir(tp, 0);
|
||||
|
||||
rtl8126_fiber_get_mdio_bit(tp);
|
||||
|
||||
return dev_addr;
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_reset_gpio_c45(struct rtl8126_private *tp)
|
||||
{
|
||||
rtl8126_set_mac_ocp_bit(tp, 0xDC4C, (BIT_7 | BIT_2));
|
||||
|
||||
/* init sfp interface */
|
||||
rtl8126_clear_mac_ocp_bit(tp, 0xDC52, BIT_7);
|
||||
rtl8126_set_mac_ocp_bit(tp, 0xDC52, BIT_2);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_write_common(struct rtl8126_private *tp, u16 val)
|
||||
{
|
||||
/* turn-around(TA) */
|
||||
rtl8126_fiber_shift_bit_in(tp, R8126_FIBER_TA, 2);
|
||||
|
||||
/* write phy data */
|
||||
rtl8126_fiber_shift_bit_in(tp, val, 16);
|
||||
|
||||
/* change to input mode */
|
||||
rtl8126_fiber_dir(tp, 0);
|
||||
|
||||
rtl8126_fiber_get_mdio_bit(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_mdio_write_gpio_c45(
|
||||
struct rtl8126_private *tp,
|
||||
u32 reg,
|
||||
u16 val,
|
||||
u8 phy_addr)
|
||||
{
|
||||
/* opcode write */
|
||||
reg = rtl8126_fiber_cmdAddr(tp, phy_addr, reg);
|
||||
rtl8126_fiber_cmd(tp, R8126_FIBER_C45_OP_W, phy_addr, reg);
|
||||
|
||||
rtl8126_fiber_write_common(tp, val);
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8126_fiber_read_common(struct rtl8126_private *tp)
|
||||
{
|
||||
u16 data = 0;
|
||||
|
||||
/* change to input mode */
|
||||
rtl8126_fiber_dir(tp, 0);
|
||||
|
||||
/* TA 0 */
|
||||
rtl8126_fiber_get_mdio_bit(tp);
|
||||
|
||||
/* read phy data */
|
||||
data = rtl8126_fiber_shift_bit_out(tp);
|
||||
|
||||
rtl8126_fiber_get_mdio_bit(tp);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static u16
|
||||
rtl8126_fiber_mdio_read_gpio_c45(
|
||||
struct rtl8126_private *tp,
|
||||
u32 reg,
|
||||
u8 phy_addr)
|
||||
{
|
||||
reg = rtl8126_fiber_cmdAddr(tp, phy_addr, reg);
|
||||
rtl8126_fiber_cmd(tp, R8126_FIBER_C45_OP_R, phy_addr, reg);
|
||||
|
||||
return rtl8126_fiber_read_common(tp);
|
||||
}
|
||||
|
||||
void
|
||||
rtl8126_fiber_mdio_write(
|
||||
struct rtl8126_private *tp,
|
||||
u32 reg,
|
||||
u16 val)
|
||||
{
|
||||
switch(tp->HwFiberStat) {
|
||||
case FIBER_STAT_CONNECT_GPO_C45:
|
||||
return rtl8126_fiber_mdio_write_gpio_c45(tp, reg, val, 0);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u16
|
||||
rtl8126_fiber_mdio_read(
|
||||
struct rtl8126_private *tp,
|
||||
u32 reg)
|
||||
{
|
||||
switch(tp->HwFiberStat) {
|
||||
case FIBER_STAT_CONNECT_GPO_C45:
|
||||
return rtl8126_fiber_mdio_read_gpio_c45(tp, reg, 0);
|
||||
default:
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_clear_and_set_phy_bit(struct rtl8126_private *tp, u32 addr, u16 clearmask, u16 setmask)
|
||||
{
|
||||
u16 PhyRegValue;
|
||||
|
||||
PhyRegValue = rtl8126_fiber_mdio_read(tp, addr);
|
||||
PhyRegValue &= ~clearmask;
|
||||
PhyRegValue |= setmask;
|
||||
rtl8126_fiber_mdio_write(tp, addr, PhyRegValue);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_clear_phy_bit(struct rtl8126_private *tp, u32 addr, u16 mask)
|
||||
{
|
||||
rtl8126_fiber_clear_and_set_phy_bit(tp, addr, mask, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_set_phy_bit(struct rtl8126_private *tp, u32 addr, u16 mask)
|
||||
{
|
||||
rtl8126_fiber_clear_and_set_phy_bit(tp, addr, 0, mask);
|
||||
}
|
||||
|
||||
#define R8126_MAKE_C45_ADDR(_mmd, _addr) (_mmd << 16 | _addr)
|
||||
|
||||
static void
|
||||
rtl8126_fiber_set_ra_8251b(struct rtl8126_private *tp)
|
||||
{
|
||||
struct pci_dev *pdev = tp->pci_dev;
|
||||
u16 const svid = pdev->subsystem_vendor;
|
||||
|
||||
rtl8126_fiber_clear_and_set_phy_bit(tp,
|
||||
R8126_MAKE_C45_ADDR(30, 0x6973),
|
||||
0x00FF,
|
||||
(svid == PCI_VENDOR_ID_DELL) ?
|
||||
0x03 : 0x12);
|
||||
rtl8126_fiber_clear_and_set_phy_bit(tp,
|
||||
R8126_MAKE_C45_ADDR(30, 0x6974),
|
||||
0x00FF,
|
||||
0x0005);
|
||||
rtl8126_fiber_clear_and_set_phy_bit(tp,
|
||||
R8126_MAKE_C45_ADDR(30, 0x6975),
|
||||
0x00FF,
|
||||
0x0008);
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_set_ra(struct rtl8126_private *tp)
|
||||
{
|
||||
switch (tp->HwFiberModeVer) {
|
||||
case FIBER_MODE_RTL8126_RTL8251B:
|
||||
rtl8126_fiber_set_ra_8251b(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_phy_reset_8251b(struct rtl8126_private *tp)
|
||||
{
|
||||
u16 PhyRegValue;
|
||||
u32 Timeout;
|
||||
|
||||
rtl8126_fiber_set_phy_bit(tp, R8126_MAKE_C45_ADDR(0x01, 0x00), BIT_15);
|
||||
|
||||
Timeout = 0;
|
||||
do {
|
||||
udelay(1000);
|
||||
|
||||
PhyRegValue = rtl8126_fiber_mdio_read(tp, R8126_MAKE_C45_ADDR(0x01, 0x00));
|
||||
|
||||
Timeout++;
|
||||
} while ((PhyRegValue & BIT_15) && (Timeout < 20));
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_fiber_phy_reset(struct rtl8126_private *tp)
|
||||
{
|
||||
switch (tp->HwFiberModeVer) {
|
||||
case FIBER_MODE_RTL8126_RTL8251B:
|
||||
rtl8126_fiber_phy_reset_8251b(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8126_hw_rtl8251b_phy_config(struct rtl8126_private *tp)
|
||||
{
|
||||
rtl8126_fiber_reset_gpio_c45(tp);
|
||||
|
||||
rtl8126_fiber_set_ra(tp);
|
||||
|
||||
rtl8126_fiber_clear_phy_bit(tp, R8126_MAKE_C45_ADDR(0x07, 0x3C), (BIT_2 | BIT_1));
|
||||
rtl8126_fiber_clear_phy_bit(tp, R8126_MAKE_C45_ADDR(0x07, 0x3E), (BIT_1 | BIT_0));
|
||||
|
||||
rtl8126_fiber_phy_reset(tp);
|
||||
}
|
||||
|
||||
void
|
||||
rtl8126_hw_fiber_phy_config(struct rtl8126_private *tp)
|
||||
{
|
||||
switch (tp->HwFiberModeVer) {
|
||||
case FIBER_MODE_RTL8126_RTL8251B:
|
||||
rtl8126_hw_rtl8251b_phy_config(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define RTL8251B_PHY_ID_1 0x001C
|
||||
#define RTL8251B_PHY_ID_2 0xC868
|
||||
static u32
|
||||
rtl8126_fiber_get_connect_status_8251b(struct rtl8126_private *tp)
|
||||
{
|
||||
int i;
|
||||
int const checkcnt = 4;
|
||||
|
||||
rtl8126_fiber_reset_gpio_c45(tp);
|
||||
|
||||
for (i = 0; i < checkcnt; i++) {
|
||||
if (RTL8251B_PHY_ID_1 != rtl8126_fiber_mdio_read_gpio_c45(tp, R8126_MAKE_C45_ADDR(0x01, 0x02), 0) ||
|
||||
RTL8251B_PHY_ID_2 != rtl8126_fiber_mdio_read_gpio_c45(tp, R8126_MAKE_C45_ADDR(0x01, 0x03), 0))
|
||||
return FIBER_STAT_DISCONNECT;
|
||||
}
|
||||
|
||||
return FIBER_STAT_CONNECT_GPO_C45;
|
||||
}
|
||||
|
||||
static u32
|
||||
rtl8126_fiber_get_connect_status(struct rtl8126_private *tp)
|
||||
{
|
||||
switch (tp->HwFiberModeVer) {
|
||||
case FIBER_MODE_RTL8126_RTL8251B:
|
||||
return rtl8126_fiber_get_connect_status_8251b(tp);
|
||||
default:
|
||||
return FIBER_STAT_NOT_CHECKED;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtl8126_check_fiber_mode_support(struct rtl8126_private *tp)
|
||||
{
|
||||
switch(tp->mcfg) {
|
||||
case CFG_METHOD_3: {
|
||||
u8 tmp = (u8)rtl8126_mac_ocp_read(tp, 0xD006);
|
||||
if (tmp == 0x03)
|
||||
tp->HwFiberModeVer = FIBER_MODE_RTL8126_RTL8251B;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (HW_FIBER_MODE_ENABLED(tp))
|
||||
tp->HwFiberStat = rtl8126_fiber_get_connect_status(tp);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
rtl8126_fiber_link_ok(struct net_device *dev)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
u16 status;
|
||||
|
||||
switch (tp->HwFiberStat) {
|
||||
case FIBER_STAT_CONNECT_GPO_C45:
|
||||
status = rtl8126_fiber_mdio_read(tp, R8126_MAKE_C45_ADDR(30, 0x758D));
|
||||
if (status != USHRT_MAX && status & BIT_1)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8126_FIBER_H
|
||||
#define _LINUX_R8126_FIBER_H
|
||||
|
||||
enum {
|
||||
FIBER_MODE_NIC_ONLY = 0,
|
||||
FIBER_MODE_RTL8126_RTL8251B,
|
||||
FIBER_MODE_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
FIBER_STAT_NOT_CHECKED = 0,
|
||||
FIBER_STAT_DISCONNECT,
|
||||
FIBER_STAT_CONNECT_GPO_C45,
|
||||
FIBER_STAT_MAX
|
||||
};
|
||||
|
||||
#define HW_FIBER_MODE_ENABLED(_M) ((_M)->HwFiberModeVer > 0)
|
||||
#define HW_FIBER_STATUS_CONNECTED(_M) (((_M)->HwFiberStat == FIBER_STAT_CONNECT_GPO_C45))
|
||||
#define HW_FIBER_STATUS_DISCONNECTED(_M) ((_M)->HwFiberStat == FIBER_STAT_DISCONNECT)
|
||||
|
||||
struct rtl8126_private;
|
||||
|
||||
void rtl8126_hw_fiber_phy_config(struct rtl8126_private *tp);
|
||||
void rtl8126_check_fiber_mode_support(struct rtl8126_private *tp);
|
||||
void rtl8126_fiber_mdio_write( struct rtl8126_private *tp, u32 reg, u16 val);
|
||||
u16 rtl8126_fiber_mdio_read(struct rtl8126_private *tp, u32 reg);
|
||||
unsigned int rtl8126_fiber_link_ok(struct net_device *dev);
|
||||
|
||||
#endif /* _LINUX_R8126_FIBER_H */
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_fiber.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_fiber.o
Normal file
Binary file not shown.
@ -0,0 +1,264 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "r8126_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[RTL8126_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 rtl8126_fw_phy_action, code[0])
|
||||
|
||||
static bool rtl8126_fw_format_ok(struct rtl8126_fw *rtl_fw)
|
||||
{
|
||||
const struct firmware *fw = rtl_fw->fw;
|
||||
struct fw_info *fw_info = (struct fw_info *)fw->data;
|
||||
struct rtl8126_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, RTL8126_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, RTL8126_VER_SIZE);
|
||||
|
||||
pa->code = (__le32 *)fw->data;
|
||||
pa->size = fw->size / FW_OPCODE_SIZE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rtl8126_fw_data_ok(struct rtl8126_fw *rtl_fw)
|
||||
{
|
||||
struct rtl8126_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 rtl8126_fw_write_firmware(struct rtl8126_private *tp, struct rtl8126_fw *rtl_fw)
|
||||
{
|
||||
struct rtl8126_fw_phy_action *pa = &rtl_fw->phy_action;
|
||||
rtl8126_fw_write_t fw_write = rtl_fw->phy_write;
|
||||
rtl8126_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 rtl8126_fw_release_firmware(struct rtl8126_fw *rtl_fw)
|
||||
{
|
||||
release_firmware(rtl_fw->fw);
|
||||
}
|
||||
|
||||
int rtl8126_fw_request_firmware(struct rtl8126_fw *rtl_fw)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
if (!rtl8126_fw_format_ok(rtl_fw) || !rtl8126_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;
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8126_FIRMWARE_H
|
||||
#define _LINUX_R8126_FIRMWARE_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
struct rtl8126_private;
|
||||
typedef void (*rtl8126_fw_write_t)(struct rtl8126_private *tp, u16 reg, u16 val);
|
||||
typedef u32 (*rtl8126_fw_read_t)(struct rtl8126_private *tp, u16 reg);
|
||||
|
||||
#define RTL8126_VER_SIZE 32
|
||||
|
||||
struct rtl8126_fw {
|
||||
rtl8126_fw_write_t phy_write;
|
||||
rtl8126_fw_read_t phy_read;
|
||||
rtl8126_fw_write_t mac_mcu_write;
|
||||
rtl8126_fw_read_t mac_mcu_read;
|
||||
const struct firmware *fw;
|
||||
const char *fw_name;
|
||||
struct device *dev;
|
||||
|
||||
char version[RTL8126_VER_SIZE];
|
||||
|
||||
struct rtl8126_fw_phy_action {
|
||||
__le32 *code;
|
||||
size_t size;
|
||||
} phy_action;
|
||||
};
|
||||
|
||||
int rtl8126_fw_request_firmware(struct rtl8126_fw *rtl_fw);
|
||||
void rtl8126_fw_release_firmware(struct rtl8126_fw *rtl_fw);
|
||||
void rtl8126_fw_write_firmware(struct rtl8126_private *tp, struct rtl8126_fw *rtl_fw);
|
||||
|
||||
#endif /* _LINUX_R8126_FIRMWARE_H */
|
||||
17666
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_n.c
Normal file
17666
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_n.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_n.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_n.o
Normal file
Binary file not shown.
944
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_ptp.c
Normal file
944
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_ptp.c
Normal file
@ -0,0 +1,944 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#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 <linux/rtnetlink.h>
|
||||
|
||||
#include "r8126.h"
|
||||
#include "r8126_ptp.h"
|
||||
|
||||
static void rtl8126_wait_clkadj_ready(struct rtl8126_private *tp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++)
|
||||
if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CLK_CFG_8126) & CLKADJ_MODE_SET))
|
||||
break;
|
||||
}
|
||||
|
||||
static void rtl8126_set_clkadj_mode(struct rtl8126_private *tp, u16 cmd)
|
||||
{
|
||||
rtl8126_clear_and_set_eth_phy_ocp_bit(tp,
|
||||
PTP_CLK_CFG_8126,
|
||||
BIT_3 | BIT_2 | BIT_1,
|
||||
CLKADJ_MODE_SET | cmd);
|
||||
|
||||
rtl8126_wait_clkadj_ready(tp);
|
||||
}
|
||||
|
||||
static int _rtl8126_phc_gettime(struct rtl8126_private *tp, struct timespec64 *ts64)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
|
||||
//Direct Read
|
||||
rtl8126_set_clkadj_mode(tp, DIRECT_READ);
|
||||
|
||||
/* nanoseconds */
|
||||
//Ns[29:16] E414[13:0]
|
||||
ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_NS_HI_8126) & 0x3fff;
|
||||
ts64->tv_nsec <<= 16;
|
||||
//Ns[15:0] E412[15:0]
|
||||
ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_NS_LO_8126);
|
||||
|
||||
|
||||
/* seconds */
|
||||
//S[47:32] E41A[15:0]
|
||||
ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_HI_8126);
|
||||
ts64->tv_sec <<= 16;
|
||||
//S[31:16] E418[15:0]
|
||||
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_MI_8126);
|
||||
ts64->tv_sec <<= 16;
|
||||
//S[15:0] E416[15:0]
|
||||
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_LO_8126);
|
||||
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _rtl8126_phc_settime(struct rtl8126_private *tp, const struct timespec64 *ts64)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
|
||||
/* nanoseconds */
|
||||
//Ns[15:0] E412[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, ts64->tv_nsec);
|
||||
//Ns[29:16] E414[13:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (ts64->tv_nsec & 0x3fff0000) >> 16);
|
||||
|
||||
/* seconds */
|
||||
//S[15:0] E416[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_LO_8126, ts64->tv_sec);
|
||||
//S[31:16] E418[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_MI_8126, (ts64->tv_sec >> 16));
|
||||
//S[47:32] E41A[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_HI_8126, (ts64->tv_sec >> 32));
|
||||
|
||||
//Direct Write
|
||||
rtl8126_set_clkadj_mode(tp, DIRECT_WRITE);
|
||||
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _rtl8126_phc_adjtime(struct rtl8126_private *tp, s64 delta)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct timespec64 d;
|
||||
bool negative;
|
||||
u64 tohw;
|
||||
u32 nsec;
|
||||
u64 sec;
|
||||
|
||||
if (delta < 0) {
|
||||
negative = true;
|
||||
tohw = -delta;
|
||||
} else {
|
||||
negative = false;
|
||||
tohw = delta;
|
||||
}
|
||||
|
||||
d = ns_to_timespec64(tohw);
|
||||
|
||||
nsec = d.tv_nsec;
|
||||
sec = d.tv_sec;
|
||||
|
||||
nsec &= 0x3fffffff;
|
||||
sec &= 0x0000ffffffffffff;
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
|
||||
/* nanoseconds */
|
||||
//Ns[15:0] E412[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, nsec);
|
||||
//Ns[29:16] E414[13:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (nsec >> 16));
|
||||
|
||||
/* seconds */
|
||||
//S[15:0] E416[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_LO_8126, sec);
|
||||
//S[31:16] E418[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_MI_8126, (sec >> 16));
|
||||
//S[47:32] E41A[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_HI_8126, (sec >> 32));
|
||||
|
||||
if (negative)
|
||||
rtl8126_set_clkadj_mode(tp, DECREMENT_STEP);
|
||||
else
|
||||
rtl8126_set_clkadj_mode(tp, INCREMENT_STEP);
|
||||
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8126_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
|
||||
int ret;
|
||||
|
||||
//netif_info(tp, drv, tp->dev, "phc adjust time\n");
|
||||
|
||||
ret = _rtl8126_phc_adjtime(tp, delta);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* delta = delta * 10^6 ppm = delta * 10^9 ppb (in this equation ppm and ppb are not variable)
|
||||
*
|
||||
* in adjfreq ppb is a variable
|
||||
* ppb = delta * 10^9
|
||||
* delta = ppb / 10^9
|
||||
* rate_value = |delta| * 2^32 = |ppb| / 10^9 * 2^32 = (|ppb| << 32) / 10^9
|
||||
*/
|
||||
static int _rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
|
||||
{
|
||||
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
|
||||
unsigned long flags;
|
||||
u32 rate_value;
|
||||
|
||||
if (ppb < 0) {
|
||||
rate_value = ((u64)-ppb << 32) / 1000000000;
|
||||
rate_value = ~rate_value + 1;
|
||||
} else
|
||||
rate_value = ((u64)ppb << 32) / 1000000000;
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
|
||||
/* nanoseconds */
|
||||
//Ns[15:0] E412[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, rate_value);
|
||||
//Ns[22:16] E414[13:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (rate_value & 0x003f0000) >> 16);
|
||||
|
||||
rtl8126_set_clkadj_mode(tp, RATE_WRITE);
|
||||
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
|
||||
static int rtl8126_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
||||
{
|
||||
s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
|
||||
|
||||
if (ppb > ptp->max_adj || ppb < -ptp->max_adj)
|
||||
return -EINVAL;
|
||||
|
||||
_rtl8126_phc_adjfreq(ptp, ppb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static int rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
|
||||
{
|
||||
//struct rtl8126_private *tp = container_of(ptp, struct rtl8126_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;
|
||||
|
||||
_rtl8126_phc_adjfreq(ptp, delta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
|
||||
static int rtl8126_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64,
|
||||
struct ptp_system_timestamp *sts)
|
||||
{
|
||||
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
|
||||
int ret;
|
||||
|
||||
//netif_info(tp, drv, tp->dev, "phc get ts\n");
|
||||
|
||||
ptp_read_system_prets(sts);
|
||||
ret = _rtl8126_phc_gettime(tp, ts64);
|
||||
ptp_read_system_postts(sts);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static int rtl8126_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64)
|
||||
{
|
||||
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
|
||||
int ret;
|
||||
|
||||
//netif_info(tp, drv, tp->dev, "phc get ts\n");
|
||||
|
||||
ret = _rtl8126_phc_gettime(tp, ts64);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) */
|
||||
|
||||
static int rtl8126_phc_settime(struct ptp_clock_info *ptp,
|
||||
const struct timespec64 *ts64)
|
||||
{
|
||||
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
|
||||
int ret;
|
||||
|
||||
//netif_info(tp, drv, tp->dev, "phc set ts\n");
|
||||
|
||||
ret = _rtl8126_phc_settime(tp, ts64);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _rtl8126_phc_enable(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *rq, int on)
|
||||
{
|
||||
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
|
||||
unsigned long flags;
|
||||
u16 phy_ocp_data;
|
||||
|
||||
if (on) {
|
||||
tp->pps_enable = 1;
|
||||
rtl8126_clear_mac_ocp_bit(tp, 0xDC00, BIT_6);
|
||||
rtl8126_clear_mac_ocp_bit(tp, 0xDC20, BIT_1);
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
|
||||
/* Set periodic pulse 1pps */
|
||||
/* E432[8:0] = 0x017d */
|
||||
phy_ocp_data = rtl8126_mdio_direct_read_phy_ocp(tp, 0xE432);
|
||||
phy_ocp_data &= 0xFE00;
|
||||
phy_ocp_data |= 0x017d;
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE432, phy_ocp_data);
|
||||
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE434, 0x7840);
|
||||
|
||||
/* E436[8:0] = 0xbe */
|
||||
phy_ocp_data = rtl8126_mdio_direct_read_phy_ocp(tp, 0xE436);
|
||||
phy_ocp_data &= 0xFE00;
|
||||
phy_ocp_data |= 0xbe;
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE436, phy_ocp_data);
|
||||
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE438, 0xbc20);
|
||||
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
|
||||
/* start hrtimer */
|
||||
hrtimer_start(&tp->pps_timer, 1000000000, HRTIMER_MODE_REL);
|
||||
} else
|
||||
tp->pps_enable = 0;
|
||||
}
|
||||
|
||||
static int rtl8126_phc_enable(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *rq, int on)
|
||||
{
|
||||
switch (rq->type) {
|
||||
case PTP_CLK_REQ_PPS:
|
||||
_rtl8126_phc_enable(ptp, rq, on);
|
||||
return 0;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static void rtl8126_ptp_enable_config(struct rtl8126_private *tp)
|
||||
{
|
||||
if (tp->syncE_en)
|
||||
rtl8126_set_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
|
||||
else
|
||||
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
|
||||
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CTL, PTP_CTL_TYPE_3 | BIT_12);
|
||||
|
||||
rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15);
|
||||
}
|
||||
|
||||
int rtl8126_get_ts_info(struct net_device *netdev,
|
||||
struct ethtool_ts_info *info)
|
||||
{
|
||||
struct rtl8126_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,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
|
||||
.adjfine = rtl8126_ptp_adjfine,
|
||||
#else
|
||||
.adjfreq = rtl8126_phc_adjfreq,
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0) */
|
||||
.adjtime = rtl8126_phc_adjtime,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
|
||||
.gettimex64 = rtl8126_phc_gettime,
|
||||
#else
|
||||
.gettime64 = rtl8126_phc_gettime,
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) */
|
||||
|
||||
.settime64 = rtl8126_phc_settime,
|
||||
.enable = rtl8126_phc_enable,
|
||||
};
|
||||
|
||||
static u16 rtl8126_ptp_get_tx_msgtype(struct rtl8126_private *tp)
|
||||
{
|
||||
u16 tx_ts_ready = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++) {
|
||||
tx_ts_ready = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & 0xF000;
|
||||
if (tx_ts_ready)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (tx_ts_ready) {
|
||||
case TX_TS_PDLYRSP_RDY:
|
||||
return PTP_MSGTYPE_PDELAY_RESP;
|
||||
case TX_TS_PDLYREQ_RDY:
|
||||
return PTP_MSGTYPE_PDELAY_REQ;
|
||||
case TX_TS_DLYREQ_RDY:
|
||||
return PTP_MSGTYPE_DELAY_REQ;
|
||||
case TX_TS_SYNC_RDY:
|
||||
default:
|
||||
return PTP_MSGTYPE_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static u16 rtl8126_ptp_get_rx_msgtype(struct rtl8126_private *tp)
|
||||
{
|
||||
u16 rx_ts_ready = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++) {
|
||||
rx_ts_ready = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & 0x0F00;
|
||||
if (rx_ts_ready)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (rx_ts_ready) {
|
||||
case RX_TS_PDLYRSP_RDY:
|
||||
return PTP_MSGTYPE_PDELAY_RESP;
|
||||
case RX_TS_PDLYREQ_RDY:
|
||||
return PTP_MSGTYPE_PDELAY_REQ;
|
||||
case RX_TS_DLYREQ_RDY:
|
||||
return PTP_MSGTYPE_DELAY_REQ;
|
||||
case RX_TS_SYNC_RDY:
|
||||
default:
|
||||
return PTP_MSGTYPE_SYNC;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static void rtl8126_wait_trx_ts_ready(struct rtl8126_private *tp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++)
|
||||
if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & TRX_TS_RD))
|
||||
break;
|
||||
}
|
||||
|
||||
static void rtl8126_set_trx_ts_cmd(struct rtl8126_private *tp, u16 cmd)
|
||||
{
|
||||
rtl8126_clear_and_set_eth_phy_ocp_bit(tp,
|
||||
PTP_TRX_TS_STA,
|
||||
TRXTS_SEL | BIT_3 | BIT_2,
|
||||
TRX_TS_RD | cmd);
|
||||
|
||||
rtl8126_wait_trx_ts_ready(tp);
|
||||
}
|
||||
|
||||
static void rtl8126_ptp_egresstime(struct rtl8126_private *tp, struct timespec64 *ts64)
|
||||
{
|
||||
u16 msgtype;
|
||||
|
||||
msgtype = rtl8126_ptp_get_tx_msgtype(tp);
|
||||
|
||||
msgtype <<= 2;
|
||||
|
||||
rtl8126_set_trx_ts_cmd(tp, (msgtype | BIT_4));
|
||||
|
||||
/* nanoseconds */
|
||||
//Ns[29:16] E448[13:0]
|
||||
ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_HI) & 0x3fff;
|
||||
ts64->tv_nsec <<= 16;
|
||||
//Ns[15:0] E446[15:0]
|
||||
ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_LO);
|
||||
|
||||
/* seconds */
|
||||
//S[47:32] E44E[15:0]
|
||||
ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_HI);
|
||||
ts64->tv_sec <<= 16;
|
||||
//S[31:16] E44C[15:0]
|
||||
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_MI);
|
||||
ts64->tv_sec <<= 16;
|
||||
//S[15:0] E44A[15:0]
|
||||
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_LO);
|
||||
}
|
||||
|
||||
static void rtl8126_ptp_ingresstime(struct rtl8126_private *tp, struct timespec64 *ts64, u8 type)
|
||||
{
|
||||
u16 msgtype;
|
||||
|
||||
switch (type) {
|
||||
case PTP_MSGTYPE_PDELAY_RESP:
|
||||
case PTP_MSGTYPE_PDELAY_REQ:
|
||||
case PTP_MSGTYPE_DELAY_REQ:
|
||||
case PTP_MSGTYPE_SYNC:
|
||||
msgtype = type << 2;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
rtl8126_set_trx_ts_cmd(tp, (TRXTS_SEL | msgtype | BIT_4));
|
||||
|
||||
/* nanoseconds */
|
||||
//Ns[29:16] E448[13:0]
|
||||
ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_HI) & 0x3fff;
|
||||
ts64->tv_nsec <<= 16;
|
||||
//Ns[15:0] E446[15:0]
|
||||
ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_LO);
|
||||
|
||||
/* seconds */
|
||||
//S[47:32] E44E[15:0]
|
||||
ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_HI);
|
||||
ts64->tv_sec <<= 16;
|
||||
//S[31:16] E44C[15:0]
|
||||
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_MI);
|
||||
ts64->tv_sec <<= 16;
|
||||
//S[15:0] E44A[15:0]
|
||||
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_LO);
|
||||
}
|
||||
|
||||
static void rtl8126_ptp_tx_hwtstamp(struct rtl8126_private *tp)
|
||||
{
|
||||
struct sk_buff *skb = tp->ptp_tx_skb;
|
||||
struct skb_shared_hwtstamps shhwtstamps = { 0 };
|
||||
struct timespec64 ts64;
|
||||
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, TX_TX_INTR);
|
||||
|
||||
rtl8126_ptp_egresstime(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;
|
||||
clear_bit_unlock(__RTL8126_PTP_TX_IN_PROGRESS, &tp->state);
|
||||
|
||||
/* Notify the stack and free the skb after we've unlocked */
|
||||
skb_tstamp_tx(skb, &shhwtstamps);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
#define RTL8126_PTP_TX_TIMEOUT (HZ * 15)
|
||||
static void rtl8126_ptp_tx_work(struct work_struct *work)
|
||||
{
|
||||
struct rtl8126_private *tp = container_of(work, struct rtl8126_private,
|
||||
ptp_tx_work);
|
||||
unsigned long flags;
|
||||
|
||||
if (!tp->ptp_tx_skb)
|
||||
return;
|
||||
|
||||
if (time_is_before_jiffies(tp->ptp_tx_start +
|
||||
RTL8126_PTP_TX_TIMEOUT)) {
|
||||
dev_kfree_skb_any(tp->ptp_tx_skb);
|
||||
tp->ptp_tx_skb = NULL;
|
||||
clear_bit_unlock(__RTL8126_PTP_TX_IN_PROGRESS, &tp->state);
|
||||
tp->tx_hwtstamp_timeouts++;
|
||||
/* Clear the tx valid bit in TSYNCTXCTL register to enable
|
||||
* interrupt
|
||||
*/
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, TX_TX_INTR);
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
if (rtl8126_mdio_direct_read_phy_ocp(tp, PTP_INSR) & TX_TX_INTR) {
|
||||
rtl8126_ptp_tx_hwtstamp(tp);
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
/* reschedule to check later */
|
||||
schedule_work(&tp->ptp_tx_work);
|
||||
}
|
||||
}
|
||||
|
||||
static int rtl8126_hwtstamp_enable(struct rtl8126_private *tp, bool enable)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
|
||||
if (enable) {
|
||||
//trx timestamp interrupt enable
|
||||
rtl8126_set_eth_phy_ocp_bit(tp, PTP_INER, BIT_2 | BIT_3);
|
||||
|
||||
//set isr clear mode
|
||||
rtl8126_set_eth_phy_ocp_bit(tp, PTP_GEN_CFG, BIT_0);
|
||||
|
||||
//clear ptp isr
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, 0xFFFF);
|
||||
|
||||
//enable ptp
|
||||
rtl8126_ptp_enable_config(tp);
|
||||
|
||||
//rtl8126_set_local_time(tp);
|
||||
} else {
|
||||
/* trx timestamp interrupt disable */
|
||||
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_INER, BIT_2 | BIT_3);
|
||||
|
||||
/* disable ptp */
|
||||
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
|
||||
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_CTL, BIT_0);
|
||||
rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtl8126_set_local_time(struct rtl8126_private *tp)
|
||||
{
|
||||
struct timespec64 ts64;
|
||||
//set system time
|
||||
ktime_get_real_ts64(&ts64);
|
||||
_rtl8126_phc_settime(tp, &ts64);
|
||||
}
|
||||
|
||||
static long rtl8126_ptp_create_clock(struct rtl8126_private *tp)
|
||||
{
|
||||
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;
|
||||
tp->ptp_clock_info.max_adj = 488281;//0x1FFFFF * 10^9 / 2^32
|
||||
|
||||
snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name),
|
||||
"%pm", tp->dev->dev_addr);
|
||||
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;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart
|
||||
rtl8126_hrtimer_for_pps(struct hrtimer *timer) {
|
||||
struct rtl8126_private *tp = container_of(timer, struct rtl8126_private, pps_timer);
|
||||
u16 tai_cfg = BIT_8 | BIT_3 | BIT_1 | BIT_0;
|
||||
s64 pps_sec;
|
||||
|
||||
if (tp->pps_enable)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
|
||||
//Direct Read
|
||||
rtl8126_set_clkadj_mode(tp, DIRECT_READ);
|
||||
|
||||
pps_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_HI_8126);
|
||||
pps_sec <<= 16;
|
||||
pps_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_MI_8126);
|
||||
pps_sec <<= 16;
|
||||
pps_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_LO_8126);
|
||||
pps_sec++;
|
||||
|
||||
//E42A[15:0]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_TS_S_LO, pps_sec & 0xffff);
|
||||
//E42C[31:16]
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_TS_S_HI, (pps_sec & 0xffff0000) >> 16);
|
||||
//Periodic Tai start
|
||||
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_CFG, tai_cfg);
|
||||
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
|
||||
hrtimer_forward_now(&tp->pps_timer, 1000000000); //rekick
|
||||
return HRTIMER_RESTART;
|
||||
} else
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
void rtl8126_ptp_reset(struct rtl8126_private *tp)
|
||||
{
|
||||
if (!tp->ptp_clock)
|
||||
return;
|
||||
|
||||
netif_info(tp, drv, tp->dev, "reset PHC clock\n");
|
||||
|
||||
rtl8126_hwtstamp_enable(tp, false);
|
||||
}
|
||||
|
||||
void rtl8126_ptp_init(struct rtl8126_private *tp)
|
||||
{
|
||||
/* obtain a PTP device, or re-use an existing device */
|
||||
if (rtl8126_ptp_create_clock(tp))
|
||||
return;
|
||||
|
||||
/* we have a clock so we can initialize work now */
|
||||
INIT_WORK(&tp->ptp_tx_work, rtl8126_ptp_tx_work);
|
||||
|
||||
/* init a hrtimer for pps */
|
||||
tp->pps_enable = 0;
|
||||
hrtimer_init(&tp->pps_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
tp->pps_timer.function = rtl8126_hrtimer_for_pps;
|
||||
|
||||
/* reset the PTP related hardware bits */
|
||||
rtl8126_ptp_reset(tp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void rtl8126_ptp_suspend(struct rtl8126_private *tp)
|
||||
{
|
||||
if (!tp->ptp_clock)
|
||||
return;
|
||||
|
||||
netif_info(tp, drv, tp->dev, "suspend PHC clock\n");
|
||||
|
||||
rtl8126_hwtstamp_enable(tp, false);
|
||||
|
||||
/* ensure that we cancel any pending PTP Tx work item in progress */
|
||||
cancel_work_sync(&tp->ptp_tx_work);
|
||||
|
||||
hrtimer_cancel(&tp->pps_timer);
|
||||
}
|
||||
|
||||
void rtl8126_ptp_stop(struct rtl8126_private *tp)
|
||||
{
|
||||
struct net_device *netdev = tp->dev;
|
||||
|
||||
netif_info(tp, drv, tp->dev, "stop PHC clock\n");
|
||||
|
||||
/* first, suspend PTP activity */
|
||||
rtl8126_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 rtl8126_set_tstamp(struct net_device *netdev, struct ifreq *ifr)
|
||||
{
|
||||
struct rtl8126_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;
|
||||
break;
|
||||
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;
|
||||
tp->flags |= RTL_FLAG_RX_HWTSTAMP_ENABLED;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
tp->flags &= ~RTL_FLAG_RX_HWTSTAMP_ENABLED;
|
||||
break;
|
||||
default:
|
||||
tp->flags &= ~RTL_FLAG_RX_HWTSTAMP_ENABLED;
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (tp->hwtstamp_config.tx_type != config.tx_type ||
|
||||
tp->hwtstamp_config.rx_filter != config.rx_filter) {
|
||||
tp->hwtstamp_config = config;
|
||||
|
||||
rtl8126_hwtstamp_enable(tp, hwtstamp);
|
||||
}
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &config,
|
||||
sizeof(config)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
static int rtl8126_get_tstamp(struct net_device *netdev, struct ifreq *ifr)
|
||||
{
|
||||
struct rtl8126_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 rtl8126_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
//netif_info(tp, drv, tp->dev, "ptp ioctl\n");
|
||||
|
||||
switch (cmd) {
|
||||
#ifdef ENABLE_PTP_SUPPORT
|
||||
case SIOCSHWTSTAMP:
|
||||
ret = rtl8126_set_tstamp(netdev, ifr);
|
||||
break;
|
||||
case SIOCGHWTSTAMP:
|
||||
ret = rtl8126_get_tstamp(netdev, ifr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rtl8126_rx_ptp_pktstamp(struct rtl8126_private *tp, struct sk_buff *skb, u8 type)
|
||||
{
|
||||
struct timespec64 ts64;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tp->phy_lock, flags);
|
||||
|
||||
rtl8126_ptp_ingresstime(tp, &ts64, type);
|
||||
|
||||
spin_unlock_irqrestore(&tp->phy_lock, flags);
|
||||
|
||||
skb_hwtstamps(skb)->hwtstamp = ktime_set(ts64.tv_sec, ts64.tv_nsec);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void rtl8126_rx_ptp_timestamp(struct rtl8126_private *tp, struct sk_buff *skb)
|
||||
{
|
||||
unsigned int ptp_class;
|
||||
struct ptp_header *hdr;
|
||||
u8 msgtype;
|
||||
|
||||
ptp_class = ptp_classify_raw(skb);
|
||||
if (ptp_class == PTP_CLASS_NONE)
|
||||
return;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
hdr = ptp_parse_header(skb, ptp_class);
|
||||
if (unlikely(!hdr))
|
||||
return;
|
||||
|
||||
msgtype = ptp_get_msgtype(hdr, ptp_class);
|
||||
rtl8126_rx_ptp_pktstamp(tp, skb, msgtype);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
|
||||
struct ptp_header *ptp_parse_header(struct sk_buff *skb, unsigned int type)
|
||||
{
|
||||
u8 *ptr = skb_mac_header(skb);
|
||||
|
||||
if (type & PTP_CLASS_VLAN)
|
||||
//ptr += VLAN_HLEN;
|
||||
ptr += 4;
|
||||
|
||||
switch (type & PTP_CLASS_PMASK) {
|
||||
case PTP_CLASS_IPV4:
|
||||
ptr += IPV4_HLEN(ptr) + UDP_HLEN;
|
||||
break;
|
||||
case PTP_CLASS_IPV6:
|
||||
ptr += IP6_HLEN + UDP_HLEN;
|
||||
break;
|
||||
case PTP_CLASS_L2:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr += ETH_HLEN;
|
||||
|
||||
/* Ensure that the entire header is present in this packet. */
|
||||
if (ptr + sizeof(struct ptp_header) > skb->data + skb->len)
|
||||
return NULL;
|
||||
|
||||
return (struct ptp_header *)ptr;
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) */
|
||||
202
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_ptp.h
Normal file
202
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_ptp.h
Normal file
@ -0,0 +1,202 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8126_PTP_H
|
||||
#define _LINUX_R8126_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>
|
||||
|
||||
#ifndef PTP_CLASS_NONE
|
||||
#define PTP_CLASS_NONE 0x00
|
||||
#endif
|
||||
|
||||
#ifndef PTP_MSGTYPE_SYNC
|
||||
#define PTP_MSGTYPE_SYNC 0x0
|
||||
#endif
|
||||
#ifndef PTP_MSGTYPE_DELAY_REQ
|
||||
#define PTP_MSGTYPE_DELAY_REQ 0x1
|
||||
#endif
|
||||
#ifndef PTP_MSGTYPE_PDELAY_REQ
|
||||
#define PTP_MSGTYPE_PDELAY_REQ 0x2
|
||||
#endif
|
||||
#ifndef PTP_MSGTYPE_PDELAY_RESP
|
||||
#define PTP_MSGTYPE_PDELAY_RESP 0x3
|
||||
#endif
|
||||
|
||||
struct rtl8126_ptp_info {
|
||||
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,
|
||||
};
|
||||
|
||||
enum PTP_CLKADJ_MOD_TYPE {
|
||||
NO_FUNCTION = 0,
|
||||
CLKADJ_MODE_SET = 1,
|
||||
RESERVED = 2,
|
||||
DIRECT_READ = 4,
|
||||
DIRECT_WRITE = 6,
|
||||
INCREMENT_STEP = 8,
|
||||
DECREMENT_STEP = 10,
|
||||
RATE_READ = 12,
|
||||
RATE_WRITE = 14,
|
||||
};
|
||||
|
||||
enum PTP_INSR_TYPE {
|
||||
EVENT_CAP_INTR = (1 << 0),
|
||||
TRIG_GEN_INTR = (1 << 1),
|
||||
RX_TS_INTR = (1 << 2),
|
||||
TX_TX_INTR = (1 << 3),
|
||||
};
|
||||
|
||||
enum PTP_TRX_TS_STA_REG {
|
||||
TRX_TS_RD = (1 << 0),
|
||||
TRXTS_SEL = (1 << 1),
|
||||
RX_TS_PDLYRSP_RDY = (1 << 8),
|
||||
RX_TS_PDLYREQ_RDY = (1 << 9),
|
||||
RX_TS_DLYREQ_RDY = (1 << 10),
|
||||
RX_TS_SYNC_RDY = (1 << 11),
|
||||
TX_TS_PDLYRSP_RDY = (1 << 12),
|
||||
TX_TS_PDLYREQ_RDY = (1 << 13),
|
||||
TX_TS_DLYREQ_RDY = (1 << 14),
|
||||
TX_TS_SYNC_RDY = (1 << 15),
|
||||
};
|
||||
|
||||
#define PTP_CTL_TYPE_0 (0xF3F)
|
||||
#define PTP_CTL_TYPE_1 (0x2FF)
|
||||
#define PTP_CTL_TYPE_2 (0x0FF)
|
||||
#define PTP_CTL_TYPE_3 (0x03F)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
|
||||
struct clock_identity {
|
||||
u8 id[8];
|
||||
} __packed;
|
||||
|
||||
struct port_identity {
|
||||
struct clock_identity clock_identity;
|
||||
__be16 port_number;
|
||||
} __packed;
|
||||
|
||||
struct ptp_header {
|
||||
u8 tsmt; /* transportSpecific | messageType */
|
||||
u8 ver; /* reserved | versionPTP */
|
||||
__be16 message_length;
|
||||
u8 domain_number;
|
||||
u8 reserved1;
|
||||
u8 flag_field[2];
|
||||
__be64 correction;
|
||||
__be32 reserved2;
|
||||
struct port_identity source_port_identity;
|
||||
__be16 sequence_id;
|
||||
u8 control;
|
||||
u8 log_message_interval;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* ptp_parse_header - Get pointer to the PTP v2 header
|
||||
* @skb: packet buffer
|
||||
* @type: type of the packet (see ptp_classify_raw())
|
||||
*
|
||||
* This function takes care of the VLAN, UDP, IPv4 and IPv6 headers. The length
|
||||
* is checked.
|
||||
*
|
||||
* Note, internally skb_mac_header() is used. Make sure that the @skb is
|
||||
* initialized accordingly.
|
||||
*
|
||||
* Return: Pointer to the ptp v2 header or NULL if not found
|
||||
*/
|
||||
struct ptp_header *ptp_parse_header(struct sk_buff *skb, unsigned int type);
|
||||
|
||||
/**
|
||||
* ptp_get_msgtype - Extract ptp message type from given header
|
||||
* @hdr: ptp header
|
||||
* @type: type of the packet (see ptp_classify_raw())
|
||||
*
|
||||
* This function returns the message type for a given ptp header. It takes care
|
||||
* of the different ptp header versions (v1 or v2).
|
||||
*
|
||||
* Return: The message type
|
||||
*/
|
||||
static inline u8 ptp_get_msgtype(const struct ptp_header *hdr,
|
||||
unsigned int type)
|
||||
{
|
||||
u8 msgtype;
|
||||
|
||||
if (unlikely(type & PTP_CLASS_V1)) {
|
||||
/* msg type is located at the control field for ptp v1 */
|
||||
msgtype = hdr->control;
|
||||
} else {
|
||||
msgtype = hdr->tsmt & 0x0f;
|
||||
}
|
||||
|
||||
return msgtype;
|
||||
}
|
||||
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) */
|
||||
|
||||
struct rtl8126_private;
|
||||
struct RxDescV3;
|
||||
|
||||
int rtl8126_get_ts_info(struct net_device *netdev,
|
||||
struct ethtool_ts_info *info);
|
||||
|
||||
void rtl8126_ptp_reset(struct rtl8126_private *tp);
|
||||
void rtl8126_ptp_init(struct rtl8126_private *tp);
|
||||
void rtl8126_ptp_suspend(struct rtl8126_private *tp);
|
||||
void rtl8126_ptp_stop(struct rtl8126_private *tp);
|
||||
|
||||
int rtl8126_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
|
||||
|
||||
void rtl8126_rx_ptp_timestamp(struct rtl8126_private *tp, struct sk_buff *skb);
|
||||
|
||||
void rtl8126_set_local_time(struct rtl8126_private *tp);
|
||||
|
||||
#endif /* _LINUX_R8126_PTP_H */
|
||||
@ -0,0 +1,118 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8126_REALWOW_H
|
||||
#define _LINUX_R8126_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 rtl8126_realwow_ioctl(struct net_device *dev, struct ifreq *ifr);
|
||||
void rtl8126_realwow_hw_init(struct net_device *dev);
|
||||
void rtl8126_get_realwow_hw_version(struct net_device *dev);
|
||||
void rtl8126_set_realwow_d3_para(struct net_device *dev);
|
||||
|
||||
#endif /* _LINUX_R8126_REALWOW_H */
|
||||
583
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_rss.c
Normal file
583
KernelPackages/drivers/net/ethernet/realtek/r8126/r8126_rss.c
Normal file
@ -0,0 +1,583 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "r8126.h"
|
||||
|
||||
enum rtl8126_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_CTRL_IPV6_EXT_SUPP = (1 << 4),
|
||||
RSS_CTRL_TCP_IPV6_EXT_SUPP = (1 << 5),
|
||||
RSS_HALF_SUPP = (1 << 7),
|
||||
RSS_CTRL_UDP_IPV4_SUPP = (1 << 11),
|
||||
RSS_CTRL_UDP_IPV6_SUPP = (1 << 12),
|
||||
RSS_CTRL_UDP_IPV6_EXT_SUPP = (1 << 13),
|
||||
RSS_QUAD_CPU_EN = (1 << 16),
|
||||
RSS_HQ_Q_SUP_R = (1 << 31),
|
||||
};
|
||||
|
||||
static int rtl8126_get_rss_hash_opts(struct rtl8126_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 rtl8126_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
||||
u32 *rule_locs)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return ret;
|
||||
|
||||
switch (cmd->cmd) {
|
||||
case ETHTOOL_GRXRINGS:
|
||||
cmd->data = rtl8126_tot_rx_rings(tp);
|
||||
ret = 0;
|
||||
break;
|
||||
case ETHTOOL_GRXFH:
|
||||
ret = rtl8126_get_rss_hash_opts(tp, cmd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 rtl8126_rss_indir_tbl_entries(struct rtl8126_private *tp)
|
||||
{
|
||||
return tp->HwSuppIndirTblEntries;
|
||||
}
|
||||
|
||||
#define RSS_MASK_BITS_OFFSET (8)
|
||||
#define RSS_CPU_NUM_OFFSET (16)
|
||||
#define RTL8126_UDP_RSS_FLAGS (RTL_8125_RSS_FLAG_HASH_UDP_IPV4 | \
|
||||
RTL_8125_RSS_FLAG_HASH_UDP_IPV6)
|
||||
static int _rtl8126_set_rss_hash_opt(struct rtl8126_private *tp)
|
||||
{
|
||||
u32 rss_flags = tp->rss_flags;
|
||||
u32 hash_mask_len;
|
||||
u32 rss_ctrl;
|
||||
|
||||
rss_ctrl = ilog2(rtl8126_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_IPV6_EXT_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_EXT_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 |
|
||||
RSS_CTRL_UDP_IPV6_EXT_SUPP;
|
||||
|
||||
hash_mask_len = ilog2(rtl8126_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 rtl8126_set_rss_hash_opt(struct rtl8126_private *tp,
|
||||
struct ethtool_rxnfc *nfc)
|
||||
{
|
||||
u32 rss_flags = tp->rss_flags;
|
||||
|
||||
/*
|
||||
* 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 & RTL8126_UDP_RSS_FLAGS) &&
|
||||
!(tp->rss_flags & RTL8126_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_IPV6_EXT_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_EXT_SUPP;
|
||||
|
||||
rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP |
|
||||
RSS_CTRL_UDP_IPV6_SUPP |
|
||||
RSS_CTRL_UDP_IPV6_EXT_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 |
|
||||
RSS_CTRL_UDP_IPV6_EXT_SUPP;
|
||||
|
||||
RTL_W32(tp, RSS_CTRL_8125, rss_ctrl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8126_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return ret;
|
||||
|
||||
switch (cmd->cmd) {
|
||||
case ETHTOOL_SRXFH:
|
||||
ret = rtl8126_set_rss_hash_opt(tp, cmd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 _rtl8126_get_rxfh_key_size(struct rtl8126_private *tp)
|
||||
{
|
||||
return sizeof(tp->rss_key);
|
||||
}
|
||||
|
||||
u32 rtl8126_get_rxfh_key_size(struct net_device *dev)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return 0;
|
||||
|
||||
return _rtl8126_get_rxfh_key_size(tp);
|
||||
}
|
||||
|
||||
u32 rtl8126_rss_indir_size(struct net_device *dev)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return 0;
|
||||
|
||||
return rtl8126_rss_indir_tbl_entries(tp);
|
||||
}
|
||||
|
||||
static void rtl8126_get_reta(struct rtl8126_private *tp, u32 *indir)
|
||||
{
|
||||
int i, reta_size = rtl8126_rss_indir_tbl_entries(tp);
|
||||
|
||||
for (i = 0; i < reta_size; i++)
|
||||
indir[i] = tp->rss_indir_tbl[i];
|
||||
}
|
||||
|
||||
static u32 rtl8126_rss_key_reg(struct rtl8126_private *tp)
|
||||
{
|
||||
return RSS_KEY_8125;
|
||||
}
|
||||
|
||||
static u32 rtl8126_rss_indir_tbl_reg(struct rtl8126_private *tp)
|
||||
{
|
||||
return RSS_INDIRECTION_TBL_8125_V2;
|
||||
}
|
||||
|
||||
static void rtl8126_store_reta(struct rtl8126_private *tp)
|
||||
{
|
||||
u16 indir_tbl_reg = rtl8126_rss_indir_tbl_reg(tp);
|
||||
u32 i, reta_entries = rtl8126_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 rtl8126_store_rss_key(struct rtl8126_private *tp)
|
||||
{
|
||||
const u16 rss_key_reg = rtl8126_rss_key_reg(tp);
|
||||
u32 i, rss_key_size = _rtl8126_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++);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
|
||||
int rtl8126_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rxfh->hfunc = ETH_RSS_HASH_TOP;
|
||||
|
||||
if (rxfh->indir)
|
||||
rtl8126_get_reta(tp, rxfh->indir);
|
||||
|
||||
if (rxfh->key)
|
||||
memcpy(rxfh->key, tp->rss_key, RTL8126_RSS_KEY_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8126_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
int i;
|
||||
u32 reta_entries = rtl8126_rss_indir_tbl_entries(tp);
|
||||
|
||||
/* We require at least one supported parameter to be changed and no
|
||||
* change in any of the unsupported parameters
|
||||
*/
|
||||
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && rxfh->hfunc != ETH_RSS_HASH_TOP)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Fill out the redirection table */
|
||||
if (rxfh->indir) {
|
||||
int max_queues = tp->num_rx_rings;
|
||||
|
||||
/* Verify user input. */
|
||||
for (i = 0; i < reta_entries; i++)
|
||||
if (rxfh->indir[i] >= max_queues)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < reta_entries; i++)
|
||||
tp->rss_indir_tbl[i] = rxfh->indir[i];
|
||||
}
|
||||
|
||||
/* Fill out the rss hash key */
|
||||
if (rxfh->key)
|
||||
memcpy(tp->rss_key, rxfh->key, RTL8126_RSS_KEY_SIZE);
|
||||
|
||||
rtl8126_store_reta(tp);
|
||||
|
||||
rtl8126_store_rss_key(tp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int rtl8126_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
|
||||
u8 *hfunc)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (hfunc)
|
||||
*hfunc = ETH_RSS_HASH_TOP;
|
||||
|
||||
if (indir)
|
||||
rtl8126_get_reta(tp, indir);
|
||||
|
||||
if (key)
|
||||
memcpy(key, tp->rss_key, RTL8126_RSS_KEY_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8126_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
{
|
||||
struct rtl8126_private *tp = netdev_priv(dev);
|
||||
int i;
|
||||
u32 reta_entries = rtl8126_rss_indir_tbl_entries(tp);
|
||||
|
||||
/* 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, RTL8126_RSS_KEY_SIZE);
|
||||
|
||||
rtl8126_store_reta(tp);
|
||||
|
||||
rtl8126_store_rss_key(tp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
|
||||
|
||||
static u32 rtl8126_get_rx_desc_hash(struct rtl8126_private *tp,
|
||||
struct RxDesc *desc)
|
||||
{
|
||||
switch (tp->InitRxDescType) {
|
||||
case RX_DESC_RING_TYPE_3:
|
||||
return le32_to_cpu(((struct RxDescV3 *)desc)->RxDescNormalDDWord2.RSSResult);
|
||||
case RX_DESC_RING_TYPE_4:
|
||||
return le32_to_cpu(((struct RxDescV4 *)desc)->RxDescNormalDDWord1.RSSResult);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define RXS_8125B_RSS_UDP BIT(9)
|
||||
#define RXS_8125_RSS_IPV4 BIT(10)
|
||||
#define RXS_8125_RSS_IPV6 BIT(12)
|
||||
#define RXS_8125_RSS_TCP BIT(13)
|
||||
#define RTL8126_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6)
|
||||
#define RTL8126_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP)
|
||||
|
||||
#define RXS_8125B_RSS_UDP_V4 BIT(27)
|
||||
#define RXS_8125_RSS_IPV4_V4 BIT(28)
|
||||
#define RXS_8125_RSS_IPV6_V4 BIT(29)
|
||||
#define RXS_8125_RSS_TCP_V4 BIT(30)
|
||||
#define RTL8126_RXS_RSS_L3_TYPE_MASK_V4 (RXS_8125_RSS_IPV4_V4 | RXS_8125_RSS_IPV6_V4)
|
||||
#define RTL8126_RXS_RSS_L4_TYPE_MASK_V4 (RXS_8125_RSS_TCP_V4 | RXS_8125B_RSS_UDP_V4)
|
||||
static void rtl8126_rx_hash_v3(struct rtl8126_private *tp,
|
||||
struct RxDescV3 *descv3,
|
||||
struct 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 & RTL8126_RXS_RSS_L3_TYPE_MASK))
|
||||
return;
|
||||
|
||||
skb_set_hash(skb, rtl8126_get_rx_desc_hash(tp, (struct RxDesc *)descv3),
|
||||
(RTL8126_RXS_RSS_L4_TYPE_MASK & rss_header_info) ?
|
||||
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
|
||||
}
|
||||
|
||||
static void rtl8126_rx_hash_v4(struct rtl8126_private *tp,
|
||||
struct RxDescV4 *descv4,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u32 rss_header_info;
|
||||
|
||||
if (!(tp->dev->features & NETIF_F_RXHASH))
|
||||
return;
|
||||
|
||||
rss_header_info = le32_to_cpu(descv4->RxDescNormalDDWord1.RSSInfo);
|
||||
|
||||
if (!(rss_header_info & RTL8126_RXS_RSS_L3_TYPE_MASK_V4))
|
||||
return;
|
||||
|
||||
skb_set_hash(skb, rtl8126_get_rx_desc_hash(tp, (struct RxDesc *)descv4),
|
||||
(RTL8126_RXS_RSS_L4_TYPE_MASK_V4 & rss_header_info) ?
|
||||
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
|
||||
}
|
||||
|
||||
void rtl8126_rx_hash(struct rtl8126_private *tp,
|
||||
struct RxDesc *desc,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
switch (tp->InitRxDescType) {
|
||||
case RX_DESC_RING_TYPE_3:
|
||||
rtl8126_rx_hash_v3(tp, (struct RxDescV3 *)desc, skb);
|
||||
break;
|
||||
case RX_DESC_RING_TYPE_4:
|
||||
rtl8126_rx_hash_v4(tp, (struct RxDescV4 *)desc, skb);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8126_disable_rss(struct rtl8126_private *tp)
|
||||
{
|
||||
RTL_W32(tp, RSS_CTRL_8125, 0x00);
|
||||
}
|
||||
|
||||
void _rtl8126_config_rss(struct rtl8126_private *tp)
|
||||
{
|
||||
_rtl8126_set_rss_hash_opt(tp);
|
||||
|
||||
rtl8126_store_reta(tp);
|
||||
|
||||
rtl8126_store_rss_key(tp);
|
||||
}
|
||||
|
||||
void rtl8126_config_rss(struct rtl8126_private *tp)
|
||||
{
|
||||
if (!tp->EnableRss) {
|
||||
rtl8126_disable_rss(tp);
|
||||
return;
|
||||
}
|
||||
|
||||
_rtl8126_config_rss(tp);
|
||||
}
|
||||
|
||||
void rtl8126_init_rss(struct rtl8126_private *tp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rtl8126_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, RTL8126_RSS_KEY_SIZE);
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8126_RSS_H
|
||||
#define _LINUX_R8126_RSS_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define RTL8126_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */
|
||||
#define RTL8126_MAX_INDIRECTION_TABLE_ENTRIES 128
|
||||
|
||||
enum rtl8126_rss_flag {
|
||||
RTL_8125_RSS_FLAG_HASH_UDP_IPV4 = (1 << 0),
|
||||
RTL_8125_RSS_FLAG_HASH_UDP_IPV6 = (1 << 1),
|
||||
};
|
||||
|
||||
struct rtl8126_private;
|
||||
struct RxDesc;
|
||||
|
||||
int rtl8126_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
||||
u32 *rule_locs);
|
||||
int rtl8126_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd);
|
||||
u32 rtl8126_get_rxfh_key_size(struct net_device *netdev);
|
||||
u32 rtl8126_rss_indir_size(struct net_device *netdev);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
|
||||
int rtl8126_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh);
|
||||
int rtl8126_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack);
|
||||
#else
|
||||
int rtl8126_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
|
||||
u8 *hfunc);
|
||||
int rtl8126_set_rxfh(struct net_device *netdev, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc);
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
|
||||
void rtl8126_rx_hash(struct rtl8126_private *tp,
|
||||
struct RxDesc *desc,
|
||||
struct sk_buff *skb);
|
||||
void _rtl8126_config_rss(struct rtl8126_private *tp);
|
||||
void rtl8126_config_rss(struct rtl8126_private *tp);
|
||||
void rtl8126_init_rss(struct rtl8126_private *tp);
|
||||
u32 rtl8126_rss_indir_tbl_entries(struct rtl8126_private *tp);
|
||||
void rtl8126_disable_rss(struct rtl8126_private *tp);
|
||||
|
||||
#endif /* _LINUX_R8126_RSS_H */
|
||||
285
KernelPackages/drivers/net/ethernet/realtek/r8126/rtl_eeprom.c
Normal file
285
KernelPackages/drivers/net/ethernet/realtek/r8126/rtl_eeprom.c
Normal file
@ -0,0 +1,285 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#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 "r8126.h"
|
||||
#include "rtl_eeprom.h"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//rtl8126_eeprom_type():
|
||||
// tell the eeprom type
|
||||
//return value:
|
||||
// 0: the eeprom type is 93C46
|
||||
// 1: the eeprom type is 93C56 or 93C66
|
||||
//-------------------------------------------------------------------
|
||||
void rtl8126_eeprom_type(struct rtl8126_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 = rtl8126_eeprom_read_sc(tp, 0);
|
||||
|
||||
out_no_eeprom:
|
||||
if ((magic != 0x8129) && (magic != 0x8128)) {
|
||||
tp->eeprom_type = EEPROM_TYPE_NONE;
|
||||
tp->eeprom_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8126_eeprom_cleanup(struct rtl8126_private *tp)
|
||||
{
|
||||
u8 x;
|
||||
|
||||
x = RTL_R8(tp, Cfg9346);
|
||||
x &= ~(Cfg9346_EEDI | Cfg9346_EECS);
|
||||
|
||||
RTL_W8(tp, Cfg9346, x);
|
||||
|
||||
rtl8126_raise_clock(tp, &x);
|
||||
rtl8126_lower_clock(tp, &x);
|
||||
}
|
||||
|
||||
static int rtl8126_eeprom_cmd_done(struct rtl8126_private *tp)
|
||||
{
|
||||
u8 x;
|
||||
int i;
|
||||
|
||||
rtl8126_stand_by(tp);
|
||||
|
||||
for (i = 0; i < 50000; i++) {
|
||||
x = RTL_R8(tp, Cfg9346);
|
||||
|
||||
if (x & Cfg9346_EEDO) {
|
||||
fsleep(RTL_CLOCK_RATE * 2 * 3);
|
||||
return 0;
|
||||
}
|
||||
fsleep(1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//rtl8126_eeprom_read_sc():
|
||||
// read one word from eeprom
|
||||
//-------------------------------------------------------------------
|
||||
u16 rtl8126_eeprom_read_sc(struct rtl8126_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);
|
||||
|
||||
rtl8126_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3);
|
||||
rtl8126_shift_out_bits(tp, reg, addr_sz);
|
||||
|
||||
data = rtl8126_shift_in_bits(tp);
|
||||
|
||||
rtl8126_eeprom_cleanup(tp);
|
||||
|
||||
RTL_W8(tp, Cfg9346, 0);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//rtl8126_eeprom_write_sc():
|
||||
// write one word to a specific address in the eeprom
|
||||
//-------------------------------------------------------------------
|
||||
void rtl8126_eeprom_write_sc(struct rtl8126_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);
|
||||
|
||||
rtl8126_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5);
|
||||
rtl8126_shift_out_bits(tp, reg, w_dummy_addr);
|
||||
rtl8126_stand_by(tp);
|
||||
|
||||
rtl8126_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3);
|
||||
rtl8126_shift_out_bits(tp, reg, addr_sz);
|
||||
if (rtl8126_eeprom_cmd_done(tp) < 0)
|
||||
return;
|
||||
rtl8126_stand_by(tp);
|
||||
|
||||
rtl8126_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3);
|
||||
rtl8126_shift_out_bits(tp, reg, addr_sz);
|
||||
rtl8126_shift_out_bits(tp, data, 16);
|
||||
if (rtl8126_eeprom_cmd_done(tp) < 0)
|
||||
return;
|
||||
rtl8126_stand_by(tp);
|
||||
|
||||
rtl8126_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5);
|
||||
rtl8126_shift_out_bits(tp, reg, w_dummy_addr);
|
||||
|
||||
rtl8126_eeprom_cleanup(tp);
|
||||
RTL_W8(tp, Cfg9346, 0);
|
||||
}
|
||||
|
||||
void rtl8126_raise_clock(struct rtl8126_private *tp, u8 *x)
|
||||
{
|
||||
*x = *x | Cfg9346_EESK;
|
||||
RTL_W8(tp, Cfg9346, *x);
|
||||
fsleep(RTL_CLOCK_RATE);
|
||||
}
|
||||
|
||||
void rtl8126_lower_clock(struct rtl8126_private *tp, u8 *x)
|
||||
{
|
||||
|
||||
*x = *x & ~Cfg9346_EESK;
|
||||
RTL_W8(tp, Cfg9346, *x);
|
||||
fsleep(RTL_CLOCK_RATE);
|
||||
}
|
||||
|
||||
void rtl8126_shift_out_bits(struct rtl8126_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);
|
||||
fsleep(RTL_CLOCK_RATE);
|
||||
rtl8126_raise_clock(tp, &x);
|
||||
rtl8126_lower_clock(tp, &x);
|
||||
mask = mask >> 1;
|
||||
} while(mask);
|
||||
|
||||
x &= ~Cfg9346_EEDI;
|
||||
RTL_W8(tp, Cfg9346, x);
|
||||
}
|
||||
|
||||
u16 rtl8126_shift_in_bits(struct rtl8126_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;
|
||||
rtl8126_raise_clock(tp, &x);
|
||||
|
||||
x = RTL_R8(tp, Cfg9346);
|
||||
x &= ~Cfg9346_EEDI;
|
||||
|
||||
if (x & Cfg9346_EEDO)
|
||||
d |= 1;
|
||||
|
||||
rtl8126_lower_clock(tp, &x);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void rtl8126_stand_by(struct rtl8126_private *tp)
|
||||
{
|
||||
u8 x;
|
||||
|
||||
x = RTL_R8(tp, Cfg9346);
|
||||
x &= ~(Cfg9346_EECS | Cfg9346_EESK);
|
||||
RTL_W8(tp, Cfg9346, x);
|
||||
fsleep(RTL_CLOCK_RATE);
|
||||
|
||||
x |= Cfg9346_EECS;
|
||||
RTL_W8(tp, Cfg9346, x);
|
||||
}
|
||||
|
||||
void rtl8126_set_eeprom_sel_low(struct rtl8126_private *tp)
|
||||
{
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK);
|
||||
|
||||
fsleep(20);
|
||||
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_RTLEEPROM_H
|
||||
#define _LINUX_RTLEEPROM_H
|
||||
|
||||
//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 rtl8126_eeprom_type(struct rtl8126_private *tp);
|
||||
void rtl8126_eeprom_cleanup(struct rtl8126_private *tp);
|
||||
u16 rtl8126_eeprom_read_sc(struct rtl8126_private *tp, u16 reg);
|
||||
void rtl8126_eeprom_write_sc(struct rtl8126_private *tp, u16 reg, u16 data);
|
||||
void rtl8126_shift_out_bits(struct rtl8126_private *tp, int data, int count);
|
||||
u16 rtl8126_shift_in_bits(struct rtl8126_private *tp);
|
||||
void rtl8126_raise_clock(struct rtl8126_private *tp, u8 *x);
|
||||
void rtl8126_lower_clock(struct rtl8126_private *tp, u8 *x);
|
||||
void rtl8126_stand_by(struct rtl8126_private *tp);
|
||||
void rtl8126_set_eeprom_sel_low(struct rtl8126_private *tp);
|
||||
|
||||
#endif /* _LINUX_RTLEEPROM_H */
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8126/rtl_eeprom.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8126/rtl_eeprom.o
Normal file
Binary file not shown.
295
KernelPackages/drivers/net/ethernet/realtek/r8126/rtltool.c
Normal file
295
KernelPackages/drivers/net/ethernet/realtek/r8126/rtltool.c
Normal file
@ -0,0 +1,295 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#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 "r8126.h"
|
||||
#include "rtl_eeprom.h"
|
||||
#include "rtltool.h"
|
||||
|
||||
int rtl8126_tool_ioctl(struct rtl8126_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 ((my_cmd.offset + my_cmd.len) > pci_resource_len(tp->pci_dev, 2)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
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 ((my_cmd.offset + my_cmd.len) > pci_resource_len(tp->pci_dev, 2)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
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:
|
||||
my_cmd.data = rtl8126_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:
|
||||
rtl8126_mdio_prot_write(tp, my_cmd.offset, my_cmd.data);
|
||||
break;
|
||||
|
||||
case RTLTOOL_READ_EPHY:
|
||||
my_cmd.data = rtl8126_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:
|
||||
rtl8126_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 = rtl8126_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 (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) {
|
||||
rtl8126_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC);
|
||||
} else {
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case RTLTOOL_READ_PCI:
|
||||
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 (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:
|
||||
my_cmd.data = rtl8126_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:
|
||||
rtl8126_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data);
|
||||
break;
|
||||
|
||||
case RTL_READ_OOB_MAC:
|
||||
rtl8126_oob_mutex_lock(tp);
|
||||
my_cmd.data = rtl8126_ocp_read(tp, my_cmd.offset, 4);
|
||||
rtl8126_oob_mutex_unlock(tp);
|
||||
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case RTL_WRITE_OOB_MAC:
|
||||
if (my_cmd.len == 0 || my_cmd.len > 4)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rtl8126_oob_mutex_lock(tp);
|
||||
rtl8126_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data);
|
||||
rtl8126_oob_mutex_unlock(tp);
|
||||
break;
|
||||
|
||||
case RTL_ENABLE_PCI_DIAG:
|
||||
tp->rtk_enable_diag = 1;
|
||||
|
||||
dprintk("enable rtk diag\n");
|
||||
break;
|
||||
|
||||
case RTL_DISABLE_PCI_DIAG:
|
||||
tp->rtk_enable_diag = 0;
|
||||
|
||||
dprintk("disable rtk diag\n");
|
||||
break;
|
||||
|
||||
case RTL_READ_MAC_OCP:
|
||||
if (my_cmd.offset % 2)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
my_cmd.data = rtl8126_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 ((my_cmd.offset % 2) || (my_cmd.len != 2))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rtl8126_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data);
|
||||
break;
|
||||
|
||||
case RTL_DIRECT_READ_PHY_OCP:
|
||||
my_cmd.data = rtl8126_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:
|
||||
rtl8126_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data);
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_FIBER_SUPPORT
|
||||
case RTL_READ_FIBER_PHY:
|
||||
if (!HW_FIBER_STATUS_CONNECTED(tp)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
my_cmd.data = rtl8126_fiber_mdio_read(tp, my_cmd.offset);
|
||||
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RTL_WRITE_FIBER_PHY:
|
||||
if (!HW_FIBER_STATUS_CONNECTED(tp)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
rtl8126_fiber_mdio_write(tp, my_cmd.offset, my_cmd.data);
|
||||
break;
|
||||
#endif /* ENABLE_FIBER_SUPPORT */
|
||||
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
89
KernelPackages/drivers/net/ethernet/realtek/r8126/rtltool.h
Normal file
89
KernelPackages/drivers/net/ethernet/realtek/r8126/rtltool.h
Normal file
@ -0,0 +1,89 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8126 is the Linux device driver released for Realtek 5 Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_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,
|
||||
|
||||
RTL_READ_FIBER_PHY,
|
||||
RTL_WRITE_FIBER_PHY,
|
||||
|
||||
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 rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr);
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_RTLTOOL_H */
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8126/rtltool.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8126/rtltool.o
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
||||
savedcmd_drivers/net/ethernet/realtek/r8168/built-in.a := rm -f drivers/net/ethernet/realtek/r8168/built-in.a; printf "drivers/net/ethernet/realtek/r8168/%s " r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o | xargs ar cDPrST drivers/net/ethernet/realtek/r8168/built-in.a
|
||||
1624
KernelPackages/drivers/net/ethernet/realtek/r8168/.r8168_asf.o.cmd
Normal file
1624
KernelPackages/drivers/net/ethernet/realtek/r8168/.r8168_asf.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1669
KernelPackages/drivers/net/ethernet/realtek/r8168/.r8168_n.o.cmd
Normal file
1669
KernelPackages/drivers/net/ethernet/realtek/r8168/.r8168_n.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1534
KernelPackages/drivers/net/ethernet/realtek/r8168/.rtl_eeprom.o.cmd
Normal file
1534
KernelPackages/drivers/net/ethernet/realtek/r8168/.rtl_eeprom.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
1568
KernelPackages/drivers/net/ethernet/realtek/r8168/.rtltool.o.cmd
Normal file
1568
KernelPackages/drivers/net/ethernet/realtek/r8168/.rtltool.o.cmd
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
config R8168
|
||||
tristate "Realtek GBE Ethernet driver (r8168)"
|
||||
depends on PCI && MII
|
||||
help
|
||||
This is the official Realtek GBE Ethernet driver.
|
||||
|
||||
68
KernelPackages/drivers/net/ethernet/realtek/r8168/Makefile
Normal file
68
KernelPackages/drivers/net/ethernet/realtek/r8168/Makefile
Normal file
@ -0,0 +1,68 @@
|
||||
obj-$(CONFIG_R8168) += r8168.o
|
||||
r8168-objs += r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o
|
||||
|
||||
EXTRA_CFLAGS += -DCONFIG_SOC_LAN
|
||||
EXTRA_CFLAGS += -DCONFIG_ASPM
|
||||
EXTRA_CFLAGS += -DENABLE_S5WOL
|
||||
EXTRA_CFLAGS += -DCONFIG_DYNAMIC_ASPM
|
||||
# EXTRA_CFLAGS += -DCONFIG_R8168_VLAN # Need to check if needed
|
||||
|
||||
#
|
||||
# Other options that can be enabled if needed.
|
||||
#
|
||||
#
|
||||
# ENABLE_REALWOW_SUPPORT:
|
||||
# r8168-objs += r8168_realwow.o
|
||||
# EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT
|
||||
#
|
||||
# ENABLE_FIBER_SUPPORT:
|
||||
# r8168-objs += r8168_fiber.o
|
||||
# EXTRA_CFLAGS += -DENABLE_FIBER_SUPPORT
|
||||
#
|
||||
# ENABLE_DASH_SUPPORT:
|
||||
# r8168-objs += r8168_dash.o
|
||||
# EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT
|
||||
#
|
||||
# ENABLE_DASH_PRINTER_SUPPORT:
|
||||
# r8168-objs += r8168_dash.o
|
||||
# EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT
|
||||
#
|
||||
# ENABLE_RSS_SUPPORT:
|
||||
# EXTRA_CFLAGS += -DCONFIG_R8168_NAPI
|
||||
#
|
||||
# CONFIG_DOWN_SPEED_100:
|
||||
# EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100
|
||||
#
|
||||
# ENABLE_S5_KEEP_CURR_MAC:
|
||||
# EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC
|
||||
#
|
||||
# ENABLE_EEE:
|
||||
# EXTRA_CFLAGS += -DENABLE_EEE
|
||||
#
|
||||
# ENABLE_S0_MAGIC_PACKET:
|
||||
# EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET
|
||||
#
|
||||
# CONFIG_DYNAMIC_ASPM:
|
||||
# EXTRA_CFLAGS += -DCONFIG_DYNAMIC_ASPM
|
||||
#
|
||||
# ENABLE_USE_FIRMWARE_FILE:
|
||||
# r8168-objs += r8168_firmware.o
|
||||
# EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE
|
||||
#
|
||||
# CONFIG_CTAP_SHORT_OFF:
|
||||
# EXTRA_CFLAGS += -DCONFIG_CTAP_SHORT_OFF
|
||||
#
|
||||
# ENABLE_MULTIPLE_TX_QUEUE:
|
||||
# EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE
|
||||
#
|
||||
# ENABLE_RSS_SUPPORT:
|
||||
# r8168-objs += r8168_rss.o
|
||||
# EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT
|
||||
#
|
||||
# ENABLE_LIB_SUPPORT:
|
||||
# r8168-objs += r8168_lib.o
|
||||
# EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT
|
||||
#
|
||||
# DISABLE_WOL_SUPPORT:
|
||||
# EXTRA_CFLAGS += -DDISABLE_WOL_SUPPORT
|
||||
|
||||
11
KernelPackages/drivers/net/ethernet/realtek/r8168/built-in.a
Normal file
11
KernelPackages/drivers/net/ethernet/realtek/r8168/built-in.a
Normal file
@ -0,0 +1,11 @@
|
||||
!<thin>
|
||||
// 50 `
|
||||
r8168_n.o/
|
||||
r8168_asf.o/
|
||||
rtl_eeprom.o/
|
||||
rtltool.o/
|
||||
|
||||
/0 0 0 0 644 1256280 `
|
||||
/11 0 0 0 644 15656 `
|
||||
/24 0 0 0 644 10088 `
|
||||
/38 0 0 0 644 5840 `
|
||||
2640
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168.h
Normal file
2640
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168.h
Normal file
File diff suppressed because it is too large
Load Diff
416
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_asf.c
Normal file
416
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_asf.c
Normal file
@ -0,0 +1,416 @@
|
||||
// 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "r8168.h"
|
||||
#include "r8168_asf.h"
|
||||
#include "rtl_eeprom.h"
|
||||
|
||||
int rtl8168_asf_ioctl(struct net_device *dev,
|
||||
struct ifreq *ifr)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
void *user_data = ifr->ifr_data;
|
||||
struct asf_ioctl_struct asf_usrdata;
|
||||
|
||||
if (tp->mcfg != CFG_METHOD_7 && tp->mcfg != CFG_METHOD_8)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&asf_usrdata, user_data, sizeof(struct asf_ioctl_struct)))
|
||||
return -EFAULT;
|
||||
|
||||
switch (asf_usrdata.offset) {
|
||||
case HBPeriod:
|
||||
rtl8168_asf_hbperiod(tp, asf_usrdata.arg, asf_usrdata.u.data);
|
||||
break;
|
||||
case WD8Timer:
|
||||
break;
|
||||
case WD16Rst:
|
||||
rtl8168_asf_wd16rst(tp, asf_usrdata.arg, asf_usrdata.u.data);
|
||||
break;
|
||||
case WD8Rst:
|
||||
rtl8168_asf_time_period(tp, asf_usrdata.arg, WD8Rst, asf_usrdata.u.data);
|
||||
break;
|
||||
case LSnsrPollCycle:
|
||||
rtl8168_asf_time_period(tp, asf_usrdata.arg, LSnsrPollCycle, asf_usrdata.u.data);
|
||||
break;
|
||||
case ASFSnsrPollPrd:
|
||||
rtl8168_asf_time_period(tp, asf_usrdata.arg, ASFSnsrPollPrd, asf_usrdata.u.data);
|
||||
break;
|
||||
case AlertReSendItvl:
|
||||
rtl8168_asf_time_period(tp, asf_usrdata.arg, AlertReSendItvl, asf_usrdata.u.data);
|
||||
break;
|
||||
case SMBAddr:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, SMBAddr, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case ASFConfigR0:
|
||||
rtl8168_asf_config_regs(tp, asf_usrdata.arg, ASFConfigR0, asf_usrdata.u.data);
|
||||
break;
|
||||
case ASFConfigR1:
|
||||
rtl8168_asf_config_regs(tp, asf_usrdata.arg, ASFConfigR1, asf_usrdata.u.data);
|
||||
break;
|
||||
case ConsoleMA:
|
||||
rtl8168_asf_console_mac(tp, asf_usrdata.arg, asf_usrdata.u.data);
|
||||
break;
|
||||
case ConsoleIP:
|
||||
rtl8168_asf_ip_address(tp, asf_usrdata.arg, ConsoleIP, asf_usrdata.u.data);
|
||||
break;
|
||||
case IPAddr:
|
||||
rtl8168_asf_ip_address(tp, asf_usrdata.arg, IPAddr, asf_usrdata.u.data);
|
||||
break;
|
||||
case UUID:
|
||||
rtl8168_asf_rw_uuid(tp, asf_usrdata.arg, asf_usrdata.u.data);
|
||||
break;
|
||||
case IANA:
|
||||
rtl8168_asf_rw_iana(tp, asf_usrdata.arg, asf_usrdata.u.data);
|
||||
break;
|
||||
case SysID:
|
||||
rtl8168_asf_rw_systemid(tp, asf_usrdata.arg, asf_usrdata.u.data);
|
||||
break;
|
||||
case Community:
|
||||
rtl8168_asf_community_string(tp, asf_usrdata.arg, asf_usrdata.u.string);
|
||||
break;
|
||||
case StringLength:
|
||||
rtl8168_asf_community_string_len(tp, asf_usrdata.arg, asf_usrdata.u.data);
|
||||
break;
|
||||
case FmCapMsk:
|
||||
rtl8168_asf_capability_masks(tp, asf_usrdata.arg, FmCapMsk, asf_usrdata.u.data);
|
||||
break;
|
||||
case SpCMDMsk:
|
||||
rtl8168_asf_capability_masks(tp, asf_usrdata.arg, SpCMDMsk, asf_usrdata.u.data);
|
||||
break;
|
||||
case SysCapMsk:
|
||||
rtl8168_asf_capability_masks(tp, asf_usrdata.arg, SysCapMsk, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtRstAddr:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstAddr, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtRstCmd:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstCmd, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtRstData:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstData, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPwrOffAddr:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffAddr, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPwrOffCmd:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffCmd, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPwrOffData:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffData, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPwrOnAddr:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnAddr, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPwrOnCmd:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnCmd, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPwrOnData:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnData, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPCRAddr:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRAddr, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPCRCmd:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRCmd, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case RmtPCRData:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRData, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case ASFSnsr0Addr:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, ASFSnsr0Addr, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case LSnsrAddr0:
|
||||
rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, LSnsrAddr0, RW_ONE_BYTE, asf_usrdata.u.data);
|
||||
break;
|
||||
case KO:
|
||||
/* Get/Set Key Operation */
|
||||
rtl8168_asf_key_access(tp, asf_usrdata.arg, KO, asf_usrdata.u.data);
|
||||
break;
|
||||
case KA:
|
||||
/* Get/Set Key Administrator */
|
||||
rtl8168_asf_key_access(tp, asf_usrdata.arg, KA, asf_usrdata.u.data);
|
||||
break;
|
||||
case KG:
|
||||
/* Get/Set Key Generation */
|
||||
rtl8168_asf_key_access(tp, asf_usrdata.arg, KG, asf_usrdata.u.data);
|
||||
break;
|
||||
case KR:
|
||||
/* Get/Set Key Random */
|
||||
rtl8168_asf_key_access(tp, asf_usrdata.arg, KR, asf_usrdata.u.data);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (copy_to_user(user_data, &asf_usrdata, sizeof(struct asf_ioctl_struct)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtl8168_asf_hbperiod(struct rtl8168_private *tp, int arg, unsigned int *data)
|
||||
{
|
||||
if (arg == ASF_GET)
|
||||
data[ASFHBPERIOD] = rtl8168_eri_read(tp, HBPeriod, RW_TWO_BYTES, ERIAR_ASF);
|
||||
else if (arg == ASF_SET) {
|
||||
rtl8168_eri_write(tp, HBPeriod, RW_TWO_BYTES, data[ASFHBPERIOD], ERIAR_ASF);
|
||||
rtl8168_eri_write(tp, 0x1EC, RW_ONE_BYTE, 0x07, ERIAR_ASF);
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8168_asf_wd16rst(struct rtl8168_private *tp, int arg, unsigned int *data)
|
||||
{
|
||||
data[ASFWD16RST] = rtl8168_eri_read(tp, WD16Rst, RW_TWO_BYTES, ERIAR_ASF);
|
||||
}
|
||||
|
||||
void rtl8168_asf_console_mac(struct rtl8168_private *tp, int arg, unsigned int *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (arg == ASF_GET) {
|
||||
for (i = 0; i < 6; i++)
|
||||
data[i] = rtl8168_eri_read(tp, ConsoleMA + i, RW_ONE_BYTE, ERIAR_ASF);
|
||||
} else if (arg == ASF_SET) {
|
||||
for (i = 0; i < 6; i++)
|
||||
rtl8168_eri_write(tp, ConsoleMA + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
|
||||
|
||||
/* write the new console MAC address to EEPROM */
|
||||
rtl8168_eeprom_write_sc(tp, 70, (data[1] << 8) | data[0]);
|
||||
rtl8168_eeprom_write_sc(tp, 71, (data[3] << 8) | data[2]);
|
||||
rtl8168_eeprom_write_sc(tp, 72, (data[5] << 8) | data[4]);
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8168_asf_ip_address(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
|
||||
{
|
||||
int i;
|
||||
int eeprom_off = 0;
|
||||
|
||||
if (arg == ASF_GET) {
|
||||
for (i = 0; i < 4; i++)
|
||||
data[i] = rtl8168_eri_read(tp, offset + i, RW_ONE_BYTE, ERIAR_ASF);
|
||||
} else if (arg == ASF_SET) {
|
||||
for (i = 0; i < 4; i++)
|
||||
rtl8168_eri_write(tp, offset + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
|
||||
|
||||
if (offset == ConsoleIP)
|
||||
eeprom_off = 73;
|
||||
else if (offset == IPAddr)
|
||||
eeprom_off = 75;
|
||||
|
||||
/* write the new IP address to EEPROM */
|
||||
rtl8168_eeprom_write_sc(tp, eeprom_off, (data[1] << 8) | data[0]);
|
||||
rtl8168_eeprom_write_sc(tp, eeprom_off + 1, (data[3] << 8) | data[2]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8168_asf_config_regs(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
if (arg == ASF_GET) {
|
||||
data[ASFCAPABILITY] = (rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF) & data[ASFCONFIG]) ? FUNCTION_ENABLE : FUNCTION_DISABLE;
|
||||
} else if (arg == ASF_SET) {
|
||||
value = rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF);
|
||||
|
||||
if (data[ASFCAPABILITY] == FUNCTION_ENABLE)
|
||||
value |= data[ASFCONFIG];
|
||||
else if (data[ASFCAPABILITY] == FUNCTION_DISABLE)
|
||||
value &= ~data[ASFCONFIG];
|
||||
|
||||
rtl8168_eri_write(tp, offset, RW_ONE_BYTE, value, ERIAR_ASF);
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8168_asf_capability_masks(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
|
||||
{
|
||||
unsigned int len, bit_mask;
|
||||
|
||||
bit_mask = DISABLE_MASK;
|
||||
|
||||
if (offset == FmCapMsk) {
|
||||
/* System firmware capabilities */
|
||||
len = RW_FOUR_BYTES;
|
||||
if (data[ASFCAPMASK] == FUNCTION_ENABLE)
|
||||
bit_mask = FMW_CAP_MASK;
|
||||
} else if (offset == SpCMDMsk) {
|
||||
/* Special commands */
|
||||
len = RW_TWO_BYTES;
|
||||
if (data[ASFCAPMASK] == FUNCTION_ENABLE)
|
||||
bit_mask = SPC_CMD_MASK;
|
||||
} else {
|
||||
/* System capability (offset == SysCapMsk)*/
|
||||
len = RW_ONE_BYTE;
|
||||
if (data[ASFCAPMASK] == FUNCTION_ENABLE)
|
||||
bit_mask = SYS_CAP_MASK;
|
||||
}
|
||||
|
||||
if (arg == ASF_GET)
|
||||
data[ASFCAPMASK] = rtl8168_eri_read(tp, offset, len, ERIAR_ASF) ? FUNCTION_ENABLE : FUNCTION_DISABLE;
|
||||
else /* arg == ASF_SET */
|
||||
rtl8168_eri_write(tp, offset, len, bit_mask, ERIAR_ASF);
|
||||
}
|
||||
|
||||
void rtl8168_asf_community_string(struct rtl8168_private *tp, int arg, char *string)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (arg == ASF_GET) {
|
||||
for (i = 0; i < COMMU_STR_MAX_LEN; i++)
|
||||
string[i] = rtl8168_eri_read(tp, Community + i, RW_ONE_BYTE, ERIAR_ASF);
|
||||
} else { /* arg == ASF_SET */
|
||||
for (i = 0; i < COMMU_STR_MAX_LEN; i++)
|
||||
rtl8168_eri_write(tp, Community + i, RW_ONE_BYTE, string[i], ERIAR_ASF);
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8168_asf_community_string_len(struct rtl8168_private *tp, int arg, unsigned int *data)
|
||||
{
|
||||
if (arg == ASF_GET)
|
||||
data[ASFCOMMULEN] = rtl8168_eri_read(tp, StringLength, RW_ONE_BYTE, ERIAR_ASF);
|
||||
else /* arg == ASF_SET */
|
||||
rtl8168_eri_write(tp, StringLength, RW_ONE_BYTE, data[ASFCOMMULEN], ERIAR_ASF);
|
||||
}
|
||||
|
||||
void rtl8168_asf_time_period(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
if (offset == WD8Rst)
|
||||
pos = ASFWD8RESET;
|
||||
else if (offset == LSnsrPollCycle)
|
||||
pos = ASFLSNRPOLLCYC;
|
||||
else if (offset == ASFSnsrPollPrd)
|
||||
pos = ASFSNRPOLLCYC;
|
||||
else if (offset == AlertReSendItvl)
|
||||
pos = ASFALERTRESND;
|
||||
|
||||
if (arg == ASF_GET)
|
||||
data[pos] = rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF);
|
||||
else /* arg == ASF_SET */
|
||||
rtl8168_eri_write(tp, offset, RW_ONE_BYTE, data[pos], ERIAR_ASF);
|
||||
|
||||
}
|
||||
|
||||
void rtl8168_asf_key_access(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
|
||||
{
|
||||
int i, j;
|
||||
int key_off = 0;
|
||||
|
||||
if (arg == ASF_GET) {
|
||||
for (i = 0; i < KEY_LEN; i++)
|
||||
data[i] = rtl8168_eri_read(tp, offset + KEY_LEN - (i + 1), RW_ONE_BYTE, ERIAR_ASF);
|
||||
} else {
|
||||
if (offset == KO)
|
||||
key_off = 162;
|
||||
else if (offset == KA)
|
||||
key_off = 172;
|
||||
else if (offset == KG)
|
||||
key_off = 182;
|
||||
else if (offset == KR)
|
||||
key_off = 192;
|
||||
|
||||
/* arg == ASF_SET */
|
||||
for (i = 0; i < KEY_LEN; i++)
|
||||
rtl8168_eri_write(tp, offset + KEY_LEN - (i + 1), RW_ONE_BYTE, data[i], ERIAR_ASF);
|
||||
|
||||
/* write the new key to EEPROM */
|
||||
for (i = 0, j = 19; i < 10; i++, j = j - 2)
|
||||
rtl8168_eeprom_write_sc(tp, key_off + i, (data[j - 1] << 8) | data[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8168_asf_rw_hexadecimal(struct rtl8168_private *tp, int arg, int offset, int len, unsigned int *data)
|
||||
{
|
||||
if (arg == ASF_GET)
|
||||
data[ASFRWHEXNUM] = rtl8168_eri_read(tp, offset, len, ERIAR_ASF);
|
||||
else /* arg == ASF_SET */
|
||||
rtl8168_eri_write(tp, offset, len, data[ASFRWHEXNUM], ERIAR_ASF);
|
||||
}
|
||||
|
||||
void rtl8168_asf_rw_systemid(struct rtl8168_private *tp, int arg, unsigned int *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (arg == ASF_GET)
|
||||
for (i = 0; i < SYSID_LEN; i++)
|
||||
data[i] = rtl8168_eri_read(tp, SysID + i, RW_ONE_BYTE, ERIAR_ASF);
|
||||
else /* arg == ASF_SET */
|
||||
for (i = 0; i < SYSID_LEN; i++)
|
||||
rtl8168_eri_write(tp, SysID + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
|
||||
}
|
||||
|
||||
void rtl8168_asf_rw_iana(struct rtl8168_private *tp, int arg, unsigned int *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (arg == ASF_GET)
|
||||
for (i = 0; i < RW_FOUR_BYTES; i++)
|
||||
data[i] = rtl8168_eri_read(tp, IANA + i, RW_ONE_BYTE, ERIAR_ASF);
|
||||
else /* arg == ASF_SET */
|
||||
for (i = 0; i < RW_FOUR_BYTES; i++)
|
||||
rtl8168_eri_write(tp, IANA + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
|
||||
}
|
||||
|
||||
void rtl8168_asf_rw_uuid(struct rtl8168_private *tp, int arg, unsigned int *data)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (arg == ASF_GET)
|
||||
for (i = UUID_LEN - 1, j = 0; i >= 0; i--, j++)
|
||||
data[j] = rtl8168_eri_read(tp, UUID + i, RW_ONE_BYTE, ERIAR_ASF);
|
||||
else /* arg == ASF_SET */
|
||||
for (i = UUID_LEN - 1, j = 0; i >= 0; i--, j++)
|
||||
rtl8168_eri_write(tp, UUID + i, RW_ONE_BYTE, data[j], ERIAR_ASF);
|
||||
}
|
||||
295
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_asf.h
Normal file
295
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_asf.h
Normal file
@ -0,0 +1,295 @@
|
||||
/* 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#define SIOCDEVPRIVATE_RTLASF SIOCDEVPRIVATE
|
||||
|
||||
#define FUNCTION_ENABLE 1
|
||||
#define FUNCTION_DISABLE 0
|
||||
|
||||
#define ASFCONFIG 0
|
||||
#define ASFCAPABILITY 1
|
||||
#define ASFCOMMULEN 0
|
||||
#define ASFHBPERIOD 0
|
||||
#define ASFWD16RST 0
|
||||
#define ASFCAPMASK 0
|
||||
#define ASFALERTRESND 0
|
||||
#define ASFLSNRPOLLCYC 0
|
||||
#define ASFSNRPOLLCYC 0
|
||||
#define ASFWD8RESET 0
|
||||
#define ASFRWHEXNUM 0
|
||||
|
||||
#define FMW_CAP_MASK 0x0000F867
|
||||
#define SPC_CMD_MASK 0x1F00
|
||||
#define SYS_CAP_MASK 0xFF
|
||||
#define DISABLE_MASK 0x00
|
||||
|
||||
#define MAX_DATA_LEN 200
|
||||
#define MAX_STR_LEN 200
|
||||
|
||||
#define COMMU_STR_MAX_LEN 23
|
||||
|
||||
#define KEY_LEN 20
|
||||
#define UUID_LEN 16
|
||||
#define SYSID_LEN 2
|
||||
|
||||
#define RW_ONE_BYTE 1
|
||||
#define RW_TWO_BYTES 2
|
||||
#define RW_FOUR_BYTES 4
|
||||
|
||||
enum asf_registers {
|
||||
HBPeriod = 0x0000,
|
||||
WD8Rst = 0x0002,
|
||||
WD8Timer = 0x0003,
|
||||
WD16Rst = 0x0004,
|
||||
LSnsrPollCycle = 0x0006,
|
||||
ASFSnsrPollPrd = 0x0007,
|
||||
AlertReSendCnt = 0x0008,
|
||||
AlertReSendItvl = 0x0009,
|
||||
SMBAddr = 0x000A,
|
||||
SMBCap = 0x000B,
|
||||
ASFConfigR0 = 0x000C,
|
||||
ASFConfigR1 = 0x000D,
|
||||
WD16Timer = 0x000E,
|
||||
ConsoleMA = 0x0010,
|
||||
ConsoleIP = 0x0016,
|
||||
IPAddr = 0x001A,
|
||||
|
||||
UUID = 0x0020,
|
||||
IANA = 0x0030,
|
||||
SysID = 0x0034,
|
||||
Community = 0x0036,
|
||||
StringLength = 0x004D,
|
||||
LC = 0x004E,
|
||||
EntityInst = 0x004F,
|
||||
FmCapMsk = 0x0050,
|
||||
SpCMDMsk = 0x0054,
|
||||
SysCapMsk = 0x0056,
|
||||
WDSysSt = 0x0057,
|
||||
RxMsgType = 0x0058,
|
||||
RxSpCMD = 0x0059,
|
||||
RxSpCMDPa = 0x005A,
|
||||
RxBtOpMsk = 0x005C,
|
||||
RmtRstAddr = 0x005E,
|
||||
RmtRstCmd = 0x005F,
|
||||
RmtRstData = 0x0060,
|
||||
RmtPwrOffAddr = 0x0061,
|
||||
RmtPwrOffCmd = 0x0062,
|
||||
RmtPwrOffData = 0x0063,
|
||||
RmtPwrOnAddr = 0x0064,
|
||||
RmtPwrOnCmd = 0x0065,
|
||||
RmtPwrOnData = 0x0066,
|
||||
RmtPCRAddr = 0x0067,
|
||||
RmtPCRCmd = 0x0068,
|
||||
RmtPCRData = 0x0069,
|
||||
RMCP_IANA = 0x006A,
|
||||
RMCP_OEM = 0x006E,
|
||||
ASFSnsr0Addr = 0x0070,
|
||||
|
||||
ASFSnsrEvSt = 0x0073,
|
||||
ASFSnsrEvAlert = 0x0081,
|
||||
|
||||
LSnsrNo = 0x00AD,
|
||||
AssrtEvntMsk = 0x00AE,
|
||||
DeAssrtEvntMsk = 0x00AF,
|
||||
|
||||
LSnsrAddr0 = 0x00B0,
|
||||
LAlertCMD0 = 0x00B1,
|
||||
LAlertDataMsk0 = 0x00B2,
|
||||
LAlertCmp0 = 0x00B3,
|
||||
LAlertESnsrT0 = 0x00B4,
|
||||
LAlertET0 = 0x00B5,
|
||||
LAlertEOffset0 = 0x00B6,
|
||||
LAlertES0 = 0x00B7,
|
||||
LAlertSN0 = 0x00B8,
|
||||
LAlertEntity0 = 0x00B9,
|
||||
LAlertEI0 = 0x00BA,
|
||||
LSnsrState0 = 0x00BB,
|
||||
|
||||
LSnsrAddr1 = 0x00BD,
|
||||
LAlertCMD1 = 0x00BE,
|
||||
LAlertDataMsk1 = 0x00BF,
|
||||
LAlertCmp1 = 0x00C0,
|
||||
LAlertESnsrT1 = 0x00C1,
|
||||
LAlertET1 = 0x00C2,
|
||||
LAlertEOffset1 = 0x00C3,
|
||||
LAlertES1 = 0x00C4,
|
||||
LAlertSN1 = 0x00C5,
|
||||
LAlertEntity1 = 0x00C6,
|
||||
LAlertEI1 = 0x00C7,
|
||||
LSnsrState1 = 0x00C8,
|
||||
|
||||
LSnsrAddr2 = 0x00CA,
|
||||
LAlertCMD2 = 0x00CB,
|
||||
LAlertDataMsk2 = 0x00CC,
|
||||
LAlertCmp2 = 0x00CD,
|
||||
LAlertESnsrT2 = 0x00CE,
|
||||
LAlertET2 = 0x00CF,
|
||||
LAlertEOffset2 = 0x00D0,
|
||||
LAlertES2 = 0x00D1,
|
||||
LAlertSN2 = 0x00D2,
|
||||
LAlertEntity2 = 0x00D3,
|
||||
LAlertEI2 = 0x00D4,
|
||||
LSnsrState2 = 0x00D5,
|
||||
|
||||
LSnsrAddr3 = 0x00D7,
|
||||
LAlertCMD3 = 0x00D8,
|
||||
LAlertDataMsk3 = 0x00D9,
|
||||
LAlertCmp3 = 0x00DA,
|
||||
LAlertESnsrT3 = 0x00DB,
|
||||
LAlertET3 = 0x00DC,
|
||||
LAlertEOffset3 = 0x00DD,
|
||||
LAlertES3 = 0x00DE,
|
||||
LAlertSN3 = 0x00DF,
|
||||
LAlertEntity3 = 0x00E0,
|
||||
LAlertEI3 = 0x00E1,
|
||||
LSnsrState3 = 0x00E2,
|
||||
|
||||
LSnsrAddr4 = 0x00E4,
|
||||
LAlertCMD4 = 0x00E5,
|
||||
LAlertDataMsk4 = 0x00E6,
|
||||
LAlertCmp4 = 0x00E7,
|
||||
LAlertESnsrT4 = 0x00E8,
|
||||
LAlertET4 = 0x00E9,
|
||||
LAlertEOffset4 = 0x00EA,
|
||||
LAlertES4 = 0x00EB,
|
||||
LAlertSN4 = 0x00EC,
|
||||
LAlertEntity4 = 0x00ED,
|
||||
LAlertEI4 = 0x00EE,
|
||||
LSnsrState4 = 0x00EF,
|
||||
|
||||
LSnsrAddr5 = 0x00F1,
|
||||
LAlertCMD5 = 0x00F2,
|
||||
LAlertDataMsk5 = 0x00F3,
|
||||
LAlertCmp5 = 0x00F4,
|
||||
LAlertESnsrT5 = 0x00F5,
|
||||
LAlertET5 = 0x00F6,
|
||||
LAlertEOffset5 = 0x00F7,
|
||||
LAlertES5 = 0x00F8,
|
||||
LAlertSN5 = 0x00F9,
|
||||
LAlertEntity5 = 0x00FA,
|
||||
LAlertEI5 = 0x00FB,
|
||||
LSnsrState5 = 0x00FC,
|
||||
|
||||
LSnsrAddr6 = 0x00FE,
|
||||
LAlertCMD6 = 0x00FF,
|
||||
LAlertDataMsk6 = 0x0100,
|
||||
LAlertCmp6 = 0x0101,
|
||||
LAlertESnsrT6 = 0x0102,
|
||||
LAlertET6 = 0x0103,
|
||||
LAlertEOffset6 = 0x0104,
|
||||
LAlertES6 = 0x0105,
|
||||
LAlertSN6 = 0x0106,
|
||||
LAlertEntity6 = 0x0107,
|
||||
LAlertEI6 = 0x0108,
|
||||
LSnsrState6 = 0x0109,
|
||||
|
||||
LSnsrAddr7 = 0x010B,
|
||||
LAlertCMD7 = 0x010C,
|
||||
LAlertDataMsk7 = 0x010D,
|
||||
LAlertCmp7 = 0x010E,
|
||||
LAlertESnsrT7 = 0x010F,
|
||||
LAlertET7 = 0x0110,
|
||||
LAlertEOffset7 = 0x0111,
|
||||
LAlertES7 = 0x0112,
|
||||
LAlertSN7 = 0x0113,
|
||||
LAlertEntity7 = 0x0114,
|
||||
LAlertEI7 = 0x0115,
|
||||
LSnsrState7 = 0x0116,
|
||||
LAssert = 0x0117,
|
||||
LDAssert = 0x0118,
|
||||
IPServiceType = 0x0119,
|
||||
IPIdfr = 0x011A,
|
||||
FlagFOffset = 0x011C,
|
||||
TTL = 0x011E,
|
||||
HbtEI = 0x011F,
|
||||
MgtConSID1 = 0x0120,
|
||||
MgtConSID2 = 0x0124,
|
||||
MgdCltSID = 0x0128,
|
||||
StCd = 0x012C,
|
||||
MgtConUR = 0x012D,
|
||||
MgtConUNL = 0x012E,
|
||||
|
||||
AuthPd = 0x0130,
|
||||
IntyPd = 0x0138,
|
||||
MgtConRN = 0x0140,
|
||||
MgdCtlRN = 0x0150,
|
||||
MgtConUN = 0x0160,
|
||||
Rakp2IntCk = 0x0170,
|
||||
KO = 0x017C,
|
||||
KA = 0x0190,
|
||||
KG = 0x01A4,
|
||||
KR = 0x01B8,
|
||||
CP = 0x01CC,
|
||||
CQ = 0x01D0,
|
||||
KC = 0x01D4,
|
||||
ConsoleSid = 0x01E8,
|
||||
|
||||
SIK1 = 0x01FC,
|
||||
SIK2 = 0x0210,
|
||||
Udpsrc_port = 0x0224,
|
||||
Udpdes_port = 0x0226,
|
||||
Asf_debug_mux = 0x0228
|
||||
};
|
||||
|
||||
enum asf_cmdln_opt {
|
||||
ASF_GET,
|
||||
ASF_SET,
|
||||
ASF_HELP
|
||||
};
|
||||
|
||||
struct asf_ioctl_struct {
|
||||
unsigned int arg;
|
||||
unsigned int offset;
|
||||
union {
|
||||
unsigned int data[MAX_DATA_LEN];
|
||||
char string[MAX_STR_LEN];
|
||||
} u;
|
||||
};
|
||||
|
||||
int rtl8168_asf_ioctl(struct net_device *dev, struct ifreq *ifr);
|
||||
void rtl8168_asf_hbperiod(struct rtl8168_private *tp, int arg, unsigned int *data);
|
||||
void rtl8168_asf_wd16rst(struct rtl8168_private *tp, int arg, unsigned int *data);
|
||||
void rtl8168_asf_console_mac(struct rtl8168_private *, int arg, unsigned int *data);
|
||||
void rtl8168_asf_ip_address(struct rtl8168_private *, int arg, int offset, unsigned int *data);
|
||||
void rtl8168_asf_config_regs(struct rtl8168_private *tp, int arg, int offset, unsigned int *data);
|
||||
void rtl8168_asf_capability_masks(struct rtl8168_private *tp, int arg, int offset, unsigned int *data);
|
||||
void rtl8168_asf_community_string(struct rtl8168_private *tp, int arg, char *string);
|
||||
void rtl8168_asf_community_string_len(struct rtl8168_private *tp, int arg, unsigned int *data);
|
||||
void rtl8168_asf_alert_resend_interval(struct rtl8168_private *tp, int arg, unsigned int *data);
|
||||
void rtl8168_asf_time_period(struct rtl8168_private *tp, int arg, int offset, unsigned int *data);
|
||||
void rtl8168_asf_key_access(struct rtl8168_private *, int arg, int offset, unsigned int *data);
|
||||
void rtl8168_asf_rw_hexadecimal(struct rtl8168_private *tp, int arg, int offset, int len, unsigned int *data);
|
||||
void rtl8168_asf_rw_iana(struct rtl8168_private *tp, int arg, unsigned int *data);
|
||||
void rtl8168_asf_rw_uuid(struct rtl8168_private *tp, int arg, unsigned int *data);
|
||||
void rtl8168_asf_rw_systemid(struct rtl8168_private *tp, int arg, unsigned int *data);
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_asf.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_asf.o
Normal file
Binary file not shown.
261
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_dash.h
Normal file
261
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_dash.h
Normal file
@ -0,0 +1,261 @@
|
||||
/* 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8168_DASH_H
|
||||
#define _LINUX_R8168_DASH_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 {
|
||||
__le16 length;
|
||||
__le16 status;
|
||||
__le32 resv;
|
||||
__le64 BufferAddress;
|
||||
}
|
||||
RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC;
|
||||
|
||||
typedef struct _TX_DASH_SEND_FW_DESC {
|
||||
__le16 length;
|
||||
__le16 status;
|
||||
__le32 resv;
|
||||
__le64 BufferAddress;
|
||||
}
|
||||
TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC;
|
||||
|
||||
typedef struct _OSOOBHdr {
|
||||
__le32 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_FIRMWARE_MAJOR_VERSION (0x120)
|
||||
|
||||
|
||||
#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 HW_DASH_SUPPORT_CMAC(_M) (HW_DASH_SUPPORT_TYPE_2(_M) || HW_DASH_SUPPORT_TYPE_3(_M))
|
||||
#define HW_DASH_SUPPORT_GET_FIRMWARE_VERSION(_M) (HW_DASH_SUPPORT_TYPE_2(_M) || \
|
||||
HW_DASH_SUPPORT_TYPE_3(_M))
|
||||
|
||||
#define RECV_FROM_FW_BUF_SIZE (2048)
|
||||
#define SEND_TO_FW_BUF_SIZE (2048)
|
||||
|
||||
#define RX_DASH_FROM_FW_OWN BIT_15
|
||||
#define TX_DASH_SEND_FW_OWN BIT_15
|
||||
|
||||
#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 rtl8168_dash_ioctl(struct net_device *dev, struct ifreq *ifr);
|
||||
bool CheckDashInterrupt(struct net_device *dev, u16 status);
|
||||
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_R8168_DASH_H */
|
||||
@ -0,0 +1,75 @@
|
||||
/* 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8168_FIBER_H
|
||||
#define _LINUX_R8168_FIBER_H
|
||||
|
||||
enum {
|
||||
FIBER_MODE_NIC_ONLY = 0,
|
||||
FIBER_MODE_RTL8168H_RTL8211FS,
|
||||
FIBER_MODE_RTL8168H_MDI_SWITCH_RTL8211FS,
|
||||
FIBER_MODE_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
FIBER_STAT_NOT_CHECKED = 0,
|
||||
FIBER_STAT_CONNECT_EEPROM,
|
||||
FIBER_STAT_DISCONNECT,
|
||||
FIBER_STAT_CONNECT_GPO,
|
||||
FIBER_STAT_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
FIBER_LED_MODE_DEFAULT = 0,
|
||||
FIBER_LED_MODE_1,
|
||||
FIBER_LED_MODE_MAX
|
||||
};
|
||||
|
||||
#define HW_FIBER_MODE_ENABLED(_M) ((_M)->HwFiberModeVer > 0)
|
||||
#define HW_FIBER_STATUS_CONNECTED(_M) (((_M)->HwFiberStat == FIBER_STAT_CONNECT_EEPROM) || ((_M)->HwFiberStat == FIBER_STAT_CONNECT_GPO))
|
||||
#define HW_FIBER_STATUS_DISCONNECTED(_M) ((_M)->HwFiberStat == FIBER_STAT_DISCONNECT)
|
||||
|
||||
struct rtl8168_private;
|
||||
|
||||
void rtl8168_hw_init_fiber_nic(struct rtl8168_private *tp);
|
||||
void rtl8168_hw_fiber_nic_d3_para(struct rtl8168_private *tp);
|
||||
void rtl8168_hw_fiber_phy_config(struct rtl8168_private *tp);
|
||||
void rtl8168_hw_switch_mdi_to_fiber(struct rtl8168_private *tp);
|
||||
void rtl8168_hw_switch_mdi_to_nic(struct rtl8168_private *tp);
|
||||
unsigned int rtl8168_hw_fiber_link_ok(struct rtl8168_private *tp);
|
||||
void rtl8168_check_fiber_link_status(struct rtl8168_private *tp);
|
||||
void rtl8168_check_hw_fiber_mode_support(struct rtl8168_private *tp);
|
||||
void rtl8168_set_fiber_mode_software_variable(struct rtl8168_private *tp);
|
||||
|
||||
#endif /* _LINUX_R8168_FIBER_H */
|
||||
@ -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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "r8168_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[RTL8168_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 rtl8168_fw_phy_action, code[0])
|
||||
|
||||
static bool rtl8168_fw_format_ok(struct rtl8168_fw *rtl_fw)
|
||||
{
|
||||
const struct firmware *fw = rtl_fw->fw;
|
||||
struct fw_info *fw_info = (struct fw_info *)fw->data;
|
||||
struct rtl8168_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, RTL8168_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, RTL8168_VER_SIZE);
|
||||
|
||||
pa->code = (__le32 *)fw->data;
|
||||
pa->size = fw->size / FW_OPCODE_SIZE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rtl8168_fw_data_ok(struct rtl8168_fw *rtl_fw)
|
||||
{
|
||||
struct rtl8168_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 rtl8168_fw_write_firmware(struct rtl8168_private *tp, struct rtl8168_fw *rtl_fw)
|
||||
{
|
||||
struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action;
|
||||
rtl8168_fw_write_t fw_write = rtl_fw->phy_write;
|
||||
rtl8168_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 rtl8168_fw_release_firmware(struct rtl8168_fw *rtl_fw)
|
||||
{
|
||||
release_firmware(rtl_fw->fw);
|
||||
}
|
||||
|
||||
int rtl8168_fw_request_firmware(struct rtl8168_fw *rtl_fw)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
if (!rtl8168_fw_format_ok(rtl_fw) || !rtl8168_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;
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
################################################################################
|
||||
#
|
||||
# r8168 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
|
||||
# controllers with PCI-Express interface.
|
||||
#
|
||||
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_RTL8168_FIRMWARE_H
|
||||
#define _LINUX_RTL8168_FIRMWARE_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
struct rtl8168_private;
|
||||
typedef void (*rtl8168_fw_write_t)(struct rtl8168_private *tp, u16 reg, u16 val);
|
||||
typedef u32 (*rtl8168_fw_read_t)(struct rtl8168_private *tp, u16 reg);
|
||||
|
||||
#define RTL8168_VER_SIZE 32
|
||||
|
||||
struct rtl8168_fw {
|
||||
rtl8168_fw_write_t phy_write;
|
||||
rtl8168_fw_read_t phy_read;
|
||||
rtl8168_fw_write_t mac_mcu_write;
|
||||
rtl8168_fw_read_t mac_mcu_read;
|
||||
const struct firmware *fw;
|
||||
const char *fw_name;
|
||||
struct device *dev;
|
||||
|
||||
char version[RTL8168_VER_SIZE];
|
||||
|
||||
struct rtl8168_fw_phy_action {
|
||||
__le32 *code;
|
||||
size_t size;
|
||||
} phy_action;
|
||||
};
|
||||
|
||||
int rtl8168_fw_request_firmware(struct rtl8168_fw *rtl_fw);
|
||||
void rtl8168_fw_release_firmware(struct rtl8168_fw *rtl_fw);
|
||||
void rtl8168_fw_write_firmware(struct rtl8168_private *tp, struct rtl8168_fw *rtl_fw);
|
||||
|
||||
#endif /* _LINUX_RTL8168_FIRMWARE_H */
|
||||
32523
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_n.c
Normal file
32523
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_n.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_n.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_n.o
Normal file
Binary file not shown.
@ -0,0 +1,118 @@
|
||||
/* 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_R8168_REALWOW_H
|
||||
#define _LINUX_R8168_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 rtl8168_realwow_ioctl(struct net_device *dev, struct ifreq *ifr);
|
||||
void rtl8168_realwow_hw_init(struct net_device *dev);
|
||||
void rtl8168_get_realwow_hw_version(struct net_device *dev);
|
||||
void rtl8168_set_realwow_d3_para(struct net_device *dev);
|
||||
|
||||
#endif /* _LINUX_R8168_REALWOW_H */
|
||||
482
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_rss.c
Normal file
482
KernelPackages/drivers/net/ethernet/realtek/r8168/r8168_rss.c
Normal file
@ -0,0 +1,482 @@
|
||||
// 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "r8168.h"
|
||||
|
||||
enum rtl8168_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_CTRL_IPV6_EXT_SUPP = (1 << 4),
|
||||
RSS_CTRL_TCP_IPV6_EXT_SUPP = (1 << 5),
|
||||
RSS_HALF_SUPP = (1 << 7),
|
||||
RSS_QUAD_CPU_EN = (1 << 16),
|
||||
RSS_HQ_Q_SUP_R = (1 << 31),
|
||||
};
|
||||
|
||||
static int rtl8168_get_rss_hash_opts(struct rtl8168_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 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 IPV6_FLOW:
|
||||
cmd->data |= RXH_IP_SRC | RXH_IP_DST;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8168_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
||||
u32 *rule_locs)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return ret;
|
||||
|
||||
switch (cmd->cmd) {
|
||||
case ETHTOOL_GRXRINGS:
|
||||
cmd->data = rtl8168_tot_rx_rings(tp);
|
||||
ret = 0;
|
||||
break;
|
||||
case ETHTOOL_GRXFH:
|
||||
ret = rtl8168_get_rss_hash_opts(tp, cmd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 rtl8168_rss_indir_tbl_entries(struct rtl8168_private *tp)
|
||||
{
|
||||
return tp->HwSuppIndirTblEntries;
|
||||
}
|
||||
|
||||
#define RSS_MASK_BITS_OFFSET (8)
|
||||
static int _rtl8168_set_rss_hash_opt(struct rtl8168_private *tp)
|
||||
{
|
||||
u32 hash_mask_len;
|
||||
u32 rss_ctrl;
|
||||
|
||||
/* Perform hash on these packet types */
|
||||
rss_ctrl = RSS_CTRL_TCP_IPV4_SUPP
|
||||
| RSS_CTRL_IPV4_SUPP
|
||||
| RSS_CTRL_IPV6_SUPP
|
||||
| RSS_CTRL_IPV6_EXT_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_EXT_SUPP;
|
||||
|
||||
if (R8168_MULTI_RSS_4Q(tp))
|
||||
rss_ctrl |= RSS_QUAD_CPU_EN;
|
||||
|
||||
hash_mask_len = ilog2(rtl8168_rss_indir_tbl_entries(tp));
|
||||
hash_mask_len &= (BIT_0 | BIT_1 | BIT_2);
|
||||
rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET;
|
||||
|
||||
rtl8168_eri_write(tp, RSS_CTRL_8168, 4, rss_ctrl, ERIAR_ExGMAC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8168_set_rss_hash_opt(struct rtl8168_private *tp,
|
||||
struct ethtool_rxnfc *nfc)
|
||||
{
|
||||
u32 rss_flags = tp->rss_flags;
|
||||
|
||||
/*
|
||||
* 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 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;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* if we changed something we need to update flags */
|
||||
if (rss_flags != tp->rss_flags) {
|
||||
u32 rss_ctrl = rtl8168_eri_read(tp, RSS_CTRL_8168, 4, ERIAR_ExGMAC);
|
||||
|
||||
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_IPV6_EXT_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_SUPP
|
||||
| RSS_CTRL_TCP_IPV6_EXT_SUPP;
|
||||
|
||||
if (R8168_MULTI_RSS_4Q(tp))
|
||||
rss_ctrl |= RSS_QUAD_CPU_EN;
|
||||
else
|
||||
rss_ctrl &= ~RSS_QUAD_CPU_EN;
|
||||
|
||||
rtl8168_eri_write(tp, RSS_CTRL_8168, 4, rss_ctrl, ERIAR_ExGMAC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8168_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return ret;
|
||||
|
||||
switch (cmd->cmd) {
|
||||
case ETHTOOL_SRXFH:
|
||||
ret = rtl8168_set_rss_hash_opt(tp, cmd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 _rtl8168_get_rxfh_key_size(struct rtl8168_private *tp)
|
||||
{
|
||||
return sizeof(tp->rss_key);
|
||||
}
|
||||
|
||||
u32 rtl8168_get_rxfh_key_size(struct net_device *dev)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return 0;
|
||||
|
||||
return _rtl8168_get_rxfh_key_size(tp);
|
||||
}
|
||||
|
||||
u32 rtl8168_rss_indir_size(struct net_device *dev)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return 0;
|
||||
|
||||
return rtl8168_rss_indir_tbl_entries(tp);
|
||||
}
|
||||
|
||||
static void rtl8168_get_reta(struct rtl8168_private *tp, u32 *indir)
|
||||
{
|
||||
int i, reta_size = rtl8168_rss_indir_tbl_entries(tp);
|
||||
|
||||
for (i = 0; i < reta_size; i++)
|
||||
indir[i] = tp->rss_indir_tbl[i];
|
||||
}
|
||||
|
||||
static u32 rtl8168_rss_key_reg(struct rtl8168_private *tp)
|
||||
{
|
||||
return RSS_KEY_8168;
|
||||
}
|
||||
|
||||
static u32 rtl8168_rss_indir_tbl_reg(struct rtl8168_private *tp)
|
||||
{
|
||||
return Rss_indir_tbl;
|
||||
}
|
||||
|
||||
static void rtl8168_store_reta(struct rtl8168_private *tp)
|
||||
{
|
||||
u32 reta_entries = rtl8168_rss_indir_tbl_entries(tp);
|
||||
u16 indir_tbl_reg = rtl8168_rss_indir_tbl_reg(tp);
|
||||
u32 hw_indir[RTL8168_RSS_INDIR_TBL_SIZE] = {0};
|
||||
u8 *indir = tp->rss_indir_tbl;
|
||||
u32 bit_on_cnt = 0x00000001;
|
||||
u32 i, j;
|
||||
|
||||
/* Mapping redirection table to HW */
|
||||
for (i = 0, j = 0; i < reta_entries; i++) {
|
||||
if ((indir[i] & 2) && R8168_MULTI_RSS_4Q(tp))
|
||||
hw_indir[j + 4] |= bit_on_cnt;
|
||||
if (indir[i] & 1)
|
||||
hw_indir[j] |= bit_on_cnt;
|
||||
|
||||
if (bit_on_cnt == 0x80000000) {
|
||||
bit_on_cnt = 0x00000001;
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
bit_on_cnt <<= 1;
|
||||
}
|
||||
|
||||
/* Write redirection table to HW */
|
||||
for (i = 0; i < RTL8168_RSS_INDIR_TBL_SIZE; i++)
|
||||
RTL_W32(tp, indir_tbl_reg + i*4, hw_indir[i]);
|
||||
}
|
||||
|
||||
static void rtl8168_store_rss_key(struct rtl8168_private *tp)
|
||||
{
|
||||
const u16 rss_key_reg = rtl8168_rss_key_reg(tp);
|
||||
u32 i, rss_key_size = _rtl8168_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)
|
||||
rtl8168_eri_write(tp, rss_key_reg + i, 4, *rss_key++, ERIAR_ExGMAC);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
|
||||
int rtl8168_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rxfh->hfunc = ETH_RSS_HASH_TOP;
|
||||
|
||||
if (rxfh->indir)
|
||||
rtl8168_get_reta(tp, rxfh->indir);
|
||||
|
||||
if (rxfh->key)
|
||||
memcpy(rxfh->key, tp->rss_key, RTL8168_RSS_KEY_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8168_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
u32 reta_entries = rtl8168_rss_indir_tbl_entries(tp);
|
||||
int i;
|
||||
|
||||
/* We require at least one supported parameter to be changed and no
|
||||
* change in any of the unsupported parameters
|
||||
*/
|
||||
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && rxfh->hfunc != ETH_RSS_HASH_TOP)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Fill out the redirection table */
|
||||
if (rxfh->indir) {
|
||||
int max_queues = tp->num_rx_rings;
|
||||
|
||||
/* Verify user input. */
|
||||
for (i = 0; i < reta_entries; i++)
|
||||
if (rxfh->indir[i] >= max_queues)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < reta_entries; i++)
|
||||
tp->rss_indir_tbl[i] = rxfh->indir[i];
|
||||
}
|
||||
|
||||
/* Fill out the rss hash key */
|
||||
if (rxfh->key)
|
||||
memcpy(tp->rss_key, rxfh->key, RTL8168_RSS_KEY_SIZE);
|
||||
|
||||
rtl8168_store_reta(tp);
|
||||
|
||||
rtl8168_store_rss_key(tp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int rtl8168_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
|
||||
u8 *hfunc)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!(dev->features & NETIF_F_RXHASH))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (hfunc)
|
||||
*hfunc = ETH_RSS_HASH_TOP;
|
||||
|
||||
if (indir)
|
||||
rtl8168_get_reta(tp, indir);
|
||||
|
||||
if (key)
|
||||
memcpy(key, tp->rss_key, RTL8168_RSS_KEY_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8168_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
{
|
||||
struct rtl8168_private *tp = netdev_priv(dev);
|
||||
u32 reta_entries = rtl8168_rss_indir_tbl_entries(tp);
|
||||
int i;
|
||||
|
||||
/* 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, RTL8168_RSS_KEY_SIZE);
|
||||
|
||||
rtl8168_store_reta(tp);
|
||||
|
||||
rtl8168_store_rss_key(tp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
|
||||
|
||||
static u32 rtl8168_get_rx_desc_hash(struct rtl8168_private *tp,
|
||||
struct RxDescV2 *desc)
|
||||
{
|
||||
if (!desc->RSSResult)
|
||||
fsleep(1);
|
||||
return le32_to_cpu(desc->RSSResult);
|
||||
}
|
||||
|
||||
#define RXS_8168_RSS_IPV4 BIT(17)
|
||||
#define RXS_8168_RSS_IPV6 BIT(18)
|
||||
#define RXS_8168_RSS_TCP BIT(19)
|
||||
#define RTL8168_RXS_RSS_L3_TYPE_MASK (RXS_8168_RSS_IPV4 | RXS_8168_RSS_IPV6)
|
||||
#define RTL8168_RXS_RSS_L4_TYPE_MASK (RXS_8168_RSS_TCP)
|
||||
void rtl8168_rx_hash(struct rtl8168_private *tp,
|
||||
struct RxDescV2 *desc,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u32 rss_header_info;
|
||||
|
||||
if (!(tp->dev->features & NETIF_F_RXHASH))
|
||||
return;
|
||||
|
||||
rss_header_info = le32_to_cpu(desc->opts2);
|
||||
|
||||
if (!(rss_header_info & RTL8168_RXS_RSS_L3_TYPE_MASK))
|
||||
return;
|
||||
|
||||
skb_set_hash(skb, rtl8168_get_rx_desc_hash(tp, desc),
|
||||
(RTL8168_RXS_RSS_L4_TYPE_MASK & rss_header_info) ?
|
||||
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
|
||||
}
|
||||
|
||||
void rtl8168_disable_rss(struct rtl8168_private *tp)
|
||||
{
|
||||
rtl8168_eri_write(tp, RSS_CTRL_8168, 4, 0x00000000, ERIAR_ExGMAC);
|
||||
}
|
||||
|
||||
void _rtl8168_config_rss(struct rtl8168_private *tp)
|
||||
{
|
||||
_rtl8168_set_rss_hash_opt(tp);
|
||||
|
||||
rtl8168_store_reta(tp);
|
||||
|
||||
rtl8168_store_rss_key(tp);
|
||||
}
|
||||
|
||||
void rtl8168_config_rss(struct rtl8168_private *tp)
|
||||
{
|
||||
if (!HW_RSS_SUPPORT_RSS(tp))
|
||||
return;
|
||||
|
||||
if (!tp->EnableRss) {
|
||||
rtl8168_disable_rss(tp);
|
||||
return;
|
||||
}
|
||||
|
||||
_rtl8168_config_rss(tp);
|
||||
}
|
||||
|
||||
void rtl8168_init_rss(struct rtl8168_private *tp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rtl8168_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, RTL8168_RSS_KEY_SIZE);
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
/* 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_RTL8168_RSS_H
|
||||
#define _LINUX_RTL8168_RSS_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define RTL8168_RSS_INDIR_TBL_SIZE 8
|
||||
#define RTL8168_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */
|
||||
#define RTL8168_MAX_INDIRECTION_TABLE_ENTRIES 128
|
||||
|
||||
struct rtl8168_private;
|
||||
struct RxDescV2;
|
||||
|
||||
int rtl8168_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
||||
u32 *rule_locs);
|
||||
int rtl8168_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd);
|
||||
u32 rtl8168_get_rxfh_key_size(struct net_device *netdev);
|
||||
u32 rtl8168_rss_indir_size(struct net_device *netdev);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
|
||||
int rtl8168_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh);
|
||||
int rtl8168_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack);
|
||||
#else
|
||||
int rtl8168_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
|
||||
u8 *hfunc);
|
||||
int rtl8168_set_rxfh(struct net_device *netdev, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc);
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
|
||||
void rtl8168_rx_hash(struct rtl8168_private *tp,
|
||||
struct RxDescV2 *desc,
|
||||
struct sk_buff *skb);
|
||||
void _rtl8168_config_rss(struct rtl8168_private *tp);
|
||||
void rtl8168_config_rss(struct rtl8168_private *tp);
|
||||
void rtl8168_init_rss(struct rtl8168_private *tp);
|
||||
u32 rtl8168_rss_indir_tbl_entries(struct rtl8168_private *tp);
|
||||
void rtl8168_disable_rss(struct rtl8168_private *tp);
|
||||
|
||||
#endif /* _LINUX_RTL8168_RSS_H */
|
||||
286
KernelPackages/drivers/net/ethernet/realtek/r8168/rtl_eeprom.c
Normal file
286
KernelPackages/drivers/net/ethernet/realtek/r8168/rtl_eeprom.c
Normal file
@ -0,0 +1,286 @@
|
||||
// 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#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 "r8168.h"
|
||||
#include "rtl_eeprom.h"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//rtl8168_eeprom_type():
|
||||
// tell the eeprom type
|
||||
//return value:
|
||||
// 0: the eeprom type is 93C46
|
||||
// 1: the eeprom type is 93C56 or 93C66
|
||||
//-------------------------------------------------------------------
|
||||
void rtl8168_eeprom_type(struct rtl8168_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 = rtl8168_eeprom_read_sc(tp, 0);
|
||||
|
||||
out_no_eeprom:
|
||||
if ((magic != 0x8129) && (magic != 0x8128)) {
|
||||
tp->eeprom_type = EEPROM_TYPE_NONE;
|
||||
tp->eeprom_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8168_eeprom_cleanup(struct rtl8168_private *tp)
|
||||
{
|
||||
u8 x;
|
||||
|
||||
x = RTL_R8(tp, Cfg9346);
|
||||
x &= ~(Cfg9346_EEDI | Cfg9346_EECS);
|
||||
|
||||
RTL_W8(tp, Cfg9346, x);
|
||||
|
||||
rtl8168_raise_clock(tp, &x);
|
||||
rtl8168_lower_clock(tp, &x);
|
||||
}
|
||||
|
||||
static int rtl8168_eeprom_cmd_done(struct rtl8168_private *tp)
|
||||
{
|
||||
u8 x;
|
||||
int i;
|
||||
|
||||
rtl8168_stand_by(tp);
|
||||
|
||||
for (i = 0; i < 50000; i++) {
|
||||
x = RTL_R8(tp, Cfg9346);
|
||||
|
||||
if (x & Cfg9346_EEDO) {
|
||||
fsleep(RTL_CLOCK_RATE * 2 * 3);
|
||||
return 0;
|
||||
}
|
||||
fsleep(1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//rtl8168_eeprom_read_sc():
|
||||
// read one word from eeprom
|
||||
//-------------------------------------------------------------------
|
||||
u16 rtl8168_eeprom_read_sc(struct rtl8168_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);
|
||||
|
||||
rtl8168_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3);
|
||||
rtl8168_shift_out_bits(tp, reg, addr_sz);
|
||||
|
||||
data = rtl8168_shift_in_bits(tp);
|
||||
|
||||
rtl8168_eeprom_cleanup(tp);
|
||||
|
||||
RTL_W8(tp, Cfg9346, 0);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//rtl8168_eeprom_write_sc():
|
||||
// write one word to a specific address in the eeprom
|
||||
//-------------------------------------------------------------------
|
||||
void rtl8168_eeprom_write_sc(struct rtl8168_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);
|
||||
|
||||
rtl8168_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5);
|
||||
rtl8168_shift_out_bits(tp, reg, w_dummy_addr);
|
||||
rtl8168_stand_by(tp);
|
||||
|
||||
rtl8168_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3);
|
||||
rtl8168_shift_out_bits(tp, reg, addr_sz);
|
||||
if (rtl8168_eeprom_cmd_done(tp) < 0)
|
||||
return;
|
||||
rtl8168_stand_by(tp);
|
||||
|
||||
rtl8168_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3);
|
||||
rtl8168_shift_out_bits(tp, reg, addr_sz);
|
||||
rtl8168_shift_out_bits(tp, data, 16);
|
||||
if (rtl8168_eeprom_cmd_done(tp) < 0)
|
||||
return;
|
||||
rtl8168_stand_by(tp);
|
||||
|
||||
rtl8168_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5);
|
||||
rtl8168_shift_out_bits(tp, reg, w_dummy_addr);
|
||||
|
||||
rtl8168_eeprom_cleanup(tp);
|
||||
RTL_W8(tp, Cfg9346, 0);
|
||||
}
|
||||
|
||||
void rtl8168_raise_clock(struct rtl8168_private *tp, u8 *x)
|
||||
{
|
||||
*x = *x | Cfg9346_EESK;
|
||||
RTL_W8(tp, Cfg9346, *x);
|
||||
fsleep(RTL_CLOCK_RATE);
|
||||
}
|
||||
|
||||
void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x)
|
||||
{
|
||||
|
||||
*x = *x & ~Cfg9346_EESK;
|
||||
RTL_W8(tp, Cfg9346, *x);
|
||||
fsleep(RTL_CLOCK_RATE);
|
||||
}
|
||||
|
||||
void rtl8168_shift_out_bits(struct rtl8168_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);
|
||||
fsleep(RTL_CLOCK_RATE);
|
||||
rtl8168_raise_clock(tp, &x);
|
||||
rtl8168_lower_clock(tp, &x);
|
||||
mask = mask >> 1;
|
||||
} while(mask);
|
||||
|
||||
x &= ~Cfg9346_EEDI;
|
||||
RTL_W8(tp, Cfg9346, x);
|
||||
}
|
||||
|
||||
u16 rtl8168_shift_in_bits(struct rtl8168_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;
|
||||
rtl8168_raise_clock(tp, &x);
|
||||
|
||||
x = RTL_R8(tp, Cfg9346);
|
||||
x &= ~Cfg9346_EEDI;
|
||||
|
||||
if (x & Cfg9346_EEDO)
|
||||
d |= 1;
|
||||
|
||||
rtl8168_lower_clock(tp, &x);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void rtl8168_stand_by(struct rtl8168_private *tp)
|
||||
{
|
||||
u8 x;
|
||||
|
||||
x = RTL_R8(tp, Cfg9346);
|
||||
x &= ~(Cfg9346_EECS | Cfg9346_EESK);
|
||||
RTL_W8(tp, Cfg9346, x);
|
||||
fsleep(RTL_CLOCK_RATE);
|
||||
|
||||
x |= Cfg9346_EECS;
|
||||
RTL_W8(tp, Cfg9346, x);
|
||||
}
|
||||
|
||||
void rtl8168_set_eeprom_sel_low(struct rtl8168_private *tp)
|
||||
{
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK);
|
||||
|
||||
fsleep(20);
|
||||
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
/* 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
//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 rtl8168_eeprom_type(struct rtl8168_private *tp);
|
||||
void rtl8168_eeprom_cleanup(struct rtl8168_private *tp);
|
||||
u16 rtl8168_eeprom_read_sc(struct rtl8168_private *tp, u16 reg);
|
||||
void rtl8168_eeprom_write_sc(struct rtl8168_private *tp, u16 reg, u16 data);
|
||||
void rtl8168_shift_out_bits(struct rtl8168_private *tp, int data, int count);
|
||||
u16 rtl8168_shift_in_bits(struct rtl8168_private *tp);
|
||||
void rtl8168_raise_clock(struct rtl8168_private *tp, u8 *x);
|
||||
void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x);
|
||||
void rtl8168_stand_by(struct rtl8168_private *tp);
|
||||
void rtl8168_set_eeprom_sel_low(struct rtl8168_private *tp);
|
||||
|
||||
|
||||
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8168/rtl_eeprom.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8168/rtl_eeprom.o
Normal file
Binary file not shown.
242
KernelPackages/drivers/net/ethernet/realtek/r8168/rtltool.c
Normal file
242
KernelPackages/drivers/net/ethernet/realtek/r8168/rtltool.c
Normal file
@ -0,0 +1,242 @@
|
||||
// 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#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 "r8168.h"
|
||||
#include "rtl_eeprom.h"
|
||||
#include "rtltool.h"
|
||||
|
||||
int rtl8168_tool_ioctl(struct rtl8168_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 ((my_cmd.offset + my_cmd.len) > R8168_REGS_SIZE) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
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 ((my_cmd.offset + my_cmd.len) > R8168_REGS_SIZE) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
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:
|
||||
my_cmd.data = rtl8168_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:
|
||||
rtl8168_mdio_prot_write(tp, my_cmd.offset, my_cmd.data);
|
||||
break;
|
||||
case RTLTOOL_READ_EPHY:
|
||||
my_cmd.data = rtl8168_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:
|
||||
rtl8168_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 = rtl8168_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 (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) {
|
||||
rtl8168_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC);
|
||||
} else {
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RTLTOOL_READ_PCI:
|
||||
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 (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:
|
||||
my_cmd.data = rtl8168_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:
|
||||
rtl8168_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data);
|
||||
break;
|
||||
case RTL_READ_OOB_MAC:
|
||||
rtl8168_oob_mutex_lock(tp);
|
||||
my_cmd.data = rtl8168_ocp_read(tp, my_cmd.offset, 4);
|
||||
rtl8168_oob_mutex_unlock(tp);
|
||||
|
||||
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RTL_WRITE_OOB_MAC:
|
||||
if (my_cmd.len == 0 || my_cmd.len > 4)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rtl8168_oob_mutex_lock(tp);
|
||||
rtl8168_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data);
|
||||
rtl8168_oob_mutex_unlock(tp);
|
||||
break;
|
||||
case RTL_ENABLE_PCI_DIAG:
|
||||
tp->rtk_enable_diag = 1;
|
||||
dprintk("enable rtk diag\n");
|
||||
break;
|
||||
case RTL_DISABLE_PCI_DIAG:
|
||||
tp->rtk_enable_diag = 0;
|
||||
dprintk("disable rtk diag\n");
|
||||
break;
|
||||
case RTL_READ_MAC_OCP:
|
||||
if (my_cmd.offset % 2)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
my_cmd.data = rtl8168_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 ((my_cmd.offset % 2) || (my_cmd.len != 2))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rtl8168_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data);
|
||||
break;
|
||||
case RTL_DIRECT_READ_PHY_OCP:
|
||||
my_cmd.data = rtl8168_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:
|
||||
rtl8168_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data);
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
86
KernelPackages/drivers/net/ethernet/realtek/r8168/rtltool.h
Normal file
86
KernelPackages/drivers/net/ethernet/realtek/r8168/rtltool.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* 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) 2024 Realtek Semiconductor Corp. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author:
|
||||
# Realtek NIC software team <nicfae@realtek.com>
|
||||
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
#
|
||||
################################################################################
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* This product is covered by one or more of the following patents:
|
||||
* US6,570,884, US6,115,776, and US6,327,625.
|
||||
***********************************************************************************/
|
||||
|
||||
#ifndef _LINUX_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 rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr);
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_RTLTOOL_H */
|
||||
BIN
KernelPackages/drivers/net/ethernet/realtek/r8168/rtltool.o
Normal file
BIN
KernelPackages/drivers/net/ethernet/realtek/r8168/rtltool.o
Normal file
Binary file not shown.
132
build.sh
132
build.sh
@ -2,12 +2,14 @@
|
||||
|
||||
source ./dependencies.sh
|
||||
|
||||
[[ -z $KERNEL_VERSION ]] && KERNEL_VERSION='6.6.69'
|
||||
[[ -z $BUILDROOT_VERSION ]] && BUILDROOT_VERSION='2024.02.9'
|
||||
[[ -z $KERNEL_VERSION ]] && KERNEL_VERSION='6.12.35'
|
||||
[[ -z $BUILDROOT_VERSION ]] && BUILDROOT_VERSION='2025.02.4'
|
||||
|
||||
declare -ar ARCHITECTURES=("x64" "x86" "arm64")
|
||||
PIPE_JOINED_ARCHITECTURES=$(IFS="|"; echo "${ARCHITECTURES[@]}"; unset IFS)
|
||||
|
||||
PROJECT_DIRECTORY="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
Usage() {
|
||||
echo -e "Usage: $0 [-knfvh?] [-a x64]"
|
||||
echo -e "\t\t-a --arch [$PIPE_JOINED_ARCHITECTURES] (optional) pick the architecture to build. Default is to build for all."
|
||||
@ -19,12 +21,12 @@ Usage() {
|
||||
echo -e "\t\t-h --help -? Display this message."
|
||||
exit 0
|
||||
}
|
||||
[[ -n $arch ]] && unset $arch
|
||||
[[ -n "$arch" ]] && unset "$arch"
|
||||
|
||||
shortopts="?hkfnia:p:"
|
||||
longopts="help,kernel-only,filesystem-only,noconfirm,install-dep,arch:,path:"
|
||||
|
||||
optargs=$(getopt -o $shortopts -l $longopts -n "$0" -- "$@")
|
||||
optargs=$(getopt -o "$shortopts" -l "$longopts" -n "$0" -- "$@")
|
||||
[[ $? -ne 0 ]] && Usage
|
||||
|
||||
eval set -- "$optargs"
|
||||
@ -33,7 +35,6 @@ while :; do
|
||||
case $1 in
|
||||
-\? | -h | --help)
|
||||
Usage
|
||||
exit 0
|
||||
;;
|
||||
-k | --kernel-only)
|
||||
buildKernelOnly="y"
|
||||
@ -53,10 +54,9 @@ while :; do
|
||||
;;
|
||||
-a | --arch)
|
||||
arch=$2
|
||||
if ! echo ${ARCHITECTURES[@]} | grep -w $arch >/dev/null; then
|
||||
if ! echo "${ARCHITECTURES[@]}" | grep -w "$arch" >/dev/null; then
|
||||
echo "Error: Invalid architecture specified. Valid options are: $PIPE_JOINED_ARCHITECTURES"
|
||||
Usage
|
||||
exit 1
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
@ -71,21 +71,20 @@ while :; do
|
||||
*)
|
||||
echo "Error: Invalid option."
|
||||
Usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
[[ -z $arch ]] && arch="${ARCHITECTURES[@]}"
|
||||
[[ -z $buildPath ]] && buildPath=$(dirname $(readlink -f $0))
|
||||
[[ -z $arch ]] && arch="${ARCHITECTURES[*]}"
|
||||
[[ -z $buildPath ]] && buildPath="$(dirname "$(readlink -f "$0")")"
|
||||
[[ -z $confirm ]] && confirm="y"
|
||||
[[ -z $installDep ]] && installDep="n"
|
||||
|
||||
checkDependencies
|
||||
installDependencies $installDep
|
||||
installDependencies "$installDep"
|
||||
|
||||
cd $buildPath || exit 1
|
||||
cd "$buildPath" || exit 1
|
||||
|
||||
|
||||
function buildFilesystem() {
|
||||
@ -95,18 +94,18 @@ function buildFilesystem() {
|
||||
if [[ ! -d fssource$arch ]]; then
|
||||
if [[ ! -f buildroot-$BUILDROOT_VERSION.tar.xz ]]; then
|
||||
dots "Downloading buildroot source package"
|
||||
wget -q $brURL && echo "Done"
|
||||
wget -q "$brURL" && echo "Done"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
dots "Extracting buildroot sources"
|
||||
tar xJf buildroot-$BUILDROOT_VERSION.tar.xz
|
||||
mv buildroot-$BUILDROOT_VERSION fssource$arch
|
||||
tar xJf "buildroot-$BUILDROOT_VERSION.tar.xz"
|
||||
mv "buildroot-$BUILDROOT_VERSION" "fssource$arch"
|
||||
echo "Done"
|
||||
fi
|
||||
cd fssource$arch
|
||||
cd "fssource$arch" || { echo "Couldn't change directory to fssource$arch"; exit 1; }
|
||||
if [[ -f ../patch/filesystem/fs.patch ]]; then
|
||||
dots " * Applying filesystem patch"
|
||||
echo
|
||||
@ -127,7 +126,7 @@ function buildFilesystem() {
|
||||
rsync -avPrI ../Buildroot/ . > /dev/null
|
||||
sed -i "s/^export initversion=[0-9][0-9]*$/export initversion=$(date +%Y%m%d)/" board/FOG/FOS/rootfs_overlay/usr/share/fog/lib/funcs.sh
|
||||
if [[ ! -f .config ]]; then
|
||||
cp ../configs/fs$arch.config .config
|
||||
cp "../configs/fs$arch.config" .config
|
||||
case "${arch}" in
|
||||
x64)
|
||||
make oldconfig
|
||||
@ -145,7 +144,7 @@ function buildFilesystem() {
|
||||
fi
|
||||
echo "Done"
|
||||
if [[ $confirm != n ]]; then
|
||||
read -p "We are ready to build. Would you like to edit the config file [y|n]?" config
|
||||
read -rp "We are ready to build. Would you like to edit the config file [y|n]?" config
|
||||
if [[ $config == y ]]; then
|
||||
case "${arch}" in
|
||||
x64)
|
||||
@ -178,7 +177,7 @@ function buildFilesystem() {
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
read -p "We are ready to build are you [y|n]?" ready
|
||||
read -rp "We are ready to build are you [y|n]?" ready
|
||||
if [[ $ready == n ]]; then
|
||||
echo "Nothing to build!? Skipping."
|
||||
cd ..
|
||||
@ -189,27 +188,27 @@ function buildFilesystem() {
|
||||
PING_LOOP_PID=$!
|
||||
case "${arch}" in
|
||||
x64)
|
||||
make >buildroot$arch.log 2>&1
|
||||
make > "buildroot$arch.log" 2>&1
|
||||
status=$?
|
||||
;;
|
||||
x86)
|
||||
make ARCH=i486 >buildroot$arch.log 2>&1
|
||||
make ARCH=i486 > "buildroot$arch.log" 2>&1
|
||||
status=$?
|
||||
;;
|
||||
arm64)
|
||||
make ARCH=aarch64 CROSS_COMPILE=aarch64-linux-gnu- >buildroot$arch.log 2>&1
|
||||
make ARCH=aarch64 CROSS_COMPILE=aarch64-linux-gnu- > "buildroot$arch.log" 2>&1
|
||||
status=$?
|
||||
;;
|
||||
*)
|
||||
make >buildroot$arch.log 2>&1
|
||||
make > "buildroot$arch.log" 2>&1
|
||||
status=$?
|
||||
;;
|
||||
esac
|
||||
kill $PING_LOOP_PID
|
||||
[[ $status -gt 0 ]] && tail buildroot$arch.log && exit $status
|
||||
[[ $status -gt 0 ]] && tail "buildroot$arch.log" && exit $status
|
||||
cd ..
|
||||
[[ ! -d dist ]] && mkdir dist
|
||||
cd dist
|
||||
cd dist || { echo "Couldn't change directory to dist"; exit 1; }
|
||||
case "${arch}" in
|
||||
x64)
|
||||
compiledfile="../fssource$arch/output/images/rootfs.ext2.xz"
|
||||
@ -224,7 +223,7 @@ function buildFilesystem() {
|
||||
initfile='arm_init.cpio.gz'
|
||||
;;
|
||||
esac
|
||||
[[ ! -f $compiledfile ]] && echo 'File not found.' || cp $compiledfile $initfile && sha256sum $initfile > ${initfile}.sha256
|
||||
[[ ! -f $compiledfile ]] && echo 'File not found.' || cp "$compiledfile" "$initfile" && sha256sum "$initfile" > "${initfile}.sha256"
|
||||
cd ..
|
||||
}
|
||||
|
||||
@ -232,52 +231,57 @@ function buildKernel() {
|
||||
local arch="$1"
|
||||
kernelURL="https://www.kernel.org/pub/linux/kernel/v${KERNEL_VERSION:0:1}.x/linux-$KERNEL_VERSION.tar.xz"
|
||||
echo "Preparing kernel $KERNEL_VERSION on $arch build:"
|
||||
[[ -d kernelsource$arch ]] && rm -rf kernelsource$arch
|
||||
[[ -d kernelsource$arch ]] && rm -rf "kernelsource$arch"
|
||||
if [[ ! -f linux-$KERNEL_VERSION.tar.xz ]]; then
|
||||
dots "Downloading kernel source"
|
||||
wget -q $kernelURL && echo "Done"
|
||||
wget -q "$kernelURL" && echo "Done"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
dots "Extracting kernel source"
|
||||
tar xJf linux-$KERNEL_VERSION.tar.xz
|
||||
mv linux-$KERNEL_VERSION kernelsource$arch
|
||||
tar xJf "linux-$KERNEL_VERSION.tar.xz"
|
||||
mv "linux-$KERNEL_VERSION" "kernelsource$arch"
|
||||
echo "Done"
|
||||
|
||||
dots "Adding kernel packages"
|
||||
addKernelPackages
|
||||
echo "Done"
|
||||
|
||||
if [[ ! -d linux-firmware ]]; then
|
||||
dots "Cloning Linux firmware repository"
|
||||
git clone git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git >/dev/null 2>&1
|
||||
echo "Done"
|
||||
else
|
||||
dots "Updating Linux firmware repository"
|
||||
cd linux-firmware
|
||||
cd linux-firmware || { echo "Couldn't change directory to linux-firmware"; exit 1; }
|
||||
git pull --rebase >/dev/null 2>&1
|
||||
cd ..
|
||||
echo "Done"
|
||||
fi
|
||||
dots "Copying firmware files"
|
||||
cp -r linux-firmware kernelsource$arch/
|
||||
cp -r linux-firmware "kernelsource$arch/"
|
||||
echo "Done"
|
||||
|
||||
dots "Preparing kernel source"
|
||||
cd kernelsource$arch
|
||||
cd "kernelsource$arch" || { echo "Couldn't change directory to kernelsource$arch"; exit 2; }
|
||||
make mrproper
|
||||
cp ../configs/kernel$arch.config .config
|
||||
cp "../configs/kernel$arch.config" .config
|
||||
echo "Done"
|
||||
if [[ -f ../patch/kernel/linux.patch ]]; then
|
||||
dots " * Applying patch"
|
||||
echo
|
||||
echo
|
||||
patch -p1 < ../patch/kernel/linux.patch
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo " * WARNING: Did not find a patch file building vanilla kernel without patches!"
|
||||
fi
|
||||
if [[ $confirm != n ]]; then
|
||||
read -p "We are ready to build. Would you like to edit the config file [y|n]?" config
|
||||
read -rp "We are ready to build. Would you like to edit the config file [y|n]?" config
|
||||
if [[ $config == y ]]; then
|
||||
case "${arch}" in
|
||||
x64)
|
||||
@ -310,24 +314,24 @@ function buildKernel() {
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
read -p "We are ready to build are you [y|n]?" ready
|
||||
read -rp "We are ready to build are you [y|n]?" ready
|
||||
if [[ $ready == y ]]; then
|
||||
echo "This make take a long time. Get some coffee, you'll be here a while!"
|
||||
case "${arch}" in
|
||||
x64)
|
||||
make -j $(nproc) bzImage
|
||||
make -j "$(nproc)" bzImage
|
||||
status=$?
|
||||
;;
|
||||
x86)
|
||||
make ARCH=i386 -j $(nproc) bzImage
|
||||
make ARCH=i386 -j "$(nproc)" bzImage
|
||||
status=$?
|
||||
;;
|
||||
arm64)
|
||||
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j $(nproc) Image
|
||||
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j "$(nproc)" Image
|
||||
status=$?
|
||||
;;
|
||||
*)
|
||||
make -j $(nproc) bzImage
|
||||
make -j "$(nproc)" bzImage
|
||||
status=$?
|
||||
;;
|
||||
esac
|
||||
@ -341,22 +345,22 @@ function buildKernel() {
|
||||
case "${arch}" in
|
||||
x64)
|
||||
make oldconfig
|
||||
make -j $(nproc) bzImage
|
||||
make -j "$(nproc)" bzImage
|
||||
status=$?
|
||||
;;
|
||||
x86)
|
||||
make ARCH=i386 oldconfig
|
||||
make ARCH=i386 -j $(nproc) bzImage
|
||||
make ARCH=i386 -j "$(nproc)" bzImage
|
||||
status=$?
|
||||
;;
|
||||
arm64)
|
||||
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- oldconfig
|
||||
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j $(nproc) Image
|
||||
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j "$(nproc)" Image
|
||||
status=$?
|
||||
;;
|
||||
*)
|
||||
make oldconfig
|
||||
make -j $(nproc) bzImage
|
||||
make -j "$(nproc)" bzImage
|
||||
status=$?
|
||||
;;
|
||||
esac
|
||||
@ -364,7 +368,7 @@ function buildKernel() {
|
||||
[[ $status -gt 0 ]] && exit $status
|
||||
cd ..
|
||||
mkdir -p dist
|
||||
cd dist
|
||||
cd dist || { echo "Couldn't change directory to dist"; exit 1; }
|
||||
case "$arch" in
|
||||
x64)
|
||||
compiledfile="../kernelsource$arch/arch/x86/boot/bzImage"
|
||||
@ -379,24 +383,48 @@ function buildKernel() {
|
||||
kernelfile='arm_Image'
|
||||
;;
|
||||
esac
|
||||
[[ ! -f $compiledfile ]] && echo 'File not found.' || cp $compiledfile $kernelfile && sha256sum $kernelfile > ${kernelfile}.sha256
|
||||
[[ ! -f $compiledfile ]] && echo 'File not found.' || cp "$compiledfile" "$kernelfile" && sha256sum "$kernelfile" > "${kernelfile}.sha256"
|
||||
cd ..
|
||||
}
|
||||
|
||||
dots() {
|
||||
local pad=$(printf "%0.1s" "."{1..60})
|
||||
function dots() {
|
||||
local pad
|
||||
pad=$(printf "%0.1s" "."{1..60})
|
||||
printf " * %s%*.*s" "$1" 0 $((60-${#1})) "$pad"
|
||||
return 0
|
||||
}
|
||||
|
||||
function addKernelPackages() {
|
||||
local source_kernel_package_dir="$PROJECT_DIRECTORY/KernelPackages"
|
||||
local target_kernel_dir="$PROJECT_DIRECTORY/kernelsource$arch"
|
||||
|
||||
find "$source_kernel_package_dir" -type f | while read -r source_file; do
|
||||
# Get the relative path from the package directory to the source file
|
||||
local relative_path="${source_file#"$source_kernel_package_dir"/}"
|
||||
|
||||
# Find the corresponding destination path
|
||||
local destination_file="$target_kernel_dir/$relative_path"
|
||||
local destination_dir
|
||||
destination_dir="$(dirname "$destination_file")"
|
||||
|
||||
mkdir -p "$destination_dir"
|
||||
|
||||
# Append if the destination file exists, otherwise copy
|
||||
if [[ -e "$destination_file" ]]; then
|
||||
cat "$source_file" >> "$destination_file"
|
||||
else
|
||||
cp "$source_file" "$destination_file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
for buildArch in $arch
|
||||
do
|
||||
if [[ -z $buildKernelOnly ]]; then
|
||||
buildFilesystem $buildArch
|
||||
buildFilesystem "$buildArch"
|
||||
fi
|
||||
if [[ -z $buildFSOnly ]]; then
|
||||
buildKernel $buildArch
|
||||
buildKernel "$buildArch"
|
||||
fi
|
||||
done
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,9 @@ declare -ar common_dependencies=(
|
||||
"file"
|
||||
"rsync"
|
||||
"patch"
|
||||
"unzip"
|
||||
"bzip2"
|
||||
"findutils"
|
||||
)
|
||||
|
||||
declare -ar deb_dependencies=(
|
||||
@ -48,7 +51,8 @@ function __epel_repo_message() {
|
||||
|
||||
|
||||
function checkDependencies() {
|
||||
local running_os=$(cat /etc/os-release | grep "^ID=" | cut -d'=' -f2 | tr -d '"')
|
||||
local running_os
|
||||
running_os=$(grep "^ID=" /etc/os-release | cut -d'=' -f2 | tr -d '"')
|
||||
package_manager=""
|
||||
|
||||
case $running_os in
|
||||
@ -79,7 +83,7 @@ function checkDependencies() {
|
||||
missing_packages=""
|
||||
for package in "${dependencies[@]}"; do
|
||||
pkgmgr | awk '{print $2}' | cut -d':' -f1 | grep -qe "${package}"
|
||||
if [[ $? > 0 ]]; then
|
||||
if [[ $? -ne 0 ]]; then
|
||||
missing_packages="${missing_packages} ${package}"
|
||||
fi
|
||||
done
|
||||
@ -101,7 +105,7 @@ function installDependencies() {
|
||||
if [[ -n $missing_packages ]]; then
|
||||
echo "Atempting to install missing dependencies..."
|
||||
$package_manager "${dependencies[@]}" > /dev/null 2>&1
|
||||
if [[ $? > 0 ]]; then
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Failed to install dependencies, please install the packages manually. Exiting now."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
diff --git a/Config.in b/Config.in
|
||||
index df43db7eff..8a3e0ac0a4 100644
|
||||
index d730f2034b..9ad4198d14 100644
|
||||
--- a/Config.in
|
||||
+++ b/Config.in
|
||||
@@ -712,6 +712,24 @@ config BR2_GLOBAL_PATCH_DIR
|
||||
@@ -741,6 +741,24 @@ config BR2_GLOBAL_PATCH_DIR
|
||||
|
||||
menu "Advanced"
|
||||
|
||||
@ -28,10 +28,10 @@ index df43db7eff..8a3e0ac0a4 100644
|
||||
bool "Force the building of host dependencies"
|
||||
help
|
||||
diff --git a/package/Makefile.in b/package/Makefile.in
|
||||
index 1cedfefa7e..62bcbd3269 100644
|
||||
index 829636900b..b2028f9a7c 100644
|
||||
--- a/package/Makefile.in
|
||||
+++ b/package/Makefile.in
|
||||
@@ -431,8 +431,9 @@ else ifeq ($(BR2_SHARED_STATIC_LIBS),y)
|
||||
@@ -447,8 +447,9 @@ else ifeq ($(BR2_SHARED_STATIC_LIBS),y)
|
||||
SHARED_STATIC_LIBS_OPTS = --enable-static --enable-shared
|
||||
endif
|
||||
|
||||
@ -53,7 +53,7 @@ index 3430fcce11..71344e2c69 100644
|
||||
+BR2_COMPILER_PARANOID_UNSAFE_PATH=y
|
||||
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
||||
diff --git a/toolchain/toolchain-wrapper.c b/toolchain/toolchain-wrapper.c
|
||||
index e436889760..caadda4eb0 100644
|
||||
index 8b1fb79dde..6d23b81ef8 100644
|
||||
--- a/toolchain/toolchain-wrapper.c
|
||||
+++ b/toolchain/toolchain-wrapper.c
|
||||
@@ -157,6 +157,7 @@ static const struct str_len_s unsafe_opts[] = {
|
||||
@ -87,10 +87,10 @@ index e436889760..caadda4eb0 100644
|
||||
char *env_debug;
|
||||
+ char *paranoid_wrapper;
|
||||
+ int paranoid;
|
||||
int ret, i, count = 0, debug = 0, found_shared = 0;
|
||||
int ret, i, count = 0, debug = 0, found_shared = 0, found_nonoption = 0;
|
||||
|
||||
/* Debug the wrapper to see arguments it was called with.
|
||||
@@ -474,6 +479,12 @@ int main(int argc, char **argv)
|
||||
@@ -475,6 +480,12 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ index e436889760..caadda4eb0 100644
|
||||
/* Check for unsafe library and header paths */
|
||||
for (i = 1; i < argc; i++) {
|
||||
const struct str_len_s *opt;
|
||||
@@ -490,9 +501,9 @@ int main(int argc, char **argv)
|
||||
@@ -491,9 +502,9 @@ int main(int argc, char **argv)
|
||||
i++;
|
||||
if (i == argc)
|
||||
break;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user