diff --git a/include/kernel-version.mk b/include/kernel-version.mk index fb18167cfe..1224eccd32 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -7,10 +7,10 @@ ifdef CONFIG_TESTING_KERNEL endif LINUX_VERSION-5.4 = .124 -LINUX_VERSION-5.10 = .43 +LINUX_VERSION-5.10 = .44 LINUX_KERNEL_HASH-5.4.124 = f7f29dda2b042d7b5986d18274413131cf70e17288c05e9a683df1f46c507d82 -LINUX_KERNEL_HASH-5.10.43 = 83b81e433ba2f8ee143064fb163699ee857e26dd789006bc1e9edf1ccd0bd403 +LINUX_KERNEL_HASH-5.10.44 = 77beefa59c854ce1e8353db947a71a8a91f2a907aed45c1335ac1f209983c767 remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) diff --git a/package/base-files/files/etc/init.d/system b/package/base-files/files/etc/init.d/system index 08cf86b97f..dcfc2616c6 100755 --- a/package/base-files/files/etc/init.d/system +++ b/package/base-files/files/etc/init.d/system @@ -4,8 +4,7 @@ START=10 USE_PROCD=1 -validate_system_section() -{ +validate_system_section() { uci_load_validate system system "$1" "$2" \ 'hostname:string:OpenWrt' \ 'conloglevel:uinteger' \ @@ -23,8 +22,9 @@ system_config() { echo "$hostname" > /proc/sys/kernel/hostname [ -z "$conloglevel" -a -z "$buffersize" ] || dmesg ${conloglevel:+-n $conloglevel} ${buffersize:+-s $buffersize} echo "$timezone" > /tmp/TZ - [ -n "$zonename" ] && [ -f "/usr/share/zoneinfo/$zonename" ] && \ - ln -sf "/usr/share/zoneinfo/$zonename" /tmp/localtime && rm -f /tmp/TZ + [ -n "$zonename" ] && [ -f "/usr/share/zoneinfo/${zonename// /_}" ] \ + && ln -sf "/usr/share/zoneinfo/${zonename// /_}" /tmp/localtime \ + && rm -f /tmp/TZ # apply timezone to kernel hwclock -u --systz @@ -35,8 +35,7 @@ reload_service() { config_foreach validate_system_section system system_config } -service_triggers() -{ +service_triggers() { procd_add_reload_trigger "system" procd_add_validation validate_system_section } diff --git a/package/base-files/files/etc/rc.common b/package/base-files/files/etc/rc.common index f39b69464e..5dcbf5138d 100755 --- a/package/base-files/files/etc/rc.common +++ b/package/base-files/files/etc/rc.common @@ -55,7 +55,12 @@ enable() { enabled() { name="$(basename "${initscript}")" - [ -x "$IPKG_INSTROOT/etc/rc.d/S${START}${name##S[0-9][0-9]}" ] + name="${name##[SK][0-9][0-9]}" + { + [ -z "${START:-}" ] || [ -L "$IPKG_INSTROOT/etc/rc.d/S${START}$name" ] + } && { + [ -z "${STOP:-}" ] || [ -L "$IPKG_INSTROOT/etc/rc.d/K${STOP}$name" ] + } } depends() { diff --git a/package/base-files/files/lib/preinit/10_indicate_preinit b/package/base-files/files/lib/preinit/10_indicate_preinit index 3c59929790..debb3d4480 100644 --- a/package/base-files/files/lib/preinit/10_indicate_preinit +++ b/package/base-files/files/lib/preinit/10_indicate_preinit @@ -18,6 +18,9 @@ preinit_ip_config() { fi ip link set dev $netdev up + if [ -n "$vid" ]; then + ip link set dev $1 up + fi ip -4 address add $pi_ip/$pi_netmask broadcast $pi_broadcast dev $1 } @@ -72,14 +75,20 @@ preinit_config_board() { json_select network json_select "lan" - json_get_vars ifname + json_get_vars device + json_get_values ports ports json_select .. json_select .. - [ -n "$ifname" ] || return + [ -n "$device" -o -n "$ports" ] || return + + # swconfig uses $device and DSA uses ports + [ -z "$ports" ] && { + ports="$device" + } # only use the first one - ifname=${ifname%% *} + ifname=${ports%% *} if [ -x /sbin/swconfig ]; then # configure the switch, if present @@ -91,6 +100,8 @@ preinit_config_board() { else # trim any vlan ids ifname=${ifname%\.*} + # trim any vlan modifiers like :t + ifname=${ifname%\:*} fi pi_ifname=$ifname diff --git a/package/kernel/bcm63xx-cfe/Makefile b/package/kernel/bcm63xx-cfe/Makefile index 568348e856..a8399ce112 100644 --- a/package/kernel/bcm63xx-cfe/Makefile +++ b/package/kernel/bcm63xx-cfe/Makefile @@ -2,13 +2,13 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=bcm63xx-cfe -PKG_RELEASE:=2 +PKG_RELEASE:=1 PKG_SOURCE_URL:=https://github.com/openwrt/bcm63xx-cfe.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-03-05 -PKG_SOURCE_VERSION:=d03501629fc8b1ba8f9b0961d543c256a3d0098f -PKG_MIRROR_HASH:=b32a6f68d59c8f4534def7ec2568ad7da7a612a605b9406328309c78115ee88d +PKG_SOURCE_DATE:=2021-06-22 +PKG_SOURCE_VERSION:=e5050f37150b34deb547b50feccd0e7439cb5bd7 +PKG_MIRROR_HASH:=85fed9f4bdf23cf7d33a02f549ffe9073666890f786d5ffa484c0368552b75ae PKG_FLAGS:=nonshared diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index 35d840b229..6cecb1a0fa 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -360,7 +360,7 @@ $(eval $(call KernelPackage,crypto-hw-geode)) define KernelPackage/crypto-hw-hifn-795x TITLE:=HIFN 795x crypto accelerator - DEPENDS:=+kmod-random-core +kmod-crypto-manager + DEPENDS:=@PCI_SUPPORT +kmod-random-core +kmod-crypto-manager KCONFIG:= \ CONFIG_CRYPTO_HW=y \ CONFIG_CRYPTO_DEV_HIFN_795X \ diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index a13889a4f2..fb7f974928 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -298,9 +298,10 @@ hostapd_common_add_bss_config() { config_add_string wps_device_type wps_device_name wps_manufacturer wps_pin config_add_string multi_ap_backhaul_ssid multi_ap_backhaul_key - config_add_boolean wnm_sleep_mode bss_transition + config_add_boolean wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition config_add_int time_advertisement config_add_string time_zone + config_add_string vendor_elements config_add_boolean ieee80211k rrm_neighbor_report rrm_beacon_report @@ -353,6 +354,7 @@ hostapd_common_add_bss_config() { config_add_boolean multicast_to_unicast proxy_arp per_sta_vif config_add_array hostapd_bss_options + config_add_boolean default_disabled config_add_boolean request_cui config_add_array radius_auth_req_attr @@ -531,7 +533,8 @@ hostapd_set_bss_options() { multi_ap multi_ap_backhaul_ssid multi_ap_backhaul_key skip_inactivity_poll \ airtime_bss_weight airtime_bss_limit airtime_sta_weight \ multicast_to_unicast proxy_arp per_sta_vif \ - eap_server eap_user_file ca_cert server_cert private_key private_key_passwd server_id + eap_server eap_user_file ca_cert server_cert private_key private_key_passwd server_id \ + vendor_elements set_default isolate 0 set_default maxassoc 0 @@ -579,6 +582,7 @@ hostapd_set_bss_options() { append bss_conf "uapsd_advertisement_enabled=$uapsd" "$N" append bss_conf "utf8_ssid=$utf8_ssid" "$N" append bss_conf "multi_ap=$multi_ap" "$N" + [ -n "$vendor_elements" ] && append bss_conf "vendor_elements=$vendor_elements" "$N" [ "$tdls_prohibit" -gt 0 ] && append bss_conf "tdls_prohibit=$tdls_prohibit" "$N" @@ -759,13 +763,17 @@ hostapd_set_bss_options() { append bss_conf "iapp_interface=$ifname" "$N" } - json_get_vars time_advertisement time_zone wnm_sleep_mode bss_transition + json_get_vars time_advertisement time_zone wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition set_default bss_transition 0 set_default wnm_sleep_mode 0 + set_default wnm_sleep_mode_no_keys 0 [ -n "$time_advertisement" ] && append bss_conf "time_advertisement=$time_advertisement" "$N" [ -n "$time_zone" ] && append bss_conf "time_zone=$time_zone" "$N" - [ "$wnm_sleep_mode" -eq "1" ] && append bss_conf "wnm_sleep_mode=1" "$N" + if [ "$wnm_sleep_mode" -eq "1" ]; then + append bss_conf "wnm_sleep_mode=1" "$N" + [ "$wnm_sleep_mode_no_keys" -eq "1" ] && append bss_conf "wnm_sleep_mode_no_keys=1" "$N" + fi [ "$bss_transition" -eq "1" ] && append bss_conf "bss_transition=1" "$N" json_get_vars ieee80211k rrm_neighbor_report rrm_beacon_report @@ -1187,7 +1195,8 @@ wpa_supplicant_add_network() { ssid bssid key \ basic_rate mcast_rate \ ieee80211w ieee80211r \ - multi_ap + multi_ap \ + default_disabled case "$auth_type" in sae|owe|eap192|eap-eap192) @@ -1200,6 +1209,7 @@ wpa_supplicant_add_network() { set_default ieee80211r 0 set_default multi_ap 0 + set_default default_disabled 0 local key_mgmt='NONE' local network_data= @@ -1231,7 +1241,10 @@ wpa_supplicant_add_network() { scan_ssid="" } - [ "$multi_ap" = 1 -a "$_w_mode" = "sta" ] && append network_data "multi_ap_backhaul_sta=1" "$N$T" + [ "$_w_mode" = "sta" ] && { + [ "$multi_ap" = 1 ] && append network_data "multi_ap_backhaul_sta=1" "$N$T" + [ "$default_disabled" = 1 ] && append network_data "disabled=1" "$N$T" + } case "$auth_type" in none) ;; diff --git a/package/system/zram-swap/Makefile b/package/system/zram-swap/Makefile index 80f87fcdff..d0d1baddd1 100644 --- a/package/system/zram-swap/Makefile +++ b/package/system/zram-swap/Makefile @@ -1,14 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only # -# Copyright (C) 2013 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# +# Copyright (C) 2013-2021 OpenWrt.org include $(TOPDIR)/rules.mk PKG_NAME:=zram-swap -PKG_RELEASE:=8 +PKG_RELEASE:=$(AUTORELEASE) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) diff --git a/package/system/zram-swap/files/zram.init b/package/system/zram-swap/files/zram.init index d97e85efa5..9fce5e4797 100755 --- a/package/system/zram-swap/files/zram.init +++ b/package/system/zram-swap/files/zram.init @@ -25,31 +25,6 @@ zram_getsize() # in megabytes fi } -zram_applicable() -{ - local zram_dev="$1" - - [ -e "$zram_dev" ] || { - logger -s -t zram_applicable -p daemon.crit "[ERROR] device '$zram_dev' not found" - return 1 - } - - [ -x /sbin/mkswap ] || { - logger -s -t zram_applicable -p daemon.err "[ERROR] 'BusyBox mkswap' not installed" - return 1 - } - - [ -x /sbin/swapon ] || { - logger -s -t zram_applicable -p daemon.err "[ERROR] 'BusyBox swapon' not installed" - return 1 - } - - [ -x /sbin/swapoff ] || { - logger -s -t zram_applicable -p daemon.err "[ERROR] 'BusyBox swapoff' not installed" - return 1 - } -} - zram_dev() { local idx="$1" @@ -160,9 +135,14 @@ start() return 1 fi - local zram_size="$( zram_getsize )" local zram_dev="$( zram_getdev )" - zram_applicable "$zram_dev" || return 1 + + [ -e "$zram_dev" ] || { + logger -s -t zram_start -p daemon.crit "[ERROR] device '$zram_dev' not found" + return 1 + } + + local zram_size="$( zram_getsize )" local zram_priority="$( uci -q get system.@system[0].zram_priority )" zram_priority=${zram_priority:+-p $zram_priority} @@ -171,8 +151,8 @@ start() zram_reset "$zram_dev" "enforcing defaults" zram_comp_algo "$zram_dev" echo $(( $zram_size * 1024 * 1024 )) >"/sys/block/$( basename "$zram_dev" )/disksize" - /sbin/mkswap "$zram_dev" - /sbin/swapon -d $zram_priority "$zram_dev" + busybox mkswap "$zram_dev" + busybox swapon -d $zram_priority "$zram_dev" } stop() @@ -181,7 +161,7 @@ stop() for zram_dev in $( grep zram /proc/swaps |awk '{print $1}' ); do { logger -s -t zram_stop -p daemon.debug "deactivate swap $zram_dev" - /sbin/swapoff "$zram_dev" && zram_reset "$zram_dev" "claiming memory back" + busybox swapoff "$zram_dev" && zram_reset "$zram_dev" "claiming memory back" local dev_index="$( echo $zram_dev | grep -o "[0-9]*$" )" if [ $dev_index -ne 0 ]; then logger -s -t zram_stop -p daemon.debug "removing zram $zram_dev" diff --git a/target/linux/ath79/patches-5.4/425-at803x-allow-sgmii-aneg-override.patch b/target/linux/ath79/patches-5.4/425-at803x-allow-sgmii-aneg-override.patch index 396b1ee7a2..a3016d1b30 100644 --- a/target/linux/ath79/patches-5.4/425-at803x-allow-sgmii-aneg-override.patch +++ b/target/linux/ath79/patches-5.4/425-at803x-allow-sgmii-aneg-override.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c -@@ -383,6 +383,13 @@ static int at803x_aneg_done(struct phy_d +@@ -404,6 +404,13 @@ static int at803x_aneg_done(struct phy_d if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) { phydev_warn(phydev, "803x_aneg_done: SGMII link is not ok\n"); aneg_done = 0; diff --git a/target/linux/generic/backport-5.10/765-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch b/target/linux/generic/backport-5.10/765-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch new file mode 100644 index 0000000000..3b630377f9 --- /dev/null +++ b/target/linux/generic/backport-5.10/765-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch @@ -0,0 +1,85 @@ +From 9d5ef190e5615a7b63af89f88c4106a5bc127974 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Fri, 5 Feb 2021 15:37:10 +0200 +Subject: [PATCH] net: dsa: automatically bring up DSA master when opening user + port + +DSA wants the master interface to be open before the user port is due to +historical reasons. The promiscuity of interfaces that are down used to +have issues, as referenced Lennert Buytenhek in commit df02c6ff2e39 +("dsa: fix master interface allmulti/promisc handling"). + +The bugfix mentioned there, commit b6c40d68ff64 ("net: only invoke +dev->change_rx_flags when device is UP"), was basically a "don't do +that" approach to working around the promiscuity while down issue. + +Further work done by Vlad Yasevich in commit d2615bf45069 ("net: core: +Always propagate flag changes to interfaces") has resolved the +underlying issue, and it is strictly up to the DSA and 8021q drivers +now, it is no longer mandated by the networking core that the master +interface must be up when changing its promiscuity. + +From DSA's point of view, deciding to error out in dsa_slave_open +because the master isn't up is +(a) a bad user experience and +(b) knocking at an open door. +Even if there still was an issue with promiscuity while down, DSA could +still just open the master and avoid it. + +Doing it this way has the additional benefit that user space can now +remove DSA-specific workarounds, like systemd-networkd with BindCarrier: +https://github.com/systemd/systemd/issues/7478 + +And we can finally remove one of the 2 bullets in the "Common pitfalls +using DSA setups" chapter. + +Tested with two cascaded DSA switches: + +$ ip link set sw0p2 up +fsl_enetc 0000:00:00.2 eno2: configuring for fixed/internal link mode +fsl_enetc 0000:00:00.2 eno2: Link is Up - 1Gbps/Full - flow control rx/tx +mscc_felix 0000:00:00.5 swp0: configuring for fixed/sgmii link mode +mscc_felix 0000:00:00.5 swp0: Link is Up - 1Gbps/Full - flow control off +8021q: adding VLAN 0 to HW filter on device swp0 +sja1105 spi2.0 sw0p2: configuring for phy/rgmii-id link mode +IPv6: ADDRCONF(NETDEV_CHANGE): eno2: link becomes ready +IPv6: ADDRCONF(NETDEV_CHANGE): swp0: link becomes ready + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + Documentation/networking/dsa/dsa.rst | 4 ---- + net/dsa/slave.c | 7 +++++-- + 2 files changed, 5 insertions(+), 6 deletions(-) + +--- a/Documentation/networking/dsa/dsa.rst ++++ b/Documentation/networking/dsa/dsa.rst +@@ -273,10 +273,6 @@ will not make us go through the switch t + the Ethernet switch on the other end, expecting a tag will typically drop this + frame. + +-Slave network devices check that the master network device is UP before allowing +-you to administratively bring UP these slave network devices. A common +-configuration mistake is forgetting to bring UP the master network device first. +- + Interactions with other subsystems + ================================== + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -68,8 +68,11 @@ static int dsa_slave_open(struct net_dev + struct dsa_port *dp = dsa_slave_to_port(dev); + int err; + +- if (!(master->flags & IFF_UP)) +- return -ENETDOWN; ++ err = dev_open(master, NULL); ++ if (err < 0) { ++ netdev_err(dev, "failed to open master %s\n", master->name); ++ goto out; ++ } + + if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) { + err = dev_uc_add(master, dev->dev_addr); diff --git a/target/linux/generic/backport-5.10/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch b/target/linux/generic/backport-5.10/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch index 77ce3b6b1e..7715e99647 100644 --- a/target/linux/generic/backport-5.10/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch +++ b/target/linux/generic/backport-5.10/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch @@ -25,7 +25,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2111,7 +2111,9 @@ static void dsa_slave_switchdev_event_wo +@@ -2114,7 +2114,9 @@ static void dsa_slave_switchdev_event_wo err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid); if (err) { @@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski break; } fdb_info->offloaded = true; -@@ -2126,9 +2128,11 @@ static void dsa_slave_switchdev_event_wo +@@ -2129,9 +2131,11 @@ static void dsa_slave_switchdev_event_wo err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid); if (err) { diff --git a/target/linux/generic/backport-5.10/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch b/target/linux/generic/backport-5.10/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch index c7e7763bfc..fcd108332b 100644 --- a/target/linux/generic/backport-5.10/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch +++ b/target/linux/generic/backport-5.10/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch @@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski struct sk_buff * (*xmit)(struct sk_buff *skb, --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2086,76 +2086,66 @@ static int dsa_slave_netdevice_event(str +@@ -2089,76 +2089,66 @@ static int dsa_slave_netdevice_event(str return NOTIFY_DONE; } @@ -167,7 +167,7 @@ Signed-off-by: Jakub Kicinski } /* Called under rcu_read_lock() */ -@@ -2163,7 +2153,9 @@ static int dsa_slave_switchdev_event(str +@@ -2166,7 +2156,9 @@ static int dsa_slave_switchdev_event(str unsigned long event, void *ptr) { struct net_device *dev = switchdev_notifier_info_to_dev(ptr); @@ -177,7 +177,7 @@ Signed-off-by: Jakub Kicinski int err; if (event == SWITCHDEV_PORT_ATTR_SET) { -@@ -2176,20 +2168,32 @@ static int dsa_slave_switchdev_event(str +@@ -2179,20 +2171,32 @@ static int dsa_slave_switchdev_event(str if (!dsa_slave_dev_check(dev)) return NOTIFY_DONE; @@ -213,7 +213,7 @@ Signed-off-by: Jakub Kicinski dev_hold(dev); break; default: -@@ -2199,10 +2203,6 @@ static int dsa_slave_switchdev_event(str +@@ -2202,10 +2206,6 @@ static int dsa_slave_switchdev_event(str dsa_schedule_work(&switchdev_work->work); return NOTIFY_OK; diff --git a/target/linux/generic/backport-5.10/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch b/target/linux/generic/backport-5.10/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch index 984578a326..12b5f4222a 100644 --- a/target/linux/generic/backport-5.10/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch +++ b/target/linux/generic/backport-5.10/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch @@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2158,31 +2158,29 @@ static int dsa_slave_switchdev_event(str +@@ -2161,31 +2161,29 @@ static int dsa_slave_switchdev_event(str struct dsa_port *dp; int err; @@ -68,7 +68,7 @@ Signed-off-by: Jakub Kicinski fdb_info = ptr; if (!fdb_info->added_by_user) { -@@ -2195,13 +2193,12 @@ static int dsa_slave_switchdev_event(str +@@ -2198,13 +2196,12 @@ static int dsa_slave_switchdev_event(str switchdev_work->vid = fdb_info->vid; dev_hold(dev); diff --git a/target/linux/generic/backport-5.10/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch b/target/linux/generic/backport-5.10/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch index 652efa2567..ba163ec77e 100644 --- a/target/linux/generic/backport-5.10/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch +++ b/target/linux/generic/backport-5.10/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch @@ -30,7 +30,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2171,6 +2171,9 @@ static int dsa_slave_switchdev_event(str +@@ -2174,6 +2174,9 @@ static int dsa_slave_switchdev_event(str dp = dsa_slave_to_port(dev); diff --git a/target/linux/generic/backport-5.10/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch b/target/linux/generic/backport-5.10/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch index e875408a3d..70d6629ee7 100644 --- a/target/linux/generic/backport-5.10/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch +++ b/target/linux/generic/backport-5.10/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch @@ -170,7 +170,7 @@ Signed-off-by: Jakub Kicinski */ --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2148,6 +2148,28 @@ static void dsa_slave_switchdev_event_wo +@@ -2151,6 +2151,28 @@ static void dsa_slave_switchdev_event_wo dev_put(dp->slave); } @@ -199,7 +199,7 @@ Signed-off-by: Jakub Kicinski /* Called under rcu_read_lock() */ static int dsa_slave_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) -@@ -2166,10 +2188,37 @@ static int dsa_slave_switchdev_event(str +@@ -2169,10 +2191,37 @@ static int dsa_slave_switchdev_event(str return notifier_from_errno(err); case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE: @@ -240,7 +240,7 @@ Signed-off-by: Jakub Kicinski if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del) return NOTIFY_DONE; -@@ -2184,18 +2233,13 @@ static int dsa_slave_switchdev_event(str +@@ -2187,18 +2236,13 @@ static int dsa_slave_switchdev_event(str switchdev_work->port = dp->index; switchdev_work->event = event; diff --git a/target/linux/generic/backport-5.4/080-wireguard-0124-crypto-mips-poly1305-enable-for-all-MIPS-processors.patch b/target/linux/generic/backport-5.4/080-wireguard-0124-crypto-mips-poly1305-enable-for-all-MIPS-processors.patch new file mode 100644 index 0000000000..c0ee841b02 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0124-crypto-mips-poly1305-enable-for-all-MIPS-processors.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Maciej W. Rozycki" +Date: Thu, 11 Mar 2021 21:50:47 -0700 +Subject: [PATCH] crypto: mips/poly1305 - enable for all MIPS processors + +commit 6c810cf20feef0d4338e9b424ab7f2644a8b353e upstream. + +The MIPS Poly1305 implementation is generic MIPS code written such as to +support down to the original MIPS I and MIPS III ISA for the 32-bit and +64-bit variant respectively. Lift the current limitation then to enable +code for MIPSr1 ISA or newer processors only and have it available for +all MIPS processors. + +Signed-off-by: Maciej W. Rozycki +Fixes: a11d055e7a64 ("crypto: mips/poly1305 - incorporate OpenSSL/CRYPTOGAMS optimized implementation") +Cc: stable@vger.kernel.org # v5.5+ +Acked-by: Jason A. Donenfeld +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Jason A. Donenfeld +--- + arch/mips/crypto/Makefile | 4 ++-- + crypto/Kconfig | 2 +- + drivers/net/Kconfig | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/mips/crypto/Makefile ++++ b/arch/mips/crypto/Makefile +@@ -12,8 +12,8 @@ AFLAGS_chacha-core.o += -O2 # needed to + obj-$(CONFIG_CRYPTO_POLY1305_MIPS) += poly1305-mips.o + poly1305-mips-y := poly1305-core.o poly1305-glue.o + +-perlasm-flavour-$(CONFIG_CPU_MIPS32) := o32 +-perlasm-flavour-$(CONFIG_CPU_MIPS64) := 64 ++perlasm-flavour-$(CONFIG_32BIT) := o32 ++perlasm-flavour-$(CONFIG_64BIT) := 64 + + quiet_cmd_perlasm = PERLASM $@ + cmd_perlasm = $(PERL) $(<) $(perlasm-flavour-y) $(@) +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -740,7 +740,7 @@ config CRYPTO_POLY1305_X86_64 + + config CRYPTO_POLY1305_MIPS + tristate "Poly1305 authenticator algorithm (MIPS optimized)" +- depends on CPU_MIPS32 || (CPU_MIPS64 && 64BIT) ++ depends on MIPS + select CRYPTO_ARCH_HAVE_LIB_POLY1305 + + config CRYPTO_MD4 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -92,7 +92,7 @@ config WIREGUARD + select CRYPTO_POLY1305_ARM if ARM + select CRYPTO_CURVE25519_NEON if ARM && KERNEL_MODE_NEON + select CRYPTO_CHACHA_MIPS if CPU_MIPS32_R2 +- select CRYPTO_POLY1305_MIPS if CPU_MIPS32 || (CPU_MIPS64 && 64BIT) ++ select CRYPTO_POLY1305_MIPS if MIPS + help + WireGuard is a secure, fast, and easy to use replacement for IPSec + that uses modern cryptography and clever networking tricks. It's diff --git a/target/linux/generic/backport-5.4/080-wireguard-0125-crypto-mips-add-poly1305-core.S-to-.gitignore.patch b/target/linux/generic/backport-5.4/080-wireguard-0125-crypto-mips-add-poly1305-core.S-to-.gitignore.patch new file mode 100644 index 0000000000..856d67d5b8 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0125-crypto-mips-add-poly1305-core.S-to-.gitignore.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ilya Lipnitskiy +Date: Sat, 27 Mar 2021 19:39:43 -0700 +Subject: [PATCH] crypto: mips: add poly1305-core.S to .gitignore + +commit dc92d0df51dc61de88bf6f4884a17bf73d5c6326 upstream. + +poly1305-core.S is an auto-generated file, so it should be ignored. + +Fixes: a11d055e7a64 ("crypto: mips/poly1305 - incorporate OpenSSL/CRYPTOGAMS optimized implementation") +Signed-off-by: Ilya Lipnitskiy +Cc: Ard Biesheuvel +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Jason A. Donenfeld +--- + arch/mips/crypto/.gitignore | 2 ++ + 1 file changed, 2 insertions(+) + create mode 100644 arch/mips/crypto/.gitignore + +--- /dev/null ++++ b/arch/mips/crypto/.gitignore +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++poly1305-core.S diff --git a/target/linux/generic/backport-5.4/080-wireguard-0126-crypto-poly1305-fix-poly1305_core_setkey-declaration.patch b/target/linux/generic/backport-5.4/080-wireguard-0126-crypto-poly1305-fix-poly1305_core_setkey-declaration.patch new file mode 100644 index 0000000000..ded6625aeb --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0126-crypto-poly1305-fix-poly1305_core_setkey-declaration.patch @@ -0,0 +1,172 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Mon, 22 Mar 2021 18:05:15 +0100 +Subject: [PATCH] crypto: poly1305 - fix poly1305_core_setkey() declaration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 8d195e7a8ada68928f2aedb2c18302a4518fe68e upstream. + +gcc-11 points out a mismatch between the declaration and the definition +of poly1305_core_setkey(): + +lib/crypto/poly1305-donna32.c:13:67: error: argument 2 of type ‘const u8[16]’ {aka ‘const unsigned char[16]’} with mismatched bound [-Werror=array-parameter=] + 13 | void poly1305_core_setkey(struct poly1305_core_key *key, const u8 raw_key[16]) + | ~~~~~~~~~^~~~~~~~~~~ +In file included from lib/crypto/poly1305-donna32.c:11: +include/crypto/internal/poly1305.h:21:68: note: previously declared as ‘const u8 *’ {aka ‘const unsigned char *’} + 21 | void poly1305_core_setkey(struct poly1305_core_key *key, const u8 *raw_key); + +This is harmless in principle, as the calling conventions are the same, +but the more specific prototype allows better type checking in the +caller. + +Change the declaration to match the actual function definition. +The poly1305_simd_init() is a bit suspicious here, as it previously +had a 32-byte argument type, but looks like it needs to take the +16-byte POLY1305_BLOCK_SIZE array instead. + +Fixes: 1c08a104360f ("crypto: poly1305 - add new 32 and 64-bit generic versions") +Signed-off-by: Arnd Bergmann +Reviewed-by: Ard Biesheuvel +Reviewed-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Jason A. Donenfeld +--- + arch/arm/crypto/poly1305-glue.c | 2 +- + arch/arm64/crypto/poly1305-glue.c | 2 +- + arch/mips/crypto/poly1305-glue.c | 2 +- + arch/x86/crypto/poly1305_glue.c | 6 +++--- + include/crypto/internal/poly1305.h | 3 ++- + include/crypto/poly1305.h | 6 ++++-- + lib/crypto/poly1305-donna32.c | 3 ++- + lib/crypto/poly1305-donna64.c | 3 ++- + lib/crypto/poly1305.c | 3 ++- + 9 files changed, 18 insertions(+), 12 deletions(-) + +--- a/arch/arm/crypto/poly1305-glue.c ++++ b/arch/arm/crypto/poly1305-glue.c +@@ -29,7 +29,7 @@ void __weak poly1305_blocks_neon(void *s + + static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon); + +-void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 *key) ++void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 key[POLY1305_KEY_SIZE]) + { + poly1305_init_arm(&dctx->h, key); + dctx->s[0] = get_unaligned_le32(key + 16); +--- a/arch/arm64/crypto/poly1305-glue.c ++++ b/arch/arm64/crypto/poly1305-glue.c +@@ -25,7 +25,7 @@ asmlinkage void poly1305_emit(void *stat + + static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon); + +-void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 *key) ++void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 key[POLY1305_KEY_SIZE]) + { + poly1305_init_arm64(&dctx->h, key); + dctx->s[0] = get_unaligned_le32(key + 16); +--- a/arch/mips/crypto/poly1305-glue.c ++++ b/arch/mips/crypto/poly1305-glue.c +@@ -17,7 +17,7 @@ asmlinkage void poly1305_init_mips(void + asmlinkage void poly1305_blocks_mips(void *state, const u8 *src, u32 len, u32 hibit); + asmlinkage void poly1305_emit_mips(void *state, u8 *digest, const u32 *nonce); + +-void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 *key) ++void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 key[POLY1305_KEY_SIZE]) + { + poly1305_init_mips(&dctx->h, key); + dctx->s[0] = get_unaligned_le32(key + 16); +--- a/arch/x86/crypto/poly1305_glue.c ++++ b/arch/x86/crypto/poly1305_glue.c +@@ -15,7 +15,7 @@ + #include + + asmlinkage void poly1305_init_x86_64(void *ctx, +- const u8 key[POLY1305_KEY_SIZE]); ++ const u8 key[POLY1305_BLOCK_SIZE]); + asmlinkage void poly1305_blocks_x86_64(void *ctx, const u8 *inp, + const size_t len, const u32 padbit); + asmlinkage void poly1305_emit_x86_64(void *ctx, u8 mac[POLY1305_DIGEST_SIZE], +@@ -80,7 +80,7 @@ static void convert_to_base2_64(void *ct + state->is_base2_26 = 0; + } + +-static void poly1305_simd_init(void *ctx, const u8 key[POLY1305_KEY_SIZE]) ++static void poly1305_simd_init(void *ctx, const u8 key[POLY1305_BLOCK_SIZE]) + { + poly1305_init_x86_64(ctx, key); + } +@@ -128,7 +128,7 @@ static void poly1305_simd_emit(void *ctx + poly1305_emit_avx(ctx, mac, nonce); + } + +-void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 *key) ++void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 key[POLY1305_KEY_SIZE]) + { + poly1305_simd_init(&dctx->h, key); + dctx->s[0] = get_unaligned_le32(&key[16]); +--- a/include/crypto/internal/poly1305.h ++++ b/include/crypto/internal/poly1305.h +@@ -18,7 +18,8 @@ + * only the ε-almost-∆-universal hash function (not the full MAC) is computed. + */ + +-void poly1305_core_setkey(struct poly1305_core_key *key, const u8 *raw_key); ++void poly1305_core_setkey(struct poly1305_core_key *key, ++ const u8 raw_key[POLY1305_BLOCK_SIZE]); + static inline void poly1305_core_init(struct poly1305_state *state) + { + *state = (struct poly1305_state){}; +--- a/include/crypto/poly1305.h ++++ b/include/crypto/poly1305.h +@@ -58,8 +58,10 @@ struct poly1305_desc_ctx { + }; + }; + +-void poly1305_init_arch(struct poly1305_desc_ctx *desc, const u8 *key); +-void poly1305_init_generic(struct poly1305_desc_ctx *desc, const u8 *key); ++void poly1305_init_arch(struct poly1305_desc_ctx *desc, ++ const u8 key[POLY1305_KEY_SIZE]); ++void poly1305_init_generic(struct poly1305_desc_ctx *desc, ++ const u8 key[POLY1305_KEY_SIZE]); + + static inline void poly1305_init(struct poly1305_desc_ctx *desc, const u8 *key) + { +--- a/lib/crypto/poly1305-donna32.c ++++ b/lib/crypto/poly1305-donna32.c +@@ -10,7 +10,8 @@ + #include + #include + +-void poly1305_core_setkey(struct poly1305_core_key *key, const u8 raw_key[16]) ++void poly1305_core_setkey(struct poly1305_core_key *key, ++ const u8 raw_key[POLY1305_BLOCK_SIZE]) + { + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + key->key.r[0] = (get_unaligned_le32(&raw_key[0])) & 0x3ffffff; +--- a/lib/crypto/poly1305-donna64.c ++++ b/lib/crypto/poly1305-donna64.c +@@ -12,7 +12,8 @@ + + typedef __uint128_t u128; + +-void poly1305_core_setkey(struct poly1305_core_key *key, const u8 raw_key[16]) ++void poly1305_core_setkey(struct poly1305_core_key *key, ++ const u8 raw_key[POLY1305_BLOCK_SIZE]) + { + u64 t0, t1; + +--- a/lib/crypto/poly1305.c ++++ b/lib/crypto/poly1305.c +@@ -12,7 +12,8 @@ + #include + #include + +-void poly1305_init_generic(struct poly1305_desc_ctx *desc, const u8 *key) ++void poly1305_init_generic(struct poly1305_desc_ctx *desc, ++ const u8 key[POLY1305_KEY_SIZE]) + { + poly1305_core_setkey(&desc->core_r, key); + desc->s[0] = get_unaligned_le32(key + 16); diff --git a/target/linux/generic/backport-5.4/080-wireguard-0127-wireguard-selftests-remove-old-conntrack-kconfig-val.patch b/target/linux/generic/backport-5.4/080-wireguard-0127-wireguard-selftests-remove-old-conntrack-kconfig-val.patch new file mode 100644 index 0000000000..3e7d1a8e02 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0127-wireguard-selftests-remove-old-conntrack-kconfig-val.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:30 +0200 +Subject: [PATCH] wireguard: selftests: remove old conntrack kconfig value + +commit acf2492b51c9a3c4dfb947f4d3477a86d315150f upstream. + +On recent kernels, this config symbol is no longer used. + +Reported-by: Rui Salvaterra +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + tools/testing/selftests/wireguard/qemu/kernel.config | 1 - + 1 file changed, 1 deletion(-) + +--- a/tools/testing/selftests/wireguard/qemu/kernel.config ++++ b/tools/testing/selftests/wireguard/qemu/kernel.config +@@ -19,7 +19,6 @@ CONFIG_NETFILTER_XTABLES=y + CONFIG_NETFILTER_XT_NAT=y + CONFIG_NETFILTER_XT_MATCH_LENGTH=y + CONFIG_NETFILTER_XT_MARK=y +-CONFIG_NF_CONNTRACK_IPV4=y + CONFIG_NF_NAT_IPV4=y + CONFIG_IP_NF_IPTABLES=y + CONFIG_IP_NF_FILTER=y diff --git a/target/linux/generic/backport-5.4/080-wireguard-0128-wireguard-selftests-make-sure-rp_filter-is-disabled-.patch b/target/linux/generic/backport-5.4/080-wireguard-0128-wireguard-selftests-make-sure-rp_filter-is-disabled-.patch new file mode 100644 index 0000000000..22d0f3e32e --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0128-wireguard-selftests-make-sure-rp_filter-is-disabled-.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:31 +0200 +Subject: [PATCH] wireguard: selftests: make sure rp_filter is disabled on + vethc + +commit f8873d11d4121aad35024f9379e431e0c83abead upstream. + +Some distros may enable strict rp_filter by default, which will prevent +vethc from receiving the packets with an unrouteable reverse path address. + +Reported-by: Hangbin Liu +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + tools/testing/selftests/wireguard/netns.sh | 1 + + 1 file changed, 1 insertion(+) + +--- a/tools/testing/selftests/wireguard/netns.sh ++++ b/tools/testing/selftests/wireguard/netns.sh +@@ -363,6 +363,7 @@ ip1 -6 rule add table main suppress_pref + ip1 -4 route add default dev wg0 table 51820 + ip1 -4 rule add not fwmark 51820 table 51820 + ip1 -4 rule add table main suppress_prefixlength 0 ++n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/vethc/rp_filter' + # Flood the pings instead of sending just one, to trigger routing table reference counting bugs. + n1 ping -W 1 -c 100 -f 192.168.99.7 + n1 ping -W 1 -c 100 -f abab::1111 diff --git a/target/linux/generic/backport-5.4/080-wireguard-0129-wireguard-do-not-use-O3.patch b/target/linux/generic/backport-5.4/080-wireguard-0129-wireguard-do-not-use-O3.patch new file mode 100644 index 0000000000..a7890a7384 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0129-wireguard-do-not-use-O3.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:32 +0200 +Subject: [PATCH] wireguard: do not use -O3 + +commit cc5060ca0285efe2728bced399a1955a7ce808b2 upstream. + +Apparently, various versions of gcc have O3-related miscompiles. Looking +at the difference between -O2 and -O3 for gcc 11 doesn't indicate +miscompiles, but the difference also doesn't seem so significant for +performance that it's worth risking. + +Link: https://lore.kernel.org/lkml/CAHk-=wjuoGyxDhAF8SsrTkN0-YfCx7E6jUN3ikC_tn2AKWTTsA@mail.gmail.com/ +Link: https://lore.kernel.org/lkml/CAHmME9otB5Wwxp7H8bR_i2uH2esEMvoBMC8uEXBMH9p0q1s6Bw@mail.gmail.com/ +Reported-by: Linus Torvalds +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + drivers/net/wireguard/Makefile | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/wireguard/Makefile ++++ b/drivers/net/wireguard/Makefile +@@ -1,5 +1,4 @@ +-ccflags-y := -O3 +-ccflags-y += -D'pr_fmt(fmt)=KBUILD_MODNAME ": " fmt' ++ccflags-y := -D'pr_fmt(fmt)=KBUILD_MODNAME ": " fmt' + ccflags-$(CONFIG_WIREGUARD_DEBUG) += -DDEBUG + wireguard-y := main.o + wireguard-y += noise.o diff --git a/target/linux/generic/backport-5.4/080-wireguard-0130-wireguard-use-synchronize_net-rather-than-synchroniz.patch b/target/linux/generic/backport-5.4/080-wireguard-0130-wireguard-use-synchronize_net-rather-than-synchroniz.patch new file mode 100644 index 0000000000..309fe36198 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0130-wireguard-use-synchronize_net-rather-than-synchroniz.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:33 +0200 +Subject: [PATCH] wireguard: use synchronize_net rather than synchronize_rcu + +commit 24b70eeeb4f46c09487f8155239ebfb1f875774a upstream. + +Many of the synchronization points are sometimes called under the rtnl +lock, which means we should use synchronize_net rather than +synchronize_rcu. Under the hood, this expands to using the expedited +flavor of function in the event that rtnl is held, in order to not stall +other concurrent changes. + +This fixes some very, very long delays when removing multiple peers at +once, which would cause some operations to take several minutes. + +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + drivers/net/wireguard/peer.c | 6 +++--- + drivers/net/wireguard/socket.c | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireguard/peer.c ++++ b/drivers/net/wireguard/peer.c +@@ -88,7 +88,7 @@ static void peer_make_dead(struct wg_pee + /* Mark as dead, so that we don't allow jumping contexts after. */ + WRITE_ONCE(peer->is_dead, true); + +- /* The caller must now synchronize_rcu() for this to take effect. */ ++ /* The caller must now synchronize_net() for this to take effect. */ + } + + static void peer_remove_after_dead(struct wg_peer *peer) +@@ -160,7 +160,7 @@ void wg_peer_remove(struct wg_peer *peer + lockdep_assert_held(&peer->device->device_update_lock); + + peer_make_dead(peer); +- synchronize_rcu(); ++ synchronize_net(); + peer_remove_after_dead(peer); + } + +@@ -178,7 +178,7 @@ void wg_peer_remove_all(struct wg_device + peer_make_dead(peer); + list_add_tail(&peer->peer_list, &dead_peers); + } +- synchronize_rcu(); ++ synchronize_net(); + list_for_each_entry_safe(peer, temp, &dead_peers, peer_list) + peer_remove_after_dead(peer); + } +--- a/drivers/net/wireguard/socket.c ++++ b/drivers/net/wireguard/socket.c +@@ -430,7 +430,7 @@ void wg_socket_reinit(struct wg_device * + if (new4) + wg->incoming_port = ntohs(inet_sk(new4)->inet_sport); + mutex_unlock(&wg->socket_update_lock); +- synchronize_rcu(); ++ synchronize_net(); + sock_free(old4); + sock_free(old6); + } diff --git a/target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch b/target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch new file mode 100644 index 0000000000..32ae327037 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch @@ -0,0 +1,125 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:34 +0200 +Subject: [PATCH] wireguard: peer: allocate in kmem_cache + +commit a4e9f8e3287c9eb6bf70df982870980dd3341863 upstream. + +With deployments having upwards of 600k peers now, this somewhat heavy +structure could benefit from more fine-grained allocations. +Specifically, instead of using a 2048-byte slab for a 1544-byte object, +we can now use 1544-byte objects directly, thus saving almost 25% +per-peer, or with 600k peers, that's a savings of 303 MiB. This also +makes wireguard's memory usage more transparent in tools like slabtop +and /proc/slabinfo. + +Fixes: 8b5553ace83c ("wireguard: queueing: get rid of per-peer ring buffers") +Suggested-by: Arnd Bergmann +Suggested-by: Matthew Wilcox +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + drivers/net/wireguard/main.c | 7 +++++++ + drivers/net/wireguard/peer.c | 21 +++++++++++++++++---- + drivers/net/wireguard/peer.h | 3 +++ + 3 files changed, 27 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireguard/main.c ++++ b/drivers/net/wireguard/main.c +@@ -28,6 +28,10 @@ static int __init mod_init(void) + #endif + wg_noise_init(); + ++ ret = wg_peer_init(); ++ if (ret < 0) ++ goto err_peer; ++ + ret = wg_device_init(); + if (ret < 0) + goto err_device; +@@ -44,6 +48,8 @@ static int __init mod_init(void) + err_netlink: + wg_device_uninit(); + err_device: ++ wg_peer_uninit(); ++err_peer: + return ret; + } + +@@ -51,6 +57,7 @@ static void __exit mod_exit(void) + { + wg_genetlink_uninit(); + wg_device_uninit(); ++ wg_peer_uninit(); + } + + module_init(mod_init); +--- a/drivers/net/wireguard/peer.c ++++ b/drivers/net/wireguard/peer.c +@@ -15,6 +15,7 @@ + #include + #include + ++static struct kmem_cache *peer_cache; + static atomic64_t peer_counter = ATOMIC64_INIT(0); + + struct wg_peer *wg_peer_create(struct wg_device *wg, +@@ -29,10 +30,10 @@ struct wg_peer *wg_peer_create(struct wg + if (wg->num_peers >= MAX_PEERS_PER_DEVICE) + return ERR_PTR(ret); + +- peer = kzalloc(sizeof(*peer), GFP_KERNEL); ++ peer = kmem_cache_zalloc(peer_cache, GFP_KERNEL); + if (unlikely(!peer)) + return ERR_PTR(ret); +- if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL)) ++ if (unlikely(dst_cache_init(&peer->endpoint_cache, GFP_KERNEL))) + goto err; + + peer->device = wg; +@@ -64,7 +65,7 @@ struct wg_peer *wg_peer_create(struct wg + return peer; + + err: +- kfree(peer); ++ kmem_cache_free(peer_cache, peer); + return ERR_PTR(ret); + } + +@@ -193,7 +194,8 @@ static void rcu_release(struct rcu_head + /* The final zeroing takes care of clearing any remaining handshake key + * material and other potentially sensitive information. + */ +- kzfree(peer); ++ memzero_explicit(peer, sizeof(*peer)); ++ kmem_cache_free(peer_cache, peer); + } + + static void kref_release(struct kref *refcount) +@@ -225,3 +227,14 @@ void wg_peer_put(struct wg_peer *peer) + return; + kref_put(&peer->refcount, kref_release); + } ++ ++int __init wg_peer_init(void) ++{ ++ peer_cache = KMEM_CACHE(wg_peer, 0); ++ return peer_cache ? 0 : -ENOMEM; ++} ++ ++void wg_peer_uninit(void) ++{ ++ kmem_cache_destroy(peer_cache); ++} +--- a/drivers/net/wireguard/peer.h ++++ b/drivers/net/wireguard/peer.h +@@ -80,4 +80,7 @@ void wg_peer_put(struct wg_peer *peer); + void wg_peer_remove(struct wg_peer *peer); + void wg_peer_remove_all(struct wg_device *wg); + ++int wg_peer_init(void); ++void wg_peer_uninit(void); ++ + #endif /* _WG_PEER_H */ diff --git a/target/linux/generic/backport-5.4/080-wireguard-0132-wireguard-allowedips-initialize-list-head-in-selftes.patch b/target/linux/generic/backport-5.4/080-wireguard-0132-wireguard-allowedips-initialize-list-head-in-selftes.patch new file mode 100644 index 0000000000..ce4e5dcf50 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0132-wireguard-allowedips-initialize-list-head-in-selftes.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:35 +0200 +Subject: [PATCH] wireguard: allowedips: initialize list head in selftest + +commit 46cfe8eee285cde465b420637507884551f5d7ca upstream. + +The randomized trie tests weren't initializing the dummy peer list head, +resulting in a NULL pointer dereference when used. Fix this by +initializing it in the randomized trie test, just like we do for the +static unit test. + +While we're at it, all of the other strings like this have the word +"self-test", so add it to the missing place here. + +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + drivers/net/wireguard/selftest/allowedips.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireguard/selftest/allowedips.c ++++ b/drivers/net/wireguard/selftest/allowedips.c +@@ -296,6 +296,7 @@ static __init bool randomized_test(void) + goto free; + } + kref_init(&peers[i]->refcount); ++ INIT_LIST_HEAD(&peers[i]->allowedips_list); + } + + mutex_lock(&mutex); +@@ -333,7 +334,7 @@ static __init bool randomized_test(void) + if (wg_allowedips_insert_v4(&t, + (struct in_addr *)mutated, + cidr, peer, &mutex) < 0) { +- pr_err("allowedips random malloc: FAIL\n"); ++ pr_err("allowedips random self-test malloc: FAIL\n"); + goto free_locked; + } + if (horrible_allowedips_insert_v4(&h, diff --git a/target/linux/generic/backport-5.4/080-wireguard-0133-wireguard-allowedips-remove-nodes-in-O-1.patch b/target/linux/generic/backport-5.4/080-wireguard-0133-wireguard-allowedips-remove-nodes-in-O-1.patch new file mode 100644 index 0000000000..78da24ea46 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0133-wireguard-allowedips-remove-nodes-in-O-1.patch @@ -0,0 +1,237 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:36 +0200 +Subject: [PATCH] wireguard: allowedips: remove nodes in O(1) + +commit f634f418c227c912e7ea95a3299efdc9b10e4022 upstream. + +Previously, deleting peers would require traversing the entire trie in +order to rebalance nodes and safely free them. This meant that removing +1000 peers from a trie with a half million nodes would take an extremely +long time, during which we're holding the rtnl lock. Large-scale users +were reporting 200ms latencies added to the networking stack as a whole +every time their userspace software would queue up significant removals. +That's a serious situation. + +This commit fixes that by maintaining a double pointer to the parent's +bit pointer for each node, and then using the already existing node list +belonging to each peer to go directly to the node, fix up its pointers, +and free it with RCU. This means removal is O(1) instead of O(n), and we +don't use gobs of stack. + +The removal algorithm has the same downside as the code that it fixes: +it won't collapse needlessly long runs of fillers. We can enhance that +in the future if it ever becomes a problem. This commit documents that +limitation with a TODO comment in code, a small but meaningful +improvement over the prior situation. + +Currently the biggest flaw, which the next commit addresses, is that +because this increases the node size on 64-bit machines from 60 bytes to +68 bytes. 60 rounds up to 64, but 68 rounds up to 128. So we wind up +using twice as much memory per node, because of power-of-two +allocations, which is a big bummer. We'll need to figure something out +there. + +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + drivers/net/wireguard/allowedips.c | 132 ++++++++++++----------------- + drivers/net/wireguard/allowedips.h | 9 +- + 2 files changed, 57 insertions(+), 84 deletions(-) + +--- a/drivers/net/wireguard/allowedips.c ++++ b/drivers/net/wireguard/allowedips.c +@@ -66,60 +66,6 @@ static void root_remove_peer_lists(struc + } + } + +-static void walk_remove_by_peer(struct allowedips_node __rcu **top, +- struct wg_peer *peer, struct mutex *lock) +-{ +-#define REF(p) rcu_access_pointer(p) +-#define DEREF(p) rcu_dereference_protected(*(p), lockdep_is_held(lock)) +-#define PUSH(p) ({ \ +- WARN_ON(IS_ENABLED(DEBUG) && len >= 128); \ +- stack[len++] = p; \ +- }) +- +- struct allowedips_node __rcu **stack[128], **nptr; +- struct allowedips_node *node, *prev; +- unsigned int len; +- +- if (unlikely(!peer || !REF(*top))) +- return; +- +- for (prev = NULL, len = 0, PUSH(top); len > 0; prev = node) { +- nptr = stack[len - 1]; +- node = DEREF(nptr); +- if (!node) { +- --len; +- continue; +- } +- if (!prev || REF(prev->bit[0]) == node || +- REF(prev->bit[1]) == node) { +- if (REF(node->bit[0])) +- PUSH(&node->bit[0]); +- else if (REF(node->bit[1])) +- PUSH(&node->bit[1]); +- } else if (REF(node->bit[0]) == prev) { +- if (REF(node->bit[1])) +- PUSH(&node->bit[1]); +- } else { +- if (rcu_dereference_protected(node->peer, +- lockdep_is_held(lock)) == peer) { +- RCU_INIT_POINTER(node->peer, NULL); +- list_del_init(&node->peer_list); +- if (!node->bit[0] || !node->bit[1]) { +- rcu_assign_pointer(*nptr, DEREF( +- &node->bit[!REF(node->bit[0])])); +- kfree_rcu(node, rcu); +- node = DEREF(nptr); +- } +- } +- --len; +- } +- } +- +-#undef REF +-#undef DEREF +-#undef PUSH +-} +- + static unsigned int fls128(u64 a, u64 b) + { + return a ? fls64(a) + 64U : fls64(b); +@@ -224,6 +170,7 @@ static int add(struct allowedips_node __ + RCU_INIT_POINTER(node->peer, peer); + list_add_tail(&node->peer_list, &peer->allowedips_list); + copy_and_assign_cidr(node, key, cidr, bits); ++ rcu_assign_pointer(node->parent_bit, trie); + rcu_assign_pointer(*trie, node); + return 0; + } +@@ -243,9 +190,9 @@ static int add(struct allowedips_node __ + if (!node) { + down = rcu_dereference_protected(*trie, lockdep_is_held(lock)); + } else { +- down = rcu_dereference_protected(CHOOSE_NODE(node, key), +- lockdep_is_held(lock)); ++ down = rcu_dereference_protected(CHOOSE_NODE(node, key), lockdep_is_held(lock)); + if (!down) { ++ rcu_assign_pointer(newnode->parent_bit, &CHOOSE_NODE(node, key)); + rcu_assign_pointer(CHOOSE_NODE(node, key), newnode); + return 0; + } +@@ -254,29 +201,37 @@ static int add(struct allowedips_node __ + parent = node; + + if (newnode->cidr == cidr) { ++ rcu_assign_pointer(down->parent_bit, &CHOOSE_NODE(newnode, down->bits)); + rcu_assign_pointer(CHOOSE_NODE(newnode, down->bits), down); +- if (!parent) ++ if (!parent) { ++ rcu_assign_pointer(newnode->parent_bit, trie); + rcu_assign_pointer(*trie, newnode); +- else +- rcu_assign_pointer(CHOOSE_NODE(parent, newnode->bits), +- newnode); +- } else { +- node = kzalloc(sizeof(*node), GFP_KERNEL); +- if (unlikely(!node)) { +- list_del(&newnode->peer_list); +- kfree(newnode); +- return -ENOMEM; ++ } else { ++ rcu_assign_pointer(newnode->parent_bit, &CHOOSE_NODE(parent, newnode->bits)); ++ rcu_assign_pointer(CHOOSE_NODE(parent, newnode->bits), newnode); + } +- INIT_LIST_HEAD(&node->peer_list); +- copy_and_assign_cidr(node, newnode->bits, cidr, bits); ++ return 0; ++ } ++ ++ node = kzalloc(sizeof(*node), GFP_KERNEL); ++ if (unlikely(!node)) { ++ list_del(&newnode->peer_list); ++ kfree(newnode); ++ return -ENOMEM; ++ } ++ INIT_LIST_HEAD(&node->peer_list); ++ copy_and_assign_cidr(node, newnode->bits, cidr, bits); + +- rcu_assign_pointer(CHOOSE_NODE(node, down->bits), down); +- rcu_assign_pointer(CHOOSE_NODE(node, newnode->bits), newnode); +- if (!parent) +- rcu_assign_pointer(*trie, node); +- else +- rcu_assign_pointer(CHOOSE_NODE(parent, node->bits), +- node); ++ rcu_assign_pointer(down->parent_bit, &CHOOSE_NODE(node, down->bits)); ++ rcu_assign_pointer(CHOOSE_NODE(node, down->bits), down); ++ rcu_assign_pointer(newnode->parent_bit, &CHOOSE_NODE(node, newnode->bits)); ++ rcu_assign_pointer(CHOOSE_NODE(node, newnode->bits), newnode); ++ if (!parent) { ++ rcu_assign_pointer(node->parent_bit, trie); ++ rcu_assign_pointer(*trie, node); ++ } else { ++ rcu_assign_pointer(node->parent_bit, &CHOOSE_NODE(parent, node->bits)); ++ rcu_assign_pointer(CHOOSE_NODE(parent, node->bits), node); + } + return 0; + } +@@ -335,9 +290,30 @@ int wg_allowedips_insert_v6(struct allow + void wg_allowedips_remove_by_peer(struct allowedips *table, + struct wg_peer *peer, struct mutex *lock) + { ++ struct allowedips_node *node, *child, *tmp; ++ ++ if (list_empty(&peer->allowedips_list)) ++ return; + ++table->seq; +- walk_remove_by_peer(&table->root4, peer, lock); +- walk_remove_by_peer(&table->root6, peer, lock); ++ list_for_each_entry_safe(node, tmp, &peer->allowedips_list, peer_list) { ++ list_del_init(&node->peer_list); ++ RCU_INIT_POINTER(node->peer, NULL); ++ if (node->bit[0] && node->bit[1]) ++ continue; ++ child = rcu_dereference_protected( ++ node->bit[!rcu_access_pointer(node->bit[0])], ++ lockdep_is_held(lock)); ++ if (child) ++ child->parent_bit = node->parent_bit; ++ *rcu_dereference_protected(node->parent_bit, lockdep_is_held(lock)) = child; ++ kfree_rcu(node, rcu); ++ ++ /* TODO: Note that we currently don't walk up and down in order to ++ * free any potential filler nodes. This means that this function ++ * doesn't free up as much as it could, which could be revisited ++ * at some point. ++ */ ++ } + } + + int wg_allowedips_read_node(struct allowedips_node *node, u8 ip[16], u8 *cidr) +--- a/drivers/net/wireguard/allowedips.h ++++ b/drivers/net/wireguard/allowedips.h +@@ -15,14 +15,11 @@ struct wg_peer; + struct allowedips_node { + struct wg_peer __rcu *peer; + struct allowedips_node __rcu *bit[2]; +- /* While it may seem scandalous that we waste space for v4, +- * we're alloc'ing to the nearest power of 2 anyway, so this +- * doesn't actually make a difference. +- */ +- u8 bits[16] __aligned(__alignof(u64)); + u8 cidr, bit_at_a, bit_at_b, bitlen; ++ u8 bits[16] __aligned(__alignof(u64)); + +- /* Keep rarely used list at bottom to be beyond cache line. */ ++ /* Keep rarely used members at bottom to be beyond cache line. */ ++ struct allowedips_node *__rcu *parent_bit; /* XXX: this puts us at 68->128 bytes instead of 60->64 bytes!! */ + union { + struct list_head peer_list; + struct rcu_head rcu; diff --git a/target/linux/generic/backport-5.4/080-wireguard-0134-wireguard-allowedips-allocate-nodes-in-kmem_cache.patch b/target/linux/generic/backport-5.4/080-wireguard-0134-wireguard-allowedips-allocate-nodes-in-kmem_cache.patch new file mode 100644 index 0000000000..65b31b05f5 --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0134-wireguard-allowedips-allocate-nodes-in-kmem_cache.patch @@ -0,0 +1,173 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:37 +0200 +Subject: [PATCH] wireguard: allowedips: allocate nodes in kmem_cache + +commit dc680de28ca849dfe589dc15ac56d22505f0ef11 upstream. + +The previous commit moved from O(n) to O(1) for removal, but in the +process introduced an additional pointer member to a struct that +increased the size from 60 to 68 bytes, putting nodes in the 128-byte +slab. With deployed systems having as many as 2 million nodes, this +represents a significant doubling in memory usage (128 MiB -> 256 MiB). +Fix this by using our own kmem_cache, that's sized exactly right. This +also makes wireguard's memory usage more transparent in tools like +slabtop and /proc/slabinfo. + +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Suggested-by: Arnd Bergmann +Suggested-by: Matthew Wilcox +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + drivers/net/wireguard/allowedips.c | 31 ++++++++++++++++++++++++------ + drivers/net/wireguard/allowedips.h | 5 ++++- + drivers/net/wireguard/main.c | 10 +++++++++- + 3 files changed, 38 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireguard/allowedips.c ++++ b/drivers/net/wireguard/allowedips.c +@@ -6,6 +6,8 @@ + #include "allowedips.h" + #include "peer.h" + ++static struct kmem_cache *node_cache; ++ + static void swap_endian(u8 *dst, const u8 *src, u8 bits) + { + if (bits == 32) { +@@ -40,6 +42,11 @@ static void push_rcu(struct allowedips_n + } + } + ++static void node_free_rcu(struct rcu_head *rcu) ++{ ++ kmem_cache_free(node_cache, container_of(rcu, struct allowedips_node, rcu)); ++} ++ + static void root_free_rcu(struct rcu_head *rcu) + { + struct allowedips_node *node, *stack[128] = { +@@ -49,7 +56,7 @@ static void root_free_rcu(struct rcu_hea + while (len > 0 && (node = stack[--len])) { + push_rcu(stack, node->bit[0], &len); + push_rcu(stack, node->bit[1], &len); +- kfree(node); ++ kmem_cache_free(node_cache, node); + } + } + +@@ -164,7 +171,7 @@ static int add(struct allowedips_node __ + return -EINVAL; + + if (!rcu_access_pointer(*trie)) { +- node = kzalloc(sizeof(*node), GFP_KERNEL); ++ node = kmem_cache_zalloc(node_cache, GFP_KERNEL); + if (unlikely(!node)) + return -ENOMEM; + RCU_INIT_POINTER(node->peer, peer); +@@ -180,7 +187,7 @@ static int add(struct allowedips_node __ + return 0; + } + +- newnode = kzalloc(sizeof(*newnode), GFP_KERNEL); ++ newnode = kmem_cache_zalloc(node_cache, GFP_KERNEL); + if (unlikely(!newnode)) + return -ENOMEM; + RCU_INIT_POINTER(newnode->peer, peer); +@@ -213,10 +220,10 @@ static int add(struct allowedips_node __ + return 0; + } + +- node = kzalloc(sizeof(*node), GFP_KERNEL); ++ node = kmem_cache_zalloc(node_cache, GFP_KERNEL); + if (unlikely(!node)) { + list_del(&newnode->peer_list); +- kfree(newnode); ++ kmem_cache_free(node_cache, newnode); + return -ENOMEM; + } + INIT_LIST_HEAD(&node->peer_list); +@@ -306,7 +313,7 @@ void wg_allowedips_remove_by_peer(struct + if (child) + child->parent_bit = node->parent_bit; + *rcu_dereference_protected(node->parent_bit, lockdep_is_held(lock)) = child; +- kfree_rcu(node, rcu); ++ call_rcu(&node->rcu, node_free_rcu); + + /* TODO: Note that we currently don't walk up and down in order to + * free any potential filler nodes. This means that this function +@@ -350,4 +357,16 @@ struct wg_peer *wg_allowedips_lookup_src + return NULL; + } + ++int __init wg_allowedips_slab_init(void) ++{ ++ node_cache = KMEM_CACHE(allowedips_node, 0); ++ return node_cache ? 0 : -ENOMEM; ++} ++ ++void wg_allowedips_slab_uninit(void) ++{ ++ rcu_barrier(); ++ kmem_cache_destroy(node_cache); ++} ++ + #include "selftest/allowedips.c" +--- a/drivers/net/wireguard/allowedips.h ++++ b/drivers/net/wireguard/allowedips.h +@@ -19,7 +19,7 @@ struct allowedips_node { + u8 bits[16] __aligned(__alignof(u64)); + + /* Keep rarely used members at bottom to be beyond cache line. */ +- struct allowedips_node *__rcu *parent_bit; /* XXX: this puts us at 68->128 bytes instead of 60->64 bytes!! */ ++ struct allowedips_node *__rcu *parent_bit; + union { + struct list_head peer_list; + struct rcu_head rcu; +@@ -53,4 +53,7 @@ struct wg_peer *wg_allowedips_lookup_src + bool wg_allowedips_selftest(void); + #endif + ++int wg_allowedips_slab_init(void); ++void wg_allowedips_slab_uninit(void); ++ + #endif /* _WG_ALLOWEDIPS_H */ +--- a/drivers/net/wireguard/main.c ++++ b/drivers/net/wireguard/main.c +@@ -21,10 +21,15 @@ static int __init mod_init(void) + { + int ret; + ++ ret = wg_allowedips_slab_init(); ++ if (ret < 0) ++ goto err_allowedips; ++ + #ifdef DEBUG ++ ret = -ENOTRECOVERABLE; + if (!wg_allowedips_selftest() || !wg_packet_counter_selftest() || + !wg_ratelimiter_selftest()) +- return -ENOTRECOVERABLE; ++ goto err_peer; + #endif + wg_noise_init(); + +@@ -50,6 +55,8 @@ err_netlink: + err_device: + wg_peer_uninit(); + err_peer: ++ wg_allowedips_slab_uninit(); ++err_allowedips: + return ret; + } + +@@ -58,6 +65,7 @@ static void __exit mod_exit(void) + wg_genetlink_uninit(); + wg_device_uninit(); + wg_peer_uninit(); ++ wg_allowedips_slab_uninit(); + } + + module_init(mod_init); diff --git a/target/linux/generic/backport-5.4/080-wireguard-0135-wireguard-allowedips-free-empty-intermediate-nodes-w.patch b/target/linux/generic/backport-5.4/080-wireguard-0135-wireguard-allowedips-free-empty-intermediate-nodes-w.patch new file mode 100644 index 0000000000..c044ad25af --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0135-wireguard-allowedips-free-empty-intermediate-nodes-w.patch @@ -0,0 +1,521 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 4 Jun 2021 17:17:38 +0200 +Subject: [PATCH] wireguard: allowedips: free empty intermediate nodes when + removing single node + +commit bf7b042dc62a31f66d3a41dd4dfc7806f267b307 upstream. + +When removing single nodes, it's possible that that node's parent is an +empty intermediate node, in which case, it too should be removed. +Otherwise the trie fills up and never is fully emptied, leading to +gradual memory leaks over time for tries that are modified often. There +was originally code to do this, but was removed during refactoring in +2016 and never reworked. Now that we have proper parent pointers from +the previous commits, we can implement this properly. + +In order to reduce branching and expensive comparisons, we want to keep +the double pointer for parent assignment (which lets us easily chain up +to the root), but we still need to actually get the parent's base +address. So encode the bit number into the last two bits of the pointer, +and pack and unpack it as needed. This is a little bit clumsy but is the +fastest and less memory wasteful of the compromises. Note that we align +the root struct here to a minimum of 4, because it's embedded into a +larger struct, and we're relying on having the bottom two bits for our +flag, which would only be 16-bit aligned on m68k. + +The existing macro-based helpers were a bit unwieldy for adding the bit +packing to, so this commit replaces them with safer and clearer ordinary +functions. + +We add a test to the randomized/fuzzer part of the selftests, to free +the randomized tries by-peer, refuzz it, and repeat, until it's supposed +to be empty, and then then see if that actually resulted in the whole +thing being emptied. That combined with kmemcheck should hopefully make +sure this commit is doing what it should. Along the way this resulted in +various other cleanups of the tests and fixes for recent graphviz. + +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Cc: stable@vger.kernel.org +Signed-off-by: Jason A. Donenfeld +Signed-off-by: David S. Miller +Signed-off-by: Jason A. Donenfeld +--- + drivers/net/wireguard/allowedips.c | 102 ++++++------ + drivers/net/wireguard/allowedips.h | 4 +- + drivers/net/wireguard/selftest/allowedips.c | 162 ++++++++++---------- + 3 files changed, 137 insertions(+), 131 deletions(-) + +--- a/drivers/net/wireguard/allowedips.c ++++ b/drivers/net/wireguard/allowedips.c +@@ -30,8 +30,11 @@ static void copy_and_assign_cidr(struct + node->bitlen = bits; + memcpy(node->bits, src, bits / 8U); + } +-#define CHOOSE_NODE(parent, key) \ +- parent->bit[(key[parent->bit_at_a] >> parent->bit_at_b) & 1] ++ ++static inline u8 choose(struct allowedips_node *node, const u8 *key) ++{ ++ return (key[node->bit_at_a] >> node->bit_at_b) & 1; ++} + + static void push_rcu(struct allowedips_node **stack, + struct allowedips_node __rcu *p, unsigned int *len) +@@ -112,7 +115,7 @@ static struct allowedips_node *find_node + found = node; + if (node->cidr == bits) + break; +- node = rcu_dereference_bh(CHOOSE_NODE(node, key)); ++ node = rcu_dereference_bh(node->bit[choose(node, key)]); + } + return found; + } +@@ -144,8 +147,7 @@ static bool node_placement(struct allowe + u8 cidr, u8 bits, struct allowedips_node **rnode, + struct mutex *lock) + { +- struct allowedips_node *node = rcu_dereference_protected(trie, +- lockdep_is_held(lock)); ++ struct allowedips_node *node = rcu_dereference_protected(trie, lockdep_is_held(lock)); + struct allowedips_node *parent = NULL; + bool exact = false; + +@@ -155,13 +157,24 @@ static bool node_placement(struct allowe + exact = true; + break; + } +- node = rcu_dereference_protected(CHOOSE_NODE(parent, key), +- lockdep_is_held(lock)); ++ node = rcu_dereference_protected(parent->bit[choose(parent, key)], lockdep_is_held(lock)); + } + *rnode = parent; + return exact; + } + ++static inline void connect_node(struct allowedips_node **parent, u8 bit, struct allowedips_node *node) ++{ ++ node->parent_bit_packed = (unsigned long)parent | bit; ++ rcu_assign_pointer(*parent, node); ++} ++ ++static inline void choose_and_connect_node(struct allowedips_node *parent, struct allowedips_node *node) ++{ ++ u8 bit = choose(parent, node->bits); ++ connect_node(&parent->bit[bit], bit, node); ++} ++ + static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, + u8 cidr, struct wg_peer *peer, struct mutex *lock) + { +@@ -177,8 +190,7 @@ static int add(struct allowedips_node __ + RCU_INIT_POINTER(node->peer, peer); + list_add_tail(&node->peer_list, &peer->allowedips_list); + copy_and_assign_cidr(node, key, cidr, bits); +- rcu_assign_pointer(node->parent_bit, trie); +- rcu_assign_pointer(*trie, node); ++ connect_node(trie, 2, node); + return 0; + } + if (node_placement(*trie, key, cidr, bits, &node, lock)) { +@@ -197,10 +209,10 @@ static int add(struct allowedips_node __ + if (!node) { + down = rcu_dereference_protected(*trie, lockdep_is_held(lock)); + } else { +- down = rcu_dereference_protected(CHOOSE_NODE(node, key), lockdep_is_held(lock)); ++ const u8 bit = choose(node, key); ++ down = rcu_dereference_protected(node->bit[bit], lockdep_is_held(lock)); + if (!down) { +- rcu_assign_pointer(newnode->parent_bit, &CHOOSE_NODE(node, key)); +- rcu_assign_pointer(CHOOSE_NODE(node, key), newnode); ++ connect_node(&node->bit[bit], bit, newnode); + return 0; + } + } +@@ -208,15 +220,11 @@ static int add(struct allowedips_node __ + parent = node; + + if (newnode->cidr == cidr) { +- rcu_assign_pointer(down->parent_bit, &CHOOSE_NODE(newnode, down->bits)); +- rcu_assign_pointer(CHOOSE_NODE(newnode, down->bits), down); +- if (!parent) { +- rcu_assign_pointer(newnode->parent_bit, trie); +- rcu_assign_pointer(*trie, newnode); +- } else { +- rcu_assign_pointer(newnode->parent_bit, &CHOOSE_NODE(parent, newnode->bits)); +- rcu_assign_pointer(CHOOSE_NODE(parent, newnode->bits), newnode); +- } ++ choose_and_connect_node(newnode, down); ++ if (!parent) ++ connect_node(trie, 2, newnode); ++ else ++ choose_and_connect_node(parent, newnode); + return 0; + } + +@@ -229,17 +237,12 @@ static int add(struct allowedips_node __ + INIT_LIST_HEAD(&node->peer_list); + copy_and_assign_cidr(node, newnode->bits, cidr, bits); + +- rcu_assign_pointer(down->parent_bit, &CHOOSE_NODE(node, down->bits)); +- rcu_assign_pointer(CHOOSE_NODE(node, down->bits), down); +- rcu_assign_pointer(newnode->parent_bit, &CHOOSE_NODE(node, newnode->bits)); +- rcu_assign_pointer(CHOOSE_NODE(node, newnode->bits), newnode); +- if (!parent) { +- rcu_assign_pointer(node->parent_bit, trie); +- rcu_assign_pointer(*trie, node); +- } else { +- rcu_assign_pointer(node->parent_bit, &CHOOSE_NODE(parent, node->bits)); +- rcu_assign_pointer(CHOOSE_NODE(parent, node->bits), node); +- } ++ choose_and_connect_node(node, down); ++ choose_and_connect_node(node, newnode); ++ if (!parent) ++ connect_node(trie, 2, node); ++ else ++ choose_and_connect_node(parent, node); + return 0; + } + +@@ -297,7 +300,8 @@ int wg_allowedips_insert_v6(struct allow + void wg_allowedips_remove_by_peer(struct allowedips *table, + struct wg_peer *peer, struct mutex *lock) + { +- struct allowedips_node *node, *child, *tmp; ++ struct allowedips_node *node, *child, **parent_bit, *parent, *tmp; ++ bool free_parent; + + if (list_empty(&peer->allowedips_list)) + return; +@@ -307,19 +311,29 @@ void wg_allowedips_remove_by_peer(struct + RCU_INIT_POINTER(node->peer, NULL); + if (node->bit[0] && node->bit[1]) + continue; +- child = rcu_dereference_protected( +- node->bit[!rcu_access_pointer(node->bit[0])], +- lockdep_is_held(lock)); ++ child = rcu_dereference_protected(node->bit[!rcu_access_pointer(node->bit[0])], ++ lockdep_is_held(lock)); + if (child) +- child->parent_bit = node->parent_bit; +- *rcu_dereference_protected(node->parent_bit, lockdep_is_held(lock)) = child; ++ child->parent_bit_packed = node->parent_bit_packed; ++ parent_bit = (struct allowedips_node **)(node->parent_bit_packed & ~3UL); ++ *parent_bit = child; ++ parent = (void *)parent_bit - ++ offsetof(struct allowedips_node, bit[node->parent_bit_packed & 1]); ++ free_parent = !rcu_access_pointer(node->bit[0]) && ++ !rcu_access_pointer(node->bit[1]) && ++ (node->parent_bit_packed & 3) <= 1 && ++ !rcu_access_pointer(parent->peer); ++ if (free_parent) ++ child = rcu_dereference_protected( ++ parent->bit[!(node->parent_bit_packed & 1)], ++ lockdep_is_held(lock)); + call_rcu(&node->rcu, node_free_rcu); +- +- /* TODO: Note that we currently don't walk up and down in order to +- * free any potential filler nodes. This means that this function +- * doesn't free up as much as it could, which could be revisited +- * at some point. +- */ ++ if (!free_parent) ++ continue; ++ if (child) ++ child->parent_bit_packed = parent->parent_bit_packed; ++ *(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child; ++ call_rcu(&parent->rcu, node_free_rcu); + } + } + +--- a/drivers/net/wireguard/allowedips.h ++++ b/drivers/net/wireguard/allowedips.h +@@ -19,7 +19,7 @@ struct allowedips_node { + u8 bits[16] __aligned(__alignof(u64)); + + /* Keep rarely used members at bottom to be beyond cache line. */ +- struct allowedips_node *__rcu *parent_bit; ++ unsigned long parent_bit_packed; + union { + struct list_head peer_list; + struct rcu_head rcu; +@@ -30,7 +30,7 @@ struct allowedips { + struct allowedips_node __rcu *root4; + struct allowedips_node __rcu *root6; + u64 seq; +-}; ++} __aligned(4); /* We pack the lower 2 bits of &root, but m68k only gives 16-bit alignment. */ + + void wg_allowedips_init(struct allowedips *table); + void wg_allowedips_free(struct allowedips *table, struct mutex *mutex); +--- a/drivers/net/wireguard/selftest/allowedips.c ++++ b/drivers/net/wireguard/selftest/allowedips.c +@@ -19,32 +19,22 @@ + + #include + +-static __init void swap_endian_and_apply_cidr(u8 *dst, const u8 *src, u8 bits, +- u8 cidr) +-{ +- swap_endian(dst, src, bits); +- memset(dst + (cidr + 7) / 8, 0, bits / 8 - (cidr + 7) / 8); +- if (cidr) +- dst[(cidr + 7) / 8 - 1] &= ~0U << ((8 - (cidr % 8)) % 8); +-} +- + static __init void print_node(struct allowedips_node *node, u8 bits) + { + char *fmt_connection = KERN_DEBUG "\t\"%p/%d\" -> \"%p/%d\";\n"; +- char *fmt_declaration = KERN_DEBUG +- "\t\"%p/%d\"[style=%s, color=\"#%06x\"];\n"; ++ char *fmt_declaration = KERN_DEBUG "\t\"%p/%d\"[style=%s, color=\"#%06x\"];\n"; ++ u8 ip1[16], ip2[16], cidr1, cidr2; + char *style = "dotted"; +- u8 ip1[16], ip2[16]; + u32 color = 0; + ++ if (node == NULL) ++ return; + if (bits == 32) { + fmt_connection = KERN_DEBUG "\t\"%pI4/%d\" -> \"%pI4/%d\";\n"; +- fmt_declaration = KERN_DEBUG +- "\t\"%pI4/%d\"[style=%s, color=\"#%06x\"];\n"; ++ fmt_declaration = KERN_DEBUG "\t\"%pI4/%d\"[style=%s, color=\"#%06x\"];\n"; + } else if (bits == 128) { + fmt_connection = KERN_DEBUG "\t\"%pI6/%d\" -> \"%pI6/%d\";\n"; +- fmt_declaration = KERN_DEBUG +- "\t\"%pI6/%d\"[style=%s, color=\"#%06x\"];\n"; ++ fmt_declaration = KERN_DEBUG "\t\"%pI6/%d\"[style=%s, color=\"#%06x\"];\n"; + } + if (node->peer) { + hsiphash_key_t key = { { 0 } }; +@@ -55,24 +45,20 @@ static __init void print_node(struct all + hsiphash_1u32(0xabad1dea, &key) % 200; + style = "bold"; + } +- swap_endian_and_apply_cidr(ip1, node->bits, bits, node->cidr); +- printk(fmt_declaration, ip1, node->cidr, style, color); ++ wg_allowedips_read_node(node, ip1, &cidr1); ++ printk(fmt_declaration, ip1, cidr1, style, color); + if (node->bit[0]) { +- swap_endian_and_apply_cidr(ip2, +- rcu_dereference_raw(node->bit[0])->bits, bits, +- node->cidr); +- printk(fmt_connection, ip1, node->cidr, ip2, +- rcu_dereference_raw(node->bit[0])->cidr); +- print_node(rcu_dereference_raw(node->bit[0]), bits); ++ wg_allowedips_read_node(rcu_dereference_raw(node->bit[0]), ip2, &cidr2); ++ printk(fmt_connection, ip1, cidr1, ip2, cidr2); + } + if (node->bit[1]) { +- swap_endian_and_apply_cidr(ip2, +- rcu_dereference_raw(node->bit[1])->bits, +- bits, node->cidr); +- printk(fmt_connection, ip1, node->cidr, ip2, +- rcu_dereference_raw(node->bit[1])->cidr); +- print_node(rcu_dereference_raw(node->bit[1]), bits); ++ wg_allowedips_read_node(rcu_dereference_raw(node->bit[1]), ip2, &cidr2); ++ printk(fmt_connection, ip1, cidr1, ip2, cidr2); + } ++ if (node->bit[0]) ++ print_node(rcu_dereference_raw(node->bit[0]), bits); ++ if (node->bit[1]) ++ print_node(rcu_dereference_raw(node->bit[1]), bits); + } + + static __init void print_tree(struct allowedips_node __rcu *top, u8 bits) +@@ -121,8 +107,8 @@ static __init inline union nf_inet_addr + { + union nf_inet_addr mask; + +- memset(&mask, 0x00, 128 / 8); +- memset(&mask, 0xff, cidr / 8); ++ memset(&mask, 0, sizeof(mask)); ++ memset(&mask.all, 0xff, cidr / 8); + if (cidr % 32) + mask.all[cidr / 32] = (__force u32)htonl( + (0xFFFFFFFFUL << (32 - (cidr % 32))) & 0xFFFFFFFFUL); +@@ -149,42 +135,36 @@ horrible_mask_self(struct horrible_allow + } + + static __init inline bool +-horrible_match_v4(const struct horrible_allowedips_node *node, +- struct in_addr *ip) ++horrible_match_v4(const struct horrible_allowedips_node *node, struct in_addr *ip) + { + return (ip->s_addr & node->mask.ip) == node->ip.ip; + } + + static __init inline bool +-horrible_match_v6(const struct horrible_allowedips_node *node, +- struct in6_addr *ip) ++horrible_match_v6(const struct horrible_allowedips_node *node, struct in6_addr *ip) + { +- return (ip->in6_u.u6_addr32[0] & node->mask.ip6[0]) == +- node->ip.ip6[0] && +- (ip->in6_u.u6_addr32[1] & node->mask.ip6[1]) == +- node->ip.ip6[1] && +- (ip->in6_u.u6_addr32[2] & node->mask.ip6[2]) == +- node->ip.ip6[2] && ++ return (ip->in6_u.u6_addr32[0] & node->mask.ip6[0]) == node->ip.ip6[0] && ++ (ip->in6_u.u6_addr32[1] & node->mask.ip6[1]) == node->ip.ip6[1] && ++ (ip->in6_u.u6_addr32[2] & node->mask.ip6[2]) == node->ip.ip6[2] && + (ip->in6_u.u6_addr32[3] & node->mask.ip6[3]) == node->ip.ip6[3]; + } + + static __init void +-horrible_insert_ordered(struct horrible_allowedips *table, +- struct horrible_allowedips_node *node) ++horrible_insert_ordered(struct horrible_allowedips *table, struct horrible_allowedips_node *node) + { + struct horrible_allowedips_node *other = NULL, *where = NULL; + u8 my_cidr = horrible_mask_to_cidr(node->mask); + + hlist_for_each_entry(other, &table->head, table) { +- if (!memcmp(&other->mask, &node->mask, +- sizeof(union nf_inet_addr)) && +- !memcmp(&other->ip, &node->ip, +- sizeof(union nf_inet_addr)) && +- other->ip_version == node->ip_version) { ++ if (other->ip_version == node->ip_version && ++ !memcmp(&other->mask, &node->mask, sizeof(union nf_inet_addr)) && ++ !memcmp(&other->ip, &node->ip, sizeof(union nf_inet_addr))) { + other->value = node->value; + kfree(node); + return; + } ++ } ++ hlist_for_each_entry(other, &table->head, table) { + where = other; + if (horrible_mask_to_cidr(other->mask) <= my_cidr) + break; +@@ -201,8 +181,7 @@ static __init int + horrible_allowedips_insert_v4(struct horrible_allowedips *table, + struct in_addr *ip, u8 cidr, void *value) + { +- struct horrible_allowedips_node *node = kzalloc(sizeof(*node), +- GFP_KERNEL); ++ struct horrible_allowedips_node *node = kzalloc(sizeof(*node), GFP_KERNEL); + + if (unlikely(!node)) + return -ENOMEM; +@@ -219,8 +198,7 @@ static __init int + horrible_allowedips_insert_v6(struct horrible_allowedips *table, + struct in6_addr *ip, u8 cidr, void *value) + { +- struct horrible_allowedips_node *node = kzalloc(sizeof(*node), +- GFP_KERNEL); ++ struct horrible_allowedips_node *node = kzalloc(sizeof(*node), GFP_KERNEL); + + if (unlikely(!node)) + return -ENOMEM; +@@ -234,39 +212,43 @@ horrible_allowedips_insert_v6(struct hor + } + + static __init void * +-horrible_allowedips_lookup_v4(struct horrible_allowedips *table, +- struct in_addr *ip) ++horrible_allowedips_lookup_v4(struct horrible_allowedips *table, struct in_addr *ip) + { + struct horrible_allowedips_node *node; +- void *ret = NULL; + + hlist_for_each_entry(node, &table->head, table) { +- if (node->ip_version != 4) +- continue; +- if (horrible_match_v4(node, ip)) { +- ret = node->value; +- break; +- } ++ if (node->ip_version == 4 && horrible_match_v4(node, ip)) ++ return node->value; + } +- return ret; ++ return NULL; + } + + static __init void * +-horrible_allowedips_lookup_v6(struct horrible_allowedips *table, +- struct in6_addr *ip) ++horrible_allowedips_lookup_v6(struct horrible_allowedips *table, struct in6_addr *ip) + { + struct horrible_allowedips_node *node; +- void *ret = NULL; + + hlist_for_each_entry(node, &table->head, table) { +- if (node->ip_version != 6) ++ if (node->ip_version == 6 && horrible_match_v6(node, ip)) ++ return node->value; ++ } ++ return NULL; ++} ++ ++ ++static __init void ++horrible_allowedips_remove_by_value(struct horrible_allowedips *table, void *value) ++{ ++ struct horrible_allowedips_node *node; ++ struct hlist_node *h; ++ ++ hlist_for_each_entry_safe(node, h, &table->head, table) { ++ if (node->value != value) + continue; +- if (horrible_match_v6(node, ip)) { +- ret = node->value; +- break; +- } ++ hlist_del(&node->table); ++ kfree(node); + } +- return ret; ++ + } + + static __init bool randomized_test(void) +@@ -397,23 +379,33 @@ static __init bool randomized_test(void) + print_tree(t.root6, 128); + } + +- for (i = 0; i < NUM_QUERIES; ++i) { +- prandom_bytes(ip, 4); +- if (lookup(t.root4, 32, ip) != +- horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip)) { +- pr_err("allowedips random self-test: FAIL\n"); +- goto free; ++ for (j = 0;; ++j) { ++ for (i = 0; i < NUM_QUERIES; ++i) { ++ prandom_bytes(ip, 4); ++ if (lookup(t.root4, 32, ip) != horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip)) { ++ horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip); ++ pr_err("allowedips random v4 self-test: FAIL\n"); ++ goto free; ++ } ++ prandom_bytes(ip, 16); ++ if (lookup(t.root6, 128, ip) != horrible_allowedips_lookup_v6(&h, (struct in6_addr *)ip)) { ++ pr_err("allowedips random v6 self-test: FAIL\n"); ++ goto free; ++ } + } ++ if (j >= NUM_PEERS) ++ break; ++ mutex_lock(&mutex); ++ wg_allowedips_remove_by_peer(&t, peers[j], &mutex); ++ mutex_unlock(&mutex); ++ horrible_allowedips_remove_by_value(&h, peers[j]); + } + +- for (i = 0; i < NUM_QUERIES; ++i) { +- prandom_bytes(ip, 16); +- if (lookup(t.root6, 128, ip) != +- horrible_allowedips_lookup_v6(&h, (struct in6_addr *)ip)) { +- pr_err("allowedips random self-test: FAIL\n"); +- goto free; +- } ++ if (t.root4 || t.root6) { ++ pr_err("allowedips random self-test removal: FAIL\n"); ++ goto free; + } ++ + ret = true; + + free: diff --git a/target/linux/generic/backport-5.4/765-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch b/target/linux/generic/backport-5.4/765-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch new file mode 100644 index 0000000000..7ec26899f9 --- /dev/null +++ b/target/linux/generic/backport-5.4/765-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch @@ -0,0 +1,85 @@ +From 9d5ef190e5615a7b63af89f88c4106a5bc127974 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Fri, 5 Feb 2021 15:37:10 +0200 +Subject: [PATCH] net: dsa: automatically bring up DSA master when opening user + port + +DSA wants the master interface to be open before the user port is due to +historical reasons. The promiscuity of interfaces that are down used to +have issues, as referenced Lennert Buytenhek in commit df02c6ff2e39 +("dsa: fix master interface allmulti/promisc handling"). + +The bugfix mentioned there, commit b6c40d68ff64 ("net: only invoke +dev->change_rx_flags when device is UP"), was basically a "don't do +that" approach to working around the promiscuity while down issue. + +Further work done by Vlad Yasevich in commit d2615bf45069 ("net: core: +Always propagate flag changes to interfaces") has resolved the +underlying issue, and it is strictly up to the DSA and 8021q drivers +now, it is no longer mandated by the networking core that the master +interface must be up when changing its promiscuity. + +From DSA's point of view, deciding to error out in dsa_slave_open +because the master isn't up is +(a) a bad user experience and +(b) knocking at an open door. +Even if there still was an issue with promiscuity while down, DSA could +still just open the master and avoid it. + +Doing it this way has the additional benefit that user space can now +remove DSA-specific workarounds, like systemd-networkd with BindCarrier: +https://github.com/systemd/systemd/issues/7478 + +And we can finally remove one of the 2 bullets in the "Common pitfalls +using DSA setups" chapter. + +Tested with two cascaded DSA switches: + +$ ip link set sw0p2 up +fsl_enetc 0000:00:00.2 eno2: configuring for fixed/internal link mode +fsl_enetc 0000:00:00.2 eno2: Link is Up - 1Gbps/Full - flow control rx/tx +mscc_felix 0000:00:00.5 swp0: configuring for fixed/sgmii link mode +mscc_felix 0000:00:00.5 swp0: Link is Up - 1Gbps/Full - flow control off +8021q: adding VLAN 0 to HW filter on device swp0 +sja1105 spi2.0 sw0p2: configuring for phy/rgmii-id link mode +IPv6: ADDRCONF(NETDEV_CHANGE): eno2: link becomes ready +IPv6: ADDRCONF(NETDEV_CHANGE): swp0: link becomes ready + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + Documentation/networking/dsa/dsa.rst | 4 ---- + net/dsa/slave.c | 7 +++++-- + 2 files changed, 5 insertions(+), 6 deletions(-) + +--- a/Documentation/networking/dsa/dsa.rst ++++ b/Documentation/networking/dsa/dsa.rst +@@ -273,10 +273,6 @@ will not make us go through the switch t + the Ethernet switch on the other end, expecting a tag will typically drop this + frame. + +-Slave network devices check that the master network device is UP before allowing +-you to administratively bring UP these slave network devices. A common +-configuration mistake is forgetting to bring UP the master network device first. +- + Interactions with other subsystems + ================================== + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -70,8 +70,11 @@ static int dsa_slave_open(struct net_dev + struct dsa_port *dp = dsa_slave_to_port(dev); + int err; + +- if (!(master->flags & IFF_UP)) +- return -ENETDOWN; ++ err = dev_open(master, NULL); ++ if (err < 0) { ++ netdev_err(dev, "failed to open master %s\n", master->name); ++ goto out; ++ } + + if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) { + err = dev_uc_add(master, dev->dev_addr); diff --git a/target/linux/generic/backport-5.4/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch b/target/linux/generic/backport-5.4/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch index 297175855b..9ec1a226b5 100644 --- a/target/linux/generic/backport-5.4/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch +++ b/target/linux/generic/backport-5.4/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch @@ -25,7 +25,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1592,7 +1592,9 @@ static void dsa_slave_switchdev_event_wo +@@ -1595,7 +1595,9 @@ static void dsa_slave_switchdev_event_wo err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid); if (err) { @@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski break; } fdb_info->offloaded = true; -@@ -1607,9 +1609,11 @@ static void dsa_slave_switchdev_event_wo +@@ -1610,9 +1612,11 @@ static void dsa_slave_switchdev_event_wo err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid); if (err) { diff --git a/target/linux/generic/backport-5.4/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch b/target/linux/generic/backport-5.4/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch index e9b74053e0..bc29fbecc4 100644 --- a/target/linux/generic/backport-5.4/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch +++ b/target/linux/generic/backport-5.4/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch @@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski struct sk_buff * (*xmit)(struct sk_buff *skb, --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1567,76 +1567,66 @@ static int dsa_slave_netdevice_event(str +@@ -1570,76 +1570,66 @@ static int dsa_slave_netdevice_event(str return NOTIFY_DONE; } @@ -167,7 +167,7 @@ Signed-off-by: Jakub Kicinski } /* Called under rcu_read_lock() */ -@@ -1644,7 +1634,9 @@ static int dsa_slave_switchdev_event(str +@@ -1647,7 +1637,9 @@ static int dsa_slave_switchdev_event(str unsigned long event, void *ptr) { struct net_device *dev = switchdev_notifier_info_to_dev(ptr); @@ -177,7 +177,7 @@ Signed-off-by: Jakub Kicinski int err; if (event == SWITCHDEV_PORT_ATTR_SET) { -@@ -1657,20 +1649,32 @@ static int dsa_slave_switchdev_event(str +@@ -1660,20 +1652,32 @@ static int dsa_slave_switchdev_event(str if (!dsa_slave_dev_check(dev)) return NOTIFY_DONE; @@ -213,7 +213,7 @@ Signed-off-by: Jakub Kicinski dev_hold(dev); break; default: -@@ -1680,10 +1684,6 @@ static int dsa_slave_switchdev_event(str +@@ -1683,10 +1687,6 @@ static int dsa_slave_switchdev_event(str dsa_schedule_work(&switchdev_work->work); return NOTIFY_OK; diff --git a/target/linux/generic/backport-5.4/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch b/target/linux/generic/backport-5.4/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch index b46cd7545e..50c7a08590 100644 --- a/target/linux/generic/backport-5.4/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch +++ b/target/linux/generic/backport-5.4/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch @@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1639,31 +1639,29 @@ static int dsa_slave_switchdev_event(str +@@ -1642,31 +1642,29 @@ static int dsa_slave_switchdev_event(str struct dsa_port *dp; int err; @@ -68,7 +68,7 @@ Signed-off-by: Jakub Kicinski fdb_info = ptr; if (!fdb_info->added_by_user) { -@@ -1676,13 +1674,12 @@ static int dsa_slave_switchdev_event(str +@@ -1679,13 +1677,12 @@ static int dsa_slave_switchdev_event(str switchdev_work->vid = fdb_info->vid; dev_hold(dev); diff --git a/target/linux/generic/backport-5.4/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch b/target/linux/generic/backport-5.4/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch index d38c3901cf..dcb6bbdc49 100644 --- a/target/linux/generic/backport-5.4/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch +++ b/target/linux/generic/backport-5.4/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch @@ -30,7 +30,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1652,6 +1652,9 @@ static int dsa_slave_switchdev_event(str +@@ -1655,6 +1655,9 @@ static int dsa_slave_switchdev_event(str dp = dsa_slave_to_port(dev); diff --git a/target/linux/generic/backport-5.4/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch b/target/linux/generic/backport-5.4/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch index 4aa85e5750..b49d11a776 100644 --- a/target/linux/generic/backport-5.4/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch +++ b/target/linux/generic/backport-5.4/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch @@ -172,7 +172,7 @@ Signed-off-by: DENG Qingfang */ --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1629,6 +1629,25 @@ static void dsa_slave_switchdev_event_wo +@@ -1632,6 +1632,25 @@ static void dsa_slave_switchdev_event_wo dev_put(dp->slave); } @@ -198,7 +198,7 @@ Signed-off-by: DENG Qingfang /* Called under rcu_read_lock() */ static int dsa_slave_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) -@@ -1647,10 +1666,37 @@ static int dsa_slave_switchdev_event(str +@@ -1650,10 +1669,37 @@ static int dsa_slave_switchdev_event(str return notifier_from_errno(err); case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE: @@ -239,7 +239,7 @@ Signed-off-by: DENG Qingfang if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del) return NOTIFY_DONE; -@@ -1665,18 +1711,13 @@ static int dsa_slave_switchdev_event(str +@@ -1668,18 +1714,13 @@ static int dsa_slave_switchdev_event(str switchdev_work->port = dp->index; switchdev_work->event = event; diff --git a/target/linux/generic/config-5.10 b/target/linux/generic/config-5.10 index d14d2be753..b00073d1f6 100644 --- a/target/linux/generic/config-5.10 +++ b/target/linux/generic/config-5.10 @@ -4167,6 +4167,7 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NVMEM_SYSFS is not set # CONFIG_NVME_FC is not set # CONFIG_NVME_TARGET is not set +# CONFIG_NVME_TCP is not set # CONFIG_NVRAM is not set # CONFIG_NV_TCO is not set # CONFIG_NXP_STB220 is not set diff --git a/target/linux/generic/hack-5.10/221-module_exports.patch b/target/linux/generic/hack-5.10/221-module_exports.patch index 07885408f1..e6854138e7 100644 --- a/target/linux/generic/hack-5.10/221-module_exports.patch +++ b/target/linux/generic/hack-5.10/221-module_exports.patch @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau } \ \ /* __*init sections */ \ -@@ -1017,6 +1027,8 @@ +@@ -1018,6 +1028,8 @@ #define COMMON_DISCARDS \ SANITIZER_DISCARDS \ diff --git a/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch b/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch index 145efa57c3..759f1adda4 100644 --- a/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch +++ b/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch @@ -18,7 +18,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2191,10 +2191,12 @@ static int dsa_slave_switchdev_event(str +@@ -2194,10 +2194,12 @@ static int dsa_slave_switchdev_event(str fdb_info = ptr; if (dsa_slave_dev_check(dev)) { diff --git a/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch b/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch index 53f1232955..0ad751cc5d 100644 --- a/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch +++ b/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch @@ -15,7 +15,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2205,7 +2205,11 @@ static int dsa_slave_switchdev_event(str +@@ -2208,7 +2208,11 @@ static int dsa_slave_switchdev_event(str struct net_device *br_dev; struct dsa_slave_priv *p; diff --git a/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch b/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch index 49418d3b86..e1daf61730 100644 --- a/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch +++ b/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch @@ -28,7 +28,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2198,9 +2198,12 @@ static int dsa_slave_switchdev_event(str +@@ -2201,9 +2201,12 @@ static int dsa_slave_switchdev_event(str else if (!fdb_info->added_by_user) return NOTIFY_OK; } else { @@ -44,7 +44,7 @@ Signed-off-by: Tobias Waldekranz */ struct net_device *br_dev; struct dsa_slave_priv *p; -@@ -2222,7 +2225,8 @@ static int dsa_slave_switchdev_event(str +@@ -2225,7 +2228,8 @@ static int dsa_slave_switchdev_event(str dp = p->dp->cpu_dp; diff --git a/target/linux/generic/pending-5.4/180-net-phy-at803x-add-support-for-AT8032.patch b/target/linux/generic/pending-5.4/180-net-phy-at803x-add-support-for-AT8032.patch index 9b88282442..3fe25c2b2b 100644 --- a/target/linux/generic/pending-5.4/180-net-phy-at803x-add-support-for-AT8032.patch +++ b/target/linux/generic/pending-5.4/180-net-phy-at803x-add-support-for-AT8032.patch @@ -17,9 +17,9 @@ Signed-off-by: Felix Fietkau #define AT803X_PHY_ID_MASK 0xffffffef +#define AT8032_PHY_ID_MASK 0xffffffff - MODULE_DESCRIPTION("Atheros 803x PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi"); -@@ -314,7 +316,7 @@ static int at803x_config_intr(struct phy + #define AT803X_PAGE_FIBER 0 + #define AT803X_PAGE_COPPER 1 +@@ -357,7 +359,7 @@ static int at803x_config_intr(struct phy static void at803x_link_change_notify(struct phy_device *phydev) { /* @@ -28,7 +28,7 @@ Signed-off-by: Felix Fietkau * signalled. This is necessary to circumvent a hardware bug that * occurs when the cable is unplugged while TX packets are pending * in the FIFO. In such cases, the FIFO enters an error mode it -@@ -471,6 +473,24 @@ static struct phy_driver at803x_driver[] +@@ -516,6 +518,24 @@ static struct phy_driver at803x_driver[] .aneg_done = at803x_aneg_done, .ack_interrupt = &at803x_ack_interrupt, .config_intr = &at803x_config_intr, @@ -53,7 +53,7 @@ Signed-off-by: Felix Fietkau } }; module_phy_driver(at803x_driver); -@@ -478,6 +498,7 @@ module_phy_driver(at803x_driver); +@@ -523,6 +543,7 @@ module_phy_driver(at803x_driver); static struct mdio_device_id __maybe_unused atheros_tbl[] = { { ATH8030_PHY_ID, AT803X_PHY_ID_MASK }, { ATH8031_PHY_ID, AT803X_PHY_ID_MASK }, diff --git a/target/linux/generic/pending-5.4/647-net-dsa-support-hardware-flow-table-offload.patch b/target/linux/generic/pending-5.4/647-net-dsa-support-hardware-flow-table-offload.patch index 85c606c455..91aae5b65c 100644 --- a/target/linux/generic/pending-5.4/647-net-dsa-support-hardware-flow-table-offload.patch +++ b/target/linux/generic/pending-5.4/647-net-dsa-support-hardware-flow-table-offload.patch @@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau #include "dsa_priv.h" -@@ -1223,6 +1227,27 @@ static struct devlink_port *dsa_slave_ge +@@ -1226,6 +1230,27 @@ static struct devlink_port *dsa_slave_ge return dp->ds->devlink ? &dp->devlink_port : NULL; } @@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau static const struct net_device_ops dsa_slave_netdev_ops = { .ndo_open = dsa_slave_open, .ndo_stop = dsa_slave_close, -@@ -1247,6 +1272,9 @@ static const struct net_device_ops dsa_s +@@ -1250,6 +1275,9 @@ static const struct net_device_ops dsa_s .ndo_vlan_rx_add_vid = dsa_slave_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = dsa_slave_vlan_rx_kill_vid, .ndo_get_devlink_port = dsa_slave_get_devlink_port, diff --git a/target/linux/generic/pending-5.4/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch b/target/linux/generic/pending-5.4/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch index e1a7a0e448..d73481fcc0 100644 --- a/target/linux/generic/pending-5.4/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch +++ b/target/linux/generic/pending-5.4/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch @@ -18,7 +18,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1697,10 +1697,12 @@ static int dsa_slave_switchdev_event(str +@@ -1700,10 +1700,12 @@ static int dsa_slave_switchdev_event(str fdb_info = ptr; if (dsa_slave_dev_check(dev)) { diff --git a/target/linux/generic/pending-5.4/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch b/target/linux/generic/pending-5.4/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch index f985adf736..e66aa93488 100644 --- a/target/linux/generic/pending-5.4/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch +++ b/target/linux/generic/pending-5.4/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch @@ -15,7 +15,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1711,7 +1711,11 @@ static int dsa_slave_switchdev_event(str +@@ -1714,7 +1714,11 @@ static int dsa_slave_switchdev_event(str struct net_device *br_dev; struct dsa_slave_priv *p; diff --git a/target/linux/generic/pending-5.4/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch b/target/linux/generic/pending-5.4/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch index 984d9805f6..5305e3d114 100644 --- a/target/linux/generic/pending-5.4/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch +++ b/target/linux/generic/pending-5.4/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch @@ -28,7 +28,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1704,9 +1704,12 @@ static int dsa_slave_switchdev_event(str +@@ -1707,9 +1707,12 @@ static int dsa_slave_switchdev_event(str else if (!fdb_info->added_by_user) return NOTIFY_OK; } else { @@ -44,7 +44,7 @@ Signed-off-by: Tobias Waldekranz */ struct net_device *br_dev; struct dsa_slave_priv *p; -@@ -1728,7 +1731,8 @@ static int dsa_slave_switchdev_event(str +@@ -1731,7 +1734,8 @@ static int dsa_slave_switchdev_event(str dp = p->dp->cpu_dp; diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network index f5796df4a0..b7137122f1 100644 --- a/target/linux/ipq40xx/base-files/etc/board.d/02_network +++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network @@ -67,7 +67,7 @@ ipq40xx_setup_interfaces() ;; avm,fritzbox-7530) ucidef_add_switch "switch0" \ - "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" + "0u@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" ;; avm,fritzrepeater-3000) ucidef_add_switch "switch0" \ diff --git a/target/linux/ramips/dts/mt7620a_alfa-network_ac1200rm.dts b/target/linux/ramips/dts/mt7620a_alfa-network_ac1200rm.dts index 27b6896cec..752a940cd8 100644 --- a/target/linux/ramips/dts/mt7620a_alfa-network_ac1200rm.dts +++ b/target/linux/ramips/dts/mt7620a_alfa-network_ac1200rm.dts @@ -72,10 +72,6 @@ status = "okay"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &ohci { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7620a_alfa-network_r36m-e4g.dts b/target/linux/ramips/dts/mt7620a_alfa-network_r36m-e4g.dts index 58386a9ac7..0991ae8447 100644 --- a/target/linux/ramips/dts/mt7620a_alfa-network_r36m-e4g.dts +++ b/target/linux/ramips/dts/mt7620a_alfa-network_r36m-e4g.dts @@ -141,10 +141,6 @@ status = "okay"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &i2c { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7620a_alfa-network_tube-e4g.dts b/target/linux/ramips/dts/mt7620a_alfa-network_tube-e4g.dts index 30a0201c39..ca58d780f4 100644 --- a/target/linux/ramips/dts/mt7620a_alfa-network_tube-e4g.dts +++ b/target/linux/ramips/dts/mt7620a_alfa-network_tube-e4g.dts @@ -114,10 +114,6 @@ status = "okay"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &ohci { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7620a_asus_rp-n53.dts b/target/linux/ramips/dts/mt7620a_asus_rp-n53.dts index 3cb9142c38..4c72c64272 100644 --- a/target/linux/ramips/dts/mt7620a_asus_rp-n53.dts +++ b/target/linux/ramips/dts/mt7620a_asus_rp-n53.dts @@ -153,8 +153,7 @@ }; }; -&gsw { - mediatek,port4 = "ephy"; +ðernet { pinctrl-names = "default"; pinctrl-0 = <&ephy_pins>; }; diff --git a/target/linux/ramips/dts/mt7620a_buffalo_whr-1166d.dts b/target/linux/ramips/dts/mt7620a_buffalo_whr-1166d.dts index 196bbde726..93a09f99c3 100644 --- a/target/linux/ramips/dts/mt7620a_buffalo_whr-1166d.dts +++ b/target/linux/ramips/dts/mt7620a_buffalo_whr-1166d.dts @@ -157,10 +157,6 @@ }; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&factory 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_buffalo_whr-300hp2.dts b/target/linux/ramips/dts/mt7620a_buffalo_whr-300hp2.dts index ed2e03d6cf..95152bc41a 100644 --- a/target/linux/ramips/dts/mt7620a_buffalo_whr-300hp2.dts +++ b/target/linux/ramips/dts/mt7620a_buffalo_whr-300hp2.dts @@ -144,10 +144,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&factory 0x0>; pinctrl-names = "default"; diff --git a/target/linux/ramips/dts/mt7620a_buffalo_whr-600d.dts b/target/linux/ramips/dts/mt7620a_buffalo_whr-600d.dts index b799a98e56..226967763b 100644 --- a/target/linux/ramips/dts/mt7620a_buffalo_whr-600d.dts +++ b/target/linux/ramips/dts/mt7620a_buffalo_whr-600d.dts @@ -144,10 +144,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&factory 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_cameo_810.dtsi b/target/linux/ramips/dts/mt7620a_cameo_810.dtsi index c3f3267d38..70407449db 100644 --- a/target/linux/ramips/dts/mt7620a_cameo_810.dtsi +++ b/target/linux/ramips/dts/mt7620a_cameo_810.dtsi @@ -132,10 +132,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &gpio2 { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7620a_dlink_dch-m225.dts b/target/linux/ramips/dts/mt7620a_dlink_dch-m225.dts index 63667da281..0c9f56875e 100644 --- a/target/linux/ramips/dts/mt7620a_dlink_dch-m225.dts +++ b/target/linux/ramips/dts/mt7620a_dlink_dch-m225.dts @@ -171,10 +171,6 @@ mtd-mac-address = <&factory 0x4>; }; -&gsw { - ralink,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&factory 0x0>; pinctrl-names = "default"; diff --git a/target/linux/ramips/dts/mt7620a_dlink_dir-510l.dts b/target/linux/ramips/dts/mt7620a_dlink_dir-510l.dts index f4db67648a..774d90c79d 100644 --- a/target/linux/ramips/dts/mt7620a_dlink_dir-510l.dts +++ b/target/linux/ramips/dts/mt7620a_dlink_dir-510l.dts @@ -120,10 +120,6 @@ }; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &state_default { default { groups = "i2c", "uartf"; diff --git a/target/linux/ramips/dts/mt7620a_dlink_dwr-118-a1.dts b/target/linux/ramips/dts/mt7620a_dlink_dwr-118-a1.dts index bacebee8e1..b86ab1449b 100644 --- a/target/linux/ramips/dts/mt7620a_dlink_dwr-118-a1.dts +++ b/target/linux/ramips/dts/mt7620a_dlink_dwr-118-a1.dts @@ -185,5 +185,6 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; diff --git a/target/linux/ramips/dts/mt7620a_dlink_dwr-118-a2.dts b/target/linux/ramips/dts/mt7620a_dlink_dwr-118-a2.dts index 0b124e67de..b0dd31cafc 100644 --- a/target/linux/ramips/dts/mt7620a_dlink_dwr-118-a2.dts +++ b/target/linux/ramips/dts/mt7620a_dlink_dwr-118-a2.dts @@ -173,6 +173,6 @@ }; &gsw { - mediatek,port4 = "gmac"; - mediatek,ephy-base-address = /bits/ 16 < 2 >; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <2>; }; diff --git a/target/linux/ramips/dts/mt7620a_dovado_tiny-ac.dts b/target/linux/ramips/dts/mt7620a_dovado_tiny-ac.dts index 9450596f1b..ba1a2becda 100644 --- a/target/linux/ramips/dts/mt7620a_dovado_tiny-ac.dts +++ b/target/linux/ramips/dts/mt7620a_dovado_tiny-ac.dts @@ -135,7 +135,8 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; &pcie { diff --git a/target/linux/ramips/dts/mt7620a_edimax_br-6478ac-v2.dts b/target/linux/ramips/dts/mt7620a_edimax_br-6478ac-v2.dts index e7af34aa8e..03a4c96f6b 100644 --- a/target/linux/ramips/dts/mt7620a_edimax_br-6478ac-v2.dts +++ b/target/linux/ramips/dts/mt7620a_edimax_br-6478ac-v2.dts @@ -178,7 +178,7 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,ephy-base = /bits/ 8 <12>; }; &wmac { diff --git a/target/linux/ramips/dts/mt7620a_edimax_ew-7478apc.dts b/target/linux/ramips/dts/mt7620a_edimax_ew-7478apc.dts index 77d214e888..986b047e47 100644 --- a/target/linux/ramips/dts/mt7620a_edimax_ew-7478apc.dts +++ b/target/linux/ramips/dts/mt7620a_edimax_ew-7478apc.dts @@ -170,7 +170,7 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,ephy-base = /bits/ 8 <12>; }; &wmac { diff --git a/target/linux/ramips/dts/mt7620a_edimax_ew-747x.dtsi b/target/linux/ramips/dts/mt7620a_edimax_ew-747x.dtsi index d17cc090c2..6060fd99a6 100644 --- a/target/linux/ramips/dts/mt7620a_edimax_ew-747x.dtsi +++ b/target/linux/ramips/dts/mt7620a_edimax_ew-747x.dtsi @@ -155,8 +155,6 @@ mtd-mac-address = <&factory 0x4>; - mediatek,mdio-mode = <1>; - phy-reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; phy-reset-duration = <30>; @@ -202,7 +200,7 @@ }; &gsw { - mediatek,port5 = "gmac"; + mediatek,ephy-base = /bits/ 8 <8>; }; &wmac { diff --git a/target/linux/ramips/dts/mt7620a_engenius_esr600.dts b/target/linux/ramips/dts/mt7620a_engenius_esr600.dts index b8fe2f8cdb..ea895ac6ea 100644 --- a/target/linux/ramips/dts/mt7620a_engenius_esr600.dts +++ b/target/linux/ramips/dts/mt7620a_engenius_esr600.dts @@ -144,7 +144,6 @@ mdio-bus { status = "okay"; - mediatek,mdio-mode; ethernet-phy@0 { reg = <0>; @@ -155,11 +154,15 @@ 0x7c 0x0000007e /* PORT0 STATUS */ 0x0c 0x05600000 /* PORT6 PAD MODE CTRL */ 0x94 0x0000007e /* PORT6 STATUS */ - >; + >; }; }; }; +&gsw { + mediatek,ephy-base = /bits/ 8 <8>; +}; + &state_default { gpio { groups = "i2c", "uartf", "nd_sd", "wled"; diff --git a/target/linux/ramips/dts/mt7620a_fon_fon2601.dts b/target/linux/ramips/dts/mt7620a_fon_fon2601.dts index ee61c6e59e..373205e725 100644 --- a/target/linux/ramips/dts/mt7620a_fon_fon2601.dts +++ b/target/linux/ramips/dts/mt7620a_fon_fon2601.dts @@ -136,7 +136,8 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; &wmac { diff --git a/target/linux/ramips/dts/mt7620a_head-weblink_hdrm200.dts b/target/linux/ramips/dts/mt7620a_head-weblink_hdrm200.dts index a0ebe4fff5..7d807bff4b 100644 --- a/target/linux/ramips/dts/mt7620a_head-weblink_hdrm200.dts +++ b/target/linux/ramips/dts/mt7620a_head-weblink_hdrm200.dts @@ -149,6 +149,11 @@ }; }; +&gsw { + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; +}; + &wmac { ralink,mtd-eeprom = <&factory 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_iodata_wn-ac1167gr.dts b/target/linux/ramips/dts/mt7620a_iodata_wn-ac1167gr.dts index 7044a511bc..d59b481a61 100644 --- a/target/linux/ramips/dts/mt7620a_iodata_wn-ac1167gr.dts +++ b/target/linux/ramips/dts/mt7620a_iodata_wn-ac1167gr.dts @@ -184,6 +184,10 @@ }; }; +&gsw { + mediatek,ephy-base = /bits/ 8 <12>; +}; + &state_default { gpio { groups = "i2c", "uartf"; diff --git a/target/linux/ramips/dts/mt7620a_iptime_a1004ns.dts b/target/linux/ramips/dts/mt7620a_iptime_a1004ns.dts index 20d0557916..6270af3b15 100644 --- a/target/linux/ramips/dts/mt7620a_iptime_a1004ns.dts +++ b/target/linux/ramips/dts/mt7620a_iptime_a1004ns.dts @@ -101,3 +101,7 @@ }; }; }; + +&gsw { + mediatek,ephy-base = /bits/ 8 <12>; +}; diff --git a/target/linux/ramips/dts/mt7620a_lava_lr-25g001.dts b/target/linux/ramips/dts/mt7620a_lava_lr-25g001.dts index 962ef3371d..41d69d009b 100644 --- a/target/linux/ramips/dts/mt7620a_lava_lr-25g001.dts +++ b/target/linux/ramips/dts/mt7620a_lava_lr-25g001.dts @@ -115,9 +115,8 @@ mdio-bus { status = "okay"; - mediatek,mdio-mode = <1>; - phy0: ethernet-phy@0 { + ethernet-phy@0 { reg = <0>; phy-mode = "rgmii"; qca,ar8327-initvals = < @@ -127,29 +126,13 @@ 0x94 0x00000000 /* PORT6_STATUS */ >; }; - - phy1: ethernet-phy@1 { - reg = <1>; - phy-mode = "rgmii"; - }; - - phy2: ethernet-phy@2 { - reg = <2>; - phy-mode = "rgmii"; - }; - - phy3: ethernet-phy@3 { - reg = <3>; - phy-mode = "rgmii"; - }; - - phy4: ethernet-phy@4 { - reg = <4>; - phy-mode = "rgmii"; - }; }; }; +&gsw { + mediatek,ephy-base = /bits/ 8 <8>; +}; + &pcie { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7620a_lb-link_bl-w1200.dts b/target/linux/ramips/dts/mt7620a_lb-link_bl-w1200.dts index bb1303d4fb..9e0b817163 100644 --- a/target/linux/ramips/dts/mt7620a_lb-link_bl-w1200.dts +++ b/target/linux/ramips/dts/mt7620a_lb-link_bl-w1200.dts @@ -135,6 +135,10 @@ }; }; +&gsw { + mediatek,ephy-base = /bits/ 8 <12>; +}; + &wmac { ralink,mtd-eeprom = <&factory 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_lenovo_newifi-y1s.dts b/target/linux/ramips/dts/mt7620a_lenovo_newifi-y1s.dts index a07683ed4a..0544550bf9 100644 --- a/target/linux/ramips/dts/mt7620a_lenovo_newifi-y1s.dts +++ b/target/linux/ramips/dts/mt7620a_lenovo_newifi-y1s.dts @@ -111,5 +111,6 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; diff --git a/target/linux/ramips/dts/mt7620a_linksys_e1700.dts b/target/linux/ramips/dts/mt7620a_linksys_e1700.dts index 2619a4653a..c38ea8082c 100644 --- a/target/linux/ramips/dts/mt7620a_linksys_e1700.dts +++ b/target/linux/ramips/dts/mt7620a_linksys_e1700.dts @@ -145,7 +145,7 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,ephy-base = /bits/ 8 <12>; }; &wmac { diff --git a/target/linux/ramips/dts/mt7620a_netis_wf2770.dts b/target/linux/ramips/dts/mt7620a_netis_wf2770.dts index ab8c61b1d8..f839048865 100644 --- a/target/linux/ramips/dts/mt7620a_netis_wf2770.dts +++ b/target/linux/ramips/dts/mt7620a_netis_wf2770.dts @@ -142,6 +142,10 @@ }; }; +&gsw { + mediatek,ephy-base = /bits/ 8 <12>; +}; + &pcie { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7620a_ohyeah_oy-0001.dts b/target/linux/ramips/dts/mt7620a_ohyeah_oy-0001.dts index 07f606fce4..7dabbed9ba 100644 --- a/target/linux/ramips/dts/mt7620a_ohyeah_oy-0001.dts +++ b/target/linux/ramips/dts/mt7620a_ohyeah_oy-0001.dts @@ -103,10 +103,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&factory 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_planex_cs-qr10.dts b/target/linux/ramips/dts/mt7620a_planex_cs-qr10.dts index aa7ddb0a25..3edc41ac0d 100644 --- a/target/linux/ramips/dts/mt7620a_planex_cs-qr10.dts +++ b/target/linux/ramips/dts/mt7620a_planex_cs-qr10.dts @@ -122,10 +122,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - ralink,port4 = "ephy"; -}; - &sdhci { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7620a_planex_db-wrt01.dts b/target/linux/ramips/dts/mt7620a_planex_db-wrt01.dts index eb373e9aa2..8f8f173de3 100644 --- a/target/linux/ramips/dts/mt7620a_planex_db-wrt01.dts +++ b/target/linux/ramips/dts/mt7620a_planex_db-wrt01.dts @@ -94,10 +94,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&factory 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_planex_mzk-750dhp.dts b/target/linux/ramips/dts/mt7620a_planex_mzk-750dhp.dts index df9c9689c3..e1c5568ed8 100644 --- a/target/linux/ramips/dts/mt7620a_planex_mzk-750dhp.dts +++ b/target/linux/ramips/dts/mt7620a_planex_mzk-750dhp.dts @@ -114,10 +114,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&factory 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_ralink_mt7620a-evb.dts b/target/linux/ramips/dts/mt7620a_ralink_mt7620a-evb.dts index 7743df06fb..ae35941507 100644 --- a/target/linux/ramips/dts/mt7620a_ralink_mt7620a-evb.dts +++ b/target/linux/ramips/dts/mt7620a_ralink_mt7620a-evb.dts @@ -105,7 +105,8 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; &sdhci { diff --git a/target/linux/ramips/dts/mt7620a_ralink_mt7620a-mt7530-evb.dts b/target/linux/ramips/dts/mt7620a_ralink_mt7620a-mt7530-evb.dts index 4a09755967..f7d8cae160 100644 --- a/target/linux/ramips/dts/mt7620a_ralink_mt7620a-mt7530-evb.dts +++ b/target/linux/ramips/dts/mt7620a_ralink_mt7620a-mt7530-evb.dts @@ -100,7 +100,7 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,ephy-base = /bits/ 8 <12>; }; &pcie { diff --git a/target/linux/ramips/dts/mt7620a_ralink_mt7620a-mt7610e-evb.dts b/target/linux/ramips/dts/mt7620a_ralink_mt7620a-mt7610e-evb.dts index ae0d364d3e..b7a71c3e25 100644 --- a/target/linux/ramips/dts/mt7620a_ralink_mt7620a-mt7610e-evb.dts +++ b/target/linux/ramips/dts/mt7620a_ralink_mt7620a-mt7610e-evb.dts @@ -71,10 +71,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &sdhci { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7620a_ralink_mt7620a-v22sg-evb.dts b/target/linux/ramips/dts/mt7620a_ralink_mt7620a-v22sg-evb.dts index bee4ba7fd3..0e963e1f02 100644 --- a/target/linux/ramips/dts/mt7620a_ralink_mt7620a-v22sg-evb.dts +++ b/target/linux/ramips/dts/mt7620a_ralink_mt7620a-v22sg-evb.dts @@ -99,7 +99,8 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; &pcie { diff --git a/target/linux/ramips/dts/mt7620a_sercomm_na930.dts b/target/linux/ramips/dts/mt7620a_sercomm_na930.dts index 4a91c07ecd..1ffc0a2bc8 100644 --- a/target/linux/ramips/dts/mt7620a_sercomm_na930.dts +++ b/target/linux/ramips/dts/mt7620a_sercomm_na930.dts @@ -166,7 +166,8 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; &ehci { diff --git a/target/linux/ramips/dts/mt7620a_tplink_archer-mr200.dts b/target/linux/ramips/dts/mt7620a_tplink_archer-mr200.dts index ae92dc85e6..4212a70dc3 100644 --- a/target/linux/ramips/dts/mt7620a_tplink_archer-mr200.dts +++ b/target/linux/ramips/dts/mt7620a_tplink_archer-mr200.dts @@ -178,10 +178,6 @@ status = "okay"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&radio 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_tplink_archer.dtsi b/target/linux/ramips/dts/mt7620a_tplink_archer.dtsi index 670bad615d..d2fb891433 100644 --- a/target/linux/ramips/dts/mt7620a_tplink_archer.dtsi +++ b/target/linux/ramips/dts/mt7620a_tplink_archer.dtsi @@ -105,10 +105,6 @@ status = "okay"; }; -&gsw { - mediatek,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&radio 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_tplink_re210-v1.dts b/target/linux/ramips/dts/mt7620a_tplink_re210-v1.dts index 41e56fbe36..57cd0ed539 100644 --- a/target/linux/ramips/dts/mt7620a_tplink_re210-v1.dts +++ b/target/linux/ramips/dts/mt7620a_tplink_re210-v1.dts @@ -61,7 +61,8 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; ðernet { diff --git a/target/linux/ramips/dts/mt7620a_wavlink_wl-wn579x3.dts b/target/linux/ramips/dts/mt7620a_wavlink_wl-wn579x3.dts index 679d9c2150..bfec806c12 100644 --- a/target/linux/ramips/dts/mt7620a_wavlink_wl-wn579x3.dts +++ b/target/linux/ramips/dts/mt7620a_wavlink_wl-wn579x3.dts @@ -195,7 +195,8 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; &wmac { diff --git a/target/linux/ramips/dts/mt7620a_youku_yk-l1.dtsi b/target/linux/ramips/dts/mt7620a_youku_yk-l1.dtsi index 61062a3179..db9bacefe8 100644 --- a/target/linux/ramips/dts/mt7620a_youku_yk-l1.dtsi +++ b/target/linux/ramips/dts/mt7620a_youku_yk-l1.dtsi @@ -103,6 +103,7 @@ ðernet { pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; mtd-mac-address = <&factory 0x28>; diff --git a/target/linux/ramips/dts/mt7620a_yukai_bocco.dts b/target/linux/ramips/dts/mt7620a_yukai_bocco.dts index 9c99a6582e..347c246e2e 100644 --- a/target/linux/ramips/dts/mt7620a_yukai_bocco.dts +++ b/target/linux/ramips/dts/mt7620a_yukai_bocco.dts @@ -141,10 +141,6 @@ mediatek,portmap = "llllw"; }; -&gsw { - ralink,port4 = "ephy"; -}; - &wmac { ralink,mtd-eeprom = <&factory 0x0>; }; diff --git a/target/linux/ramips/dts/mt7620a_zte_q7.dts b/target/linux/ramips/dts/mt7620a_zte_q7.dts index 1ec3ba2e33..550f750c5a 100644 --- a/target/linux/ramips/dts/mt7620a_zte_q7.dts +++ b/target/linux/ramips/dts/mt7620a_zte_q7.dts @@ -111,7 +111,3 @@ &ohci { status = "okay"; }; - -&gsw { - mediatek,port4 = "ephy"; -}; diff --git a/target/linux/ramips/dts/mt7620a_zyxel_keenetic-viva.dts b/target/linux/ramips/dts/mt7620a_zyxel_keenetic-viva.dts index 8c07de4845..1a5ff2d0df 100644 --- a/target/linux/ramips/dts/mt7620a_zyxel_keenetic-viva.dts +++ b/target/linux/ramips/dts/mt7620a_zyxel_keenetic-viva.dts @@ -157,7 +157,8 @@ }; &gsw { - mediatek,port4 = "gmac"; + mediatek,port4-gmac; + mediatek,ephy-base = /bits/ 8 <8>; }; &wmac { diff --git a/target/linux/ramips/dts/mt7620n.dtsi b/target/linux/ramips/dts/mt7620n.dtsi index 2fac091898..276bc13733 100644 --- a/target/linux/ramips/dts/mt7620n.dtsi +++ b/target/linux/ramips/dts/mt7620n.dtsi @@ -322,20 +322,6 @@ reset-names = "fe", "esw"; mediatek,switch = <&gsw>; - - mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - status = "disabled"; - }; - - port@4 { - compatible = "mediatek,mt7620a-gsw-port", "mediatek,eth-port"; - reg = <4>; - - status = "disabled"; - }; }; gsw: gsw@10110000 { @@ -347,7 +333,6 @@ interrupt-parent = <&intc>; interrupts = <17>; - mediatek,port4 = "ephy"; }; ehci: ehci@101c0000 { diff --git a/target/linux/ramips/dts/mt7620n_dlink_dwr-921-c1.dts b/target/linux/ramips/dts/mt7620n_dlink_dwr-921-c1.dts index c784839c34..d37bdb4013 100644 --- a/target/linux/ramips/dts/mt7620n_dlink_dwr-921-c1.dts +++ b/target/linux/ramips/dts/mt7620n_dlink_dwr-921-c1.dts @@ -133,12 +133,6 @@ status = "okay"; }; -ðernet { - port@4 { - status = "okay"; - }; -}; - &state_default { default { groups = "spi refclk", "i2c", "ephy", "wled"; diff --git a/target/linux/ramips/dts/mt7620n_dlink_dwr-922-e2.dts b/target/linux/ramips/dts/mt7620n_dlink_dwr-922-e2.dts index 9400394d89..d3ca0dd53f 100644 --- a/target/linux/ramips/dts/mt7620n_dlink_dwr-922-e2.dts +++ b/target/linux/ramips/dts/mt7620n_dlink_dwr-922-e2.dts @@ -136,12 +136,6 @@ status = "okay"; }; -ðernet { - port@4 { - status = "okay"; - }; -}; - &state_default { default { groups = "spi refclk", "i2c", "ephy", "wled"; diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi index d622aa9077..0dafdc790e 100644 --- a/target/linux/ramips/dts/mt7628an.dtsi +++ b/target/linux/ramips/dts/mt7628an.dtsi @@ -429,8 +429,8 @@ interrupt-parent = <&cpuintc>; interrupts = <5>; - resets = <&rstctrl 21 &rstctrl 23>; - reset-names = "fe", "esw"; + resets = <&rstctrl 21>; + reset-names = "fe"; mediatek,switch = <&esw>; }; @@ -439,8 +439,8 @@ compatible = "mediatek,mt7628-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&rstctrl 23>; - reset-names = "esw"; + resets = <&rstctrl 23 &rstctrl 24>; + reset-names = "esw", "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/mt7628an_hilink_hlk-7628n.dts b/target/linux/ramips/dts/mt7628an_hilink_hlk-7628n.dts index f5106a5080..87dff72c40 100644 --- a/target/linux/ramips/dts/mt7628an_hilink_hlk-7628n.dts +++ b/target/linux/ramips/dts/mt7628an_hilink_hlk-7628n.dts @@ -47,6 +47,7 @@ compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <10000000>; + broken-flash-reset; partitions { compatible = "fixed-partitions"; diff --git a/target/linux/ramips/dts/rt3050.dtsi b/target/linux/ramips/dts/rt3050.dtsi index 0cecd5d8cf..492474fdc4 100644 --- a/target/linux/ramips/dts/rt3050.dtsi +++ b/target/linux/ramips/dts/rt3050.dtsi @@ -319,8 +319,8 @@ compatible = "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&rstctrl 23>; - reset-names = "esw"; + resets = <&rstctrl 23 &rstctrl 24>; + reset-names = "esw", "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/rt3352.dtsi b/target/linux/ramips/dts/rt3352.dtsi index 84d6ed5905..608222cb5c 100644 --- a/target/linux/ramips/dts/rt3352.dtsi +++ b/target/linux/ramips/dts/rt3352.dtsi @@ -331,8 +331,8 @@ compatible = "ralink,rt3352-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&rstctrl 23>; - reset-names = "esw"; + resets = <&rstctrl 23 &rstctrl 24>; + reset-names = "esw", "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/rt5350.dtsi b/target/linux/ramips/dts/rt5350.dtsi index ac4c6d9db2..090e755743 100644 --- a/target/linux/ramips/dts/rt5350.dtsi +++ b/target/linux/ramips/dts/rt5350.dtsi @@ -343,8 +343,8 @@ compatible = "ralink,rt5350-eth"; reg = <0x10100000 0x10000>; - resets = <&rstctrl 21 &rstctrl 23>; - reset-names = "fe", "esw"; + resets = <&rstctrl 21>; + reset-names = "fe"; interrupt-parent = <&cpuintc>; interrupts = <5>; @@ -356,8 +356,8 @@ compatible = "ralink,rt5350-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&rstctrl 23>; - reset-names = "esw"; + resets = <&rstctrl 23 &rstctrl 24>; + reset-names = "esw", "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c index 292f11a170..75b6707be2 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c @@ -17,11 +17,14 @@ #include #include #include +#include #include #include +#include #include "mtk_eth_soc.h" +#include "esw_rt3050.h" /* HW limitations for this switch: * - No large frame support (PKT_MAX_LEN at most 1536) @@ -172,7 +175,6 @@ #define RT5350_ESW_REG_PXTPC(_x) (0x150 + (4 * _x)) #define RT5350_EWS_REG_LED_POLARITY 0x168 -#define RT5350_RESET_EPHY BIT(24) enum { /* Global attributes. */ @@ -215,6 +217,7 @@ struct rt305x_esw { struct device *dev; void __iomem *base; int irq; + struct fe_priv *priv; /* Protects against concurrent register r/w operations. */ spinlock_t reg_rw_lock; @@ -232,6 +235,8 @@ struct rt305x_esw { int led_frequency; struct esw_vlan vlans[RT305X_ESW_NUM_VLANS]; struct esw_port ports[RT305X_ESW_NUM_PORTS]; + struct reset_control *rst_esw; + struct reset_control *rst_ephy; }; @@ -254,6 +259,29 @@ static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, __raw_writel(t | val, esw->base + reg); } +static void esw_reset(struct rt305x_esw *esw) +{ + if (!esw->rst_esw) + return; + + reset_control_assert(esw->rst_esw); + usleep_range(60, 120); + reset_control_deassert(esw->rst_esw); + /* the esw takes long to reset otherwise the board hang */ + msleep(10); +} + +static void esw_reset_ephy(struct rt305x_esw *esw) +{ + if (!esw->rst_ephy) + return; + + reset_control_assert(esw->rst_ephy); + usleep_range(60, 120); + reset_control_deassert(esw->rst_ephy); + usleep_range(60, 120); +} + static void esw_rmw(struct rt305x_esw *esw, unsigned reg, unsigned long mask, unsigned long val) { @@ -436,6 +464,8 @@ static void esw_hw_init(struct rt305x_esw *esw) u8 port_disable = 0; u8 port_map = RT305X_ESW_PMAP_LLLLLL; + esw_reset(esw); + /* vodoo from original driver */ esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0); esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2); @@ -505,8 +535,7 @@ static void esw_hw_init(struct rt305x_esw *esw) esw->ports[i].disable = (port_disable & (1 << i)) != 0; if (ralink_soc == RT305X_SOC_RT3352) { - /* reset EPHY */ - fe_reset(RT5350_RESET_EPHY); + esw_reset_ephy(esw); rt305x_mii_write(esw, 0, 31, 0x8000); for (i = 0; i < 5; i++) { @@ -556,8 +585,7 @@ static void esw_hw_init(struct rt305x_esw *esw) /* select local register */ rt305x_mii_write(esw, 0, 31, 0x8000); } else if (ralink_soc == RT305X_SOC_RT5350) { - /* reset EPHY */ - fe_reset(RT5350_RESET_EPHY); + esw_reset_ephy(esw); /* set the led polarity */ esw_w32(esw, esw->reg_led_polarity & 0x1F, @@ -614,8 +642,7 @@ static void esw_hw_init(struct rt305x_esw *esw) } else if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) { int i; - /* reset EPHY */ - fe_reset(RT5350_RESET_EPHY); + esw_reset_ephy(esw); /* set the led polarity */ esw_w32(esw, esw->reg_led_polarity & 0x1F, @@ -711,19 +738,44 @@ static void esw_hw_init(struct rt305x_esw *esw) esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); } + +int rt3050_esw_has_carrier(struct fe_priv *priv) +{ + struct rt305x_esw *esw = priv->soc->swpriv; + u32 link; + int i; + bool cpuport; + + link = esw_r32(esw, RT305X_ESW_REG_POA); + link >>= RT305X_ESW_POA_LINK_SHIFT; + cpuport = link & BIT(RT305X_ESW_PORT6); + link &= RT305X_ESW_POA_LINK_MASK; + for (i = 0; i <= RT305X_ESW_PORT5; i++) { + if (priv->link[i] != (link & BIT(i))) + dev_info(esw->dev, "port %d link %s\n", i, link & BIT(i) ? "up" : "down"); + priv->link[i] = link & BIT(i); + } + + return !!link && cpuport; +} + static irqreturn_t esw_interrupt(int irq, void *_esw) { - struct rt305x_esw *esw = (struct rt305x_esw *)_esw; + struct rt305x_esw *esw = (struct rt305x_esw *) _esw; u32 status; + int i; status = esw_r32(esw, RT305X_ESW_REG_ISR); if (status & RT305X_ESW_PORT_ST_CHG) { - u32 link = esw_r32(esw, RT305X_ESW_REG_POA); - - link >>= RT305X_ESW_POA_LINK_SHIFT; - link &= RT305X_ESW_POA_LINK_MASK; - dev_info(esw->dev, "link changed 0x%02X\n", link); + if (!esw->priv) + goto out; + if (rt3050_esw_has_carrier(esw->priv)) + netif_carrier_on(esw->priv->netdev); + else + netif_carrier_off(esw->priv->netdev); } + +out: esw_w32(esw, status, RT305X_ESW_REG_ISR); return IRQ_HANDLED; @@ -1351,9 +1403,7 @@ static int esw_probe(struct platform_device *pdev) struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct device_node *np = pdev->dev.of_node; const __be32 *port_map, *port_disable, *reg_init; - struct switch_dev *swdev; struct rt305x_esw *esw; - int ret; esw = devm_kzalloc(&pdev->dev, sizeof(*esw), GFP_KERNEL); if (!esw) @@ -1385,48 +1435,17 @@ static int esw_probe(struct platform_device *pdev) if (reg_init) esw->reg_led_polarity = be32_to_cpu(*reg_init); - swdev = &esw->swdev; - swdev->of_node = pdev->dev.of_node; - swdev->name = "rt305x-esw"; - swdev->alias = "rt305x"; - swdev->cpu_port = RT305X_ESW_PORT6; - swdev->ports = RT305X_ESW_NUM_PORTS; - swdev->vlans = RT305X_ESW_NUM_VIDS; - swdev->ops = &esw_ops; - - ret = register_switch(swdev, NULL); - if (ret < 0) { - dev_err(&pdev->dev, "register_switch failed\n"); - return ret; - } - - platform_set_drvdata(pdev, esw); + esw->rst_esw = devm_reset_control_get(&pdev->dev, "esw"); + if (IS_ERR(esw->rst_esw)) + esw->rst_esw = NULL; + esw->rst_ephy = devm_reset_control_get(&pdev->dev, "ephy"); + if (IS_ERR(esw->rst_ephy)) + esw->rst_ephy = NULL; spin_lock_init(&esw->reg_rw_lock); + platform_set_drvdata(pdev, esw); - esw_hw_init(esw); - - reg_init = of_get_property(np, "ralink,rgmii", NULL); - if (reg_init && be32_to_cpu(*reg_init) == 1) { - /* - * External switch connected to RGMII interface. - * Unregister the switch device after initialization. - */ - dev_err(&pdev->dev, "RGMII mode, not exporting switch device.\n"); - unregister_switch(&esw->swdev); - platform_set_drvdata(pdev, NULL); - return -ENODEV; - } - - ret = devm_request_irq(&pdev->dev, esw->irq, esw_interrupt, 0, "esw", - esw); - - if (!ret) { - esw_w32(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR); - esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); - } - - return ret; + return 0; } static int esw_remove(struct platform_device *pdev) @@ -1447,6 +1466,71 @@ static const struct of_device_id ralink_esw_match[] = { }; MODULE_DEVICE_TABLE(of, ralink_esw_match); +/* called by the ethernet driver to bound with the switch driver */ +int rt3050_esw_init(struct fe_priv *priv) +{ + struct device_node *np = priv->switch_np; + struct platform_device *pdev = of_find_device_by_node(np); + struct switch_dev *swdev; + struct rt305x_esw *esw; + const __be32 *rgmii; + int ret; + + if (!pdev) + return -ENODEV; + + if (!of_device_is_compatible(np, ralink_esw_match->compatible)) + return -EINVAL; + + esw = platform_get_drvdata(pdev); + if (!esw) + return -EPROBE_DEFER; + + priv->soc->swpriv = esw; + esw->priv = priv; + + esw_hw_init(esw); + + rgmii = of_get_property(np, "ralink,rgmii", NULL); + if (rgmii && be32_to_cpu(*rgmii) == 1) { + /* + * External switch connected to RGMII interface. + * Unregister the switch device after initialization. + */ + dev_err(&pdev->dev, "RGMII mode, not exporting switch device.\n"); + unregister_switch(&esw->swdev); + platform_set_drvdata(pdev, NULL); + return -ENODEV; + } + + swdev = &esw->swdev; + swdev->of_node = pdev->dev.of_node; + swdev->name = "rt305x-esw"; + swdev->alias = "rt305x"; + swdev->cpu_port = RT305X_ESW_PORT6; + swdev->ports = RT305X_ESW_NUM_PORTS; + swdev->vlans = RT305X_ESW_NUM_VIDS; + swdev->ops = &esw_ops; + + ret = register_switch(swdev, NULL); + if (ret < 0) { + dev_err(&pdev->dev, "register_switch failed\n"); + return ret; + } + + ret = devm_request_irq(&pdev->dev, esw->irq, esw_interrupt, 0, "esw", + esw); + if (!ret) { + esw_w32(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR); + esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); + } + + dev_info(&pdev->dev, "mediatek esw at 0x%08lx, irq %d initialized\n", + esw->base, esw->irq); + + return 0; +} + static struct platform_driver esw_driver = { .probe = esw_probe, .remove = esw_remove, diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.h index bbc8fbd52a..c9650209cf 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.h @@ -26,4 +26,7 @@ static inline int __init mtk_switch_init(void) { return 0; } static inline void mtk_switch_exit(void) { } #endif + +int rt3050_esw_init(struct fe_priv *priv); +int rt3050_esw_has_carrier(struct fe_priv *priv); #endif diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c index 0b09814cc8..7c91e5840b 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c @@ -40,7 +40,7 @@ static irqreturn_t gsw_interrupt_mt7620(int irq, void *_priv) struct fe_priv *priv = (struct fe_priv *)_priv; struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; u32 status; - int i, max = (gsw->port4 == PORT4_EPHY) ? (4) : (3); + int i, max = (gsw->port4_ephy) ? (4) : (3); status = mtk_switch_r32(gsw, GSW_REG_ISR); if (status & PORT_IRQ_ST_CHG) @@ -61,119 +61,82 @@ static irqreturn_t gsw_interrupt_mt7620(int irq, void *_priv) return IRQ_HANDLED; } -static int mt7620_mdio_mode(struct device_node *eth_node) -{ - struct device_node *phy_node, *mdiobus_node; - const __be32 *id; - int ret = 0; - - mdiobus_node = of_get_child_by_name(eth_node, "mdio-bus"); - - if (mdiobus_node) { - if (of_property_read_bool(mdiobus_node, "mediatek,mdio-mode")) - ret = 1; - - for_each_child_of_node(mdiobus_node, phy_node) { - id = of_get_property(phy_node, "reg", NULL); - if (id && (be32_to_cpu(*id) == 0x1f)) - ret = 1; - } - - of_node_put(mdiobus_node); - } - - return ret; -} - -static void mt7620_hw_init(struct mt7620_gsw *gsw, int mdio_mode) +static void mt7620_hw_init(struct mt7620_gsw *gsw) { u32 i; u32 val; - u32 is_BGA = (rt_sysc_r32(0x0c) >> 16) & 1; + u32 is_BGA = (rt_sysc_r32(SYSC_REG_CHIP_REV_ID) >> 16) & 1; + + /* Internal ethernet requires PCIe RC mode */ + rt_sysc_w32(rt_sysc_r32(SYSC_REG_CFG1) | PCIE_RC_MODE, SYSC_REG_CFG1); - rt_sysc_w32(rt_sysc_r32(SYSC_REG_CFG1) | BIT(8), SYSC_REG_CFG1); mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_CKGCR) & ~(0x3 << 4), GSW_REG_CKGCR); /* Enable MIB stats */ mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_MIB_CNT_EN) | (1 << 1), GSW_REG_MIB_CNT_EN); - if (mdio_mode) { - u32 val; - - /* turn off ephy and set phy base addr to 12 */ + if (gsw->ephy_disable) { mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_GPC1) | - (0x1f << 24) | (0xc << 16), + (gsw->ephy_base << 16) | (0x1f << 24), GSW_REG_GPC1); - /* set MT7530 central align */ - val = mt7530_mdio_r32(gsw, 0x7830); - val &= ~BIT(0); - val |= BIT(1); - mt7530_mdio_w32(gsw, 0x7830, val); + pr_info("gsw: internal ephy disabled\n"); + } else if (gsw->ephy_base) { + mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_GPC1) | + (gsw->ephy_base << 16), + GSW_REG_GPC1); + fe_reset(MT7620A_RESET_EPHY); - val = mt7530_mdio_r32(gsw, 0x7a40); - val &= ~BIT(30); - mt7530_mdio_w32(gsw, 0x7a40, val); + pr_info("gsw: ephy base address: %d\n", gsw->ephy_base); + } - mt7530_mdio_w32(gsw, 0x7a78, 0x855); + /* global page 4 */ + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 31, 0x4000); + + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 17, 0x7444); + if (is_BGA) + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 19, 0x0114); + else + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 19, 0x0117); + + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 22, 0x10cf); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 25, 0x6212); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 26, 0x0777); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 29, 0x4000); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 28, 0xc077); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 24, 0x0000); + + /* global page 3 */ + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 31, 0x3000); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 17, 0x4838); + + /* global page 2 */ + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 31, 0x2000); + if (is_BGA) { + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 21, 0x0515); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 22, 0x0053); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 23, 0x00bf); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 24, 0x0aaf); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 25, 0x0fad); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 26, 0x0fc1); } else { + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 21, 0x0517); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 22, 0x0fd2); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 23, 0x00bf); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 24, 0x0aab); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 25, 0x00ae); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 26, 0x0fff); + } + /* global page 1 */ + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 31, 0x1000); + _mt7620_mii_write(gsw, gsw->ephy_base + 1, 17, 0xe7f8); - if (gsw->ephy_base) { - /* set phy base addr to ephy_base */ - mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_GPC1) | - (gsw->ephy_base << 16), - GSW_REG_GPC1); - fe_reset(BIT(24)); /* Resets the Ethernet PHY block. */ - } - - /* global page 4 */ - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 31, 0x4000); - - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 17, 0x7444); - if (is_BGA) - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 19, 0x0114); - else - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 19, 0x0117); - - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 22, 0x10cf); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 25, 0x6212); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 26, 0x0777); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 29, 0x4000); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 28, 0xc077); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 24, 0x0000); - - /* global page 3 */ - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 31, 0x3000); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 17, 0x4838); - - /* global page 2 */ - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 31, 0x2000); - if (is_BGA) { - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 21, 0x0515); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 22, 0x0053); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 23, 0x00bf); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 24, 0x0aaf); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 25, 0x0fad); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 26, 0x0fc1); - } else { - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 21, 0x0517); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 22, 0x0fd2); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 23, 0x00bf); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 24, 0x0aab); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 25, 0x00ae); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 26, 0x0fff); - } - /* global page 1 */ - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 31, 0x1000); - _mt7620_mii_write(gsw, gsw->ephy_base + 1, 17, 0xe7f8); - - /* turn on all PHYs */ - for (i = 0; i <= 4; i++) { - val = _mt7620_mii_read(gsw, gsw->ephy_base + i, MII_BMCR); - val &= ~BMCR_PDOWN; - val |= BMCR_ANRESTART | BMCR_ANENABLE | BMCR_SPEED100; - _mt7620_mii_write(gsw, gsw->ephy_base + i, MII_BMCR, val); - } + /* turn on all PHYs */ + for (i = 0; i <= 4; i++) { + val = _mt7620_mii_read(gsw, gsw->ephy_base + i, MII_BMCR); + val &= ~BMCR_PDOWN; + val |= BMCR_ANRESTART | BMCR_ANENABLE | BMCR_SPEED100; + _mt7620_mii_write(gsw, gsw->ephy_base + i, MII_BMCR, val); } /* global page 0 */ @@ -202,8 +165,8 @@ static void mt7620_hw_init(struct mt7620_gsw *gsw, int mdio_mode) mtk_switch_w32(gsw, 0x7f7f7fe0, 0x0010); /* setup port 4 */ - if (gsw->port4 == PORT4_EPHY) { - u32 val = rt_sysc_r32(SYSC_REG_CFG1); + if (gsw->port4_ephy) { + val = rt_sysc_r32(SYSC_REG_CFG1); val |= 3 << 14; rt_sysc_w32(val, SYSC_REG_CFG1); @@ -211,12 +174,6 @@ static void mt7620_hw_init(struct mt7620_gsw *gsw, int mdio_mode) _mt7620_mii_write(gsw, gsw->ephy_base + 4, 4, 0x05e1); _mt7620_mii_write(gsw, gsw->ephy_base + 4, 16, 0x1313); pr_info("gsw: setting port4 to ephy mode\n"); - } else if (!mdio_mode) { - u32 val = rt_sysc_r32(SYSC_REG_CFG1); - - val &= ~(3 << 14); - rt_sysc_w32(val, SYSC_REG_CFG1); - pr_info("gsw: setting port4 to gmac mode\n"); } } @@ -228,9 +185,13 @@ MODULE_DEVICE_TABLE(of, mediatek_gsw_match); int mtk_gsw_init(struct fe_priv *priv) { + struct device_node *eth_node = priv->dev->of_node; + struct device_node *phy_node, *mdiobus_node; struct device_node *np = priv->switch_np; struct platform_device *pdev = of_find_device_by_node(np); struct mt7620_gsw *gsw; + const __be32 *id; + u8 val; if (!pdev) return -ENODEV; @@ -241,7 +202,27 @@ int mtk_gsw_init(struct fe_priv *priv) gsw = platform_get_drvdata(pdev); priv->soc->swpriv = gsw; - mt7620_hw_init(gsw, mt7620_mdio_mode(priv->dev->of_node)); + gsw->ephy_disable = of_property_read_bool(np, "mediatek,ephy-disable"); + + mdiobus_node = of_get_child_by_name(eth_node, "mdio-bus"); + if (mdiobus_node) { + for_each_child_of_node(mdiobus_node, phy_node) { + id = of_get_property(phy_node, "reg", NULL); + if (id && (be32_to_cpu(*id) == 0x1f)) + gsw->ephy_disable = true; + } + + of_node_put(mdiobus_node); + } + + gsw->port4_ephy = !of_property_read_bool(np, "mediatek,port4-gmac"); + + if (of_property_read_u8(np, "mediatek,ephy-base", &val) == 0) + gsw->ephy_base = val; + else + gsw->ephy_base = 0; + + mt7620_hw_init(gsw); if (gsw->irq) { request_irq(gsw->irq, gsw_interrupt_mt7620, 0, @@ -255,10 +236,7 @@ int mtk_gsw_init(struct fe_priv *priv) static int mt7620_gsw_probe(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - const char *port4 = NULL; struct mt7620_gsw *gsw; - struct device_node *np = pdev->dev.of_node; - u16 val; gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL); if (!gsw) @@ -270,19 +248,6 @@ static int mt7620_gsw_probe(struct platform_device *pdev) gsw->dev = &pdev->dev; - of_property_read_string(np, "mediatek,port4", &port4); - if (port4 && !strcmp(port4, "ephy")) - gsw->port4 = PORT4_EPHY; - else if (port4 && !strcmp(port4, "gmac")) - gsw->port4 = PORT4_EXT; - else - gsw->port4 = PORT4_EPHY; - - if (of_property_read_u16(np, "mediatek,ephy-base-address", &val) == 0) - gsw->ephy_base = val; - else - gsw->ephy_base = 0; - gsw->irq = platform_get_irq(pdev, 0); platform_set_drvdata(pdev, gsw); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h index f10946a173..cb5d098e9c 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h @@ -55,7 +55,7 @@ #define SYSC_REG_CHIP_REV_ID 0x0c #define SYSC_REG_CFG1 0x14 -#define RST_CTRL_MCM BIT(2) +#define PCIE_RC_MODE BIT(8) #define SYSC_PAD_RGMII2_MDIO 0x58 #define SYSC_GPIO_MODE 0x60 @@ -88,16 +88,12 @@ enum { GSW_ATTR_PORT_UNTAG, }; -enum { - PORT4_EPHY = 0, - PORT4_EXT, -}; - struct mt7620_gsw { struct device *dev; void __iomem *base; int irq; - int port4; + bool ephy_disable; + bool port4_ephy; unsigned long int autopoll; u16 ephy_base; }; diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c index dceb08b835..b923b02af9 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c @@ -232,7 +232,8 @@ int fe_mdio_init(struct fe_priv *priv) mii_np = of_get_child_by_name(priv->dev->of_node, "mdio-bus"); if (!mii_np) { dev_err(priv->dev, "no %s child node found", "mdio-bus"); - return -ENODEV; + err = 0; + goto err_no_bus; } if (!of_device_is_available(mii_np)) { @@ -264,6 +265,8 @@ err_free_bus: kfree(priv->mii_bus); err_put_node: of_node_put(mii_np); +err_no_bus: + dev_err(priv->dev, "%s disabled", "mdio-bus"); priv->mii_bus = NULL; return err; } diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c index b6e321b78c..cf6d4806ed 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c @@ -141,6 +141,17 @@ void fe_reset(u32 reset_bits) usleep_range(10, 20); } +void fe_reset_fe(struct fe_priv *priv) +{ + if (!priv->rst_fe) + return; + + reset_control_assert(priv->rst_fe); + usleep_range(60, 120); + reset_control_deassert(priv->rst_fe); + usleep_range(60, 120); +} + static inline void fe_int_disable(u32 mask) { fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) & ~mask, @@ -1360,13 +1371,21 @@ static int __init fe_init(struct net_device *dev) const char *mac_addr; int err; - priv->soc->reset_fe(); + if (priv->soc->reset_fe) + priv->soc->reset_fe(priv); + else + fe_reset_fe(priv); + + if (priv->soc->switch_init) { + err = priv->soc->switch_init(priv); + if (err) { + if (err == -EPROBE_DEFER) + return err; - if (priv->soc->switch_init) - if (priv->soc->switch_init(priv)) { netdev_err(dev, "failed to initialize switch core\n"); return -ENODEV; } + } fe_reset_phy(priv); @@ -1579,6 +1598,12 @@ static int fe_probe(struct platform_device *pdev) goto err_free_dev; } + priv = netdev_priv(netdev); + spin_lock_init(&priv->page_lock); + priv->rst_fe = devm_reset_control_get(&pdev->dev, "fe"); + if (IS_ERR(priv->rst_fe)) + priv->rst_fe = NULL; + if (soc->init_data) soc->init_data(soc, netdev); netdev->vlan_features = netdev->hw_features & @@ -1593,8 +1618,6 @@ static int fe_probe(struct platform_device *pdev) if (fe_reg_table[FE_REG_FE_DMA_VID_BASE]) netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - priv = netdev_priv(netdev); - spin_lock_init(&priv->page_lock); if (fe_reg_table[FE_REG_FE_COUNTER_BASE]) { priv->hw_stats = kzalloc(sizeof(*priv->hw_stats), GFP_KERNEL); if (!priv->hw_stats) { diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h index 00f1a0e7e6..968db366cf 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h @@ -49,7 +49,7 @@ enum fe_work_flag { FE_FLAG_MAX }; -#define MTK_FE_DRV_VERSION "0.1.2" +#define MTK_FE_DRV_VERSION "0.2" /* power of 2 to let NEXT_TX_DESP_IDX work */ #define NUM_DMA_DESC BIT(10) @@ -157,6 +157,10 @@ enum fe_work_flag { #define MT7620A_FE_GDMA1_MAC_ADRL (MT7620A_GDMA_OFFSET + 0x0C) #define MT7620A_FE_GDMA1_MAC_ADRH (MT7620A_GDMA_OFFSET + 0x10) +#define MT7620A_RESET_FE BIT(21) +#define MT7620A_RESET_ESW BIT(23) +#define MT7620A_RESET_EPHY BIT(24) + #define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00) #define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04) #define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08) @@ -378,7 +382,7 @@ struct fe_soc_data { const u16 *reg_table; void (*init_data)(struct fe_soc_data *data, struct net_device *netdev); - void (*reset_fe)(void); + void (*reset_fe)(struct fe_priv *priv); void (*set_mac)(struct fe_priv *priv, unsigned char *mac); int (*fwd_config)(struct fe_priv *priv); void (*tx_dma)(struct fe_tx_dma *txd); @@ -494,6 +498,7 @@ struct fe_priv { DECLARE_BITMAP(pending_flags, FE_FLAG_MAX); struct reset_control *rst_ppe; + struct reset_control *rst_fe; struct mtk_foe_entry *foe_table; dma_addr_t foe_table_phys; struct flow_offload __rcu **foe_flow_table; @@ -513,6 +518,7 @@ void fe_reg_w32(u32 val, enum fe_reg reg); u32 fe_reg_r32(enum fe_reg reg); void fe_reset(u32 reset_bits); +void fe_reset_fe(struct fe_priv *priv); static inline void *priv_netdev(struct fe_priv *priv) { diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c index 7317bc30aa..42685eebc3 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c @@ -27,8 +27,6 @@ #define MT7620A_CDMA_CSG_CFG 0x400 #define MT7620_DMA_VID (MT7620A_CDMA_CSG_CFG | 0x30) -#define MT7620A_RESET_FE BIT(21) -#define MT7620A_RESET_ESW BIT(23) #define MT7620_L4_VALID BIT(23) #define MT7620_TX_DMA_UDF BIT(15) @@ -82,11 +80,26 @@ static const u16 mt7620_reg_table[FE_REG_COUNT] = { static int mt7620_gsw_config(struct fe_priv *priv) { struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + u32 val; /* is the mt7530 internal or external */ if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, 0x1f)) { mt7530_probe(priv->dev, gsw->base, NULL, 0); mt7530_probe(priv->dev, NULL, priv->mii_bus, 1); + + /* magic values from original SDK */ + val = mt7530_mdio_r32(gsw, 0x7830); + val &= ~BIT(0); + val |= BIT(1); + mt7530_mdio_w32(gsw, 0x7830, val); + + val = mt7530_mdio_r32(gsw, 0x7a40); + val &= ~BIT(30); + mt7530_mdio_w32(gsw, 0x7a40, val); + + mt7530_mdio_w32(gsw, 0x7a78, 0x855); + + pr_info("mt7530: mdio central align\n"); } else { mt7530_probe(priv->dev, gsw->base, NULL, 1); } @@ -141,7 +154,7 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) u32 val, mask = 0; u32 val_delay = 0; u32 mask_delay = GSW_REG_GPCx_TXDELAY | GSW_REG_GPCx_RXDELAY; - int min = (gsw->port4 == PORT4_EPHY) ? (5) : (4); + int min = (gsw->port4_ephy) ? (5) : (4); if (!_id || (be32_to_cpu(*_id) < min) || (be32_to_cpu(*_id) > 5)) { if (_id) @@ -163,7 +176,6 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) (size != (4 * sizeof(*priv->phy->phy_fixed[id])))) { pr_err("%s: invalid fixed link property\n", np->name); priv->phy->phy_fixed[id] = NULL; - return; } #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) @@ -191,7 +203,7 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) break; case PHY_INTERFACE_MODE_RGMII_TXID: mask = 0; - val_delay &= ~GSW_REG_GPCx_TXDELAY; + val_delay |= GSW_REG_GPCx_TXDELAY; val_delay |= GSW_REG_GPCx_RXDELAY; break; case PHY_INTERFACE_MODE_MII: @@ -205,10 +217,6 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) return; } - priv->phy->phy_node[id] = of_parse_phandle(np, "phy-handle", 0); - if (!priv->phy->phy_node[id] && !priv->phy->phy_fixed[id]) - return; - val = rt_sysc_r32(SYSC_REG_CFG1); val &= ~(3 << shift); val |= mask << shift; @@ -249,8 +257,8 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) val = 2; break; default: - dev_err(priv->dev, "invalid link speed: %d\n", - priv->phy->speed[id]); + dev_err(priv->dev, "port %d - invalid link speed: %d\n", + id, priv->phy->speed[id]); priv->phy->phy_fixed[id] = 0; return; } @@ -264,7 +272,13 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) if (priv->phy->duplex[id]) val |= PMCR_DUPLEX; mtk_switch_w32(gsw, val, GSW_REG_PORT_PMCR(id)); - dev_info(priv->dev, "using fixed link parameters\n"); + dev_info(priv->dev, "port %d - using fixed link parameters\n", id); + return; + } + + priv->phy->phy_node[id] = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy->phy_node[id]) { + dev_err(priv->dev, "port %d - missing phy handle\n", id); return; } @@ -277,11 +291,10 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) fe_connect_phy_node(priv, priv->phy->phy_node[id], id); gsw->autopoll |= BIT(be32_to_cpup(phy_addr)); mt7620_auto_poll(gsw,id); - return; } } -static void mt7620_fe_reset(void) +static void mt7620_fe_reset(struct fe_priv *priv) { fe_reset(MT7620A_RESET_FE | MT7620A_RESET_ESW); } diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt2880.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt2880.c index 6c89c997d9..f36904950d 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt2880.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt2880.c @@ -19,8 +19,6 @@ #include "mtk_eth_soc.h" #include "mdio_rt2880.h" -#define RT2880_RESET_FE BIT(18) - static void rt2880_init_data(struct fe_soc_data *data, struct net_device *netdev) { @@ -33,11 +31,6 @@ static void rt2880_init_data(struct fe_soc_data *data, /* netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; */ } -void rt2880_fe_reset(void) -{ - fe_reset(RT2880_RESET_FE); -} - static int rt2880_fwd_config(struct fe_priv *priv) { int ret; @@ -55,7 +48,6 @@ static int rt2880_fwd_config(struct fe_priv *priv) struct fe_soc_data rt2880_data = { .init_data = rt2880_init_data, - .reset_fe = rt2880_fe_reset, .fwd_config = rt2880_fwd_config, .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, .checksum_bit = RX_DMA_L4VALID, diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3050.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3050.c index 914b81410e..435f007477 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3050.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3050.c @@ -17,11 +17,9 @@ #include #include "mtk_eth_soc.h" +#include "esw_rt3050.h" #include "mdio_rt2880.h" -#define RT305X_RESET_FE BIT(21) -#define RT305X_RESET_ESW BIT(23) - static const u16 rt5350_reg_table[FE_REG_COUNT] = { [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, @@ -69,11 +67,6 @@ static int rt3050_fwd_config(struct fe_priv *priv) return 0; } -static void rt305x_fe_reset(void) -{ - fe_reset(RT305X_RESET_FE); -} - static void rt5350_init_data(struct fe_soc_data *data, struct net_device *netdev) { @@ -120,15 +113,10 @@ static void rt5350_tx_dma(struct fe_tx_dma *txd) txd->txd4 = 0; } -static void rt5350_fe_reset(void) -{ - fe_reset(RT305X_RESET_FE | RT305X_RESET_ESW); -} - static struct fe_soc_data rt3050_data = { .init_data = rt305x_init_data, - .reset_fe = rt305x_fe_reset, .fwd_config = rt3050_fwd_config, + .switch_init = rt3050_esw_init, .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, .checksum_bit = RX_DMA_L4VALID, .rx_int = FE_RX_DONE_INT, @@ -139,9 +127,9 @@ static struct fe_soc_data rt3050_data = { static struct fe_soc_data rt5350_data = { .init_data = rt5350_init_data, .reg_table = rt5350_reg_table, - .reset_fe = rt5350_fe_reset, .set_mac = rt5350_set_mac, .fwd_config = rt5350_fwd_config, + .switch_init = rt3050_esw_init, .tx_dma = rt5350_tx_dma, .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, .checksum_bit = RX_DMA_L4VALID, diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3883.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3883.c index 4935b7fbd4..7b61e9c407 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3883.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3883.c @@ -19,13 +19,6 @@ #include "mtk_eth_soc.h" #include "mdio_rt2880.h" -#define RT3883_RSTCTRL_FE BIT(21) - -static void rt3883_fe_reset(void) -{ - fe_reset(RT3883_RSTCTRL_FE); -} - static int rt3883_fwd_config(struct fe_priv *priv) { int ret; @@ -54,7 +47,6 @@ static void rt3883_init_data(struct fe_soc_data *data, static struct fe_soc_data rt3883_data = { .init_data = rt3883_init_data, - .reset_fe = rt3883_fe_reset, .fwd_config = rt3883_fwd_config, .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, .rx_int = FE_RX_DONE_INT, diff --git a/target/linux/ramips/mt7620/base-files/etc/board.d/02_network b/target/linux/ramips/mt7620/base-files/etc/board.d/02_network index 71850863c0..eaa8cbf7aa 100644 --- a/target/linux/ramips/mt7620/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7620/base-files/etc/board.d/02_network @@ -136,6 +136,9 @@ ramips_setup_interfaces() engenius,esr600) ucidef_add_switch "switch0" \ "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "5:wan" "0@eth0" + ucidef_add_switch "switch1" \ + "5:lan" "6@eth0" + ucidef_add_switch_attr "switch1" "enable" "false" ;; fon,fon2601) ucidef_add_switch "switch0" \ @@ -168,6 +171,9 @@ ramips_setup_interfaces() lava,lr-25g001) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" "0@eth0" + ucidef_add_switch "switch1" \ + "5:lan" "6@eth0" + ucidef_add_switch_attr "switch1" "enable" "false" ;; lenovo,newifi-y1|\ xiaomi,miwifi-mini) diff --git a/target/linux/realtek/base-files/lib/preinit/05_set_preinit_iface_realtek b/target/linux/realtek/base-files/lib/preinit/05_set_preinit_iface_realtek new file mode 100644 index 0000000000..e2a7cf5a69 --- /dev/null +++ b/target/linux/realtek/base-files/lib/preinit/05_set_preinit_iface_realtek @@ -0,0 +1,13 @@ +set_preinit_iface() { + + # Create a switch on lan1 to configure the VLAN 1. + # Without configuring VLAN ID 1 RTL8380 - RTL9300 will not + # forward packets. + ip link add name switch type bridge vlan_filtering 1 + ip link set dev lan1 master switch + ip link set lan1 up + + pi_ifname=switch +} + +boot_hook_add preinit_main set_preinit_iface diff --git a/target/linux/realtek/base-files/lib/preinit/98_remove_preinit_realtek b/target/linux/realtek/base-files/lib/preinit/98_remove_preinit_realtek new file mode 100644 index 0000000000..dc5fdb059b --- /dev/null +++ b/target/linux/realtek/base-files/lib/preinit/98_remove_preinit_realtek @@ -0,0 +1,6 @@ +remove_switch() { + # delete switch created in 05_set_preinit_iface_realtek again + ip link del name switch +} + +boot_hook_add preinit_main remove_switch diff --git a/target/linux/realtek/files-5.4/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.4/drivers/net/ethernet/rtl838x_eth.c index c5c6e3b6b7..de54868cad 100644 --- a/target/linux/realtek/files-5.4/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.4/drivers/net/ethernet/rtl838x_eth.c @@ -1129,23 +1129,16 @@ static int rtl838x_eth_tx(struct sk_buff *skb, struct net_device *dev) /* Check for DSA tagging at the end of the buffer */ if (netdev_uses_dsa(dev) && skb->data[len-4] == 0x80 && skb->data[len-3] > 0 - && skb->data[len-3] < 28 && skb->data[len-2] == 0x10 + && skb->data[len-3] < priv->cpu_port && skb->data[len-2] == 0x10 && skb->data[len-1] == 0x00) { /* Reuse tag space for CRC if possible */ dest_port = skb->data[len-3]; + skb->data[len-4] = skb->data[len-3] = skb->data[len-2] = skb->data[len-1] = 0x00; len -= 4; } len += 4; // Add space for CRC - // On RTL8380 SoCs, the packet needs extra padding - if (priv->family_id == RTL8380_FAMILY_ID) { - if (len < ETH_ZLEN) - len = ETH_ZLEN; // SoC not automatically padding to ETH_ZLEN - else - len += 4; - } - if (skb_padto(skb, len)) { ret = NETDEV_TX_OK; goto txdone; @@ -1158,6 +1151,11 @@ static int rtl838x_eth_tx(struct sk_buff *skb, struct net_device *dev) h = &ring->tx_header[q][ring->c_tx[q]]; h->size = len; h->len = len; + // On RTL8380 SoCs, small packet lengths being sent need adjustments + if (priv->family_id == RTL8380_FAMILY_ID) { + if (len < ETH_ZLEN - 4) + h->len -= 4; + } priv->r->create_tx_header(h, dest_port, skb->priority >> 1);